diff --git a/.gitignore b/.gitignore
deleted file mode 100644
index cda677a..0000000
--- a/.gitignore
+++ /dev/null
@@ -1,8 +0,0 @@
-target
-.settings
-.classpath
-.project
-legacyworlds-server-main/data-source.xml
-legacyworlds-server-data/db-structure/db-config.txt
-*.log
-full-debug*.zip
diff --git a/.project b/.project
new file mode 100644
index 0000000..b09df49
--- /dev/null
+++ b/.project
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>legacyworlds</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.maven.ide.eclipse.maven2Builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.maven.ide.eclipse.maven2Nature</nature>
+	</natures>
+</projectDescription>
diff --git a/build-tools/BUILD.sh b/build-tools/BUILD.sh
new file mode 100755
index 0000000..b76b7f5
--- /dev/null
+++ b/build-tools/BUILD.sh
@@ -0,0 +1,51 @@
+#!/bin/sh
+
+cd `dirname $0`/..
+SRCDIR=`pwd`
+if [ "x$1" = "x" ]; then
+	OUTDIR="$SRCDIR";
+else
+	OUTDIR="$1";
+fi
+
+echo "Building Legacy Worlds..."
+mvn clean || { echo "Maven clean-up failed"; exit 1; };
+mvn package || { echo "Maven build failed"; exit 1; };
+
+echo "Copying files..."
+
+TEMPDIR=`mktemp -d`
+mkdir $TEMPDIR/legacyworlds
+mkdir $TEMPDIR/legacyworlds/server
+mkdir $TEMPDIR/legacyworlds/server/data
+mkdir $TEMPDIR/legacyworlds/web
+mkdir $TEMPDIR/legacyworlds/sql
+
+# Database and initial data
+cp -Rapv legacyworlds-server/legacyworlds-server-data/db-structure/database.sql $TEMPDIR/legacyworlds/sql
+cp -Rapv legacyworlds-server/legacyworlds-server-data/db-structure/db-config.txt $TEMPDIR/legacyworlds/sql/db-config-example.txt
+cp -Rapv legacyworlds-server/legacyworlds-server-data/db-structure/parts $TEMPDIR/legacyworlds/sql
+cp -Rapv legacyworlds-server/legacyworlds-server-main/data/* $TEMPDIR/legacyworlds/server/data
+# Server
+cp -Rapv legacyworlds-server/legacyworlds-server-main/target/*.jar $TEMPDIR/legacyworlds/server
+cp -Rapv legacyworlds-server/legacyworlds-server-main/target/lib $TEMPDIR/legacyworlds/server
+cp -Rapv legacyworlds-server/legacyworlds-server-main/data-source.xml $TEMPDIR/legacyworlds/server/data-source-example.xml
+# Tools
+cp -Rapv build-tools/server-config-example.sh $TEMPDIR/legacyworlds
+cp -Rapv build-tools/start-server.sh $TEMPDIR/legacyworlds
+cp -Rapv build-tools/stop-server.sh $TEMPDIR/legacyworlds
+cp -Rapv build-tools/execute-clit.sh $TEMPDIR/legacyworlds
+cp -Rapv build-tools/deploy.sh $TEMPDIR/legacyworlds
+# Web sites
+cp -Rapv legacyworlds-web/legacyworlds-web-*/target/*.war $TEMPDIR/legacyworlds/web
+
+echo "Preparing archive..."
+cd $TEMPDIR
+find $TEMPDIR/legacyworlds -type d -name .svn | xargs rm -rf
+tar cvjf $OUTDIR/legacyworlds.tar.bz2 legacyworlds || { echo "Archive generation failed"; exit 1; };
+
+echo "Removing temporary directory..."
+cd $SRCDIR
+rm -rf $TEMPDIR
+
+echo "All done. Legacy Worlds archive: $OUTDIR/legacyworlds.tar.bz2"
diff --git a/build-tools/deploy.sh b/build-tools/deploy.sh
new file mode 100755
index 0000000..5edbf77
--- /dev/null
+++ b/build-tools/deploy.sh
@@ -0,0 +1,34 @@
+#!/bin/sh
+
+COREDIR="$1"
+if [ "x$COREDIR" = "x" ] || ! [ -d "$COREDIR" ]; then
+	echo "Syntax: $0 main_dir tomcat_dir web_dir"
+	exit 1;
+fi
+
+TOMCATDIR="$2"
+if [ "x$TOMCATDIR" = "x" ] || ! [ -d "$TOMCATDIR" ]; then
+	echo "Syntax: $0 main_dir tomcat_dir web_dir"
+	exit 1;
+fi
+
+WEBDIR="$3"
+if [ "x$WEBDIR" = "x" ] || ! [ -d "$WEBDIR" ]; then
+	echo "Syntax: $0 main_dir tomcat_dir web_dir"
+	exit 1;
+fi
+
+
+cd `dirname $0`
+SRCDIR=`pwd`
+cp -Rap server web *-*.sh $COREDIR
+
+cd "$TOMCATDIR"
+if [ -L "lwmain.war" ]; then
+	rm -f lwmain.war lwadmin.war
+fi
+ln -s "$COREDIR/web/legacyworlds-web-main-"*.war lwmain.war
+ln -s "$COREDIR/web/legacyworlds-web-admin-"*.war lwadmin.war
+
+cd $WEBDIR
+unzip -o $COREDIR/web/legacyworlds-web-main-*.war "css/*" "js/*" "pjirc/*" "img/*"
diff --git a/legacyworlds/build-tools/execute-clit.sh b/build-tools/execute-clit.sh
similarity index 100%
rename from legacyworlds/build-tools/execute-clit.sh
rename to build-tools/execute-clit.sh
diff --git a/legacyworlds/build-tools/server-config-example.sh b/build-tools/server-config-example.sh
similarity index 100%
rename from legacyworlds/build-tools/server-config-example.sh
rename to build-tools/server-config-example.sh
diff --git a/legacyworlds/build-tools/start-server.sh b/build-tools/start-server.sh
similarity index 100%
rename from legacyworlds/build-tools/start-server.sh
rename to build-tools/start-server.sh
diff --git a/legacyworlds/build-tools/stop-server.sh b/build-tools/stop-server.sh
similarity index 100%
rename from legacyworlds/build-tools/stop-server.sh
rename to build-tools/stop-server.sh
diff --git a/build/post-build.d/10-database-tests.sh b/build/post-build.d/10-database-tests.sh
deleted file mode 100644
index 68e6fc9..0000000
--- a/build/post-build.d/10-database-tests.sh
+++ /dev/null
@@ -1,58 +0,0 @@
-#!/bin/bash
-
-cd legacyworlds-server-data/db-structure
-if ! [ -f db-config.txt ]; then
-	cat > db-config.txt <<EOF
-admin=$USER
-db=tests
-user=tests
-password=tests
-EOF
-fi
-export TEST_DATABASE="`grep ^db= db-config.txt | sed -e s/.*=//`"
-export TEST_USER="`grep ^user= db-config.txt | sed -e s/.*=//`"
-
-echo
-echo
-echo "======================================================================"
-echo "LOADING DATABASE DEFINITION ..."
-echo "======================================================================"
-echo
-echo
-psql -vQUIET=1 -vON_ERROR_STOP=1 -e --file database.sql || exit 1
-
-if ! [ -d tests/admin ] && ! [ -d tests/user ]; then
-	echo
-	echo
-	echo "WARNING: no unit tests to run"
-	echo
-	echo
-	exit 0
-fi
-
-echo
-echo
-echo "======================================================================"
-echo "LOADING TEST FRAMEWORK ..."
-echo "======================================================================"
-echo
-echo
-psql -vQUIET=1 -f tests/pgtap.sql $TEST_DATABASE || exit 1
-
-echo
-echo
-echo "======================================================================"
-echo "RUNNING DATABASE TESTS ..."
-echo "======================================================================"
-echo
-echo
-cd tests
-if [ -d admin ]; then
-	pg_prove -d $TEST_DATABASE `find admin/ -type f -name '*.sql'` || exit 1
-fi
-if [ -d user ]; then
-	pg_prove -U $TEST_USER -d $TEST_DATABASE `find user/ -type f -name '*.sql'` || exit 1
-fi
-if [ -x dirty/run-dirty-tests.sh ]; then
-	( cd dirty; exec ./run-dirty-tests.sh ) || exit 1
-fi
diff --git a/build/post-build.d/20-import-tools.sh b/build/post-build.d/20-import-tools.sh
deleted file mode 100644
index 5a09127..0000000
--- a/build/post-build.d/20-import-tools.sh
+++ /dev/null
@@ -1,51 +0,0 @@
-#!/bin/bash
-
-TESTDIR=`mktemp -d`
-cp -Rapv legacyworlds-server-DIST/target/legacyworlds/legacyworlds-server-* $TESTDIR
-
-
-cd $TESTDIR/legacyworlds-server-*/sql
-cat > db-config.txt <<EOF
-admin=$USER
-db=tests
-user=tests
-password=tests
-EOF
-psql -vQUIET=1 -vON_ERROR_STOP=1 -e --file database.sql || exit 1
-cd ..
-
-cat > data-source.xml <<EOF
-<?xml version="1.0" encoding="UTF-8"?>
-<beans xmlns="http://www.springframework.org/schema/beans"
-	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
-
-	<bean name="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
-		<property name="driverClassName" value="org.postgresql.Driver" />
-		<property name="url" value="jdbc:postgresql:tests" />
-		<property name="username" value="tests" />
-		<property name="password" value="tests" />
-	</bean>
-
-</beans>
-EOF
-
-java legacyworlds-server-main-*.jar --run-tool ImportText data/i18n-text.xml || exit 1
-java legacyworlds-server-main-*.jar --run-tool ImportEvents data/event-definitions.xml || exit 1
-java legacyworlds-server-main-*.jar --run-tool ImportResources data/resources.xml || exit 1
-java legacyworlds-server-main-*.jar --run-tool ImportTechs data/techs.xml || exit 1
-java legacyworlds-server-main-*.jar --run-tool ImportTechGraph data/tech-graph.xml || exit 1
-java legacyworlds-server-main-*.jar --run-tool ImportBuildables data/buildables.xml || exit 1
-
-java legacyworlds-server-main-*.jar &
-sleep 10
-if ! ps ux | grep -q 'java -jar legacyworlds-server-main'; then
-	exit 1;
-fi
-java legacyworlds-server-main-*.jar --run-tool Stop || {
-	killall java
-	exit 1;
-}
-
-java -jar legacyworlds-server-main-1.0.0-0.jar --run-tool CreateUser 'test@example.org 12blah34bleh en' || exit 1
-java -jar legacyworlds-server-main-1.0.0-0.jar --run-tool CreateSuperuser 'test@example.org Turlututu' || exit 1
diff --git a/legacyworlds/eclipse-code-format.xml b/eclipse-code-format.xml
similarity index 100%
rename from legacyworlds/eclipse-code-format.xml
rename to eclipse-code-format.xml
diff --git a/legacyworlds-server-DIST/pom.xml b/legacyworlds-server-DIST/pom.xml
deleted file mode 100644
index 39d7676..0000000
--- a/legacyworlds-server-DIST/pom.xml
+++ /dev/null
@@ -1,67 +0,0 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-	<modelVersion>4.0.0</modelVersion>
-	<parent>
-		<artifactId>legacyworlds-server</artifactId>
-		<groupId>com.deepclone.lw</groupId>
-		<version>1.0.0</version>
-		<relativePath>../legacyworlds-server/pom.xml</relativePath>
-	</parent>
-
-	<artifactId>legacyworlds-server-DIST</artifactId>
-	<version>${legacyworlds.version.main}.${legacyworlds.version.release}-${legacyworlds.version.build}</version>
-
-	<packaging>pom</packaging>
-	<name>Legacy Worlds - Server - Packaging</name>
-	<description>This Maven module is responsible for creating the Legacy Worlds server's packaging.</description>
-
-
-	<!-- Depend solely on the server's JAR, other dependencies will update automatically -->
-	<dependencies>
-		<dependency>
-			<groupId>com.deepclone.lw</groupId>
-			<artifactId>legacyworlds-server-main</artifactId>
-		</dependency>
-	</dependencies>
-
-	<build>
-		<plugins>
-			<!-- Clean the target directory before generating the distribution -->
-			<plugin>
-				<artifactId>maven-clean-plugin</artifactId>
-				<executions>
-					<execution>
-						<id>clean-before-assembly</id>
-						<phase>initialize</phase>
-						<goals>
-							<goal>clean</goal>
-						</goals>
-					</execution>
-				</executions>
-			</plugin>
-
-			<!-- Use the assembly plug-in to generate the distribution -->
-			<plugin>
-				<artifactId>maven-assembly-plugin</artifactId>
-				<executions>
-					<execution>
-						<id>distribution-assembly</id>
-						<phase>package</phase>
-						<goals>
-							<goal>single</goal>
-						</goals>
-						<configuration>
-							<attach>false</attach>
-							<finalName>legacyworlds-server-${project.version}</finalName>
-							<descriptors>
-								<descriptor>src/server.xml</descriptor>
-							</descriptors>
-							<appendAssemblyId>false</appendAssemblyId>
-						</configuration>
-					</execution>
-				</executions>
-			</plugin>
-		</plugins>
-
-	</build>
-</project>
\ No newline at end of file
diff --git a/legacyworlds-server-DIST/src/server.xml b/legacyworlds-server-DIST/src/server.xml
deleted file mode 100644
index cf10d97..0000000
--- a/legacyworlds-server-DIST/src/server.xml
+++ /dev/null
@@ -1,79 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<assembly
-	xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
-	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
-
-	<!-- Legacy Worlds server assembly -->
-
-	<id>legacyworlds-server</id>
-	<formats>
-		<format>dir</format>
-	</formats>
-	<includeBaseDirectory>false</includeBaseDirectory>
-
-	<dependencySets>
-
-		<!-- The server's main archive -->
-		<dependencySet>
-			<useProjectArtifact>false</useProjectArtifact>
-			<outputDirectory>.</outputDirectory>
-			<unpack>false</unpack>
-			<includes>
-				<include>com.deepclone.lw:legacyworlds-server-main:jar</include>
-			</includes>
-		</dependencySet>
-
-		<!-- Libraries - both internal and external dependencies -->
-		<dependencySet>
-			<useProjectArtifact>false</useProjectArtifact>
-			<outputDirectory>lib</outputDirectory>
-			<unpack>false</unpack>
-			<includes>
-				<include>*:jar</include>
-			</includes>
-			<excludes>
-				<exclude>com.deepclone.lw:legacyworlds-server-main:jar</exclude>
-			</excludes>
-		</dependencySet>
-
-	</dependencySets>
-
-	<fileSets>
-
-		<!-- Database definitions -->
-		<fileSet>
-			<directory>../legacyworlds-server-data/db-structure</directory>
-			<outputDirectory>sql</outputDirectory>
-			<includes>
-				<include>*.sql</include>
-				<include>parts/**</include>
-				<include>db-config.sample.txt</include>
-			</includes>
-		</fileSet>
-
-		<!-- Default data -->
-		<fileSet>
-			<directory>../legacyworlds-server-main/data</directory>
-			<outputDirectory>data</outputDirectory>
-			<includes>
-				<include>i18n/**</include>
-				<include>**.xml</include>
-			</includes>
-		</fileSet>
-
-	</fileSets>
-
-	<files>
-
-		<!-- Data source configuration -->
-		<file>
-			<source>../legacyworlds-server-main/data-source.sample.xml</source>
-			<fileMode>0600</fileMode>
-			<outputDirectory>.</outputDirectory>
-		</file>
-		
-	</files>
-
-
-</assembly>
diff --git a/legacyworlds-server-beans-accounts/src/main/resources/configuration/meta/accounts.xml b/legacyworlds-server-beans-accounts/src/main/resources/configuration/meta/accounts.xml
deleted file mode 100644
index 98207c4..0000000
--- a/legacyworlds-server-beans-accounts/src/main/resources/configuration/meta/accounts.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<beans xmlns="http://www.springframework.org/schema/beans"
-	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	xsi:schemaLocation="
-                        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
-
-	<bean id="accountCleanup" class="com.deepclone.lw.beans.acm.AccountCleanupBean" />
-	<bean id="accountManagement" class="com.deepclone.lw.beans.acm.AccountManagementBean" />
-	<bean id="adminDao" class="com.deepclone.lw.beans.admin.AdminDAOBean" />
-	<bean id="administration" class="com.deepclone.lw.beans.admin.AdministrationBean" />
-	<bean id="adminRecap" class="com.deepclone.lw.beans.admin.AdminRecapBean" />
-	<bean id="bansDao" class="com.deepclone.lw.beans.admin.BansDAOBean" />
-	<bean id="bansProcessor" class="com.deepclone.lw.beans.admin.BansProcessorBean" />
-	<bean id="defaultPreferences" class="com.deepclone.lw.beans.prefs.DefaultPreferencesBean" />
-	<bean id="ipBan" class="com.deepclone.lw.beans.admin.IpBanBean" />
-	<bean id="preferenceDefinitions" class="com.deepclone.lw.beans.prefs.PreferenceDefinitionsBean" />
-	<bean id="preferencesDAO" class="com.deepclone.lw.beans.prefs.PreferencesDAOBean" />
-	<bean id="preferenceTypesRegistry"
-		class="com.deepclone.lw.beans.prefs.PreferenceTypesRegistryBean" />
-	<bean id="quitProcessor" class="com.deepclone.lw.beans.acm.QuitProcessorBean" />
-	<bean id="requestsExpiration" class="com.deepclone.lw.beans.acm.RequestsExpirationBean" />
-	<bean id="usersDAO" class="com.deepclone.lw.beans.acm.UsersDAOBean" />
-	<bean id="userSessionDao" class="com.deepclone.lw.beans.acm.UserSessionDAOBean" />
-	<bean id="vacationProcessor" class="com.deepclone.lw.beans.acm.VacationProcessorBean" />
-
-</beans>
\ No newline at end of file
diff --git a/legacyworlds-server-beans-accounts/src/test/java/.empty b/legacyworlds-server-beans-accounts/src/test/java/.empty
deleted file mode 100644
index e69de29..0000000
diff --git a/legacyworlds-server-beans-accounts/src/test/resources/.empty b/legacyworlds-server-beans-accounts/src/test/resources/.empty
deleted file mode 100644
index e69de29..0000000
diff --git a/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/BuildingsInformationMapper.java b/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/BuildingsInformationMapper.java
deleted file mode 100644
index 3a233c9..0000000
--- a/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/BuildingsInformationMapper.java
+++ /dev/null
@@ -1,44 +0,0 @@
-package com.deepclone.lw.beans.bt.es;
-
-
-import java.sql.ResultSet;
-import java.sql.SQLException;
-
-import org.springframework.jdbc.core.RowMapper;
-
-import com.deepclone.lw.beans.bt.es.data.BuildingsInformation;
-
-
-
-/**
- * Building information row mapper
- * 
- * <p>
- * Map rows from <code>bugs.dump_buildings_view</code> into {@link BuildingsInformation} instances.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- * 
- */
-final class BuildingsInformationMapper
-		implements RowMapper< BuildingsInformation >
-{
-
-	/**
-	 * Map a row from <code>bugs.dump_buildings_view</code>
-	 * 
-	 * <p>
-	 * Generate and initialise a {@link BuildingsInformation} instance using the row's fields.
-	 */
-	@Override
-	public BuildingsInformation mapRow( ResultSet rs , int rowNum )
-			throws SQLException
-	{
-		BuildingsInformation bi = new BuildingsInformation( );
-		bi.setPlanetId( rs.getInt( "planet_id" ) );
-		bi.setId( rs.getInt( "building_id" ) );
-		bi.setName( rs.getString( "building_name" ) );
-		bi.setAmount( rs.getInt( "amount" ) );
-		bi.setDamage( rs.getDouble( "damage" ) );
-		return bi;
-	}
-}
\ No newline at end of file
diff --git a/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/DebugInformationMapper.java b/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/DebugInformationMapper.java
deleted file mode 100644
index b8a5399..0000000
--- a/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/DebugInformationMapper.java
+++ /dev/null
@@ -1,65 +0,0 @@
-package com.deepclone.lw.beans.bt.es;
-
-
-import java.sql.ResultSet;
-import java.sql.SQLException;
-
-import org.springframework.jdbc.core.RowMapper;
-
-import com.deepclone.lw.beans.bt.es.data.AllianceInformation;
-import com.deepclone.lw.beans.bt.es.data.DebugInformation;
-
-
-
-/**
- * Top-level empire summary row mapper
- * 
- * <p>
- * This class maps an entry from the database's main empire summary view,
- * <code>bugs.dump_main_view</code>, into a top-level {@link DebugInformation} instance.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- * 
- */
-final class DebugInformationMapper
-		implements RowMapper< DebugInformation >
-{
-	/**
-	 * Map a row from <code>bugs.dump_main_view</code> into a {@link DebugInformation} instance
-	 * 
-	 * <p>
-	 * Converts the row into a {@link DebugInformation} instance containing system information,
-	 * account information and empire information. If the row contains alliance information, add an
-	 * {@link AllianceInformation} record to the empire information.
-	 */
-	@Override
-	public DebugInformation mapRow( ResultSet rs , int rowNum )
-			throws SQLException
-	{
-		DebugInformation di = new DebugInformation( );
-
-		di.getSystem( ).setNextTick( rs.getLong( "next_tick" ) );
-		di.getSystem( ).setCurrentTick( (Long) rs.getObject( "current_tick" ) );
-
-		di.getAccount( ).setId( rs.getInt( "account_id" ) );
-		di.getAccount( ).setAddress( rs.getString( "account_address" ) );
-		di.getAccount( ).setGameCredits( rs.getInt( "game_credits" ) );
-		di.getAccount( ).setStatus( rs.getString( "account_status" ) );
-		di.getAccount( ).setLanguage( rs.getString( "account_language" ) );
-
-		di.getEmpire( ).setId( rs.getInt( "empire_id" ) );
-		di.getEmpire( ).setName( rs.getString( "empire_name" ) );
-		di.getEmpire( ).setCash( rs.getDouble( "cash" ) );
-
-		String allianceTag = rs.getString( "alliance_tag" );
-		if ( allianceTag != null ) {
-			AllianceInformation alliance = new AllianceInformation( );
-			alliance.setId( rs.getInt( "alliance_id" ) );
-			alliance.setTag( allianceTag );
-			alliance.setPending( rs.getBoolean( "alliance_pending" ) );
-			di.getEmpire( ).setAlliance( alliance );
-		}
-
-		return di;
-	}
-}
\ No newline at end of file
diff --git a/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/EmpireResourceInformationMapper.java b/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/EmpireResourceInformationMapper.java
deleted file mode 100644
index 3140781..0000000
--- a/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/EmpireResourceInformationMapper.java
+++ /dev/null
@@ -1,52 +0,0 @@
-package com.deepclone.lw.beans.bt.es;
-
-
-import java.sql.ResultSet;
-import java.sql.SQLException;
-
-import org.springframework.jdbc.core.RowMapper;
-
-import com.deepclone.lw.beans.bt.es.data.EmpireResourceInformation;
-
-
-
-/**
- * Empire resource row mapper
- * 
- * <p>
- * This class is responsible for transforming rows from <code>bugs.dump_emp_resources_view</code>
- * into {@link EmpireResourceInformation} instances.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-final class EmpireResourceInformationMapper
-		implements RowMapper< EmpireResourceInformation >
-{
-
-	/**
-	 * Map a row from <code>bugs.dump_emp_resources_view</code>
-	 * 
-	 * <p>
-	 * Create a new {@link EmpireResourceInformation} instance and set its fields using the row's
-	 * contents. If a mining priority is present, set it, otherwise leave the field to its default
-	 * <code>null</code> value.
-	 */
-	@Override
-	public EmpireResourceInformation mapRow( ResultSet rs , int rowNum )
-			throws SQLException
-	{
-		EmpireResourceInformation empRes = new EmpireResourceInformation( );
-
-		empRes.setResource( rs.getString( "resource_name" ) );
-		empRes.setOwed( rs.getDouble( "empres_owed" ) );
-		empRes.setPossessed( rs.getDouble( "empres_possessed" ) );
-
-		int priority = rs.getInt( "mining_priority" );
-		if ( !rs.wasNull( ) ) {
-			empRes.setMiningPriority( priority );
-		}
-
-		return empRes;
-	}
-
-}
diff --git a/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/EmpireSummaryBean.java b/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/EmpireSummaryBean.java
deleted file mode 100644
index 2cc7d8d..0000000
--- a/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/EmpireSummaryBean.java
+++ /dev/null
@@ -1,359 +0,0 @@
-package com.deepclone.lw.beans.bt.es;
-
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import javax.sql.DataSource;
-
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.jdbc.core.JdbcTemplate;
-
-import com.deepclone.lw.beans.bt.es.data.AccountInformation;
-import com.deepclone.lw.beans.bt.es.data.AllianceInformation;
-import com.deepclone.lw.beans.bt.es.data.BuildingsInformation;
-import com.deepclone.lw.beans.bt.es.data.DebugInformation;
-import com.deepclone.lw.beans.bt.es.data.EmpireInformation;
-import com.deepclone.lw.beans.bt.es.data.EmpireResourceInformation;
-import com.deepclone.lw.beans.bt.es.data.FleetInformation;
-import com.deepclone.lw.beans.bt.es.data.MovementInformation;
-import com.deepclone.lw.beans.bt.es.data.PlanetInformation;
-import com.deepclone.lw.beans.bt.es.data.QueueInformation;
-import com.deepclone.lw.beans.bt.es.data.QueueItemInformation;
-import com.deepclone.lw.beans.bt.es.data.ResearchGraphInformation;
-import com.deepclone.lw.beans.bt.es.data.ResearchInformation;
-import com.deepclone.lw.beans.bt.es.data.ResearchLineInformation;
-import com.deepclone.lw.beans.bt.es.data.ResourceDeltaInformation;
-import com.deepclone.lw.beans.bt.es.data.ResourceProviderInformation;
-import com.deepclone.lw.beans.bt.es.data.ShipsInformation;
-import com.deepclone.lw.beans.bt.es.data.SystemInformation;
-import com.deepclone.lw.interfaces.bt.EmpireSummary;
-import com.thoughtworks.xstream.XStream;
-
-
-
-/**
- * Empire XML summary generator
- * 
- * <p>
- * This component is used by the bug tracking system to generate XML dumps of an empire's state. It
- * reads the necessary data from the database, convert it to XML dump record classes then serialises
- * the whole thing through XStream.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-public class EmpireSummaryBean
-		implements EmpireSummary
-{
-	/** Beginning of all dump SQL queries */
-	private static final String SQL_START = "SELECT * FROM bugs.dump_";
-
-	/** Ending of (almost) all dump SQL queries */
-	private static final String SQL_END = "_view WHERE empire_id = ?";
-
-	/** SQL query that accesses the main empire dump view */
-	private static final String Q_EMPIRE = SQL_START + "main" + SQL_END;
-
-	/** SQL query that accesses the resources dump view */
-	private static final String Q_RESOURCES = SQL_START + "emp_resources" + SQL_END;
-
-	/** SQL query that accesses the research dump view */
-	private static final String Q_RESEARCH = SQL_START + "research" + SQL_END;
-
-	/** SQL query that accesses the empire's planets dump view */
-	private static final String Q_PLANETS = SQL_START + "planets" + SQL_END;
-
-	/** SQL query that accesses the planetary resources dump view */
-	private static final String Q_PLANET_RESOURCES = SQL_START + "planet_resources" + SQL_END;
-
-	/** SQL query that accesses the build queues dump view */
-	private static final String Q_BUILD_QUEUES = SQL_START + "queues" + SQL_END + " ORDER BY queue_order";
-
-	/** SQL query that accesses the buildings dump view */
-	private static final String Q_BUILDINGS = SQL_START + "buildings" + SQL_END;
-
-	/** SQL query that accesses the fleets dump view */
-	private static final String Q_FLEETS = SQL_START + "fleets" + SQL_END;
-
-	/** SQL query that accesses the ships dump view */
-	private static final String Q_SHIPS = SQL_START + "ships" + SQL_END;
-
-	/** JDBC access interface */
-	private JdbcTemplate dTemplate;
-
-	/** XStream instance used to serialise XML dumps */
-	private final XStream xStream;
-
-	/** Top-level row mapper */
-	private final DebugInformationMapper mMainInfo;
-
-	/** Empire resources row mapper */
-	private final EmpireResourceInformationMapper mResources;
-
-	/** Empire research row mapper */
-	private final ResearchInformationMapper mResearch;
-
-	/** Empire-owned planet row mapper */
-	private final PlanetInformationMapper mPlanet;
-
-	/** Planet resources row mapper */
-	private final ResourceRowMapper mPlanetResources;
-
-	/** Planet construction queue item row mapper */
-	private final QueueItemInformationMapper mQueueItem;
-
-	/** Planet buildings information mapper */
-	private final BuildingsInformationMapper mBuildings;
-
-	/** Fleet information row mapper */
-	private final FleetInformationMapper mFleet;
-
-	/** Fleet ships row mapper */
-	private final ShipsInformationMapper mShips;
-
-
-	/**
-	 * Set up the {@link XStream} instance that generates the dumps as well as the necessary row
-	 * mappers.
-	 */
-	public EmpireSummaryBean( )
-	{
-		this.xStream = new XStream( );
-		this.xStream.processAnnotations( new Class< ? >[] {
-				AccountInformation.class , AllianceInformation.class , BuildingsInformation.class ,
-				DebugInformation.class , EmpireInformation.class , FleetInformation.class , MovementInformation.class ,
-				PlanetInformation.class , QueueInformation.class , QueueItemInformation.class ,
-				ResearchLineInformation.class , ResearchGraphInformation.class , ResourceDeltaInformation.class ,
-				ResourceProviderInformation.class , ShipsInformation.class , SystemInformation.class
-		} );
-
-		this.mMainInfo = new DebugInformationMapper( );
-		this.mResources = new EmpireResourceInformationMapper( );
-		this.mResearch = new ResearchInformationMapper( );
-		this.mPlanet = new PlanetInformationMapper( );
-		this.mPlanetResources = new ResourceRowMapper( );
-		this.mQueueItem = new QueueItemInformationMapper( );
-		this.mBuildings = new BuildingsInformationMapper( );
-		this.mFleet = new FleetInformationMapper( );
-		this.mShips = new ShipsInformationMapper( );
-	}
-
-
-	/**
-	 * Dependency injector that sets the data source
-	 * 
-	 * @param dataSource
-	 *            the data source
-	 */
-	@Autowired( required = true )
-	public void setDataSource( DataSource dataSource )
-	{
-		this.dTemplate = new JdbcTemplate( dataSource );
-	}
-
-
-	/**
-	 * Generate an empire's XML summary
-	 * 
-	 * <p>
-	 * Retrieve all information from the database, convert that information into XML dump record
-	 * instances through row mappers, then convert the top-level record into XML using the
-	 * component's {@link XStream} instance.
-	 */
-	@Override
-	public String getSummary( int empireId )
-	{
-		DebugInformation empireDump = this.dTemplate.queryForObject( Q_EMPIRE , this.mMainInfo , empireId );
-		this.getResources( empireId , empireDump );
-		this.getResearch( empireId , empireDump );
-
-		this.getPlanets( empireId , empireDump );
-		this.getFleets( empireId , empireDump );
-
-		return this.xStream.toXML( empireDump );
-	}
-
-
-	/**
-	 * Extract resources information
-	 * 
-	 * <p>
-	 * Read the list of empire resources from the appropriate view and add the extracted entries to
-	 * the empire's list of resources.
-	 * 
-	 * @param empireId
-	 *            the empire's identifier
-	 * @param empireDump
-	 *            the top-level instance
-	 */
-	private void getResources( int empireId , DebugInformation empireDump )
-	{
-		List< EmpireResourceInformation > resources = empireDump.getEmpire( ).getResources( );
-		for ( EmpireResourceInformation empRes : this.dTemplate.query( Q_RESOURCES , this.mResources , empireId ) ) {
-			resources.add( empRes );
-		}
-	}
-
-
-	/**
-	 * Get research information
-	 * 
-	 * <p>
-	 * Read all research-related information from the appropriate dump view, and add corresponding
-	 * entries to the top-level instance.
-	 * 
-	 * @param empireId
-	 *            the empire's identifier
-	 * @param empireDump
-	 *            the top-level instance
-	 */
-	private void getResearch( int empireId , DebugInformation empireDump )
-	{
-		for ( ResearchInformation ri : this.dTemplate.query( Q_RESEARCH , this.mResearch , empireId ) ) {
-			empireDump.getResearch( ).add( ri );
-		}
-	}
-
-
-	/**
-	 * Get empire planets and related information
-	 * 
-	 * <p>
-	 * Read the planet list and basic planet information from the appropriate dump view, then read
-	 * all extra information (resources, build queues, buildings).
-	 * 
-	 * @param empireId
-	 *            the empire's identifier
-	 * @param empireDump
-	 *            the top-level instance
-	 */
-	private void getPlanets( int empireId , DebugInformation empireDump )
-	{
-		HashMap< Integer , PlanetInformation > planets = new HashMap< Integer , PlanetInformation >( );
-		for ( PlanetInformation planet : this.dTemplate.query( Q_PLANETS , this.mPlanet , empireId ) ) {
-			empireDump.getPlanets( ).add( planet );
-			planets.put( planet.getId( ) , planet );
-		}
-
-		this.getPlanetResources( empireId , planets );
-		this.getBuildQueues( empireId , planets );
-		this.getBuildings( empireId , planets );
-	}
-
-
-	/**
-	 * Add resources information to planets
-	 * 
-	 * <p>
-	 * Access resources information for the empire's planets and add the records to each planet.
-	 * 
-	 * @param empireId
-	 *            the empire's identifier
-	 * @param planets
-	 *            a map associating planet records with their identifier
-	 */
-	private void getPlanetResources( int empireId , Map< Integer , PlanetInformation > planets )
-	{
-		for ( PlanetResourceRow resRow : this.dTemplate.query( Q_PLANET_RESOURCES , this.mPlanetResources , empireId ) ) {
-			PlanetInformation planet = planets.get( resRow.getPlanetId( ) );
-			planet.getResourceDeltas( ).add( resRow.getDelta( ) );
-
-			ResourceProviderInformation resProv = resRow.getProvider( );
-			if ( resProv != null ) {
-				planet.getResourceProviders( ).add( resProv );
-			}
-		}
-	}
-
-
-	/**
-	 * Add build queue information to planet records
-	 * 
-	 * <p>
-	 * Access the contents of build queues and add the records to the corresponding planets.
-	 * 
-	 * @param empireId
-	 *            the empire's identifier
-	 * @param planets
-	 *            the map of planets by identifier
-	 */
-	private void getBuildQueues( int empireId , Map< Integer , PlanetInformation > planets )
-	{
-		for ( QueueItemInformation queueItem : this.dTemplate.query( Q_BUILD_QUEUES , this.mQueueItem , empireId ) ) {
-			PlanetInformation planet = planets.get( queueItem.getPlanetId( ) );
-
-			QueueInformation queue;
-			if ( queueItem.isMilitary( ) ) {
-				queue = planet.getMilitaryQueue( );
-			} else {
-				queue = planet.getCivilianQueue( );
-			}
-
-			queue.getItems( ).add( queueItem );
-		}
-	}
-
-
-	/**
-	 * Add buildings information to planet records
-	 * 
-	 * <p>
-	 * Access the contents of the buildings dump view and add the building records to the
-	 * corresponding planets.
-	 * 
-	 * @param empireId
-	 *            the empire's identifier
-	 * @param planets
-	 *            the map of planets by identifier
-	 */
-	private void getBuildings( int empireId , Map< Integer , PlanetInformation > planets )
-	{
-		for ( BuildingsInformation bi : this.dTemplate.query( Q_BUILDINGS , this.mBuildings , empireId ) ) {
-			planets.get( bi.getPlanetId( ) ).getBuildings( ).add( bi );
-		}
-	}
-
-
-	/**
-	 * Retrieve information about the empire's fleets
-	 * 
-	 * <p>
-	 * Access the list of fleets, add the records to the top-level instance, then retrieve all
-	 * necessary information.
-	 * 
-	 * @param empireId
-	 *            the empire's identifier
-	 * @param empireDump
-	 *            the top-level empire dump
-	 */
-	private void getFleets( int empireId , DebugInformation empireDump )
-	{
-		Map< Long , FleetInformation > fleets = new HashMap< Long , FleetInformation >( );
-		for ( FleetInformation fi : this.dTemplate.query( Q_FLEETS , this.mFleet , empireId ) ) {
-			empireDump.getFleets( ).add( fi );
-			fleets.put( fi.getId( ) , fi );
-		}
-		this.getShips( empireId , fleets );
-	}
-
-
-	/**
-	 * Add ships information to fleet records
-	 * 
-	 * <p>
-	 * Retrieve information about ships and add the records to the corresponding fleets.
-	 * 
-	 * @param empireId
-	 *            the empire's identifier
-	 * @param fleets
-	 *            the map of fleets by identifier
-	 */
-	private void getShips( int empireId , Map< Long , FleetInformation > fleets )
-	{
-		for ( ShipsInformation si : this.dTemplate.query( Q_SHIPS , this.mShips , empireId ) ) {
-			fleets.get( si.getFleetId( ) ).getShips( ).add( si );
-		}
-	}
-
-}
diff --git a/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/FleetInformationMapper.java b/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/FleetInformationMapper.java
deleted file mode 100644
index 46b433f..0000000
--- a/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/FleetInformationMapper.java
+++ /dev/null
@@ -1,66 +0,0 @@
-package com.deepclone.lw.beans.bt.es;
-
-
-import java.sql.ResultSet;
-import java.sql.SQLException;
-
-import org.springframework.jdbc.core.RowMapper;
-
-import com.deepclone.lw.beans.bt.es.data.FleetInformation;
-import com.deepclone.lw.beans.bt.es.data.MovementInformation;
-
-
-
-/**
- * Fleet information row mapper
- * 
- * <p>
- * This class is responsible for mapping rows from <code>bugs.dump_fleets_view</code> into
- * {@link FleetInformation} instances.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- * 
- */
-final class FleetInformationMapper
-		implements RowMapper< FleetInformation >
-{
-
-	/**
-	 * Map a row from <code>bugs.dump_fleets_view</code>
-	 * 
-	 * <p>
-	 * Generate a {@link FleetInformation} instance from the row's contents. If the row indicates
-	 * that the fleet is moving, add a {@link MovementInformation} instance to the fleet information
-	 * record.
-	 */
-	@Override
-	public FleetInformation mapRow( ResultSet rs , int rowNum )
-			throws SQLException
-	{
-		FleetInformation fi = new FleetInformation( );
-		fi.setId( rs.getLong( "fleet_id" ) );
-		fi.setName( rs.getString( "fleet_name" ) );
-		fi.setStatus( rs.getString( "status" ) );
-		fi.setAttacking( rs.getBoolean( "attacking" ) );
-		fi.setLocationId( rs.getInt( "location_id" ) );
-		fi.setLocationName( rs.getString( "location_name" ) );
-
-		Integer sourceId = (Integer) rs.getObject( "source_id" );
-		if ( sourceId != null ) {
-			MovementInformation mi = new MovementInformation( );
-			mi.setSourceId( sourceId );
-			mi.setSourceName( rs.getString( "source_name" ) );
-			mi.setTimeLeft( rs.getInt( "time_left" ) );
-			mi.setStateTimeLeft( rs.getInt( "state_time_left" ) );
-			mi.setNearId( (Integer) rs.getObject( "ref_point_id" ) );
-			mi.setNearName( rs.getString( "ref_point_name" ) );
-			mi.setOutwards( (Boolean) rs.getObject( "outwards" ) );
-			mi.setPastRefPoint( (Boolean) rs.getObject( "past_ref_point" ) );
-			mi.setStartX( (Float) rs.getObject( "start_x" ) );
-			mi.setStartY( (Float) rs.getObject( "start_y" ) );
-			fi.setMovement( mi );
-		}
-
-		return fi;
-	}
-}
\ No newline at end of file
diff --git a/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/PlanetInformationMapper.java b/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/PlanetInformationMapper.java
deleted file mode 100644
index 87ebd06..0000000
--- a/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/PlanetInformationMapper.java
+++ /dev/null
@@ -1,50 +0,0 @@
-package com.deepclone.lw.beans.bt.es;
-
-
-import java.sql.ResultSet;
-import java.sql.SQLException;
-
-import org.springframework.jdbc.core.RowMapper;
-
-import com.deepclone.lw.beans.bt.es.data.PlanetInformation;
-
-
-
-/**
- * Top-level planet information row mapper
- * 
- * <p>
- * This class maps rows from <code>bugs.dump_planets_view</code> into {@link PlanetInformation}
- * instances.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- * 
- */
-final class PlanetInformationMapper
-		implements RowMapper< PlanetInformation >
-{
-
-	/**
-	 * Map a row from <code>bugs.dump_planets_view</code>
-	 * 
-	 * <p>
-	 * Create a new {@link PlanetInformation} instance from the row's contents. The instance's
-	 * civilian and military construction queues, while left mostly uninitialised, will have their
-	 * money and work accumulators set.
-	 */
-	@Override
-	public PlanetInformation mapRow( ResultSet rs , int rowNum )
-			throws SQLException
-	{
-		PlanetInformation pi = new PlanetInformation( );
-		pi.setId( rs.getInt( "planet_id" ) );
-		pi.setPopulation( rs.getDouble( "population" ) );
-		pi.setCurrentHappiness( rs.getDouble( "current_happiness" ) );
-		pi.setTargetHappiness( rs.getDouble( "target_happiness" ) );
-		pi.getCivilianQueue( ).setAccMoney( rs.getDouble( "civ_money" ) );
-		pi.getCivilianQueue( ).setAccWork( rs.getDouble( "civ_work" ) );
-		pi.getMilitaryQueue( ).setAccMoney( rs.getDouble( "mil_money" ) );
-		pi.getMilitaryQueue( ).setAccWork( rs.getDouble( "mil_work" ) );
-		return pi;
-	}
-}
\ No newline at end of file
diff --git a/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/PlanetResourceRow.java b/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/PlanetResourceRow.java
deleted file mode 100644
index 3d6a7e2..0000000
--- a/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/PlanetResourceRow.java
+++ /dev/null
@@ -1,96 +0,0 @@
-package com.deepclone.lw.beans.bt.es;
-
-
-import com.deepclone.lw.beans.bt.es.data.ResourceDeltaInformation;
-import com.deepclone.lw.beans.bt.es.data.ResourceProviderInformation;
-
-
-
-/**
- * Planet resource row information
- * 
- * <p>
- * Planet resources and resource providers are both extracted from the same
- * <code>bugs.planet_resources_view</code> rows. Because of that, this class is used to transmit the
- * information (as a {@link ResourceDeltaInformation} instance and an optional
- * {@link ResourceProviderInformation} instance) from the row mapper to the summary creation
- * component.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-class PlanetResourceRow
-{
-
-	/** Identifier of the planet */
-	private final int planetId;
-
-	/** Resource delta information */
-	private final ResourceDeltaInformation delta = new ResourceDeltaInformation( );
-
-	/** Resource provider information */
-	private ResourceProviderInformation provider;
-
-
-	/**
-	 * Initialise the instance by setting the planet identifier
-	 * 
-	 * @param planetId
-	 *            the planet's identifier
-	 */
-	public PlanetResourceRow( int planetId )
-	{
-		this.planetId = planetId;
-	}
-
-
-	/** @return the planet's identifier */
-	public int getPlanetId( )
-	{
-		return this.planetId;
-	}
-
-
-	/** @return the resource delta information record */
-	public ResourceDeltaInformation getDelta( )
-	{
-		return this.delta;
-	}
-
-
-	/** @return the resource provider information record */
-	public ResourceProviderInformation getProvider( )
-	{
-		return this.provider;
-	}
-
-
-	/**
-	 * Set the resource provider information record
-	 * 
-	 * @param provider
-	 *            the resource provider information record
-	 */
-	public void setProvider( ResourceProviderInformation provider )
-	{
-		this.provider = provider;
-	}
-
-
-	/**
-	 * Set the name of the resource
-	 * 
-	 * <p>
-	 * This method should be called once the rest of the record(s) has been initialised. It will set
-	 * the resource name on both the delta and the provider (if the latter exists).
-	 * 
-	 * @param resource
-	 *            the name of the resource
-	 */
-	public void setResource( String resource )
-	{
-		this.delta.setResource( resource );
-		if ( this.provider != null ) {
-			this.provider.setResource( resource );
-		}
-	}
-}
diff --git a/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/QueueItemInformationMapper.java b/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/QueueItemInformationMapper.java
deleted file mode 100644
index 0d21815..0000000
--- a/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/QueueItemInformationMapper.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package com.deepclone.lw.beans.bt.es;
-
-
-import java.sql.ResultSet;
-import java.sql.SQLException;
-
-import org.springframework.jdbc.core.RowMapper;
-
-import com.deepclone.lw.beans.bt.es.data.QueueItemInformation;
-
-
-
-/**
- * Generic row mapper for construction queue items
- * 
- * <p>
- * This class is responsible for mapping rows from <code>bugs.dump_queues_view</code> into
- * {@link QueueItemInformation} instances. These instances will be added to the right queue later.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- * 
- */
-final class QueueItemInformationMapper
-		implements RowMapper< QueueItemInformation >
-{
-
-	/**
-	 * Map a row from <code>bugs.dump_queues_view</code>
-	 * 
-	 * <p>
-	 * Create a {@link QueueItemInformation} instance from the row's contents.
-	 */
-	@Override
-	public QueueItemInformation mapRow( ResultSet rs , int rowNum )
-			throws SQLException
-	{
-		QueueItemInformation qii = new QueueItemInformation( );
-		qii.setPlanetId( rs.getInt( "planet_id" ) );
-		qii.setMilitary( rs.getBoolean( "military" ) );
-		qii.setId( rs.getInt( "item_id" ) );
-		qii.setName( rs.getString( "item_name" ) );
-		qii.setDestroy( rs.getBoolean( "destroy" ) );
-		qii.setAmount( rs.getInt( "amount" ) );
-		return qii;
-	}
-}
\ No newline at end of file
diff --git a/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/ResearchInformationMapper.java b/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/ResearchInformationMapper.java
deleted file mode 100644
index 09a6ce7..0000000
--- a/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/ResearchInformationMapper.java
+++ /dev/null
@@ -1,49 +0,0 @@
-package com.deepclone.lw.beans.bt.es;
-
-
-import java.sql.ResultSet;
-import java.sql.SQLException;
-
-import org.postgresql.util.PGobject;
-import org.springframework.jdbc.core.RowMapper;
-
-import com.deepclone.lw.beans.bt.es.data.ResearchGraphInformation;
-import com.deepclone.lw.beans.bt.es.data.ResearchInformation;
-import com.deepclone.lw.beans.bt.es.data.TechnologyState;
-
-
-
-/**
- * Research information row mapper
- * 
- * <p>
- * This class maps rows from <code>bugs.dump_research_view</code> into
- * {@link ResearchGraphInformation} instances.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- * 
- */
-final class ResearchInformationMapper
-		implements RowMapper< ResearchInformation >
-{
-
-	/**
-	 * Map a <code>bugs.dump_research_view</code> row
-	 * 
-	 * <p>
-	 * Create a {@link ResearchGraphInformation} instance from the row's contents.
-	 */
-	@Override
-	public ResearchInformation mapRow( ResultSet rs , int rowNum )
-			throws SQLException
-	{
-		ResearchGraphInformation ri = new ResearchGraphInformation( );
-		ri.setName( rs.getString( "name" ) );
-		ri.setState( TechnologyState.valueOf( ( (PGobject) rs.getObject( "state" ) ).toString( ) ) );
-		if ( ri.getState( ) == TechnologyState.RESEARCH ) {
-			ri.setPoints( rs.getDouble( "points" ) );
-			ri.setPriority( rs.getInt( "priority" ) );
-		}
-		return ri;
-	}
-}
\ No newline at end of file
diff --git a/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/ResourceRowMapper.java b/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/ResourceRowMapper.java
deleted file mode 100644
index 8f2ceed..0000000
--- a/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/ResourceRowMapper.java
+++ /dev/null
@@ -1,65 +0,0 @@
-package com.deepclone.lw.beans.bt.es;
-
-
-import java.sql.ResultSet;
-import java.sql.SQLException;
-
-import org.springframework.jdbc.core.RowMapper;
-
-import com.deepclone.lw.beans.bt.es.data.ResourceProviderInformation;
-
-
-
-/**
- * Mapper which extract planet resources and resource providers information
- * 
- * <p>
- * This class maps rows from <code>bugs.dump_planet_resources_view</code> into
- * {@link PlanetResourceRow} instances.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- * 
- */
-class ResourceRowMapper
-		implements RowMapper< PlanetResourceRow >
-{
-
-	/**
-	 * Map a row from <code>bugs.dump_planet_resources_view</code>
-	 * 
-	 * <p>
-	 * Generate the {@link PlanetResourceRow} instance with the correct planet identifier, resource
-	 * name, income and upkeep. If there is also a resource provider, attach a
-	 * {@link ResourceProviderInformation} instance to the result, and set its mining priority if
-	 * one exists.
-	 */
-	@Override
-	public PlanetResourceRow mapRow( ResultSet rs , int rowNum )
-			throws SQLException
-	{
-		PlanetResourceRow row = new PlanetResourceRow( rs.getInt( "planet_id" ) );
-
-		row.getDelta( ).setIncome( rs.getDouble( "pres_income" ) );
-		row.getDelta( ).setUpkeep( rs.getDouble( "pres_upkeep" ) );
-
-		double pCapacity = rs.getDouble( "resprov_quantity_max" );
-		if ( !rs.wasNull( ) ) {
-			ResourceProviderInformation rpi = new ResourceProviderInformation( );
-			rpi.setMaximalQuantity( pCapacity );
-			rpi.setCurrentQuantity( rs.getDouble( "resprov_quantity" ) );
-			rpi.setDifficulty( rs.getDouble( "resprov_difficulty" ) );
-			rpi.setRecovery( rs.getDouble( "resprov_recovery" ) );
-
-			int miningPriority = rs.getInt( "mining_priority" );
-			if ( !rs.wasNull( ) ) {
-				rpi.setMiningPriority( miningPriority );
-			}
-
-			row.setProvider( rpi );
-		}
-
-		row.setResource( rs.getString( "resource_name" ) );
-		return row;
-	}
-
-}
diff --git a/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/ShipsInformationMapper.java b/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/ShipsInformationMapper.java
deleted file mode 100644
index 730d054..0000000
--- a/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/ShipsInformationMapper.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package com.deepclone.lw.beans.bt.es;
-
-
-import java.sql.ResultSet;
-import java.sql.SQLException;
-
-import org.springframework.jdbc.core.RowMapper;
-
-import com.deepclone.lw.beans.bt.es.data.ShipsInformation;
-
-
-
-/**
- * Fleet ships information row mapper
- * 
- * <p>
- * This class is responsible for creating {@link ShipsInformation} instances from the contents of
- * <code>bugs.dump_ships_view</code>.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- * 
- */
-final class ShipsInformationMapper
-		implements RowMapper< ShipsInformation >
-{
-
-	/**
-	 * Map a row from <code>bugs.dump_ships_view</code>
-	 * 
-	 * <p>
-	 * Generate a {@link ShipsInformation} instance and initialise its fields based on the row's
-	 * contents.
-	 */
-	@Override
-	public ShipsInformation mapRow( ResultSet rs , int rowNum )
-			throws SQLException
-	{
-		ShipsInformation si = new ShipsInformation( );
-		si.setFleetId( rs.getLong( "fleet_id" ) );
-		si.setId( rs.getInt( "ship_id" ) );
-		si.setName( rs.getString( "ship_name" ) );
-		si.setAmount( rs.getInt( "amount" ) );
-		si.setDamage( rs.getDouble( "damage" ) );
-		return si;
-	}
-}
\ No newline at end of file
diff --git a/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/data/EmpireInformation.java b/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/data/EmpireInformation.java
deleted file mode 100644
index 0bee8fb..0000000
--- a/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/data/EmpireInformation.java
+++ /dev/null
@@ -1,141 +0,0 @@
-package com.deepclone.lw.beans.bt.es.data;
-
-
-import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
-
-
-
-/**
- * Empire information record for XML dumps
- * 
- * <p>
- * This class regroups all "main" empire information in XML dumps. This includes the empire's name
- * and identifier, details about the alliance, and the list of resources.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-@SuppressWarnings( "serial" )
-public class EmpireInformation
-		implements Serializable
-{
-
-	/** The empire's numeric identifier */
-	@XStreamAsAttribute
-	private Integer id;
-
-	/** The empire's name */
-	@XStreamAsAttribute
-	private String name;
-
-	/** The empire's cash */
-	@XStreamAsAttribute
-	private Double cash;
-
-	/**
-	 * The alliance the empire belongs to or has requested membership of (or <code>null</code> if
-	 * the empire is neither in an alliance nor requesting to join one)
-	 */
-	private AllianceInformation alliance;
-
-	/** The empire's resources */
-	private final ArrayList< EmpireResourceInformation > resources = new ArrayList< EmpireResourceInformation >( );
-
-
-	/** @return the empire's numeric identifier */
-	public Integer getId( )
-	{
-		return this.id;
-	}
-
-
-	/**
-	 * Set the empire's numeric identifier
-	 * 
-	 * @param id
-	 *            the empire's numeric identifier
-	 */
-	public void setId( int id )
-	{
-		this.id = id;
-	}
-
-
-	/** @return the empire's name */
-	public String getName( )
-	{
-		return this.name;
-	}
-
-
-	/**
-	 * Set the empire's name
-	 * 
-	 * @param name
-	 *            the empire's name
-	 */
-	public void setName( String name )
-	{
-		this.name = name;
-	}
-
-
-	/** @return the amount of cash possessed by the empire */
-	public Double getCash( )
-	{
-		return this.cash;
-	}
-
-
-	/**
-	 * Set the amount of cash possessed by the empire
-	 * 
-	 * @param cash
-	 *            the amount of cash possessed by the empire
-	 */
-	public void setCash( double cash )
-	{
-		this.cash = cash;
-	}
-
-
-	/**
-	 * @return the alliance the empire belongs to or has requested membership of, or
-	 *         <code>null</code> if the empire is neither in an alliance nor requesting to join one
-	 */
-	public AllianceInformation getAlliance( )
-	{
-		return this.alliance;
-	}
-
-
-	/**
-	 * Set the information about the alliance
-	 * 
-	 * @param alliance
-	 *            the information about the alliance
-	 */
-	public void setAlliance( AllianceInformation alliance )
-	{
-		this.alliance = alliance;
-	}
-
-
-	/**
-	 * Access the list of resources
-	 * 
-	 * @return the list of resources, even if none was set in the file the instance was loaded from.
-	 */
-	public List< EmpireResourceInformation > getResources( )
-	{
-		if ( this.resources == null ) {
-			return Collections.emptyList( );
-		}
-		return this.resources;
-	}
-
-}
diff --git a/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/data/EmpireResourceInformation.java b/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/data/EmpireResourceInformation.java
deleted file mode 100644
index 52e74ad..0000000
--- a/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/data/EmpireResourceInformation.java
+++ /dev/null
@@ -1,134 +0,0 @@
-package com.deepclone.lw.beans.bt.es.data;
-
-
-import java.io.Serializable;
-
-import com.thoughtworks.xstream.annotations.XStreamAlias;
-import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
-
-
-
-/**
- * Empire resources XML dump record
- * 
- * <p>
- * This class is used to store information about an empire's resources in debugging XML dumps. Each
- * instance indicates the amount possessed or owed for a given type of resources, as well as the
- * mining priority if it is a natural resource.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-@XStreamAlias( "resource" )
-@SuppressWarnings( "serial" )
-public class EmpireResourceInformation
-		implements Serializable
-{
-
-	/** The type of resources */
-	@XStreamAlias( "id" )
-	@XStreamAsAttribute
-	private String resource;
-
-	/** The amount of resources possessed */
-	@XStreamAsAttribute
-	private Double possessed;
-
-	/** The amount of resources owed */
-	@XStreamAsAttribute
-	private Double owed;
-
-	/**
-	 * The mining priority for this type of resource, or <code>null</code> if it is not a natural
-	 * resource
-	 */
-	@XStreamAlias( "mining-priority" )
-	@XStreamAsAttribute
-	private Integer miningPriority;
-
-
-	/** @return the type of resources */
-	public String getResource( )
-	{
-		return this.resource;
-	}
-
-
-	/**
-	 * Set the type of resources
-	 * 
-	 * @param resource
-	 *            the type of resources
-	 * 
-	 * @throws InvalidDumpContentsException
-	 *             if the specified resource type is <code>null</code>
-	 */
-	public void setResource( String resource )
-			throws InvalidDumpContentsException
-	{
-		if ( resource == null ) {
-			throw new InvalidDumpContentsException( this.getClass( ) , "resource" );
-		}
-		this.resource = resource;
-	}
-
-
-	/** @return the amount of resources possessed */
-	public Double getPossessed( )
-	{
-		return this.possessed;
-	}
-
-
-	/**
-	 * Set the amount of resources possessed
-	 * 
-	 * @param possessed
-	 *            the amount of resources possessed
-	 */
-	public void setPossessed( Double possessed )
-	{
-		this.possessed = possessed;
-	}
-
-
-	/** @return the amount of resources owed */
-	public Double getOwed( )
-	{
-		return this.owed;
-	}
-
-
-	/**
-	 * Set the amount of resources owed
-	 * 
-	 * @param owed
-	 *            the amount of resources owed
-	 */
-	public void setOwed( Double owed )
-	{
-		this.owed = owed;
-	}
-
-
-	/**
-	 * @return the mining priority for this type of resource, or <code>null</code> if it is not a
-	 *         natural resource
-	 */
-	public Integer getMiningPriority( )
-	{
-		return this.miningPriority;
-	}
-
-
-	/**
-	 * Set the mining priority for this type of resource
-	 * 
-	 * @param miningPriority
-	 *            the mining priority for this type of resource
-	 */
-	public void setMiningPriority( int miningPriority )
-	{
-		this.miningPriority = miningPriority;
-	}
-
-}
diff --git a/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/data/InvalidDumpContentsException.java b/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/data/InvalidDumpContentsException.java
deleted file mode 100644
index 2044984..0000000
--- a/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/data/InvalidDumpContentsException.java
+++ /dev/null
@@ -1,60 +0,0 @@
-package com.deepclone.lw.beans.bt.es.data;
-
-
-import java.io.Serializable;
-
-
-
-/**
- * Invalid dump contents exception
- * 
- * <p>
- * This runtime exception is thrown by the debugging data record classes when one of the fields is
- * set to an incorrect value.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- * 
- */
-public final class InvalidDumpContentsException
-		extends RuntimeException
-{
-	/** Serialisation identifier */
-	private static final long serialVersionUID = 1L;
-
-	/** Class in which the error was caused */
-	private final Class< ? extends Serializable > recordType;
-
-	/** Name of the field to which invalid contents were assigned */
-	private final String field;
-
-
-	/**
-	 * Initialise the exception by setting the record and field
-	 * 
-	 * @param type
-	 *            the type of the XML dump record
-	 * @param field
-	 *            the field to which invalid contents were assigned
-	 */
-	InvalidDumpContentsException( Class< ? extends Serializable > type , String field )
-	{
-		super( "Invalid contents for field " + field + " of record " + type.getSimpleName( ) );
-		this.recordType = type;
-		this.field = field;
-	}
-
-
-	/** @return the type of the XML dump record */
-	public Class< ? extends Serializable > getRecordType( )
-	{
-		return this.recordType;
-	}
-
-
-	/** @return the field to which invalid contents were assigned */
-	public String getField( )
-	{
-		return this.field;
-	}
-
-}
diff --git a/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/data/PlanetInformation.java b/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/data/PlanetInformation.java
deleted file mode 100644
index a03f60c..0000000
--- a/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/data/PlanetInformation.java
+++ /dev/null
@@ -1,210 +0,0 @@
-package com.deepclone.lw.beans.bt.es.data;
-
-
-import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.List;
-
-import com.thoughtworks.xstream.annotations.XStreamAlias;
-import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
-import com.thoughtworks.xstream.annotations.XStreamImplicit;
-
-
-
-/**
- * Planet XML record
- * 
- * <p>
- * This class is used in XML dumps to represent the information about a planet. It includes a few
- * basic values, as well as information about buildings, queues and resources.
- * 
- * <p>
- * This record exists since version 1 (B6M1) of XML dumps. However, the following changes were made
- * later.
- * <ul>
- * <li>Version 2 (B6M2):
- * <ul>
- * <li>resource providers added,
- * </ul>
- * </ul>
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- * 
- */
-@XStreamAlias( "planet" )
-@SuppressWarnings( "serial" )
-public class PlanetInformation
-		implements Serializable
-{
-
-	/** Planet identifier */
-	@XStreamAsAttribute
-	private Integer id;
-
-	/** Planet name */
-	@XStreamAsAttribute
-	private String name;
-
-	/** Current population of the planet */
-	@XStreamAlias( "population" )
-	private Double population;
-
-	/** Current happiness of the planet's population */
-	@XStreamAlias( "current-happiness" )
-	private Double currentHappiness;
-
-	/** Target happiness of the planet's population */
-	@XStreamAlias( "target-happiness" )
-	private double targetHappiness;
-
-	/** List of buildings */
-	@XStreamAlias( "buildings" )
-	private final List< BuildingsInformation > buildings = new ArrayList< BuildingsInformation >( );
-
-	/** Civilian construction queue */
-	@XStreamAlias( "civ-queue" )
-	private final QueueInformation civilianQueue = new QueueInformation( );
-
-	/** Military construction queue */
-	@XStreamAlias( "mil-queue" )
-	private final QueueInformation militaryQueue = new QueueInformation( );
-
-	/** Planet resource deltas */
-	@XStreamImplicit
-	private final ArrayList< ResourceDeltaInformation > resourceDeltas = new ArrayList< ResourceDeltaInformation >( );
-
-	/** List of resource providers */
-	@XStreamImplicit( itemFieldName = "resource-provider" )
-	private final ArrayList< ResourceProviderInformation > resourceProviders = new ArrayList< ResourceProviderInformation >( );
-
-
-	/** @return the planet's identifier */
-	public Integer getId( )
-	{
-		return this.id;
-	}
-
-
-	/**
-	 * Set the planet's identifier
-	 * 
-	 * @param id
-	 *            the planet's identifier
-	 */
-	public void setId( int id )
-	{
-		this.id = id;
-	}
-
-
-	/** @return the planet's name */
-	public String getName( )
-	{
-		return this.name;
-	}
-
-
-	/**
-	 * Set the planet's name
-	 * 
-	 * @param name
-	 *            the planet's name
-	 */
-	public void setName( String name )
-	{
-		this.name = name;
-	}
-
-
-	/** @return the planet's current population */
-	public Double getPopulation( )
-	{
-		return this.population;
-	}
-
-
-	/**
-	 * Set the planet's current population
-	 * 
-	 * @param population
-	 *            the planet's current population
-	 */
-	public void setPopulation( double population )
-	{
-		this.population = population;
-	}
-
-
-	/** @return the current happiness of the planet's population */
-	public Double getCurrentHappiness( )
-	{
-		return this.currentHappiness;
-	}
-
-
-	/**
-	 * Set the current happiness of the planet's population
-	 * 
-	 * @param currentHappiness
-	 *            the current happiness of the planet's population
-	 */
-	public void setCurrentHappiness( double currentHappiness )
-	{
-		this.currentHappiness = currentHappiness;
-	}
-
-
-	/** @return the target happiness of the planet's population */
-	public Double getTargetHappiness( )
-	{
-		return this.targetHappiness;
-	}
-
-
-	/**
-	 * Set the target happiness of the planet's population
-	 * 
-	 * @param targetHappiness
-	 *            the target happiness of the planet's population
-	 */
-	public void setTargetHappiness( double targetHappiness )
-	{
-		this.targetHappiness = targetHappiness;
-	}
-
-
-	/** @return the list of buildings constructed on the planet */
-	public List< BuildingsInformation > getBuildings( )
-	{
-		return this.buildings;
-	}
-
-
-	/** @return the civilian construction queue */
-	public QueueInformation getCivilianQueue( )
-	{
-		return this.civilianQueue;
-	}
-
-
-	/** @return the military construction queue */
-	public QueueInformation getMilitaryQueue( )
-	{
-		return this.militaryQueue;
-	}
-
-
-	/** @return the list of resource delta records */
-	public ArrayList< ResourceDeltaInformation > getResourceDeltas( )
-	{
-		return this.resourceDeltas;
-	}
-
-
-	/** @return the list of resource provider records */
-	public ArrayList< ResourceProviderInformation > getResourceProviders( )
-	{
-		return this.resourceProviders;
-	}
-
-}
diff --git a/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/data/ResearchGraphInformation.java b/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/data/ResearchGraphInformation.java
deleted file mode 100644
index 8f9e137..0000000
--- a/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/data/ResearchGraphInformation.java
+++ /dev/null
@@ -1,136 +0,0 @@
-package com.deepclone.lw.beans.bt.es.data;
-
-
-import com.thoughtworks.xstream.annotations.XStreamAlias;
-import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
-
-
-
-/**
- * Technology from the technology graph and associated state information
- * 
- * <p>
- * This class represents the state of a technology from the B6M2+ technology graph for the empire
- * being dumped.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-@SuppressWarnings( "serial" )
-@XStreamAlias( "technology" )
-public class ResearchGraphInformation
-		extends ResearchInformation
-{
-
-	/** The technology's name */
-	@XStreamAsAttribute
-	private String name;
-
-	/** The technology's state */
-	@XStreamAsAttribute
-	private TechnologyState state;
-
-	/**
-	 * The amount of accumulated research points, or <code>null</code> if the technology has been
-	 * researched
-	 */
-	@XStreamAsAttribute
-	private Double points;
-
-	/** The research priority, or <code>null</code> if the technology has been researched */
-	@XStreamAsAttribute
-	private Integer priority;
-
-
-	/**
-	 * Gets the technology's name.
-	 * 
-	 * @return the technology's name
-	 */
-	public String getName( )
-	{
-		return this.name;
-	}
-
-
-	/**
-	 * Sets the technology's name.
-	 * 
-	 * @param name
-	 *            the technology's new name
-	 */
-	public void setName( String name )
-	{
-		this.name = name;
-	}
-
-
-	/**
-	 * Gets the technology's state.
-	 * 
-	 * @return the technology's state
-	 */
-	public TechnologyState getState( )
-	{
-		return this.state;
-	}
-
-
-	/**
-	 * Sets the technology's state.
-	 * 
-	 * @param state
-	 *            the technology's new state
-	 */
-	public void setState( TechnologyState state )
-	{
-		this.state = state;
-	}
-
-
-	/**
-	 * Gets the amount of accumulated research points
-	 * 
-	 * @return the amount of accumulated research points, or <code>null</code> if the technology has
-	 *         been researched
-	 */
-	public Double getPoints( )
-	{
-		return this.points;
-	}
-
-
-	/**
-	 * Sets the amount of accumulated research points
-	 * 
-	 * @param points
-	 *            the amount of accumulated research points
-	 */
-	public void setPoints( Double points )
-	{
-		this.points = points;
-	}
-
-
-	/**
-	 * Gets the research priority
-	 * 
-	 * @return the research priority, or <code>null</code> if the technology has been researched
-	 */
-	public Integer getPriority( )
-	{
-		return this.priority;
-	}
-
-
-	/**
-	 * Sets the research priority
-	 * 
-	 * @param priority
-	 *            the new research priority
-	 */
-	public void setPriority( Integer priority )
-	{
-		this.priority = priority;
-	}
-
-}
diff --git a/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/data/ResearchInformation.java b/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/data/ResearchInformation.java
deleted file mode 100644
index 4465b2f..0000000
--- a/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/data/ResearchInformation.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package com.deepclone.lw.beans.bt.es.data;
-
-
-import java.io.Serializable;
-
-
-
-/**
- * Empty, base research record
- * 
- * <p>
- * This class used to contain B6M1 research line entries; however, in order to support B6M2
- * technologies while maintaining XML compatibility, it has been replaced with an empty class which
- * servces as the base class for both old and new records.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- * 
- */
-@SuppressWarnings( "serial" )
-public abstract class ResearchInformation
-		implements Serializable
-
-{
-	// EMPTY
-}
diff --git a/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/data/ResearchLineInformation.java b/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/data/ResearchLineInformation.java
deleted file mode 100644
index 392ee79..0000000
--- a/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/data/ResearchLineInformation.java
+++ /dev/null
@@ -1,137 +0,0 @@
-package com.deepclone.lw.beans.bt.es.data;
-
-
-import com.thoughtworks.xstream.annotations.XStreamAlias;
-import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
-
-
-
-/**
- * Research line information
- * 
- * <p>
- * This class defines data stored in the dumps for B6M1 research lines. It is no longer actively
- * used as of B6M2, but is kept around so the XML files can still be used if necessary.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-@XStreamAlias( "research-line" )
-public class ResearchLineInformation
-		extends ResearchInformation
-{
-
-	private static final long serialVersionUID = 1L;
-
-	/** Identifier of the technology line */
-	@XStreamAsAttribute
-	@XStreamAlias( "line" )
-	private int id;
-
-	/** Current level for that line */
-	@XStreamAsAttribute
-	@XStreamAlias( "level" )
-	private int currentLevel;
-
-	/** Name of the last level */
-	@XStreamAsAttribute
-	@XStreamAlias( "name" )
-	private String levelName;
-
-	/** Accumulated points towards the next level */
-	@XStreamAsAttribute
-	@XStreamAlias( "accumulated-points" )
-	private double accumulated;
-
-
-	/**
-	 * Gets the identifier of the technology line.
-	 * 
-	 * @return the identifier of the technology line
-	 */
-	public int getId( )
-	{
-		return this.id;
-	}
-
-
-	/**
-	 * Sets the identifier of the technology line.
-	 * 
-	 * @param id
-	 *            the new identifier of the technology line
-	 */
-	public void setId( int id )
-	{
-		this.id = id;
-	}
-
-
-	/**
-	 * Gets the current level for that line.
-	 * 
-	 * @return the current level for that line
-	 */
-	public int getCurrentLevel( )
-	{
-		return this.currentLevel;
-	}
-
-
-	/**
-	 * Sets the current level for that line.
-	 * 
-	 * @param currentLevel
-	 *            the new level for that line
-	 */
-	public void setCurrentLevel( int currentLevel )
-	{
-		this.currentLevel = currentLevel;
-	}
-
-
-	/**
-	 * Gets the name of the last level.
-	 * 
-	 * @return the name of the last level
-	 */
-	public String getLevelName( )
-	{
-		return this.levelName;
-	}
-
-
-	/**
-	 * Sets the name of the last level.
-	 * 
-	 * @param levelName
-	 *            the new name of the last level
-	 */
-	public void setLevelName( String levelName )
-	{
-		this.levelName = levelName;
-	}
-
-
-	/**
-	 * Gets the accumulated points towards the next level.
-	 * 
-	 * @return the accumulated points towards the next level
-	 */
-	public double getAccumulated( )
-	{
-		return this.accumulated;
-	}
-
-
-	/**
-	 * Sets the accumulated points towards the next level.
-	 * 
-	 * @param accumulated
-	 *            the new accumulated points towards the next level
-	 */
-	public void setAccumulated( double accumulated )
-	{
-		this.accumulated = accumulated;
-	}
-
-}
diff --git a/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/data/ResourceDeltaInformation.java b/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/data/ResourceDeltaInformation.java
deleted file mode 100644
index 679b077..0000000
--- a/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/data/ResourceDeltaInformation.java
+++ /dev/null
@@ -1,109 +0,0 @@
-package com.deepclone.lw.beans.bt.es.data;
-
-
-import java.io.Serializable;
-
-import com.thoughtworks.xstream.annotations.XStreamAlias;
-import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
-
-
-
-/**
- * Resource delta information
- * 
- * <p>
- * This class represents records which contain a resource's delta - that is, the income and upkeep
- * for some type of resource.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-@SuppressWarnings( "serial" )
-@XStreamAlias( "resource-delta" )
-public class ResourceDeltaInformation
-		implements Serializable
-{
-
-	/** Identifier of the resource */
-	@XStreamAlias( "id" )
-	@XStreamAsAttribute
-	private String resource;
-
-	/** Income for that type of resource */
-	@XStreamAsAttribute
-	private Double income;
-
-	/** Upkeep for that type of resource */
-	@XStreamAsAttribute
-	private Double upkeep;
-
-
-	/** @return the resource's identifier */
-	public String getResource( )
-	{
-		return this.resource;
-	}
-
-
-	/**
-	 * Set the resource's identifier
-	 * 
-	 * @param resource
-	 *            the resource's identifier
-	 * 
-	 * @throws InvalidDumpContentsException
-	 *             if the specified resource type is <code>null</code>
-	 */
-	public void setResource( String resource )
-			throws InvalidDumpContentsException
-	{
-		if ( resource == null ) {
-			throw new InvalidDumpContentsException( this.getClass( ) , "resource" );
-		}
-		this.resource = resource;
-	}
-
-
-	/**
-	 * @return the income for that type of resource, or <code>null</code> if no income information
-	 *         is available
-	 */
-	public Double getIncome( )
-	{
-		return this.income;
-	}
-
-
-	/**
-	 * Set the income for that type of resource
-	 * 
-	 * @param income
-	 *            the income for that type of resource
-	 */
-	public void setIncome( double income )
-	{
-		this.income = income;
-	}
-
-
-	/**
-	 * @return the upkeep for that type of resource, or <code>null</code> if no upkeep information
-	 *         is available
-	 */
-	public Double getUpkeep( )
-	{
-		return this.upkeep;
-	}
-
-
-	/**
-	 * Set the upkeep for that type of resource
-	 * 
-	 * @param upkeep
-	 *            the upkeep for that type of resource
-	 */
-	public void setUpkeep( double upkeep )
-	{
-		this.upkeep = upkeep;
-	}
-
-}
diff --git a/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/data/ResourceProviderInformation.java b/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/data/ResourceProviderInformation.java
deleted file mode 100644
index 29a9968..0000000
--- a/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/data/ResourceProviderInformation.java
+++ /dev/null
@@ -1,179 +0,0 @@
-package com.deepclone.lw.beans.bt.es.data;
-
-
-import java.io.Serializable;
-
-import com.thoughtworks.xstream.annotations.XStreamAlias;
-import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
-
-
-
-/**
- * Resource provider XML record
- * 
- * <p>
- * This class represents the information about a resource provider that will be serialised to the
- * debugging XML dump when a player posts a bug report.
- * 
- * <p>
- * This record exists since version 2 (B6M2) of XML dumps.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-@SuppressWarnings( "serial" )
-public class ResourceProviderInformation
-		implements Serializable
-{
-
-	/** Identifier of the resource */
-	@XStreamAsAttribute
-	private String resource;
-
-	/** Maximal quantity in the provider */
-	@XStreamAsAttribute
-	@XStreamAlias( "max" )
-	private Double maximalQuantity;
-
-	/** Current quantity in the provider */
-	@XStreamAsAttribute
-	@XStreamAlias( "current" )
-	private Double currentQuantity;
-
-	/** Extraction difficulty */
-	@XStreamAsAttribute
-	private Double difficulty;
-
-	/** Recovery rate */
-	@XStreamAsAttribute
-	private Double recovery;
-
-	/** Planet-specific mining priority */
-	@XStreamAlias( "mining-priority" )
-	@XStreamAsAttribute
-	private Integer miningPriority;
-
-
-	/** @return the resource's identifier */
-	public String getResource( )
-	{
-		return this.resource;
-	}
-
-
-	/**
-	 * Set the resource's identifier
-	 * 
-	 * @param resource
-	 *            the resource's identifier
-	 * 
-	 * @throws InvalidDumpContentsException
-	 *             if the resource's identifier is <code>null</code>
-	 */
-	public void setResource( String resource )
-			throws InvalidDumpContentsException
-	{
-		if ( resource == null ) {
-			throw new InvalidDumpContentsException( this.getClass( ) , "resource" );
-		}
-		this.resource = resource;
-	}
-
-
-	/** @return the provider's total capacity */
-	public Double getMaximalQuantity( )
-	{
-		return this.maximalQuantity;
-	}
-
-
-	/**
-	 * Set the maximal quantity of resources in the provider
-	 * 
-	 * @param maximalQuantity
-	 *            the provider's total capacity
-	 */
-	public void setMaximalQuantity( double maximalQuantity )
-	{
-		this.maximalQuantity = maximalQuantity;
-	}
-
-
-	/** @return the current quantity of resources in the provider */
-	public Double getCurrentQuantity( )
-	{
-		return this.currentQuantity;
-	}
-
-
-	/**
-	 * Set the current quantity of resources in the provider
-	 * 
-	 * @param currentQuantity
-	 *            the current quantity of resources in the provider
-	 */
-	public void setCurrentQuantity( double currentQuantity )
-	{
-		this.currentQuantity = currentQuantity;
-	}
-
-
-	/** @return the provider's extraction difficulty */
-	public Double getDifficulty( )
-	{
-		return this.difficulty;
-	}
-
-
-	/**
-	 * Set the provider's extraction difficulty
-	 * 
-	 * @param difficulty
-	 *            the provider's extraction difficulty
-	 */
-	public void setDifficulty( double difficulty )
-	{
-		this.difficulty = difficulty;
-	}
-
-
-	/** @return the provider's recovery rate */
-	public Double getRecovery( )
-	{
-		return this.recovery;
-	}
-
-
-	/**
-	 * Set the provider's recovery rate
-	 * 
-	 * @param recovery
-	 *            the provider's recovery rate
-	 */
-	public void setRecovery( double recovery )
-	{
-		this.recovery = recovery;
-	}
-
-
-	/**
-	 * @return the planet-specific mining priority, or <code>null</code> if the empire's global
-	 *         settings are in used
-	 */
-	public Integer getMiningPriority( )
-	{
-		return this.miningPriority;
-	}
-
-
-	/**
-	 * Set the planet-specific mining priority
-	 * 
-	 * @param miningPriority
-	 *            the planet-specific mining priority
-	 */
-	public void setMiningPriority( int miningPriority )
-	{
-		this.miningPriority = miningPriority;
-	}
-
-}
diff --git a/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/data/TechnologyState.java b/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/data/TechnologyState.java
deleted file mode 100644
index 3684b61..0000000
--- a/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/data/TechnologyState.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package com.deepclone.lw.beans.bt.es.data;
-
-
-/**
- * State of a (B6M2+) technology
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-public enum TechnologyState {
-
-	/** The technology is being researched */
-	RESEARCH ,
-
-	/** The technology needs to be implemented */
-	PENDING ,
-
-	/** The technology has been researched and implemented */
-	KNOWN
-
-}
diff --git a/legacyworlds-server-beans-bt/src/test/java/.empty b/legacyworlds-server-beans-bt/src/test/java/.empty
deleted file mode 100644
index e69de29..0000000
diff --git a/legacyworlds-server-beans-bt/src/test/resources/.empty b/legacyworlds-server-beans-bt/src/test/resources/.empty
deleted file mode 100644
index e69de29..0000000
diff --git a/legacyworlds-server-beans-eventlog/src/main/resources/configuration/meta/eventlog.xml b/legacyworlds-server-beans-eventlog/src/main/resources/configuration/meta/eventlog.xml
deleted file mode 100644
index 7841904..0000000
--- a/legacyworlds-server-beans-eventlog/src/main/resources/configuration/meta/eventlog.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<beans xmlns="http://www.springframework.org/schema/beans"
-	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	xsi:schemaLocation="
-                        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
-
-	<bean id="adminErrorMail" class="com.deepclone.lw.beans.eventlog.AdminErrorMailBean" />
-	<bean id="logCleaner" class="com.deepclone.lw.beans.eventlog.LogCleanerBean" />
-	<bean id="logger" class="com.deepclone.lw.beans.eventlog.LoggerBean" />
-	<bean id="logReader" class="com.deepclone.lw.beans.eventlog.LogReaderBean" />
-	<bean id="logWriter" class="com.deepclone.lw.beans.eventlog.LogWriterBean" />
-
-</beans>
\ No newline at end of file
diff --git a/legacyworlds-server-beans-eventlog/src/test/java/.empty b/legacyworlds-server-beans-eventlog/src/test/java/.empty
deleted file mode 100644
index e69de29..0000000
diff --git a/legacyworlds-server-beans-eventlog/src/test/resources/.empty b/legacyworlds-server-beans-eventlog/src/test/resources/.empty
deleted file mode 100644
index e69de29..0000000
diff --git a/legacyworlds-server-beans-events/pom.xml b/legacyworlds-server-beans-events/pom.xml
deleted file mode 100644
index de11442..0000000
--- a/legacyworlds-server-beans-events/pom.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-	<modelVersion>4.0.0</modelVersion>
-	<parent>
-		<artifactId>legacyworlds-server-beans</artifactId>
-		<groupId>com.deepclone.lw</groupId>
-		<version>1.0.0</version>
-		<relativePath>../legacyworlds-server-beans/pom.xml</relativePath>
-	</parent>
-
-	<artifactId>legacyworlds-server-beans-events</artifactId>
-	<version>${legacyworlds.version.main}.${legacyworlds.version.release}-${legacyworlds.version.build}</version>
-	<name>Legacy Worlds - Server - Components - Events</name>
-	<description>This package defines the components used to process and handle game events.</description>
-</project>
\ No newline at end of file
diff --git a/legacyworlds-server-beans-events/src/main/java/.empty b/legacyworlds-server-beans-events/src/main/java/.empty
deleted file mode 100644
index e69de29..0000000
diff --git a/legacyworlds-server-beans-events/src/main/java/com/deepclone/lw/beans/events/EventProcessorBean.java b/legacyworlds-server-beans-events/src/main/java/com/deepclone/lw/beans/events/EventProcessorBean.java
deleted file mode 100644
index 54a9154..0000000
--- a/legacyworlds-server-beans-events/src/main/java/com/deepclone/lw/beans/events/EventProcessorBean.java
+++ /dev/null
@@ -1,113 +0,0 @@
-package com.deepclone.lw.beans.events;
-
-
-import javax.sql.DataSource;
-
-import org.springframework.beans.factory.DisposableBean;
-import org.springframework.beans.factory.InitializingBean;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.transaction.PlatformTransactionManager;
-import org.springframework.transaction.support.TransactionTemplate;
-
-import com.deepclone.lw.interfaces.sys.Ticker;
-import com.deepclone.lw.interfaces.sys.Ticker.Frequency;
-
-
-
-/**
- * Events processor component
- * 
- * <p>
- * This component acquires the necessary dependencies to create an {@link EventProcessorTask}, does
- * so, and registers it with the ticker. It clears the reference to the task when destroyed.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- * 
- */
-class EventProcessorBean
-		implements InitializingBean , DisposableBean
-{
-
-	/** The ticker */
-	private Ticker ticker;
-
-	/** The Spring transaction template */
-	private TransactionTemplate tTemplate;
-
-	/** The database interface */
-	private DataSource dataSource;
-
-	/** The task */
-	private Runnable task;
-
-
-	/**
-	 * Dependency injector that sets the ticker component
-	 * 
-	 * @param ticker
-	 *            the ticker component
-	 */
-	@Autowired( required = true )
-	public void setTicker( Ticker ticker )
-	{
-		this.ticker = ticker;
-	}
-
-
-	/**
-	 * Dependency injector that sets the transaction manager
-	 * 
-	 * <p>
-	 * Creates the transaction template from the transaction manager
-	 * 
-	 * @param tManager
-	 *            the Spring transaction manager
-	 */
-	@Autowired( required = true )
-	public void setTransactionManager( PlatformTransactionManager tManager )
-	{
-		this.tTemplate = new TransactionTemplate( tManager );
-	}
-
-
-	/**
-	 * Dependency injector that sets the database interface
-	 * 
-	 * @param dataSource
-	 *            the database interface
-	 */
-	@Autowired( required = true )
-	public void setDataSource( DataSource dataSource )
-	{
-		this.dataSource = dataSource;
-	}
-
-
-	/**
-	 * Initialise and register the event processing task
-	 * 
-	 * <p>
-	 * When the component's dependencies have been injected, this method creates the
-	 * {@link EventProcessorTask} instance and registers it to the ticker.
-	 */
-	@Override
-	public void afterPropertiesSet( )
-	{
-		this.task = new EventProcessorTask( this.tTemplate , this.dataSource );
-		this.ticker.registerTask( Frequency.HIGH , "Events processor" , this.task );
-	}
-
-
-	/**
-	 * Clear the task reference
-	 * 
-	 * <p>
-	 * Remove the reference to the {@link EventProcessorTask} instance, allowing the ticker to clean
-	 * up.
-	 */
-	@Override
-	public void destroy( )
-	{
-		this.task = null;
-	}
-}
diff --git a/legacyworlds-server-beans-events/src/main/java/com/deepclone/lw/beans/events/EventProcessorTask.java b/legacyworlds-server-beans-events/src/main/java/com/deepclone/lw/beans/events/EventProcessorTask.java
deleted file mode 100644
index 4818331..0000000
--- a/legacyworlds-server-beans-events/src/main/java/com/deepclone/lw/beans/events/EventProcessorTask.java
+++ /dev/null
@@ -1,86 +0,0 @@
-package com.deepclone.lw.beans.events;
-
-
-import javax.sql.DataSource;
-
-import org.springframework.transaction.TransactionStatus;
-import org.springframework.transaction.support.TransactionCallback;
-import org.springframework.transaction.support.TransactionTemplate;
-
-import com.deepclone.lw.utils.StoredProc;
-
-
-
-/**
- * Event processing task
- * 
- * <p>
- * This class implements the task responsible for regular database event processing calls. It is
- * registered as a high-frequency ticker task by {@link EventProcessorBean}.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-class EventProcessorTask
-		implements Runnable
-{
-
-	/** The Spring transaction template */
-	private final TransactionTemplate tTemplate;
-
-	/** The stored procedure that implements event processing */
-	private final StoredProc eqProcess;
-
-
-	/**
-	 * Initialise the transaction template and stored procedure interface
-	 * 
-	 * @param tTemplate
-	 *            the transaction template
-	 * @param dataSource
-	 *            the database interface
-	 */
-	public EventProcessorTask( TransactionTemplate tTemplate , DataSource dataSource )
-	{
-		this.tTemplate = tTemplate;
-		this.eqProcess = new StoredProc( dataSource , "events" , "eq_process" );
-		this.eqProcess.addOutput( "_result" , java.sql.Types.BOOLEAN );
-	}
-
-
-	/**
-	 * When the task executes, it will call <code>events.eq_process()</code> repeatedly until the
-	 * stored procedure returns <code>false</code>. Each call is made in a separate transaction.
-	 */
-	@Override
-	public void run( )
-	{
-		boolean hasMore;
-		do {
-			hasMore = this.processBatch( );
-		} while ( hasMore );
-	}
-
-
-	/**
-	 * Process a batch of events
-	 * 
-	 * <p>
-	 * This method spawns a transaction in which the <code>events.eq_process()</code> stored
-	 * procedure is called.
-	 * 
-	 * @return <code>true</code> if events were processed, <code>false</code> if the queues were
-	 *         empty.
-	 */
-	private boolean processBatch( )
-	{
-		return this.tTemplate.execute( new TransactionCallback< Boolean >( ) {
-
-			@Override
-			public Boolean doInTransaction( TransactionStatus status )
-			{
-				return (Boolean) EventProcessorTask.this.eqProcess.execute( ).get( "_result" );
-			}
-
-		} );
-	}
-}
diff --git a/legacyworlds-server-beans-events/src/main/resources/.empty b/legacyworlds-server-beans-events/src/main/resources/.empty
deleted file mode 100644
index e69de29..0000000
diff --git a/legacyworlds-server-beans-events/src/test/java/.empty b/legacyworlds-server-beans-events/src/test/java/.empty
deleted file mode 100644
index e69de29..0000000
diff --git a/legacyworlds-server-beans-events/src/test/resources/.empty b/legacyworlds-server-beans-events/src/test/resources/.empty
deleted file mode 100644
index e69de29..0000000
diff --git a/legacyworlds-server-beans-i18n/pom.xml b/legacyworlds-server-beans-i18n/pom.xml
deleted file mode 100644
index 6660fee..0000000
--- a/legacyworlds-server-beans-i18n/pom.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-	<modelVersion>4.0.0</modelVersion>
-	<parent>
-		<artifactId>legacyworlds-server-beans</artifactId>
-		<groupId>com.deepclone.lw</groupId>
-		<version>1.0.0</version>
-		<relativePath>../legacyworlds-server-beans/pom.xml</relativePath>
-	</parent>
-
-	<artifactId>legacyworlds-server-beans-i18n</artifactId>
-	<name>Legacy Worlds - Server - Components - Internationalisation</name>
-	<description>This package defines the components which control server-side internationalised text management.</description>
-	<version>${legacyworlds.version.main}.${legacyworlds.version.release}-${legacyworlds.version.build}</version>
-
-</project>
diff --git a/legacyworlds-server-beans-i18n/src/test/java/.empty b/legacyworlds-server-beans-i18n/src/test/java/.empty
deleted file mode 100644
index e69de29..0000000
diff --git a/legacyworlds-server-beans-i18n/src/test/resources/.empty b/legacyworlds-server-beans-i18n/src/test/resources/.empty
deleted file mode 100644
index e69de29..0000000
diff --git a/legacyworlds-server-beans-mailer/src/test/java/.empty b/legacyworlds-server-beans-mailer/src/test/java/.empty
deleted file mode 100644
index e69de29..0000000
diff --git a/legacyworlds-server-beans-mailer/src/test/resources/.empty b/legacyworlds-server-beans-mailer/src/test/resources/.empty
deleted file mode 100644
index e69de29..0000000
diff --git a/legacyworlds-server-beans-naming/src/main/java/com/deepclone/lw/beans/naming/ObjectNameValidatorBean.java b/legacyworlds-server-beans-naming/src/main/java/com/deepclone/lw/beans/naming/ObjectNameValidatorBean.java
deleted file mode 100644
index 4f3b83f..0000000
--- a/legacyworlds-server-beans-naming/src/main/java/com/deepclone/lw/beans/naming/ObjectNameValidatorBean.java
+++ /dev/null
@@ -1,136 +0,0 @@
-package com.deepclone.lw.beans.naming;
-
-
-import java.util.regex.Pattern;
-
-import com.deepclone.lw.cmd.ObjectNameError;
-import com.deepclone.lw.interfaces.naming.ObjectNameValidator;
-
-
-
-/**
- * Object name validation component
- * 
- * <p>
- * This component implements the simple name "pre-validation" component, used before an empire or
- * map name is sent to the database.
- * 
- * <p>
- * By default, it will accept names that are between 2 and 20 characters. That may be modified in
- * the component's initialisation.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-class ObjectNameValidatorBean
-		implements ObjectNameValidator
-{
-	/** Default minimal length */
-	public static final int MIN_LENGTH = 2;
-
-	/** Default maximal length */
-	public static final int MAX_LENGTH = 20;
-
-	/**
-	 * Invalid patterns
-	 * 
-	 * <p>
-	 * This constant lists patterns which must be rejected systematically.
-	 */
-	private static final Pattern fail[] = {
-			Pattern.compile( "\\s\\s+" ) , Pattern.compile( "[^A-Za-z0-9 _\\'\\!\\:\\,\\-\\.\\*@\\[\\]\\{\\}]" )
-	};
-
-	/**
-	 * Required patterns
-	 * 
-	 * <p>
-	 * This constant lists patters which must be present for a name to be considered valid.
-	 */
-	private static final Pattern needed[] = {
-		Pattern.compile( "[A-Za-z]" )
-	};
-
-	/** Minimal length of a name */
-	private int minLength = MIN_LENGTH;
-
-	/** Maximal length of a name */
-	private int maxLength = MAX_LENGTH;
-
-
-	/**
-	 * Set the minimal length of a name
-	 * 
-	 * @param length
-	 *            the new minimal length
-	 */
-	public void setMinLength( Integer length )
-	{
-		this.minLength = length;
-	}
-
-
-	/**
-	 * Set the maximal length of a name
-	 * 
-	 * @param length
-	 *            the new maximal length
-	 */
-	public void setMaxLength( Integer length )
-	{
-		this.maxLength = length;
-	}
-
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see com.deepclone.lw.beans.user.ObjectNameValidator#validate(java.lang.String)
-	 */
-	@Override
-	public ObjectNameError validate( String name )
-	{
-		return this.validate( name , this.minLength , this.maxLength );
-	}
-
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see com.deepclone.lw.beans.user.ObjectNameValidator#customValidate(java.lang.String, int,
-	 * int)
-	 */
-	@Override
-	public ObjectNameError validate( String name , int minLength , int maxLength )
-	{
-		if ( "".equals( name.trim( ) ) ) {
-			return ObjectNameError.EMPTY;
-		}
-
-		// No leading or trailing spaces
-		if ( !name.equals( name.trim( ) ) ) {
-			return ObjectNameError.INVALID;
-		}
-
-		// Check length
-		int length = name.length( );
-		if ( length < minLength || length > maxLength ) {
-			return ObjectNameError.INVALID;
-		}
-
-		// Check bad patterns
-		for ( Pattern p : ObjectNameValidatorBean.fail ) {
-			if ( p.matcher( name ).find( ) ) {
-				return ObjectNameError.INVALID;
-			}
-		}
-
-		// Check good patterns
-		for ( Pattern p : ObjectNameValidatorBean.needed ) {
-			if ( !p.matcher( name ).find( ) ) {
-				return ObjectNameError.INVALID;
-			}
-		}
-
-		return null;
-	}
-}
diff --git a/legacyworlds-server-beans-naming/src/test/java/.empty b/legacyworlds-server-beans-naming/src/test/java/.empty
deleted file mode 100644
index e69de29..0000000
diff --git a/legacyworlds-server-beans-naming/src/test/resources/.empty b/legacyworlds-server-beans-naming/src/test/resources/.empty
deleted file mode 100644
index e69de29..0000000
diff --git a/legacyworlds-server-beans-resources/pom.xml b/legacyworlds-server-beans-resources/pom.xml
deleted file mode 100644
index 404345a..0000000
--- a/legacyworlds-server-beans-resources/pom.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-	<modelVersion>4.0.0</modelVersion>
-
-	<parent>
-		<artifactId>legacyworlds-server-beans</artifactId>
-		<groupId>com.deepclone.lw</groupId>
-		<version>1.0.0</version>
-		<relativePath>../legacyworlds-server-beans/pom.xml</relativePath>
-	</parent>
-
-	<artifactId>legacyworlds-server-beans-resources</artifactId>
-	<name>Legacy Worlds - Server - Components - Resources</name>
-	<version>${legacyworlds.version.main}.${legacyworlds.version.release}-${legacyworlds.version.build}</version>
-	<description>This module contains the components which manage and access in-universe resources, including money and natural resources.</description>
-
-</project>
\ No newline at end of file
diff --git a/legacyworlds-server-beans-resources/src/main/java/.empty b/legacyworlds-server-beans-resources/src/main/java/.empty
deleted file mode 100644
index e69de29..0000000
diff --git a/legacyworlds-server-beans-resources/src/main/java/com/deepclone/lw/beans/game/resources/AbstractResourceMapper.java b/legacyworlds-server-beans-resources/src/main/java/com/deepclone/lw/beans/game/resources/AbstractResourceMapper.java
deleted file mode 100644
index 39e7847..0000000
--- a/legacyworlds-server-beans-resources/src/main/java/com/deepclone/lw/beans/game/resources/AbstractResourceMapper.java
+++ /dev/null
@@ -1,61 +0,0 @@
-package com.deepclone.lw.beans.game.resources;
-
-
-import java.sql.ResultSet;
-import java.sql.SQLException;
-
-import org.springframework.jdbc.core.RowMapper;
-
-import com.deepclone.lw.cmd.player.gdata.AbstractResourceRecord;
-
-
-
-/**
- * Base class for resource information row mappers
- * 
- * <p>
- * This class can be used to map resource information rows (for either planets or empires). It
- * provides a method which maps the resource information's descriptive fields, and implements
- * Spring's {@link RowMapper} for the correct type.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- * 
- * @param <RTYPE>
- *            a resource information record based on {@link AbstractResourceRecord}.
- */
-abstract class AbstractResourceMapper< RTYPE extends AbstractResourceRecord >
-		implements RowMapper< RTYPE >
-{
-
-	/**
-	 * Extract a resource information row's descriptive fields
-	 * 
-	 * <p>
-	 * This method will extract the descriptive fields from a resource information row and store
-	 * them in a resource information instance. It extracts:
-	 * <ul>
-	 * <li>the resource's text identifier,
-	 * <li>the resource's internationalised name,
-	 * <li>the resource's internationalised description,
-	 * <li>the resource's internationalised category name, if there is one.
-	 * </ul>
-	 * 
-	 * @param resource
-	 *            the resource information record
-	 * @param rs
-	 *            the result set with the correct row selected
-	 * 
-	 * @throws SQLException
-	 *             if a SQLException is encountered getting column values
-	 */
-	protected final void getResourceDescription( RTYPE resource , ResultSet rs )
-			throws SQLException
-	{
-		resource.setIdentifier( rs.getString( "resource_identifier" ) );
-		resource.setTitle( rs.getString( "resource_name" ) );
-		resource.setDescription( rs.getString( "resource_description" ) );
-		resource.setCategory( rs.getString( "resource_category" ) );
-
-	}
-
-}
diff --git a/legacyworlds-server-beans-resources/src/main/java/com/deepclone/lw/beans/game/resources/EmpireResourceMapper.java b/legacyworlds-server-beans-resources/src/main/java/com/deepclone/lw/beans/game/resources/EmpireResourceMapper.java
deleted file mode 100644
index 71e6b7c..0000000
--- a/legacyworlds-server-beans-resources/src/main/java/com/deepclone/lw/beans/game/resources/EmpireResourceMapper.java
+++ /dev/null
@@ -1,72 +0,0 @@
-package com.deepclone.lw.beans.game.resources;
-
-
-import java.sql.ResultSet;
-import java.sql.SQLException;
-
-import com.deepclone.lw.cmd.player.gdata.empire.EmpireResourceRecord;
-
-
-
-/**
- * Row mapper for empire resources
- * 
- * <p>
- * This class is responsible for converting empire resource information rows into instances of the
- * corresponding class, {@link EmpireResourceRecord}.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-class EmpireResourceMapper
-		extends AbstractResourceMapper< EmpireResourceRecord >
-{
-
-	/**
-	 * Map a row from <code>emp.resources_view</code>
-	 * 
-	 * <p>
-	 * This method extracts the resource's description and the fields specific to empire resource
-	 * information from the row, returning the information as an {@link EmpireResourceRecord}
-	 * instance.
-	 */
-	@Override
-	public EmpireResourceRecord mapRow( ResultSet rs , int rowNum )
-			throws SQLException
-	{
-		EmpireResourceRecord resource = new EmpireResourceRecord( );
-		this.getResourceDescription( resource , rs );
-		this.getEmpireFields( resource , rs );
-		return resource;
-	}
-
-
-	/**
-	 * Read empire-specific resource information from a row
-	 * 
-	 * <p>
-	 * This method extracts the stockpiled quantity as well as income and upkeep from the row. If a
-	 * mining setting is set, it extracts it as well.
-	 * 
-	 * @param resource
-	 *            the empire resource record
-	 * @param rs
-	 *            the result set with the correct row selected
-	 * 
-	 * @throws SQLException
-	 *             if a SQLException is encountered getting column values
-	 */
-	private void getEmpireFields( EmpireResourceRecord resource , ResultSet rs )
-			throws SQLException
-	{
-		resource.setStockpiled( rs.getLong( "empres_possessed" ) );
-		resource.setPlanetUpkeep( rs.getLong( "planets_upkeep" ) );
-		resource.setIncome( rs.getLong( "planets_income" ) );
-		resource.setFleetUpkeep( rs.getLong( "fleets_upkeep" ) );
-
-		int miningPriority = rs.getInt( "empmset_weight" );
-		if ( !rs.wasNull( ) ) {
-			resource.setMiningPriority( miningPriority );
-		}
-	}
-
-}
diff --git a/legacyworlds-server-beans-resources/src/main/java/com/deepclone/lw/beans/game/resources/FullPlanetListRecord.java b/legacyworlds-server-beans-resources/src/main/java/com/deepclone/lw/beans/game/resources/FullPlanetListRecord.java
deleted file mode 100644
index 786a96a..0000000
--- a/legacyworlds-server-beans-resources/src/main/java/com/deepclone/lw/beans/game/resources/FullPlanetListRecord.java
+++ /dev/null
@@ -1,65 +0,0 @@
-package com.deepclone.lw.beans.game.resources;
-
-
-import com.deepclone.lw.cmd.player.gdata.PlanetListResourceRecord;
-
-
-
-/**
- * Intermediary class for planet list resource records extraction
- * 
- * <p>
- * This class is used as an intermediary to extract {@link PlanetListResourceRecord} instances from
- * <code>emp.plist_resources_view</code>. It contains the instance itself, and an additional field
- * which indicates the planet's identifier.
- * 
- * <p>
- * Instances of this class are returned by {@link PlanetListResourceRecordMapper} and then processed
- * to generate the map returned by {@link ResourcesInformationDAOBean#getPlanetListData(int)}.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- * 
- */
-class FullPlanetListRecord
-{
-	/** The planet's identifier */
-	private int planetId;
-
-	/** The resource record */
-	private final PlanetListResourceRecord record = new PlanetListResourceRecord( );
-
-
-	/**
-	 * Gets the planet's identifier.
-	 * 
-	 * @return the planet's identifier
-	 */
-	public int getPlanetId( )
-	{
-		return this.planetId;
-	}
-
-
-	/**
-	 * Sets the planet's identifier.
-	 * 
-	 * @param planetId
-	 *            the new planet's identifier
-	 */
-	public void setPlanetId( int planetId )
-	{
-		this.planetId = planetId;
-	}
-
-
-	/**
-	 * Gets the resource record.
-	 * 
-	 * @return the resource record
-	 */
-	public PlanetListResourceRecord getRecord( )
-	{
-		return this.record;
-	}
-
-}
diff --git a/legacyworlds-server-beans-resources/src/main/java/com/deepclone/lw/beans/game/resources/MiningSettingsDAOBean.java b/legacyworlds-server-beans-resources/src/main/java/com/deepclone/lw/beans/game/resources/MiningSettingsDAOBean.java
deleted file mode 100644
index e2585f3..0000000
--- a/legacyworlds-server-beans-resources/src/main/java/com/deepclone/lw/beans/game/resources/MiningSettingsDAOBean.java
+++ /dev/null
@@ -1,114 +0,0 @@
-package com.deepclone.lw.beans.game.resources;
-
-
-import java.sql.Types;
-
-import javax.sql.DataSource;
-
-import org.springframework.beans.factory.annotation.Autowired;
-
-import com.deepclone.lw.interfaces.game.resources.MiningSettingsDAO;
-import com.deepclone.lw.utils.StoredProc;
-
-
-
-/**
- * Data access component for mining settings
- * 
- * <p>
- * This component implements the methods which allow mining settings to be updated by calling the
- * appropriate stored procedures.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-class MiningSettingsDAOBean
-		implements MiningSettingsDAO
-{
-	/** <code>emp.mset_update_start(INT)</code> stored procedure */
-	private StoredProc pStartEmpireUpdate;
-
-	/** <code>emp.mset_update_start(INT,INT)</code> stored procedure */
-	private StoredProc pStartPlanetUpdate;
-
-	/** <code>emp.mset_update_set(TEXT,INT)</code> stored procedure */
-	private StoredProc pSetMiningPriority;
-
-	/** <code>emp.mset_update_apply()</code> stored procedure */
-	private StoredProc pApplyUpdate;
-
-	/** <code>emp.mset_toggle_source(INT,INT)</code> stored procedure */
-	private StoredProc pToggleSource;
-
-
-	/**
-	 * Dependency injector that sets the data source
-	 * 
-	 * @param dataSource
-	 *            the data source
-	 */
-	@Autowired( required = true )
-	public void setDataSource( DataSource dataSource )
-	{
-		this.pStartEmpireUpdate = new StoredProc( dataSource , "emp" , "mset_update_start" );
-		this.pStartEmpireUpdate.addParameter( "_empire" , Types.INTEGER );
-		this.pStartEmpireUpdate.addOutput( "_success" , Types.BOOLEAN );
-
-		this.pStartPlanetUpdate = new StoredProc( dataSource , "emp" , "mset_update_start" );
-		this.pStartPlanetUpdate.addParameter( "_empire" , Types.INTEGER );
-		this.pStartPlanetUpdate.addParameter( "_planet" , Types.INTEGER );
-		this.pStartPlanetUpdate.addOutput( "_success" , Types.BOOLEAN );
-
-		this.pSetMiningPriority = new StoredProc( dataSource , "emp" , "mset_update_set" );
-		this.pSetMiningPriority.addParameter( "_resource" , Types.VARCHAR );
-		this.pSetMiningPriority.addParameter( "_priority" , Types.INTEGER );
-		this.pSetMiningPriority.addOutput( "_success" , Types.BOOLEAN );
-
-		this.pApplyUpdate = new StoredProc( dataSource , "emp" , "mset_update_apply" );
-		this.pApplyUpdate.addOutput( "_success" , Types.BOOLEAN );
-
-		this.pToggleSource = new StoredProc( dataSource , "emp" , "mset_toggle_source" );
-		this.pToggleSource.addParameter( "_empire" , Types.INTEGER );
-		this.pToggleSource.addParameter( "_planet" , Types.INTEGER );
-	}
-
-
-	/* Documented in interface */
-	@Override
-	public boolean startUpdate( int empireId )
-	{
-		return (Boolean) this.pStartEmpireUpdate.execute( empireId ).get( "_success" );
-	}
-
-
-	/* Documented in interface */
-	@Override
-	public boolean startUpdate( int empire , int planet )
-	{
-		return (Boolean) this.pStartPlanetUpdate.execute( empire , planet ).get( "_success" );
-	}
-
-
-	/* Documented in interface */
-	@Override
-	public boolean setNewPriority( String resource , int priority )
-	{
-		return (Boolean) this.pSetMiningPriority.execute( resource , priority ).get( "_success" );
-	}
-
-
-	/* Documented in interface */
-	@Override
-	public boolean applyUpdate( )
-	{
-		return (Boolean) this.pApplyUpdate.execute( ).get( "_success" );
-	}
-
-
-	/* Documented in interface */
-	@Override
-	public void togglePlanet( int empire , int planet )
-	{
-		this.pToggleSource.execute( empire , planet );
-	}
-
-}
diff --git a/legacyworlds-server-beans-resources/src/main/java/com/deepclone/lw/beans/game/resources/PlanetListResourceRecordMapper.java b/legacyworlds-server-beans-resources/src/main/java/com/deepclone/lw/beans/game/resources/PlanetListResourceRecordMapper.java
deleted file mode 100644
index c09f25b..0000000
--- a/legacyworlds-server-beans-resources/src/main/java/com/deepclone/lw/beans/game/resources/PlanetListResourceRecordMapper.java
+++ /dev/null
@@ -1,72 +0,0 @@
-package com.deepclone.lw.beans.game.resources;
-
-
-import java.sql.ResultSet;
-import java.sql.SQLException;
-
-import org.springframework.jdbc.core.RowMapper;
-
-import com.deepclone.lw.cmd.player.gdata.PlanetListResourceRecord;
-
-
-
-/**
- * Planet list resource records mapper
- * 
- * <p>
- * This class is responsible for mapping rows from <code>emp.plist_resources_view</code> into
- * {@link FullPlanetListRecord} instances.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-class PlanetListResourceRecordMapper
-		implements RowMapper< FullPlanetListRecord >
-{
-
-	/**
-	 * Map a row from <code>emp.plist_resources_view</code>
-	 * 
-	 * <p>
-	 * Convert a row from <code>emp.plist_resources_view</code> into a {@link FullPlanetListRecord}
-	 * instance. The resulting instance will have both its planet identifier and actual record set
-	 * according to the row's contents.
-	 */
-	@Override
-	public FullPlanetListRecord mapRow( ResultSet rs , int rowNum )
-			throws SQLException
-	{
-		FullPlanetListRecord fullRecord = new FullPlanetListRecord( );
-
-		fullRecord.setPlanetId( rs.getInt( "planet_id" ) );
-		this.extractRecord( fullRecord.getRecord( ) , rs );
-
-		return fullRecord;
-	}
-
-
-	/**
-	 * Extract the contents of the actual record
-	 * 
-	 * <p>
-	 * This method extracts the contents of the record that will be sent to the client from the
-	 * result set.
-	 * 
-	 * @param record
-	 *            the planet list resource record to update
-	 * @param rs
-	 *            the result set to extract information from
-	 * 
-	 * @throws SQLException
-	 *             if a SQLException is encountered getting column values
-	 */
-	private void extractRecord( PlanetListResourceRecord record , ResultSet rs )
-			throws SQLException
-	{
-		record.setName( rs.getString( "resource_name" ) );
-		record.setIncome( rs.getLong( "pres_income" ) );
-		record.setUpkeep( rs.getLong( "pres_upkeep" ) );
-		record.setCivInvestment( rs.getLong( "civ_investment" ) );
-		record.setMilInvestment( rs.getLong( "mil_investment" ) );
-	}
-
-}
diff --git a/legacyworlds-server-beans-resources/src/main/java/com/deepclone/lw/beans/game/resources/PlanetResourceMapper.java b/legacyworlds-server-beans-resources/src/main/java/com/deepclone/lw/beans/game/resources/PlanetResourceMapper.java
deleted file mode 100644
index f35426d..0000000
--- a/legacyworlds-server-beans-resources/src/main/java/com/deepclone/lw/beans/game/resources/PlanetResourceMapper.java
+++ /dev/null
@@ -1,105 +0,0 @@
-package com.deepclone.lw.beans.game.resources;
-
-
-import java.sql.ResultSet;
-import java.sql.SQLException;
-
-import com.deepclone.lw.cmd.player.gdata.planets.PlanetResourceRecord;
-import com.deepclone.lw.cmd.player.gdata.planets.ResourceProviderRecord;
-
-
-
-/**
- * Row mapper for planet resources
- * 
- * <p>
- * This class maps rows obtained from the planet resources information stored procedure into
- * instances of {@link PlanetResourceRecord} which can be sent to a client.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-class PlanetResourceMapper
-		extends AbstractResourceMapper< PlanetResourceRecord >
-{
-
-	/**
-	 * Map a row from <code>emp.get_planet_resources( )</code>
-	 * 
-	 * <p>
-	 * This method extracts fields that are always present, generating the
-	 * {@link PlanetResourceRecord} instance and setting it accordingly, then reads resource
-	 * provider columns and adds a {@link ResourceProviderRecord} instance to the record if
-	 * necessary.
-	 */
-	@Override
-	public PlanetResourceRecord mapRow( ResultSet rs , int rowNum )
-			throws SQLException
-	{
-		PlanetResourceRecord resource = getResourceFields( rs );
-		getResourceProvider( rs , resource );
-		return resource;
-	}
-
-
-	/**
-	 * Map common fields into a {@link PlanetResourceRecord} instance
-	 * 
-	 * <p>
-	 * This method creates the instance then reads descriptive fields, then extracts the income,
-	 * upkeep and investment fields.
-	 * 
-	 * @param rs
-	 *            the JDBC result set that contains the row being extracted
-	 * 
-	 * @return the new {@link PlanetResourceRecord} instance with its common fields set
-	 * 
-	 * @throws SQLException
-	 *             if a SQLException is encountered getting column values
-	 */
-	private PlanetResourceRecord getResourceFields( ResultSet rs )
-			throws SQLException
-	{
-		PlanetResourceRecord resource = new PlanetResourceRecord( );
-		this.getResourceDescription( resource , rs );
-		resource.setIncome( rs.getLong( "pres_income" ) );
-		resource.setUpkeep( rs.getLong( "pres_upkeep" ) );
-		resource.setInvested( rs.getLong( "pres_invested" ) );
-		return resource;
-	}
-
-
-	/**
-	 * Map resource provider fields if they are present.
-	 * 
-	 * <p>
-	 * Check if the record includes resource provider information. If it does, extract the fields'
-	 * values into a {@link ResourceProviderRecord} instance and add it to the
-	 * {@link PlanetResourceRecord}.
-	 * 
-	 * @param rs
-	 *            the JDBC result set that contains the row being extracted
-	 * @param resource
-	 *            the {@link PlanetResourceRecord} instance to add information to
-	 * 
-	 * @throws SQLException
-	 *             if a SQLException is encountered getting column values
-	 */
-	private void getResourceProvider( ResultSet rs , PlanetResourceRecord resource )
-			throws SQLException
-	{
-		long capacity = rs.getLong( "resprov_capacity" );
-		if ( rs.wasNull( ) ) {
-			return;
-		}
-
-		ResourceProviderRecord provider = new ResourceProviderRecord( );
-
-		provider.setCapacity( capacity );
-		provider.setQuantity( rs.getLong( "resprov_quantity" ) );
-		provider.setDifficulty( rs.getInt( "resprov_difficulty" ) );
-		provider.setPriority( rs.getInt( "mset_weight" ) );
-
-		resource.setResourceProvider( provider );
-	}
-
-}
diff --git a/legacyworlds-server-beans-resources/src/main/java/com/deepclone/lw/beans/game/resources/ResourcesControllerBean.java b/legacyworlds-server-beans-resources/src/main/java/com/deepclone/lw/beans/game/resources/ResourcesControllerBean.java
deleted file mode 100644
index 1829713..0000000
--- a/legacyworlds-server-beans-resources/src/main/java/com/deepclone/lw/beans/game/resources/ResourcesControllerBean.java
+++ /dev/null
@@ -1,107 +0,0 @@
-package com.deepclone.lw.beans.game.resources;
-
-
-import java.util.Map;
-
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.transaction.annotation.Transactional;
-
-import com.deepclone.lw.interfaces.game.resources.MiningSettingsDAO;
-import com.deepclone.lw.interfaces.game.resources.ResourcesController;
-
-
-
-/**
- * Resources controller component
- * 
- * <p>
- * This component implements all game actions that affect resources or resource-related information,
- * such as mining priorities.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-@Transactional
-class ResourcesControllerBean
-		implements ResourcesController
-{
-
-	/** The mining settings access interface */
-	private MiningSettingsDAO settings;
-
-
-	/**
-	 * Dependency injector that sets the mining settings access interface
-	 * 
-	 * @param settings
-	 *            the mining settings access interface
-	 */
-	@Autowired( required = true )
-	public void setMiningSettingsDAO( MiningSettingsDAO settings )
-	{
-		this.settings = settings;
-	}
-
-
-	/**
-	 * Update an empire's mining settings
-	 * 
-	 * <p>
-	 * Start a mining settings update for the specified empire, then set each resource-specific
-	 * priority, then apply the update. Exit whenever something goes wrong.
-	 */
-	@Override
-	public void updateEmpireSettings( int empireId , Map< String , Integer > settings )
-	{
-		if ( this.settings.startUpdate( empireId ) ) {
-			this.sendMiningSettings( settings );
-		}
-	}
-
-
-	/* Documented in interface */
-	@Override
-	public void togglePlanet( int empire , int planet )
-	{
-		this.settings.togglePlanet( empire , planet );
-	}
-
-
-	/**
-	 * Update a planet's mining settings
-	 * 
-	 * <p>
-	 * Start a mining settings update for the specified planet / empire combination, then set each
-	 * resource-specific priority, then apply the update. Exit whenever something goes wrong.
-	 */
-	@Override
-	public void updatePlanetSettings( int empire , int planet , Map< String , Integer > settings )
-	{
-		if ( this.settings.startUpdate( empire , planet ) ) {
-			this.sendMiningSettings( settings );
-		}
-	}
-
-
-	/**
-	 * Send mining settings to the database
-	 * 
-	 * <p>
-	 * This method is called once a mining settings update has been started (whether it's a
-	 * planet-specific or empire-wide update). It sends all settings to the database server, and
-	 * aborts if anything goes wrong.
-	 * 
-	 * @param settings
-	 *            the settings to upload
-	 */
-	private void sendMiningSettings( Map< String , Integer > settings )
-	{
-		for ( Map.Entry< String , Integer > entry : settings.entrySet( ) ) {
-			if ( !this.settings.setNewPriority( entry.getKey( ) , entry.getValue( ) ) ) {
-				return;
-			}
-		}
-
-		this.settings.applyUpdate( );
-	}
-
-}
diff --git a/legacyworlds-server-beans-resources/src/main/java/com/deepclone/lw/beans/game/resources/ResourcesInformationDAOBean.java b/legacyworlds-server-beans-resources/src/main/java/com/deepclone/lw/beans/game/resources/ResourcesInformationDAOBean.java
deleted file mode 100644
index ca6b415..0000000
--- a/legacyworlds-server-beans-resources/src/main/java/com/deepclone/lw/beans/game/resources/ResourcesInformationDAOBean.java
+++ /dev/null
@@ -1,140 +0,0 @@
-package com.deepclone.lw.beans.game.resources;
-
-
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-
-import javax.sql.DataSource;
-
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.jdbc.core.JdbcTemplate;
-
-import com.deepclone.lw.cmd.player.gdata.PlanetListResourceRecord;
-import com.deepclone.lw.cmd.player.gdata.empire.EmpireResourceRecord;
-import com.deepclone.lw.cmd.player.gdata.planets.PlanetResourceRecord;
-import com.deepclone.lw.interfaces.game.resources.ResourcesInformationDAO;
-
-
-
-/**
- * Resource information access component
- * 
- * <p>
- * This component's goal is to read information about resources from the database and return the
- * records in some usable format.
- * 
- * <p>
- * It does not contain any method that actually change the database.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- * 
- */
-class ResourcesInformationDAOBean
-		implements ResourcesInformationDAO
-{
-
-	/** SQL query that fetches a planet's resources information */
-	private static final String Q_PLANET_RESOURCES = "SELECT * FROM emp.get_planet_resources( ? )";
-
-	/** SQL query that fetches an empire's resources information */
-	private static final String Q_EMPIRE_RESOURCES = "SELECT * FROM emp.resources_view WHERE empire_id = ?";
-
-	/** SQL query that fetches the resource records for an empire's planet list */
-	private static final String Q_PLIST_RESOURCES = "SELECT * FROM emp.plist_resources_view WHERE empire_id = ?";
-
-	/** Row mapper for planet resources */
-	private final PlanetResourceMapper mPlanetResource;
-
-	/** Row mapper for empire resources */
-	private final EmpireResourceMapper mEmpireResource;
-
-	/** Row mapper for planet list records */
-	private final PlanetListResourceRecordMapper mPlanetListRecord;
-
-	/** Spring JDBC interface */
-	private JdbcTemplate dTemplate;
-
-
-	/** Initialise the necessary row mappers */
-	public ResourcesInformationDAOBean( )
-	{
-		this.mPlanetResource = new PlanetResourceMapper( );
-		this.mEmpireResource = new EmpireResourceMapper( );
-		this.mPlanetListRecord = new PlanetListResourceRecordMapper( );
-	}
-
-
-	/**
-	 * Dependency injector that sets the data source
-	 * 
-	 * @param dataSource
-	 *            the data source
-	 */
-	@Autowired( required = true )
-	public void setDataSource( DataSource dataSource )
-	{
-		this.dTemplate = new JdbcTemplate( dataSource );
-	}
-
-
-	/**
-	 * Run the planet resources information query and extract the data
-	 * 
-	 * <p>
-	 * This implementation simply executes a query using the <code>emp.get_planet_resources()</code>
-	 * stored procedure and maps the resulting rows into a list of {@link PlanetResourceRecord}
-	 * instances.
-	 */
-	@Override
-	public List< PlanetResourceRecord > getPlanetInformation( int planet )
-	{
-		return this.dTemplate.query( Q_PLANET_RESOURCES , this.mPlanetResource , planet );
-	}
-
-
-	/**
-	 * Run the empire resources information query and extract the data
-	 * 
-	 * <p>
-	 * This implementation executes a query on <code>emp.resources_view</code> for a specific
-	 * empire, and maps the resulting rows into a list of {@link EmpireResourceRecord} instances.
-	 */
-	@Override
-	public List< EmpireResourceRecord > getEmpireInformation( int empire )
-	{
-		return this.dTemplate.query( Q_EMPIRE_RESOURCES , this.mEmpireResource , empire );
-	}
-
-
-	/**
-	 * Run the planet list resources query and extract the data
-	 * 
-	 * <p>
-	 * This implementation queries <code>emp.plist_resources_view</code> to obtain the planet list's
-	 * records, then maps the resulting rows using the intermediary {@link FullPlanetListRecord}
-	 * class, and finally associates records to the corresponding planet identifiers.
-	 */
-	@Override
-	public Map< Integer , List< PlanetListResourceRecord > > getPlanetListData( int empire )
-	{
-		Map< Integer , List< PlanetListResourceRecord > > result;
-		result = new HashMap< Integer , List< PlanetListResourceRecord > >( );
-
-		List< FullPlanetListRecord > queryOutput;
-		queryOutput = this.dTemplate.query( Q_PLIST_RESOURCES , this.mPlanetListRecord , empire );
-
-		for ( FullPlanetListRecord fullRecord : queryOutput ) {
-			List< PlanetListResourceRecord > records = result.get( fullRecord.getPlanetId( ) );
-			if ( records == null ) {
-				records = new LinkedList< PlanetListResourceRecord >( );
-				result.put( fullRecord.getPlanetId( ) , records );
-			}
-			records.add( fullRecord.getRecord( ) );
-		}
-
-		return result;
-	}
-
-}
diff --git a/legacyworlds-server-beans-resources/src/main/resources/.empty b/legacyworlds-server-beans-resources/src/main/resources/.empty
deleted file mode 100644
index e69de29..0000000
diff --git a/legacyworlds-server-beans-resources/src/main/resources/configuration/game/resources.xml b/legacyworlds-server-beans-resources/src/main/resources/configuration/game/resources.xml
deleted file mode 100644
index 12debf7..0000000
--- a/legacyworlds-server-beans-resources/src/main/resources/configuration/game/resources.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	xsi:schemaLocation="
-                        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
-
-	<bean id="miningSettingsDAO" class="com.deepclone.lw.beans.game.resources.MiningSettingsDAOBean" />
-	<bean id="resourcesController" class="com.deepclone.lw.beans.game.resources.ResourcesControllerBean" />
-	<bean id="resourcesInformationDAO" class="com.deepclone.lw.beans.game.resources.ResourcesInformationDAOBean" />
-
-</beans>
diff --git a/legacyworlds-server-beans-resources/src/test/java/.empty b/legacyworlds-server-beans-resources/src/test/java/.empty
deleted file mode 100644
index e69de29..0000000
diff --git a/legacyworlds-server-beans-resources/src/test/resources/.empty b/legacyworlds-server-beans-resources/src/test/resources/.empty
deleted file mode 100644
index e69de29..0000000
diff --git a/legacyworlds-server-beans-simple/pom.xml b/legacyworlds-server-beans-simple/pom.xml
deleted file mode 100644
index 023a858..0000000
--- a/legacyworlds-server-beans-simple/pom.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-	<modelVersion>4.0.0</modelVersion>
-	<parent>
-		<artifactId>legacyworlds-server-beans</artifactId>
-		<groupId>com.deepclone.lw</groupId>
-		<version>1.0.0</version>
-		<relativePath>../legacyworlds-server-beans/pom.xml</relativePath>
-	</parent>
-
-	<artifactId>legacyworlds-server-beans-simple</artifactId>
-	<name>Legacy Worlds - Server - Components - Simple game</name>
-	<version>${legacyworlds.version.main}.${legacyworlds.version.release}-${legacyworlds.version.build}</version>
-	<description>This module contains code that corresponds to a simple "placeholder" game. This code should become obsolete over time, as it is being replaced with actual LWB6 code, until the module can finally be removed.</description>
-</project>
diff --git a/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/empire/GeneralInformationRowMapper.java b/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/empire/GeneralInformationRowMapper.java
deleted file mode 100644
index fd8be8a..0000000
--- a/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/empire/GeneralInformationRowMapper.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package com.deepclone.lw.beans.empire;
-
-
-import java.sql.ResultSet;
-import java.sql.SQLException;
-
-import org.springframework.jdbc.core.RowMapper;
-
-import com.deepclone.lw.sqld.game.GeneralInformation;
-
-
-
-class GeneralInformationRowMapper
-		implements RowMapper< GeneralInformation >
-{
-
-	@Override
-	public GeneralInformation mapRow( ResultSet rs , int rowNum )
-			throws SQLException
-	{
-		GeneralInformation info = new GeneralInformation( );
-		
-		info.setName( rs.getString( "name" ) );
-		info.setTag( rs.getString( "alliance" ) );
-		info.setCash( rs.getLong( "cash" ) );
-		info.setLanguage( rs.getString( "language" ) );
-		info.setNextTick( rs.getLong( "game_time" ) );
-		info.setAccountId( rs.getInt( "account_id" ) );
-
-		String statusString = rs.getString( "status" );
-		info.setStatus( rs.wasNull( ) ? null : statusString.charAt( 0 ) );
-
-		return info;
-	}
-
-}
diff --git a/legacyworlds-server-beans-simple/src/test/java/.empty b/legacyworlds-server-beans-simple/src/test/java/.empty
deleted file mode 100644
index e69de29..0000000
diff --git a/legacyworlds-server-beans-simple/src/test/resources/.empty b/legacyworlds-server-beans-simple/src/test/resources/.empty
deleted file mode 100644
index e69de29..0000000
diff --git a/legacyworlds-server-beans-system/src/test/java/.empty b/legacyworlds-server-beans-system/src/test/java/.empty
deleted file mode 100644
index e69de29..0000000
diff --git a/legacyworlds-server-beans-system/src/test/resources/.empty b/legacyworlds-server-beans-system/src/test/resources/.empty
deleted file mode 100644
index e69de29..0000000
diff --git a/legacyworlds-server-beans-technologies/pom.xml b/legacyworlds-server-beans-technologies/pom.xml
deleted file mode 100644
index f3ddea4..0000000
--- a/legacyworlds-server-beans-technologies/pom.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-	<modelVersion>4.0.0</modelVersion>
-
-	<parent>
-		<artifactId>legacyworlds-server-beans</artifactId>
-		<groupId>com.deepclone.lw</groupId>
-		<version>1.0.0</version>
-		<relativePath>../legacyworlds-server-beans/pom.xml</relativePath>
-	</parent>
-
-	<artifactId>legacyworlds-server-beans-technologies</artifactId>
-	<name>Legacy Worlds - Server - Components - Technologies</name>
-	<version>${legacyworlds.version.main}.${legacyworlds.version.release}-${legacyworlds.version.build}</version>
-	<description>This module contains the components which manage and access in-universe technologies.</description>
-
-	<dependencies>
-
-		<dependency>
-			<groupId>postgresql</groupId>
-			<artifactId>postgresql</artifactId>
-		</dependency>
-
-	</dependencies>
-
-</project>
\ No newline at end of file
diff --git a/legacyworlds-server-beans-technologies/src/main/java/.empty b/legacyworlds-server-beans-technologies/src/main/java/.empty
deleted file mode 100644
index e69de29..0000000
diff --git a/legacyworlds-server-beans-technologies/src/main/java/com/deepclone/lw/beans/game/technologies/PlayerTechnologiesDAOBean.java b/legacyworlds-server-beans-technologies/src/main/java/com/deepclone/lw/beans/game/technologies/PlayerTechnologiesDAOBean.java
deleted file mode 100644
index ba2bf6e..0000000
--- a/legacyworlds-server-beans-technologies/src/main/java/com/deepclone/lw/beans/game/technologies/PlayerTechnologiesDAOBean.java
+++ /dev/null
@@ -1,143 +0,0 @@
-package com.deepclone.lw.beans.game.technologies;
-
-
-import java.sql.Types;
-import java.util.List;
-
-import javax.sql.DataSource;
-
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.jdbc.core.JdbcTemplate;
-
-import com.deepclone.lw.cmd.player.gdata.empire.ResearchData;
-import com.deepclone.lw.interfaces.game.technologies.PlayerTechnologiesDAO;
-import com.deepclone.lw.utils.StoredProc;
-
-
-
-/**
- * Data access component for player technologies
- * 
- * <p>
- * This class implements database queries and calls to stored procedures which allow players to
- * access and manage their empires' research.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-class PlayerTechnologiesDAOBean
-		implements PlayerTechnologiesDAO
-{
-
-	/** SQL query that fetches an empire's research state */
-	private static final String Q_EMPIRE_RESEARCH = "SELECT * FROM emp.technologies_view WHERE empire_id = ?";
-
-	/** Row mapper for research state entries */
-	private final ResearchRowMapper mResearch;
-	
-	/** Stored procedure that initiates a research priority update */
-	private StoredProc fResprioUpdateStart;
-
-	/** Stored procedure that uploads a single research priority */
-	private StoredProc fResprioUpdateSet;
-
-	/** Stored procedure that applies a research priority update */
-	private StoredProc fResprioUpdateApply;
-	
-	/** Stored procedure that implements a technology */
-	private StoredProc fTechnologyImplement;
-
-	/** Spring JDBC interface */
-	private JdbcTemplate dTemplate;
-
-
-	/** Initialise the necessary row mappers */
-	public PlayerTechnologiesDAOBean( )
-	{
-		this.mResearch = new ResearchRowMapper( );
-	}
-
-
-	/**
-	 * Dependency injector that sets the data source and initialises stored procedures 
-	 * 
-	 * @param dataSource
-	 *            the data source
-	 */
-	@Autowired( required = true )
-	public void setDataSource( DataSource dataSource )
-	{
-		this.dTemplate = new JdbcTemplate( dataSource );
-
-		this.fResprioUpdateStart = new StoredProc( dataSource , "emp" , "resprio_update_start" )
-			.addParameter( "_empire" , Types.INTEGER )
-			.addOutput( "_result" , Types.BOOLEAN );
-
-		this.fResprioUpdateSet = new StoredProc( dataSource , "emp" , "resprio_update_set" )
-			.addParameter( "_technology" , Types.VARCHAR )
-			.addParameter( "_priority" , Types.INTEGER )
-			.addOutput( "_result" , Types.BOOLEAN );
-
-		this.fResprioUpdateApply = new StoredProc( dataSource , "emp" , "resprio_update_apply" )
-			.addOutput( "_result" , Types.BOOLEAN );
-
-		this.fTechnologyImplement = new StoredProc( dataSource , "emp" , "technology_implement" )
-			.addParameter( "_empire" , Types.INTEGER )
-			.addParameter( "_technology" , Types.VARCHAR )
-			.addOutput( "_result" , Types.BOOLEAN );
-	}
-
-
-	/**
-	 * Query and map research entries for an empire
-	 * 
-	 * <p>
-	 * Run the query against <code>emp.technologies_view</code> then map all rows using a
-	 * {@link ResearchRowMapper}.
-	 */
-	@Override
-	public List< ResearchData > getResearchData( int empire )
-	{
-		return this.dTemplate.query( Q_EMPIRE_RESEARCH , this.mResearch , empire );
-	}
-
-
-	/**
-	 * Call <code>emp.resprio_update_start</code>
-	 */
-	@Override
-	public boolean startPriorityUpdate( int empire )
-	{
-		return (Boolean) this.fResprioUpdateStart.execute( empire ).get( "_result" );
-	}
-
-
-	/**
-	 * Call <code>emp.resprio_update_set</code>
-	 */
-	@Override
-	public boolean uploadResearchPriority( String identifier , int priority )
-	{
-		return (Boolean) this.fResprioUpdateSet.execute( identifier , priority ).get( "_result" );
-	}
-
-
-	/**
-	 * Call <code>emp.resprio_update_apply</code>
-	 */
-	@Override
-	public boolean applyPriorityUpdate( )
-	{
-		return (Boolean) this.fResprioUpdateApply.execute( ).get( "_result" );
-	}
-
-
-	/**
-	 * Call <code>emp.technology_implement</code>
-	 */
-	@Override
-	public boolean implement( int empire , String technology )
-	{
-		return (Boolean) this.fTechnologyImplement.execute( empire , technology ).get( "_result" );
-	}
-
-}
diff --git a/legacyworlds-server-beans-technologies/src/main/java/com/deepclone/lw/beans/game/technologies/ResearchControllerBean.java b/legacyworlds-server-beans-technologies/src/main/java/com/deepclone/lw/beans/game/technologies/ResearchControllerBean.java
deleted file mode 100644
index 7be0c2d..0000000
--- a/legacyworlds-server-beans-technologies/src/main/java/com/deepclone/lw/beans/game/technologies/ResearchControllerBean.java
+++ /dev/null
@@ -1,224 +0,0 @@
-package com.deepclone.lw.beans.game.technologies;
-
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.transaction.annotation.Transactional;
-
-import com.deepclone.lw.cmd.player.gdata.GamePageData;
-import com.deepclone.lw.cmd.player.gdata.empire.ResearchData;
-import com.deepclone.lw.cmd.player.tech.GetResearchResponse;
-import com.deepclone.lw.interfaces.game.EmpireManagement;
-import com.deepclone.lw.interfaces.game.technologies.PlayerTechnologiesDAO;
-import com.deepclone.lw.interfaces.game.technologies.ResearchController;
-import com.deepclone.lw.interfaces.i18n.TranslationException;
-import com.deepclone.lw.interfaces.i18n.Translator;
-
-
-
-/**
- * Research control component
- * 
- * <p>
- * This component implements all actions allowing a player to view and update its empire's research
- * state.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-@Transactional
-class ResearchControllerBean
-		implements ResearchController
-{
-	/** Main empire management component */
-	private EmpireManagement empireManagement;
-
-	/** String translator */
-	private Translator translator;
-
-	/** Data access object for technologies */
-	private PlayerTechnologiesDAO playerTechnologiesDAO;
-
-
-	/**
-	 * Dependency injector that sets the empire management component
-	 * 
-	 * @param empireManagement
-	 *            the empire management component
-	 */
-	@Autowired( required = true )
-	public void setEmpireManagement( EmpireManagement empireManagement )
-	{
-		this.empireManagement = empireManagement;
-	}
-
-
-	/**
-	 * Dependency injector that sets the translation component
-	 * 
-	 * @param translator
-	 *            the translation component
-	 */
-	@Autowired( required = true )
-	public void setTranslator( Translator translator )
-	{
-		this.translator = translator;
-	}
-
-
-	/**
-	 * Dependency injector that sets the data access object for technologies
-	 * 
-	 * @param playerTechnologiesDAO
-	 *            the data access object for technologies
-	 */
-	@Autowired( required = true )
-	public void setPlayerTechnologiesDAO( PlayerTechnologiesDAO playerTechnologiesDAO )
-	{
-		this.playerTechnologiesDAO = playerTechnologiesDAO;
-	}
-
-
-	/**
-	 * Get the raw research data from the database, then handle translation and dependencies
-	 * 
-	 * <p>
-	 * In order to generate the response, this method fetches the raw research state information
-	 * from the database. It then proceeds with translating all categories, names and descriptions,
-	 * then adds reverse dependency information to all loaded technologies.
-	 */
-	@Override
-	public GetResearchResponse getResearchData( int empire )
-	{
-		GamePageData pageData = this.empireManagement.getGeneralInformation( empire );
-		List< ResearchData > technologies = this.playerTechnologiesDAO.getResearchData( empire );
-
-		// Translate categories, names and descriptions
-		Map< String , String > translations = this.getTranslationsFor( technologies , pageData.getLanguage( ) );
-		Map< String , ResearchData > byId = new HashMap< String , ResearchData >( );
-		for ( ResearchData tech : technologies ) {
-			byId.put( tech.getIdentifier( ) , tech );
-			tech.setCategory( translations.get( tech.getCategory( ) ) );
-			if ( tech.getName( ) != null ) {
-				tech.setName( translations.get( tech.getName( ) ) );
-				tech.setDescription( translations.get( tech.getDescription( ) ) );
-			}
-
-			tech.setBuildings( this.translateList( tech.getBuildings( ) , translations ) );
-		}
-
-		// Add reverse dependency identifiers
-		for ( ResearchData tech : technologies ) {
-			for ( String dependency : tech.getDependencies( ) ) {
-				byId.get( dependency ).addReverseDependency( tech.getIdentifier( ) );
-			}
-		}
-
-		return new GetResearchResponse( pageData , technologies );
-	}
-
-
-	/**
-	 * Get translations used by a list of raw research entries
-	 * 
-	 * <p>
-	 * This method is fed the raw research state data from the player technologies data access
-	 * object. It generates a set of string identifiers which contains all categories, names and
-	 * descriptions, then fetches these strings' translations.
-	 * 
-	 * @param technologies
-	 *            the research state data from the DAO
-	 * @param language
-	 *            the player's selected language
-	 * 
-	 * @return the map of string identifiers to string contents
-	 */
-	private Map< String , String > getTranslationsFor( List< ResearchData > technologies , String language )
-	{
-		Set< String > identifiers = new HashSet< String >( );
-		for ( ResearchData tech : technologies ) {
-			identifiers.add( tech.getCategory( ) );
-			if ( tech.getName( ) != null ) {
-				identifiers.add( tech.getName( ) );
-				identifiers.add( tech.getDescription( ) );
-			}
-			identifiers.addAll( tech.getBuildings( ) );
-		}
-
-		try {
-			return this.translator.translate( language , identifiers );
-		} catch ( TranslationException e ) {
-			throw new RuntimeException( "error while translating technology-related data" , e );
-		}
-	}
-
-
-	/**
-	 * Translate a list of strings
-	 * 
-	 * <p>
-	 * This method fetches translations for a list of string identifiers.
-	 * 
-	 * @param input
-	 *            the list of strings to translate
-	 * @param translations
-	 *            the map of translations returned by {@link #getTranslationsFor(List, String)}
-	 * 
-	 * @return the translated list of strings
-	 */
-	private List< String > translateList( List< String > input , Map< String , String > translations )
-	{
-		ArrayList< String > result = new ArrayList< String >( input.size( ) );
-		for ( String str : input ) {
-			result.add( translations.get( str ) );
-		}
-		return result;
-	}
-
-
-	/**
-	 * Update research priorities
-	 * 
-	 * <p>
-	 * This method will start a research priority update for the specified empire, then upload each
-	 * value in the map to the database. Finally, it will try to apply the update.
-	 * 
-	 * <p>
-	 * If any of the above steps fail, the method will abort.
-	 */
-	@Override
-	public boolean updatePriorities( int empire , Map< String , Integer > priorities )
-	{
-		if ( !this.playerTechnologiesDAO.startPriorityUpdate( empire ) ) {
-			return false;
-		}
-
-		for ( Map.Entry< String , Integer > entry : priorities.entrySet( ) ) {
-			if ( !this.playerTechnologiesDAO.uploadResearchPriority( entry.getKey( ) , entry.getValue( ) ) ) {
-				return false;
-			}
-		}
-
-		return this.playerTechnologiesDAO.applyPriorityUpdate( );
-	}
-
-
-	/**
-	 * Implement a technology
-	 * 
-	 * <p>
-	 * Call the DAO's technology implementation method in order to access the corresponding stored
-	 * procedure.
-	 */
-	@Override
-	public boolean implement( int empire , String technology )
-	{
-		return this.playerTechnologiesDAO.implement( empire , technology );
-	}
-
-}
diff --git a/legacyworlds-server-beans-technologies/src/main/java/com/deepclone/lw/beans/game/technologies/ResearchRowMapper.java b/legacyworlds-server-beans-technologies/src/main/java/com/deepclone/lw/beans/game/technologies/ResearchRowMapper.java
deleted file mode 100644
index 8f0b19f..0000000
--- a/legacyworlds-server-beans-technologies/src/main/java/com/deepclone/lw/beans/game/technologies/ResearchRowMapper.java
+++ /dev/null
@@ -1,95 +0,0 @@
-package com.deepclone.lw.beans.game.technologies;
-
-
-import java.sql.ResultSet;
-import java.sql.SQLException;
-
-import org.postgresql.util.PGobject;
-
-import org.springframework.jdbc.core.RowMapper;
-
-import com.deepclone.lw.cmd.player.gdata.empire.ResearchData;
-
-
-
-/**
- * Row mapper for empire research state entries
- * 
- * <p>
- * This class is responsible for converting empire research state information rows into instances of
- * the corresponding class, {@link ResearchData}. The instances it produces are "raw": they contain
- * string identifiers instead of translations, and their reverse dependencies are not set.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- * 
- */
-class ResearchRowMapper
-		implements RowMapper< ResearchData >
-{
-
-	/**
-	 * Map a row from <code>emp.technologies_view</code>
-	 * 
-	 * <p>
-	 * This method maps a single row from the <code>emp.technologies_view</code> view into a
-	 * {@link ResearchData} instance.
-	 */
-	@Override
-	public ResearchData mapRow( ResultSet rs , int rowNum )
-			throws SQLException
-	{
-		ResearchData output = new ResearchData( );
-
-		output.setIdentifier( rs.getString( "emptech_id" ) );
-		output.setCategory( rs.getString( "technology_category" ) );
-
-		if ( rs.getBoolean( "emptech_visible" ) ) {
-			output.setName( rs.getString( "technology_name" ) );
-			output.setDescription( rs.getString( "technology_description" ) );
-			output.setPrice( rs.getLong( "technology_price" ) );
-		}
-
-		int ratio = rs.getInt( "emptech_ratio" );
-		if ( rs.wasNull( ) ) {
-			String state = ( (PGobject) rs.getObject( "emptech_state" ) ).getValue( );
-			output.setImplemented( "KNOWN".equals( state ) );
-		} else {
-			output.setCompletion( ratio );
-			output.setPriority( rs.getInt( "emptech_priority" ) );
-		}
-
-		output.setDependencies( this.splitField( rs , "technology_dependencies" ) );
-		output.setBuildings( this.splitField( rs , "technology_buildings" ) );
-
-		return output;
-	}
-
-
-	/**
-	 * Extract a comma-separated field
-	 * 
-	 * <p>
-	 * This method accesses then extracts the contents of a comma-separated field (for example
-	 * dependencies or unlocked buildings).
-	 * 
-	 * @param rs
-	 *            the SQL result set
-	 * @param field
-	 *            the field's name
-	 * 
-	 * @return an array of strings containing the field's values
-	 * 
-	 * @throws SQLException
-	 *             if something goes wrong while accessing the field
-	 */
-	private String[] splitField( ResultSet rs , String field )
-			throws SQLException
-	{
-		String fValue = rs.getString( field );
-		if ( fValue == null || "".equals( fValue ) ) {
-			return new String[ 0 ];
-		}
-		return fValue.split( "," );
-	}
-
-}
diff --git a/legacyworlds-server-beans-technologies/src/main/resources/.empty b/legacyworlds-server-beans-technologies/src/main/resources/.empty
deleted file mode 100644
index e69de29..0000000
diff --git a/legacyworlds-server-beans-technologies/src/main/resources/configuration/game/technologies.xml b/legacyworlds-server-beans-technologies/src/main/resources/configuration/game/technologies.xml
deleted file mode 100644
index e0b7bdc..0000000
--- a/legacyworlds-server-beans-technologies/src/main/resources/configuration/game/technologies.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	xsi:schemaLocation="
-                        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
-
-	<bean id="playerTechnologiesDAO" class="com.deepclone.lw.beans.game.technologies.PlayerTechnologiesDAOBean" />
-	<bean id="reesearchController" class="com.deepclone.lw.beans.game.technologies.ResearchControllerBean" />
-
-</beans>
diff --git a/legacyworlds-server-beans-technologies/src/test/java/.empty b/legacyworlds-server-beans-technologies/src/test/java/.empty
deleted file mode 100644
index e69de29..0000000
diff --git a/legacyworlds-server-beans-technologies/src/test/resources/.empty b/legacyworlds-server-beans-technologies/src/test/resources/.empty
deleted file mode 100644
index e69de29..0000000
diff --git a/legacyworlds-server-beans-updates/pom.xml b/legacyworlds-server-beans-updates/pom.xml
deleted file mode 100644
index d719f44..0000000
--- a/legacyworlds-server-beans-updates/pom.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-	<modelVersion>4.0.0</modelVersion>
-
-	<parent>
-		<artifactId>legacyworlds-server-beans</artifactId>
-		<groupId>com.deepclone.lw</groupId>
-		<version>1.0.0</version>
-		<relativePath>../legacyworlds-server-beans/pom.xml</relativePath>
-	</parent>
-
-	<artifactId>legacyworlds-server-beans-updates</artifactId>
-	<name>Legacy Worlds - Server - Components - Game updates</name>
-	<version>${legacyworlds.version.main}.${legacyworlds.version.release}-${legacyworlds.version.build}</version>
-	<description>This module contains the components which process the game updates and allow the administration interface to display information about them.</description>
-
-</project>
\ No newline at end of file
diff --git a/legacyworlds-server-beans-updates/src/main/java/.empty b/legacyworlds-server-beans-updates/src/main/java/.empty
deleted file mode 100644
index e69de29..0000000
diff --git a/legacyworlds-server-beans-updates/src/main/java/com/deepclone/lw/beans/updates/GameUpdateProcessorBean.java b/legacyworlds-server-beans-updates/src/main/java/com/deepclone/lw/beans/updates/GameUpdateProcessorBean.java
deleted file mode 100644
index 73da48f..0000000
--- a/legacyworlds-server-beans-updates/src/main/java/com/deepclone/lw/beans/updates/GameUpdateProcessorBean.java
+++ /dev/null
@@ -1,238 +0,0 @@
-package com.deepclone.lw.beans.updates;
-
-
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.transaction.PlatformTransactionManager;
-import org.springframework.transaction.support.TransactionTemplate;
-
-import com.deepclone.lw.cmd.admin.logs.LogLevel;
-import com.deepclone.lw.interfaces.eventlog.Logger;
-import com.deepclone.lw.interfaces.eventlog.SystemLogger;
-import com.deepclone.lw.interfaces.game.updates.GameUpdateProcessor;
-import com.deepclone.lw.interfaces.game.updates.UpdatesDAO;
-import com.deepclone.lw.interfaces.sys.MaintenanceStatusException;
-import com.deepclone.lw.interfaces.sys.SystemStatus;
-import com.deepclone.lw.interfaces.sys.TickStatusException;
-
-
-
-/**
- * Game update processor component
- * 
- * <p>
- * This component implements game updates processing. It will update the system status as necessary,
- * checking for maintenance mode, and of course implement the necessary operations for game updates.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-class GameUpdateProcessorBean
-		implements GameUpdateProcessor
-{
-	/** System state management component */
-	private SystemStatus systemStatus;
-
-	/** Logger used by this component */
-	private SystemLogger logger;
-
-	/** Transaction template used to run update batches */
-	private TransactionTemplate tTemplate;
-
-	/** Update processing database interface */
-	private UpdatesDAO updatesDao;
-
-	/** Server-level update processors registry */
-	private ServerProcessorRegistry registry;
-
-	/** Game update processor lock */
-	private boolean executing;
-
-
-	/**
-	 * Dependency injector that sets the sytstem state management component
-	 * 
-	 * @param systemStatus
-	 *            the sytstem state management component
-	 */
-	@Autowired( required = true )
-	public void setSystemStatus( SystemStatus systemStatus )
-	{
-		this.systemStatus = systemStatus;
-	}
-
-
-	/**
-	 * Dependency injector that initialises the logger from the logging component
-	 * 
-	 * @param logger
-	 *            the logging component
-	 */
-	@Autowired( required = true )
-	public void setLogger( Logger logger )
-	{
-		this.logger = logger.getSystemLogger( "GameUpdate" );
-	}
-
-
-	/**
-	 * Dependency injector that initialises the transaction template from the transaction manager
-	 * 
-	 * @param transactionManager
-	 *            the transaction manager
-	 */
-	@Autowired( required = true )
-	public void setTransactionManager( PlatformTransactionManager transactionManager )
-	{
-		this.tTemplate = new TransactionTemplate( transactionManager );
-	}
-
-
-	/**
-	 * Dependency injector that sets the database access component for game updates
-	 * 
-	 * @param updatesDao
-	 *            the database access component for game updates
-	 */
-	@Autowired( required = true )
-	public void setUpdatesDAO( UpdatesDAO updatesDao )
-	{
-		this.updatesDao = updatesDao;
-	}
-
-
-	/**
-	 * Dependency injector that sets the processor registry
-	 * 
-	 * @param registry
-	 *            the processor registry
-	 */
-	@Autowired( required = true )
-	public void setRegistry( ServerProcessorRegistry registry )
-	{
-		this.registry = registry;
-	}
-
-
-	/**
-	 * Try and lock the processor
-	 * 
-	 * <p>
-	 * Test the {@link #executing} field, setting it to <code>true</code> and returning
-	 * <code>true</code> if it wasn't or returning <code>false</code> if it was.
-	 */
-	@Override
-	public synchronized boolean tryLock( )
-	{
-		if ( this.executing ) {
-			return false;
-		}
-		this.executing = true;
-		return true;
-	}
-
-
-	/**
-	 * Unlock the processor
-	 * 
-	 * <p>
-	 * Set {@link #executing} back to <code>false</code>. If it was already set to
-	 * <code>false</code>, throw an {@link IllegalStateException}.
-	 */
-	@Override
-	public synchronized void unlock( )
-			throws IllegalStateException
-	{
-		if ( !this.executing ) {
-			throw new IllegalStateException( "Trying to unlock game update processor, but it isn't locked" );
-		}
-		this.executing = false;
-	}
-
-
-	/**
-	 * Check for an unfinished update cycle and terminate it
-	 * 
-	 * <p>
-	 * Check for a "stuck" update cycle. If there is one, issue a warning and process it through the
-	 * {@link #executeTick(long)} method.
-	 */
-	@Override
-	public boolean endPreviousCycle( )
-	{
-		Long currentTick;
-		try {
-			currentTick = this.systemStatus.checkStuckTick( );
-		} catch ( MaintenanceStatusException e ) {
-			return true;
-		}
-
-		if ( currentTick == null ) {
-			return false;
-		}
-
-		this.logger.log( LogLevel.WARNING , "Tick " + currentTick + " restarted" ).flush( );
-		this.executeTick( currentTick );
-		return true;
-	}
-
-
-	/**
-	 * Execute an update cycle
-	 * 
-	 * <p>
-	 * Start by checking for, and executing if necessary, a "stuck" update cycle. If one is found,
-	 * return. Otherwise, start a new tick through the system state manager, and call
-	 * {@link #executeTick(long)} to process it.
-	 * 
-	 * <p>
-	 * If maintenance mode is active, the new tick will not be started.
-	 */
-	@Override
-	public void executeUpdateCycle( )
-	{
-		// Attempt to end the previous tick, if e.g. maintenance mode was initiated while it was
-		// being processed
-		if ( this.endPreviousCycle( ) ) {
-			return;
-		}
-
-		// Initiate next tick
-		long tickId;
-		try {
-			tickId = this.systemStatus.startTick( );
-		} catch ( TickStatusException e ) {
-			throw new RuntimeException( "tick initiated while previous tick still being processed" , e );
-		} catch ( MaintenanceStatusException e ) {
-			return;
-		}
-
-		// Execute tick
-		this.logger.log( LogLevel.DEBUG , "Tick " + tickId + " started" ).flush( );
-		this.executeTick( tickId );
-	}
-
-
-	/**
-	 * Process all remaining update batches for an update cycle
-	 * 
-	 * <p>
-	 * This method will try and process all update batches using a {@link GameUpdateTransaction}
-	 * instance. It loops until the transaction indicates that no further updates are to be
-	 * processed. However, the loop will exit if maintenance mode becomes active between update
-	 * batches.
-	 * 
-	 * @param tickId
-	 *            the game update cycle's identifier
-	 */
-	private void executeTick( final long tickId )
-	{
-		GameUpdateTransaction transaction = new GameUpdateTransaction( this.updatesDao , this.registry , tickId );
-		while ( !this.tTemplate.execute( transaction ) ) {
-			if ( this.systemStatus.checkMaintenance( ) != null ) {
-				this.logger.log( LogLevel.INFO , "Tick " + tickId + " interrupted by system maintenance" ).flush( );
-				return;
-			}
-		}
-		this.logger.log( LogLevel.TRACE , "Tick " + tickId + " completed" ).flush( );
-	}
-
-}
diff --git a/legacyworlds-server-beans-updates/src/main/java/com/deepclone/lw/beans/updates/GameUpdateTaskBean.java b/legacyworlds-server-beans-updates/src/main/java/com/deepclone/lw/beans/updates/GameUpdateTaskBean.java
deleted file mode 100644
index 6878e1b..0000000
--- a/legacyworlds-server-beans-updates/src/main/java/com/deepclone/lw/beans/updates/GameUpdateTaskBean.java
+++ /dev/null
@@ -1,96 +0,0 @@
-package com.deepclone.lw.beans.updates;
-
-
-import org.springframework.beans.factory.InitializingBean;
-import org.springframework.beans.factory.annotation.Autowired;
-
-import com.deepclone.lw.interfaces.game.updates.GameUpdateProcessor;
-import com.deepclone.lw.interfaces.sys.Ticker;
-import com.deepclone.lw.interfaces.sys.Ticker.Frequency;
-
-
-
-/**
- * Game update ticker task
- * 
- * <p>
- * This component will register itself as a ticker task to be executed once per minute. When it
- * runs, it will try and execute an update cycle.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-class GameUpdateTaskBean
-		implements InitializingBean , Runnable
-{
-	/** The ticker component */
-	private Ticker ticker;
-
-	/** The game updates processor */
-	private GameUpdateProcessor gameUpdateProcessor;
-
-
-	/**
-	 * Dependency injector that sets the ticker component
-	 * 
-	 * @param ticker
-	 *            the ticker component
-	 */
-	@Autowired( required = true )
-	public void setTicker( Ticker ticker )
-	{
-		this.ticker = ticker;
-	}
-
-
-	/**
-	 * Dependency injector that sets the game update processor
-	 * 
-	 * @param gameUpdateProcessor
-	 *            the game update processor
-	 */
-	@Autowired( required = true )
-	public void setGameUpdateProcessor( GameUpdateProcessor gameUpdateProcessor )
-	{
-		this.gameUpdateProcessor = gameUpdateProcessor;
-	}
-
-
-	/**
-	 * Finish a previous update cycle if there is one, then register the component to the ticker
-	 */
-	@Override
-	public void afterPropertiesSet( )
-	{
-		if ( this.gameUpdateProcessor.tryLock( ) ) {
-
-			try {
-				this.gameUpdateProcessor.endPreviousCycle( );
-			} finally {
-				this.gameUpdateProcessor.unlock( );
-			}
-
-		}
-		this.ticker.registerTask( Frequency.MINUTE , "Game update" , this );
-	}
-
-
-	/**
-	 * Run a game update cycle
-	 * 
-	 * <p>
-	 * Try locking the game update processor. On success, execute an update cycle, then unlock the
-	 * processor.
-	 */
-	@Override
-	public void run( )
-	{
-		if ( !this.gameUpdateProcessor.tryLock( ) ) {
-			return;
-		}
-		try {
-			this.gameUpdateProcessor.executeUpdateCycle( );
-		} finally {
-			this.gameUpdateProcessor.unlock( );
-		}
-	}
-}
diff --git a/legacyworlds-server-beans-updates/src/main/java/com/deepclone/lw/beans/updates/GameUpdateTransaction.java b/legacyworlds-server-beans-updates/src/main/java/com/deepclone/lw/beans/updates/GameUpdateTransaction.java
deleted file mode 100644
index b040555..0000000
--- a/legacyworlds-server-beans-updates/src/main/java/com/deepclone/lw/beans/updates/GameUpdateTransaction.java
+++ /dev/null
@@ -1,89 +0,0 @@
-package com.deepclone.lw.beans.updates;
-
-
-import org.springframework.transaction.TransactionStatus;
-import org.springframework.transaction.support.TransactionCallback;
-
-import com.deepclone.lw.interfaces.game.updates.UpdateBatchProcessor;
-import com.deepclone.lw.interfaces.game.updates.UpdatesDAO;
-import com.deepclone.lw.sqld.sys.GameUpdateResult;
-
-
-
-/**
- * Game update transaction
- * 
- * <p>
- * This class is responsible for executing the necessary operations during a game update
- * transaction. It is used by the {@link GameUpdateProcessorBean} component to implement its main
- * processing loop.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-class GameUpdateTransaction
-		implements TransactionCallback< Boolean >
-{
-	/** The game updates database access interface */
-	private final UpdatesDAO updatesDao;
-
-	/** The registry of server-side update batch processors */
-	private final ServerProcessorRegistry registry;
-
-	/** The identifier of the current update cycle */
-	private final long tickId;
-
-
-	/**
-	 * Initialise the various dependencies and set the identifier of the current cycle
-	 * 
-	 * @param updatesDao
-	 *            the game updates database access interface
-	 * @param registry
-	 *            the registry of server-side update batch processors
-	 * @param tickId
-	 *            the identifier of the current update cycle
-	 */
-	GameUpdateTransaction( UpdatesDAO updatesDao , ServerProcessorRegistry registry , long tickId )
-	{
-		this.updatesDao = updatesDao;
-		this.registry = registry;
-		this.tickId = tickId;
-	}
-
-
-	/**
-	 * Update batch processing transaction
-	 * 
-	 * <p>
-	 * Call the database's game update processing function, returning immediately if the function
-	 * indicates that the cycle has been completed. Otherwise, execute a server-side processor if
-	 * necessary.
-	 * 
-	 * <p>
-	 * If the database requests server-side processing but no processor is found, an
-	 * {@link UnsupportedUpdateException} will be thrown.
-	 * 
-	 * @return <code>true</code> if the current update cycle has been completed, <code>false</code>
-	 *         if more updates are needed.
-	 */
-	@Override
-	public Boolean doInTransaction( TransactionStatus status )
-	{
-		GameUpdateResult result = this.updatesDao.processUpdates( this.tickId );
-		String local = result.getLocalExecution( );
-		if ( result.isFinished( ) ) {
-			return true;
-		} else if ( local == null ) {
-			return false;
-		}
-
-		UpdateBatchProcessor processor = this.registry.getProcessorFor( local );
-		if ( processor == null ) {
-			throw new UnsupportedUpdateException( local );
-		}
-
-		processor.processBatch( this.tickId );
-		return false;
-	}
-
-}
diff --git a/legacyworlds-server-beans-updates/src/main/java/com/deepclone/lw/beans/updates/ServerProcessorRegistry.java b/legacyworlds-server-beans-updates/src/main/java/com/deepclone/lw/beans/updates/ServerProcessorRegistry.java
deleted file mode 100644
index 423c7cc..0000000
--- a/legacyworlds-server-beans-updates/src/main/java/com/deepclone/lw/beans/updates/ServerProcessorRegistry.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package com.deepclone.lw.beans.updates;
-
-
-import com.deepclone.lw.interfaces.game.updates.UpdateBatchProcessor;
-
-
-
-/**
- * Server-side update processor registry
- * 
- * <p>
- * This interface allows server-side game update batch processors to be looked up depending on the
- * type of the updates to process.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- * 
- */
-interface ServerProcessorRegistry
-{
-
-	/**
-	 * Get a batch processor for some type of update
-	 * 
-	 * @param type
-	 *            the type of updates to process, as stored in the <code>sys.update_types</code>
-	 *            database table
-	 * 
-	 * @return <code>null</code> if no processor for the specified type has been registered, or the
-	 *         processor to use.
-	 */
-	public UpdateBatchProcessor getProcessorFor( String type );
-
-}
diff --git a/legacyworlds-server-beans-updates/src/main/java/com/deepclone/lw/beans/updates/ServerProcessorRegistryBean.java b/legacyworlds-server-beans-updates/src/main/java/com/deepclone/lw/beans/updates/ServerProcessorRegistryBean.java
deleted file mode 100644
index 9055ae9..0000000
--- a/legacyworlds-server-beans-updates/src/main/java/com/deepclone/lw/beans/updates/ServerProcessorRegistryBean.java
+++ /dev/null
@@ -1,68 +0,0 @@
-package com.deepclone.lw.beans.updates;
-
-
-import java.util.HashMap;
-import java.util.Map;
-
-import org.springframework.beans.BeansException;
-import org.springframework.beans.factory.BeanInitializationException;
-import org.springframework.beans.factory.config.BeanPostProcessor;
-
-import com.deepclone.lw.interfaces.game.updates.UpdateBatchProcessor;
-
-
-
-/**
- * Server-side update processor registry component
- * 
- * <p>
- * This component will look through registered Spring components for update processors, and use the
- * results as the registry's contents.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-class ServerProcessorRegistryBean
-		implements ServerProcessorRegistry , BeanPostProcessor
-{
-
-	/** Known server-side update batch processors */
-	private final Map< String , UpdateBatchProcessor > processors = new HashMap< String , UpdateBatchProcessor >( );
-
-
-	/** Do nothing - we're not interested in uninitialised components */
-	@Override
-	public Object postProcessBeforeInitialization( Object bean , String beanName )
-	{
-		return bean;
-	}
-
-
-	/**
-	 * If an initialised component implements the {@link UpdateBatchProcessor} interface, add it to
-	 * the {@link #processors} map. A {@link BeanInitializationException} will be thrown if two
-	 * components seem to process the same update type.
-	 */
-	@Override
-	public Object postProcessAfterInitialization( Object bean , String beanName )
-			throws BeansException
-	{
-		if ( bean instanceof UpdateBatchProcessor ) {
-			UpdateBatchProcessor processor = (UpdateBatchProcessor) bean;
-			String updType = processor.getUpdateType( );
-			if ( this.processors.containsKey( updType ) ) {
-				throw new BeanInitializationException( "Duplicate update processor for update type " + updType );
-			}
-			this.processors.put( updType , processor );
-		}
-		return bean;
-	}
-
-
-	/** Obtain the processor from the {@link #processors} map */
-	@Override
-	public UpdateBatchProcessor getProcessorFor( String type )
-	{
-		return this.processors.get( type );
-	}
-
-}
diff --git a/legacyworlds-server-beans-updates/src/main/java/com/deepclone/lw/beans/updates/UnsupportedUpdateException.java b/legacyworlds-server-beans-updates/src/main/java/com/deepclone/lw/beans/updates/UnsupportedUpdateException.java
deleted file mode 100644
index c167bf1..0000000
--- a/legacyworlds-server-beans-updates/src/main/java/com/deepclone/lw/beans/updates/UnsupportedUpdateException.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package com.deepclone.lw.beans.updates;
-
-
-/**
- * Unsupported update exception
- * 
- * <p>
- * This exception is thrown by the {@link GameUpdateTransaction} when there is no server-side
- * processor for some update type.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-@SuppressWarnings( "serial" )
-public class UnsupportedUpdateException
-		extends RuntimeException
-{
-
-	/**
-	 * Initialise the exception
-	 * 
-	 * @param name
-	 *            the name of the update type for which no processor is registered.
-	 */
-	UnsupportedUpdateException( String name )
-	{
-		super( "No processor found for update type " + name );
-	}
-
-}
diff --git a/legacyworlds-server-beans-updates/src/main/java/com/deepclone/lw/beans/updates/UpdatesDAOBean.java b/legacyworlds-server-beans-updates/src/main/java/com/deepclone/lw/beans/updates/UpdatesDAOBean.java
deleted file mode 100644
index 8de9681..0000000
--- a/legacyworlds-server-beans-updates/src/main/java/com/deepclone/lw/beans/updates/UpdatesDAOBean.java
+++ /dev/null
@@ -1,69 +0,0 @@
-package com.deepclone.lw.beans.updates;
-
-
-import java.sql.Types;
-import java.util.Map;
-
-import javax.sql.DataSource;
-
-import org.springframework.beans.factory.annotation.Autowired;
-
-import com.deepclone.lw.interfaces.game.updates.UpdatesDAO;
-import com.deepclone.lw.sqld.sys.GameUpdateResult;
-import com.deepclone.lw.utils.StoredProc;
-
-
-
-/**
- * Updates data access component
- * 
- * <p>
- * This component accesses the database procedures and views which constitute the game update
- * system.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-class UpdatesDAOBean
-		implements UpdatesDAO
-{
-
-	/** Game update processor stored procedure */
-	private StoredProc process;
-
-
-	/**
-	 * Dependency injector for the data source
-	 * 
-	 * <p>
-	 * When Spring injects the data source component, initialise the stored procedures used by the
-	 * component.
-	 * 
-	 * @param dataSource
-	 *            the data source component
-	 */
-	@Autowired( required = true )
-	public void setDataSource( DataSource dataSource )
-	{
-		this.process = new StoredProc( dataSource , "sys" , "process_updates" ).addParameter( "tick_id" , Types.BIGINT )
-				.addOutput( "_has_more" , Types.BOOLEAN ).addOutput( "_process_externally" , Types.VARCHAR );
-	}
-
-
-	/**
-	 * Execute the processor's stored procedure
-	 * 
-	 * <p>
-	 * This implementation simply runs the database's <code>sys.process_updates()</code> stored
-	 * procedure, and converts the two values it returns into a {@link GameUpdateResult} instance.
-	 */
-	@Override
-	public GameUpdateResult processUpdates( long tickId )
-	{
-		Map< String , Object > m = this.process.execute( tickId );
-		if ( !(Boolean) m.get( "_has_more" ) ) {
-			return new GameUpdateResult( );
-		}
-		return new GameUpdateResult( (String) m.get( "_process_externally" ) );
-	}
-
-}
diff --git a/legacyworlds-server-beans-updates/src/main/resources/.empty b/legacyworlds-server-beans-updates/src/main/resources/.empty
deleted file mode 100644
index e69de29..0000000
diff --git a/legacyworlds-server-beans-updates/src/main/resources/configuration/game/updates.xml b/legacyworlds-server-beans-updates/src/main/resources/configuration/game/updates.xml
deleted file mode 100644
index b957642..0000000
--- a/legacyworlds-server-beans-updates/src/main/resources/configuration/game/updates.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<beans xmlns="http://www.springframework.org/schema/beans"
-	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	xsi:schemaLocation="
-                        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
-
-	<bean id="gameUpdateDAO" class="com.deepclone.lw.beans.updates.UpdatesDAOBean" />
-	<bean id="gameUpdateProcessor" class="com.deepclone.lw.beans.updates.GameUpdateProcessorBean" />
-	<bean id="gameUpdateRegistry"
-		class="com.deepclone.lw.beans.updates.ServerProcessorRegistryBean" />
-	<bean id="gameUpdateTask" class="com.deepclone.lw.beans.updates.GameUpdateTaskBean" />
-
-</beans>
diff --git a/legacyworlds-server-beans-updates/src/test/java/.empty b/legacyworlds-server-beans-updates/src/test/java/.empty
deleted file mode 100644
index e69de29..0000000
diff --git a/legacyworlds-server-beans-updates/src/test/resources/.empty b/legacyworlds-server-beans-updates/src/test/resources/.empty
deleted file mode 100644
index e69de29..0000000
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/UpdateEmpireMiningSettingsCommandDelegateBean.java b/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/UpdateEmpireMiningSettingsCommandDelegateBean.java
deleted file mode 100644
index ea0b021..0000000
--- a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/UpdateEmpireMiningSettingsCommandDelegateBean.java
+++ /dev/null
@@ -1,74 +0,0 @@
-package com.deepclone.lw.beans.user.player.game;
-
-
-import org.springframework.beans.factory.annotation.Autowired;
-
-import com.deepclone.lw.beans.user.abst.AutowiredCommandDelegate;
-import com.deepclone.lw.beans.user.abst.SessionCommandHandler;
-import com.deepclone.lw.beans.user.player.GameSubTypeBean;
-import com.deepclone.lw.cmd.player.UpdateEmpireMiningSettingsCommand;
-import com.deepclone.lw.interfaces.game.resources.ResourcesController;
-import com.deepclone.lw.interfaces.session.ServerSession;
-import com.deepclone.lw.session.Command;
-import com.deepclone.lw.session.CommandResponse;
-import com.deepclone.lw.session.NullResponse;
-
-
-
-/**
- * Command handler for empire mining settings updates
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-class UpdateEmpireMiningSettingsCommandDelegateBean
-		implements AutowiredCommandDelegate
-{
-
-	/** The resources controller */
-	private ResourcesController resourcesController;
-
-
-	/**
-	 * Dependency injector that sets the resources controller
-	 * 
-	 * @param resourcesController
-	 *            the resources controller
-	 */
-	@Autowired( required = true )
-	public void setResourcesController( ResourcesController resourcesController )
-	{
-		this.resourcesController = resourcesController;
-	}
-
-
-	/** This class handles {@link UpdateEmpireMiningSettingsCommand} instances */
-	@Override
-	public Class< ? extends Command > getType( )
-	{
-		return UpdateEmpireMiningSettingsCommand.class;
-	}
-
-
-	/** This class is enabled for the {@link GameSubTypeBean} session type */
-	@Override
-	public Class< ? extends SessionCommandHandler > getCommandHandler( )
-	{
-		return GameSubTypeBean.class;
-	}
-
-
-	/**
-	 * If the account is not in vacation mode, update mining settings. Always return a
-	 * {@link NullResponse}.
-	 */
-	@Override
-	public CommandResponse execute( ServerSession session , Command command )
-	{
-		if ( !session.get( "vacation" , Boolean.class ) ) {
-			int empireId = session.get( "empireId" , Integer.class );
-			this.resourcesController.updateEmpireSettings( empireId ,
-					( (UpdateEmpireMiningSettingsCommand) command ).getSettings( ) );
-		}
-		return new NullResponse( );
-	}
-}
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/planets/ToggleMiningSettingsCommandDelegateBean.java b/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/planets/ToggleMiningSettingsCommandDelegateBean.java
deleted file mode 100644
index f4a951a..0000000
--- a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/planets/ToggleMiningSettingsCommandDelegateBean.java
+++ /dev/null
@@ -1,73 +0,0 @@
-package com.deepclone.lw.beans.user.player.game.planets;
-
-
-import org.springframework.beans.factory.annotation.Autowired;
-
-import com.deepclone.lw.beans.user.abst.AutowiredCommandDelegate;
-import com.deepclone.lw.beans.user.abst.SessionCommandHandler;
-import com.deepclone.lw.beans.user.player.GameSubTypeBean;
-import com.deepclone.lw.cmd.player.planets.ToggleMiningSettingsCommand;
-import com.deepclone.lw.cmd.player.planets.ViewPlanetCommand;
-import com.deepclone.lw.interfaces.game.resources.ResourcesController;
-import com.deepclone.lw.interfaces.session.ServerSession;
-import com.deepclone.lw.session.Command;
-import com.deepclone.lw.session.CommandResponse;
-import com.deepclone.lw.session.NullResponse;
-
-
-
-/**
- * Command handler for {@link ToggleMiningSettingsCommand}
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-class ToggleMiningSettingsCommandDelegateBean
-		implements AutowiredCommandDelegate
-{
-
-	/** The resources controller */
-	private ResourcesController resourcesController;
-
-
-	/**
-	 * Dependency injector that sets the resources controller
-	 * 
-	 * @param resourcesController
-	 *            the resources controller
-	 */
-	@Autowired( required = true )
-	public void setResourcesController( ResourcesController resourcesController )
-	{
-		this.resourcesController = resourcesController;
-	}
-
-
-	/** This class handles {@link ToggleMiningSettingsCommand} instances */
-	@Override
-	public Class< ? extends Command > getType( )
-	{
-		return ToggleMiningSettingsCommand.class;
-	}
-
-
-	/** This class is enabled for the {@link GameSubTypeBean} session type */
-	@Override
-	public Class< ? extends SessionCommandHandler > getCommandHandler( )
-	{
-		return GameSubTypeBean.class;
-	}
-
-
-	/** If the account is not in vacation mode, try to toggle the planet's settings */
-	@Override
-	public CommandResponse execute( ServerSession session , Command command )
-	{
-		if ( !session.get( "vacation" , Boolean.class ) ) {
-			int empireId = session.get( "empireId" , Integer.class );
-			ViewPlanetCommand planet = (ViewPlanetCommand) command;
-			this.resourcesController.togglePlanet( empireId , planet.getId( ) );
-		}
-		return new NullResponse( );
-	}
-
-}
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/planets/UpdatePlanetMiningSettingsCommandDelegateBean.java b/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/planets/UpdatePlanetMiningSettingsCommandDelegateBean.java
deleted file mode 100644
index 1a7d954..0000000
--- a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/planets/UpdatePlanetMiningSettingsCommandDelegateBean.java
+++ /dev/null
@@ -1,72 +0,0 @@
-package com.deepclone.lw.beans.user.player.game.planets;
-
-
-import org.springframework.beans.factory.annotation.Autowired;
-
-import com.deepclone.lw.beans.user.abst.AutowiredCommandDelegate;
-import com.deepclone.lw.beans.user.abst.SessionCommandHandler;
-import com.deepclone.lw.beans.user.player.GameSubTypeBean;
-import com.deepclone.lw.cmd.player.planets.UpdatePlanetMiningSettingsCommand;
-import com.deepclone.lw.interfaces.game.resources.ResourcesController;
-import com.deepclone.lw.interfaces.session.ServerSession;
-import com.deepclone.lw.session.Command;
-import com.deepclone.lw.session.CommandResponse;
-import com.deepclone.lw.session.NullResponse;
-
-
-
-/**
- * Command handler for {@link UpdatePlanetMiningSettingsCommand}
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-class UpdatePlanetMiningSettingsCommandDelegateBean
-		implements AutowiredCommandDelegate
-{
-
-	/** The resources controller */
-	private ResourcesController resourcesController;
-
-
-	/**
-	 * Dependency injector that sets the resources controller
-	 * 
-	 * @param resourcesController
-	 *            the resources controller
-	 */
-	@Autowired( required = true )
-	public void setResourcesController( ResourcesController resourcesController )
-	{
-		this.resourcesController = resourcesController;
-	}
-
-
-	/** This class handles {@link UpdatePlanetMiningSettingsCommand} instances */
-	@Override
-	public Class< ? extends Command > getType( )
-	{
-		return UpdatePlanetMiningSettingsCommand.class;
-	}
-
-
-	/** This class is enabled for the {@link GameSubTypeBean} session type */
-	@Override
-	public Class< ? extends SessionCommandHandler > getCommandHandler( )
-	{
-		return GameSubTypeBean.class;
-	}
-
-
-	/** If the empire is not in vacation mode, try updating the planet's mining priorities */
-	@Override
-	public CommandResponse execute( ServerSession session , Command command )
-	{
-		if ( !session.get( "vacation" , Boolean.class ) ) {
-			UpdatePlanetMiningSettingsCommand settings = (UpdatePlanetMiningSettingsCommand) command;
-			int empireId = session.get( "empireId" , Integer.class );
-			this.resourcesController.updatePlanetSettings( empireId , settings.getId( ) , settings.getSettings( ) );
-		}
-		return new NullResponse( );
-	}
-
-}
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/tech/GetResearchCommandDelegateBean.java b/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/tech/GetResearchCommandDelegateBean.java
deleted file mode 100644
index 8735745..0000000
--- a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/tech/GetResearchCommandDelegateBean.java
+++ /dev/null
@@ -1,70 +0,0 @@
-package com.deepclone.lw.beans.user.player.game.tech;
-
-
-import org.springframework.beans.factory.annotation.Autowired;
-
-import com.deepclone.lw.beans.user.abst.AutowiredCommandDelegate;
-import com.deepclone.lw.beans.user.abst.SessionCommandHandler;
-import com.deepclone.lw.beans.user.player.GameSubTypeBean;
-import com.deepclone.lw.cmd.player.tech.GetResearchCommand;
-import com.deepclone.lw.interfaces.game.technologies.ResearchController;
-import com.deepclone.lw.interfaces.session.ServerSession;
-import com.deepclone.lw.session.Command;
-import com.deepclone.lw.session.CommandResponse;
-
-
-
-/**
- * Command delegate for {@link GetResearchCommand}
- * 
- * <p>
- * This command delegate uses the {@link ResearchController} to obtain all information pertaining to
- * an empire's research.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-class GetResearchCommandDelegateBean
-		implements AutowiredCommandDelegate
-{
-	/** The research controller */
-	private ResearchController researchController;
-
-
-	/**
-	 * Dependency injector that sets the research controller
-	 * 
-	 * @param researchController
-	 *            the research controller
-	 */
-	@Autowired
-	public void setResearchController( ResearchController researchController )
-	{
-		this.researchController = researchController;
-	}
-
-
-	/** This delegate handles {@link GetResearchCommand} instances */
-	@Override
-	public Class< ? extends Command > getType( )
-	{
-		return GetResearchCommand.class;
-	}
-
-
-	/** This delegate is part of the game session sub-type */
-	@Override
-	public Class< ? extends SessionCommandHandler > getCommandHandler( )
-	{
-		return GameSubTypeBean.class;
-	}
-
-
-	/** When the command is executed, fetch relevant data from the research controller */
-	@Override
-	public CommandResponse execute( ServerSession session , Command command )
-	{
-		int empire = session.get( "empireId" , Integer.class );
-		return this.researchController.getResearchData( empire );
-	}
-
-}
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/tech/ImplementTechCommandDelegateBean.java b/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/tech/ImplementTechCommandDelegateBean.java
deleted file mode 100644
index 5b13636..0000000
--- a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/tech/ImplementTechCommandDelegateBean.java
+++ /dev/null
@@ -1,72 +0,0 @@
-package com.deepclone.lw.beans.user.player.game.tech;
-
-
-import org.springframework.beans.factory.annotation.Autowired;
-
-import com.deepclone.lw.beans.user.abst.AutowiredCommandDelegate;
-import com.deepclone.lw.beans.user.abst.SessionCommandHandler;
-import com.deepclone.lw.beans.user.player.GameSubTypeBean;
-import com.deepclone.lw.cmd.player.tech.ImplementTechCommand;
-import com.deepclone.lw.interfaces.game.technologies.ResearchController;
-import com.deepclone.lw.interfaces.session.ServerSession;
-import com.deepclone.lw.session.Command;
-import com.deepclone.lw.session.CommandResponse;
-import com.deepclone.lw.session.NullResponse;
-
-
-
-public class ImplementTechCommandDelegateBean
-		implements AutowiredCommandDelegate
-
-{
-	/** The research controller */
-	private ResearchController researchController;
-
-
-	/**
-	 * Dependency injector that sets the research controller
-	 * 
-	 * @param researchController
-	 *            the research controller
-	 */
-	@Autowired( required = true )
-	public void setResearchController( ResearchController researchController )
-	{
-		this.researchController = researchController;
-	}
-
-
-	/** This class handles {@link ImplementTechCommand} instances */
-	@Override
-	public Class< ? extends Command > getType( )
-	{
-		return ImplementTechCommand.class;
-	}
-
-
-	/** This class is enabled for the {@link GameSubTypeBean} session type */
-	@Override
-	public Class< ? extends SessionCommandHandler > getCommandHandler( )
-	{
-		return GameSubTypeBean.class;
-	}
-
-
-	/**
-	 * Implement a technology
-	 * 
-	 * <p>
-	 * If the empire is not in vacation mode, try to implement the technology. Always return a
-	 * {@link NullResponse}.
-	 */
-	@Override
-	public CommandResponse execute( ServerSession session , Command cParam )
-	{
-		ImplementTechCommand command = (ImplementTechCommand) cParam;
-		int empire = session.get( "empireId" , Integer.class );
-		if ( !session.get( "vacation" , Boolean.class ) ) {
-			this.researchController.implement( empire , command.getTech( ) );
-		}
-		return new NullResponse( );
-	}
-}
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/tech/UpdateResearchPrioritiesCommandDelegateBean.java b/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/tech/UpdateResearchPrioritiesCommandDelegateBean.java
deleted file mode 100644
index c3dc103..0000000
--- a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/tech/UpdateResearchPrioritiesCommandDelegateBean.java
+++ /dev/null
@@ -1,77 +0,0 @@
-package com.deepclone.lw.beans.user.player.game.tech;
-
-
-import org.springframework.beans.factory.annotation.Autowired;
-
-import com.deepclone.lw.beans.user.abst.AutowiredCommandDelegate;
-import com.deepclone.lw.beans.user.abst.SessionCommandHandler;
-import com.deepclone.lw.beans.user.player.GameSubTypeBean;
-import com.deepclone.lw.cmd.player.tech.UpdateResearchPrioritiesCommand;
-import com.deepclone.lw.interfaces.game.technologies.ResearchController;
-import com.deepclone.lw.interfaces.session.ServerSession;
-import com.deepclone.lw.session.Command;
-import com.deepclone.lw.session.CommandResponse;
-import com.deepclone.lw.session.NullResponse;
-
-
-
-/**
- * Command handler for research priority updates
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-class UpdateResearchPrioritiesCommandDelegateBean
-		implements AutowiredCommandDelegate
-{
-	/** The research controller */
-	private ResearchController researchController;
-
-
-	/**
-	 * Dependency injector that sets the research controller
-	 * 
-	 * @param researchController
-	 *            the research controller
-	 */
-	@Autowired( required = true )
-	public void setResearchController( ResearchController researchController )
-	{
-		this.researchController = researchController;
-	}
-
-
-	/** This class handles {@link UpdateResearchPrioritiesCommand} instances */
-	@Override
-	public Class< ? extends Command > getType( )
-	{
-		return UpdateResearchPrioritiesCommand.class;
-	}
-
-
-	/** This class is enabled for the {@link GameSubTypeBean} session type */
-	@Override
-	public Class< ? extends SessionCommandHandler > getCommandHandler( )
-	{
-		return GameSubTypeBean.class;
-	}
-
-
-	/**
-	 * Update research priorities
-	 * 
-	 * <p>
-	 * If the empire is not in vacation mode, access the research controller and update mining
-	 * priorities using the specified values. Return a {@link NullResponse} in all cases.
-	 */
-	@Override
-	public CommandResponse execute( ServerSession session , Command command )
-	{
-		if ( !session.get( "vacation" , Boolean.class ) ) {
-			int empireId = session.get( "empireId" , Integer.class );
-			this.researchController.updatePriorities( empireId ,
-					( (UpdateResearchPrioritiesCommand) command ).getPriorities( ) );
-		}
-		return new NullResponse( );
-	}
-
-}
diff --git a/legacyworlds-server-beans-user/src/test/java/.empty b/legacyworlds-server-beans-user/src/test/java/.empty
deleted file mode 100644
index e69de29..0000000
diff --git a/legacyworlds-server-beans-user/src/test/resources/.empty b/legacyworlds-server-beans-user/src/test/resources/.empty
deleted file mode 100644
index e69de29..0000000
diff --git a/legacyworlds-server-beans/pom.xml b/legacyworlds-server-beans/pom.xml
deleted file mode 100644
index 59c6c30..0000000
--- a/legacyworlds-server-beans/pom.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-	<modelVersion>4.0.0</modelVersion>
-	<parent>
-		<artifactId>legacyworlds-server</artifactId>
-		<groupId>com.deepclone.lw</groupId>
-		<version>1.0.0</version>
-		<relativePath>../legacyworlds-server/pom.xml</relativePath>
-	</parent>
-
-	<artifactId>legacyworlds-server-beans</artifactId>
-	<name>Legacy Worlds - Server - Components</name>
-	<packaging>pom</packaging>
-	<description>This metapackage regroups all packages which define beans for the Legacy Worlds server.</description>
-
-	<dependencies>
-		<dependency>
-			<groupId>com.deepclone.lw</groupId>
-			<artifactId>legacyworlds-server-interfaces</artifactId>
-		</dependency>
-	</dependencies>
-
-	<modules>
-		<module>../legacyworlds-server-beans-accounts</module>
-		<module>../legacyworlds-server-beans-bt</module>
-		<module>../legacyworlds-server-beans-eventlog</module>
-		<module>../legacyworlds-server-beans-events</module>
-		<module>../legacyworlds-server-beans-i18n</module>
-		<module>../legacyworlds-server-beans-mailer</module>
-		<module>../legacyworlds-server-beans-naming</module>
-		<module>../legacyworlds-server-beans-resources</module>
-		<module>../legacyworlds-server-beans-simple</module>
-		<module>../legacyworlds-server-beans-system</module>
-		<module>../legacyworlds-server-beans-technologies</module>
-		<module>../legacyworlds-server-beans-updates</module>
-		<module>../legacyworlds-server-beans-user</module>
-	</modules>
-</project>
diff --git a/legacyworlds-server-data/db-structure/parts/020-extensions.sql b/legacyworlds-server-data/db-structure/parts/020-extensions.sql
deleted file mode 100644
index 50db2a8..0000000
--- a/legacyworlds-server-data/db-structure/parts/020-extensions.sql
+++ /dev/null
@@ -1,35 +0,0 @@
--- LegacyWorlds Beta 6
--- PostgreSQL database scripts
---
--- Load and configure required PostgreSQL extensions
---
--- Copyright(C) 2004-2012, DeepClone Development
--- --------------------------------------------------------
-
-/* Register the dblink extension */
-CREATE EXTENSION dblink;
-
-/* Create foreign data wrapper and server used to write logs from within
- * transanctions
- */
-CREATE FOREIGN DATA WRAPPER pgsql
-	VALIDATOR postgresql_fdw_validator;
-
-CREATE SERVER srv_logging
-	FOREIGN DATA WRAPPER pgsql
-	OPTIONS ( hostaddr '127.0.0.1' , dbname :dbname_string );
-
-CREATE USER MAPPING FOR :pgadmin
-	SERVER srv_logging
-	OPTIONS ( user :dbuser_string , password :dbupass );
-
-CREATE USER MAPPING FOR :dbuser
-	SERVER srv_logging
-	OPTIONS ( user :dbuser_string , password :dbupass );
-
-GRANT USAGE ON FOREIGN SERVER srv_logging TO :dbuser;
-
-/* The events sytem uses the hash store extension to convert events from the
- * queues to main storage.
- */
-CREATE EXTENSION hstore;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/parts/030-data/075-resources.sql b/legacyworlds-server-data/db-structure/parts/030-data/075-resources.sql
deleted file mode 100644
index 70f1347..0000000
--- a/legacyworlds-server-data/db-structure/parts/030-data/075-resources.sql
+++ /dev/null
@@ -1,121 +0,0 @@
--- LegacyWorlds Beta 6
--- PostgreSQL database scripts
---
--- Resource definitions
---
--- Copyright(C) 2004-2011, DeepClone Development
--- --------------------------------------------------------
-
-
-/*
- * Common resource definitions
- * ----------------------------
- * 
- * The defs.resources table is used to describe the part of a resource's
- * definition that's idependant 
- */
-
-CREATE TABLE defs.resources(
-	/* The resource identifier is a reference to an I18N string that
-	 * represents the resource's name. It also serves as the table's
-	 * primary key.
-	 */
-	resource_name_id			INT NOT NULL PRIMARY KEY ,
-
-	/* Identifier of an I18N string which serves as the resource's
-	 * description. 
-	 */
-	resource_description_id		INT NOT NULL ,
-
-	/* Identifier of an I18N string that names the resource's category. This
-	 * field may be NULL for resources that do not belong to a category. 
-	 */
-	resource_category_id		INT ,
-
-	/* The weight is used when sorting resources. For resources that do not
-	 * have a category, it is used directly. Otherwise, categories themselves
-	 * are sorted by average weight of their contents, and resources in
-	 * categories are sorted by weight.
-	 */
-	resource_weight				INT NOT NULL
-									CHECK ( resource_weight > 0 )
-);
-
-CREATE UNIQUE INDEX idx_resources_description
-	ON defs.resources( resource_description_id );
-CREATE INDEX idx_resources_category
-	ON defs.resources( resource_category_id );
-CREATE INDEX idx_resources_weight
-	ON defs.resources( resource_weight );
-
-ALTER TABLE defs.resources
-	ADD CONSTRAINT fk_resources_name
-		FOREIGN KEY ( resource_name_id ) REFERENCES defs.strings ,
-	ADD CONSTRAINT fk_resources_description
-		FOREIGN KEY ( resource_description_id ) REFERENCES defs.strings ,
-	ADD CONSTRAINT fk_resources_category
-		FOREIGN KEY ( resource_category_id ) REFERENCES defs.strings;
-
-
-
-/*
- * Natural resources
- * ------------------
- * 
- * This table contains additional resource information that is used for
- * natural resources only. These fields are used by the universe generator
- * when it creates resource providers. 
- */
-CREATE TABLE defs.natural_resources (
-	/* Identifier of the resource definition for this natural resource, which
-	 * also serves as the primary key for this table.
-	 */
-	resource_name_id			INT NOT NULL PRIMARY KEY ,
-
-	/* Presence probability, used by the universe generator to determine
-	 * whether some type of resource should be added to a planet or not. The
-	 * generator will try to enforce this probability on the universe in
-	 * general (that is, not assigning the resource to a planet will increase
-	 * the probability of it being assigned to another).
-	 */
-	natres_p_presence		DOUBLE PRECISION NOT NULL
-								CHECK ( natres_p_presence > 0
-									AND natres_p_presence < 1 ) ,
-
-	/* Average quantity in resource providers. */
-	natres_quantity_avg		DOUBLE PRECISION NOT NULL
-								CHECK( natres_quantity_avg > 0 ) ,
-	/* Maximal deviation from the average quantity. */
-	natres_quantity_dev		DOUBLE PRECISION NOT NULL
-								CHECK( natres_quantity_dev >= 0 ) ,
-
-	/* Average extraction difficulty assigned to resource providers */
-	natres_difficulty_avg	DOUBLE PRECISION NOT NULL
-								CHECK( natres_difficulty_avg BETWEEN 0 AND 1 ) ,
-	/* Maximal deviation from the average extraction difficulty */
-	natres_difficulty_dev	DOUBLE PRECISION NOT NULL
-								CHECK( natres_difficulty_dev >= 0 ) ,
-
-	/* Average recovery rate for resource providers */
-	natres_recovery_avg		DOUBLE PRECISION NOT NULL
-								CHECK( natres_recovery_avg > 0
-									AND natres_recovery_avg <= 1 ) ,
-	/* Maximal deviation from the average recovery rate */
-	natres_recovery_dev		DOUBLE PRECISION NOT NULL
-								CHECK( natres_recovery_dev >= 0 ) ,
-	
-	/*
-	 * For all values which include both an average and a maximal deviation,
-	 * make sure the range defined by the deviation is still within valid
-	 * boundaries for the value in question.
-	 */
-	CHECK( natres_quantity_avg - natres_quantity_dev > 0 ) ,
-	CHECK( natres_difficulty_avg + natres_difficulty_dev <= 1 ) ,
-	CHECK( natres_difficulty_avg - natres_difficulty_dev >= 0 ) ,
-	CHECK( natres_recovery_avg + natres_recovery_dev <= 1 ) ,
-	CHECK( natres_recovery_avg - natres_recovery_dev > 0 )
-);
-
-ALTER TABLE defs.natural_resources
-	ADD CONSTRAINT fk_natres_resource
-		FOREIGN KEY ( resource_name_id ) REFERENCES defs.resources;
diff --git a/legacyworlds-server-data/db-structure/parts/030-data/080-techs.sql b/legacyworlds-server-data/db-structure/parts/030-data/080-techs.sql
deleted file mode 100644
index 2c77522..0000000
--- a/legacyworlds-server-data/db-structure/parts/030-data/080-techs.sql
+++ /dev/null
@@ -1,163 +0,0 @@
--- LegacyWorlds Beta 6
--- PostgreSQL database scripts
---
--- Technology definitions
---
--- Copyright(C) 2004-2012, DeepClone Development
--- --------------------------------------------------------
-
-
-/*
- * Technology definitions
- * -----------------------
- * 
- * This table contains all defined technologies. It includes references to
- * the various I18N strings used to describe the technology, as well as its
- * cost in research points.
- * 
- * FIXME: for now it also includes the monetary cost, but that will go away
- *		when the full resource system is completed.
- */
-CREATE TABLE defs.technologies(
-	/* Name of the technology (I18N string) */
-	technology_name_id			INT NOT NULL PRIMARY KEY ,
-
-	/* Category of the technology (I18N string) */
-	technology_category_id		INT NOT NULL ,
-
-	/* Text to display when the technology is discovered (I18N string) */
-	technology_discovery_id		INT NOT NULL ,
-	
-	/* A more "factual" description of the technology (I18N string) */
-	technology_description_id	INT NOT NULL ,
-	
-	/* Monetary price of the technology - FIXME: will be removed later */
-	technology_price			BIGINT NOT NULL
-									CHECK( technology_price > 0 ) ,
-
-	/* Cost of the technology in terms of research points */
-	technology_points			BIGINT NOT NULL
-									CHECK( technology_points > 0 )
-);
-
-CREATE INDEX idx_techs_category
-	ON defs.technologies( technology_category_id );
-CREATE UNIQUE INDEX idx_techs_discovery
-	ON defs.technologies( technology_discovery_id );
-CREATE UNIQUE INDEX idx_techs_description
-	ON defs.technologies( technology_description_id );
-
-ALTER TABLE defs.technologies
-	ADD CONSTRAINT fk_techs_name
-		FOREIGN KEY ( technology_name_id ) REFERENCES defs.strings ,
-	ADD CONSTRAINT fk_techs_category
-		FOREIGN KEY ( technology_category_id ) REFERENCES defs.strings ,
-	ADD CONSTRAINT fk_techs_discovery
-		FOREIGN KEY ( technology_discovery_id ) REFERENCES defs.strings ,
-	ADD CONSTRAINT fk_techs_description
-		FOREIGN KEY ( technology_description_id ) REFERENCES defs.strings;
-
-
-
-/*
- * Technology dependencies
- * ------------------------
- *
- * This table list dependencies between technologies. It stores pairs of
- * dependent / dependency references.
- */
-CREATE TABLE defs.technology_dependencies(
-	/* Identifier of the dependency itself. Makes integrity checks easier */
-	techdep_id					SERIAL NOT NULL PRIMARY KEY ,
-	
-	/* Identifier of the dependent technology */
-	technology_name_id			INT NOT NULL ,
-
-	/* Identifier of the technology being depended on */
-	technology_name_id_depends	INT NOT NULL
-);
-
-CREATE UNIQUE INDEX idx_techdeps_techs
-	ON defs.technology_dependencies( technology_name_id , technology_name_id_depends );
-CREATE INDEX idx_techdeps_dependency
-	ON defs.technology_dependencies( technology_name_id_depends );
-
-ALTER TABLE defs.technology_dependencies
-	ADD CONSTRAINT fk_techdeps_dependent
-		FOREIGN KEY ( technology_name_id ) REFERENCES defs.technologies ,
-	ADD CONSTRAINT fk_techdeps_dependency
-		FOREIGN KEY ( technology_name_id_depends ) REFERENCES defs.technologies;
-
-
-/*
- * Technology dependencies graph cache
- * ------------------------------------
- *
- * This table is a cache of all dependency relationships between technologies.
- * It serves two purposes. First, it allows dependencies to be checked to
- * maintain the graph's integrity. Second, it allows all dependencies or
- * reverse dependencies of a technology to be looked up in one single SELECT
- * statement.
- *
- * It works by maintaining, for each node of the graph, a set of trees which
- * correspond to the dependencies or reverse dependencies. Each part of a
- * tree that is not determined solely by the dependency itself is a copy of
- * another tree. Because of that, multiple copies of the same tree may exist
- * in the records for a single technology.
- *
- * Technologies which have no dependencies or reverse dependencies are also
- * present in the table, as it makes things easier when dependencies are added.
- */
-CREATE TABLE defs.techdep_cache(
-	/* Identifier of the technology represented by this node */
-	technology_name_id			INT NOT NULL,
-
-	/* Whether the node is part of a forward or reverse dependencies tree */
-	tdcache_reverse				BOOLEAN NOT NULL ,
-
-	/* Identifier of the cache entry itself */
-	tdcache_id					SERIAL NOT NULL ,
-
-	/* Identifier of the parent cache entry, if any */
-	tdcache_id_parent			INT ,
-
-	/* Depth of the dependency relationship */
-	tdcache_depth				INT NOT NULL ,
-
-	/* Identifier of the technology of the entry this entry is a copy of */
-	technology_name_id_copyof	INT NOT NULL ,
-
-	/* Identifier of the entry this entry is a copy of */
-	tdcache_id_copyof			INT ,
-
-	/* Identifier of the dependency because of which the entry exists, or
-	 * NULL if the entry exists because of a technology definition.
-	 */
-	techdep_id					INT ,
-
-	PRIMARY KEY( technology_name_id , tdcache_reverse , tdcache_id )
-);
-
-CREATE INDEX idx_tdcache_reversetechs
-	ON defs.techdep_cache ( tdcache_reverse , tdcache_id_parent );
-CREATE INDEX idx_tdcache_copyof
-	ON defs.techdep_cache ( technology_name_id_copyof );
-CREATE INDEX idx_tdcache_techdep
-	ON defs.techdep_cache ( techdep_id );
-
-ALTER TABLE defs.techdep_cache
-	ADD CONSTRAINT fk_tdcache_technology
-		FOREIGN KEY ( technology_name_id ) REFERENCES defs.technologies
-			ON DELETE CASCADE ,
-	ADD CONSTRAINT fk_tdcache_techdep
-		FOREIGN KEY ( techdep_id ) REFERENCES defs.technology_dependencies
-			ON DELETE CASCADE ,
-	ADD CONSTRAINT fk_tdcache_copyof
-		FOREIGN KEY( technology_name_id_copyof , tdcache_reverse , tdcache_id_copyof )
-			REFERENCES defs.techdep_cache( technology_name_id , tdcache_reverse , tdcache_id )
-				ON DELETE CASCADE ,
-	ADD CONSTRAINT fk_tdcache_parent
-		FOREIGN KEY( technology_name_id , tdcache_reverse , tdcache_id_parent )
-			REFERENCES defs.techdep_cache( technology_name_id , tdcache_reverse , tdcache_id )
-				ON DELETE CASCADE;
-
diff --git a/legacyworlds-server-data/db-structure/parts/030-data/100-universe.sql b/legacyworlds-server-data/db-structure/parts/030-data/100-universe.sql
deleted file mode 100644
index 2453ded..0000000
--- a/legacyworlds-server-data/db-structure/parts/030-data/100-universe.sql
+++ /dev/null
@@ -1,202 +0,0 @@
--- LegacyWorlds Beta 6
--- PostgreSQL database scripts
---
--- Stellar systems and planets
---
--- Copyright(C) 2004-2010, DeepClone Development
--- --------------------------------------------------------
-
-
---
--- Stellar systems
---
-CREATE TABLE verse.systems(
-	id		SERIAL NOT NULL PRIMARY KEY ,
-	x		INT NOT NULL ,
-	y		INT NOT NULL
-);
-
-CREATE UNIQUE INDEX idx_systems_coordinates
-	ON verse.systems( x , y );
-
---
--- Planets
---
-CREATE TABLE verse.planets(
-	name_id		INT NOT NULL PRIMARY KEY ,
-	system_id	INT NOT NULL ,
-	orbit		INT NOT NULL
-					CHECK( orbit BETWEEN 1 AND 5 ) ,
-	picture		INT NOT NULL ,
-	population	REAL NOT NULL
-					CHECK( population >= 0 )
-);
-
-CREATE UNIQUE INDEX idx_planets_coordinates
-	ON verse.planets( system_id , orbit );
-	
-ALTER TABLE verse.planets
-	ADD CONSTRAINT fk_planets_name
-		FOREIGN KEY (name_id) REFERENCES naming.map_names ,
-	ADD CONSTRAINT fk_planets_system
-		FOREIGN KEY (system_id) REFERENCES verse.systems;
-
-
-
-/*
- * Resource providers
- * -------------------
- * 
- * A resource provider allows natural resources to be extracted. Resource
- * providers are initialised by the universe generator and updated when
- * mining results are computed.
- * 
- * For now, resource providers are bound to planets. Each planet may only
- * have one provider for a given type of natural resource.
- */
-CREATE TABLE verse.resource_providers(
-
-	/* The identifier of the planet the resource provider is bound to. */
-	planet_id				INT NOT NULL ,
-
-	/* The identifier of the natural resource that can be mined from this
-	 * resource provider.
-	 */
-	resource_name_id		INT NOT NULL ,
-
-	/* The maximal quantity of resource units in the provider */ 
-	resprov_quantity_max	DOUBLE PRECISION NOT NULL
-								CHECK( resprov_quantity_max > 0 ) ,
-	/* The current quantity of resources */
-	resprov_quantity		DOUBLE PRECISION NOT NULL
-								CHECK( resprov_quantity >= 0 ) ,
-
-	/* The extraction difficulty, which affects the amount of work required to
-	 * extract resources.
-	 */
-	resprov_difficulty		DOUBLE PRECISION NOT NULL
-								CHECK( resprov_difficulty BETWEEN 0 AND 1 ) ,
-
-	/* The provider's recovery rate, which determines how fast the provider's
-	 * resources are regenerated.
-	 */
-	resprov_recovery		DOUBLE PRECISION NOT NULL
-								CHECK( resprov_recovery > 0
-									AND resprov_recovery <= 1 ) ,
-
-	/* Primary key on (planet,type of resource) */
-	PRIMARY KEY( planet_id , resource_name_id ) ,
-
-	/* Make sure the quantity is always equal or smaller than the maximal
-	 * quantity.
-	 */
-	CHECK( resprov_quantity <= resprov_quantity_max )
-);
-
-CREATE INDEX idx_resprov_resource
-	ON verse.resource_providers( resource_name_id );
-
-ALTER TABLE verse.resource_providers
-	ADD CONSTRAINT fk_resprov_planet
-		FOREIGN KEY ( planet_id ) REFERENCES verse.planets ,
-	ADD CONSTRAINT fk_resprov_resource
-		FOREIGN KEY ( resource_name_id ) REFERENCES defs.natural_resources;
-
-
---
--- Happiness
---
-CREATE TABLE verse.planet_happiness(
-	planet_id	INT NOT NULL PRIMARY KEY ,
-	target		REAL NOT NULL
-					CHECK( target BETWEEN 0.0 AND 1.0 ) ,
-	current		REAL NOT NULL
-					CHECK( current > 0 )
-);
-
-ALTER TABLE verse.planet_happiness
-	ADD CONSTRAINT fk_planethappiness_planet
-		FOREIGN KEY (planet_id) REFERENCES verse.planets;
-
-
---
--- Money
---
-CREATE TABLE verse.planet_money(
-	planet_id	INT NOT NULL PRIMARY KEY ,
-	income		REAL NOT NULL
-					CHECK( income >= 0 ) ,
-	upkeep		REAL NOT NULL
-					CHECK( upkeep >= 0 )
-);
-
-ALTER TABLE verse.planet_money
-	ADD CONSTRAINT fk_planetmoney_planet
-		FOREIGN KEY (planet_id) REFERENCES verse.planets;
-
-
-
-/*
- * Planet resource changes
- * ------------------------
- * 
- * This table stores the results of planet resource updates. It will then be
- * used to update the owning empires' resources.
- * 
- * This table applies to both basic and natural resources. 
- */
-CREATE TABLE verse.planet_resources(
-
-	/* Identifier of the planet */
-	planet_id			INT NOT NULL ,
-
-	/* Identifier of the resource type */
-	resource_name_id	INT NOT NULL ,
-
-	/* Quantity of that resource which was somehow gained at the last game
-	 * update.
-	 */
-	pres_income			DOUBLE PRECISION NOT NULL
-							DEFAULT 0
-							CHECK( pres_income >= 0 ) ,
-
-	/* Quantity of that resource used by the planet's various buildings at the
-	 * last game update.
-	 */
-	pres_upkeep			DOUBLE PRECISION NOT NULL
-							DEFAULT 0
-							CHECK( pres_upkeep >= 0 ) ,
-
-	/* Primary key on (planet,type of resource) */
-	PRIMARY KEY( planet_id , resource_name_id )
-);
-
-CREATE INDEX idx_pres_resource
-	ON verse.planet_resources( resource_name_id );
-
-ALTER TABLE verse.planet_resources
-	ADD CONSTRAINT fk_pres_planet
-		FOREIGN KEY ( planet_id ) REFERENCES verse.planets ,
-	ADD CONSTRAINT fk_pres_resource
-		FOREIGN KEY ( resource_name_id ) REFERENCES defs.resources;
-
-
---
--- Buildings
---
-CREATE TABLE verse.planet_buildings(
-	planet_id		INT NOT NULL ,
-	building_id		INT NOT NULL ,
-	amount			INT NOT NULL CHECK( amount >= 0 ) ,
-	damage			REAL NOT NULL CHECK( damage >= 0 ) ,
-	PRIMARY KEY( planet_id , building_id )
-);
-
-CREATE INDEX idx_planetbuildings_building
-	ON verse.planet_buildings (building_id);
-
-ALTER TABLE verse.planet_buildings
-	ADD CONSTRAINT fk_planetbuildings_planet
-		FOREIGN KEY (planet_id) REFERENCES verse.planets ,
-	ADD CONSTRAINT fk_planetbuildings_building
-		FOREIGN KEY (building_id) REFERENCES tech.buildings;
diff --git a/legacyworlds-server-data/db-structure/parts/030-data/110-empires.sql b/legacyworlds-server-data/db-structure/parts/030-data/110-empires.sql
deleted file mode 100644
index 54bb9b5..0000000
--- a/legacyworlds-server-data/db-structure/parts/030-data/110-empires.sql
+++ /dev/null
@@ -1,361 +0,0 @@
--- LegacyWorlds Beta 6
--- PostgreSQL database scripts
---
--- Empires and alliances
---
--- Copyright(C) 2004-2010, DeepClone Development
--- --------------------------------------------------------
-
-
---
--- Empires
---
-
-CREATE TABLE emp.empires(
-	name_id		INT NOT NULL PRIMARY KEY ,
-	cash		REAL NOT NULL
-					CHECK( cash >= 0 ),
-	debt		REAL NOT NULL DEFAULT 0
-					CHECK( debt >= 0)
-);
-
-ALTER TABLE emp.empires
-	ADD CONSTRAINT fk_empires_name
-		FOREIGN KEY (name_id) REFERENCES naming.empire_names;
-
-
-/*
- * Empire resources
- * -----------------
- * 
- * This table contains the list of resources possessed and owed by each
- * empire.
- */
-
-CREATE TABLE emp.resources(
-	/* Identifier of the empire */
-	empire_id			INT NOT NULL ,
-	
-	/* Identifier of the type of resource */
-	resource_name_id	INT NOT NULL ,
-
-	/* Amount of that specific resource possessed by the empire */
-	empres_possessed	DOUBLE PRECISION NOT NULL
-							DEFAULT 0
-							CHECK( empres_possessed >= 0 ) ,
-
-	/* Amount of that specific resource owed by the empire. This value is
-	 * used to accumulate debts and that, in turn, is used when computing
-	 * debt-related fleet and building destruction.
-	 */
-	empres_owed			DOUBLE PRECISION NOT NULL
-							DEFAULT 0
-							CHECK( empres_owed >= 0 ) ,
-
-	/* There is only one entry for each (empire,type of resource) pair */
-	PRIMARY KEY( empire_id , resource_name_id )
-);
-
-CREATE INDEX idx_empres_resource
-	ON emp.resources ( resource_name_id );
-
-ALTER TABLE emp.resources
-	ADD CONSTRAINT fk_empres_empire
-		FOREIGN KEY ( empire_id ) REFERENCES emp.empires
-			ON DELETE CASCADE ,
-	ADD CONSTRAINT fk_empres_resource
-		FOREIGN KEY ( resource_name_id ) REFERENCES defs.resources;
-
-
-
-/*
- * States for empire technologies
- * -------------------------------
- *
- * This enumerated type represents the 3 possible state for an empire
- * technology: being researched, pending implementation, or implemented.
- */
-
-DROP TYPE IF EXISTS emp.technology_state CASCADE;
-CREATE TYPE emp.technology_state
-	AS ENUM(
-		/* Research in progress */
-		'RESEARCH' ,
-		/* Implementation pending */
-		'PENDING' ,
-		/* Implemented technology */
-		'KNOWN'
-	);
-
-
-/*
- * Empire technologies
- * --------------------
- * 
- * This table stores technologies that are being researched, need to be or
- * have been implemented by an empire. Technologies that are being researched
- * include additional information that represent the research progress and
- * priority.
- * 
- * FIXME: this table must be renamed to emp.technologies after the old
- * research system has been removed 
- */
-
-CREATE TABLE emp.technologies(
-	/* Identifier of the empire */
-	empire_id				INT NOT NULL ,
-	
-	/* Identifier of the technology */
-	technology_name_id		INT NOT NULL ,
-	
-	/* Current state of the technology */
-	emptech_state			emp.technology_state NOT NULL
-								DEFAULT 'RESEARCH' ,
-
-	/* Accumulated research points, or NULL if research is over */
-	emptech_points			DOUBLE PRECISION
-								DEFAULT 0.0 ,
-
-	/* Research priority, or NULL if research is over */
-	emptech_priority		INT DEFAULT 2
-								CHECK( emptech_priority BETWEEN 0 AND 4 ) ,
-
-	/* Primary key is the empire / technology pair */
-	PRIMARY KEY( empire_id , technology_name_id ) ,
-	
-	/* Make sure there are both research points and a priority during research
-	 * and neither when the technology is pending implementation or
-	 * implemented.
-	 */
-	CHECK( CASE emptech_state
-		WHEN 'RESEARCH' THEN
-			( emptech_points IS NOT NULL AND emptech_priority IS NOT NULL )
-		ELSE
-			( emptech_points IS NULL AND emptech_priority IS NULL )
-	END )
-);
-
-CREATE INDEX idx_emptech_technology
-	ON emp.technologies ( technology_name_id );
-
-ALTER TABLE emp.technologies
-	ADD CONSTRAINT fk_emptech_empire
-		FOREIGN KEY ( empire_id ) REFERENCES emp.empires ( name_id )
-			ON DELETE CASCADE ,
-	ADD CONSTRAINT fk_emptech_technology
-		FOREIGN KEY ( technology_name_id ) REFERENCES defs.technologies;
-
-
---
--- Empire planets
--- 
-
-CREATE TABLE emp.planets(
-	planet_id		INT NOT NULL PRIMARY KEY ,
-	empire_id		INT NOT NULL
-);
-
-CREATE INDEX idx_planets_empire
-	ON emp.planets (empire_id);
-
-ALTER TABLE emp.planets
-	ADD CONSTRAINT fk_eplanets_planet
-		FOREIGN KEY (planet_id) REFERENCES verse.planets ,
-	ADD CONSTRAINT fk_eplanets_empire
-		FOREIGN KEY (empire_id) REFERENCES emp.empires
-			ON DELETE CASCADE;
-
-
-/*
- * Empire mining settings
- * -----------------------
- * 
- * This table is used to store general empire mining settings. When the empire
- * gains control over a new planet, or if the planet does not have specific
- * settings, these settings are used to determine the amount of work units
- * that go into extracting each type of resource.
- * 
- * Empire-wide settings are ignored if the planet has specific settings, or if
- * none of the resources present on the planet have a positive weight (in
- * which case all present resources are extracted as if they had the same
- * weight).
- */
-
-CREATE TABLE emp.mining_settings(
-	/* Identifier of the empire */
-	empire_id			INT NOT NULL ,
-
-	/* Identifier of the type of resources */
-	resource_name_id	INT NOT NULL ,
-
-	/* Weight to give to this type of resource when there are no planet-
-	 * specific settings. The weight is a value between 0 (lowest priority)
-	 * and 4 (highest priority)
-	 */ 
-	empmset_weight		INT NOT NULL
-							DEFAULT 2
-							CHECK( empmset_weight BETWEEN 0 AND 4 ) ,
-
-	/* Primary key on (empire,resource type) pairs */
-	PRIMARY KEY( empire_id , resource_name_id )
-);
-
-CREATE INDEX idx_empmset_resource
-	ON emp.mining_settings ( resource_name_id );
-
-ALTER TABLE emp.mining_settings
-	ADD CONSTRAINT fk_empmset_empire
-		FOREIGN KEY ( empire_id ) REFERENCES emp.empires
-			ON DELETE CASCADE ,
-	ADD CONSTRAINT fk_empmset_resource
-		FOREIGN KEY ( resource_name_id ) REFERENCES defs.natural_resources;
-
-
-/*
- * Planet-specific mining settings
- * --------------------------------
- * 
- * Empire may set planet-specific mining settings when they own a planet. Even
- * once the empire abandons the planet (or when it is taken away), the
- * settings are kept in the database and restored if the empire takes control
- * over the planet again.
- */
-
-CREATE TABLE emp.planet_mining_settings(
-	/* Identifier of the empire */
-	empire_id			INT NOT NULL ,
-
-	/* The identifier of the planet */
-	planet_id				INT NOT NULL ,
-
-	/* Identifier of the type of resources */
-	resource_name_id	INT NOT NULL ,
-
-	/* Weight to give to this type of resource. Works in a manner similar to 
-	 * the empmset_weight column of emp.mining_settings.
-	 */ 
-	emppmset_weight		INT NOT NULL
-							DEFAULT 2
-							CHECK( emppmset_weight BETWEEN 0 AND 4 ) ,
-
-	/* Primary key on (empire,resource type) pairs */
-	PRIMARY KEY( empire_id , planet_id , resource_name_id )
-);
-
-CREATE INDEX idx_emppmset_provider
-	ON emp.planet_mining_settings ( planet_id , resource_name_id );
-
-ALTER TABLE emp.planet_mining_settings
-	ADD CONSTRAINT fk_emppmset_empire
-		FOREIGN KEY ( empire_id ) REFERENCES emp.empires
-			ON DELETE CASCADE ,
-	ADD CONSTRAINT fk_emppmset_resource
-		FOREIGN KEY ( planet_id , resource_name_id )
-			REFERENCES verse.resource_providers;
-
-
---
--- Planets being abandonned
---
-
-CREATE TABLE emp.abandon(
-	planet_id		INT NOT NULL PRIMARY KEY ,
-	time_left		INT NOT NULL CHECK ( time_left > 0 )
-);
-
-CREATE INDEX idx_abandon_ready
-	ON emp.abandon ( ( time_left = 1 ) );
-
-ALTER TABLE emp.abandon
-	ADD CONSTRAINT fk_abandon_planet
-		FOREIGN KEY (planet_id) REFERENCES emp.planets
-			ON DELETE CASCADE;
-
-
---
--- Alliances
---
-
-CREATE TABLE emp.alliances(
-	id				SERIAL NOT NULL PRIMARY KEY ,
-	tag				VARCHAR(5) NOT NULL ,
-	name			VARCHAR(128) NOT NULL ,
-	leader_id		INT NOT NULL
-);
-
-CREATE UNIQUE INDEX idx_alliances_tag
-	ON emp.alliances ( lower(tag) );
-CREATE UNIQUE INDEX idx_alliances_leader
-	ON emp.alliances (leader_id);
-
-ALTER TABLE emp.alliances
-	ADD CONSTRAINT fk_alliances_leader
-		FOREIGN KEY (leader_id) REFERENCES emp.empires
-			ON DELETE CASCADE;
-
-
---
--- Alliance membership
---
-
-CREATE TABLE emp.alliance_members(
-	empire_id		INT NOT NULL PRIMARY KEY ,
-	alliance_id		INT NOT NULL ,
-	is_pending		BOOLEAN NOT NULL
-						DEFAULT TRUE
-);
-
-CREATE INDEX idx_alliancemembers_alliance
-	ON emp.alliance_members( alliance_id );
-
-ALTER TABLE emp.alliance_members
-	ADD CONSTRAINT fk_alliancemembers_empire
-		FOREIGN KEY (empire_id) REFERENCES emp.empires
-			ON DELETE CASCADE ,
-	ADD CONSTRAINT fk_alliancemembers_alliance
-		FOREIGN KEY (alliance_id) REFERENCES emp.alliances
-			ON DELETE CASCADE;
-
-
---
--- Enemy lists, alliances
---
-
-CREATE TABLE emp.enemy_alliances(
-	empire_id		INT NOT NULL ,
-	alliance_id		INT NOT NULL ,
-	PRIMARY KEY (empire_id,alliance_id)
-);
-
-CREATE INDEX idx_enemyalliances_alliance
-	ON emp.enemy_alliances (alliance_id);
-
-ALTER TABLE emp.enemy_alliances
-	ADD CONSTRAINT fk_enemyalliances_empire
-		FOREIGN KEY (empire_id) REFERENCES emp.empires
-			ON DELETE CASCADE ,
-	ADD CONSTRAINT fk_enemyalliances_alliance
-		FOREIGN KEY (alliance_id) REFERENCES emp.alliances
-			ON DELETE CASCADE;
-
-
---
--- Enemy lists, empires
---
-
-CREATE TABLE emp.enemy_empires(
-	empire_id		INT NOT NULL ,
-	enemy_id		INT NOT NULL ,
-	PRIMARY KEY (empire_id,enemy_id)
-);
-
-CREATE INDEX idx_enemyempires_enemy
-	ON emp.enemy_empires (enemy_id);
-
-ALTER TABLE emp.enemy_empires
-	ADD CONSTRAINT fk_enemyempires_empire
-		FOREIGN KEY (empire_id) REFERENCES emp.empires
-			ON DELETE CASCADE ,
-	ADD CONSTRAINT fk_enemyempires_enemy
-		FOREIGN KEY (enemy_id) REFERENCES emp.empires
-			ON DELETE CASCADE;
diff --git a/legacyworlds-server-data/db-structure/parts/030-data/140-status.sql b/legacyworlds-server-data/db-structure/parts/030-data/140-status.sql
deleted file mode 100644
index ef0b8d4..0000000
--- a/legacyworlds-server-data/db-structure/parts/030-data/140-status.sql
+++ /dev/null
@@ -1,55 +0,0 @@
--- LegacyWorlds Beta 6
--- PostgreSQL database scripts
---
--- System & ticker status
---
--- Copyright(C) 2004-2010, DeepClone Development
--- --------------------------------------------------------
-
---
--- System status
---
-CREATE TABLE sys.status(
-	next_tick			BIGINT NOT NULL
-							DEFAULT 0 ,
-	current_tick		BIGINT ,
-
-	last_msg_recap		TIMESTAMP WITHOUT TIME ZONE
-							NOT NULL
-							DEFAULT now( ) ,
-	last_admin_recap	TIMESTAMP WITHOUT TIME ZONE
-							NOT NULL
-							DEFAULT now( ) ,
-	last_error_recap	TIMESTAMP WITHOUT TIME ZONE
-							NOT NULL
-							DEFAULT now( ) ,
-
-	maintenance_start	TIMESTAMP WITHOUT TIME ZONE ,
-	maintenance_end		TIMESTAMP WITHOUT TIME ZONE ,
-	maintenance_text	TEXT
-);
-
-INSERT INTO sys.status DEFAULT VALUES;
-
-GRANT SELECT ON sys.status TO :dbuser;
-
-
-
---
--- Ticker status
---
-
-CREATE TYPE ticker_task_status
-	AS ENUM( 'RUNNING' , 'STOPPED' , 'AUTO' );
-
-CREATE TABLE sys.ticker(
-	id				SERIAL PRIMARY KEY ,
-	task_name		VARCHAR(64) NOT NULL UNIQUE ,
-	status			ticker_task_status NOT NULL ,
-	auto_start		TIMESTAMP WITHOUT TIME ZONE
-);
-
-INSERT INTO sys.ticker( task_name , status )
-	VALUES ( 'Game update' , 'STOPPED' );
-
-GRANT SELECT ON sys.ticker TO :dbuser;
diff --git a/legacyworlds-server-data/db-structure/parts/030-data/145-updates.sql b/legacyworlds-server-data/db-structure/parts/030-data/145-updates.sql
deleted file mode 100644
index 8ce13f5..0000000
--- a/legacyworlds-server-data/db-structure/parts/030-data/145-updates.sql
+++ /dev/null
@@ -1,172 +0,0 @@
--- LegacyWorlds Beta 6
--- PostgreSQL database scripts
---
--- Game updates control tables
---
--- Copyright(C) 2004-2012, DeepClone Development
--- --------------------------------------------------------
-
-
-/*
- * Update targets
- * ---------------
- * 
- * An update target refers to a table whose rows are the units to be updated
- * by some step of the game update.
- * 
- * Inserting rows into this control table will generate a new, specific table
- * to store references, and a set of triggers.
- */
-DROP TABLE IF EXISTS sys.update_targets CASCADE;
-CREATE TABLE sys.update_targets(
-	/* Automatically generated identifier of the target type */
-	updtgt_id			SERIAL NOT NULL PRIMARY KEY ,
-	
-	/* Name of the target, displayed in the administration interface */
-	updtgt_name			VARCHAR( 32 ) NOT NULL ,
-
-	/* Schema in which the target table resides */
-	updtgt_schema		NAME NOT NULL ,
-
-	/* Name of the target table */
-	updtgt_table		NAME NOT NULL
-);
-
-/* Update target names are unique */
-CREATE UNIQUE INDEX idx_updtgt_name
-	ON sys.update_targets ( LOWER( updtgt_name ) );
-/* Schema / table combinations are unique */
-CREATE UNIQUE INDEX idx_updtgt_target
-	ON sys.update_targets ( updtgt_schema , updtgt_table );
-
-
-
-/*
- * Update type definitions
- * ------------------------
- * 
- * An update type corresponds to a procedure which will be applied at each
- * game update cycle (once per minute, unless defaults have been modified),
- * and which performs a computation or set thereof on the game's data.
- */
-DROP TABLE IF EXISTS sys.update_types CASCADE;
-CREATE TABLE sys.update_types(
-	/* Automatically generated identifier of the update type */
-	updtype_id			SERIAL NOT NULL ,
-
-	/* The type of target this update refers to */
-	updtgt_id			INT NOT NULL ,
-	
-	/* Name of the update type, used in the administration interface and when
-	 * updates need to be executed externally.
-	 */
-	updtype_name		VARCHAR( 64 ) NOT NULL ,
-
-	/* Ordering index of the update type. This field is always re-generated
-	 * when update types are added or removed.
-	 */
-	updtype_ordering	INT NOT NULL ,
-
-	/* Description of the update type to be included in the administration
-	 * interface.
-	 */
-	updtype_description	TEXT NOT NULL ,
-	
-	/* Name of the stored procedure which handles the update. When this is
-	 * NULL, the update type is assumed to be supported externally (i.e. by
-	 * the game server) rather than internally. Otherwise, a stored procedure
-	 * bearing that name, accepting a BIGINT as its parameter and returning
-	 * VOID, must exist in the sys schema. 
-	 */
-	updtype_proc_name	NAME ,
-
-	/* Size of the update batch. If this is NULL, the global value from the
-	 * game.batchSize constant will be used.
-	 */
-	updtype_batch_size	INT ,
-
-	/* The primary key includes both the update type identifier and the target
-	 * identifier for coherence reasons.
-	 */
-	PRIMARY KEY( updtype_id , updtgt_id ) ,
-
-	/* Batch sizes are either NULL or strictly positive */
-	CHECK( updtype_batch_size IS NULL
-			OR updtype_batch_size > 0 )
-);
-
-/* Update names must be unique, independently of the case */
-CREATE UNIQUE INDEX idx_updtype_name
-	ON sys.update_types ( LOWER( updtype_name ) );
-/* Update ordering index must be unique */
-CREATE UNIQUE INDEX idx_updtype_ordering
-	ON sys.update_types ( updtype_ordering );
-/* Procedure names must be unique */
-CREATE UNIQUE INDEX idx_updtype_procname
-	ON sys.update_types ( updtype_proc_name );
-
-
-
-ALTER TABLE sys.update_types
-	ADD CONSTRAINT fk_updtype_target
-		FOREIGN KEY ( updtgt_id ) REFERENCES sys.update_targets( updtgt_id );
-
-
-
-/*
- * Update state type
- * ------------------
- * 
- * This type represents the possible states of a game update
- */
-DROP TYPE IF EXISTS sys.update_state_type CASCADE;
-CREATE TYPE sys.update_state_type
-	AS ENUM (
-		/* The row will be included in the current game update */
-		'FUTURE' ,
-		/* The row is being processed */
-		'PROCESSING' ,
-		/* The row has been processed by the current or previous game update */
-		'PROCESSED'
-	);
-
-
-/*
- * Main updates table
- * -------------------
- * 
- * This table lists all update rows, including their type and target, as well
- * as their state.
- */
-DROP TABLE IF EXISTS sys.updates CASCADE;
-CREATE TABLE sys.updates(
-	/* The update row's automatically generated identifier */
-	update_id		BIGSERIAL NOT NULL ,
-
-	/* The type of update this row is about */
-	updtype_id		INT NOT NULL ,
-
-	/* The type of target for the update */
-	updtgt_id		INT NOT NULL ,
-
-	/* The update row's current state */
-	update_state	sys.update_state_type
-						NOT NULL
-						DEFAULT 'FUTURE' ,
-
-	/* The tick identifier corresponding to the last game update in which
-	 * this row was processed.
-	 */
-	update_last		BIGINT NOT NULL
-						DEFAULT -1 ,
-
-	/* The primary key includes the automatically generated identifier but
-	 * also the type and target type.
-	 */
-	PRIMARY KEY( update_id , updtype_id , updtgt_id )
-);
-
-ALTER TABLE sys.updates
-	ADD CONSTRAINT fk_update_type
-		FOREIGN KEY ( updtype_id , updtgt_id ) REFERENCES sys.update_types
-			ON DELETE CASCADE;
diff --git a/legacyworlds-server-data/db-structure/parts/030-data/170-events.sql b/legacyworlds-server-data/db-structure/parts/030-data/170-events.sql
deleted file mode 100644
index 77fc97c..0000000
--- a/legacyworlds-server-data/db-structure/parts/030-data/170-events.sql
+++ /dev/null
@@ -1,750 +0,0 @@
--- LegacyWorlds Beta 6
--- PostgreSQL database scripts
---
--- Storage of events
---
--- Copyright(C) 2004-2012, DeepClone Development
--- --------------------------------------------------------
-
-
-/*
- * Event type definitions
- * -----------------------
- * 
- * This table stores the "root" of event type definitions. Each definition is
- * uniquely identifier by a short string.
- */
-DROP TABLE IF EXISTS events.event_definitions CASCADE;
-CREATE TABLE events.event_definitions(
-	/* The event definition identifier */
-	evdef_id			VARCHAR( 48 ) NOT NULL PRIMARY KEY ,
-
-	/* The default priority of the events of this type */
-	evdef_priority		INT NOT NULL
-							CHECK( evdef_priority BETWEEN 0 AND 4 ) ,
-
-	/* Whether the priority for this type of event may be adjusted */
-	evdef_adjustable	BOOLEAN NOT NULL ,
-
-	/* Internationalised string that contains the name of the event type;
-	 * used when displaying priority settings.
-	 */
-	evdef_name_id		INT NOT NULL ,
-	
-	/* Internationalised string that contains the template to use when
-	 * generating the output for a single event.
-	 */
-	evdef_template_id	INT NOT NULL
-);
-
-/* Unique index allowing the custom priorities table to reference only
- * adjustable event types.
- */
-CREATE UNIQUE INDEX idx_evdef_adjustables
-	ON events.event_definitions( evdef_id , evdef_adjustable );
-/* Foreign key indexes */
-CREATE UNIQUE INDEX idx_evdef_name
-	ON events.event_definitions( evdef_name_id );
-CREATE UNIQUE INDEX idx_evdef_template
-	ON events.event_definitions( evdef_template_id );
-
-ALTER TABLE events.event_definitions
-	ADD CONSTRAINT fk_evdef_name
-		FOREIGN KEY ( evdef_name_id ) REFERENCES defs.strings ,
-	ADD CONSTRAINT fk_evdef_template
-		FOREIGN KEY ( evdef_template_id ) REFERENCES defs.strings;
-
-GRANT SELECT ON events.event_definitions TO :dbuser;
-
-
-/*
- * General event field types
- * --------------------------
- */
-DROP TYPE IF EXISTS events.field_type CASCADE;
-CREATE TYPE events.field_type AS ENUM(
-		/* A numeric event field */
-		'NUMERIC' ,
-		/* A raw text event field */
-		'TEXT' ,
-		/* A boolean event field */
-		'BOOL' ,
-		/* An internationalised text field */
-		'I18N' ,
-		/* A field which links to another game entity */
-		'ENTITY'
-	);
-
-
-/*
- * Entity field sub-types
- * -----------------------
- * 
- * FIXME: no message sub-type for now
- */
-DROP TYPE IF EXISTS events.entity_field_type CASCADE;
-CREATE TYPE events.entity_field_type AS ENUM(
-		/* An empire */
-		'EMP' ,
-		/* A planet */
-		'PLN' ,
-		/* A fleet */
-		'FLT' ,
-		/* An alliance */
-		'ALL' ,
-		/* A battle */
-		'BAT' ,
-		/* An administrator */
-		'ADM' ,
-		/* A bug report */
-		'BUG'
-	);
-	
-
-/*
- * Event field definition
- * -----------------------
- * 
- * An event field definition can be associated with an event definition to
- * specify which fields an event will possess.
- */
-DROP TABLE IF EXISTS events.field_definitions CASCADE;
-CREATE TABLE events.field_definitions (
-	/* Identifier of the event type definition */
-	evdef_id		VARCHAR( 48 ) NOT NULL ,
-	
-	/* Identifier of the field itself */
-	efdef_id		VARCHAR( 48 ) NOT NULL ,
-	
-	/* Whether the field is optional or mandatory */
-	efdef_optional	BOOLEAN NOT NULL ,
-	
-	/* General type of the event field */
-	efdef_type		events.field_type NOT NULL ,
-
-	/* Entity type if the field is an entity */
-	efdef_entity	events.entity_field_type ,
-	
-	/* Whether the field should contain an integer or a real number, if the
-	 * field is numeric.
-	 */
-	efdef_integer	BOOLEAN ,
-	
-	/* Minimal value or length of the field if it is either a numeric field or
-	 * a text field.
-	 */
-	efdef_min		NUMERIC ,
-	
-	/* Maximal value or length of the field if it is either a numeric field or
-	 * a text field.
-	 */
-	efdef_max		NUMERIC ,
-
-	/* Use both the event type identifier and the field identifier as
-	 * the primary key
-	 */
-	PRIMARY KEY( evdef_id , efdef_id ) ,
-	
-	/* Entity type is NULL unless the field is an entity field */
-	CONSTRAINT ck_efdef_entity CHECK( CASE
-		WHEN efdef_type = 'ENTITY' THEN
-			efdef_entity IS NOT NULL
-		ELSE
-			efdef_entity IS NULL
-	END ) ,
-
-	/* Make sure the integer flag is set only when the field is numeric */
-	CONSTRAINT ck_efdef_numtype CHECK( CASE
-		WHEN efdef_type = 'NUMERIC' THEN
-			efdef_integer IS NOT NULL
-		ELSE
-			efdef_integer IS NULL
-	END ) ,
-
-	/* Minimal / maximal values only allowed for numerics and raw strings */
-	CONSTRAINT ck_efdef_hasminmax CHECK( CASE
-		WHEN efdef_type IN ( 'NUMERIC' , 'TEXT' ) THEN
-			TRUE
-		ELSE
-			efdef_min IS NULL AND efdef_max IS NULL
-	END ) ,
-
-	/* If both a minimal and maximal values are present, minimal must be lower
-	 * than maximal.
-	 */
-	CONSTRAINT ck_efdef_minmaxvalues CHECK( CASE
-		WHEN efdef_min IS NULL OR efdef_max IS NULL THEN
-			TRUE
-		ELSE
-			efdef_min < efdef_max
-	END )
-);
-
-ALTER TABLE events.field_definitions
-	ADD CONSTRAINT fk_efdef_evdef
-		FOREIGN KEY ( evdef_id ) REFERENCES events.event_definitions
-			ON DELETE CASCADE;
-
-GRANT SELECT ON events.field_definitions TO :dbuser;
-
-
-/*
- * Custom event priorities
- * -----------------------
- * 
- * This table stores player-defined event priority overrides. Only events
- * with custom priorities may be present in this table.
- */
-DROP TABLE IF EXISTS events.custom_priorities CASCADE;
-CREATE TABLE events.custom_priorities(
-	/* Identifier of the event type */
-	evdef_id			VARCHAR(48) NOT NULL ,
-
-	/* Used in reference to the event types - forces this table to
-	 * reference only events that *can* be customised.
-	 */
-	evdef_adjustable	BOOLEAN NOT NULL DEFAULT TRUE
-							CHECK( evdef_adjustable ) ,
-
-	/* Account identifier */
-	address_id			INT NOT NULL ,
-	
-	/* Custom priority */
-	evcp_priority		INT NOT NULL
-							CHECK( evcp_priority BETWEEN 0 AND 4 ) ,
-
-	/* Use the event identifier and "adjustable" set value as the primary
-	 * key. The advantage is that we get an index on both fields.
-	 */
-	PRIMARY KEY( evdef_id , evdef_adjustable )
-);
-
-ALTER TABLE events.custom_priorities
-	ADD CONSTRAINT fk_evcp_evdef
-		FOREIGN KEY ( evdef_id , evdef_adjustable )
-			REFERENCES events.event_definitions ( evdef_id , evdef_adjustable );
-
-GRANT SELECT ON events.custom_priorities TO :dbuser;
-
-
-/*
- * Event identifier sequence
- * -------------------------
- * 
- * This sequence is used by the various type-specific event queues to
- * generate the events' identifiers.
- */
-DROP SEQUENCE IF EXISTS events.event_id_sequence CASCADE;
-CREATE SEQUENCE events.event_id_sequence;
-GRANT SELECT,UPDATE ON events.event_id_sequence TO :dbuser;
-
-
-/*
- * Pending events
- * --------------
- *
- * This table is updated when events are inserted into queues and when they
- * are converted. It tracks events that need to be converted.
- * 
- * Note: the table does not have a primary key or foreign keys; it is simply
- * 		a cache which must not get in the way of inserts into queues.
- *
- * Warning: a record in this table may be orphaned, i.e. there could be no
- *		corresponding entry in the queue table.
- */
-DROP TABLE IF EXISTS events.pending_events CASCADE;
-CREATE TABLE events.pending_events(
-	/* Event identifier */
-	event_id		BIGINT NOT NULL ,
-	/* Event type */
-	evdef_id		VARCHAR(48) NOT NULL
-);
-
-
-/*
- * Event storage table
- * -------------------
- * 
- * This table stores the main entries for actual events. It is fed using the
- * various type-specific event queues.
- * 
- * FIXME: this table should be renamed once the old internal messages are
- * gone.
- */
-DROP TABLE IF EXISTS events.events_v2 CASCADE;
-CREATE TABLE events.events_v2(
-	/* Numeric identifier of the event */
-	event_id		BIGINT NOT NULL PRIMARY KEY ,
-	
-	/* Type of the event */
-	evdef_id		VARCHAR( 48 ) NOT NULL ,
-
-	/* Real time at which the event occurred */
-	event_rtime		TIMESTAMP WITHOUT TIME ZONE
-						NOT NULL ,
-
-	/* Game time (tick identifier) at which the event occurred */
-	event_gtime		BIGINT NOT NULL ,
-	
-	/* Identifier of the empire to which the event applies */
-	empire_id		INT NOT NULL
-);
-
-CREATE UNIQUE INDEX idx_events_iddef
-	ON events.events_v2 ( event_id , evdef_id );
-CREATE INDEX idx_events_selector
-	ON events.events_v2 ( empire_id , event_rtime );
-
-ALTER TABLE events.events_v2
-	ADD CONSTRAINT fk_events_evdef
-		FOREIGN KEY ( evdef_id ) REFERENCES events.event_definitions ( evdef_id ) ,
-	ADD CONSTRAINT fk_events_empire
-		FOREIGN KEY ( empire_id ) REFERENCES emp.empires ( name_id )
-			ON DELETE CASCADE;
-
-GRANT SELECT ON events.events_v2 TO :dbuser;
-
-
-/*
- * Event field values storage table
- * --------------------------------
- * 
- * This table stores the values of the events' fields.
- */
-DROP TABLE IF EXISTS events.field_values CASCADE;
-CREATE TABLE events.field_values(
-	/* The event's identifier */
-	event_id		BIGINT NOT NULL ,
-	
-	/* The event's type */
-	evdef_id		VARCHAR(48) NOT NULL ,
-	
-	/* The field's identifier */
-	efdef_id		VARCHAR(48) NOT NULL ,
-	
-	/* Literal field value */ 
-	efval_litteral	TEXT NOT NULL ,
-	
-	/* I18N string reference */
-	string_id		INT ,
-
-	/* Empire reference */
-	empire_id		INT ,
-	
-	/* Planet reference */
-	planet_id		INT ,
-	
-	/* Fleet reference */
-	fleet_id		BIGINT ,
-	
-	/* Alliance reference */
-	alliance_id		INT ,
-
-	/* Battle reference */
-	battle_id		BIGINT ,
-
-	/* Administrator reference */
-	admin_id		INT ,
-
-	/* Bug report reference */
-	bug_report_id	BIGINT ,
-	
-	PRIMARY KEY( event_id , evdef_id , efdef_id )
-);
-
-CREATE INDEX idx_fvalues_string
-	ON events.field_values ( string_id );
-CREATE INDEX idx_fvalues_empire
-	ON events.field_values ( empire_id );
-CREATE INDEX idx_fvalues_planet
-	ON events.field_values ( planet_id );
-CREATE INDEX idx_fvalues_fleet
-	ON events.field_values ( fleet_id );
-CREATE INDEX idx_fvalues_alliance
-	ON events.field_values ( alliance_id );
-CREATE INDEX idx_fvalues_battle
-	ON events.field_values ( battle_id );
-CREATE INDEX idx_fvalues_admin
-	ON events.field_values ( admin_id );
-CREATE INDEX idx_fvalues_bugreport
-	ON events.field_values ( bug_report_id );
-
-ALTER TABLE events.field_values
-	ADD CONSTRAINT fk_fvalues_event
-		FOREIGN KEY ( event_id , evdef_id ) REFERENCES events.events_v2 ( event_id , evdef_id )
-			ON DELETE CASCADE ,
-	ADD CONSTRAINT fk_fvalues_field
-		FOREIGN KEY ( evdef_id , efdef_id ) REFERENCES events.field_definitions ,
-	ADD CONSTRAINT fk_fvalues_string
-		FOREIGN KEY ( string_id ) REFERENCES defs.strings ,
-	ADD CONSTRAINT fk_fvalues_empire
-		FOREIGN KEY ( empire_id ) REFERENCES emp.empires
-			ON DELETE CASCADE ,
-	ADD CONSTRAINT fk_fvalues_planet
-		FOREIGN KEY ( planet_id ) REFERENCES verse.planets
-			ON DELETE CASCADE ,
-	ADD CONSTRAINT fk_fvalues_fleet
-		FOREIGN KEY ( fleet_id ) REFERENCES fleets.fleets
-			ON DELETE CASCADE ,
-	ADD CONSTRAINT fk_fvalues_alliance
-		FOREIGN KEY ( alliance_id ) REFERENCES emp.alliances
-			ON DELETE CASCADE ,
-	ADD CONSTRAINT fk_fvalues_battle
-		FOREIGN KEY ( battle_id ) REFERENCES battles.battles
-			ON DELETE CASCADE ,
-	ADD CONSTRAINT fk_fvalues_admin
-		FOREIGN KEY ( admin_id ) REFERENCES admin.administrators
-			ON DELETE CASCADE ,
-	ADD CONSTRAINT fk_fvalues_bugreport
-		FOREIGN KEY ( bug_report_id ) REFERENCES bugs.initial_report_events
-			ON DELETE CASCADE;
-
-GRANT SELECT ON events.field_values TO :dbuser;
-
-
-/*
- * Event viewing interfaces
- * ------------------------
- * 
- * This table stores the list of interfaces which can be used to access the
- * events. It allows the system to handle multiple types of event viewing or
- * processing: for example the web interface and email notifications.
- */
-CREATE TABLE events.interfaces(
-
-	/* A short string that identifies the interface */
-	evi_id		VARCHAR(8) NOT NULL PRIMARY KEY ,
-
-	/* A description of the interface */
-	evi_descr	TEXT NOT NULL
-
-);
-
-/* Directly insert interface types */
-INSERT INTO events.interfaces( evi_id , evi_descr ) VALUES
-	( 'game' , 'The game''s main interface' ) ,
-	( 'mail' , 'The e-mail notifications system' );
-
-
-/*
- * Events to process
- * -----------------
- * 
- * This table stores the list of events which need to be processed for each
- * interface.
- */
-CREATE TABLE events.unprocessed_events(
-	/* The event's identifier */
-	event_id			BIGINT NOT NULL ,
-
-	/* The interface's identifier */
-	evi_id				VARCHAR(8) NOT NULL ,
-
-	/* Whether the interface has pre-processed the event, but not displayed
-	 * or sent it yet. This is used with e.g. the email notification system,
-	 * which waits for more events once a first event is ready. When the
-	 * server restarts, the field is set back to FALSE.
-	 */
-	upe_preprocessed	BOOLEAN NOT NULL
-							DEFAULT FALSE ,
-	
-	/* Use both the event and interface as the primary key */
-	PRIMARY KEY( event_id , evi_id )
-);
-
-CREATE INDEX idx_unprocessed_interface
-	ON events.unprocessed_events( evi_id );
-
-ALTER TABLE events.unprocessed_events
-	ADD CONSTRAINT fk_unprocessed_event
-		FOREIGN KEY ( event_id ) REFERENCES events.events_v2 ( event_id )
-			ON DELETE CASCADE ,
-	ADD CONSTRAINT fk_unprocessed_interface
-		FOREIGN KEY ( evi_id ) REFERENCES events.interfaces ( evi_id );
-
-
-/*
- * OLD B6M1 CODE BELOW!
- */
-
-
-CREATE TYPE event_type
-	AS ENUM ( 'QUEUE' , 'EMPIRE' , 'FLEETS' , 'PLANET', 'ALLIANCE', 'ADMIN' , 'BUGS' );
-
-CREATE TYPE event_status
-	AS ENUM( 'TICK' , 'ACTION' , 'READY' , 'SENT' );
-
-
-
---
--- Events table
---
-
-CREATE TABLE events.events(
-	event_id		BIGSERIAL PRIMARY KEY ,
-	empire_id		INT NOT NULL ,
-	tick			BIGINT NOT NULL ,
-	real_time		TIMESTAMP WITHOUT TIME ZONE
-						NOT NULL
-						DEFAULT now() ,
-	evt_type		event_type NOT NULL ,
-	evt_subtype		INT NOT NULL ,
-	status			event_status NOT NULL
-);
-
-CREATE INDEX idx_events_empire
-	ON events.events (empire_id);
-
-CREATE INDEX idx_events_time
-	ON events.events (real_time);
-
-CREATE INDEX idx_events_lookup
-	ON events.events( empire_id , tick , evt_type , evt_subtype , status )
-	WHERE status IN ( 'TICK' , 'ACTION' );
-
-ALTER TABLE events.events
-	ADD CONSTRAINT fk_events_empire
-		FOREIGN KEY ( empire_id ) REFERENCES emp.empires
-			ON DELETE CASCADE;
-
-GRANT SELECT ON events.events TO :dbuser;
-
-
---
--- Build queue events
---
-
-CREATE TABLE events.queue_events (
-	event_id		BIGINT NOT NULL PRIMARY KEY
-);
-
-ALTER TABLE events.queue_events
-	ADD CONSTRAINT fk_bqevents_event
-		FOREIGN KEY (event_id) REFERENCES events.events
-			ON DELETE CASCADE;
-
-
-
---
--- Build queue event locations
---
-
-CREATE TABLE events.bqe_locations(
-	event_id		BIGINT NOT NULL ,
-	location_id		INT NOT NULL ,
-	location_name	VARCHAR(20) NOT NULL ,
-	PRIMARY KEY( event_id , location_id )
-);
-
-ALTER TABLE events.bqe_locations
-	ADD CONSTRAINT fk_bqelocations_event
-		FOREIGN KEY (event_id) REFERENCES events.queue_events
-			ON DELETE CASCADE ,
-	ADD CONSTRAINT fk_bqelocations_location
-		FOREIGN KEY (location_id) REFERENCES verse.planets;
-
-
---
--- Fleet events
---
-
-CREATE TABLE events.fleets_events(
-	event_id		BIGINT NOT NULL PRIMARY KEY ,
-	location_id		INT NOT NULL ,
-	location_name	VARCHAR(20) NOT NULL
-);
-
-CREATE INDEX idx_flevents_location
-	ON events.fleets_events( location_id );
-
-ALTER TABLE events.fleets_events
-	ADD CONSTRAINT fk_flevents_event
-		FOREIGN KEY (event_id) REFERENCES events.events
-			ON DELETE CASCADE ,
-	ADD CONSTRAINT fk_flevents_location
-		FOREIGN KEY (location_id) REFERENCES verse.planets;
-
-
-
---
--- Fleets for fleet events
---
-
-CREATE TABLE events.fleet_lists(
-	id				BIGSERIAL PRIMARY KEY ,
-	event_id		BIGINT NOT NULL ,
-	owner_id		INT ,
-	owner_name		VARCHAR(20) NOT NULL ,
-	fleet_name		VARCHAR(64) ,
-	fleet_power		BIGINT NOT NULL CHECK( fleet_power > 0 ) ,
-	status			BOOLEAN ,
-	source_id		INT ,
-	source_name		VARCHAR(20) ,
-	CHECK( source_id IS NULL AND source_name IS NULL OR source_id IS NOT NULL AND source_name IS NOT NULL )
-);
-
-CREATE INDEX idx_flelists_event
-	ON events.fleet_lists( event_id );
-
-CREATE INDEX idx_flelists_owner
-	ON events.fleet_lists( owner_id )
-	WHERE owner_id IS NOT NULL;
-
-CREATE INDEX idx_flelists_source
-	ON events.fleet_lists( source_id )
-	WHERE source_id IS NOT NULL;
-
-ALTER TABLE events.fleet_lists
-	ADD CONSTRAINT fk_flelist_event
-		FOREIGN KEY ( event_id ) REFERENCES events.fleets_events
-			ON DELETE CASCADE ,
-	ADD CONSTRAINT fk_flelist_owner
-		FOREIGN KEY ( owner_id ) REFERENCES emp.empires
-			ON DELETE SET NULL ,
-	ADD CONSTRAINT fk_flelist_source
-		FOREIGN KEY ( source_id ) REFERENCES verse.planets;
-
-GRANT SELECT ON events.fleet_lists TO :dbuser;
-
-
-
---
--- Planet events
---
-
-CREATE TABLE events.planet_events(
-	event_id		BIGINT PRIMARY KEY,
-	location_id		INT NOT NULL ,
-	location_name	VARCHAR(20) NOT NULL ,
-	empire_id		INT ,
-	empire_name		VARCHAR(20) ,
-	battle_id		BIGINT ,
-	CHECK( battle_id IS NULL AND empire_id IS NULL AND empire_name IS NULL
-		OR battle_id IS NOT NULL AND empire_id IS NULL AND empire_name IS NULL
-		OR battle_id IS NULL AND empire_name IS NOT NULL )
-);
-
-CREATE INDEX idx_pevents_event
-	ON events.planet_events ( event_id );
-
-CREATE INDEX idx_pevents_location
-	ON events.planet_events ( location_id );
-
-CREATE INDEX idx_pevents_empire
-	ON events.planet_events ( empire_id )
-	WHERE empire_id IS NOT NULL;
-
-CREATE INDEX idx_pevents_battle
-	ON events.planet_events ( battle_id )
-	WHERE battle_id IS NOT NULL;
-
-ALTER TABLE events.planet_events
-	ADD CONSTRAINT fk_pevents_event
-		FOREIGN KEY ( event_id ) REFERENCES events.events
-			ON DELETE CASCADE ,
-	ADD CONSTRAINT fk_pevents_location
-		FOREIGN KEY ( location_id ) REFERENCES verse.planets ,
-	ADD CONSTRAINT fk_pevents_empire
-		FOREIGN KEY ( empire_id ) REFERENCES emp.empires
-			ON DELETE SET NULL ,
-	ADD CONSTRAINT fk_pevents_battle
-		FOREIGN KEY ( battle_id ) REFERENCES battles.battles;
-
-
-
---
--- Alliance events
---
-
-CREATE TABLE events.alliance_events(
-	event_id		BIGINT PRIMARY KEY ,
-	alliance_id		INT ,
-	alliance_tag	VARCHAR( 5 ) NOT NULL ,
-	empire_id		INT ,
-	empire_name		VARCHAR( 20 ) ,
-	req_result		BOOLEAN ,
-	CHECK( req_result IS NULL AND empire_id IS NULL AND empire_name IS NULL
-		OR req_result IS NOT NULL AND empire_id IS NULL AND empire_name IS NULL
-		OR req_result IS NULL AND empire_name IS NOT NULL )
-);
-
-CREATE INDEX idx_aevents_event
-	ON events.alliance_events ( event_id );
-
-CREATE INDEX idx_aevents_alliance
-	ON events.alliance_events ( alliance_id )
-	WHERE alliance_id IS NOT NULL;
-
-CREATE INDEX idx_aevents_empire
-	ON events.alliance_events ( empire_id )
-	WHERE empire_id IS NOT NULL;
-
-ALTER TABLE events.alliance_events
-	ADD CONSTRAINT fk_aevents_event
-		FOREIGN KEY ( event_id ) REFERENCES events.events
-			ON DELETE CASCADE ,
-	ADD CONSTRAINT fk_aevents_allliance
-		FOREIGN KEY ( alliance_id ) REFERENCES emp.alliances
-			ON DELETE SET NULL ,
-	ADD CONSTRAINT fk_aevents_empire
-		FOREIGN KEY ( empire_id ) REFERENCES emp.empires
-			ON DELETE SET NULL;
-
-
-
---
--- Admin events
---
-
-CREATE TABLE events.admin_events(
-	event_id		BIGINT PRIMARY KEY ,
-	n_warnings		INT ,
-	location_id		INT ,
-	old_name		VARCHAR( 20 ) NOT NULL ,
-	new_name		VARCHAR( 20 )
-);
-
-CREATE INDEX idx_adevents_event
-	ON events.admin_events ( event_id );
-
-CREATE INDEX idx_adevents_location
-	ON events.admin_events ( location_id )
-	WHERE location_id IS NOT NULL;
-
-ALTER TABLE events.admin_events
-	ADD CONSTRAINT fk_adevents_event
-		FOREIGN KEY ( event_id ) REFERENCES events.events
-			ON DELETE CASCADE ,
-	ADD CONSTRAINT fk_adevents_location
-		FOREIGN KEY ( location_id ) REFERENCES verse.planets;
-
-
-
---
--- Bug tracking events
---
-
-CREATE TABLE events.bug_events(
-	event_id		BIGINT PRIMARY KEY ,
-	bug_id			BIGINT NOT NULL ,
-	submitter_id	BIGINT NOT NULL
-);
-
-CREATE INDEX idx_btevents_event
-	ON events.bug_events ( event_id );
-
-CREATE INDEX idx_btevents_bug
-	ON events.bug_events ( bug_id );
-
-CREATE INDEX idx_btevents_submitter
-	ON events.bug_events ( submitter_id );
-
-
-ALTER TABLE events.bug_events
-	ADD CONSTRAINT fk_btevents_event
-		FOREIGN KEY ( event_id ) REFERENCES events.events
-			ON DELETE CASCADE ,
-	ADD CONSTRAINT fk_btevents_bug
-		FOREIGN KEY ( bug_id ) REFERENCES bugs.initial_report_events ,
-	ADD CONSTRAINT fk_btevents_submitter
-		FOREIGN KEY ( submitter_id ) REFERENCES bugs.submitters;
diff --git a/legacyworlds-server-data/db-structure/parts/040-functions/003-updates.sql b/legacyworlds-server-data/db-structure/parts/040-functions/003-updates.sql
deleted file mode 100644
index 0a2e5f3..0000000
--- a/legacyworlds-server-data/db-structure/parts/040-functions/003-updates.sql
+++ /dev/null
@@ -1,571 +0,0 @@
--- LegacyWorlds Beta 6
--- PostgreSQL database scripts
---
--- Game updates - support functions for update definitions
---
--- Copyright(C) 2004-2012, DeepClone Development
--- --------------------------------------------------------
-
-
-/*
- * Type that represents a field from a primary key
- * ------------------------------------------------
- * 
- * This type represents both the field itself (as a name) and its type.
- */
-DROP TYPE IF EXISTS sys.pk_field_type CASCADE;
-CREATE TYPE sys.pk_field_type AS (
-	f_name			NAME ,
-	f_type			NAME 
-);
-
-
-/*
- * Get a table's primary key fields and field types
- * -------------------------------------------------
- * 
- * This function will list all fields from a table's primary key along with
- * their types.
- * 
- * Parameters:
- *		_schema_name		The name of the schema the table resides in
- *		_table_name			The name of the table
- *
- * Returns:
- * 		?					A set of sys.pk_field_type records
- */
-DROP FUNCTION IF EXISTS sys.get_table_pkey( NAME , NAME ) CASCADE;
-CREATE FUNCTION sys.get_table_pkey( _schema_name NAME , _table_name NAME )
-	RETURNS SETOF sys.pk_field_type
-	LANGUAGE SQL
-	STRICT IMMUTABLE
-	SECURITY INVOKER
-AS $get_table_pkey$
-
-	SELECT _attr.attname AS f_name , _type.typname AS f_type
-
-		FROM pg_namespace _schema
-			INNER JOIN pg_class _table
-				ON _table.relnamespace = _schema.oid
-			INNER JOIN (
-					SELECT indrelid , unnest( indkey ) AS indattnum
-						FROM pg_index WHERE indisprimary
-				) _index ON _index.indrelid = _table.oid
-			INNER JOIN pg_attribute _attr
-				ON _attr.attrelid = _table.oid
-					AND _attr.attnum = _index.indattnum
-			INNER JOIN pg_type _type
-				ON _type.oid = _attr.atttypid
-
-		WHERE _schema.nspname = $1
-			AND _table.relname = $2
-
-		ORDER BY _index.indattnum;
-
-$get_table_pkey$;
-
-REVOKE EXECUTE
-	ON FUNCTION sys.get_table_pkey( NAME , NAME )
-	FROM PUBLIC;
-
-
-
-/*
- * Automatic update row insertion
- * -------------------------------
- * 
- * This trigger function is added to all type-specific update tables. It is
- * called before insertions, and will make sure a generic update row exists
- * for the new row.
- */
-DROP FUNCTION IF EXISTS sys.tgf_speupd_before_insert( ) CASCADE;
-CREATE FUNCTION sys.tgf_speupd_before_insert( )
-		RETURNS TRIGGER
-		LANGUAGE PLPGSQL
-		STRICT VOLATILE
-		SECURITY INVOKER
-	AS $tgf_speupd_before_insert$
-
-DECLARE
-	_update_id	BIGINT;
-
-BEGIN
-	
-	INSERT INTO sys.updates ( updtype_id , updtgt_id )
-		VALUES ( NEW.updtype_id , NEW.updtgt_id )
-		RETURNING update_id INTO _update_id;
-
-	NEW.update_id := _update_id;
-	RETURN NEW;
-END;
-$tgf_speupd_before_insert$;
-
-REVOKE EXECUTE
-	ON FUNCTION sys.tgf_speupd_before_insert( )
-	FROM PUBLIC;
-
-
-
-/*
- * Automatic update row removal
- * -----------------------------
- * 
- * This trigger function is added to all type-specific update tables. It is
- * called once a row has been deleted, and will remove the corresponding
- * generic update row.
- */
-DROP FUNCTION IF EXISTS sys.tgf_speupd_after_delete( ) CASCADE;
-CREATE FUNCTION sys.tgf_speupd_after_delete( )
-		RETURNS TRIGGER
-		LANGUAGE PLPGSQL
-		STRICT VOLATILE
-		SECURITY INVOKER
-	AS $tgf_speupd_after_delete$
-BEGIN
-
-	DELETE FROM sys.updates
-		WHERE update_id = OLD.update_id
-			AND updtype_id = OLD.updtype_id
-			AND updtgt_id = OLD.updtgt_id;
-
-	RETURN OLD;
-END;
-$tgf_speupd_after_delete$;
-
-REVOKE EXECUTE
-	ON FUNCTION sys.tgf_speupd_after_delete( )
-	FROM PUBLIC;
-
-
-
-/*
- * Add missing update rows
- * ------------------------
- * 
- * This function adds rows missing from the update and specific update tables
- * for a given target type.
- * 
- * Parameters:
- *		_target_type	The identifier of the target type for which missing
- *							rows are to be inserted.
- */
-DROP FUNCTION IF EXISTS sys.insert_missing_updates( INT ) CASCADE;
-CREATE FUNCTION sys.insert_missing_updates( _target_type INT )
-		RETURNS VOID
-		LANGUAGE PLPGSQL
-		STRICT VOLATILE
-		SECURITY INVOKER
-	AS $insert_missing_updates$
-
-DECLARE
-	_t_schema		TEXT;
-	_t_table		TEXT;
-	_field_list		TEXT;
-	_query			TEXT;
-
-BEGIN
-	SELECT INTO _t_schema , _t_table updtgt_schema , updtgt_table
-		FROM sys.update_targets
-		WHERE updtgt_id = _target_type;
-	SELECT INTO _field_list array_to_string( array_agg( f_name ) , ' , ' )
-		FROM sys.get_table_pkey( _t_schema , _t_table );
-
-	_query := 'INSERT INTO "' || _t_schema || '"."' || _t_table || '_updates" '
-		|| '( updtgt_id , updtype_id , ' || _field_list || ') '
-		|| 'SELECT updtgt_id , updtype_id , ' || _field_list
-			|| ' FROM sys.update_types CROSS JOIN "'
-		|| _t_schema || '"."' || _t_table || '" LEFT OUTER JOIN "'
-		|| _t_schema || '"."' || _t_table
-		|| '_updates" USING ( updtgt_id , updtype_id , ' || _field_list
-		|| ') WHERE update_id IS NULL AND updtgt_id = ' || _target_type;
-	EXECUTE _query;
-
-END;
-$insert_missing_updates$;
-
-REVOKE EXECUTE
-	ON FUNCTION sys.insert_missing_updates( INT )
-	FROM PUBLIC;
-
-
-
-/*
- * Trigger function that adds missing update rows
- * ----------------------------------------------
- * 
- * This function calls sys.insert_missing_updates. The main difference between
- * the original function and this one is that the former cannot be used in
- * triggers, while the latter is meant to be used as a trigger on the target
- * table.
- */
-DROP FUNCTION IF EXISTS sys.tgf_insert_missing_updates( ) CASCADE;
-CREATE FUNCTION sys.tgf_insert_missing_updates( )
-		RETURNS TRIGGER
-		LANGUAGE PLPGSQL
-		STRICT VOLATILE
-		SECURITY INVOKER
-	AS $tgf_insert_missing_updates$
-BEGIN
-	IF TG_NARGS <> 1 THEN
-		RAISE EXCEPTION 'This trigger function requires one argument';
-	END IF;
-	PERFORM sys.insert_missing_updates( TG_ARGV[ 0 ]::INT );
-	RETURN NULL;
-END;
-$tgf_insert_missing_updates$;
-
-REVOKE EXECUTE
-	ON FUNCTION sys.tgf_insert_missing_updates( )
-	FROM PUBLIC;
-
-
-/*
- * Handle new update types
- * ------------------------
- * 
- * This function is triggered when a new update type is created; it will insert
- * the update rows for the new type.
- */
-DROP FUNCTION IF EXISTS sys.tgf_updtype_after_insert_row( ) CASCADE;
-CREATE FUNCTION sys.tgf_updtype_after_insert_row( )
-		RETURNS TRIGGER
-		LANGUAGE PLPGSQL
-		STRICT VOLATILE
-		SECURITY INVOKER
-	AS $tgf_updtype_after_insert$
-BEGIN
-	PERFORM sys.insert_missing_updates( NEW.updtgt_id );
-	RETURN NEW;
-END;
-$tgf_updtype_after_insert$;
-
-REVOKE EXECUTE
-	ON FUNCTION sys.tgf_updtype_after_insert_row( )
-	FROM PUBLIC;
-
-CREATE TRIGGER tg_updtype_after_insert_row
-	AFTER INSERT ON sys.update_types
-	FOR EACH ROW EXECUTE PROCEDURE sys.tgf_updtype_after_insert_row( );
-
-	
-/*
- * Update type definition check
- * -----------------------------
- * 
- * This trigger function is called when a new update type is added or when
- * an update type's stored procedure is updated. It makes sure that the
- * corresponding stored procedure actually exists.
- */
-DROP FUNCTION IF EXISTS sys.tgf_check_update_type_proc( ) CASCADE;
-CREATE FUNCTION sys.tgf_check_update_type_proc( )
-		RETURNS TRIGGER
-		LANGUAGE PLPGSQL
-		STRICT VOLATILE
-		SECURITY INVOKER
-	AS $tgf_check_update_type_proc$
-BEGIN
-
-	IF NEW.updtype_proc_name IS NULL THEN
-		RETURN NEW;
-	END IF;
-	
-	PERFORM 1
-		FROM pg_namespace _schema
-			INNER JOIN pg_proc _proc
-				ON _proc.pronamespace = _schema.oid
-		WHERE _schema.nspname = 'sys'
-			AND _proc.proname = NEW.updtype_proc_name;
-	IF NOT FOUND THEN
-		RAISE EXCEPTION 'Update type % has invalid update function sys.%' ,
-			NEW.updtype_name , NEW.updtype_proc_name;
-	END IF;
-
-	RETURN NEW;
-END;
-$tgf_check_update_type_proc$;
-
-REVOKE EXECUTE
-	ON FUNCTION sys.tgf_check_update_type_proc( )
-	FROM PUBLIC;
-
-CREATE TRIGGER tg_check_update_type_proc_insert
-	BEFORE INSERT ON sys.update_types
-	FOR EACH ROW EXECUTE PROCEDURE sys.tgf_check_update_type_proc( );
-CREATE TRIGGER tg_check_update_type_proc_update
-	BEFORE UPDATE OF updtype_proc_name ON sys.update_types
-	FOR EACH ROW EXECUTE PROCEDURE sys.tgf_check_update_type_proc( );
-
-
-/*
- * Trigger that reorders the update types
- * ---------------------------------------
- * 
- * This function will update the ordering field of update types whenever rows
- * are inserted or deleted.
- */
-DROP FUNCTION IF EXISTS sys.tgf_reorder_update_types( ) CASCADE;
-CREATE FUNCTION sys.tgf_reorder_update_types( )
-		RETURNS TRIGGER
-		LANGUAGE PLPGSQL
-		STRICT VOLATILE
-		SECURITY INVOKER
-	AS $tgf_reorder_update_types$
-
-DECLARE
-	_max_ordering	INT;
-
-BEGIN
-	
-	SELECT INTO _max_ordering MAX( updtype_ordering ) FROM sys.update_types;
-	IF _max_ordering IS NOT NULL THEN
-		UPDATE sys.update_types
-			SET updtype_ordering = updtype_ordering + _max_ordering * 2;
-	END IF;
-
-	UPDATE sys.update_types
-		SET updtype_ordering = updtype_rownumber * 2
-		FROM (
-			SELECT updtype_id AS id,
-					row_number( ) OVER (
-							ORDER BY updtype_ordering
-						) AS updtype_rownumber
-				FROM sys.update_types
-		) _row
-		WHERE updtype_id = _row.id;
-
-		RETURN NULL;
-END;
-$tgf_reorder_update_types$;
-
-REVOKE EXECUTE
-	ON FUNCTION sys.tgf_reorder_update_types( )
-	FROM PUBLIC;
-
-CREATE TRIGGER tg_updtype_after_insert_stmt
-	AFTER INSERT ON sys.update_types
-	FOR EACH STATEMENT EXECUTE PROCEDURE sys.tgf_reorder_update_types( );
-
-CREATE TRIGGER tg_updtype_after_delete_stmt
-	AFTER DELETE ON sys.update_types
-	FOR EACH STATEMENT EXECUTE PROCEDURE sys.tgf_reorder_update_types( );
-
-
-
-/*
- * Check target tables
- * --------------------
- * 
- * Before a new row is inserted into sys.update_targets, make sure
- * the target table it contains actually exists.
- */
-DROP FUNCTION IF EXISTS sys.tgf_updtgt_before_insert( ) CASCADE;
-CREATE FUNCTION sys.tgf_updtgt_before_insert( )
-		RETURNS TRIGGER
-		LANGUAGE PLPGSQL
-		STRICT VOLATILE
-		SECURITY INVOKER
-	AS $tgf_updtgt_before_insert$
-BEGIN
-	PERFORM 1
-		FROM pg_class pc
-			INNER JOIN pg_namespace pn
-				ON pn.oid = pc.relnamespace
-			INNER JOIN pg_roles pr
-				ON pr.oid = pc.relowner
-		WHERE pn.nspname = NEW.updtgt_schema
-			AND pc.relname = NEW.updtgt_table
-			AND pc.reltype <> 0 AND pc.relkind = 'r'
-			AND pr.rolname <> 'postgres';
-	IF NOT FOUND THEN
-		RAISE EXCEPTION 'Update target table %.% not found' ,
-				NEW.updtgt_schema , NEW.updtgt_table  
-			USING ERRCODE = 'foreign_key_violation';
-	END IF;
-	
-	RETURN NEW;
-END;
-$tgf_updtgt_before_insert$;
-
-REVOKE EXECUTE
-	ON FUNCTION sys.tgf_updtgt_before_insert( )
-	FROM PUBLIC;
-
-CREATE TRIGGER tg_updtgt_before_insert
-	BEFORE INSERT ON sys.update_targets
-	FOR EACH ROW EXECUTE PROCEDURE sys.tgf_updtgt_before_insert( );
-
-
-
-/*
- * Create update list and triggers for target table
- * -------------------------------------------------
- *
- * After a new update type has been registered, a table listing updates
- * as well as a set of triggers on the target table need to be created.
- */
-DROP FUNCTION IF EXISTS sys.tgf_updtgt_after_insert( ) CASCADE;
-CREATE FUNCTION sys.tgf_updtgt_after_insert( )
-		RETURNS TRIGGER
-		LANGUAGE PLPGSQL
-		STRICT VOLATILE
-	AS $tgf_updtgt_after_insert$
-
-DECLARE
-	_table_name		TEXT;
-	_query			TEXT;
-	_field_name		NAME;
-	_field_type		NAME;
-	_field_list		TEXT;
-
-BEGIN
-	_table_name := '"' || NEW.updtgt_schema || '"."' || NEW.updtgt_table || '_updates"';
-	_query := 'CREATE TABLE ' || _table_name || $_table_base_fields$(
-			update_id		BIGINT NOT NULL ,
-			updtype_id		INT NOT NULL ,
-			updtgt_id		INT NOT NULL
-		$_table_base_fields$;
-
-	-- List target table's primary key fields
-	_field_list := '';
-	FOR _field_name , _field_type IN
-			SELECT * FROM sys.get_table_pkey( NEW.updtgt_schema , NEW.updtgt_table )
-	LOOP
-		_query := _query || ', "' || _field_name || '" "' || _field_type
-				|| '" NOT NULL';
-		IF _field_list <> '' THEN
-			_field_list := _field_list || ' , ';
-		END IF;
-		_field_list := _field_list || '"' || _field_name || '"';
-	END LOOP;
-	
-	_query := _query ||
-		' , PRIMARY KEY ( updtgt_id , updtype_id , update_id , '
-		|| _field_list || ' ) , CHECK ( updtgt_id = ' || NEW.updtgt_id || ' ) )';
-	EXECUTE _query;
-
-	-- Add foreign keys
-	_query := 'ALTER TABLE ' || _table_name
-		|| ' ADD CONSTRAINT fk_upd_' || NEW.updtgt_table || '_update '
-			|| 'FOREIGN KEY ( update_id , updtype_id , updtgt_id ) REFERENCES sys.updates '
-				|| 'ON DELETE CASCADE , '
-		|| ' ADD CONSTRAINT fk_upd_' || NEW.updtgt_table || '_target '
-			|| 'FOREIGN KEY ( ' || _field_list
-				|| ' ) REFERENCES "' || NEW.updtgt_schema || '"."' || NEW.updtgt_table
-				|| '" ON DELETE CASCADE';
-	EXECUTE _query;
-
-	-- Create automatic update creation/deletion triggers
-	_query := 'CREATE TRIGGER tg_speupd_before_insert BEFORE INSERT ON ' || _table_name
-		|| ' FOR EACH ROW EXECUTE PROCEDURE sys.tgf_speupd_before_insert( )';
-	EXECUTE _query;
-	_query := 'CREATE TRIGGER tg_speupd_after_delete AFTER DELETE ON ' || _table_name
-		|| ' FOR EACH ROW EXECUTE PROCEDURE sys.tgf_speupd_after_delete( )';
-	EXECUTE _query;
-	
-	-- Create triggers that will insert/delete update rows when new items are added/removed
-	_query := 'CREATE TRIGGER tg_speupd_after_insert AFTER INSERT ON "'
-		||	NEW.updtgt_schema || '"."' || NEW.updtgt_table
-		|| '" FOR EACH STATEMENT EXECUTE PROCEDURE sys.tgf_insert_missing_updates( '
-		|| NEW.updtgt_id || ' )';
-	EXECUTE _query;
-
-	RETURN NEW;
-END;
-$tgf_updtgt_after_insert$;
-
-REVOKE EXECUTE
-	ON FUNCTION sys.tgf_updtgt_after_insert( )
-	FROM PUBLIC;
-
-CREATE TRIGGER tg_updtgt_after_insert
-	AFTER INSERT ON sys.update_targets
-	FOR EACH ROW EXECUTE PROCEDURE sys.tgf_updtgt_after_insert( );
-
-
-/*
- * Trigger function that deletes specific update tables
- * -----------------------------------------------------
- *
- * This trigger function is called after a row has been deleted from the
- * update target definitions table. It will destroy the corresponding table.
- */
-DROP FUNCTION IF EXISTS sys.tgf_updtgt_after_delete( );
-CREATE FUNCTION sys.tgf_updtgt_after_delete( )
-		RETURNS TRIGGER
-		LANGUAGE PLPGSQL
-		STRICT VOLATILE
-		SECURITY INVOKER
-	AS $tgf_updtgt_after_delete$
-DECLARE
-	_query	TEXT;
-BEGIN
-	_query := 'DROP TABLE "' || OLD.updtgt_schema || '"."' || OLD.updtgt_table || '_updates"';
-	EXECUTE _query;
-	RETURN NULL;
-END;
-$tgf_updtgt_after_delete$;
-
-REVOKE EXECUTE
-	ON FUNCTION sys.tgf_updtgt_after_delete( )
-	FROM PUBLIC;
-
-CREATE TRIGGER tg_updtgt_after_delete
-	AFTER DELETE ON sys.update_targets
-	FOR EACH ROW EXECUTE PROCEDURE sys.tgf_updtgt_after_delete( );
-
-
-
-/*
- * Stored update type registration
- * --------------------------------
- *
- * This function can be called to register an update type that uses a stored
- * procedure. The new update type is added at the end of the list of updates.
- * 
- * Since this function is meant to be used from the SQL definition code only,
- * it does not handle errors and will raise exceptions when something goes
- * wrong.
- * 
- * Parameters:
- *		_target			The name of the target for this update type
- *		_name			The name of the update type
- *		_description	The update type's description
- *		_proc			The name of the stored procedure
- */
-DROP FUNCTION IF EXISTS sys.register_update_type( TEXT , TEXT , TEXT , NAME );
-CREATE FUNCTION sys.register_update_type( _target TEXT , _name TEXT , _description TEXT , _proc NAME )
-		RETURNS VOID
-		LANGUAGE PLPGSQL
-		STRICT VOLATILE
-		SECURITY INVOKER
-	AS $register_update_type$
-
-DECLARE
-	_target_id		INT;
-	_max_ordering	INT;
-
-BEGIN
-	SELECT INTO _target_id updtgt_id
-		FROM sys.update_targets
-		WHERE updtgt_name = _target;
-
-	SELECT INTO _max_ordering MAX( updtype_ordering )
-		FROM sys.update_types;
-	IF _max_ordering IS NULL THEN
-		_max_ordering := 1;
-	END IF;
-
-	INSERT INTO sys.update_types(
-			updtgt_id , updtype_name , updtype_ordering ,
-			updtype_description , updtype_proc_name
-		) VALUES (
-			_target_id , _name , _max_ordering + 1 ,
-			_description , _proc
-		);
-END;
-$register_update_type$;
-
-
-REVOKE EXECUTE
-	ON FUNCTION sys.register_update_type( TEXT , TEXT , TEXT , NAME )
-	FROM PUBLIC;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/parts/040-functions/025-resources.sql b/legacyworlds-server-data/db-structure/parts/040-functions/025-resources.sql
deleted file mode 100644
index 4a7fa06..0000000
--- a/legacyworlds-server-data/db-structure/parts/040-functions/025-resources.sql
+++ /dev/null
@@ -1,563 +0,0 @@
--- LegacyWorlds Beta 6
--- PostgreSQL database scripts
---
--- Resource definitions management functions
---
--- Copyright(C) 2004-2011, DeepClone Development
--- --------------------------------------------------------
-
-/*
- * Return codes for resource creation or update functions.
- */
-DROP TYPE IF EXISTS defs.resource_update_result CASCADE;
-CREATE TYPE defs.resource_update_result
-	AS ENUM(
-		/* The resource definition was created */
-		'CREATED' ,
-
-		/* The resource definition was updated */
-		'UPDATED' ,
-
-		/* The resource definition already existed, and was either a basic
-		 * resource definition while the update required a natural resource,
-		 * or a natural resource definition when the update required a basic
-		 * resource.
-		 */
-		'BAD_TYPE' ,
-
-		/* The name, description or category string identifiers were not valid
-		 * string identifiers.
-		 */
-		'BAD_STRINGS' ,
-
-		/* One (or more) of the numeric parameters is invalid */
-		'BAD_VALUE' ,
-
-		/* The specified description was in use by another resource */
-		'DUP_DESCR'
-	);
-
-
-/*
- * Add a resource to all empire and planet records
- * 
- * This function makes sure that all empire and planet records have a row for
- * a newly-created resource.
- * 
- * Parameters:
- *		_resource		The identifier of the resource to add
- */
-DROP FUNCTION IF EXISTS defs.add_resource_records( INT );
-CREATE FUNCTION defs.add_resource_records( _resource INT )
-	RETURNS VOID
-	STRICT VOLATILE
-	SECURITY INVOKER
-AS $$
-
-	INSERT INTO emp.resources ( empire_id , resource_name_id )
-			SELECT name_id , $1 FROM emp.empires;
-
-	INSERT INTO verse.planet_resources ( planet_id , resource_name_id )
-			SELECT name_id , $1 FROM verse.planets;
-
-$$ LANGUAGE SQL;
-
-REVOKE EXECUTE
-	ON FUNCTION defs.add_resource_records( INT )
-	FROM PUBLIC;
-
-
-
-/*
- * Create or update a basic resource
- * 
- * /!\ INTERNAL FUNCTION /!\
- * 
- * This function is called by the variants of defs.uoc_resource() to actually
- * update or create the resource. It will make sure that all string
- * identifiers exist, then try to insert the resource. If that fails because
- * the resource already exists, make sure it's a basic resource then update
- * it.
- * 
- * Parameters:
- *		_name			the identifier of the resource's name
- *		_description	the identifier of the resource's description
- *		_category		the identifier of the resource's category, or NULL if
- *							the resource does not belong to a category
- *		_weight			the resource's ordering weight
- *
- * Returns:
- *		?				the result code for the operation
- */
-DROP FUNCTION IF EXISTS defs.uoc_resource_internal( TEXT , TEXT , TEXT , INT );
-CREATE FUNCTION defs.uoc_resource_internal(
-				_name TEXT ,
-				_description TEXT ,
-				_category TEXT ,
-				_weight INT )
-		RETURNS defs.resource_update_result
-		CALLED ON NULL INPUT
-		VOLATILE
-		SECURITY INVOKER
-	AS $$
-DECLARE
-	_ret		defs.resource_update_result;
-	_name_id	INT;
-	_desc_id	INT;
-	_cat_id		INT;
-BEGIN
-	-- Get all string identifiers
-	SELECT INTO _name_id id FROM defs.strings WHERE name = _name;
-	IF NOT FOUND THEN
-		RETURN 'BAD_STRINGS';
-	END IF;
-	SELECT INTO _desc_id id FROM defs.strings WHERE name = _description;
-	IF NOT FOUND THEN
-		RETURN 'BAD_STRINGS';
-	END IF;
-	IF _category IS NULL THEN
-		_cat_id := NULL;
-	ELSE
-		SELECT INTO _cat_id id FROM defs.strings WHERE name = _category;
-		IF NOT FOUND THEN
-			RETURN 'BAD_STRINGS';
-		END IF;
-	END IF;
-
-	-- Try inserting the record
-	BEGIN
-		INSERT INTO defs.resources (
-			resource_name_id , resource_description_id ,
-			resource_category_id , resource_weight
-		) VALUES (
-			_name_id , _desc_id , _cat_id , _weight
-		);
-
-		PERFORM defs.add_resource_records( _name_id );
-		RETURN 'CREATED';
-	EXCEPTION
-		WHEN unique_violation THEN
-			IF SQLERRM LIKE '%_description_%' THEN
-				RETURN 'DUP_DESCR';
-			END IF;
-	END;
-
-	-- Insertion failed, make sure the resource is a basic resource
-	PERFORM *
-		FROM defs.resources basic_res
-			LEFT OUTER JOIN defs.natural_resources nat_res
-				USING ( resource_name_id )
-		WHERE basic_res.resource_name_id = _name_id
-			AND nat_res.resource_name_id IS NULL
-		FOR UPDATE OF basic_res;
-	IF NOT FOUND THEN
-		RETURN 'BAD_TYPE';
-	END IF;
-
-	-- Update the resource
-	BEGIN
-		UPDATE defs.resources
-			SET resource_description_id = _desc_id ,
-				resource_category_id = _cat_id ,
-				resource_weight = _weight
-			WHERE resource_name_id = _name_id;
-		RETURN 'UPDATED';
-	EXCEPTION
-		WHEN unique_violation THEN
-			RETURN 'DUP_DESCR';
-	END;
-EXCEPTION
-	WHEN check_violation THEN
-		RETURN 'BAD_VALUE';
-END;
-$$ LANGUAGE PLPGSQL;
-
-REVOKE EXECUTE
-	ON FUNCTION defs.uoc_resource_internal( TEXT , TEXT , TEXT , INT )
-	FROM PUBLIC;
-
-
-
-/*
- * Update or create a basic resource definition with no category
- * 
- * Parameters:
- *		_name			the identifier of the resource's name
- *		_description	the identifier of the resource's description
- *		_weight			the resource's ordering weight
- *
- * Returns:
- *		?				the result code for the operation
- */
-DROP FUNCTION IF EXISTS defs.uoc_resource( TEXT , TEXT , INT );
-CREATE FUNCTION defs.uoc_resource(
-			_name TEXT ,
-			_description TEXT ,
-			_weight INT )
-	RETURNS defs.resource_update_result
-	STRICT
-	VOLATILE
-	SECURITY DEFINER
-AS $$
-	SELECT defs.uoc_resource_internal( $1 , $2 , NULL , $3 );
-$$ LANGUAGE SQL;
-
-REVOKE EXECUTE
-	ON FUNCTION defs.uoc_resource( TEXT , TEXT , INT )
-	FROM PUBLIC;
-GRANT EXECUTE
-	ON FUNCTION defs.uoc_resource( TEXT , TEXT , INT )
-	TO :dbuser;
-
-
-
-/*
- * Update or create a basic resource definition with a category
- * 
- * Parameters:
- *		_name			the identifier of the resource's name
- *		_description	the identifier of the resource's description
- *		_category		the identifier of the resource's category
- *		_weight			the resource's ordering weight
- *
- * Returns:
- *		?				the result code for the operation
- */
-DROP FUNCTION IF EXISTS defs.uoc_resource( TEXT , TEXT , TEXT , INT );
-CREATE FUNCTION defs.uoc_resource(
-			_name TEXT ,
-			_description TEXT ,
-			_category TEXT ,
-			_weight INT )
-	RETURNS defs.resource_update_result
-	STRICT
-	VOLATILE
-	SECURITY DEFINER
-AS $$
-	SELECT defs.uoc_resource_internal( $1 , $2 , $3 , $4 );
-$$ LANGUAGE SQL;
-
-REVOKE EXECUTE
-	ON FUNCTION defs.uoc_resource( TEXT , TEXT , TEXT , INT )
-	FROM PUBLIC;
-GRANT EXECUTE
-	ON FUNCTION defs.uoc_resource( TEXT , TEXT , TEXT , INT )
-	TO :dbuser;
-
-
-
-/*
- * Create or update a natural resource
- * 
- * /!\ INTERNAL FUNCTION /!\
- * 
- * This function is called by the variants of defs.uoc_natural_resource() to
- * actually update or create the resource. It will make sure that all string
- * identifiers exist, then try to insert the resource. If that fails because
- * the resource already exists, make sure it's a natural resource then update
- * it.
- * 
- * Parameters:
- *		_name			the identifier of the resource's name
- *		_description	the identifier of the resource's description
- *		_category		the identifier of the resource's category, or NULL if
- *							the resource does not belong to a category
- *		_weight			the resource's ordering weight
- *		_presence		the presence probability
- *		_quantity_avg	the average quantity
- *		_quantity_dev	the deviation from the average quantity
- *		_difficulty_avg	the average extraction difficulty
- *		_difficulty_dev	the deviation from the average extraction difficulty
- *		_recovery_avg	the average recovery rate
- *		_recovery_dev	the deviation from the average recovery rate
- *
- * Returns:
- *		?				the result code for the operation
- */
-DROP FUNCTION IF EXISTS defs.uoc_natres_internal( TEXT ,  TEXT , TEXT , INT ,
-			DOUBLE PRECISION , DOUBLE PRECISION , DOUBLE PRECISION ,
-			DOUBLE PRECISION , DOUBLE PRECISION , DOUBLE PRECISION ,
-			DOUBLE PRECISION );
-CREATE FUNCTION defs.uoc_natres_internal(
-				_name TEXT ,
-				_description TEXT ,
-				_category TEXT ,
-				_weight INT ,
-				_presence DOUBLE PRECISION ,
-				_quantity_avg DOUBLE PRECISION ,
-				_quantity_dev DOUBLE PRECISION ,
-				_difficulty_avg DOUBLE PRECISION ,
-				_difficulty_dev DOUBLE PRECISION ,
-				_recovery_avg DOUBLE PRECISION ,
-				_recovery_dev DOUBLE PRECISION )
-		RETURNS defs.resource_update_result
-		CALLED ON NULL INPUT
-		VOLATILE
-		SECURITY INVOKER
-	AS $$
-DECLARE
-	_ret		defs.resource_update_result;
-	_name_id	INT;
-	_desc_id	INT;
-	_cat_id		INT;
-	_inserted	BOOLEAN;
-BEGIN
-	-- Get all string identifiers
-	SELECT INTO _name_id id FROM defs.strings WHERE name = _name;
-	IF NOT FOUND THEN
-		RETURN 'BAD_STRINGS';
-	END IF;
-	SELECT INTO _desc_id id FROM defs.strings WHERE name = _description;
-	IF NOT FOUND THEN
-		RETURN 'BAD_STRINGS';
-	END IF;
-	IF _category IS NULL THEN
-		_cat_id := NULL;
-	ELSE
-		SELECT INTO _cat_id id FROM defs.strings WHERE name = _category;
-		IF NOT FOUND THEN
-			RETURN 'BAD_STRINGS';
-		END IF;
-	END IF;
-
-	-- Try inserting the basic record
-	BEGIN
-		INSERT INTO defs.resources (
-			resource_name_id , resource_description_id ,
-			resource_category_id , resource_weight
-		) VALUES (
-			_name_id , _desc_id , _cat_id , _weight
-		);
-		_inserted := TRUE;
-	EXCEPTION
-		WHEN unique_violation THEN
-			IF SQLERRM LIKE '%_description_%' THEN
-				RETURN 'DUP_DESCR';
-			END IF;
-		_inserted := FALSE;
-	END;
-
-	-- If insertion succeeded, insert the rest of the record
-	IF _inserted THEN
-		INSERT INTO defs.natural_resources(
-			resource_name_id , natres_p_presence ,
-			natres_quantity_avg , natres_quantity_dev ,
-			natres_difficulty_avg , natres_difficulty_dev ,
-			natres_recovery_avg , natres_recovery_dev
-		) VALUES (
-			_name_id , _presence ,
-			_quantity_avg , _quantity_dev ,
-			_difficulty_avg , _difficulty_dev ,
-			_recovery_avg , _recovery_dev
-		);
-
-		PERFORM defs.add_resource_records( _name_id );
-		RETURN 'CREATED';
-	END IF;
-
-	-- Insertion failed, make sure it is a natural resource
-	PERFORM *
-		FROM defs.resources basic_res
-			INNER JOIN defs.natural_resources nat_res
-				USING ( resource_name_id )
-		WHERE basic_res.resource_name_id = _name_id
-		FOR UPDATE;
-	IF NOT FOUND THEN
-		RETURN 'BAD_TYPE';
-	END IF;
-
-	-- Update the resource
-	BEGIN
-		UPDATE defs.resources
-			SET resource_description_id = _desc_id ,
-				resource_category_id = _cat_id ,
-				resource_weight = _weight
-			WHERE resource_name_id = _name_id;
-		UPDATE defs.natural_resources
-			SET natres_p_presence = _presence ,
-				natres_quantity_avg = _quantity_avg ,
-				natres_quantity_dev = _quantity_dev ,
-				natres_difficulty_avg = _difficulty_avg ,
-				natres_difficulty_dev = _difficulty_dev ,
-				natres_recovery_avg = _recovery_avg ,
-				natres_recovery_dev = _recovery_dev
-			WHERE resource_name_id = _name_id;
-		RETURN 'UPDATED';
-	EXCEPTION
-		WHEN unique_violation THEN
-			RETURN 'DUP_DESCR';
-	END;
-EXCEPTION
-	WHEN check_violation THEN
-		RETURN 'BAD_VALUE';
-END;
-$$ LANGUAGE PLPGSQL;
-
-REVOKE EXECUTE
-	ON FUNCTION defs.uoc_natres_internal( TEXT ,  TEXT , TEXT , INT ,
-			DOUBLE PRECISION , DOUBLE PRECISION , DOUBLE PRECISION ,
-			DOUBLE PRECISION , DOUBLE PRECISION , DOUBLE PRECISION ,
-			DOUBLE PRECISION )
-	FROM PUBLIC;
-
-
-
-/*
- * Create or update a natural resource with no category
- * 
- * Parameters:
- *		_name			the identifier of the resource's name
- *		_description	the identifier of the resource's description
- *		_weight			the resource's ordering weight
- *		_presence		the presence probability
- *		_quantity_avg	the average quantity
- *		_quantity_dev	the deviation from the average quantity
- *		_difficulty_avg	the average extraction difficulty
- *		_difficulty_dev	the deviation from the average extraction difficulty
- *		_recovery_avg	the average recovery rate
- *		_recovery_dev	the deviation from the average recovery rate
- *
- * Returns:
- *		?				the result code for the operation
- */
-CREATE OR REPLACE FUNCTION defs.uoc_natural_resource(
-			_name TEXT ,
-			_description TEXT ,
-			_weight INT ,
-			_presence DOUBLE PRECISION ,
-			_quantity_avg DOUBLE PRECISION ,
-			_quantity_dev DOUBLE PRECISION ,
-			_difficulty_avg DOUBLE PRECISION ,
-			_difficulty_dev DOUBLE PRECISION ,
-			_recovery_avg DOUBLE PRECISION ,
-			_recovery_dev DOUBLE PRECISION )
-	RETURNS defs.resource_update_result
-	STRICT VOLATILE
-	SECURITY DEFINER
-AS $$
-	SELECT defs.uoc_natres_internal( $1 , $2 , NULL , $3 , $4 , $5 , $6 , $7 ,
-		$8 , $9 , $10 );
-$$ LANGUAGE SQL;
-
-REVOKE EXECUTE
-	ON FUNCTION defs.uoc_natural_resource( TEXT ,  TEXT , INT ,
-			DOUBLE PRECISION , DOUBLE PRECISION , DOUBLE PRECISION ,
-			DOUBLE PRECISION , DOUBLE PRECISION , DOUBLE PRECISION ,
-			DOUBLE PRECISION )
-	FROM PUBLIC;
-GRANT EXECUTE
-	ON FUNCTION defs.uoc_natural_resource( TEXT ,  TEXT , INT ,
-			DOUBLE PRECISION , DOUBLE PRECISION , DOUBLE PRECISION ,
-			DOUBLE PRECISION , DOUBLE PRECISION , DOUBLE PRECISION ,
-			DOUBLE PRECISION )
-	TO :dbuser;
-
-
-
-/*
- * Create or update a natural resource with a category
- * 
- * Parameters:
- *		_name			the identifier of the resource's name
- *		_description	the identifier of the resource's description
- *		_category		the identifier of the resource's category
- *		_weight			the resource's ordering weight
- *		_presence		the presence probability
- *		_quantity_avg	the average quantity
- *		_quantity_dev	the deviation from the average quantity
- *		_difficulty_avg	the average extraction difficulty
- *		_difficulty_dev	the deviation from the average extraction difficulty
- *		_recovery_avg	the average recovery rate
- *		_recovery_dev	the deviation from the average recovery rate
- *
- * Returns:
- *		?				the result code for the operation
- */
-CREATE OR REPLACE FUNCTION defs.uoc_natural_resource(
-			_name TEXT ,
-			_description TEXT ,
-			_category TEXT ,
-			_weight INT ,
-			_presence DOUBLE PRECISION ,
-			_quantity_avg DOUBLE PRECISION ,
-			_quantity_dev DOUBLE PRECISION ,
-			_difficulty_avg DOUBLE PRECISION ,
-			_difficulty_dev DOUBLE PRECISION ,
-			_recovery_avg DOUBLE PRECISION ,
-			_recovery_dev DOUBLE PRECISION )
-	RETURNS defs.resource_update_result
-	STRICT VOLATILE
-	SECURITY DEFINER
-AS $$
-	SELECT defs.uoc_natres_internal( $1 , $2 , $3 , $4 , $5 , $6 , $7 , $8 ,
-		$9 , $10 , $11 );
-$$ LANGUAGE SQL;
-
-REVOKE EXECUTE
-	ON FUNCTION defs.uoc_natural_resource( TEXT ,  TEXT , TEXT , INT ,
-			DOUBLE PRECISION , DOUBLE PRECISION , DOUBLE PRECISION ,
-			DOUBLE PRECISION , DOUBLE PRECISION , DOUBLE PRECISION ,
-			DOUBLE PRECISION )
-	FROM PUBLIC;
-GRANT EXECUTE
-	ON FUNCTION defs.uoc_natural_resource( TEXT , TEXT , TEXT , INT ,
-			DOUBLE PRECISION , DOUBLE PRECISION , DOUBLE PRECISION ,
-			DOUBLE PRECISION , DOUBLE PRECISION , DOUBLE PRECISION ,
-			DOUBLE PRECISION )
-	TO :dbuser;
-
-
-
-/*
- * View of resource category weights
- * 
- * This view computes the average resource weight per category for all
- * resource definitions.
- * 
- * Fields:
- *		resource_category_id		The category's identifier
- *		resource_category_weight	The average weight of resource defintions
- *										in the category.
- */
-DROP VIEW IF EXISTS defs.resource_category_weight_view CASCADE;
-CREATE VIEW defs.resource_category_weight_view
-	AS SELECT resource_category_id ,
-				AVG( resource_weight ) AS resource_category_weight
-			FROM defs.resources
-			WHERE resource_category_id IS NOT NULL
-			GROUP BY resource_category_id;
-
-
-
-/*
- * Ordered resource definitions
- * 
- * This view contains the name, category and description identifier for all
- * resource definitions, ordered based on the category's average weight and
- * the resource's own weight.
- * 
- * Fields:
- *		resource_name_id		The identifier of the resource's name
- *		resource_category_id	The identifier of the category's name, or NULL
- *									if the resource is not in a category
- *		resource_description_id	The identifier of the resource's description
- *		resource_ordering		The index of the resource in a sorted view
- */
-DROP VIEW IF EXISTS defs.ordered_resources_view CASCADE;
-CREATE VIEW defs.ordered_resources_view
-	AS SELECT resource_name_id , resource_category_id , resource_description_id ,
-				row_number( ) OVER(
-					ORDER BY (
-						CASE
-							WHEN resource_category_id IS NULL THEN
-								resource_weight
-							ELSE
-								resource_category_weight
-						END ) , resource_weight
-				) AS resource_ordering
-
-			FROM defs.resources
-				LEFT OUTER JOIN defs.resource_category_weight_view
-					USING ( resource_category_id )
-			
-			;
diff --git a/legacyworlds-server-data/db-structure/parts/040-functions/026-technology-dependencies.sql b/legacyworlds-server-data/db-structure/parts/040-functions/026-technology-dependencies.sql
deleted file mode 100644
index 0a1fc41..0000000
--- a/legacyworlds-server-data/db-structure/parts/040-functions/026-technology-dependencies.sql
+++ /dev/null
@@ -1,337 +0,0 @@
--- LegacyWorlds Beta 6
--- PostgreSQL database scripts
---
--- Functions and triggers that maintain the technology
--- dependency cache and, generally speaking, the integrity
--- of the technology graph.
---
--- Copyright(C) 2004-2012, DeepClone Development
--- --------------------------------------------------------
-
-
-/*
- * Dependency tree copy function
- * ------------------------------
- * 
- * This function is used when a dependency is added. It allows a dependency
- * tree to be copied as the child of another node on a different tree.
- *
- * Parameters:
- *		_reverse		Whether the tree being copied is a reverse or
- *							forward dependency tree
- *		_src			Identifier of the source tree
- *		_dest			Identifier of the destination tree
- *		_cache			Identifier of the cache entry to use as a parent
- *		_depth			Depth of the parent node
- *		_dependency		Identifier of the dependency being added
- */
-DROP FUNCTION IF EXISTS defs.tdcache_copy_tree(
-		BOOLEAN , INT , INT , INT , INT , INT ) CASCADE;
-CREATE FUNCTION defs.tdcache_copy_tree(
-			_reverse	BOOLEAN ,
-			_src		INT ,
-			_dest		INT ,
-			_cache		INT ,
-			_depth		INT ,
-			_dependency	INT )
-		RETURNS VOID
-		LANGUAGE PLPGSQL
-		STRICT VOLATILE
-	AS $tdcache_copy_tree$
-
-DECLARE
-	_record		RECORD;
-	_new_entry	INT;
-
-BEGIN
-	CREATE TEMPORARY TABLE tdcache_copy_ids(
-		old_id	INT ,
-		new_id	INT
-	);
-
-	FOR _record IN
-		SELECT * FROM defs.techdep_cache
-			WHERE technology_name_id = _src
-				AND tdcache_reverse = _reverse
-			ORDER BY tdcache_depth ASC
-	LOOP
-		-- Set source of copy
-		IF _record.tdcache_id_copyof IS NULL THEN
-			_record.technology_name_id_copyof := _src;
-			_record.tdcache_id_copyof := _record.tdcache_id;
-		END IF;
-
-		IF _record.tdcache_id_parent IS NULL THEN
-			-- Set parent and dependency if there is none
-			_record.tdcache_id_parent := _cache;
-			_record.techdep_id := _dependency;
-		ELSE
-			-- Remap child nodes to the tree's copy
-			SELECT INTO _record.tdcache_id_parent new_id
-				FROM tdcache_copy_ids
-				WHERE old_id = _record.tdcache_id_parent;
-		END IF;
-
-		-- Set depth
-		_record.tdcache_depth := _record.tdcache_depth + _depth;
-
-		-- Insert new cache entry and add mapping to temporary table
-		INSERT INTO defs.techdep_cache(
-				technology_name_id , tdcache_reverse , tdcache_id_parent ,
-				tdcache_depth , technology_name_id_copyof ,
-				tdcache_id_copyof , techdep_id
-			) VALUES (
-				_dest , _reverse , _record.tdcache_id_parent ,
-				_record.tdcache_depth , _record.technology_name_id_copyof ,
-				_record.tdcache_id_copyof , _record.techdep_id
-			) RETURNING tdcache_id INTO _new_entry;
-
-		INSERT INTO tdcache_copy_ids
-			VALUES ( _record.tdcache_id , _new_entry );
-	END LOOP;
-
-	DROP TABLE tdcache_copy_ids;
-END;
-$tdcache_copy_tree$;
-
-REVOKE EXECUTE
-	ON FUNCTION defs.tdcache_copy_tree(
-			BOOLEAN , INT , INT , INT , INT , INT )
-	FROM PUBLIC;
-
-
-
-/*
- * Add a sub-tree to all copies of some node
- * ------------------------------------------
- * 
- * This function copies a source tree to all copies for a given technology and
- * direction.
- * 
- * Parameters:
- *		_reverse	Whether the tree being copied represents reverse or
- *						forward dependencies
- *		_src		The identifier of the technology whose dependency tree
- *						needs to be copied
- *		_dest		The identifier of the technology onto which the source
- *						tree is to be grafted
- *		_dependency	The identifier of the dependency because of which the
- *						copy is being carried out
- */
-DROP FUNCTION IF EXISTS defs.tdcache_set_child( BOOLEAN , INT , INT , INT );
-CREATE FUNCTION defs.tdcache_set_child(
-			_reverse	BOOLEAN ,
-			_src		INT ,
-			_dest		INT ,
-			_dependency	INT )
-		RETURNS VOID
-		LANGUAGE PLPGSQL
-		STRICT VOLATILE
-	AS $tdcache_set_child$
-
-DECLARE
-	_tree	INT;
-	_entry	INT;
-	_depth	INT;
-
-BEGIN
-	FOR _tree , _entry , _depth IN
-		SELECT technology_name_id , tdcache_id , tdcache_depth + 1
-			FROM defs.techdep_cache
-			WHERE tdcache_reverse = _reverse
-				AND technology_name_id_copyof = _dest
-	LOOP
-		PERFORM defs.tdcache_copy_tree( _reverse , _src , _tree , _entry , _depth , _dependency );
-	END LOOP;
-
-END;
-$tdcache_set_child$;
-
-REVOKE EXECUTE
-	ON FUNCTION defs.tdcache_set_child( BOOLEAN , INT , INT , INT )
-	FROM PUBLIC;
-
-
-
-/*
- * Trigger function that handles new technology definitions
- * ---------------------------------------------------------
- * 
- * When a new technology definition is added, a pair of records needs to be
- * inserted into the dependency cache. These records correspond to the root
- * of the trees for the technology for both forward and reverse dependencies.
- */
-DROP FUNCTION IF EXISTS defs.tgf_technologies_ai( ) CASCADE;
-CREATE FUNCTION defs.tgf_technologies_ai( )
-		RETURNS TRIGGER
-		LANGUAGE PLPGSQL
-		STRICT VOLATILE
-		SECURITY DEFINER
-	AS $tgf_technologies_ai$
-BEGIN
-
-	INSERT INTO defs.techdep_cache (
-			technology_name_id , tdcache_reverse , tdcache_depth , technology_name_id_copyof
-		) VALUES (
-			NEW.technology_name_id , FALSE , 0 , NEW.technology_name_id
-		) , (
-			NEW.technology_name_id , TRUE , 0 , NEW.technology_name_id
-		);
-	RETURN NEW;
-
-END;
-$tgf_technologies_ai$;
-
-REVOKE EXECUTE
-	ON FUNCTION defs.tgf_technologies_ai()
-	FROM PUBLIC;
-
-CREATE TRIGGER tg_technologies_ai
-	AFTER INSERT ON defs.technologies
-		FOR EACH ROW EXECUTE PROCEDURE defs.tgf_technologies_ai( );
-
-
-
-/*
- * Trigger function that verifies new dependencies
- * ------------------------------------------------
- *
- * This trigger function locks all related trees, then check that the new
- * dependency does not lead to cycles or redundant dependencies.
- */
-DROP FUNCTION IF EXISTS defs.tgf_techdeps_bi( ) CASCADE;
-CREATE FUNCTION defs.tgf_techdeps_bi( )
-		RETURNS TRIGGER
-		LANGUAGE PLPGSQL
-		STRICT VOLATILE
-		SECURITY DEFINER
-	AS $tgf_techdeps_bi$
-BEGIN
-	-- Lock all trees
-	PERFORM 1
-		FROM defs.techdep_cache n1
-			INNER JOIN defs.techdep_cache n2
-				USING ( technology_name_id )
-		WHERE n1.technology_name_id_copyof IN (
-				NEW.technology_name_id , NEW.technology_name_id_depends )
-		FOR UPDATE OF n2;
-
-	-- Check for cycles
-	PERFORM 1 FROM defs.techdep_cache
-		WHERE technology_name_id = NEW.technology_name_id
-			AND technology_name_id_copyof = NEW.technology_name_id_depends
-			AND tdcache_reverse;
-	IF FOUND THEN
-		RAISE EXCEPTION 'Cycle detected'
-			USING ERRCODE = 'check_violation';
-	END IF;
-
-	-- Check for redundant dependencies
-	PERFORM  1
-		FROM defs.techdep_cache n1
-			INNER JOIN defs.technology_dependencies d
-				ON d.technology_name_id = n1.technology_name_id_copyof
-		WHERE n1.technology_name_id = NEW.technology_name_id
-			AND n1.tdcache_reverse
-			AND d.technology_name_id_depends = NEW.technology_name_id_depends;
-	IF FOUND THEN
-		RAISE EXCEPTION '% is a dependency of a technology that depends on %' ,
-				NEW.technology_name_id_depends , NEW.technology_name_id
-			USING ERRCODE = 'check_violation';
-	END IF;
-
-	PERFORM 1
-		FROM defs.technology_dependencies d1
-			INNER JOIN defs.techdep_cache n
-				ON n.technology_name_id = d1.technology_name_id_depends
-		WHERE d1.technology_name_id = NEW.technology_name_id
-			AND n.tdcache_reverse
-			AND n.technology_name_id_copyof = NEW.technology_name_id_depends;
-	IF FOUND THEN
-		RAISE EXCEPTION '% depends on a dependency of %' ,
-				NEW.technology_name_id , NEW.technology_name_id_depends
-			USING ERRCODE = 'check_violation';
-	END IF;
-
-	PERFORM 1 FROM defs.techdep_cache
-		WHERE technology_name_id = NEW.technology_name_id
-			AND technology_name_id_copyof = NEW.technology_name_id_depends
-			AND NOT tdcache_reverse;
-	IF FOUND THEN
-		RAISE EXCEPTION '% is already a dependency of %' ,
-				NEW.technology_name_id_depends , NEW.technology_name_id
-			USING ERRCODE = 'check_violation';
-	END IF;
-
-	RETURN NEW;
-END;
-$tgf_techdeps_bi$;
-
-
-CREATE TRIGGER tg_techdeps_bi
-	BEFORE INSERT ON defs.technology_dependencies
-		FOR EACH ROW EXECUTE PROCEDURE defs.tgf_techdeps_bi( );
-
-REVOKE EXECUTE
-	ON FUNCTION defs.tgf_techdeps_bi( )
-	FROM PUBLIC;
-
-
-/*
- * Trigger function that updates the dependency cache
- * ---------------------------------------------------
- * 
- * After a new, valid dependency has been added, trees for both forward and
- * reverse depdencies must be copied.
- */
-DROP FUNCTION IF EXISTS defs.tgf_techdeps_ai( ) CASCADE;
-CREATE FUNCTION defs.tgf_techdeps_ai( )
-		RETURNS TRIGGER
-		LANGUAGE PLPGSQL
-		STRICT VOLATILE
-		SECURITY DEFINER
-	AS $tgf_techdeps_ai$
-BEGIN
-
-	PERFORM defs.tdcache_set_child( FALSE ,
-		NEW.technology_name_id_depends , NEW.technology_name_id ,
-		NEW.techdep_id );
-
-	PERFORM defs.tdcache_set_child( TRUE ,
-		NEW.technology_name_id , NEW.technology_name_id_depends ,
-		NEW.techdep_id );
-
-	RETURN NEW;
-END;
-$tgf_techdeps_ai$;
-
-CREATE TRIGGER tg_techdeps_ai
-	AFTER INSERT ON defs.technology_dependencies
-		FOR EACH ROW EXECUTE PROCEDURE defs.tgf_techdeps_ai( );
-
-REVOKE EXECUTE
-	ON FUNCTION defs.tgf_techdeps_ai( )
-	FROM PUBLIC;
-
-
-/*
- * Technology dependencies view
- * -----------------------------
- * 
- * This view generates a parseable list of dependencies per technology.
- * 
- * Columns:
- *		technology_name_id		The technology's name
- *		technology_dependencies	A list of comma-separated technology name
- *									identifiers
- */
-DROP VIEW IF EXISTS defs.technology_dependencies_view CASCADE;
-CREATE VIEW defs.technology_dependencies_view
-	AS SELECT technology_name_id ,
-			array_to_string( array_agg( _name_str.name ) , ',' ) AS technology_dependencies
-		FROM defs.technologies _tech
-			LEFT OUTER JOIN defs.technology_dependencies
-				USING ( technology_name_id )
-			LEFT OUTER JOIN defs.strings _name_str
-				ON _name_str.id = technology_name_id_depends
-		GROUP BY technology_name_id;
diff --git a/legacyworlds-server-data/db-structure/parts/040-functions/030-tech.sql b/legacyworlds-server-data/db-structure/parts/040-functions/030-tech.sql
deleted file mode 100644
index d5779bb..0000000
--- a/legacyworlds-server-data/db-structure/parts/040-functions/030-tech.sql
+++ /dev/null
@@ -1,670 +0,0 @@
--- LegacyWorlds Beta 6
--- PostgreSQL database scripts
---
--- Functions and views for technologies and buildables
---
--- Copyright(C) 2004-2010, DeepClone Development
--- --------------------------------------------------------
-
-
-/*
- * Return type for technology management functions
- * ------------------------------------------------
- * 
- * This enumerated type is used for the return values of all technology
- * management functions. This includes defs.uoc_technology() of course,
- * but also defs.techdep_add() and defs.techdep_remove().
- */
-DROP TYPE IF EXISTS defs.technology_update_result CASCADE;
-CREATE TYPE defs.technology_update_result
-	AS ENUM(
-		/* The technology definition or dependency was created */
-		'CREATED' ,
-
-		/* The technology definition was updated */
-		'UPDATED' ,
-		
-		/* The dependency was deleted */
-		'DELETED' ,
-		
-		/* The specified dependency does not exist */
-		'MISSING' ,
-
-		/* One (or more) of the numeric parameters is invalid */
-		'BAD_VALUE' ,
-
-		/* The name, description, discovery or category string identifiers
-		 * were not valid string identifiers.
-		 */
-		'BAD_STRINGS' ,
-
-		/* The specified description and/or discovery string was in use by
-		 * another technology.
-		 */
-		'DUP_STRING' ,
-		
-		/* The dependency would cause a cycle */
-		'CYCLE' ,
-		
-		/* The dependency would be redundant */
-		'REDUNDANT'
-	);
-
-
-/*
- * Update or create a technology definition
- * -----------------------------------------
- *
- * This stored procedure can be used to update existing technology definitions
- * or create new records. It will not affect technology dependencies: no
- * depedencies will be added when creating a new technology, and existing
- * dependencies will be conserved when updating.
- * 
- * If a technology already exists, check for empires researching that
- * technology, and scale their current progress accordingly.
- * 
- * Parameters:
- *		_name			Text identifier of the name string
- *		_category		Text identifier of the category string
- *		_discovery		Text identifier of the discovery string
- *		_description	Text identifier of the description string
- *		_price			Monetary cost to implement the technology
- *		_points			Amount of points required to research teh technology
- *
- * Returns:
- *		?				One of the following return codes: CREATED, UPDATED,
- *							BAD_VALUE, BAD_STRINGS, DUP_STRING
- */
-DROP FUNCTION IF EXISTS defs.uoc_technology(
-		TEXT , TEXT , TEXT , TEXT , BIGINT , BIGINT ) CASCADE;
-CREATE FUNCTION defs.uoc_technology(
-			_name			TEXT ,
-			_category		TEXT ,
-			_discovery		TEXT ,
-			_description	TEXT ,
-			_price			BIGINT ,
-			_points			BIGINT )
-		RETURNS defs.technology_update_result
-		LANGUAGE PLPGSQL
-		STRICT VOLATILE
-		SECURITY DEFINER
-	AS $uoc_technology$
-
-DECLARE
-	_name_id	INT;
-	_disc_id	INT;
-	_desc_id	INT;
-	_cat_id		INT;
-	_old_points	BIGINT;
-	_multi		DOUBLE PRECISION;
-
-BEGIN
-	-- Get all string identifiers
-	SELECT INTO _name_id id FROM defs.strings WHERE name = _name;
-	IF NOT FOUND THEN
-		RETURN 'BAD_STRINGS';
-	END IF;
-	SELECT INTO _desc_id id FROM defs.strings WHERE name = _description;
-	IF NOT FOUND THEN
-		RETURN 'BAD_STRINGS';
-	END IF;
-	SELECT INTO _disc_id id FROM defs.strings WHERE name = _discovery;
-	IF NOT FOUND THEN
-		RETURN 'BAD_STRINGS';
-	END IF;
-	SELECT INTO _cat_id id FROM defs.strings WHERE name = _category;
-	IF NOT FOUND THEN
-		RETURN 'BAD_STRINGS';
-	END IF;
-
-	-- Try inserting the record
-	BEGIN
-		INSERT INTO defs.technologies (
-			technology_name_id , technology_category_id ,
-			technology_discovery_id , technology_description_id ,
-			technology_price , technology_points
-		) VALUES (
-			_name_id , _cat_id ,
-			_disc_id , _desc_id ,
-			_price , _points
-		);
-		RETURN 'CREATED';
-	EXCEPTION
-		WHEN unique_violation THEN
-			-- Continue, we can't determine which error this
-			-- was about at this point.
-	END;
-	
-	-- Lock existing definition and empire research records
-	PERFORM 1
-		FROM defs.technologies _def
-			LEFT OUTER JOIN (
-					SELECT technology_name_id
-						FROM emp.technologies _tech
-						WHERE technology_name_id = _name_id
-								AND emptech_state = 'RESEARCH'
-						FOR UPDATE OF _tech
-				) _emps USING ( technology_name_id )
-		WHERE technology_name_id = _name_id
-		FOR UPDATE OF _def;
-	IF NOT FOUND THEN
-		RETURN 'DUP_STRING';
-	END IF;
-	
-	-- Get old value for research points
-	SELECT INTO _old_points technology_points
-		FROM defs.technologies
-		WHERE technology_name_id = _name_id;
-
-	-- Update the record
-	BEGIN
-		UPDATE defs.technologies
-			SET technology_category_id = _cat_id ,
-				technology_discovery_id = _disc_id ,
-				technology_description_id = _desc_id ,
-				technology_price = _price ,
-				technology_points = _points
-			WHERE technology_name_id = _name_id;
-	EXCEPTION
-		WHEN unique_violation THEN
-			RETURN 'DUP_STRING';
-	END;
-	
-	-- Update empire research if necessary
-	IF _old_points <> _points THEN
-		_multi := _points::DOUBLE PRECISION / _old_points::DOUBLE PRECISION;
-		UPDATE emp.technologies
-			SET emptech_points = emptech_points * _multi
-			WHERE technology_name_id = _name_id
-				AND emptech_points IS NOT NULL;
-	END IF;
-
-	RETURN 'UPDATED';
-
-EXCEPTION
-	WHEN check_violation THEN
-		RETURN 'BAD_VALUE';
-
-END;
-$uoc_technology$;
-
-REVOKE EXECUTE
-	ON FUNCTION defs.uoc_technology(
-		TEXT , TEXT , TEXT , TEXT , BIGINT , BIGINT )
-	FROM PUBLIC;
-GRANT EXECUTE
-	ON FUNCTION defs.uoc_technology(
-		TEXT , TEXT , TEXT , TEXT , BIGINT , BIGINT )
-	TO :dbuser;
-
-
-
-/*
- * Add a technology dependency
- * ----------------------------
- * 
- * This stored procedure attempts to create a dependency between two
- * technologies by looking them up by name then inserting the pair in the
- * dependency table.
- *
- * Parameters:
- *		_dependent		The name of the dependent technology
- *		_dependency		The name of the dependency
- *
- * Returns:
- * 		?				One of the following return codes: CREATED,
- *							BAD_STRINGS, CYCLE, REDUNDANT
- */
-DROP FUNCTION IF EXISTS defs.techdep_add( TEXT , TEXT );
-CREATE FUNCTION defs.techdep_add( _dependent TEXT , _dependency TEXT )
-		RETURNS defs.technology_update_result
-		LANGUAGE PLPGSQL
-		STRICT VOLATILE
-		SECURITY DEFINER
-	AS $techdep_add$
-
-DECLARE
-	_tech1_id	INT;
-	_tech2_id	INT;
-
-BEGIN
-	
-	SELECT INTO _tech1_id , _tech2_id _str1.id , _str2.id
-		FROM defs.strings _str1
-			CROSS JOIN defs.strings _str2
-		WHERE _str1.name = _dependent
-			AND _str2.name = _dependency;
-	IF NOT FOUND THEN
-		RETURN 'BAD_STRINGS';
-	END IF;
-	
-	INSERT INTO defs.technology_dependencies (
-			technology_name_id , technology_name_id_depends
-		) VALUES ( _tech1_id , _tech2_id );
-	RETURN 'CREATED';
-
-EXCEPTION
-
-	WHEN foreign_key_violation THEN
-		RETURN 'BAD_STRINGS';
-
-	WHEN unique_violation THEN
-		RETURN 'REDUNDANT';
-
-	WHEN check_violation THEN
-		IF SQLERRM LIKE '%Cycle detected%' THEN
-			RETURN 'CYCLE';
-		END IF;
-		RETURN 'REDUNDANT';
-
-END;
-$techdep_add$;
-
-REVOKE EXECUTE
-	ON FUNCTION defs.techdep_add( TEXT , TEXT )
-	FROM PUBLIC;
-GRANT EXECUTE
-	ON FUNCTION defs.techdep_add( TEXT , TEXT )
-	TO :dbuser;
-
-
-
-/*
- * Remove a technology dependency
- * -------------------------------
- * 
- * This stored procedure removes a dependency from a technology to another.
- * 
- * Parameters:
- *		_dependent		The name of the dependent technology
- *		_dependency		The name of the dependency
- *
- * Returns:
- * 		?				One of the following return codes: DELETED, MISSING
- */
-DROP FUNCTION IF EXISTS defs.techdep_remove( TEXT , TEXT );
-CREATE FUNCTION defs.techdep_remove( _dependent TEXT , _dependency TEXT )
-		RETURNS defs.technology_update_result
-		LANGUAGE PLPGSQL
-		STRICT VOLATILE
-		SECURITY DEFINER
-	AS $techdep_remove$
-
-DECLARE
-	_dep_id		INT;
-
-BEGIN
-	
-	SELECT INTO _dep_id techdep_id
-		FROM defs.technology_dependencies _td
-			INNER JOIN defs.strings _str1
-				ON _str1.id = _td.technology_name_id
-			INNER JOIN defs.strings _str2
-				ON _str2.id = _td.technology_name_id_depends
-		WHERE _str1.name = _dependent
-			AND _str2.name = _dependency
-		FOR UPDATE OF _td;
-	IF NOT FOUND THEN
-		RETURN 'MISSING';
-	END IF;
-
-	DELETE FROM defs.technology_dependencies
-		WHERE techdep_id = _dep_id;
-	RETURN 'DELETED';
-
-END;
-$techdep_remove$;
-
-REVOKE EXECUTE
-	ON FUNCTION defs.techdep_remove( TEXT , TEXT )
-	FROM PUBLIC;
-GRANT EXECUTE
-	ON FUNCTION defs.techdep_remove( TEXT , TEXT )
-	TO :dbuser;
-
-
-
-/*
- * Remove all dependencies for a technology
- * -----------------------------------------
- * 
- * This stored procedure removes all dependencies and reverse dependencies for
- * some technology.
- * 
- * Parameters:
- *		_technology		The name of the technology
- */
-DROP FUNCTION IF EXISTS defs.techdep_clear( TEXT );
-CREATE FUNCTION defs.techdep_clear( _technology TEXT )
-	RETURNS VOID
-	LANGUAGE SQL
-	STRICT VOLATILE
-	SECURITY DEFINER
-AS $techdep_clear$
-
-	DELETE FROM defs.technology_dependencies
-		WHERE technology_name_id = (
-				SELECT id FROM defs.strings
-					WHERE name = $1
-			);
-
-	DELETE FROM defs.technology_dependencies
-		WHERE technology_name_id_depends = (
-				SELECT id FROM defs.strings
-					WHERE name = $1
-			);
-
-$techdep_clear$;
-
-REVOKE EXECUTE
-	ON FUNCTION defs.techdep_clear( TEXT )
-	FROM PUBLIC;
-GRANT EXECUTE
-	ON FUNCTION defs.techdep_clear( TEXT )
-	TO :dbuser;
-
-
-
--- ********************************************************
--- OLD CODE BELOW
--- ********************************************************
-
---
--- "Basic" buildables view (buildables that do not depend on any technology)
---
-
-CREATE VIEW tech.basic_buildables
-	AS SELECT * FROM tech.buildables
-		WHERE technology_name_id IS NULL;
-
-
---
--- Buildings view
---
-
-CREATE VIEW tech.buildings_view
-	AS SELECT b.name_id , b.description_id , b.technology_name_id ,
-			b.cost , b.work , b.upkeep ,
-			bld.workers , bld.output_type , bld.output
-		FROM tech.buildables b
-			INNER JOIN tech.buildings bld
-				ON b.name_id = bld.buildable_id;
-
-
-/*
- * Buildings / technology view
- * ----------------------------
- * 
- * This view generates a parseable list of buildings unlocked by a technology
- * for each technology.
- * 
- * Columns:
- *		technology_name_id		The technology's name
- *		technology_buildings	A list of comma-separated building identifiers
- */
-DROP VIEW IF EXISTS defs.technology_buildings_view CASCADE;
-CREATE VIEW defs.technology_buildings_view
-	AS SELECT technology_name_id ,
-			array_to_string( array_agg( _name.name ) , ',' ) AS technology_buildings
-		FROM defs.technologies _tech
-			LEFT OUTER JOIN tech.buildings_view _building
-				USING ( technology_name_id )
-			LEFT OUTER JOIN defs.strings _name
-				ON _name.id = _building.name_id
-		GROUP BY technology_name_id;
-
-
---
--- Ships view
---
-
-CREATE VIEW tech.ships_view
-	AS SELECT b.name_id , b.description_id , b.technology_name_id ,
-			b.cost , b.work , b.upkeep ,
-			s.flight_time , s.power
-		FROM tech.buildables b
-			INNER JOIN tech.ships s
-				ON b.name_id = s.buildable_id;
-
-
---
--- Creates or updates a buildable definition
---
--- Parameters:
---	bdn		Buildable name
---	bdd		Buildable description
---	bdc		Cost
---	bdw		Work
---	bdu		Upkeep
---	_tech	Technology dependency
---
--- Returns:
---	the buildable's identifier
---
-
-CREATE OR REPLACE FUNCTION tech.uoc_buildable( bdn TEXT , bdd TEXT , bdc INT , bdw INT , bdu INT , _tech TEXT )
-		RETURNS INT
-		STRICT
-		VOLATILE
-		SECURITY INVOKER
-	AS $$
-DECLARE
-	nid			INT;
-	did			INT;
-	_tech_id	INT;
-BEGIN
-	-- Get the various translations
-	SELECT INTO nid id FROM defs.strings WHERE name = bdn;
-	SELECT INTO did id FROM defs.strings WHERE name = bdd;
-	IF _tech <> '' THEN
-		SELECT INTO _tech_id technology_name_id
-			FROM defs.technologies
-				INNER JOIN defs.strings s
-					ON s.id = technology_name_id
-			WHERE s.name = _tech;
-	ELSE
-		_tech_id := NULL;
-	END IF;
-	
-	-- Create or update the definition
-	BEGIN
-		INSERT INTO tech.buildables ( name_id , description_id , technology_name_id , cost , work , upkeep )
-			VALUES ( nid , did , _tech_id , bdc , bdw , bdu );
-	EXCEPTION
-		WHEN unique_violation THEN
-			UPDATE tech.buildables
-				SET description_id = did , technology_name_id = _tech_id ,
-					cost = bdc , work = bdw , upkeep = bdu
-				WHERE name_id = nid;
-	END;
-	
-	RETURN nid;
-END;
-$$ LANGUAGE plpgsql;
-
-
-
---
--- Update or create a building definition (no tech dependency)
---
--- Parameters:
---	bdn		Buildable name
---	bdd		Buildable description
---	bdc		Cost
---	bdw		Work
---	bdu		Upkeep
---	bdwk	Workers
---	bdot	Output type
---	bdo		Output
---
-
-CREATE OR REPLACE FUNCTION tech.uoc_building( bdn TEXT , bdd TEXT , bdc INT , bdw INT ,
-											  bdu INT , bdwk INT , bdot building_output_type , bdo INT )
-		RETURNS VOID
-		STRICT
-		VOLATILE
-		SECURITY DEFINER
-	AS $$
-DECLARE
-	bdid	INT;
-BEGIN
-	bdid := tech.uoc_buildable( bdn , bdd , bdc , bdw , bdu , '' );
-	
-	PERFORM buildable_id FROM tech.ships WHERE buildable_id = bdid;
-	IF FOUND THEN
-		RAISE EXCEPTION 'Trying to transform a ship into a building';
-	END IF;
-
-	BEGIN
-		INSERT INTO tech.buildings (buildable_id, workers, output_type, output)
-			VALUES (bdid , bdwk , bdot , bdo);
-	EXCEPTION
-		WHEN unique_violation THEN
-			UPDATE tech.buildings SET workers = bdwk , output_type = bdot , output = bdo
-				WHERE buildable_id = bdid;
-	END;
-END;
-$$ LANGUAGE plpgsql;
-
-GRANT EXECUTE ON FUNCTION tech.uoc_building( TEXT , TEXT , INT , INT , INT , INT , building_output_type , INT ) TO :dbuser;
-
-
-
---
--- Update or create a building definition (with tech dependency)
---
--- Parameters:
---	bdn		Buildable name
---	bdd		Buildable description
---	bdc		Cost
---	bdw		Work
---	bdu		Upkeep
---	bdwk	Workers
---	bdot	Output type
---	bdo		Output
---	_tech	Technology dependency
---
-
-CREATE OR REPLACE FUNCTION tech.uoc_building( bdn TEXT , bdd TEXT , bdc INT , bdw INT ,
-											  bdu INT , bdwk INT , bdot building_output_type , bdo INT ,
-											  _tech TEXT )
-		RETURNS VOID
-		STRICT
-		VOLATILE
-		SECURITY DEFINER
-	AS $$
-DECLARE
-	bdid	INT;
-BEGIN
-	bdid := tech.uoc_buildable( bdn , bdd , bdc , bdw , bdu , _tech );
-	
-	PERFORM buildable_id FROM tech.ships WHERE buildable_id = bdid;
-	IF FOUND THEN
-		RAISE EXCEPTION 'Trying to transform a ship into a building';
-	END IF;
-
-	BEGIN
-		INSERT INTO tech.buildings (buildable_id, workers, output_type, output)
-			VALUES (bdid , bdwk , bdot , bdo);
-	EXCEPTION
-		WHEN unique_violation THEN
-			UPDATE tech.buildings SET workers = bdwk , output_type = bdot , output = bdo
-				WHERE buildable_id = bdid;
-	END;
-END;
-$$ LANGUAGE plpgsql;
-
-GRANT EXECUTE ON FUNCTION tech.uoc_building( TEXT , TEXT , INT , INT , INT , INT , building_output_type , INT , TEXT ) TO :dbuser;
-
-
-
---
--- Update or create a ship definition (no tech dependency)
---
--- Parameters:
---	sn		Buildable name
---	sd		Buildable description
---	sc		Cost
---	sw		Work
---	su		Upkeep
---	sp		Power
---	sft		Orbital flight time
---
-
-CREATE OR REPLACE FUNCTION tech.uoc_ship( sn TEXT , sd TEXT , sc INT , sw INT ,
-										  su INT , sp INT , sft INT )
-		RETURNS VOID
-		STRICT
-		VOLATILE
-		SECURITY DEFINER
-	AS $$
-DECLARE
-	bdid	INT;
-BEGIN
-	bdid := tech.uoc_buildable( sn , sd , sc , sw , su , '' );
-	
-	PERFORM buildable_id FROM tech.buildings WHERE buildable_id = bdid;
-	IF FOUND THEN
-		RAISE EXCEPTION 'Trying to transform a building into a ship';
-	END IF;
-
-	BEGIN
-		INSERT INTO tech.ships (buildable_id, flight_time, power)
-			VALUES (bdid , sft , sp);
-	EXCEPTION
-		WHEN unique_violation THEN
-			UPDATE tech.ships SET flight_time = sft , power = sp
-				WHERE buildable_id = bdid;
-	END;
-END;
-$$ LANGUAGE plpgsql;
-
-GRANT EXECUTE ON FUNCTION tech.uoc_ship( TEXT , TEXT , INT , INT , INT , INT , INT ) TO :dbuser;
-
-
-
---
--- Update or create a ship definition
---
--- Parameters:
---	sn		Buildable name
---	sd		Buildable description
---	sc		Cost
---	sw		Work
---	su		Upkeep
---	sp		Power
---	sft		Orbital flight time
---	_tech	Technology dependency
---
-
-CREATE OR REPLACE FUNCTION tech.uoc_ship( sn TEXT , sd TEXT , sc INT , sw INT ,
-										  su INT , sp INT , sft INT , _tech TEXT )
-		RETURNS VOID
-		STRICT
-		VOLATILE
-		SECURITY DEFINER
-	AS $$
-DECLARE
-	bdid	INT;
-BEGIN
-	bdid := tech.uoc_buildable( sn , sd , sc , sw , su , _tech );
-	
-	PERFORM buildable_id FROM tech.buildings WHERE buildable_id = bdid;
-	IF FOUND THEN
-		RAISE EXCEPTION 'Trying to transform a building into a ship';
-	END IF;
-
-	BEGIN
-		INSERT INTO tech.ships (buildable_id, flight_time, power)
-			VALUES (bdid , sft , sp);
-	EXCEPTION
-		WHEN unique_violation THEN
-			UPDATE tech.ships SET flight_time = sft , power = sp
-				WHERE buildable_id = bdid;
-	END;
-END;
-$$ LANGUAGE plpgsql;
-
-GRANT EXECUTE ON FUNCTION tech.uoc_ship( TEXT , TEXT , INT , INT , INT , INT , INT , TEXT ) TO :dbuser;
-
-
diff --git a/legacyworlds-server-data/db-structure/parts/040-functions/043-computation.sql b/legacyworlds-server-data/db-structure/parts/040-functions/043-computation.sql
deleted file mode 100644
index 0d6c1bb..0000000
--- a/legacyworlds-server-data/db-structure/parts/040-functions/043-computation.sql
+++ /dev/null
@@ -1,365 +0,0 @@
--- LegacyWorlds Beta 6
--- PostgreSQL database scripts
---
--- Various functions for in-game computations
---
--- Copyright(C) 2004-2010, DeepClone Development
--- --------------------------------------------------------
-
-
-/*
- * Random value with deviation
- * 
- * Parameters:
- *		_mean		the mean value
- *		_deviation	the deviation
- *
- * Returns:
- *		?			a random value between _mean - _deviation and
- *						_mean + _deviation, with a higher probability
- *						of a value that is close to _mean
- */
-DROP FUNCTION IF EXISTS verse.random_deviation( DOUBLE PRECISION , DOUBLE PRECISION );
-CREATE FUNCTION verse.random_deviation( _mean DOUBLE PRECISION , _deviation DOUBLE PRECISION )
-		RETURNS DOUBLE PRECISION
-		STRICT VOLATILE
-		SECURITY INVOKER
-	AS $random_deviation$
-
-DECLARE
-	_result	DOUBLE PRECISION;
-
-BEGIN
-	_result := _deviation * RANDOM( ) ^ 2.5;
-	IF RANDOM() < 0.5 THEN
-		_result := -_result;
-	END IF;
-	RETURN _result + _mean;
-END;
-$random_deviation$ LANGUAGE PLPGSQL;
-
-
-REVOKE EXECUTE
-	ON FUNCTION verse.random_deviation( DOUBLE PRECISION , DOUBLE PRECISION )
-	FROM PUBLIC;
-
-
-
-/*
- * Randomly distribute some part of a total value
- * 
- * This function can be used when a total value must be distributed between
- * various items. It will compute the minimal and maximal values that may be
- * attributed, enforcing the fact that the whole value needs to be consumed
- * in the end, and that values must conform to a specific range expressed as
- * a mean value and a deviation.
- * 
- * The total value is assumed to be valid with regards to the mean and
- * deviation. That is:
- * 
- *		_parts * ( _mean - _deviation ) <= _quantity
- *		_parts * ( _mean + _deviation ) >= _quantity
- *
- * Parameters:
- *		_quantity		the total quantity left to distribute
- *		_parts			the amount of items left
- *		_mean			the result's mean value
- *		_deviation		the result's deviation
- *
- * Returns:
- * 		?				the value to attribute to the nex item
- */
-DROP FUNCTION IF EXISTS verse.get_random_part( DOUBLE PRECISION , INT , DOUBLE PRECISION , DOUBLE PRECISION );
-CREATE FUNCTION verse.get_random_part(
-			_quantity DOUBLE PRECISION ,
-			_parts INT ,
-			_mean DOUBLE PRECISION ,
-			_deviation DOUBLE PRECISION )
-		RETURNS DOUBLE PRECISION
-		STRICT VOLATILE
-		SECURITY INVOKER
-	AS $get_random_part$
-
-DECLARE
-	_min	DOUBLE PRECISION;
-	_max	DOUBLE PRECISION;
-	_n_mean	DOUBLE PRECISION;
-
-BEGIN
-	IF _parts = 1 THEN
-		RETURN _quantity;
-	END IF;
-
-	_min := _quantity - ( _mean + _deviation ) * ( _parts - 1 );
-	IF _min < _mean - _deviation THEN
-		_min := _mean - _deviation;
-	END IF;
-
-	_max := _quantity - ( _mean - _deviation ) * ( _parts - 1 );
-	IF _max > _mean + _deviation THEN
-		_max := _mean + _deviation;
-	END IF;
-	
-	IF _min = _max THEN
-		RETURN _min;
-	END IF;
-	
-	_n_mean := ( _min + _max ) * 0.5;
-	RETURN verse.random_deviation( _n_mean , _n_mean - _min );
-END;
-$get_random_part$ LANGUAGE PLPGSQL;
-
-REVOKE EXECUTE
-	ON FUNCTION verse.get_random_part( DOUBLE PRECISION , INT , DOUBLE PRECISION , DOUBLE PRECISION )
-	FROM PUBLIC;
-
-
-
-
---
--- sigma( x ) = exp( x ) / ( 1 + exp( x ) )
---
-
-CREATE OR REPLACE FUNCTION verse.sigma( x REAL )
-	RETURNS REAL
-	STRICT IMMUTABLE SECURITY INVOKER
-AS $$
-	SELECT ( CASE
-		WHEN $1 < -100 THEN 0
-		WHEN $1 > 100 THEN 1
-		ELSE ( exp( $1 ) / ( 1 + exp( $1 ) ) )::REAL
-	END );
-$$ LANGUAGE SQL;
-
-
-
---
--- poly( x , a , b , c ) = ( a * x + b ) * x + c 
---
-
-CREATE OR REPLACE FUNCTION verse.poly( x REAL , a REAL , b REAL , c REAL )
-	RETURNS REAL
-	STRICT IMMUTABLE SECURITY INVOKER
-AS $$
-	SELECT ( $2 * $1 + $3 ) * $1 + $4;
-$$ LANGUAGE SQL;
-
-
-
---
--- Happiness curve, K1 constant
---
-
-CREATE OR REPLACE FUNCTION verse.hcc_const_k1( xmax REAL , ymax REAL , xlimit REAL , ylimit REAL )
-	RETURNS REAL
-	STRICT IMMUTABLE SECURITY INVOKER
-AS $$
-	SELECT ( ( $4 - $2 ) / ( ( $3 - $1 ) ^ 2 ) )::REAL;
-$$ LANGUAGE SQL;
-
-
-
---
--- Happiness curve, K2 constant
---
-
-CREATE OR REPLACE FUNCTION verse.hcc_const_k2( ylimit REAL , yasymptote REAL )
-	RETURNS REAL
-	STRICT IMMUTABLE SECURITY INVOKER
-AS $$
-	SELECT ( 2 * ( $1 - $2 ) )::REAL;
-$$ LANGUAGE SQL;
-
-
-
---
--- Happiness curve, K3 constant
---
-
-CREATE OR REPLACE FUNCTION verse.hcc_const_k3( xmax REAL , ymax REAL , xlimit REAL , ylimit REAL , yasymptote REAL )
-	RETURNS REAL
-	STRICT IMMUTABLE SECURITY INVOKER
-AS $$
-	SELECT ( verse.hcc_const_k1( $1 , $2 , $3 , $4 ) * 4 * ( $3 - $1 ) / ( $5 - $4 ) ) ::REAL;
-$$ LANGUAGE SQL;
-
-
-
---
--- Happiness curve, first part
---
-
-CREATE OR REPLACE FUNCTION verse.hcc_part_1( x REAL , ymin REAL , ymax REAL , xmax REAL )
-	RETURNS REAL
-	STRICT IMMUTABLE SECURITY INVOKER
-AS $$
-DECLARE
-	v	REAL;
-BEGIN
-	v := ( ymin - ymax ) / xmax;
-	RETURN verse.poly( x , ( v / xmax )::REAL , ( -2 * v )::REAL , ymin );
-END;
-$$ LANGUAGE plpgsql;
-
-
-
---
--- Happiness curve, second part
---
-
-CREATE OR REPLACE FUNCTION verse.hcc_part_2( x REAL , xmax REAL , ymax REAL , xlimit REAL , ylimit REAL )
-	RETURNS REAL
-	STRICT IMMUTABLE SECURITY INVOKER
-AS $$
-DECLARE
-	k1	REAL;
-BEGIN
-	k1 := verse.hcc_const_k1( xmax , ymax , xlimit , ylimit );
-	RETURN verse.poly( x , k1 , ( -2 * xmax * k1 )::REAL , ( ymax + k1 * xmax * xmax )::REAL );
-END;
-$$ LANGUAGE plpgsql;
-
-
-
---
--- Happiness curve, third part
---
-
-CREATE OR REPLACE FUNCTION verse.hcc_part_3( x REAL , xmax REAL , ymax REAL , xlimit REAL , ylimit REAL , yasymptote REAL )
-	RETURNS REAL
-	STRICT IMMUTABLE SECURITY INVOKER
-AS $$
-DECLARE
-	k2	REAL;
-	k3	REAL;
-BEGIN
-	k2 := verse.hcc_const_k2( ylimit , yasymptote );
-	k3 := verse.hcc_const_k3( xmax , ymax , xlimit , ylimit , yasymptote );
-	RETURN yasymptote + k2 * ( 1 - verse.sigma( ( k3 * ( x - xlimit ) ) )::REAL );
-END;
-$$ LANGUAGE plpgsql;
-
-
-
---
--- Happiness curve
---
-
-CREATE OR REPLACE FUNCTION verse.happiness_curve( x REAL , ymin REAL , xmax REAL , ymax REAL , xlimit REAL , ylimit REAL , yasymptote REAL )
-	RETURNS REAL
-	STRICT IMMUTABLE SECURITY INVOKER
-AS $$
-	SELECT (CASE
-		WHEN $1 < $3 THEN
-			verse.hcc_part_1( $1 , $2 , $4 , $3 )
-		WHEN $1 < $5 THEN
-			verse.hcc_part_2( $1 , $3 , $4 , $5 , $6 )
-		ELSE
-			verse.hcc_part_3( $1 , $3 , $4 , $5 , $6 , $7 )
-	END)
-$$ LANGUAGE SQL;
-
-
-
---
--- Happiness computation
---
-
-CREATE OR REPLACE FUNCTION verse.compute_happiness( population REAL , workers REAL , defence REAL , empsize INT )
-		RETURNS REAL
-		STRICT STABLE SECURITY INVOKER
-	AS $$
-DECLARE
-	whappiness	REAL;
-	dhappiness	REAL;
-	shappiness	REAL;
-BEGIN
-	-- Work-related happiness
-	whappiness := verse.happiness_curve(
-		( workers / population )::REAL ,
-		sys.get_constant( 'game.happiness.noEmployment' ) , 1.0 , 1.0 , 
-		sys.get_constant( 'game.happiness.employmentLimit' ) , 0.5 , 0
-	);
-
-	-- Defence-related happiness
-	dhappiness := verse.happiness_curve(
-		( sys.get_constant( 'game.happiness.popPerDefencePoint' ) * defence / population )::REAL ,
-		sys.get_constant( 'game.happiness.noDefence' ) , 1.0 , 1.0 , 
-		sys.get_constant( 'game.happiness.defenceLimit' ) , 0.5 , 0
-	);
-	
-	-- Influence of empire size
-	shappiness := verse.happiness_curve(
-		( empsize::REAL / sys.get_constant( 'game.happiness.idealEmpireSize' ) )::REAL ,
-		sys.get_constant( 'game.happiness.smallEmpire' ) , 1.0 , 1.0 , 
-		sys.get_constant( 'game.happiness.eSizeLimit' ) , 0.5 , 0
-	);
-	
-	RETURN ( shappiness * ( whappiness + dhappiness ) / 2.0 )::REAL;
-END;
-$$ LANGUAGE plpgsql;
-
-
-
-/*
- * Production adjustment
- * ----------------------
- *
- * Adjust productions depending on a planet's happiness ratio. When the
- * happiness ratio is greater than the game.happiness.strike constant, the
- * production is not affected. However, under that threshold, the production
- * decreases proportionally, until it reaches 0.
- * 
- * Parameters:
- *		_prod		The production's valule
- *		_h_ratio	The happiness ratio
- *
- * Returns:
- *		?			The adjusted production value
- */
-DROP FUNCTION IF EXISTS verse.adjust_production( REAL , REAL ) CASCADE;
-CREATE OR REPLACE FUNCTION verse.adjust_production( _prod REAL , _h_ratio REAL )
-	RETURNS REAL
-	LANGUAGE SQL
-	STRICT IMMUTABLE
-	SECURITY INVOKER
-AS $adjust_production$
-
-	SELECT ( CASE
-		WHEN $2 < sys.get_constant( 'game.happiness.strike' ) THEN
-			( $1 * $2 / sys.get_constant( 'game.happiness.strike' ) )::REAL
-		ELSE
-			$1
-	END );
-
-$adjust_production$;
-
-REVOKE EXECUTE
-	ON FUNCTION verse.adjust_production( REAL , REAL )
-	FROM PUBLIC;
-GRANT EXECUTE
-	ON FUNCTION verse.adjust_production( REAL , REAL )
-	TO :dbuser;
-
-
---
--- Income computation
---
-
-CREATE OR REPLACE FUNCTION verse.compute_income( population REAL , happiness REAL , cashprod REAL )
-		RETURNS REAL
-		STRICT STABLE
-		SECURITY INVOKER
-	AS $$
-DECLARE
-	base	REAL;
-	badj	REAL;
-	cprod	REAL;
-BEGIN
-	badj := ( 1 - verse.adjust_production( 1.0 , happiness ) ) * sys.get_constant( 'game.work.strikeEffect' );
-	base := floor( population ) * sys.get_constant( 'game.work.population' ) * ( 1 - badj );
-	cprod := verse.adjust_production( cashprod , happiness ) * sys.get_constant( 'game.work.factory' );
-	RETURN cprod + base;
-END;
-$$ LANGUAGE plpgsql;
-
diff --git a/legacyworlds-server-data/db-structure/parts/040-functions/045-empire-research.sql b/legacyworlds-server-data/db-structure/parts/040-functions/045-empire-research.sql
deleted file mode 100644
index 42f3eaf..0000000
--- a/legacyworlds-server-data/db-structure/parts/040-functions/045-empire-research.sql
+++ /dev/null
@@ -1,518 +0,0 @@
--- LegacyWorlds Beta 6
--- PostgreSQL database scripts
---
--- Empire research functions and views
---
--- Copyright(C) 2004-2012, DeepClone Development
--- --------------------------------------------------------
-
-
-
-/*
- * Implements a technology
- * ------------------------
- * 
- * This stored procedure is called when an empire attempts to implement a
- * technology. It will check the empire's resources and the technology itself,
- * then mark it as implemented if necessary. It will also add new research
- * entries if necessary.
- * 
- * Parameters:
- *		_empire			The empire's identifier
- *		_technology		The string identifier for the technology to implement
- */
-DROP FUNCTION IF EXISTS emp.technology_implement( INT , TEXT );
-CREATE FUNCTION emp.technology_implement( _empire INT , _technology TEXT )
-		RETURNS BOOLEAN
-		LANGUAGE PLPGSQL
-		STRICT VOLATILE
-		SECURITY DEFINER
-	AS $technology_implement$
-
-DECLARE
-	_impl_data	RECORD;
-
-BEGIN
-
-	-- Access and lock the records
-	SELECT INTO _impl_data
-			technology_name_id , technology_price
-		FROM emp.empires _emp
-			INNER JOIN emp.technologies _tech
-				ON _tech.empire_id = _emp.name_id
-			INNER JOIN defs.technologies _def
-				USING ( technology_name_id )
-			INNER JOIN defs.strings _name
-				ON _def.technology_name_id = _name.id
-		WHERE _emp.name_id = _empire
-			AND _name.name = _technology
-			AND _tech.emptech_state = 'PENDING'
-			AND _emp.cash >= _def.technology_price
-		FOR UPDATE OF _emp , _tech
-		FOR SHARE OF _def;
-	IF NOT FOUND THEN
-		RETURN FALSE;
-	END IF;
-
-	-- Implement the technology
-	UPDATE emp.empires
-		SET cash = cash - _impl_data.technology_price
-		WHERE name_id = _empire;
-	UPDATE emp.technologies
-		SET emptech_state = 'KNOWN'
-		WHERE empire_id = _empire
-			AND technology_name_id = _impl_data.technology_name_id;
-
-	-- Insert new research
-	INSERT INTO emp.technologies ( empire_id , technology_name_id )
-		SELECT _empire , _valid.technology_name_id
-			FROM  ( SELECT _tech.technology_name_id ,
-							( COUNT(*) = COUNT(_emptech.emptech_state) ) AS emptech_has_dependencies
-						FROM defs.technologies _tech
-							INNER JOIN defs.technology_dependencies _deps
-									USING ( technology_name_id )
-							LEFT OUTER JOIN emp.technologies _emptech
-									ON _emptech.technology_name_id = _deps.technology_name_id_depends
-										AND _emptech.emptech_state = 'KNOWN'
-										AND _emptech.empire_id = _empire
-						GROUP BY _tech.technology_name_id ) _valid
-				LEFT OUTER JOIN emp.technologies _emptech
-					ON _emptech.empire_id = _empire
-						AND _emptech.technology_name_id = _valid.technology_name_id
-			WHERE _emptech.empire_id IS NULL AND _valid.emptech_has_dependencies;
-
-	RETURN TRUE;
-END;
-$technology_implement$;
-
-REVOKE EXECUTE
-	ON FUNCTION emp.technology_implement( INT , TEXT )
-	FROM PUBLIC;
-
-GRANT EXECUTE
-	ON FUNCTION emp.technology_implement( INT , TEXT )
-	TO :dbuser;
-
-
-/*
- * Compute a technology identifier
- * --------------------------------
- * 
- * This function returns the identifier of a technology as seen from the
- * player's side. The identifier is either the string identifier for the
- * technology's name, or a MD5 hash including both the empire's identifier
- * and the string identifier for "unknown" technologies.
- * 
- * Parameters:
- *		_empire		The empire's identifier
- *		_technology	The technology's string identifier
- *		_visible	TRUE if the technology is supposed to be visible, FALSE
- *						otherwise
- *
- * Returns:
- *		?			The technology's client-side identifier
- */
-DROP FUNCTION IF EXISTS emp.technology_make_identifier( INT , TEXT , BOOLEAN );
-CREATE FUNCTION emp.technology_make_identifier(
-				_empire INT , _technology TEXT , _visible BOOLEAN )
-	RETURNS TEXT
-	LANGUAGE SQL
-	STRICT IMMUTABLE
-	SECURITY DEFINER
-AS $technology_make_identifier$
-
-	SELECT ( CASE
-		WHEN $3 THEN
-			$2
-		ELSE
-			md5( $1::TEXT || ' (making hash less obvious) ' || $2 )
-	END );
-
-$technology_make_identifier$;
-
-REVOKE EXECUTE
-	ON FUNCTION emp.technology_make_identifier( INT , TEXT , BOOLEAN )
-	FROM PUBLIC;
-
-GRANT EXECUTE
-	ON FUNCTION emp.technology_make_identifier( INT , TEXT , BOOLEAN )
-	TO :dbuser;
-
-
-/*
- * Initialise a research priorities update
- * ----------------------------------------
- * 
- * This stored procedure prepares a temporary table which is used to update
- * an empire's research priorities.
- *
- * Parameters:
- *		_empire		The empire's identifier
- *
- * Returns:
- *		?			TRUE if the empire exists, is not on vacation mode and has
- *						in-progress research, FALSE otherwise.
- */
-DROP FUNCTION IF EXISTS emp.resprio_update_start( INT );
-CREATE FUNCTION emp.resprio_update_start( _empire INT )
-		RETURNS BOOLEAN
-		LANGUAGE PLPGSQL
-		STRICT VOLATILE
-		SECURITY DEFINER
-	AS $resprio_update_start$
-BEGIN
-
-	-- Create temporary table
-	CREATE TEMPORARY TABLE rprio_update(
-		_empire_id			INT ,
-		_technology_name_id	INT ,
-		_emptech_id			TEXT ,
-		_emptech_priority	INT
-	) ON COMMIT DROP;
-
-	-- Lock records and fill table
-	INSERT INTO rprio_update (
-			_empire_id , _technology_name_id , _emptech_id , _emptech_priority
-		) SELECT _emp.name_id , _tech.technology_name_id ,
-				emp.technology_make_identifier( empire_id , _str.name , emptech_visible ) ,
-				_etech.emptech_priority
-			FROM emp.empires _emp
-				INNER JOIN emp.technologies _etech
-					ON _etech.empire_id = _emp.name_id
-						AND _etech.emptech_state = 'RESEARCH'
-				INNER JOIN defs.technologies _tech
-					USING ( technology_name_id )
-				INNER JOIN emp.technology_visibility_view _vis
-					USING ( empire_id , technology_name_id )
-				INNER JOIN defs.strings _str
-					ON _str.id = _tech.technology_name_id
-				INNER JOIN naming.empire_names _ename
-					ON _ename.id = _emp.name_id
-				LEFT OUTER JOIN users.vacations _vac
-					ON _vac.account_id = _ename.owner_id
-						AND _vac.status = 'PROCESSED'
-			WHERE _emp.name_id = _empire AND _vac.account_id IS NULL
-			FOR UPDATE OF _emp , _etech
-			FOR SHARE OF _tech , _str , _ename;
-
-	RETURN FOUND;
-END;
-$resprio_update_start$;
-
-REVOKE EXECUTE
-	ON FUNCTION emp.resprio_update_start( INT )
-	FROM PUBLIC;
-
-GRANT EXECUTE
-	ON FUNCTION emp.resprio_update_start( INT )
-	TO :dbuser;
-
-
-/*
- * Set the priority of some research
- * ----------------------------------
- * 
- * This stored procedure updates the priority of some in-progress empire
- * research. It will only function correctly if emp.resprio_update_start() was
- * already executed.
- * 
- * Parameters:
- *		_technology		The client-side identifier of the technology, as
- *							returned by emp.technology_make_identifier()
- *		_priority		The priority to assign to the technology
- *
- * Returns:
- *		?				TRUE if the technology was found, FALSE if it wasn't.
- */
-DROP FUNCTION IF EXISTS emp.resprio_update_set( TEXT , INT );
-CREATE FUNCTION emp.resprio_update_set( _technology TEXT , _priority INT )
-		RETURNS BOOLEAN
-		LANGUAGE PLPGSQL
-		STRICT VOLATILE
-		SECURITY DEFINER
-	AS $resprio_update_set$
-BEGIN
-	
-	UPDATE rprio_update
-		SET _emptech_priority = _priority
-		WHERE _emptech_id = _technology;
-	RETURN FOUND;
-
-END;
-$resprio_update_set$;
-
-REVOKE EXECUTE
-	ON FUNCTION emp.resprio_update_set( TEXT , INT )
-	FROM PUBLIC;
-
-GRANT EXECUTE
-	ON FUNCTION emp.resprio_update_set( TEXT , INT )
-	TO :dbuser;
-
-
-/*
- * Apply an update to research priorities
- * ---------------------------------------
- * 
- * This stored procedure applies changes listed in the temporary research
- * priority table by updating the actual table with the new values.
- * 
- * Returns:
- *		?		TRUE if the update was valid, FALSE if one of the updated
- *					values was incorrect
- */
-DROP FUNCTION IF EXISTS emp.resprio_update_apply( );
-CREATE FUNCTION emp.resprio_update_apply( )
-		RETURNS BOOLEAN
-		LANGUAGE PLPGSQL
-		STRICT VOLATILE
-		SECURITY DEFINER
-	AS $resprio_update_apply$
-BEGIN
-	
-	UPDATE emp.technologies
-		SET emptech_priority = _emptech_priority
-		FROM rprio_update
-		WHERE _empire_id = empire_id
-			AND _technology_name_id = technology_name_id;
-	RETURN TRUE;
-
-EXCEPTION
-
-	WHEN check_violation THEN
-		RETURN FALSE;
-
-END;
-$resprio_update_apply$;
-
-REVOKE EXECUTE
-	ON FUNCTION emp.resprio_update_apply( )
-	FROM PUBLIC;
-
-GRANT EXECUTE
-	ON FUNCTION emp.resprio_update_apply( )
-	TO :dbuser;
-
-
-
-/*
- * Compute an empire's total research points
- * ------------------------------------------
- * 
- * Obtain an empire's total research points by adding the happiness-adjusted
- * value for each planet, then applying the global modifier for vacation mode
- * if necessary.
- *
- * FIXME: time factor is hard-coded
- * 
- * Parameters:
- *		_empire			The empire's identifier
- *		_on_vacation	TRUE if the player is on vacation, FALSE otherwise
- *
- * Returns:
- *		?				The amount of research points.
- */
-DROP FUNCTION IF EXISTS emp.research_get_points( INT , BOOLEAN );
-CREATE FUNCTION emp.research_get_points( _empire INT , _on_vacation BOOLEAN )
-	RETURNS DOUBLE PRECISION
-	LANGUAGE SQL
-	STRICT STABLE
-	SECURITY INVOKER
-AS $research_get_points$
-
-	SELECT SUM( verse.adjust_production(
-					_planet.population * sys.get_constant( 'game.research.basePoints' ) ,
-					_happiness.current / _planet.population
-				) ) * ( CASE
-					WHEN $2 THEN
-						sys.get_constant( 'game.research.vacation' )
-					ELSE
-						1.0
-				END )::DOUBLE PRECISION
-		FROM emp.planets _emp_planet
-			INNER JOIN verse.planets _planet
-				ON _emp_planet.planet_id = _planet.name_id
-			INNER JOIN verse.planet_happiness _happiness
-				USING ( planet_id )
-		WHERE _emp_planet.empire_id = $1;
-
-$research_get_points$;
-
-REVOKE EXECUTE
-	ON FUNCTION emp.research_get_points( INT , BOOLEAN )
-	FROM PUBLIC;
-
-
-
-
-
-/*
- * Technology visibility view
- * ---------------------------
- * 
- * This view can be used to determine whether entries from empires' research
- * and technologies table are fully visible or only displayed as "unknown
- * technologies".
- * 
- * Columns:
- *		empire_id			The empire's identifier
- *		technology_name_id	The technology's identifier
- *		emptech_visible		TRUE if the technology's details are visible,
- *								FALSE if they should be hidden
- */
-DROP VIEW IF EXISTS emp.technology_visibility_view CASCADE;
-CREATE VIEW emp.technology_visibility_view
-	AS SELECT empire_id , technology_name_id ,
-			( emptech_state <> 'RESEARCH'
-				OR emptech_points >= sys.get_constant( 'game.research.visibility.points' )
-				OR emptech_points / technology_points::DOUBLE PRECISION >= sys.get_constant( 'game.research.visibility.ratio' )
-			) AS emptech_visible
-		FROM emp.technologies
-			INNER JOIN defs.technologies
-				USING ( technology_name_id );
-
-
-
-/*
- * Research weights
- * -----------------
- * 
- * This view computes weights based on priorities for each in-progress
- * research.
- * 
- * Columns:
- *		empire_id			The empire's identifier
- *		technology_name_id	The technology's identifier
- *		emptech_weight		The weight
- */
-DROP VIEW IF EXISTS emp.research_weights_view CASCADE;
-CREATE VIEW emp.research_weights_view
-	AS SELECT empire_id , technology_name_id ,
-			POW( sys.get_constant( 'game.research.weightBase' ) ,
-					emptech_priority ) AS emptech_weight
-		FROM emp.technologies
-		WHERE emptech_state = 'RESEARCH';
-
-/*
- * Total research weights
- * -----------------------
- * 
- * This view computes total research weights for each empire with in-progress
- * research.
- * 
- * Columns:
- *		empire_id				The empire's identifier
- *		emptech_total_weight	The total research weight
- */
-DROP VIEW IF EXISTS emp.research_total_weights_view CASCADE;
-CREATE VIEW emp.research_total_weights_view
-	AS SELECT empire_id , SUM( emptech_weight ) AS emptech_total_weight
-		FROM emp.research_weights_view
-		GROUP BY empire_id;
-
-
-/*
- * Empire research and technologies
- * ---------------------------------
- * 
- * This view lists empires' research and technologies, along with their
- * current state.
- * 
- * Columns:
- *		empire_id			The empire's identifier
- *		emptech_id			An identifier for the technology, which is either
- *								the string identifier of the technology's name
- *								or a MD5 hash if the technology is not
- *								supposed to be visible
- *		emptech_state		The state of the technology, straight from the
- *								empire technology table
- *		emptech_visible		Whether the technology is supposed to be visible
- *								or not
- *		technology_category	The string identifier of the technology's category
- *		technology_name		The string identifier of the technology's name,
- *								or NULL if the technology is not supposed to
- *								be visible
- *		technology_description	The string identifier of the technology's name,
- *									or NULL if the technology is not supposed
- *									to be visible
- *		emptech_points		The amount of points accumulated while researching
- *								the technology, or NULL if the technology is
- *								not supposed to be visible
- *		emptech_priority	The current research priority, or NULL if the
- *								technology is no longer being researched
- *		emptech_ratio		The percentage of points accumulated while
- *								researching the technology, or NULL if the
- *								technology is no longer being researched
- *		technology_price	The monetary price of the technology, or NULL if
- *								the technology is not supposed to be visible
- *		technology_dependencies	The technology's dependencies from the
- *									dependencies view
- *		technology_buildings	The buildings which are unlocked when the
- *									technology is implemented
- */
-DROP VIEW IF EXISTS emp.technologies_view CASCADE;
-CREATE VIEW emp.technologies_view
-	AS SELECT empire_id ,
-			emp.technology_make_identifier( empire_id , _name_str.name , emptech_visible ) AS emptech_id ,
-			emptech_state ,
-			emptech_visible ,
-			_cat_str.name AS technology_category ,
-			( CASE
-				WHEN emptech_visible THEN
-					_name_str.name
-				ELSE
-					NULL::TEXT
-			END ) AS technology_name ,
-			( CASE
-				WHEN emptech_visible THEN
-					_descr_str.name
-				ELSE
-					NULL::TEXT
-			END ) AS technology_description ,
-			( CASE
-				WHEN emptech_state <> 'RESEARCH' then
-					technology_points
-				WHEN emptech_visible THEN
-					FLOOR( emptech_points )::BIGINT
-				ELSE
-					NULL::BIGINT
-			END ) AS emptech_points ,
-			emptech_priority ,
-			( CASE
-				WHEN emptech_state = 'RESEARCH' THEN
-					FLOOR( 100.0 * emptech_points / technology_points::DOUBLE PRECISION )::INT
-				ELSE
-					NULL::INT
-			END ) AS emptech_ratio ,
-			( CASE
-				WHEN emptech_visible THEN
-					technology_price
-				ELSE
-					NULL::INT
-			END ) AS technology_price ,
-			technology_dependencies ,
-			( CASE
-				WHEN emptech_visible THEN
-					technology_buildings
-				ELSE
-					''
-			END ) AS technology_buildings
-		FROM emp.technologies
-			INNER JOIN emp.technology_visibility_view
-				USING ( technology_name_id , empire_id )
-			INNER JOIN defs.technologies _tech
-				USING ( technology_name_id )
-			INNER JOIN defs.technology_dependencies_view
-				USING ( technology_name_id )
-			INNER JOIN defs.technology_buildings_view
-				USING ( technology_name_id )
-			INNER JOIN defs.strings _name_str
-				ON _name_str.id = _tech.technology_name_id
-			INNER JOIN defs.strings _cat_str
-				ON _cat_str.id = _tech.technology_category_id
-			INNER JOIN defs.strings _descr_str
-				ON _descr_str.id = _tech.technology_description_id;
-
-GRANT SELECT
-	ON emp.technologies_view
-	TO :dbuser;
diff --git a/legacyworlds-server-data/db-structure/parts/040-functions/053-generator-basics.sql b/legacyworlds-server-data/db-structure/parts/040-functions/053-generator-basics.sql
deleted file mode 100644
index a7fb6f0..0000000
--- a/legacyworlds-server-data/db-structure/parts/040-functions/053-generator-basics.sql
+++ /dev/null
@@ -1,51 +0,0 @@
--- LegacyWorlds Beta 6
--- PostgreSQL database scripts
---
--- A few types and internal functions used in most parts
--- of the universe generator.
---
--- Copyright(C) 2004-2012, DeepClone Development
--- --------------------------------------------------------
-
-
-/* The coordinates of the area being generated. */
-DROP TYPE IF EXISTS verse.generator_area_type CASCADE;
-CREATE TYPE verse.generator_area_type AS (
-	x0 INT , y0 INT ,
-	x1 INT , y1 INT
-);
-
-
-
-/*
- * List some quantity of random planets from an area of the universe
- * 
- * This function returns a set of planet identifiers chosen at random from the
- * specified area of the universe.
- * 
- * Parameters:
- *		_area		The area to select planets from
- *		_count		The maximal amount of planets to return
- */
-DROP FUNCTION IF EXISTS verse.list_random_planets_in( verse.generator_area_type , INT );
-CREATE FUNCTION verse.list_random_planets_in( _area verse.generator_area_type , _count INT )
-	RETURNS SETOF INT
-	STRICT VOLATILE
-	SECURITY INVOKER
-AS $list_random_planets_in$
-
-	SELECT _planets.name_id
-		FROM verse.planets _planets
-			INNER JOIN verse.systems _systems
-				ON _planets.system_id = _systems.id
-		WHERE _systems.x BETWEEN $1.x0 AND $1.x1
-			AND _systems.y BETWEEN $1.y0 AND $1.y1
-		ORDER BY RANDOM( )
-		LIMIT $2;
-
-$list_random_planets_in$ LANGUAGE SQL;
-
-REVOKE EXECUTE
-	ON FUNCTION verse.list_random_planets_in( verse.generator_area_type ,
-			INT )
-	FROM PUBLIC;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/parts/040-functions/055-generator-resources.sql b/legacyworlds-server-data/db-structure/parts/040-functions/055-generator-resources.sql
deleted file mode 100644
index 2e0e0fe..0000000
--- a/legacyworlds-server-data/db-structure/parts/040-functions/055-generator-resources.sql
+++ /dev/null
@@ -1,387 +0,0 @@
--- LegacyWorlds Beta 6
--- PostgreSQL database scripts
---
--- Functions for the resource provider generator
---
--- Copyright(C) 2004-2012, DeepClone Development
--- --------------------------------------------------------
-
-
-
-/*
- * Resource provider generator data
- * 
- * This data type is used to store statistics about the existing resource
- * providers. A single item of the type represents both statistics and
- * parameters for a given resource type.
- */
-DROP TYPE IF EXISTS verse.resprov_generator_type CASCADE;
-CREATE TYPE verse.resprov_generator_type AS (
-		/* Type of natural resource */
-	 	resource_name_id		INT ,
-
-	 	/* Planets in the universe */
-	 	planets					DOUBLE PRECISION ,
-	 	
-	 	/* Providers of this type in the universe */
-	 	providers				DOUBLE PRECISION ,
-
-	 	/* Presence probability (from the resource's definition) */
-	 	presence				DOUBLE PRECISION ,
-
-	 	/* Total maximal quantity of this type of resource in the whole
-	 	 * universe.
-	 	 */
-	 	quantity				DOUBLE PRECISION ,
-	 	
-	 	/* Average quantity (from the resource's definition) */
-	 	quantity_avg			DOUBLE PRECISION ,
-	 	
-	 	/* Maximal deviation from the average quantity (from the resource's
-	 	 * definition)
-	 	 */
-	 	quantity_dev			DOUBLE PRECISION ,
-
-	 	/* Total extraction difficulty for this type of resource in the whole
-	 	 * universe.
-	 	 */
-	 	difficulty				DOUBLE PRECISION ,
-	 	
-	 	/* Average difficulty (from the resource's definition) */
-	 	difficulty_avg			DOUBLE PRECISION ,
-	 	
-	 	/* Maximal deviation from the average difficulty (from the resource's
-	 	 * definition)
-	 	 */
-	 	difficulty_dev			DOUBLE PRECISION ,
-
-	 	/* Total recovery rate for this type of resource in the whole
-	 	 * universe.
-	 	 */
-	 	recovery				DOUBLE PRECISION ,
-	 	
-	 	/* Average recovery rate (from the resource's definition) */
-	 	recovery_avg			DOUBLE PRECISION ,
-	 	
-	 	/* Maximal deviation from the average recovery rate (from the
-	 	 */
-	 	recovery_dev			DOUBLE PRECISION
-);
-
-
-
-/*
- * Collect resource provider statistics
- * 
- * This procedure collects statistics about resource providers into a
- * temporary table named resource_statistics, using the resprov_generator_type
- * as the table's structure. The table will be dropped on commit.
- * 
- * This function is necessary because the statistics must be collected before
- * new planets are generated.
- */
-DROP FUNCTION IF EXISTS verse.collect_resprov_statistics( );
-CREATE FUNCTION verse.collect_resprov_statistics( )
-		RETURNS VOID
-		STRICT VOLATILE
-		SECURITY INVOKER
-	AS $collect_resprov_statistics$
-
-BEGIN
-	 CREATE TEMP TABLE rp_stats
-	 	OF verse.resprov_generator_type
-	 	ON COMMIT DROP;
-
-	INSERT INTO rp_stats
-		SELECT resource_name_id ,
-					_pcount.planets AS planets ,
-					( CASE
-						WHEN _rp_stats.providers IS NULL THEN 0
-						ELSE _rp_stats.providers
-					END ) AS providers ,
-					natres_p_presence AS presence ,
-					( CASE
-						WHEN _rp_stats.tot_quantity IS NULL THEN 0
-						ELSE _rp_stats.tot_quantity
-					END ) AS quantity ,
-					natres_quantity_avg AS quantity_avg ,
-					natres_quantity_dev AS quantity_dev ,
-					( CASE
-						WHEN _rp_stats.tot_difficulty IS NULL THEN 0
-						ELSE _rp_stats.tot_difficulty
-					END ) AS difficulty ,
-					natres_difficulty_avg AS difficulty_avg ,
-					natres_difficulty_dev AS difficulty_dev ,
-					( CASE
-						WHEN _rp_stats.tot_recovery IS NULL THEN 0
-						ELSE _rp_stats.tot_recovery
-					END ) AS recovery ,
-					natres_recovery_avg AS recovery_avg ,
-					natres_recovery_dev AS recovery_dev
-			FROM defs.natural_resources
-				LEFT OUTER JOIN (
-					SELECT resource_name_id ,
-							COUNT(*) AS providers ,
-							SUM( resprov_quantity_max ) AS tot_quantity ,
-							SUM( resprov_difficulty ) AS tot_difficulty ,
-							SUM( resprov_recovery ) AS tot_recovery
-						FROM verse.resource_providers
-						GROUP BY resource_name_id
-					) AS _rp_stats USING ( resource_name_id )
-				CROSS JOIN (
-					SELECT COUNT(*) AS planets
-						FROM verse.planets
-				) AS _pcount;
-END;
-$collect_resprov_statistics$ LANGUAGE PLPGSQL;
-
-REVOKE EXECUTE
-	ON FUNCTION verse.collect_resprov_statistics( )
-	FROM PUBLIC;
-
-
-
-/* Compute a random delta for one of the resource provider parameters
- * 
- * This function computes the total change on one of the resource provider
- * parameters. The resulting value can then be split amongst resource
- * providers as they are created.
- * 
- * Parameters:
- *		_existing			Amount of existing resource providers
- *		_new				Amount of resource providers being created
- *		_total				Current total value for the parameter
- *		_p_average			Average parameter value (from the definition)
- *		_p_deviation		Parameter value deviation (from the definition)
- *
- * Returns:
- *		?					The total value to distribute amongst new resource
- *								providers
- */
-DROP FUNCTION IF EXISTS verse.compute_rpp_delta( DOUBLE PRECISION , DOUBLE PRECISION ,
-		DOUBLE PRECISION , DOUBLE PRECISION , DOUBLE PRECISION );
-CREATE FUNCTION verse.compute_rpp_delta(
-			_existing		DOUBLE PRECISION ,
-			_new			DOUBLE PRECISION ,
-			_total			DOUBLE PRECISION ,
-			_p_average		DOUBLE PRECISION ,
-			_p_deviation	DOUBLE PRECISION )
-		RETURNS DOUBLE PRECISION
-		STRICT VOLATILE
-		SECURITY INVOKER
-	AS $compute_rpp_delta$
-
-DECLARE
-	_result	DOUBLE PRECISION;
-
-BEGIN
-	_result := verse.random_deviation( _p_average , _p_deviation )
-					* ( _existing + _new ) - _total;
-
-	IF _result < ( _p_average - _p_deviation ) * _new THEN
-		_result := ( _p_average - _p_deviation ) * _new;
-	ELSIF _result > ( _p_average + _p_deviation ) * _new THEN
-		_result := ( _p_average + _p_deviation ) * _new;
-	END IF;
-	
-	RETURN _result;
-END;
-$compute_rpp_delta$ LANGUAGE PLPGSQL;
-
-REVOKE EXECUTE
-	ON FUNCTION verse.compute_rpp_delta( DOUBLE PRECISION , DOUBLE PRECISION ,
-			DOUBLE PRECISION , DOUBLE PRECISION , DOUBLE PRECISION )
-	FROM PUBLIC;
-
-
-
-/*
- * Create a single resource provider
- * 
- * This function creates a single resource provider on some planet. It will
- * return the updated values for the amount of providers left to handle and
- * the totals.
- * 
- * Parameters:
- *		_planet			The identifier of the planet to create a provider on
- *		_data			The statistics and parameters for the type of resource
- *		_providers_left	The amount of resource providers that still need to be
- *							generated (including the current provider)
- *		_tot_quantity	The total value left to distribute for the providers'
- *							maximal quantity
- *		_tot_difficulty	The total value left to distribute for the providers'
- *							extraction difficulty
- *		_tot_recovery	The total value left to distribute for the providers'
- *							recovery rate
- *
- * Returns:
- *		_providers_left	The updated value for the amount of providers left
- *		_tot_quantity	The updated value for the total maximal quantity to
- *							distribute
- *		_tot_difficulty	The updated value for the total extraction difficulty
- *							to distribute
- *		_tot_recovery	The updated value for the total recovery rate to
- *							distribute
- */
-DROP FUNCTION IF EXISTS verse.create_resource_provider(
-	INT , verse.resprov_generator_type , INT , DOUBLE PRECISION ,
-	DOUBLE PRECISION , DOUBLE PRECISION );
-CREATE FUNCTION verse.create_resource_provider(
-			_planet					INT ,
-			_data					verse.resprov_generator_type ,
-			INOUT _providers_left	INT ,
-			INOUT _tot_quantity		DOUBLE PRECISION ,
-			INOUT _tot_difficulty	DOUBLE PRECISION ,
-			INOUT _tot_recovery		DOUBLE PRECISION )
-		STRICT VOLATILE
-		SECURITY INVOKER
-	AS $create_resource_provider$
-
-DECLARE
-	_quantity		DOUBLE PRECISION;
-	_difficulty		DOUBLE PRECISION;
-	_recovery		DOUBLE PRECISION;
-
-BEGIN
-	_quantity := verse.get_random_part( _tot_quantity , _providers_left ,
-		_data.quantity_avg , _data.quantity_dev );
-	_difficulty := verse.get_random_part( _tot_difficulty , _providers_left ,
-		_data.difficulty_avg , _data.difficulty_dev );
-	_recovery := verse.get_random_part( _tot_recovery , _providers_left ,
-		_data.recovery_avg , _data.recovery_dev );
-
-	PERFORM sys.write_sql_log( 'UniverseGenerator' , 'TRACE'::log_level ,
-		'Resource #' || _data.resource_name_id || ',  planet #' || _planet
-		|| ': quantity ' || _quantity || ' , difficulty '
-		|| _difficulty || ' , recovery ' || _recovery );
-
-	INSERT INTO verse.resource_providers (
-			planet_id , resource_name_id , resprov_quantity_max ,
-			resprov_quantity , resprov_difficulty , resprov_recovery
-		) VALUES (
-			_planet , _data.resource_name_id , _quantity ,
-			_quantity , _difficulty , _recovery
-		);
-
-	_tot_quantity := _tot_quantity - _quantity;
-	_tot_difficulty := _tot_difficulty - _difficulty;
-	_tot_recovery := _tot_recovery - _recovery;
-	_providers_left := _providers_left - 1;
-END;
-$create_resource_provider$ LANGUAGE PLPGSQL;
-
-REVOKE EXECUTE
-	ON FUNCTION verse.create_resource_provider( INT ,
-			verse.resprov_generator_type , INT , DOUBLE PRECISION ,
-			DOUBLE PRECISION , DOUBLE PRECISION )
-	FROM PUBLIC;
-
-
-
-/*
- * Create resource providers for a given type of resource
- * 
- * This function will create resource providers for some specified type of
- * resource in an area of the universe. It tries to balance the generated
- * values according to the resource's definition.
- * 
- * Parameters:
- *		_area		The area to generate resource providers in
- *		_data		The identifier, definition and statistics for the type of
- *						resource
- */
-DROP FUNCTION IF EXISTS verse.create_resource_providers(
-	verse.generator_area_type , verse.resprov_generator_type );
-CREATE FUNCTION verse.create_resource_providers(
-			_area verse.generator_area_type ,
-			_data verse.resprov_generator_type )
-		RETURNS VOID
-		STRICT VOLATILE
-		SECURITY INVOKER
-	AS $create_resource_providers$
-
-DECLARE
-	_ncount			INT;
-	_create			INT;
-	_tot_quantity	DOUBLE PRECISION;
-	_tot_difficulty	DOUBLE PRECISION;
-	_tot_recovery	DOUBLE PRECISION;
-	_planet			INT;
-
-BEGIN
-	_ncount := ( _area.x1 - _area.x0 + 1 ) * ( _area.y1 - _area.y0 + 1 ) * 5;
-
-	-- Determine the amount of providers to create
-	_create := FLOOR( ( _data.planets + _ncount ) * _data.presence - _data.providers )::INT;
-	IF _create <= 0 THEN
-		RETURN;
-	ELSIF _create > _ncount THEN
-		_create := _ncount;
-	END IF;
-
-	-- Compute the total delta for quantity, difficulty and recovery rate
-	_tot_quantity := verse.compute_rpp_delta( _data.providers , _create ,
-			_data.quantity , _data.quantity_avg , _data.quantity_dev );
-	_tot_difficulty := verse.compute_rpp_delta( _data.providers , _create ,
-			_data.difficulty , _data.difficulty_avg , _data.difficulty_dev );
-	_tot_recovery := verse.compute_rpp_delta( _data.providers , _create ,
-			_data.recovery , _data.recovery_avg , _data.recovery_dev );
-
-	PERFORM sys.write_sql_log( 'UniverseGenerator' , 'TRACE'::log_level ,
-		'Resource #' || _data.resource_name_id || ': ' || _create
-		|| ' new provider(s), quantity: ' || _tot_quantity || ' (avg. '
-		|| ( _tot_quantity / _create ) || ') , difficulty: '
-		|| _tot_difficulty || ' (avg. ' || ( _tot_difficulty / _create )
-		|| '), recovery: ' || _tot_recovery || ' (avg. '
-		|| _tot_recovery / _create || ')' );
-
-	-- Select random planets to add resource providers to
-	FOR _planet IN SELECT * FROM verse.list_random_planets_in( _area , _create )
-	LOOP
-		SELECT INTO _create , _tot_quantity , _tot_difficulty , _tot_recovery
-			* FROM verse.create_resource_provider( _planet , _data , _create ,
-					_tot_quantity , _tot_difficulty , _tot_recovery );
-	END LOOP;
-
-END;
-$create_resource_providers$ LANGUAGE PLPGSQL;
-
-REVOKE EXECUTE
-	ON FUNCTION verse.create_resource_providers( verse.generator_area_type ,
-			verse.resprov_generator_type )
-	FROM PUBLIC;
-
-
-
-/*
- * Create resource providers in some area of the universe
- * 
- * This function creates resource providers in the specified area using the
- * statistics collected before the area was created to balance the resource
- * providers' parameters.
- * 
- * Parameters:
- *		_area		The area to generate resource providers in
- */
-DROP FUNCTION IF EXISTS verse.create_resource_providers( verse.generator_area_type );
-CREATE FUNCTION verse.create_resource_providers( _area verse.generator_area_type )
-		RETURNS VOID
-		STRICT VOLATILE
-		SECURITY INVOKER
-	AS $create_resource_providers$
-
-DECLARE
-	_rp_data		verse.resprov_generator_type;
-
-BEGIN
-	FOR _rp_data IN SELECT * FROM rp_stats
-	LOOP
-		PERFORM verse.create_resource_providers( _area , _rp_data );
-	END LOOP;
-END;
-$create_resource_providers$ LANGUAGE PLPGSQL;
-
-
-REVOKE EXECUTE
-	ON FUNCTION verse.create_resource_providers( verse.generator_area_type )
-	FROM PUBLIC;
diff --git a/legacyworlds-server-data/db-structure/parts/040-functions/145-resource-providers.sql b/legacyworlds-server-data/db-structure/parts/040-functions/145-resource-providers.sql
deleted file mode 100644
index ebab70b..0000000
--- a/legacyworlds-server-data/db-structure/parts/040-functions/145-resource-providers.sql
+++ /dev/null
@@ -1,560 +0,0 @@
--- LegacyWorlds Beta 6
--- PostgreSQL database scripts
---
--- Resource providers functions
---
--- Copyright(C) 2004-2012, DeepClone Development
--- --------------------------------------------------------
-
-
-/*
- * Compute resource provider regeneration
- * 
- * This function computes the quantity in a resource provider after it has
- * been regenerated.
- * 
- * Parameters:
- *		_quantity		The current quantity of resources in the provider
- *		_max			The maximal amount of resources supported by the
- *							provider
- *		_recovery_rate	The provider's recovery rate
- *
- * Returns:
- *		?				The new quantity of resources.
- */
-CREATE OR REPLACE FUNCTION verse.compute_provider_regeneration(
-				_quantity		DOUBLE PRECISION ,
-				_max			DOUBLE PRECISION ,
-				_recovery_rate	DOUBLE PRECISION )
-		RETURNS DOUBLE PRECISION
-		STRICT IMMUTABLE
-		SECURITY INVOKER
-	AS $compute_provider_regeneration$
-
-DECLARE
-	_uc_recovery	DOUBLE PRECISION;
-	_uc_dampening	DOUBLE PRECISION;
-	_uc_ticks		DOUBLE PRECISION;
-	_result			DOUBLE PRECISION;
-
-BEGIN
-	_uc_recovery := sys.get_constant( 'game.resources.recovery' );
-	_uc_dampening := sys.get_constant( 'game.resources.recoveryDampening' );
-	_uc_ticks := 1440; -- FIXME: this should be a constant
-	
-	_result := ( 1 - _quantity / _max ) ^ _uc_dampening;
-	_result := _quantity + _result * _recovery_rate * _uc_recovery / _uc_ticks;
-
-	IF _result > _max THEN
-		_result := _max;
-	END IF;
-
-	RETURN _result;
-END;
-$compute_provider_regeneration$ LANGUAGE PLPGSQL;
-
-
-REVOKE EXECUTE
-	ON FUNCTION verse.compute_provider_regeneration(
-		DOUBLE PRECISION , DOUBLE PRECISION ,
-		DOUBLE PRECISION )
-	FROM PUBLIC;
-
-
-
-/*
- * Mining settings view
- * ---------------------
- *
- * This view lists mining settings being used on planets owned by empires
- * for each resource providers. The settings are taken from planet-specific
- * settings if they are available, or from empire-wide settings.
- * 
- * Columns:
- *
- *		planet_id			The planet's identifier
- *		resource_name_id	The type of resources
- *		mset_weight			The setting to use for mining priorities
- *		mset_specific		True if the settings are specific for this planet,
- *								false if empire-wise settings are in use. 
- */
-DROP VIEW IF EXISTS emp.mining_settings_view CASCADE;
-CREATE VIEW emp.mining_settings_view
-	AS SELECT planet_id , resource_name_id ,
-				( CASE
-					WHEN _pl_settings.planet_id IS NULL THEN
-						_emp_settings.empmset_weight
-					ELSE
-						_pl_settings.emppmset_weight
-				END ) AS mset_weight ,
-				( _pl_settings.planet_id IS NOT NULL ) AS mset_specific
-			FROM verse.resource_providers
-				INNER JOIN emp.planets
-					USING ( planet_id )
-				INNER JOIN emp.mining_settings _emp_settings
-					USING ( empire_id , resource_name_id )
-				LEFT OUTER JOIN emp.planet_mining_settings _pl_settings
-					USING ( planet_id , empire_id , resource_name_id );
-
-GRANT SELECT
-	ON emp.mining_settings_view
-	TO :dbuser;
-
-
-
-/*
- * Compute a resource provider's extraction factor
- * 
- * This function computes the extraction factor - a multiplier which makes
- * mining more costly if the difficulty is high or if a provider is almost
- * empty - based on a provider's fill ratio and difficulty.
- * 
- * The complete formula can be read on the Wiki:
- *		https://wiki.legacyworlds.com/wiki/Mining#Resource_provider_extraction
- *
- * Parameters:
- * 		_fill_ratio		The ratio between the provider's current and maximal
- *							quantities
- *		_difficulty		The provider's extraction difficulty.
- *
- * Returns:
- *		?				The provider's extraction factor
- */
-DROP FUNCTION IF EXISTS verse.get_extraction_factor( 
-	DOUBLE PRECISION , DOUBLE PRECISION );
-CREATE FUNCTION verse.get_extraction_factor(
-		_fill_ratio DOUBLE PRECISION ,
-		_difficulty	DOUBLE PRECISION )
-	RETURNS DOUBLE PRECISION
-	STRICT IMMUTABLE
-	SECURITY INVOKER
-AS $get_extraction_factor$
-
-	SELECT ( 1 - $2 * 0.5 ) * POW( $1 , 1.5 + 2 * $2 );
-
-$get_extraction_factor$ LANGUAGE SQL;
-
-REVOKE EXECUTE
-	ON FUNCTION verse.get_extraction_factor( 
-		DOUBLE PRECISION , DOUBLE PRECISION )
-	FROM PUBLIC;
-
-
-/*
- * Planet resources type
- * ----------------------
- * 
- * This type is used to transmit a planet's resources information to the game
- * server. It contains the resource's description, the planet's economic data
- * and, if there is a resource provider on the planet, the provider's
- * information and mining priority.
- */
-DROP TYPE IF EXISTS emp.planet_resources_type CASCADE;
-CREATE TYPE emp.planet_resources_type AS (
-	/* Text identifier of the resource */
-	resource_identifier		TEXT ,
-	
-	/* Internationalised name of the resource */
-	resource_name			TEXT ,
-	
-	/* Internationalised description of the resource */
-	resource_description	TEXT ,
-	
-	/* Internationalised name of the category the resource is a part of, or
-	 * NULL if the resource is not in any category.
-	 */
-	resource_category		TEXT ,
-	
-	/* The planet's income for this resource, over a period of 12h RT/ 1 month
-	 * GT.
-	 */
-	pres_income				BIGINT ,
-	
-	/* The planet's upkeep for this resource, over a period of 12h RT/ 1 month
-	 * GT.
-	 */
-	pres_upkeep				BIGINT ,
-	
-	/* The current quantity of this resource invested in the planet's build
-	 * queues.
-	 */
-	pres_invested			BIGINT ,
-	
-	/** The capacity of the resource provider, if there is one, or NULL if
-	 * there is no provider.
-	 */
-	resprov_capacity		BIGINT ,
-	
-	/** The quantity of resources in the resource provider, if there is one,
-	 * or NULL if there is no provider.
-	 */
-	resprov_quantity		BIGINT ,
-	
-	/** The extraction difficulty of the resource provider as a percentage, or
-	 * NULL if there is no provider.
-	 */
-	resprov_difficulty		INT ,
-	
-	/* The mining priority for the resource in question, or NULL if there is no
-	 * resource provider.
-	 */
-	mset_weight				INT
-);
-
-
-
-/*
- * Access all available information about a planet's resources
- *
- * This function retrieves resource information about an empire-owned planet,
- * and converts it to the format used in the game server (rounded quantities,
- * difficulty as percentage, internationalised strings).
- * 
- * FIXME:
- *		1) pres_invested is always set to 0 in the output
- *		2) time-related computations use hardcoded values
- * 
- * Parameters:
- *		_planet		The planet's identifier
- *
- * Returns:
- *		N/A			Resource information records, ordered using resource
- *						weights.
- */
-DROP FUNCTION IF EXISTS emp.get_planet_resources( INT );
-CREATE FUNCTION emp.get_planet_resources( _planet INT )
-	RETURNS SETOF emp.planet_resources_type
-	STRICT STABLE
-	SECURITY DEFINER
-AS $get_planet_resources$
-
-	SELECT _name_str.name AS resource_identifier ,
-			_name_trans.translated_string AS resource_name ,
-			_desc_trans.translated_string AS resource_description ,
-			_cat_trans.translated_string AS resource_category ,
-			FLOOR( pres_income * 720.0 )::BIGINT AS pres_income ,
-			CEIL( pres_upkeep * 720.0 )::BIGINT AS pres_upkeep ,
-			0::BIGINT AS pres_invested ,
-			ROUND( resprov_quantity_max )::BIGINT AS resprov_capacity ,
-			ROUND( resprov_quantity )::BIGINT AS resprov_quantity ,
-			ROUND( 100.0 * resprov_difficulty )::INT AS resprov_difficulty ,
-			mset_weight
-
-		FROM defs.ordered_resources_view
-			INNER JOIN verse.planet_resources USING ( resource_name_id )
-			INNER JOIN emp.planets USING ( planet_id )
-			INNER JOIN naming.empire_names _emp_name
-				ON _emp_name.id = empire_id
-			INNER JOIN users.credentials _user
-				ON _emp_name.owner_id = _user.address_id
-			INNER JOIN defs.strings _name_str
-				ON _name_str.id = resource_name_id
-			INNER JOIN defs.translations _name_trans
-				ON _name_trans.string_id = resource_name_id
-					AND _name_trans.lang_id = _user.language_id
-			INNER JOIN defs.translations _desc_trans
-				ON _desc_trans.string_id = resource_description_id
-					AND _desc_trans.lang_id = _user.language_id
-			LEFT OUTER JOIN defs.translations _cat_trans
-				ON _cat_trans.string_id = resource_category_id
-					AND _cat_trans.lang_id = _user.language_id
-			LEFT OUTER JOIN verse.resource_providers
-				USING ( planet_id , resource_name_id )
-			LEFT OUTER JOIN emp.mining_settings_view
-				USING ( planet_id , resource_name_id )
-
-	WHERE planet_id = $1
-	
-	ORDER BY resource_ordering;
-
-$get_planet_resources$ LANGUAGE SQL;
-
-REVOKE EXECUTE
-	ON FUNCTION emp.get_planet_resources( INT )
-	FROM PUBLIC;
-GRANT EXECUTE
-	ON FUNCTION emp.get_planet_resources( INT )
-	TO :dbuser;
-
-
-
-/*
- * Planet mining update data
- * --------------------------
- * 
- * This type is used by the records used by planet mining updates to compute a
- * planet's mining output.
- */
-DROP TYPE IF EXISTS emp.planet_mining_type CASCADE;
-CREATE TYPE emp.planet_mining_type AS (
-	/* The planet's identifier */
-	planet			INT ,
-
-	/* The resource's identifier */
-	resource		INT ,
-
-	/* The provider's quantity of resources */
-	quantity		DOUBLE PRECISION ,
-
-	/* The provider's maximal quantity of resources */
-	quantity_max	DOUBLE PRECISION ,
-
-	/* The provider's extraction difficulty */
-	difficulty		DOUBLE PRECISION ,
-
-	/* The empire who owns the planet, or NULL if the planet is neutral */
-	empire			INT ,
-
-	/* The planet's happiness, or NULL if the planet is neutral */
-	happiness		REAL ,
-
-	/* The weight computed from the resource's extraction priority as
-	 * set by either the empire in general or the planet-specific settings,
-	 * or NULL if the planet is neutral.
-	 */
-	weight			DOUBLE PRECISION ,
-
-	/* The total weight computed from either the empire-wide or the
-	 * planet-specific mining settings, or NULL if the planet is neutral.
-	 */
-	total_weight	DOUBLE PRECISION
-);
-
-
-/*
- * Mining computation - Weights view
- * ----------------------------------
- * 
- * This view computes the actual values used in the mining computations for
- * each resource provider on all empire-owned planets.
- * 
- * Columns:
- *		planet_id			The planet's identifier
- *		resource_name_id	The resource type's identifier
- *		pmc_weight			The computed weight
- */
-DROP VIEW IF EXISTS emp.scaled_mining_weights_view CASCADE;
-CREATE VIEW emp.scaled_mining_weights_view
-	AS SELECT planet_id , resource_name_id ,
-				POW( sys.get_constant( 'game.resources.weightBase' ) ,
-					mset_weight ) AS pmc_weight
-			FROM emp.mining_settings_view;
-
-
-/*
- * Mining computation - Total weights view
- * ----------------------------------------
- *
- * This view computes per-planet totals for actual mining weights.
- * 
- * Columns:
- *		planet_id			The planet's identifier
- *		pmc_total			The sum of all mining weights on the planet.
- */
-DROP VIEW IF EXISTS emp.total_mining_weights_view CASCADE;
-CREATE VIEW emp.total_mining_weights_view
-	AS SELECT planet_id , SUM( pmc_weight ) AS pmc_total
-			FROM emp.scaled_mining_weights_view
-			GROUP BY planet_id;
-
-
-/*
- * Compute the extracted quantity
- * -------------------------------
- *
- * Compute the quantity of resources that will be extracted from a resource
- * provider at the next game update. This function is used by the mining
- * update, obviously, but also by the various functions which control mining
- * settings and by ownership changes.
- *
- * Parameters:
- *		_input		Data about the resource provider to update
- *
- * Returns:
- * 		?			The quantity that will be extracted from the provider
- */
-DROP FUNCTION IF EXISTS emp.mining_compute_extraction( emp.planet_mining_type );
-CREATE FUNCTION emp.mining_compute_extraction( _input emp.planet_mining_type )
-		RETURNS DOUBLE PRECISION
-		LANGUAGE PLPGSQL
-		STRICT IMMUTABLE
-		SECURITY INVOKER
-	AS $resprov_compute_extraction$
-
-DECLARE
-	_extraction	DOUBLE PRECISION;
-	_allocation	DOUBLE PRECISION;
-	_production	DOUBLE PRECISION;
-	_quantity	DOUBLE PRECISION;
-
-BEGIN
-	IF _input.empire IS NULL THEN
-		RETURN 0;
-	END IF;
-
-	_extraction := verse.get_extraction_factor(
-		_input.quantity / _input.quantity_max ,
-		_input.difficulty );
-	_allocation := _input.weight / _input.total_weight;
-	_production := verse.adjust_production(
-			verse.get_raw_production( _input.planet , 'MINE' ) ,
-			_input.happiness )
-		* sys.get_constant( 'game.resources.extraction' )
-		/ 1440.0; -- FIXME: hardcoded!
-
-	_quantity := _allocation * _production * _extraction;
-	IF _quantity > _input.quantity THEN
-		_quantity := _input.quantity;
-	END IF;
-
-	RETURN _quantity;
-END; 
-$resprov_compute_extraction$;
-
-REVOKE EXECUTE
-	ON FUNCTION emp.mining_compute_extraction( emp.planet_mining_type )
-	FROM PUBLIC;
-
-
-/*
- * Get resource extraction input for a single planet
- * --------------------------------------------------
- *
- * This function locks and retrieves all data required to update a single
- * planet's resource extraction quantities. It is used when a planet's
- * owner changes (including planet assignment) or when a planet's specific
- * mining settings are modified.
- * 
- * Parameters:
- *		_planet		The planet's identifier
- *
- * Returns:
- *		the set of emp.planet_mining_type records for the planet  
- */
-DROP FUNCTION IF EXISTS verse.mining_get_input( _planet INT );
-CREATE FUNCTION verse.mining_get_input( _planet INT )
-	RETURNS SETOF emp.planet_mining_type
-	LANGUAGE SQL
-	STRICT VOLATILE
-	SECURITY INVOKER
-AS $mining_get_input$
-
-		SELECT planet_id AS planet ,
-			resource_name_id AS resource,
-			resprov_quantity AS quantity ,
-			resprov_quantity_max AS quantity_max ,
-			resprov_difficulty AS difficulty ,
-			empire_id AS empire ,
-			( happy_pop / _planet.population ) AS happiness ,
-			pmc_weight AS weight ,
-			pmc_total AS total_weight
-
-		FROM verse.planets _planet
-			INNER JOIN verse.resource_providers _resprov
-				ON planet_id = name_id
-			INNER JOIN verse.planet_resources _pres
-				USING ( planet_id , resource_name_id )
-			LEFT OUTER JOIN (
-						SELECT _emp_planet.empire_id , _emp_planet.planet_id ,
-								_emset.resource_name_id , pmc_weight ,
-								pmc_total , _happ.current AS happy_pop
-		
-							FROM emp.planets _emp_planet
-								INNER JOIN emp.empires _emp
-									ON _emp_planet.empire_id = _emp.name_id
-								INNER JOIN emp.mining_settings _emset
-									USING ( empire_id )
-								INNER JOIN verse.planet_happiness _happ
-									USING ( planet_id )
-								INNER JOIN emp.scaled_mining_weights_view
-									USING ( planet_id , resource_name_id)
-								INNER JOIN emp.total_mining_weights_view
-									USING ( planet_id )
-								LEFT OUTER JOIN (
-											SELECT * FROM emp.planet_mining_settings
-												FOR SHARE
-										) AS _pmset
-									USING ( empire_id , planet_id , resource_name_id )
-	
-							WHERE _emp_planet.planet_id = $1
-
-							FOR SHARE OF _emp_planet , _emp , _emset , _happ 
-					) AS _owner
-				USING ( planet_id , resource_name_id )
-	
-		WHERE _planet.name_id = $1
-	
-		FOR UPDATE OF _resprov , _pres
-		FOR SHARE OF _planet ;
-
-$mining_get_input$;
-
-REVOKE EXECUTE
-	ON FUNCTION verse.mining_get_input( _planet INT )
-	FROM PUBLIC;
-
-
-/*
- * Get resource extraction input for a whole empire
- * -------------------------------------------------
- *
- * This function retrieves all mining information for a whole empire. It is
- * used to recompute extracted quantities when global settings are updated.
- * 
- * Parameters:
- *		_empire		The empire's identifier
- *
- * Returns:
- *		the set of emp.planet_mining_type records for the empire  
- */
-DROP FUNCTION IF EXISTS emp.mining_get_input( _empire INT );
-CREATE FUNCTION emp.mining_get_input( _empire INT )
-	RETURNS SETOF emp.planet_mining_type
-	LANGUAGE SQL
-	STRICT VOLATILE
-	SECURITY INVOKER
-AS $mining_get_input$
-
-		SELECT planet_id AS planet ,
-			resource_name_id AS resource,
-			resprov_quantity AS quantity ,
-			resprov_quantity_max AS quantity_max ,
-			resprov_difficulty AS difficulty ,
-			empire_id AS empire ,
-			_happ.current / _planet.population AS happiness ,
-			pmc_weight AS weight ,
-			pmc_total AS total_weight
-
-		FROM emp.planets _emp_planet
-			INNER JOIN emp.empires _emp
-				ON _emp_planet.empire_id = _emp.name_id
-			INNER JOIN emp.mining_settings _emset
-				USING ( empire_id )
-			INNER JOIN verse.planets _planet
-				ON _planet.name_id = _emp_planet.planet_id
-			INNER JOIN verse.resource_providers _resprov
-				USING ( planet_id , resource_name_id )
-			INNER JOIN verse.planet_resources _pres
-				USING ( planet_id , resource_name_id )
-			INNER JOIN verse.planet_happiness _happ
-				USING ( planet_id )
-			INNER JOIN emp.scaled_mining_weights_view
-				USING ( planet_id , resource_name_id )
-			INNER JOIN emp.total_mining_weights_view
-				USING ( planet_id )
-			LEFT OUTER JOIN (
-						SELECT * FROM emp.planet_mining_settings
-							FOR SHARE
-					) AS _pmset
-				USING ( empire_id , planet_id , resource_name_id )
-
-		WHERE _emp_planet.empire_id = $1
-	
-		FOR UPDATE OF _resprov , _pres
-		FOR SHARE OF _emp_planet , _emp , _emset , _happ , _planet ;
-
-$mining_get_input$;
-
-REVOKE EXECUTE
-	ON FUNCTION emp.mining_get_input( _empire INT )
-	FROM PUBLIC;
diff --git a/legacyworlds-server-data/db-structure/parts/040-functions/147-empire-mining.sql b/legacyworlds-server-data/db-structure/parts/040-functions/147-empire-mining.sql
deleted file mode 100644
index c2c0096..0000000
--- a/legacyworlds-server-data/db-structure/parts/040-functions/147-empire-mining.sql
+++ /dev/null
@@ -1,348 +0,0 @@
--- LegacyWorlds Beta 6
--- PostgreSQL database scripts
---
--- Functions that control and compute empire mining
---
--- Copyright(C) 2004-2010, DeepClone Development
--- --------------------------------------------------------
-
-
-/*
- * Prepare for an update on empire mining settings
- * 
- * This function creates a temporary table mimicking the structure of
- * emp.mining_settings, and stores default settings into it.
- * 
- * Parameters:
- *		_empire_id		The empire's identifier
- *
- * Returns:
- *		?				True if the empire exists, false otherwise
- */
-DROP FUNCTION IF EXISTS emp.mset_update_start( INT );
-CREATE FUNCTION emp.mset_update_start( _empire_id INT )
-		RETURNS BOOLEAN
-		STRICT VOLATILE
-		SECURITY DEFINER
-	AS $mset_update_start$
-BEGIN
-
-	CREATE TEMPORARY TABLE mset_update(
-		empire_id			INT ,
-		resource_name		TEXT ,
-		empmset_weight		INT
-	) ON COMMIT DROP;
-
-	INSERT INTO mset_update
-		SELECT _mset.empire_id , _str.name , 2
-			FROM emp.empires _empire
-				INNER JOIN emp.mining_settings _mset
-					ON _empire.name_id = _mset.empire_id
-				INNER JOIN defs.strings _str
-					ON _str.id = _mset.resource_name_id
-			WHERE _empire.name_id = _empire_id
-			FOR SHARE OF _empire
-			FOR UPDATE OF _mset;
-
-	RETURN FOUND;
-
-END;
-$mset_update_start$ LANGUAGE PLPGSQL;
-
-REVOKE EXECUTE
-	ON FUNCTION emp.mset_update_start( INT )
-	FROM PUBLIC;
-GRANT EXECUTE
-	ON FUNCTION emp.mset_update_start( INT )
-	TO :dbuser;
-
-
-/*
- * Prepare for an update on planet-specific mining settings
- * 
- * This function creates a temporary table mimicking the structure of
- * emp.planet_mining_settings, and stores default settings into it, using the
- * planet's list of resource provider as the source.
- * 
- * Parameters:
- *		_empire_id		The empire's identifier
- *		_planet_id		The planet's identifier
- *
- * Returns:
- *		?				True if the empire exists and owns the planet and if
- *							the planet is using planet-specific settings,
- *							false otherwise
- */
-DROP FUNCTION IF EXISTS emp.mset_update_start( INT , INT );
-CREATE FUNCTION emp.mset_update_start( _empire_id INT , _planet_id INT )
-		RETURNS BOOLEAN
-		STRICT VOLATILE
-		SECURITY DEFINER
-	AS $mset_update_start$
-BEGIN
-
-	CREATE TEMPORARY TABLE mset_update(
-		empire_id			INT ,
-		planet_id			INT ,
-		resource_name		TEXT ,
-		empmset_weight		INT
-	) ON COMMIT DROP;
-	
-	PERFORM 1
-		FROM emp.empires _empire
-			INNER JOIN emp.planets _emp_planet
-				ON _empire.name_id = _emp_planet.empire_id
-			INNER JOIN verse.planets _planet
-				ON _planet.name_id = _emp_planet.planet_id
-			INNER JOIN verse.resource_providers _resprov
-				ON _resprov.planet_id = _planet.name_id
-			INNER JOIN emp.planet_mining_settings _mset
-				ON _mset.planet_id = _planet.name_id
-					AND _mset.empire_id = _empire.name_id
-					AND _mset.resource_name_id = _resprov.resource_name_id
-		WHERE _empire.name_id = _empire_id
-				AND _planet.name_id = _planet_id
-		FOR SHARE OF _empire, _emp_planet , _planet , _resprov
-		FOR UPDATE OF _mset;
-	IF NOT FOUND THEN
-		RETURN FALSE;
-	END IF;
-	
-	PERFORM 1
-		FROM emp.planet_mining_settings
-		WHERE empire_id = _empire_id AND planet_id = _planet_id
-		FOR UPDATE;
-
-	INSERT INTO mset_update
-		SELECT _empire_id , _planet_id , _str.name , 2
-			FROM verse.resource_providers
-				INNER JOIN defs.strings _str
-					ON _str.id = resource_name_id
-			WHERE planet_id = _planet_id;
-
-	RETURN TRUE;
-
-END;
-$mset_update_start$ LANGUAGE PLPGSQL;
-
-REVOKE EXECUTE
-	ON FUNCTION emp.mset_update_start( INT , INT )
-	FROM PUBLIC;
-GRANT EXECUTE
-	ON FUNCTION emp.mset_update_start( INT , INT )
-	TO :dbuser;
-
-
-
-/*
- * Update the weight of some resource
- * 
- * This function updates the weight of a resource in the temporary table. It
- * must be called after emp.mset_update_start() has initialised the table.
- *
- * Parameters:
- *		_resource			The resource's text identifier
- *		_weight				The setting's new value
- *
- * Returns:
- *		?					True if the resource exists, false otherwise.
- */
-DROP FUNCTION IF EXISTS emp.mset_update_set( TEXT , INT );
-CREATE FUNCTION emp.mset_update_set( _resource TEXT , _weight INT )
-		RETURNS BOOLEAN
-		STRICT VOLATILE
-		SECURITY DEFINER
-	AS $mset_update_set$
-BEGIN
-
-	UPDATE mset_update
-		SET empmset_weight = _weight
-		WHERE resource_name = _resource;
-	RETURN FOUND;
-
-END;
-$mset_update_set$ LANGUAGE PLPGSQL;
-
-
-REVOKE EXECUTE
-	ON FUNCTION emp.mset_update_set( TEXT , INT )
-	FROM PUBLIC;
-GRANT EXECUTE
-	ON FUNCTION emp.mset_update_set( TEXT , INT )
-	TO :dbuser;
-
-
-
-/*
- * Apply a pending update to empire or planet mining settings
- * 
- * This function is called once mining settings (whether empire-wise or
- * planet-specific) have been uploaded. It will apply all changes to the
- * actual mining settings table.
- * 
- * Returns:
- *		?			True if the update was applied, false if one of the
- *						weights was invalid.
- */
-DROP FUNCTION IF EXISTS emp.mset_update_apply( );
-CREATE FUNCTION emp.mset_update_apply( )
-		RETURNS BOOLEAN
-		STRICT VOLATILE
-		SECURITY DEFINER
-	AS $mset_update_apply$
-
-DECLARE
-	_empire	INT;
-	_planet	INT;
-
-BEGIN
-	BEGIN
-
-		-- Get empire and planet identifier (will cause exception if this is
-		-- not a planet settings update).
-		SELECT INTO _empire , _planet
-				empire_id , planet_id
-			FROM mset_update
-			LIMIT 1;
-
-		-- Delete then re-insert all settings for the planet
-		DELETE FROM emp.planet_mining_settings
-			WHERE empire_id = _empire AND planet_id = _planet;
-		INSERT INTO emp.planet_mining_settings (
-					empire_id , planet_id , resource_name_id ,
-					emppmset_weight
-			) SELECT empire_id , planet_id ,
-					_str.id , empmset_weight
-				FROM mset_update
-					INNER JOIN defs.strings _str
-						ON _str.name = resource_name;
-
-		-- Update the planet's extraction
-		UPDATE verse.planet_resources
-			SET pres_income = emp.mining_compute_extraction( _update_row )
-			FROM verse.mining_get_input( _planet ) _update_row
-			WHERE planet_id = _update_row.planet
-				AND resource_name_id = _update_row.resource;
-
-	EXCEPTION
-
-		WHEN undefined_column THEN
-		
-			-- Get empire identifier
-			SELECT INTO _empire empire_id
-				FROM mset_update LIMIT 1;
-
-			-- Update the empire's settings
-			UPDATE emp.mining_settings _settings
-				SET empmset_weight = _update.empmset_weight
-				FROM mset_update _update
-					INNER JOIN defs.strings _str
-						ON _str.name = _update.resource_name
-				WHERE _update.empire_id = _settings.empire_id
-					AND _str.id = _settings.resource_name_id;
-
-			-- Update extracted quantities for the whole empire
-			UPDATE verse.planet_resources
-				SET pres_income = emp.mining_compute_extraction( _update_row )
-				FROM emp.mining_get_input( _empire ) _update_row
-				WHERE planet_id = _update_row.planet
-					AND resource_name_id = _update_row.resource;
-
-	END;
-	RETURN TRUE;
-
-EXCEPTION
-
-	-- One of the weights was invalid
-	WHEN check_violation THEN
-		RETURN FALSE;
-
-END;
-$mset_update_apply$ LANGUAGE PLPGSQL;
-
-
-REVOKE EXECUTE
-	ON FUNCTION emp.mset_update_apply( )
-	FROM PUBLIC;
-GRANT EXECUTE
-	ON FUNCTION emp.mset_update_apply( )
-	TO :dbuser;
-
-
-/*
- * Toggle the source of a planet's mining settings
- * ------------------------------------------------
- * 
- * This function causes a planet to be switched between empire-wide and
- * planet-specific mining settings.
- * 
- * Parameters:
- *		_empire		The empire's identifier
- *		_planet		The planet's identifier
- *
- * Returns:
- *		?			TRUE if the operation succeeded, FALSE if the planet
- *						didn't exist or wasn't owned by the specified empire.
- */
-DROP FUNCTION IF EXISTS emp.mset_toggle_source( INT , INT );
-CREATE FUNCTION emp.mset_toggle_source( _empire INT , _planet INT )
-		RETURNS BOOLEAN
-		LANGUAGE PLPGSQL
-		STRICT VOLATILE
-		SECURITY DEFINER
-	AS $mset_toggle_source$
-BEGIN
-	PERFORM 1
-		FROM emp.planets _ep
-			INNER JOIN verse.resource_providers _rp
-				USING ( planet_id )
-			LEFT OUTER JOIN (
-				SELECT * FROM emp.planet_mining_settings _pms
-					WHERE planet_id = _planet
-						AND empire_id = _empire
-					FOR UPDATE
-				) _pms USING ( planet_id , empire_id , resource_name_id )
-		WHERE _ep.empire_id = _empire
-			AND _ep.planet_id = _planet
-		FOR UPDATE OF _ep;
-	IF NOT FOUND THEN
-		RETURN FALSE;
-	END IF;
-
-	PERFORM 1 FROM emp.planet_mining_settings _pms
-		WHERE planet_id = _planet AND empire_id = _empire;
-	IF FOUND THEN
-
-		-- Remove planet-specific settings, then update extracted quantities
-		DELETE FROM emp.planet_mining_settings
-			WHERE planet_id = _planet AND empire_id = _empire;
-		UPDATE verse.planet_resources
-			SET pres_income = emp.mining_compute_extraction( _update_row )
-			FROM verse.mining_get_input( _planet ) _update_row
-			WHERE planet_id = _update_row.planet
-				AND resource_name_id = _update_row.resource;
-
-	ELSE
-
-		-- Create planet-specific settings using empire-wide values as the
-		-- defaults. Because of that, no extraction update is necessary.
-		INSERT INTO emp.planet_mining_settings(
-				empire_id , planet_id , resource_name_id , emppmset_weight
-			) SELECT empire_id  , planet_id , resource_name_id , empmset_weight
-				FROM verse.resource_providers _rp
-					INNER JOIN emp.mining_settings
-						USING ( resource_name_id )
-				WHERE planet_id = _planet AND empire_id = _empire;
-
-	END IF;
-	
-	RETURN TRUE;
-END;
-$mset_toggle_source$;
-
-REVOKE EXECUTE
-	ON FUNCTION emp.mset_toggle_source( INT , INT )
-	FROM PUBLIC;
-GRANT EXECUTE
-	ON FUNCTION emp.mset_toggle_source( INT , INT )
-	TO :dbuser;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/parts/040-functions/170-event-definitions.sql b/legacyworlds-server-data/db-structure/parts/040-functions/170-event-definitions.sql
deleted file mode 100644
index f593da8..0000000
--- a/legacyworlds-server-data/db-structure/parts/040-functions/170-event-definitions.sql
+++ /dev/null
@@ -1,897 +0,0 @@
--- LegacyWorlds Beta 6
--- PostgreSQL database scripts
---
--- Functions allowing event definitions to be added to the
--- database
---
--- Copyright(C) 2004-2012, DeepClone Development
--- --------------------------------------------------------
-
-
-/*
- * Return values for event definition functions
- * ---------------------------------------------
- */
-DROP TYPE IF EXISTS events.evdef_create_result CASCADE;
-CREATE TYPE events.evdef_create_result AS ENUM(
-	/* The event type definition function succeeded. If it was the initial
-	 * creation function or a field creation function, this means the creation
-	 * can continue. If it was the finalisation function, this means the event
-	 * definition has been added. 
-	 */
-	'OK' ,
-	
-	/* A bad identifier was specified. This value is returned by both the
-	 * initial creation function and event field definition functions.
-	 */
-	'BAD_ID' ,
-	
-	/* An internationalised string (either an event type's name or template)
-	 * could not be found.
-	 */
-	'BAD_STRINGS' ,
-
-	/* Duplicate event or field identifier found. This value is returned by
-	 * the finalisation function, with its "_fld" set to NULL if the duplicate
-	 * identifier is the event's.
-	 */
-	'DUPLICATE' ,
-
-	/* Bad event or field specification found. This value is returned by the
-	 * finalisation function when an event or field cannot be inserted due to
-	 * check failures.
-	 */
-	'BAD_SPEC' ,
-	
-	/* This error code is returned when trying to finalise an event after one
-	 * of the definition calls failed. 
-	 */
-	'NO_DATA'
-);
-
-
-
-/*
- * Start defining a new event type
- * -------------------------------
- * 
- * This function creates a temporary table used to defgine a new type of
- * event. No checks beyond the length and contents of the event type's
- * identifier are made at this point.
- * 
- * Note: the temporary table will be created in all cases, even when the
- *		identifier is invalid.
- * 
- * Parameters:
- *		_id			The identifier of the event type
- *		_prio		The event type's default priority
- *		_adj		Whether the player may adjust the priority for this type
- *						of events.
- *		_i18n		The "base" of the I18N strings identifiers; the function
- *						will attempt to use "<_i18n>Name" as the name's
- *						identifier and "<_i18n>Template" as the template's.
- *
- * Returns:
- * 		???			An error code: OK or BAD_ID
- *						(see events.evdef_create_result)
- */
-DROP FUNCTION IF EXISTS events.evdef_start( TEXT , INT , BOOLEAN , TEXT );
-CREATE FUNCTION events.evdef_start(
-			_id		TEXT ,
-			_prio	INT ,
-			_adj	BOOLEAN ,
-			_i18n	TEXT )
-		RETURNS events.evdef_create_result
-		LANGUAGE PLPGSQL
-		STRICT VOLATILE SECURITY DEFINER
-	AS $evdef_start$
-
-DECLARE
-	_name_id		INT;
-	_template_id	INT;
-
-BEGIN
-	CREATE TEMPORARY TABLE evdef_temp(
-		evdef_id		TEXT ,
-		evfld_id		TEXT ,
-		evfld_typespec	TEXT
-	) ON COMMIT DROP;
-	
-	IF LENGTH( _id ) < 2 OR LENGTH( _id ) > 48
-			OR NOT _id ~ '^[a-z\-]+$'
-	THEN
-		RETURN 'BAD_ID';
-	END IF;
-	
-	SELECT INTO _name_id id FROM defs.strings
-		WHERE name = _i18n || 'Name';
-	SELECT INTO _template_id id FROM defs.strings
-		WHERE name = _i18n || 'Template';
-	IF _name_id IS NULL OR _template_id IS NULL THEN
-		RETURN 'BAD_STRINGS';
-	END IF;
-
-	INSERT INTO evdef_temp( evdef_id , evfld_typespec )
-		VALUES( _id , _prio::TEXT || ',' || _adj::TEXT
-					|| ',' || _name_id || ',' || _template_id );
-	RETURN 'OK';
-END;
-$evdef_start$;
-
-REVOKE EXECUTE
-	ON FUNCTION events.evdef_start( TEXT , INT , BOOLEAN , TEXT )
-	FROM PUBLIC;
-GRANT EXECUTE
-	ON FUNCTION events.evdef_start( TEXT , INT , BOOLEAN , TEXT )
-	TO :dbuser;
-
-
-
-/*
- * Create a new field
- * ------------------
- * 
- * /!\ INTERNAL FUNCTION /!\
- * 
- * This function adds data about a new field to the temporary event
- * definition table.
- * 
- * Parameters:
- *		_id			The field's identifier
- *		_opt		Whether the field is optional
- *		_type		The field's type
- *		_etype		The field's entity type (may be NULL)
- *		_is_int		Whether the field is an integer (may be NULL)
- *		_min_val	Minimal value/length (may be NULL)
- *		_max_val	Maximal value/length (may be NULL)
- *
- * Returns:
- * 		???			An error code: OK or BAD_ID
- *						(see events.evdef_create_result)
- */
-DROP FUNCTION IF EXISTS events.evdef_addfld_internal(
-	TEXT , BOOLEAN , events.field_type , events.entity_field_type ,
-	BOOLEAN , NUMERIC , NUMERIC ) CASCADE;
-CREATE FUNCTION events.evdef_addfld_internal(
-			_id			TEXT ,
-			_opt		BOOLEAN ,
-			_type		events.field_type ,
-			_etype		events.entity_field_type ,
-			_is_int		BOOLEAN ,
-			_min_val	NUMERIC ,
-			_max_val	NUMERIC
-		) RETURNS events.evdef_create_result
-		LANGUAGE PLPGSQL
-		CALLED ON NULL INPUT
-		VOLATILE SECURITY INVOKER
-	AS $evdef_addfld_internal$
-
-DECLARE
-	_iq_string	TEXT;
-
-BEGIN
-	IF LENGTH( _id ) < 2 OR LENGTH( _id ) > 48
-			OR NOT _id ~ '^[a-z\-]+$'
-	THEN
-		DELETE FROM evdef_temp;
-		RETURN 'BAD_ID'::events.evdef_create_result;
-	END IF;
-
-	_iq_string := _opt::TEXT || ' , ''' || _type::TEXT || ''' , ';
-	IF _etype IS NULL
-	THEN
-		_iq_string := _iq_string || 'NULL';
-	ELSE
-		_iq_string := _iq_string || '''' || _etype::TEXT || '''';
-	END IF;
-	_iq_string := _iq_string || ' , ';
-	IF _is_int IS NULL
-	THEN
-		_iq_string := _iq_string || 'NULL';
-	ELSE
-		_iq_string := _iq_string || _is_int::TEXT;
-	END IF;
-	_iq_string := _iq_string || ' , ';
-	IF _min_val IS NULL
-	THEN
-		_iq_string := _iq_string || 'NULL';
-	ELSE
-		_iq_string := _iq_string || _min_val::TEXT;
-	END IF;
-	_iq_string := _iq_string || ' , ';
-	IF _max_val IS NULL
-	THEN
-		_iq_string := _iq_string || 'NULL';
-	ELSE
-		_iq_string := _iq_string || _max_val::TEXT;
-	END IF;
-
-	INSERT INTO evdef_temp( evdef_id , evfld_id , evfld_typespec )
-		SELECT evdef_id , _id , _iq_string
-			FROM evdef_temp
-			WHERE evfld_id IS NULL;
-	RETURN 'OK'::events.evdef_create_result;
-END;
-$evdef_addfld_internal$;
-
-REVOKE EXECUTE
-	ON FUNCTION events.evdef_addfld_internal(
-		TEXT , BOOLEAN , events.field_type , events.entity_field_type ,
-		BOOLEAN , NUMERIC , NUMERIC ) 
-	FROM PUBLIC;
-
-
-/*
- * Actual field creation functions
- * --------------------------------
- * 
- * Bunch of functions that create the field records in the temporary table
- * through events.evdef_addfld_internal().
- * 
- * Note:
- *	These functions are not dropped manually here, as it is assumed that
- *		dropping events.evdef_addfld_internal() will have cascaded.
- */
-
--- INTEGER FIELD, NO BOUNDS
-CREATE FUNCTION events.evdef_addfld_int( _id TEXT , _opt BOOLEAN )
-		RETURNS events.evdef_create_result
-		LANGUAGE SQL
-		STRICT VOLATILE SECURITY DEFINER
-	AS $$ SELECT events.evdef_addfld_internal(
-			$1,$2,'NUMERIC'::events.field_type,NULL,TRUE,NULL,NULL); $$;
-REVOKE EXECUTE
-	ON FUNCTION events.evdef_addfld_int( TEXT , BOOLEAN ) 
-	FROM PUBLIC;
-GRANT EXECUTE
-	ON FUNCTION events.evdef_addfld_int( TEXT , BOOLEAN ) 
-	TO :dbuser;
-
--- INTEGER FIELD W/ LOWER BOUND
-CREATE FUNCTION events.evdef_addfld_int_min( _id TEXT , _opt BOOLEAN , _min INT )
-		RETURNS events.evdef_create_result
-		LANGUAGE SQL
-		STRICT VOLATILE SECURITY DEFINER
-	AS $$ SELECT events.evdef_addfld_internal(
-			$1,$2,'NUMERIC'::events.field_type,NULL,TRUE,$3::NUMERIC,NULL); $$;
-REVOKE EXECUTE
-	ON FUNCTION events.evdef_addfld_int_min( TEXT , BOOLEAN , INT ) 
-	FROM PUBLIC;
-GRANT EXECUTE
-	ON FUNCTION events.evdef_addfld_int_min( TEXT , BOOLEAN , INT )
-	TO :dbuser;
-
--- INTEGER FIELD W/ HIGHER BOUND
-CREATE FUNCTION events.evdef_addfld_int_max( _id TEXT , _opt BOOLEAN , _max INT )
-		RETURNS events.evdef_create_result
-		LANGUAGE SQL
-		STRICT VOLATILE SECURITY DEFINER
-	AS $$ SELECT events.evdef_addfld_internal(
-			$1,$2,'NUMERIC'::events.field_type,NULL,TRUE,NULL,$3::NUMERIC); $$;
-REVOKE EXECUTE
-	ON FUNCTION events.evdef_addfld_int_max( TEXT , BOOLEAN , INT ) 
-	FROM PUBLIC;
-GRANT EXECUTE
-	ON FUNCTION events.evdef_addfld_int_max( TEXT , BOOLEAN , INT )
-	TO :dbuser;
-
--- INTEGER FIELD W/ LIMITED RANGE
-CREATE FUNCTION events.evdef_addfld_int_range( _id TEXT , _opt BOOLEAN , _min INT , _max INT )
-		RETURNS events.evdef_create_result
-		LANGUAGE SQL
-		STRICT VOLATILE SECURITY DEFINER
-	AS $$ SELECT events.evdef_addfld_internal(
-			$1,$2,'NUMERIC'::events.field_type,NULL,TRUE,$3::NUMERIC,$4::NUMERIC); $$;
-REVOKE EXECUTE
-	ON FUNCTION events.evdef_addfld_int_range( TEXT , BOOLEAN , INT , INT ) 
-	FROM PUBLIC;
-GRANT EXECUTE
-	ON FUNCTION events.evdef_addfld_int_range( TEXT , BOOLEAN , INT , INT )
-	TO :dbuser;
-
--- REAL FIELD, NO BOUNDS
-CREATE FUNCTION events.evdef_addfld_real( _id TEXT , _opt BOOLEAN )
-		RETURNS events.evdef_create_result
-		LANGUAGE SQL
-		STRICT VOLATILE SECURITY DEFINER
-	AS $$ SELECT events.evdef_addfld_internal(
-			$1,$2,'NUMERIC'::events.field_type,NULL,FALSE,NULL,NULL); $$;
-REVOKE EXECUTE
-	ON FUNCTION events.evdef_addfld_real( TEXT , BOOLEAN ) 
-	FROM PUBLIC;
-GRANT EXECUTE
-	ON FUNCTION events.evdef_addfld_real( TEXT , BOOLEAN ) 
-	TO :dbuser;
-
--- REAL FIELD W/ LOWER BOUND
-CREATE FUNCTION events.evdef_addfld_real_min( _id TEXT , _opt BOOLEAN , _min DOUBLE PRECISION )
-		RETURNS events.evdef_create_result
-		LANGUAGE SQL
-		STRICT VOLATILE SECURITY DEFINER
-	AS $$ SELECT events.evdef_addfld_internal(
-			$1,$2,'NUMERIC'::events.field_type,NULL,FALSE,$3::NUMERIC,NULL); $$;
-REVOKE EXECUTE
-	ON FUNCTION events.evdef_addfld_real_min( TEXT , BOOLEAN , DOUBLE PRECISION ) 
-	FROM PUBLIC;
-GRANT EXECUTE
-	ON FUNCTION events.evdef_addfld_real_min( TEXT , BOOLEAN , DOUBLE PRECISION )
-	TO :dbuser;
-
--- REAL FIELD W/ HIGHER BOUND
-CREATE FUNCTION events.evdef_addfld_real_max( _id TEXT , _opt BOOLEAN , _max DOUBLE PRECISION )
-		RETURNS events.evdef_create_result
-		LANGUAGE SQL
-		STRICT VOLATILE SECURITY DEFINER
-	AS $$ SELECT events.evdef_addfld_internal(
-			$1,$2,'NUMERIC'::events.field_type,NULL,FALSE,NULL,$3::NUMERIC); $$;
-REVOKE EXECUTE
-	ON FUNCTION events.evdef_addfld_real_max( TEXT , BOOLEAN , DOUBLE PRECISION ) 
-	FROM PUBLIC;
-GRANT EXECUTE
-	ON FUNCTION events.evdef_addfld_real_max( TEXT , BOOLEAN , DOUBLE PRECISION )
-	TO :dbuser;
-
--- REAL FIELD W/ LIMITED RANGE
-CREATE FUNCTION events.evdef_addfld_real_range( _id TEXT , _opt BOOLEAN , _min DOUBLE PRECISION , _max DOUBLE PRECISION )
-		RETURNS events.evdef_create_result
-		LANGUAGE SQL
-		STRICT VOLATILE SECURITY DEFINER
-	AS $$ SELECT events.evdef_addfld_internal(
-			$1,$2,'NUMERIC'::events.field_type,NULL,FALSE,$3::NUMERIC,$4::NUMERIC); $$;
-REVOKE EXECUTE
-	ON FUNCTION events.evdef_addfld_real_range( TEXT , BOOLEAN , DOUBLE PRECISION , DOUBLE PRECISION ) 
-	FROM PUBLIC;
-GRANT EXECUTE
-	ON FUNCTION events.evdef_addfld_real_range( TEXT , BOOLEAN , DOUBLE PRECISION , DOUBLE PRECISION )
-	TO :dbuser;
-
--- TEXT FIELD, NO BOUNDS
-CREATE FUNCTION events.evdef_addfld_text( _id TEXT , _opt BOOLEAN )
-		RETURNS events.evdef_create_result
-		LANGUAGE SQL
-		STRICT VOLATILE SECURITY DEFINER
-	AS $$ SELECT events.evdef_addfld_internal(
-			$1,$2,'TEXT'::events.field_type,NULL,NULL,NULL,NULL); $$;
-REVOKE EXECUTE
-	ON FUNCTION events.evdef_addfld_text( TEXT , BOOLEAN ) 
-	FROM PUBLIC;
-GRANT EXECUTE
-	ON FUNCTION events.evdef_addfld_text( TEXT , BOOLEAN ) 
-	TO :dbuser;
-
--- TEXT FIELD W/ LOWER BOUND
-CREATE FUNCTION events.evdef_addfld_text_min( _id TEXT , _opt BOOLEAN , _min INT )
-		RETURNS events.evdef_create_result
-		LANGUAGE SQL
-		STRICT VOLATILE SECURITY DEFINER
-	AS $$ SELECT events.evdef_addfld_internal(
-			$1,$2,'TEXT'::events.field_type,NULL,NULL,$3::NUMERIC,NULL); $$;
-REVOKE EXECUTE
-	ON FUNCTION events.evdef_addfld_text_min( TEXT , BOOLEAN , INT ) 
-	FROM PUBLIC;
-GRANT EXECUTE
-	ON FUNCTION events.evdef_addfld_text_min( TEXT , BOOLEAN , INT )
-	TO :dbuser;
-
--- TEXT FIELD W/ HIGHER BOUND
-CREATE FUNCTION events.evdef_addfld_text_max( _id TEXT , _opt BOOLEAN , _max INT )
-		RETURNS events.evdef_create_result
-		LANGUAGE SQL
-		STRICT VOLATILE SECURITY DEFINER
-	AS $$ SELECT events.evdef_addfld_internal(
-			$1,$2,'TEXT'::events.field_type,NULL,NULL,NULL,$3::NUMERIC); $$;
-REVOKE EXECUTE
-	ON FUNCTION events.evdef_addfld_text_max( TEXT , BOOLEAN , INT ) 
-	FROM PUBLIC;
-GRANT EXECUTE
-	ON FUNCTION events.evdef_addfld_text_max( TEXT , BOOLEAN , INT )
-	TO :dbuser;
-
--- TEXT FIELD W/ LIMITED RANGE
-CREATE FUNCTION events.evdef_addfld_text_range( _id TEXT , _opt BOOLEAN , _min INT , _max INT )
-		RETURNS events.evdef_create_result
-		LANGUAGE SQL
-		STRICT VOLATILE SECURITY DEFINER
-	AS $$ SELECT events.evdef_addfld_internal(
-			$1,$2,'TEXT'::events.field_type,NULL,NULL,$3::NUMERIC,$4::NUMERIC); $$;
-REVOKE EXECUTE
-	ON FUNCTION events.evdef_addfld_text_range( TEXT , BOOLEAN , INT , INT ) 
-	FROM PUBLIC;
-GRANT EXECUTE
-	ON FUNCTION events.evdef_addfld_text_range( TEXT , BOOLEAN , INT , INT )
-	TO :dbuser;
-
--- BOOLEAN FIELD
-CREATE FUNCTION events.evdef_addfld_bool( _id TEXT , _opt BOOLEAN )
-		RETURNS events.evdef_create_result
-		LANGUAGE SQL
-		STRICT VOLATILE SECURITY DEFINER
-	AS $$ SELECT events.evdef_addfld_internal(
-			$1,$2,'BOOL'::events.field_type,NULL,NULL,NULL,NULL); $$;
-REVOKE EXECUTE
-	ON FUNCTION events.evdef_addfld_bool( TEXT , BOOLEAN ) 
-	FROM PUBLIC;
-GRANT EXECUTE
-	ON FUNCTION events.evdef_addfld_bool( TEXT , BOOLEAN ) 
-	TO :dbuser;
-
--- I18N TEXT FIELD
-CREATE FUNCTION events.evdef_addfld_i18n( _id TEXT , _opt BOOLEAN )
-		RETURNS events.evdef_create_result
-		LANGUAGE SQL
-		STRICT VOLATILE SECURITY DEFINER
-	AS $$ SELECT events.evdef_addfld_internal(
-			$1,$2,'I18N'::events.field_type,NULL,NULL,NULL,NULL); $$;
-REVOKE EXECUTE
-	ON FUNCTION events.evdef_addfld_i18n( TEXT , BOOLEAN ) 
-	FROM PUBLIC;
-GRANT EXECUTE
-	ON FUNCTION events.evdef_addfld_i18n( TEXT , BOOLEAN ) 
-	TO :dbuser;
-
--- ENTITY LINK FIELD
-CREATE FUNCTION events.evdef_addfld_entity( _id TEXT , _opt BOOLEAN , _etype events.entity_field_type )
-		RETURNS events.evdef_create_result
-		LANGUAGE SQL
-		STRICT VOLATILE SECURITY DEFINER
-	AS $$ SELECT events.evdef_addfld_internal(
-			$1,$2,'ENTITY'::events.field_type,$3,NULL,NULL,NULL); $$;
-REVOKE EXECUTE
-	ON FUNCTION events.evdef_addfld_entity( TEXT , BOOLEAN , events.entity_field_type ) 
-	FROM PUBLIC;
-GRANT EXECUTE
-	ON FUNCTION events.evdef_addfld_entity( TEXT , BOOLEAN , events.entity_field_type ) 
-	TO :dbuser;
-
-
-/*
- * Create an event definition record
- * ---------------------------------
- * 
- * /!\ INTERNAL FUNCTION /!\
- * 
- * This function inserts the record for an event definition into the
- * appropriate table.
- * 
- * Returns:
- *		???		An error code
- */
-DROP FUNCTION IF EXISTS events.evdef_create_record( );
-CREATE FUNCTION events.evdef_create_record( )
-		RETURNS events.evdef_create_result
-		LANGUAGE PLPGSQL
-		STRICT VOLATILE SECURITY INVOKER
-	AS $evdef_create_record$
-
-DECLARE
-	_rec	RECORD;
-	_qstr	TEXT;
-
-BEGIN
-	SELECT INTO _rec *
-		FROM evdef_temp
-		WHERE evfld_id IS NULL;
-	IF NOT FOUND
-	THEN
-		RETURN 'NO_DATA';
-	END IF;
-
-	_qstr := 'INSERT INTO events.event_definitions (' ||
-				'evdef_id , evdef_priority , evdef_adjustable , ' ||
-				'evdef_name_id , evdef_template_id' ||
-			') VALUES ( $1 , ' || _rec.evfld_typespec || ');';
-
-	BEGIN
-		EXECUTE _qstr USING _rec.evdef_id;
-	EXCEPTION
-		WHEN unique_violation THEN
-			RETURN 'DUPLICATE';
-		WHEN check_violation THEN
-			RETURN 'BAD_SPEC';
-	END;
-
-	RETURN 'OK';
-END;
-$evdef_create_record$;
-
-REVOKE EXECUTE
-	ON FUNCTION events.evdef_create_record( )
-	FROM PUBLIC;
-
-
-/*
- * Create an event field definition record
- * ---------------------------------------
- * 
- * /!\ INTERNAL FUNCTION /!\
- * 
- * This function inserts a new event field definition record into the
- * appropriate table.
- *
- * Parameters:
- * 		_evdef_id	The event definition's identifier
- *		_efdef_id	The field's identifier
- *		_typespec	The type specification from the temporary table
- *
- * Returns:
- *		???			An error code
- */
-DROP FUNCTION IF EXISTS events.evdef_create_field_record(
-		TEXT , TEXT , TEXT );
-CREATE FUNCTION events.evdef_create_field_record(
-			_evdef_id	TEXT ,
-			_efdef_id	TEXT ,
-			_typespec	TEXT )
-		RETURNS events.evdef_create_result
-		LANGUAGE PLPGSQL
-		STRICT VOLATILE SECURITY INVOKER
-	AS $evdef_create_field_record$
-
-DECLARE
-	_qstr	TEXT;
-
-BEGIN
-	_qstr := 'INSERT INTO events.field_definitions (' ||
-			'evdef_id , efdef_id , efdef_optional , efdef_type , ' ||
-			'efdef_entity , efdef_integer , efdef_min , efdef_max ' ||
-		') VALUES ( $1 , $2 , ' || _typespec || ');';
-	BEGIN
-		EXECUTE _qstr USING _evdef_id , _efdef_id;
-	EXCEPTION
-		WHEN unique_violation THEN
-			RETURN 'DUPLICATE';
-		WHEN check_violation THEN
-			RETURN 'BAD_SPEC';
-	END;
-	RETURN 'OK';
-
-END;
-$evdef_create_field_record$;
-
-REVOKE EXECUTE
-	ON FUNCTION events.evdef_create_field_record( TEXT , TEXT , TEXT )
-	FROM PUBLIC;
-
-
-/*
- * Generate the DDL for a numeric field
- * ------------------------------------
- * 
- * /!\ INTERNAL FUNCTION /!\
- * 
- * This function generates the DDL for a numeric event field in an event queue
- * table.
- * 
- * Parameters:
- *		_fname		The field's table name
- *		_opt		Whether the field is optional
- *		_is_int		Whether the field is an integer
- *		_min		Minimal value of the field (may be NULL)
- *		_max		Maximal value of the field (may be NULL)
- *
- * Returns:
- * 		???			The field's DDL
- */
-DROP FUNCTION IF EXISTS events.efdef_ddl_numeric(
-		TEXT , BOOLEAN , BOOLEAN , NUMERIC , NUMERIC );
-CREATE FUNCTION events.efdef_ddl_numeric(
-		_fname	TEXT ,
-		_opt	BOOLEAN ,
-		_is_int	BOOLEAN ,
-		_min	NUMERIC ,
-		_max	NUMERIC )
-	RETURNS TEXT
-	LANGUAGE SQL
-	IMMUTABLE SECURITY INVOKER
-	CALLED ON NULL INPUT
-AS $efdef_ddl_numeric$
-	SELECT ',' || $1 || ' '
-		|| ( CASE WHEN $3 THEN 'BIGINT' ELSE 'DOUBLE PRECISION' END )
-		|| ( CASE WHEN $2 THEN '' ELSE ' NOT NULL' END )
-		|| ( CASE
-			WHEN $4 IS NULL AND $5 IS NULL
-				THEN ''
-			ELSE
-				' CHECK(' || $1 || ( CASE
-					WHEN $5 IS NULL
-						THEN '>=' || $4::TEXT
-					WHEN $4 IS NULL
-						THEN '<=' || $5::TEXT
-					ELSE
-						' BETWEEN ' || $4::TEXT || ' AND ' || $5::TEXT
-				END ) || ')'
-		END );
-$efdef_ddl_numeric$;
-
-REVOKE EXECUTE
-	ON FUNCTION events.efdef_ddl_numeric(
-		TEXT , BOOLEAN , BOOLEAN , NUMERIC , NUMERIC )
-	FROM PUBLIC;
-
-
-
-/*
- * Generate the DDL for a text field
- * ---------------------------------
- * 
- * /!\ INTERNAL FUNCTION /!\
- * 
- * This function generates the DDL for a text event field in an event queue
- * table.
- * 
- * Parameters:
- *		_fname		The field's table name
- *		_opt		Whether the field is optional
- *		_min		Minimal length of the field (may be NULL)
- *		_max		Maximal length of the field (may be NULL)
- *
- * Returns:
- * 		???			The field's DDL
- */
-DROP FUNCTION IF EXISTS events.efdef_ddl_text(
-		TEXT , BOOLEAN , NUMERIC , NUMERIC );
-CREATE FUNCTION events.efdef_ddl_text(
-		_fname	TEXT ,
-		_opt	BOOLEAN ,
-		_min	NUMERIC ,
-		_max	NUMERIC )
-	RETURNS TEXT
-	LANGUAGE SQL
-	IMMUTABLE SECURITY INVOKER
-	CALLED ON NULL INPUT
-AS $efdef_ddl_text$
-	SELECT ',' || $1 || ' '
-		|| ( CASE WHEN $4 IS NULL THEN 'TEXT' ELSE 'VARCHAR(' || $4::TEXT || ')' END )
-		|| ( CASE WHEN $2 THEN '' ELSE ' NOT NULL' END )
-		|| ( CASE
-			WHEN $3 IS NULL
-				THEN ''
-			ELSE
-				' CHECK(LENGTH(' || $1 || ')>=' || $3::TEXT || ')'
-		END );
-$efdef_ddl_text$;
-
-REVOKE EXECUTE
-	ON FUNCTION events.efdef_ddl_text(
-		TEXT , BOOLEAN , NUMERIC , NUMERIC )
-	FROM PUBLIC;
-
-
-
-/*
- * Generate the DDL for an entity field
- * ------------------------------------
- * 
- * /!\ INTERNAL FUNCTION /!\
- * 
- * This function generates the DDL for an entity event field in an event queue
- * table.
- * 
- * Parameters:
- *		_fname		The field's table name
- *		_opt		Whether the field is optional
- *		_etype		Type of entity to reference
- *
- * Returns:
- * 		???			The field's DDL
- */
-DROP FUNCTION IF EXISTS events.efdef_ddl_entity(
-		TEXT , BOOLEAN , events.entity_field_type );
-CREATE FUNCTION events.efdef_ddl_entity(
-		_fname	TEXT ,
-		_opt	BOOLEAN ,
-		_etype	events.entity_field_type )
-	RETURNS TEXT
-	LANGUAGE SQL
-	STRICT IMMUTABLE SECURITY INVOKER
-AS $efdef_ddl_entity$
-	SELECT ',' || $1 || ' '
-		|| ( CASE 
-			WHEN $3 IN ( 'EMP' , 'PLN', 'ALL' , 'ADM' ) THEN 'INT'
-			ELSE 'BIGINT'
-		END ) || ( CASE WHEN $2 THEN ' NOT NULL' ELSE '' END )
-		|| ' REFERENCES ' || ( CASE $3
-			WHEN 'EMP' THEN 'emp.empires(name_id)'
-			WHEN 'PLN' THEN 'verse.planets(name_id)'
-			WHEN 'FLT' THEN 'fleets.fleets(id)'
-			WHEN 'ALL' THEN 'emp.alliances(id)'
-			WHEN 'BAT' THEN 'battles.battles(id)'
-			WHEN 'ADM' THEN 'admin.administrators(id)'
-			WHEN 'BUG' THEN 'bugs.initial_report_events(event_id)'
-		END ) || ' ON DELETE CASCADE';
-$efdef_ddl_entity$;
-
-REVOKE EXECUTE
-	ON FUNCTION events.efdef_ddl_entity(
-		TEXT , BOOLEAN , events.entity_field_type )
-	FROM PUBLIC;
-
-
-/*
- * Trigger used to insert entries into pending_events
- * --------------------------------------------------
- * 
- * This function is used as a trigger to insert queued events into the
- * events.pending_events table.
- * 
- * Parameters:
- *		TG_ARGV[0]	Event type identifier
- */
-DROP FUNCTION IF EXISTS events.tgf_eq_insert( );
-CREATE FUNCTION events.tgf_eq_insert(  )
-		RETURNS TRIGGER
-		LANGUAGE PLPGSQL
-		STRICT VOLATILE SECURITY DEFINER
-	AS $tgf_eq_insert$
-BEGIN
-	INSERT INTO events.pending_events( event_id , evdef_id )
-		VALUES ( NEW.event_id , TG_ARGV[0] );
-	RETURN NEW;
-END;
-$tgf_eq_insert$;
-
-REVOKE EXECUTE
-	ON FUNCTION events.tgf_eq_insert( )
-	FROM PUBLIC;
-
-	
-/*
- * Create the event queuing table for a new definition
- * ---------------------------------------------------
- *
- * /!\ INTERNAL FUNCTION /!\
- *
- * This function generates the event queuing table from the list of fields
- * that compose an event definition. The queuing table's name will always be
- * "events.evq_<type identifier>"; it will contain an event identifier
- * generated from the event ID sequence (events.event_id_sequence), an empire
- * identifier, a timestamp, the tick identifier, and rows corresponding to the
- * event definition's fields.
- * 
- * Parameters:
- *		_evdef_id		The event definition's identifier   
- */
-DROP FUNCTION IF EXISTS events.evdef_create_queue_table( TEXT );
-CREATE FUNCTION _temp_init_func(_user TEXT)  RETURNS VOID LANGUAGE PLPGSQL AS $init_func$
-BEGIN EXECUTE $init_code$
-CREATE FUNCTION events.evdef_create_queue_table( _evdef_id TEXT )
-		RETURNS VOID
-		LANGUAGE PLPGSQL
-		STRICT VOLATILE SECURITY INVOKER
-	AS $evdef_create_queue_table$
-
-DECLARE
-	_tsfx	TEXT;
-	_rec	RECORD;
-	_qstr	TEXT;
-	_fname	TEXT;
-
-BEGIN
-	_tsfx := replace( _evdef_id , '-' , '_' );
-	_qstr := 'CREATE TABLE events.eq_' || _tsfx || $tbl_def$ (
-			event_id BIGINT NOT NULL PRIMARY KEY
-					DEFAULT nextval('events.event_id_sequence'::regclass) ,
-			event_rtime TIMESTAMP WITHOUT TIME ZONE NOT NULL
-					DEFAULT now( ) ,
-			event_gtime BIGINT NOT NULL ,
-			empire_id INT NOT NULL REFERENCES emp.empires ( name_id )
-					ON DELETE CASCADE
-	$tbl_def$;
-	
-	FOR _rec IN SELECT *
-			FROM events.field_definitions
-			WHERE evdef_id = _evdef_id
-	LOOP
-		_fname := 'ef_' || replace( _rec.efdef_id , '-' , '_' );
-		_qstr := _qstr || ( CASE _rec.efdef_type
-				WHEN 'NUMERIC' THEN
-					events.efdef_ddl_numeric( _fname , _rec.efdef_optional ,
-						_rec.efdef_integer , _rec.efdef_min , _rec.efdef_max )
-				WHEN 'TEXT' THEN
-					events.efdef_ddl_text( _fname , _rec.efdef_optional ,
-						_rec.efdef_min , _rec.efdef_max )
-				WHEN 'BOOL' THEN
-					',' || _fname || ' BOOLEAN' || ( CASE
-						WHEN NOT _rec.efdef_optional THEN ' NOT NULL'
-						ELSE ''
-					END )
-				WHEN 'I18N' THEN
-					',' || _fname || ' VARCHAR(64)' || ( CASE
-						WHEN NOT _rec.efdef_optional THEN ' NOT NULL'
-						ELSE ''
-					END ) || ' REFERENCES defs.strings(name)'
-				WHEN 'ENTITY' THEN
-					events.efdef_ddl_entity( _fname , _rec.efdef_optional ,
-						_rec.efdef_entity )
-			END );
-	END LOOP;
-
-	_qstr := _qstr || ');';
-	EXECUTE _qstr;
-	
-	_qstr := 'GRANT INSERT ON TABLE events.eq_' || _tsfx
-		|| ' TO $init_code$ || $1 || $init_code$;';
-	EXECUTE _qstr;
-	
-	_qstr := 'CREATE TRIGGER tg_eqi_' || _tsfx || ' AFTER INSERT ON events.eq_'
-		|| _tsfx || ' FOR EACH ROW EXECUTE PROCEDURE events.tgf_eq_insert('''
-		|| _evdef_id || ''');';
-	EXECUTE _qstr;
-END;
-$evdef_create_queue_table$; $init_code$ USING $1; END; $init_func$;
-SELECT _temp_init_func(:dbuser_string);
-DROP FUNCTION _temp_init_func(TEXT);
-
-REVOKE EXECUTE
-	ON FUNCTION events.evdef_create_queue_table( TEXT )
-	FROM PUBLIC;
-
-
-
-/*
- * Validate and finalise an event definition
- * -----------------------------------------
- * 
- * This function inserts the contents of the temporary event definition table
- * into the main table. If everything goes well, the event queuing table is
- * created and the temporary table is destroyed.
- * 
- * Returns:
- *		_error		An error code (see events.evdef_create_result)
- *		_fld		The name of the field which caused the error, or NULL
- *						if the error was table-related or if there was no
- *						error.
- */
-DROP FUNCTION IF EXISTS events.evdef_finalise( );
-CREATE FUNCTION events.evdef_finalise(
-			OUT _error events.evdef_create_result ,
-			OUT _fld TEXT )
-		LANGUAGE PLPGSQL
-		STRICT VOLATILE SECURITY DEFINER
-	AS $evdef_finalise$
-
-DECLARE
-	_eid	TEXT;
-	_rec	RECORD;
-
-BEGIN
-	-- First create the event definition record
-	_fld := NULL;
-	_error := events.evdef_create_record( );
-	IF _error = 'OK'
-	THEN
-		-- Then create records for all fields
-		FOR _rec IN SELECT * FROM evdef_temp WHERE evfld_id IS NOT NULL
-		LOOP
-			_error := events.evdef_create_field_record(
-					_rec.evdef_id , _rec.evfld_id , _rec.evfld_typespec );
-
-			IF _error <> 'OK'
-			THEN
-				-- Destroy the definition record on failure
-				_fld := _rec.evfld_id;
-				DELETE FROM events.event_definitions
-					WHERE evdef_id = _rec.evdef_id;
-				EXIT;
-			END IF;
-
-		END LOOP;
-	END IF;
-
-	-- If everything went well so far, create the queueing table
-	IF _error = 'OK'
-	THEN
-		SELECT INTO _eid evdef_id FROM evdef_temp LIMIT 1;
-		PERFORM events.evdef_create_queue_table( _eid );
-	END IF;
-
-	DROP TABLE evdef_temp;
-END;
-$evdef_finalise$;
-
-REVOKE EXECUTE
-	ON FUNCTION events.evdef_finalise( )
-	FROM PUBLIC;
-GRANT EXECUTE
-	ON FUNCTION events.evdef_finalise( )
-	TO :dbuser;
diff --git a/legacyworlds-server-data/db-structure/parts/040-functions/171-event-priorities.sql b/legacyworlds-server-data/db-structure/parts/040-functions/171-event-priorities.sql
deleted file mode 100644
index ca67917..0000000
--- a/legacyworlds-server-data/db-structure/parts/040-functions/171-event-priorities.sql
+++ /dev/null
@@ -1,143 +0,0 @@
--- LegacyWorlds Beta 6
--- PostgreSQL database scripts
---
--- Functions to manipulate player-defined event priority
--- overrides.
---
--- Copyright(C) 2004-2012, DeepClone Development
--- --------------------------------------------------------
-
-
-
-/*
- * Set an event priority override
- * ------------------------------
- * 
- * Adds a new event priority override or modify its value. If the event type
- * does not exist, does not allow overrides or if the specified priority is
- * invalid, the error will be ignored silently.
- * 
- * Parameters:
- *		_empire_id		The identifier of the player's empire
- *		_evdef_id		The identifier of the event type
- *		_priority		The custom priority value
- */
-DROP FUNCTION IF EXISTS events.evcp_set( INT , TEXT , INT );
-CREATE FUNCTION events.evcp_set(
-			_empire_id	INT ,
-			_evdef_id	TEXT ,
-			_priority	INT )
-		RETURNS VOID
-		LANGUAGE PLPGSQL
-		STRICT VOLATILE SECURITY DEFINER
-	AS $evcp_set$
-
-DECLARE
-	_user_id	INT;
-
-BEGIN
-	BEGIN
-		INSERT INTO events.custom_priorities(
-				evdef_id , address_id , evcp_priority )
-			SELECT _evdef_id , owner_id , _priority
-				FROM naming.empire_names
-				WHERE id = _empire_id;
-		IF NOT FOUND
-		THEN
-			RAISE EXCEPTION 'missing empire';
-		END IF;
-	EXCEPTION
-		WHEN unique_violation THEN
-			UPDATE events.custom_priorities
-				SET evcp_priority = _priority
-				WHERE evdef_id = _evdef_id
-					AND address_id = (
-						SELECT owner_id
-							FROM naming.empire_names
-							WHERE id = _empire_id );
-	END;
-
-EXCEPTION
-	WHEN raise_exception THEN
-		PERFORM sys.write_sql_log( 'Events' , 'WARNING'::log_level ,
-			'Call to events.evcp_set() from missing empire #' || _empire_id );
-
-	WHEN foreign_key_violation OR check_violation THEN
-		PERFORM sys.write_sql_log( 'Events' , 'WARNING'::log_level ,
-			'Bad call to events.evcp_set() from empire #' || _empire_id );
-END;
-$evcp_set$;
-
-REVOKE EXECUTE
-	ON FUNCTION events.evcp_set( INT , TEXT , INT )
-	FROM PUBLIC;
-GRANT EXECUTE
-	ON FUNCTION events.evcp_set( INT , TEXT , INT )
-	TO :dbuser;
-
-
-
-/*
- * Clear an event priority override
- * --------------------------------
- * 
- * Remove an event priority override from the custom priorities table. If
- * there was no override for the specified event type and empire, do nothing.
- * 
- * Parameters:
- *		_empire_id		The identifier of the player's empire
- *		_evdef_id		The identifier of the event type
- */
-DROP FUNCTION IF EXISTS events.evcp_clear( INT , TEXT );
-CREATE FUNCTION events.evcp_clear(
-		_empire_id	INT ,
-		_evdef_id	TEXT )
-	RETURNS VOID
-	LANGUAGE SQL
-	STRICT VOLATILE SECURITY DEFINER
-AS $evcp_clear$
-	DELETE FROM events.custom_priorities
-		WHERE evdef_id = $2
-			AND address_id = (
-				SELECT owner_id
-					FROM naming.empire_names
-					WHERE id = $1 )
-$evcp_clear$;
-
-REVOKE EXECUTE
-	ON FUNCTION events.evcp_clear( INT , TEXT )
-	FROM PUBLIC;
-GRANT EXECUTE
-	ON FUNCTION events.evcp_clear( INT , TEXT )
-	TO :dbuser;
-
-
-
-/*
- * Clear all event priority overrides
- * ----------------------------------
- * 
- * Remove all event priority overrides set by some player.
- * 
- * Parameters:
- *		_empire_id		The identifier of the player's empire
- */
-DROP FUNCTION IF EXISTS events.evcp_clear( INT );
-CREATE FUNCTION events.evcp_clear( _empire_id INT )
-	RETURNS VOID
-	LANGUAGE SQL
-	STRICT VOLATILE SECURITY DEFINER
-AS $evcp_clear$
-	DELETE FROM events.custom_priorities
-		WHERE address_id = (
-				SELECT owner_id
-					FROM naming.empire_names
-					WHERE id = $1 )
-$evcp_clear$;
-
-REVOKE EXECUTE
-	ON FUNCTION events.evcp_clear( INT )
-	FROM PUBLIC;
-GRANT EXECUTE
-	ON FUNCTION events.evcp_clear( INT )
-	TO :dbuser;
diff --git a/legacyworlds-server-data/db-structure/parts/040-functions/172-event-storage.sql b/legacyworlds-server-data/db-structure/parts/040-functions/172-event-storage.sql
deleted file mode 100644
index ed351fa..0000000
--- a/legacyworlds-server-data/db-structure/parts/040-functions/172-event-storage.sql
+++ /dev/null
@@ -1,183 +0,0 @@
--- LegacyWorlds Beta 6
--- PostgreSQL database scripts
---
--- Functions that extract event data from the queue tables
--- and store them in the long term storage tables.
---
--- Copyright(C) 2004-2012, DeepClone Development
--- --------------------------------------------------------
-
-
-/*
- * Entity fields table
- * -------------------
- * 
- * This table, which is filled when the database is created, associates entity
- * types with fields in the events.field_values table.
- */
-DROP TABLE IF EXISTS events._entity_fields;
-CREATE TABLE events._entity_fields(
-	efdef_entity	events.entity_field_type NOT NULL PRIMARY KEY ,
-	field_name		NAME NOT NULL ,
-	field_type		NAME NOT NULL
-);
-INSERT INTO events._entity_fields VALUES
-	( 'EMP' , 'empire_id' , 'INT' ) ,
-	( 'PLN' , 'planet_id' , 'INT' ) ,
-	( 'FLT' , 'fleet_id' , 'BIGINT' ) ,
-	( 'ALL' , 'alliance_id' , 'INT' ) ,
-	( 'BAT' , 'battle_id' , 'BIGINT' ) ,
-	( 'ADM' , 'admin_id' , 'INT' ) ,
-	( 'BUG' , 'bug_report_id' , 'BIGINT' );
-
-
-
-/*
- * Process a pending event
- * -----------------------
- * 
- * /!\ INTERNAL FUNCTION /!\
- * 
- * This procedure processes a single row from an event queue.
- * 
- * If the specified event identifier actually exists in the queue, it is
- * converted and stored in the main events tables, then the queue entry is
- * removed.
- * 
- * In all cases, the entry is deleted from events.pending_events.
- * 
- * Parameters:
- *		_event_id	The event's identifier
- *		_evdef_id	The event's type
- *
- * Returns:
- *		???			TRUE 
- */
-DROP FUNCTION IF EXISTS events.eq_process_event( BIGINT , TEXT );
-CREATE FUNCTION events.eq_process_event(
-			_event_id	BIGINT ,
-			_evdef_id	TEXT )
-		RETURNS BOOLEAN
-		LANGUAGE PLPGSQL
-		STRICT VOLATILE SECURITY INVOKER
-	AS $eq_process_event$
-
-DECLARE
-	_tbl	TEXT;
-	_qstr	TEXT;
-	_qentry	RECORD;
-	_nfound	INT;
-	_efdef	RECORD;
-
-BEGIN
-	
-	_tbl := 'events.eq_' || replace( _evdef_id , '-' , '_' );
-	_qstr := 'SELECT event_rtime , event_gtime , empire_id FROM '
-		|| _tbl || ' WHERE event_id = $1';
-	EXECUTE _qstr INTO _qentry USING _event_id;
-	GET DIAGNOSTICS _nfound = ROW_COUNT;
-
-	IF _nfound > 0
-	THEN
-	
-		INSERT INTO events.events_v2 (
-				event_id , evdef_id , event_rtime , event_gtime , empire_id
-			) VALUES (
-				_event_id , _evdef_id , _qentry.event_rtime ,
-				_qentry.event_gtime , _qentry.empire_id
-			);
-
-		_qstr := format( $field_acquisition$
-			SELECT efdef_id , field_name , field_type ,
-					( efdef_type = 'I18N') AS i18n , _sq1.value 
-				FROM events.field_definitions
-					INNER JOIN (
-						SELECT (each(hstore(_tbl))).*
-							FROM %s _tbl
-							WHERE _tbl.event_id = $1
-						) _sq1 ON _sq1.key = 'ef_' || replace(efdef_id , '-','_')
-					LEFT OUTER JOIN events._entity_fields
-						USING ( efdef_entity )
-				WHERE evdef_id = $2
-		$field_acquisition$ , _tbl );
-
-		FOR _efdef IN EXECUTE _qstr USING _event_id , _evdef_id
-		LOOP
-			_qstr := 'INSERT INTO events.field_values(event_id,evdef_id,efdef_id,efval_litteral'
-				|| ( CASE 
-					WHEN _efdef.field_name IS NOT NULL
-						THEN ',' || _efdef.field_name
-					WHEN _efdef.i18n
-						THEN ',string_id'
-					ELSE
-						''
-				END ) || ') ';
-
-			IF _efdef.i18n
-			THEN
-				_qstr := _qstr || $i18n_query$
-					SELECT $1,$2,$3,_str.id::TEXT||' '||_str.name,_str.id
-						FROM defs.strings _str
-						WHERE _str.name = $4
-					$i18n_query$;
-			ELSIF _efdef.field_name IS NOT NULL
-			THEN
-				_qstr := _qstr || format( 'VALUES($1,$2,$3,$4,$4::%s)' , _efdef.field_type );
-			ELSE
-				_qstr := _qstr || 'VALUES($1,$2,$3,$4)';
-			END IF;
-
-			EXECUTE _qstr USING _event_id , _evdef_id , _efdef.efdef_id , _efdef.value;
-		END LOOP;
-
-	END IF;
-
-	DELETE FROM events.pending_events
-		WHERE event_id = _event_id;
-	RETURN TRUE;
-
-END;
-$eq_process_event$;
-
-REVOKE EXECUTE
-	ON FUNCTION events.eq_process_event( BIGINT , TEXT )
-	FROM PUBLIC;
-
-
-
-/*
- * Process pending events
- * ----------------------
- * 
- * This procedure processes events from the queues. Each time the procedure is
- * called, it will process at most "game.events.batchSize" events.
- *
- * Returns:
- *		???			TRUE if events were processed, FALSE if the queues are
- *						empty
- */
-DROP FUNCTION IF EXISTS events.eq_process( );
-CREATE FUNCTION events.eq_process( )
-		RETURNS BOOLEAN
-		LANGUAGE PLPGSQL
-		STRICT VOLATILE SECURITY DEFINER
-	AS $eq_process$
-
-DECLARE
-	_limit	INT;
-
-BEGIN
-	_limit := sys.get_constant( 'game.events.batchSize' );
-	PERFORM events.eq_process_event( event_id , evdef_id )
-		FROM events.pending_events
-		LIMIT _limit;
-	RETURN FOUND;
-END;
-$eq_process$;
-
-REVOKE EXECUTE
-	ON FUNCTION events.eq_process( )
-	FROM PUBLIC;
-GRANT EXECUTE
-	ON FUNCTION events.eq_process( )
-	TO :dbuser;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/parts/040-functions/173-event-access.sql b/legacyworlds-server-data/db-structure/parts/040-functions/173-event-access.sql
deleted file mode 100644
index 3d0f6ea..0000000
--- a/legacyworlds-server-data/db-structure/parts/040-functions/173-event-access.sql
+++ /dev/null
@@ -1,724 +0,0 @@
--- LegacyWorlds Beta 6
--- PostgreSQL database scripts
---
--- Functions that read event data and update event
--- states on behalf of event viewing / processing
--- interfaces.
---
--- Copyright(C) 2004-2012, DeepClone Development
--- --------------------------------------------------------
-
-
-/*
- * SOME GENERAL DOCUMENTATION
- * --------------------------
- * 
- * This file provides a few functions the server can use to access the events:
- * 
- * The events.ep_read() function variants provide read-only access to the
- * list. They may be used with or without a target (whether that target is an
- * user or an empire), and they can be given an offset and a limit if partial
- * selection is desired. ep_read() accepts the following parameters ("+"
- * means that the parameter is required).
- *
- *		+ access interface identifier
- *		  target identifier
- *		  target is empire?
- *		+ access processed events?
- *		+ access preprocessed events?
- *		+ access new events?
- *		  offset of first event
- *		  maximal amount of events
- * 
- * The events.ep_access() function variants provide the same service, but will
- * additionally update the events' state after reading them. ep_access()
- * uses the same parameters as ep_read(), but adds two new mandatory parameters
- * at the end:
- * 
- *		+ mark preprocessed events as processed?
- *		+ state to set for new events
- */
-
-
-
-/*
- * Insert new events in unprocessed list
- * -------------------------------------
- * 
- * This trigger function is used to insert new events into the list of
- * unprocessed events for all interface types.
- */
-DROP FUNCTION IF EXISTS events.tgf_insert_unprocessed( ) CASCADE;
-CREATE FUNCTION events.tgf_insert_unprocessed( )
-		RETURNS TRIGGER
-		LANGUAGE PLPGSQL
-		STRICT VOLATILE SECURITY DEFINER
-	AS $tgf_insert_unprocessed$
-BEGIN
-	INSERT INTO events.unprocessed_events( event_id , evi_id )
-		SELECT NEW.event_id , evi_id
-			FROM events.interfaces;
-	RETURN NEW;
-END;
-$tgf_insert_unprocessed$;
-
-REVOKE EXECUTE
-	ON FUNCTION events.tgf_insert_unprocessed( )
-	FROM PUBLIC;
-
-CREATE TRIGGER tg_insert_unprocessed
-	AFTER INSERT ON events.events_v2
-	FOR EACH ROW EXECUTE PROCEDURE events.tgf_insert_unprocessed( );
-
-
-/*
- * Event processing states
- * -----------------------
- * 
- * This type serves as an indication of event processing state.
- * 
- * Note: this type is not used for storage, only for access.
- */
-DROP TYPE IF EXISTS events.processing_state CASCADE;
-CREATE TYPE events.processing_state AS ENUM(
-		/* The event is new and hasn't been processed yet */
-		'NEW' ,
-		
-		/* The event has been preprocessed */
-		'PRE' ,
-	
-		/* The event has been fully processed */
-		'DONE'
-	);
-
-
-/*
- * Event list entry
- * ----------------
- * 
- * This type corresponds to entries of the event lists returned by
- * events.ep_list_events().
- */
-DROP TYPE IF EXISTS events.ep_list_entry CASCADE;
-CREATE TYPE events.ep_list_entry AS (
-	/* The event's identifier */
-	event_id		BIGINT ,
-	
-	/* The event type */
-	evdef_id		TEXT ,
-
-	/* The user's identifier */
-	empire_id		INT ,
-	
-	/* The event's processing state */
-	event_state		events.processing_state
-);
-
-
-/*
- * Build the events listing query
- * ------------------------------
- * 
- * /!\ INTERNAL FUNCTION /!\
- * 
- * This procedure generates the query string used to extract events for a given
- * set of parameters.
- * 
- * Parameters:
- *	_check_emp		TRUE if the query ought to check the events' target
- *						empire, FALSE if all empires should be returned
- *	_accept_old		Whether processed events should be selected
- *	_accept_pre		Whether preprocessed events should be selected
- *	_accept_new		Whether unprocessed events should be selected
- *
- * Returns:
- * 	???				The query string
- */
-DROP FUNCTION IF EXISTS events.ep_make_list_query(
-		BOOLEAN , BOOLEAN , BOOLEAN , BOOLEAN );
-CREATE FUNCTION events.ep_make_list_query(
-			_check_emp	BOOLEAN ,
-			_accept_old	BOOLEAN ,
-			_accept_pre	BOOLEAN ,
-			_accept_new BOOLEAN )
-		RETURNS TEXT
-		LANGUAGE PLPGSQL
-		STRICT IMMUTABLE SECURITY INVOKER
-	AS $ep_make_list_query$
-
-DECLARE
-	_qstr		TEXT;
-	_wstr		TEXT;
-	_need_or	BOOLEAN;
-
-BEGIN
-		IF NOT ( _accept_old OR _accept_pre OR _accept_new )
-	THEN
-		RAISE EXCEPTION 'No events accepted';
-	END IF;
-
-	_qstr := $sel_query$
-		SELECT _evt.event_id ,_evt.evdef_id , _evt.empire_id , ( CASE
-					WHEN _upe.upe_preprocessed IS NULL
-						THEN 'DONE'
-					WHEN _upe.upe_preprocessed
-						THEN 'PRE'
-					ELSE
-						'NEW'
-				END )::events.processing_state
-			FROM events.events_v2 _evt
-				LEFT OUTER JOIN events.unprocessed_events _upe
-					ON _upe.event_id = _evt.event_id AND _upe.evi_id = $1
-	$sel_query$;
-	
-	IF _check_emp THEN
-		_wstr := '_evt.empire_id = $2';
-	ELSE
-		_wstr := '';
-	END IF;
-
-	IF NOT ( _accept_old AND _accept_pre AND _accept_new )
-	THEN
-		IF _wstr <> ''
-		THEN
-			_wstr := _wstr || ' AND ';
-		END IF;
-		_wstr := _wstr || '(';
-
-		_need_or := FALSE;
-		IF _accept_old THEN
-			_wstr := _wstr || '_upe.event_id IS NULL';
-			_need_or := TRUE;
-		END IF;
-		
-		IF _accept_pre THEN
-			IF _need_or THEN
-				_wstr := _wstr || ' OR ';
-			ELSE
-				_need_or := TRUE;
-			END IF;
-			_wstr := _wstr || '_upe.upe_preprocessed';
-		END IF;
-		
-		IF _accept_new THEN
-			IF _need_or THEN
-				_wstr := _wstr || ' OR ';
-			END IF;
-			_wstr := _wstr || 'NOT _upe.upe_preprocessed';
-		END IF;
-		
-		_wstr := _wstr || ')';
-	END IF;
-
-	IF _wstr <> ''
-	THEN
-		_qstr := _qstr || ' WHERE ' || _wstr;
-	END IF;
-	
-	_qstr := _qstr || ' ORDER BY _evt.event_id DESC';
-	RETURN _qstr;
-END;
-$ep_make_list_query$;
-
-REVOKE EXECUTE
-	ON FUNCTION events.ep_make_list_query(
-		BOOLEAN , BOOLEAN , BOOLEAN , BOOLEAN )
-	FROM PUBLIC;
-
-
-
-/*
- * List events
- * -----------
- * 
- * /!\ INTERNAL FUNCTION /!\
- * 
- * This procedure generates a list of events for some type of interface.
- * 
- * Parameters:
- *		_evi_id		Identifier of the interface accessing events
- *		_empire_id	The identifier of the empire to get events for (may be NULL)
- *		_accept_old	Whether processed events should be selected
- *		_accept_pre	Whether preprocessed events should be selected
- *		_accept_new	Whether unprocessed events should be selected
- *
- * Returns:
- * 		the set of events
- */
-DROP FUNCTION IF EXISTS events.ep_list_events(
-	TEXT , INT , BOOLEAN , BOOLEAN , BOOLEAN );
-CREATE FUNCTION events.ep_list_events(
-			_evi_id			TEXT ,
-			_empire_id		INT ,
-			_accept_old		BOOLEAN ,
-			_accept_pre		BOOLEAN ,
-			_accept_new		BOOLEAN )
-		RETURNS SETOF events.ep_list_entry
-		LANGUAGE PLPGSQL
-		CALLED ON NULL INPUT
-		STABLE SECURITY INVOKER
-	AS $ep_list_events$
-
-DECLARE
-	_record	events.ep_list_entry;
-
-BEGIN
-	FOR _record IN EXECUTE events.ep_make_list_query(
-				_empire_id IS NOT NULL ,
-				_accept_old , _accept_pre , _accept_new )
-			USING _evi_id , _empire_id
-	LOOP
-		RETURN NEXT _record;
-	END LOOP;
-END;
-$ep_list_events$;
-
-REVOKE EXECUTE
-	ON FUNCTION events.ep_list_events(
-		TEXT , INT , BOOLEAN , BOOLEAN , BOOLEAN )
-	FROM PUBLIC;
-
-
-
-DROP TYPE IF EXISTS events.event_list_type CASCADE;
-CREATE TYPE events.event_list_type AS (
-	/* Identifier of the empire to which the event applies */
-	empire_id		INT ,
-	
-	/* Identifier of the user who controls the empire */
-	user_id			INT ,
-
-	/* Selected language for the empire */
-	lang_id			TEXT ,
-
-	/* Numeric identifier of the event */
-	event_id		BIGINT ,
-	
-	/* The event's processing state */
-	event_state		events.processing_state ,
-
-	/* Real time at which the event occurred */
-	event_rtime		TIMESTAMP WITHOUT TIME ZONE ,
-
-	/* Game time (tick identifier) at which the event occurred */
-	event_gtime		BIGINT ,
-
-	/* Event priority from either the definition or the custom priorities */
-	event_priority	INT ,
-	
-	/* Type of the event */
-	evdef_id		TEXT ,
-
-	/* Internationalised string that contains the name of the event type;
-	 * used when displaying priority settings.
-	 */
-	evdef_name		TEXT ,
-	
-	/* Internationalised string that contains the template to use when
-	 * generating the output for a single event.
-	 */
-	evdef_template	TEXT ,
-	
-	/* Field name */
-	efdef_id		TEXT ,
-
-	/* Field value */
-	field_value		TEXT
-);
-
-
-
-/*
- * Main events listing function
- * ----------------------------
- * 
- * /!\ INTERNAL FUNCTION /!\
- * 
- * This function contains the main code for event access. It is capable of
- * selecting events based on their target and/or state, can limit the amount
- * of events fetched or fetch them starting from some offset, and is capable
- * of updating event states for selected events.
- * 
- * Parameters:
- *	_evi_id			The identifier of the interface accessing the events list
- *	_target_id		An empire or user identifier (may be NULL)
- *	_target_is_emp	Whether the specified identifier is an empire (TRUE) or an
- *						user. May be NULL.
- *	_accept_old		Whether processed events should be selected
- *	_accept_pre		Whether preprocessed events should be selected
- *	_accept_new		Whether unprocessed events should be selected
- *	_offset			Offset of the first event to obtain in the list. May be
- *						NULL.
- *	_limit			Maximal amount of events to list. May be NULL.
- *	_clear_pre		If TRUE, selected events that had been preprocessed will
- *						be marked as fully processed. May be NULL.
- *	_change_new		The state to which new events should be set. May be NULL
- *						or 'NEW' if no changes are to be made.
- *
- * Returns:
- * 	A set of events.event_list_type records
- */
-DROP FUNCTION IF EXISTS events.ep_get_events_internal(
-	TEXT , INT , BOOLEAN , BOOLEAN , BOOLEAN , BOOLEAN , INT , INT , BOOLEAN ,
-	events.processing_state ) CASCADE;
-CREATE FUNCTION events.ep_get_events_internal(
-			_evi_id			TEXT ,
-			_target_id		INT ,
-			_target_is_emp	BOOLEAN ,
-			_accept_old		BOOLEAN ,
-			_accept_pre		BOOLEAN ,
-			_accept_new		BOOLEAN ,
-			_offset			INT ,
-			_limit			INT ,
-			_clear_pre		BOOLEAN ,
-			_change_new		events.processing_state )
-		RETURNS SETOF events.event_list_type
-		LANGUAGE PLPGSQL
-		CALLED ON NULL INPUT
-		VOLATILE SECURITY INVOKER
-	AS $ep_get_events_internal$
-
-DECLARE
-	_sel_query	TEXT;
-	_empire_id	INT;
-	_record		events.event_list_type;
-
-BEGIN
-	-- Get empire identifier if necessary
-	IF NOT _target_is_emp
-	THEN
-		SELECT INTO _empire_id _emp.name_id
-			FROM emp.empires _emp
-				INNER JOIN naming.empire_names _emp_name
-					ON _emp.name_id = _emp_name.id
-			WHERE _emp_name.owner_id = _target_id;
-		IF NOT FOUND
-		THEN
-			RETURN;
-		END IF;
-	ELSE
-		_empire_id := _target_id;
-	END IF;
-
-	-- Generate event selection query
-	_sel_query := $sel_query$
-		CREATE TEMPORARY TABLE ep_selected
-			ON COMMIT DROP
-			AS SELECT * FROM events.ep_list_events(
-					$1 , $2 , $3 , $4 , $5 )
-	$sel_query$;
-	IF _offset >= 0
-	THEN
-		_sel_query := _sel_query || ' OFFSET ' || _offset;
-	END IF;
-	IF _limit > 0
-	THEN
-		_sel_query := _sel_query || ' LIMIT ' || _limit;
-	END IF;
-
-	-- Select events
-	EXECUTE _sel_query
-		USING _evi_id , _empire_id , _accept_old , _accept_pre , _accept_new;
-
-	-- Update event states if necessary
-	IF _clear_pre THEN
-		DELETE FROM events.unprocessed_events
-			WHERE event_id IN ( SELECT event_id FROM ep_selected )
-				AND upe_preprocessed
-				AND evi_id = _evi_id;
-	END IF;
-	IF _change_new = 'DONE'
-	THEN
-		DELETE FROM events.unprocessed_events
-			WHERE event_id IN ( SELECT event_id FROM ep_selected )
-				AND NOT upe_preprocessed
-				AND evi_id = _evi_id;
-	ELSIF _change_new = 'PRE'
-	THEN
-		UPDATE events.unprocessed_events _upe
-			SET upe_preprocessed = TRUE
-			FROM ep_selected _sel
-			WHERE _sel.event_id = _upe.event_id
-				AND NOT _upe.upe_preprocessed
-				AND _upe.evi_id = _evi_id;
-	END IF;
-
-	-- Select and return event data
-	FOR _record IN
-		SELECT _sel.empire_id , _emp_name.owner_id AS user_id ,
-				_lg.language AS lang_id , _sel.event_id ,
-				_sel.event_state , _ev.event_rtime , _ev.event_gtime ,
-				( CASE
-					WHEN _cp.evcp_priority IS NULL
-						THEN _evdef.evdef_priority
-					ELSE
-						_cp.evcp_priority
-				END ) AS event_priority ,
-				_evdef.evdef_id , _edns.name AS evdef_name ,
-				_edts.name AS evdef_template , _fval.efdef_id ,
-				_fval.efval_litteral AS field_value
-			FROM ep_selected _sel
-				INNER JOIN events.events_v2 _ev
-					USING ( event_id , evdef_id )
-				INNER JOIN events.event_definitions _evdef
-					USING ( evdef_id )
-				INNER JOIN naming.empire_names _emp_name
-					ON _emp_name.id = _sel.empire_id
-				INNER JOIN users.credentials _user
-					ON _user.address_id = _emp_name.owner_id
-				INNER JOIN defs.languages _lg
-					ON _lg.id = _user.language_id
-				INNER JOIN defs.strings _edns
-					ON _edns.id = _evdef.evdef_name_id
-				INNER JOIN defs.strings _edts
-					ON _edts.id = _evdef.evdef_template_id
-				LEFT OUTER JOIN events.field_values _fval
-					USING ( event_id , evdef_id )
-				LEFT OUTER JOIN events.custom_priorities _cp
-					USING ( evdef_id , evdef_adjustable , address_id )
-	LOOP
-		RETURN NEXT _record;
-	END LOOP;
-	
-	DROP TABLE ep_selected;
-END;
-$ep_get_events_internal$;
-
-REVOKE EXECUTE
-	ON FUNCTION events.ep_get_events_internal(
-		TEXT , INT , BOOLEAN , BOOLEAN , BOOLEAN , BOOLEAN , INT , INT ,
-		BOOLEAN , events.processing_state )
-	FROM PUBLIC;
-
-
-
-/*
- * READ-ONLY EVENT ACCESS WRAPPERS 
- */
-DROP FUNCTION IF EXISTS events.ep_read( TEXT, BOOLEAN , BOOLEAN , BOOLEAN );
-CREATE FUNCTION events.ep_read(
-		_evi_id			TEXT ,
-		_accept_old		BOOLEAN ,
-		_accept_pre		BOOLEAN ,
-		_accept_new		BOOLEAN )
-	RETURNS SETOF events.event_list_type
-	LANGUAGE SQL
-	STRICT VOLATILE SECURITY DEFINER
-AS $ep_read$
-	SELECT * FROM events.ep_get_events_internal( $1 , NULL , NULL , $2 , $3 ,
-		$4 , NULL , NULL , NULL , NULL );
-$ep_read$;
-
-REVOKE EXECUTE
-	ON FUNCTION events.ep_read( TEXT , BOOLEAN , BOOLEAN , BOOLEAN )
-	FROM PUBLIC;
-GRANT EXECUTE
-	ON FUNCTION events.ep_read( TEXT , BOOLEAN , BOOLEAN , BOOLEAN )
-	TO :dbuser;
-
-DROP FUNCTION IF EXISTS events.ep_read(
-	TEXT , INT , BOOLEAN , BOOLEAN , BOOLEAN , BOOLEAN );
-CREATE FUNCTION events.ep_read(
-		_evi_id			TEXT ,
-		_target_id		INT ,
-		_target_is_emp	BOOLEAN ,
-		_accept_old		BOOLEAN ,
-		_accept_pre		BOOLEAN ,
-		_accept_new		BOOLEAN )
-	RETURNS SETOF events.event_list_type
-	LANGUAGE SQL
-	STRICT VOLATILE SECURITY DEFINER
-AS $ep_read$
-	SELECT * FROM events.ep_get_events_internal( $1 , $2 , $3 , $4 , $5 , $6 ,
-		NULL , NULL , NULL , NULL );
-$ep_read$;
-
-REVOKE EXECUTE
-	ON FUNCTION events.ep_read(
-		TEXT , INT , BOOLEAN , BOOLEAN , BOOLEAN , BOOLEAN )
-	FROM PUBLIC;
-GRANT EXECUTE
-	ON FUNCTION events.ep_read(
-		TEXT , INT , BOOLEAN , BOOLEAN , BOOLEAN , BOOLEAN )
-	TO :dbuser;
-
-DROP FUNCTION IF EXISTS events.ep_read(
-	TEXT, BOOLEAN , BOOLEAN , BOOLEAN , INT , INT );
-CREATE FUNCTION events.ep_read(
-		_evi_id			TEXT ,
-		_accept_old		BOOLEAN ,
-		_accept_pre		BOOLEAN ,
-		_accept_new		BOOLEAN ,
-		_offset			INT ,
-		_limit			INT )
-	RETURNS SETOF events.event_list_type
-	LANGUAGE SQL
-	STRICT VOLATILE SECURITY DEFINER
-AS $ep_read$
-	SELECT * FROM events.ep_get_events_internal( $1 , NULL , NULL , $2 , $3 ,
-		$4 , $5 , $6 , NULL , NULL );
-$ep_read$;
-
-REVOKE EXECUTE
-	ON FUNCTION events.ep_read(
-		TEXT , BOOLEAN , BOOLEAN , BOOLEAN , INT , INT )
-	FROM PUBLIC;
-GRANT EXECUTE
-	ON FUNCTION events.ep_read(
-		TEXT , BOOLEAN , BOOLEAN , BOOLEAN , INT , INT )
-	TO :dbuser;
-
-DROP FUNCTION IF EXISTS events.ep_read(
-	TEXT , INT , BOOLEAN , BOOLEAN , BOOLEAN , BOOLEAN , INT , INT );
-CREATE FUNCTION events.ep_read(
-		_evi_id			TEXT ,
-		_target_id		INT ,
-		_target_is_emp	BOOLEAN ,
-		_accept_old		BOOLEAN ,
-		_accept_pre		BOOLEAN ,
-		_accept_new		BOOLEAN ,
-		_offset			INT ,
-		_limit			INT )
-	RETURNS SETOF events.event_list_type
-	LANGUAGE SQL
-	STRICT VOLATILE SECURITY DEFINER
-AS $ep_read$
-	SELECT * FROM events.ep_get_events_internal( $1 , $2 , $3 , $4 , $5 , $6 ,
-		$7 , $8 , NULL , NULL );
-$ep_read$;
-
-REVOKE EXECUTE
-	ON FUNCTION events.ep_read(
-		TEXT , INT , BOOLEAN , BOOLEAN , BOOLEAN , BOOLEAN , INT , INT )
-	FROM PUBLIC;
-GRANT EXECUTE
-	ON FUNCTION events.ep_read(
-		TEXT , INT , BOOLEAN , BOOLEAN , BOOLEAN , BOOLEAN , INT , INT )
-	TO :dbuser;
-
-
-/*
- * EVENT ACCESS WRAPPERS WITH UPDATE CAPABILITIES 
- */
-DROP FUNCTION IF EXISTS events.ep_access(
-	TEXT, BOOLEAN , BOOLEAN , BOOLEAN , BOOLEAN , events.processing_state );
-CREATE FUNCTION events.ep_access(
-		_evi_id			TEXT ,
-		_accept_old		BOOLEAN ,
-		_accept_pre		BOOLEAN ,
-		_accept_new		BOOLEAN ,
-		_clear_pre		BOOLEAN ,
-		_change_new		events.processing_state )
-	RETURNS SETOF events.event_list_type
-	LANGUAGE SQL
-	STRICT VOLATILE SECURITY DEFINER
-AS $ep_access$
-	SELECT * FROM events.ep_get_events_internal( $1 , NULL , NULL , $2 , $3 ,
-		$4 , NULL , NULL , $5 , $6 );
-$ep_access$;
-
-REVOKE EXECUTE
-	ON FUNCTION events.ep_access(
-		TEXT , BOOLEAN , BOOLEAN , BOOLEAN , BOOLEAN ,
-		events.processing_state )
-	FROM PUBLIC;
-GRANT EXECUTE
-	ON FUNCTION events.ep_access(
-		TEXT , BOOLEAN , BOOLEAN , BOOLEAN , BOOLEAN ,
-		events.processing_state )
-	TO :dbuser;
-
-DROP FUNCTION IF EXISTS events.ep_access(
-	TEXT , INT , BOOLEAN , BOOLEAN , BOOLEAN , BOOLEAN , BOOLEAN ,
-	events.processing_state );
-CREATE FUNCTION events.ep_access(
-		_evi_id			TEXT ,
-		_target_id		INT ,
-		_target_is_emp	BOOLEAN ,
-		_accept_old		BOOLEAN ,
-		_accept_pre		BOOLEAN ,
-		_accept_new		BOOLEAN ,
-		_clear_pre		BOOLEAN ,
-		_change_new		events.processing_state )
-	RETURNS SETOF events.event_list_type
-	LANGUAGE SQL
-	STRICT VOLATILE SECURITY DEFINER
-AS $ep_access$
-	SELECT * FROM events.ep_get_events_internal( $1 , $2 , $3 , $4 , $5 , $6 ,
-		NULL , NULL , $7 , $8 );
-$ep_access$;
-
-REVOKE EXECUTE
-	ON FUNCTION events.ep_access(
-		TEXT , INT , BOOLEAN , BOOLEAN , BOOLEAN , BOOLEAN ,
-		BOOLEAN , events.processing_state )
-	FROM PUBLIC;
-GRANT EXECUTE
-	ON FUNCTION events.ep_access(
-		TEXT , INT , BOOLEAN , BOOLEAN , BOOLEAN , BOOLEAN ,
-		BOOLEAN , events.processing_state )
-	TO :dbuser;
-
-DROP FUNCTION IF EXISTS events.ep_access(
-	TEXT, BOOLEAN , BOOLEAN , BOOLEAN , INT , INT , BOOLEAN ,
-	events.processing_state );
-CREATE FUNCTION events.ep_access(
-		_evi_id			TEXT ,
-		_accept_old		BOOLEAN ,
-		_accept_pre		BOOLEAN ,
-		_accept_new		BOOLEAN ,
-		_offset			INT ,
-		_limit			INT ,
-		_clear_pre		BOOLEAN ,
-		_change_new		events.processing_state )
-	RETURNS SETOF events.event_list_type
-	LANGUAGE SQL
-	STRICT VOLATILE SECURITY DEFINER
-AS $ep_access$
-	SELECT * FROM events.ep_get_events_internal( $1 , NULL , NULL , $2 , $3 ,
-		$4 , $5 , $6 , $7 , $8 );
-$ep_access$;
-
-REVOKE EXECUTE
-	ON FUNCTION events.ep_access(
-		TEXT , BOOLEAN , BOOLEAN , BOOLEAN , INT , INT , BOOLEAN ,
-		events.processing_state )
-	FROM PUBLIC;
-GRANT EXECUTE
-	ON FUNCTION events.ep_access(
-		TEXT , BOOLEAN , BOOLEAN , BOOLEAN , INT , INT , BOOLEAN ,
-		events.processing_state )
-	TO :dbuser;
-
-DROP FUNCTION IF EXISTS events.ep_access(
-	TEXT , INT , BOOLEAN , BOOLEAN , BOOLEAN , BOOLEAN , INT , INT , BOOLEAN ,
-	events.processing_state );
-CREATE FUNCTION events.ep_access(
-		_evi_id			TEXT ,
-		_target_id		INT ,
-		_target_is_emp	BOOLEAN ,
-		_accept_old		BOOLEAN ,
-		_accept_pre		BOOLEAN ,
-		_accept_new		BOOLEAN ,
-		_offset			INT ,
-		_limit			INT ,
-		_clear_pre		BOOLEAN ,
-		_change_new		events.processing_state )
-	RETURNS SETOF events.event_list_type
-	LANGUAGE SQL
-	STRICT VOLATILE SECURITY DEFINER
-AS $ep_access$
-	SELECT * FROM events.ep_get_events_internal( $1 , $2 , $3 , $4 , $5 , $6 ,
-		$7 , $8 , $9 , $10 );
-$ep_access$;
-
-REVOKE EXECUTE
-	ON FUNCTION events.ep_access(
-		TEXT , INT , BOOLEAN , BOOLEAN , BOOLEAN , BOOLEAN , INT , INT,
-		BOOLEAN , events.processing_state )
-	FROM PUBLIC;
-GRANT EXECUTE
-	ON FUNCTION events.ep_access(
-		TEXT , INT , BOOLEAN , BOOLEAN , BOOLEAN , BOOLEAN , INT , INT ,
-		BOOLEAN , events.processing_state )
-	TO :dbuser;
diff --git a/legacyworlds-server-data/db-structure/parts/050-updates/000-updates-ctrl.sql b/legacyworlds-server-data/db-structure/parts/050-updates/000-updates-ctrl.sql
deleted file mode 100644
index 7ab8252..0000000
--- a/legacyworlds-server-data/db-structure/parts/050-updates/000-updates-ctrl.sql
+++ /dev/null
@@ -1,258 +0,0 @@
--- LegacyWorlds Beta 6
--- PostgreSQL database scripts
---
--- Game updates - control functions
---
--- Copyright(C) 2004-2010, DeepClone Development
--- --------------------------------------------------------
-
-
-
-/*
- * Start a game update cycle
- * --------------------------
- *
- * This function prepares the execution of a cycle of game updates. It will
- * try to find the identifier of the next update, and mark all game updates
- * as requiring an update for this identifier.
- * 
- * Returns:
- *		tick_id		The identifier of the new update cycle, or NULL if an
- *						update was already in progress. 
- */
-DROP FUNCTION IF EXISTS sys.start_tick( ) CASCADE;
-CREATE FUNCTION sys.start_tick( OUT tick_id BIGINT )
-		LANGUAGE PLPGSQL
-		STRICT VOLATILE
-		SECURITY DEFINER
-	AS $start_tick$
-
-DECLARE
-	n_tick	BIGINT;
-	c_tick	BIGINT;
-
-BEGIN
-	-- Get next / current tick
-	SELECT INTO n_tick , c_tick next_tick , current_tick
-		FROM sys.status
-		WHERE maintenance_start IS NULL
-		FOR UPDATE;
-	IF NOT FOUND OR c_tick IS NOT NULL THEN
-		tick_id := NULL;
-		RETURN;
-	END IF;
-
-	-- Prepare game updates
-	UPDATE sys.updates
-		SET update_last = n_tick ,
-			update_state = 'FUTURE'
-		WHERE update_last < n_tick;
-
-	-- Update system status
-	UPDATE sys.status
-		SET current_tick = n_tick ,
-			next_tick = n_tick + 1;
-	
-	tick_id := n_tick;
-
-END;
-$start_tick$;
-
-REVOKE EXECUTE
-	ON FUNCTION sys.start_tick( )
-	FROM PUBLIC;
-GRANT EXECUTE
-	ON FUNCTION sys.start_tick( )
-	TO :dbuser;
-
-
-
---
--- Marks a tick as completed
---
-
-CREATE OR REPLACE FUNCTION sys.end_tick( IN tick_id BIGINT )
-		RETURNS VOID
-		STRICT VOLATILE
-		SECURITY INVOKER
-	AS $$
-BEGIN
-	UPDATE events.events SET status = 'READY'
-		WHERE status = 'TICK' AND tick = tick_id;
-	UPDATE sys.status SET current_tick = NULL;
-	PERFORM msgs.deliver_internal( );
-END;
-$$ LANGUAGE plpgsql;
-
-
-
-/*
- * Check if a game update cycle got "stuck"
- * -----------------------------------------
- * 
- * Check sys.status for an in-progress game update identifier. If there is
- * one, check if there are further updates to execute in the cycle in
- * question.
- * 
- * Returns:
- *		tick_id		The stuck tick's identifier, or NULL if there is no stuck
- *						tick or if maintenance mode is enabled  
- */
-DROP FUNCTION IF EXISTS sys.check_stuck_tick( ) CASCADE;
-CREATE FUNCTION sys.check_stuck_tick( OUT tick_id BIGINT )
-		LANGUAGE PLPGSQL
-		STRICT VOLATILE
-		SECURITY DEFINER
-	AS $check_stuck_tick$
-
-DECLARE
-	c_tick	BIGINT;
-	u_count	INT;
-
-BEGIN
-	-- Get next / current tick
-	SELECT INTO c_tick current_tick
-		FROM sys.status
-		WHERE maintenance_start IS NULL
-		FOR UPDATE;
-	IF NOT FOUND OR c_tick IS NULL THEN
-		tick_id := NULL;
-		RETURN;
-	END IF;
-	
-	-- Are there any updates left?
-	SELECT INTO u_count count(*)
-		FROM sys.updates
-		WHERE update_state = 'FUTURE'
-			AND update_last = c_tick;
-	IF u_count = 0 THEN
-		PERFORM sys.end_tick( c_tick );
-		tick_id := NULL;
-	ELSE
-		tick_id := c_tick;
-	END IF;
-
-END;
-$check_stuck_tick$;
-
-REVOKE EXECUTE
-	ON FUNCTION sys.check_stuck_tick( )
-	FROM PUBLIC;
-GRANT EXECUTE
-	ON FUNCTION sys.check_stuck_tick( )
-	TO :dbuser;
-
-
-
-/*
- * Process game updates
- * ---------------------
- * 
- * This function checks for game update elements, marking some of them for
- * processing depending on their type. If there are no more updates to run,
- * end the update cycle; otherwise, depending on the type of update, process
- * the items internally or return a value that indicates they are to be
- * processed by the external Java code.
- * 
- * Parameters:
- *		_current_update		Current game update's identifier
- *
- * Returns:
- *		_has_more			TRUE if the function must be called again, FALSE
- *								otherwise
- *		_process_externally	NULL if there is no update to process or if the
- *								updates were processed in the database, or
- *								the name of the update type if external
- *								processing is needed.
- */
-DROP FUNCTION IF EXISTS sys.process_updates( BIGINT ) CASCADE;
-CREATE FUNCTION sys.process_updates(
-			IN _current_update BIGINT ,
-			OUT _has_more BOOLEAN ,
-			OUT _process_externally TEXT )
-		LANGUAGE PLPGSQL
-		STRICT VOLATILE
-		SECURITY DEFINER
-	AS $process_updates$
-
-DECLARE
-	_current_type	INT;
-	_batch_size		INT;
-	_type_name		TEXT;
-	_proc_name		NAME;
-
-BEGIN
-	-- Mark all entries that were being processed as having been processed
-	UPDATE sys.updates
-		SET update_state = 'PROCESSED'
-		WHERE update_state = 'PROCESSING'
-			AND update_last = _current_update;
-
-	-- Find the next type of update to process and its specific parameters
-	SELECT INTO _current_type , _batch_size , _type_name , _proc_name
-			updtype_id , updtype_batch_size , updtype_name , updtype_proc_name
-		FROM sys.update_types
-			INNER JOIN sys.updates
-				USING ( updtype_id , updtgt_id )
-		WHERE update_state = 'FUTURE'
-			AND update_last = _current_update
-		ORDER BY updtype_ordering
-		LIMIT 1;
-
-	_has_more := FOUND;
-	IF _has_more THEN
-		-- Check batch size
-		IF _batch_size IS NULL THEN
-			_batch_size := sys.get_constant( 'game.batchSize' ); 
-		END IF;
-	
-		-- Mark at most _batch_size entries of the right type as being updated
-		UPDATE sys.updates
-			SET update_state = 'PROCESSING'
-			WHERE update_id IN (
-					SELECT update_id FROM sys.updates
-						WHERE updtype_id = _current_type
-							AND update_state = 'FUTURE'
-							AND update_last = _current_update
-						LIMIT _batch_size
-				);
-
-		IF _proc_name IS NULL THEN
-			-- External processing is required
-			_process_externally := _type_name;
-		ELSE
-			-- Process updates using a stored procedure
-			EXECUTE 'SELECT sys."' || _proc_name || '"( $1 )'
-				USING _current_update;
-		END IF;
-	ELSE
-		-- No updates left to run
-		PERFORM sys.end_tick( _current_update );
-	END IF;
-END;
-$process_updates$;
-
-REVOKE EXECUTE
-	ON FUNCTION sys.process_updates( BIGINT )
-	FROM PUBLIC;
-GRANT EXECUTE
-	ON FUNCTION sys.process_updates( BIGINT )
-	TO :dbuser;
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/legacyworlds-server-data/db-structure/parts/050-updates/005-core-update-targets.sql b/legacyworlds-server-data/db-structure/parts/050-updates/005-core-update-targets.sql
deleted file mode 100644
index 8fa557e..0000000
--- a/legacyworlds-server-data/db-structure/parts/050-updates/005-core-update-targets.sql
+++ /dev/null
@@ -1,16 +0,0 @@
--- LegacyWorlds Beta 6
--- PostgreSQL database scripts
---
--- Game updates - core update targets
---
--- Copyright(C) 2004-2012, DeepClone Development
--- --------------------------------------------------------
-
-INSERT INTO sys.update_targets (
-		updtgt_name , updtgt_schema , updtgt_table
-	) VALUES (
-		'Planets' , 'verse' , 'planets'
-	) , (
-		'Empires' , 'emp' , 'empires'
-	);
-	
diff --git a/legacyworlds-server-data/db-structure/parts/050-updates/015-empire-resources.sql b/legacyworlds-server-data/db-structure/parts/050-updates/015-empire-resources.sql
deleted file mode 100644
index 64d1448..0000000
--- a/legacyworlds-server-data/db-structure/parts/050-updates/015-empire-resources.sql
+++ /dev/null
@@ -1,85 +0,0 @@
--- LegacyWorlds Beta 6
--- PostgreSQL database scripts
---
--- Game updates - empire resources
---
--- Copyright(C) 2004-2012, DeepClone Development
--- --------------------------------------------------------
-
-
-/*
- * Empire resources update
- * 
- * For each empire in the update batch, compute the new amount of resources
- * based on the upkeep and income from planets.
- * 
- * FIXME: this should also include fleet upkeeps. This situation will be
- *        resolved once the system is modified to rely solely on resources.
- * 
- * Parameters:
- *		_tick		The identifier of the game update
- */
-DROP FUNCTION IF EXISTS sys.process_empire_resources_updates( BIGINT );
-CREATE FUNCTION sys.process_empire_resources_updates( _tick BIGINT )
-	RETURNS VOID
-	STRICT VOLATILE
-	SECURITY INVOKER
-AS $process_empire_resources_updates$
-
-	UPDATE emp.resources _emp_resources
-
-		SET empres_possessed = CASE
-				WHEN _emp_resources.empres_possessed + _raw.res_delta > 0 THEN
-					_emp_resources.empres_possessed + _raw.res_delta
-				ELSE
-					0
-				END ,
-			empres_owed = CASE
-				WHEN _emp_resources.empres_possessed + _raw.res_delta < 0 THEN
-					 -( _emp_resources.empres_possessed + _raw.res_delta ) 
-				ELSE
-					0
-				END
-
-		FROM (
-			SELECT _upd_emp.name_id AS empire_id ,  _pl_resources.resource_name_id ,
-					( _pl_resources.pres_income - _pl_resources.pres_upkeep ) / ( CASE
-						WHEN _vacation.account_id IS NULL THEN
-							1
-						ELSE
-							sys.get_constant( 'vacation.cashDivider' )
-					END ) AS res_delta
-
-				FROM sys.updates _upd_sys
-					INNER JOIN emp.empires_updates _upd_emp
-						USING ( updtgt_id , updtype_id , update_id )
-					INNER JOIN emp.planets _emp_planets
-						ON empire_id = name_id
-					INNER JOIN verse.planet_resources _pl_resources
-						USING ( planet_id )
-					INNER JOIN naming.empire_names _emp_name
-						ON _emp_name.id = _upd_emp.name_id
-					LEFT OUTER JOIN users.vacations _vacation
-						ON _vacation.account_id = _emp_name.owner_id
-							AND _vacation.status = 'PROCESSED'
-
-				WHERE _upd_sys.update_last = $1
-					AND _upd_sys.update_state = 'PROCESSING'
-			) _raw
-
-		WHERE _emp_resources.empire_id = _raw.empire_id
-			AND _emp_resources.resource_name_id = _raw.resource_name_id;
-
-$process_empire_resources_updates$ LANGUAGE SQL;
-
-
-REVOKE EXECUTE
-	ON FUNCTION sys.process_empire_resources_updates( BIGINT )
-	FROM PUBLIC;
-
-
-
-SELECT sys.register_update_type( 'Empires' , 'EmpireResources' ,
-		'Empires'' resources are being updated using the previous update''s results. ' ,
-		'process_empire_resources_updates'
-	);
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/parts/050-updates/020-empire-research.sql b/legacyworlds-server-data/db-structure/parts/050-updates/020-empire-research.sql
deleted file mode 100644
index 6500839..0000000
--- a/legacyworlds-server-data/db-structure/parts/050-updates/020-empire-research.sql
+++ /dev/null
@@ -1,192 +0,0 @@
--- LegacyWorlds Beta 6
--- PostgreSQL database scripts
---
--- Game updates - empire research
---
--- Copyright(C) 2004-2012, DeepClone Development
--- --------------------------------------------------------
-
-
-/*
- * Empire update data
- * -------------------
- * 
- * This type can be used to return empires along with their "on vacation"
- * status.
- * 
- * FIXME: it should probably be somewhere else, but for now this is the only
- * file that uses it.
- */
-DROP TYPE IF EXISTS sys.empire_update_type CASCADE;
-CREATE TYPE sys.empire_update_type AS (
-	/* The empire's identifier */
-	empire_id		INT ,
-
-	/* TRUE if the player is on vacation, FALSE otherwise */
-	on_vacation		BOOLEAN
-);
-
-
-/*
- * Lock records and list empires which require a research update
- * --------------------------------------------------------------
- * 
- * This function will lock all records needed for a research update, and
- * return the list of empires to be updated. These empires, in addition to
- * being marked for update, must possess planets and have in-progress
- * research.
- * 
- * Parameters:
- *		_tick		The identifier of the current update cycle
- *
- * Returns a set of:
- * 		empire_id	The empire's identifier
- *		on_vacation	TRUE if the player is on vacation, FALSE otherwise
- */
-DROP FUNCTION IF EXISTS sys.gu_research_get_empires( BIGINT ) CASCADE;
-CREATE FUNCTION sys.gu_research_get_empires( _tick BIGINT )
-	RETURNS SETOF sys.empire_update_type
-	LANGUAGE SQL
-	STRICT VOLATILE
-	SECURITY INVOKER
-AS $gu_research_get_empires$
-
-	SELECT DISTINCT * FROM (
-		SELECT _empire.name_id AS empire_id ,
-				( _vacation.status IS NOT NULL AND
-					_vacation.status = 'PROCESSED' ) AS on_vacation
-			FROM sys.updates _upd_sys
-				INNER JOIN emp.empires_updates _emp_update
-					USING ( updtgt_id , updtype_id , update_id )
-				INNER JOIN emp.empires _empire
-					USING ( name_id )
-				INNER JOIN emp.technologies _emp_tech
-					ON _emp_tech.empire_id = _empire.name_id
-				INNER JOIN defs.technologies _tech
-					USING ( technology_name_id )
-				INNER JOIN emp.planets _emp_planet
-					USING ( empire_id )
-				INNER JOIN verse.planets _planet
-					ON _emp_planet.planet_id = _planet.name_id
-				INNER JOIN verse.planet_happiness _happiness
-					USING ( planet_id )
-				INNER JOIN naming.empire_names _emp_name
-					ON _emp_name.id = _empire.name_id
-				INNER JOIN users.credentials _user
-					ON _user.address_id = _emp_name.owner_id
-				LEFT OUTER JOIN users.vacations _vacation
-					ON _vacation.account_id = _emp_name.owner_id
-			WHERE _upd_sys.update_last = $1
-				AND _upd_sys.update_state = 'PROCESSING'
-				AND _emp_tech.emptech_state = 'RESEARCH'
-			FOR UPDATE OF _upd_sys , _emp_update , _emp_tech
-			FOR SHARE OF _empire , _tech , _emp_planet , _planet ,
-				_happiness , _emp_name , _user
-		) _sub;
-
-$gu_research_get_empires$;
-
-REVOKE EXECUTE
-	ON FUNCTION sys.gu_research_get_empires( BIGINT )
-	FROM PUBLIC;
-
-
-/*
- * Update research for a single empire
- * ------------------------------------
- *
- * This stored procedure updates research points for all in-progress research
- * of a single empire.
- *
- * Parameters:
- * 		_empire_id		The empire's identifier
- *		_on_vacation	TRUE if the player is on vacation, FALSE otherwise
- */
-DROP FUNCTION IF EXISTS sys.gu_research_update_empire( INT , BOOLEAN ) CASCADE;
-CREATE FUNCTION sys.gu_research_update_empire( _empire INT , _on_vacation BOOLEAN )
-		RETURNS VOID
-		LANGUAGE PLPGSQL
-		STRICT VOLATILE
-		SECURITY INVOKER
-	AS $gu_research_update_empire$
-
-DECLARE
-	_points		DOUBLE PRECISION;
-	_record		RECORD;
-
-BEGIN
-
-	_points := emp.research_get_points( _empire , _on_vacation );	
-	FOR _record IN
-			SELECT _emp_tech.technology_name_id , _emp_tech.emptech_points , _emp_tech.emptech_priority ,
-					_points * _weights.emptech_weight / ( _totals.emptech_total_weight * 1440 ) AS emptech_new_points ,
-					_def.technology_points::DOUBLE PRECISION AS technology_points
-				FROM emp.technologies _emp_tech
-					INNER JOIN emp.research_weights_view _weights
-						USING ( empire_id , technology_name_id )
-					INNER JOIN emp.research_total_weights_view _totals
-						USING ( empire_id )
-					INNER JOIN defs.technologies _def
-						USING ( technology_name_id )
-				WHERE _emp_tech.empire_id = _empire
-					AND _emp_tech.emptech_state = 'RESEARCH'
-	LOOP
-
-		IF _record.emptech_points + _record.emptech_new_points >= _record.technology_points THEN
-			UPDATE emp.technologies
-				SET emptech_state = 'PENDING' ,
-					emptech_points = NULL ,
-					emptech_priority = NULL
-				WHERE technology_name_id = _record.technology_name_id
-					AND empire_id = _empire;
-
-		ELSE
-			UPDATE emp.technologies 
-				SET emptech_points = emptech_points + _record.emptech_new_points
-				WHERE technology_name_id = _record.technology_name_id
-					AND empire_id = _empire;
-		END IF;
-
-	END LOOP;
-
-END;
-$gu_research_update_empire$;
-
-REVOKE EXECUTE
-	ON FUNCTION sys.gu_research_update_empire( INT , BOOLEAN )
-	FROM PUBLIC;
-
-
-
-/*
- * Process a batch of empire research updates
- * -------------------------------------------
- * 
- * Update all empires in the batch which have both in-progress research and
- * planets.
- * 
- * Parameters:
- *		_tick		The identifier of the current update cycle
- */
-DROP FUNCTION IF EXISTS sys.process_empire_research_updates( BIGINT ) CASCADE;
-CREATE FUNCTION sys.process_empire_research_updates( _tick BIGINT )
-	RETURNS VOID
-	LANGUAGE SQL
-	STRICT VOLATILE
-	SECURITY INVOKER
-AS $process_empire_research_updates$
-
-	SELECT sys.gu_research_update_empire( empire_id , on_vacation )
-		FROM sys.gu_research_get_empires( $1::BIGINT );
-
-$process_empire_research_updates$;
-
-REVOKE EXECUTE
-	ON FUNCTION sys.process_empire_research_updates( BIGINT )
-	FROM PUBLIC;
-
-
-SELECT sys.register_update_type( 'Empires' , 'EmpireResearch' ,
-		'Empire research points are being attributed to technologies.' ,
-		'process_empire_research_updates'
-	);
diff --git a/legacyworlds-server-data/db-structure/parts/050-updates/070-planet-abandon.sql b/legacyworlds-server-data/db-structure/parts/050-updates/070-planet-abandon.sql
deleted file mode 100644
index 1cdb636..0000000
--- a/legacyworlds-server-data/db-structure/parts/050-updates/070-planet-abandon.sql
+++ /dev/null
@@ -1,61 +0,0 @@
--- LegacyWorlds Beta 6
--- PostgreSQL database scripts
---
--- Game updates - abandon
---
--- Copyright(C) 2004-2010, DeepClone Development
--- --------------------------------------------------------
-
-
-CREATE OR REPLACE FUNCTION sys.process_planet_abandon_updates( c_tick BIGINT )
-		RETURNS VOID
-		STRICT VOLATILE
-		SECURITY INVOKER
-	AS $$
-DECLARE
-	p_id	INT;
-BEGIN
-	-- Lock all records
-	PERFORM p.name_id
-		FROM sys.updates su
-			INNER JOIN verse.planets_updates vu
-				USING ( update_id , updtype_id , updtgt_id )
-			INNER JOIN verse.planets p
-				USING ( name_id )
-			INNER JOIN emp.planets ep
-				ON ep.planet_id = p.name_id 
-			INNER JOIN emp.empires e
-				ON e.name_id = ep.empire_id
-			INNER JOIN emp.abandon a
-				ON a.planet_id = p.name_id
-		WHERE su.update_last = c_tick AND su.update_state = 'PROCESSING'
-		FOR UPDATE;
-
-	-- Handle planets where time has run out
-	FOR p_id IN SELECT p.name_id
-					FROM sys.updates su
-						INNER JOIN verse.planets_updates vu
-							USING ( update_id , updtype_id , updtgt_id )
-						INNER JOIN verse.planets p
-							USING ( name_id )
-							INNER JOIN emp.abandon a ON a.planet_id = p.name_id
-					WHERE su.update_last = c_tick AND su.update_state = 'PROCESSING'
-						AND a.time_left = 1
-	LOOP
-		PERFORM emp.leave_planet( p_id );
-	END LOOP;
-	
-	-- Update all abandon records
-	UPDATE emp.abandon a SET time_left = a.time_left - 1
-		FROM sys.updates su
-			INNER JOIN verse.planets_updates vu
-				USING ( update_id , updtype_id , updtgt_id )
-		WHERE su.update_last = c_tick AND su.update_state = 'PROCESSING'
-			AND a.planet_id = vu.name_id;
-END;
-$$ LANGUAGE plpgsql;
-
-SELECT sys.register_update_type( 'Planets' , 'PlanetAbandon' ,
-		'Planets are being abandoned.' ,
-		'process_planet_abandon_updates'
-	);
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/parts/050-updates/105-planet-resource-regeneration.sql b/legacyworlds-server-data/db-structure/parts/050-updates/105-planet-resource-regeneration.sql
deleted file mode 100644
index a0a6db3..0000000
--- a/legacyworlds-server-data/db-structure/parts/050-updates/105-planet-resource-regeneration.sql
+++ /dev/null
@@ -1,51 +0,0 @@
--- LegacyWorlds Beta 6
--- PostgreSQL database scripts
---
--- Game updates - resource regeneration
---
--- Copyright(C) 2004-2012, DeepClone Development
--- --------------------------------------------------------
-
-
-/*
- * Resource provider regeneration update
- * 
- * This function computes the regeneration of resource providers for the current batch
- * of planets.
- * 
- * Parameters:
- *		_tick		The identifier of the game update
- */
-CREATE OR REPLACE FUNCTION sys.process_res_regen_updates( _tick BIGINT )
-	RETURNS VOID
-	STRICT VOLATILE
-	SECURITY INVOKER
-AS $process_planet_res_regen_updates$
-
-	UPDATE verse.resource_providers _provider
-
-		SET resprov_quantity = verse.compute_provider_regeneration(
-				_provider.resprov_quantity ,
-				_provider.resprov_quantity_max ,
-				_provider.resprov_recovery
-			)
-
-		FROM sys.updates _upd_sys
-			INNER JOIN verse.planets_updates _upd_verse
-				USING ( update_id , updtype_id , updtgt_id )
-
-		WHERE _upd_sys.update_last = $1
-			AND _upd_sys.update_state = 'PROCESSING'
-			AND _provider.planet_id = _upd_verse.name_id;
-
-$process_planet_res_regen_updates$ LANGUAGE SQL;
-
-
-REVOKE EXECUTE
-	ON FUNCTION sys.process_res_regen_updates( BIGINT )
-	FROM PUBLIC;
-
-SELECT sys.register_update_type( 'Planets' , 'ResourceRegeneration' ,
-		'Resource providers are being regenerated.' ,
-		'process_res_regen_updates'
-	);
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/parts/050-updates/120-planet-mining.sql b/legacyworlds-server-data/db-structure/parts/050-updates/120-planet-mining.sql
deleted file mode 100644
index 1a6ae31..0000000
--- a/legacyworlds-server-data/db-structure/parts/050-updates/120-planet-mining.sql
+++ /dev/null
@@ -1,160 +0,0 @@
--- LegacyWorlds Beta 6
--- PostgreSQL database scripts
---
--- Game updates - planet mining computations
---
--- Copyright(C) 2004-2012, DeepClone Development
--- --------------------------------------------------------
-
-
-/*
- * Lock the rows and access the data used by the mining update
- * 
- * This function executes a single query which serves the dual purpose of
- * locking all rows from various tables used by the planet mining update
- * and returning the data needed by the computation.
- *
- * As far as locking is concerned, the following tables are locked: 
- *	- Update records are already locked, so we don't care.
- *	- Planets with resource providers are locked for share.
- *	- Resource providers and corresponding resource records are locked
- *		for update
- *	- Resource definitions are locked for share.
- *	- Owning empires, as well as their mining settings and any set of
- *		planet-specific settings for one of the planets we're inspecting,
- *		are locked for share.
- *
- * The data itself is returned as a set of rows using emp.planet_mining_type
- * 
- * Parameters:
- *		_tick			The identifier of the current game update
- */ 
-DROP FUNCTION IF EXISTS sys.gu_pmc_get_data( BIGINT );
-CREATE FUNCTION sys.gu_pmc_get_data( _tick BIGINT )
-	RETURNS SETOF emp.planet_mining_type
-	STRICT VOLATILE
-	SECURITY INVOKER
-AS $gu_pmc_get_data$
-	SELECT planet_id AS planet ,
-			resource_name_id AS resource,
-			resprov_quantity AS quantity ,
-			resprov_quantity_max AS quantity_max ,
-			resprov_difficulty AS difficulty ,
-			empire_id AS empire ,
-			( happy_pop / _planet.population ) AS happiness ,
-			pmc_weight AS weight ,
-			pmc_total AS total_weight
-
-		FROM sys.updates _upd_sys
-			INNER JOIN verse.planets_updates _upd_verse
-				USING ( update_id , updtype_id , updtgt_id )
-			INNER JOIN verse.planets _planet
-				USING ( name_id )
-			INNER JOIN verse.resource_providers _resprov
-				ON planet_id = name_id
-			INNER JOIN verse.planet_resources _pres
-				USING ( planet_id , resource_name_id )
-			LEFT OUTER JOIN (
-						SELECT _emp_planet.empire_id , _emp_planet.planet_id ,
-								_emset.resource_name_id , pmc_weight , pmc_total ,
-								_happ.current AS happy_pop
-		
-							FROM sys.updates _upd_sys
-								INNER JOIN verse.planets_updates _upd_verse
-									USING ( update_id , updtype_id , updtgt_id )
-								INNER JOIN emp.planets _emp_planet
-									ON _emp_planet.planet_id = _upd_verse.name_id 
-								INNER JOIN emp.empires _emp
-									ON _emp_planet.empire_id = _emp.name_id
-								INNER JOIN emp.mining_settings _emset
-									USING ( empire_id )
-								INNER JOIN verse.planet_happiness _happ
-									USING ( planet_id )
-								INNER JOIN emp.scaled_mining_weights_view
-									USING ( planet_id , resource_name_id)
-								INNER JOIN emp.total_mining_weights_view
-									USING ( planet_id )
-								LEFT OUTER JOIN (
-											SELECT * FROM emp.planet_mining_settings
-												FOR SHARE
-										) AS _pmset
-									USING ( empire_id , planet_id , resource_name_id )
-	
-							WHERE _upd_sys.update_last = $1
-								AND _upd_sys.update_state = 'PROCESSING'
-
-							FOR SHARE OF _emp_planet , _emp , _emset , _happ 
-					) AS _owner
-				USING ( planet_id , resource_name_id )
-	
-		WHERE _upd_sys.update_last = $1
-			AND _upd_sys.update_state = 'PROCESSING'
-	
-		FOR UPDATE OF _resprov , _pres
-		FOR SHARE OF _planet ;
-$gu_pmc_get_data$ LANGUAGE SQL;
-
-
-REVOKE EXECUTE
-	ON FUNCTION sys.gu_pmc_get_data( BIGINT )
-	FROM PUBLIC;
-
-
-
-
-/*
- * Planet mining game update
- * --------------------------
- * 
- * Lock all records involved with the update, then update the quantity of
- * resources in resource providers depending on what was mined this turn.
- * Finally update all extraction quantities.
- * 
- * Obtains all records to update for the current batch, then either set the
- * income to 0 without modifying the resource provider if the planet is
- * neutral, or call gu_pmc_update_resource() if there is an owner.
- * 
- * Parameters:
- *		_tick		The current tick's identifier
- */
-DROP FUNCTION IF EXISTS sys.process_planet_mining_updates( BIGINT );
-CREATE FUNCTION sys.process_planet_mining_updates( _tick BIGINT )
-	RETURNS VOID
-	LANGUAGE SQL
-	STRICT VOLATILE
-	SECURITY INVOKER
-AS $process_planet_mining_updates$
-	-- Lock all rows
-	SELECT 1 FROM sys.gu_pmc_get_data( $1 );
-
-	-- Execute the actual mining
-	UPDATE verse.resource_providers _resprov
-		SET resprov_quantity = resprov_quantity - _pres.pres_income
-		FROM sys.updates _upd_sys
-			INNER JOIN verse.planets_updates _upd_verse
-				USING ( update_id , updtype_id , updtgt_id )
-			INNER JOIN verse.planet_resources _pres
-				ON _pres.planet_id = _upd_verse.name_id
-		WHERE _upd_sys.update_last = $1
-			AND _upd_sys.update_state = 'PROCESSING'
-			AND _pres.planet_id = _resprov.planet_id
-			AND _pres.resource_name_id = _resprov.resource_name_id;
-
-	-- Update extraction data
-	UPDATE verse.planet_resources
-		SET pres_income = emp.mining_compute_extraction( _update_row )
-		FROM sys.gu_pmc_get_data( $1 ) _update_row
-		WHERE planet_id = _update_row.planet
-			AND resource_name_id = _update_row.resource;
-
-$process_planet_mining_updates$;
-
-
-REVOKE EXECUTE
-	ON FUNCTION sys.process_planet_mining_updates( BIGINT )
-	FROM PUBLIC;
-
-SELECT sys.register_update_type( 'Planets' , 'PlanetMining' ,
-		'Resources are being extracted from mines.' ,
-		'process_planet_mining_updates'
-	);
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/admin/020-extensions/010-dblink.sql b/legacyworlds-server-data/db-structure/tests/admin/020-extensions/010-dblink.sql
deleted file mode 100644
index 24f8267..0000000
--- a/legacyworlds-server-data/db-structure/tests/admin/020-extensions/010-dblink.sql
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Test the presence and configuration of the dblink
- * extension
- */
-BEGIN;
-	SELECT plan( 6 );
-	
-	SELECT diag_test_name( 'dblink - dblink_connect() exists' );
-	SELECT has_function( 'dblink_connect' );
-
-	SELECT diag_test_name( 'dblink - Foreign data wrapper defined' );
-	SELECT is( p.proname , 'postgresql_fdw_validator' )
-		FROM pg_foreign_data_wrapper w
-			INNER JOIN pg_proc p ON w.fdwvalidator = p.oid
-		WHERE w.fdwname = 'pgsql';
-
-	SELECT diag_test_name( 'dblink - Foreign server defined' );
-	SELECT is ( w.fdwname , 'pgsql' )
-		FROM pg_foreign_server s
-			INNER JOIN pg_foreign_data_wrapper w
-				ON s.srvfdw = w.oid
-		WHERE s.srvname = 'srv_logging';
-
-	SELECT diag_test_name( 'dblink - Connection' );
-	SELECT lives_ok(
-		$$ SELECT dblink_connect( 'cn_logging' , 'srv_logging' ) $$
-	);
-	
-	SELECT diag_test_name( 'dblink - Remote user is not the administrator' );
-	SELECT isnt( username , current_user::TEXT )
-		FROM dblink( 'cn_logging' , 'SELECT current_user' )
-			AS ( username TEXT );
-
-	SELECT diag_test_name( 'dblink - Disconnection' );
-	SELECT lives_ok(
-		$$ SELECT dblink_disconnect( 'cn_logging' ) $$
-	);
-
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/admin/030-data/075-resources/010-resources.sql b/legacyworlds-server-data/db-structure/tests/admin/030-data/075-resources/010-resources.sql
deleted file mode 100644
index 216b857..0000000
--- a/legacyworlds-server-data/db-structure/tests/admin/030-data/075-resources/010-resources.sql
+++ /dev/null
@@ -1,225 +0,0 @@
-/*
- * Test constraints and foreign keys on defs.resources
- */
-BEGIN;
-	
-	/* We need a few strings to be used when creating resource definitions. */
-	\i utils/strings.sql
-	SELECT _create_test_strings( 6 );
-
-	/****** TESTS BEGIN HERE ******/
-	SELECT plan( 17 );
-
-	
-	/* Valid resource definition, no category */
-	SELECT diag_test_name( 'Valid resource definition without category' );
-	PREPARE _test_this AS
-		INSERT INTO defs.resources (
-			resource_name_id , resource_description_id , resource_weight
-		) VALUES (
-			_get_string( 'test1' ) , _get_string( 'test2' ) , 1
-		);
-	SELECT lives_ok( '_test_this' );
-	DEALLOCATE ALL;
-	DELETE FROM defs.resources;
-
-	/* Resource with valid fields, including a category */
-	SELECT diag_test_name( 'Valid resource definition with category' );
-	PREPARE _test_this AS
-		INSERT INTO defs.resources (
-			resource_name_id , resource_description_id ,
-			resource_category_id , resource_weight
-		) VALUES (
-			_get_string( 'test1' ) , _get_string( 'test2' ) ,
-			_get_string( 'test3' ) , 1
-		);
-	SELECT lives_ok( '_test_this' );
-	DEALLOCATE ALL;
-	DELETE FROM defs.resources;
-
-
-	/* Resource definition with an invalid name */
-	SELECT diag_test_name( 'Resource definition with an invalid name' );
-	PREPARE _test_this AS
-		INSERT INTO defs.resources (
-			resource_name_id , resource_description_id , resource_weight
-		) VALUES (
-			_get_bad_string( ) , _get_string( 'test2' ) , 1
-		);
-	SELECT throws_ok( '_test_this' , 23503 );
-	DEALLOCATE ALL;
-
-	/* Resource definition with a NULL name */
-	SELECT diag_test_name( 'Resource definition with a NULL name' );
-	PREPARE _test_this AS
-		INSERT INTO defs.resources (
-			resource_name_id , resource_description_id , resource_weight
-		) VALUES (
-			NULL , _get_string( 'test2' ) , 1
-		);
-	SELECT throws_ok( '_test_this' , 23502 );
-	DEALLOCATE ALL;
-
-
-	/* Resource definition with an invalid description */
-	SELECT diag_test_name( 'Resource definition with an invalid description' );
-	PREPARE _test_this AS
-		INSERT INTO defs.resources (
-			resource_name_id , resource_description_id , resource_weight
-		) VALUES (
-			_get_string( 'test1' ) , _get_bad_string( ) , 1
-		);
-	SELECT throws_ok( '_test_this' , 23503 );
-	DEALLOCATE ALL;
-
-	/* Resource definition with a NULL description */
-	SELECT diag_test_name( 'Resource definition with a NULL description' );
-	PREPARE _test_this AS
-		INSERT INTO defs.resources (
-			resource_name_id , resource_description_id , resource_weight
-		) VALUES (
-			_get_string( 'test1' ) , NULL , 1
-		);
-	SELECT throws_ok( '_test_this' , 23502 );
-	DEALLOCATE ALL;
-
-
-	/* Resource definition with an invalid category */
-	SELECT diag_test_name( 'Resource definition with an invalid category' );
-	PREPARE _test_this AS
-		INSERT INTO defs.resources (
-			resource_name_id , resource_description_id ,
-			resource_category_id , resource_weight
-		) VALUES (
-			_get_string( 'test1' ) , _get_string( 'test2' ) ,
-			_get_bad_string( ) , 1
-		);
-	SELECT throws_ok( '_test_this' , 23503 );
-	DEALLOCATE ALL;
-
-
-	/* Resource definition with an invalid weight */
-	SELECT diag_test_name( 'Resource definition with an invalid weight' );
-	PREPARE _test_this AS
-		INSERT INTO defs.resources (
-			resource_name_id , resource_description_id , resource_weight
-		) VALUES (
-			_get_string( 'test1' ) , _get_string( 'test2' ) , 0
-		);
-	SELECT throws_ok( '_test_this' , 23514 );
-	DEALLOCATE ALL;
-
-	/* Resource definition with a NULL weight */
-	SELECT diag_test_name( 'Resource definition with a NULL weight' );
-	PREPARE _test_this AS
-		INSERT INTO defs.resources (
-			resource_name_id , resource_description_id , resource_weight
-		) VALUES (
-			_get_string( 'test1' ) , _get_string( 'test2' ) , NULL
-		);
-	SELECT throws_ok( '_test_this' , 23502 );
-	DEALLOCATE ALL;
-
-
-	/* Resource definitions using the same name */
-	INSERT INTO defs.resources (
-		resource_name_id , resource_description_id , resource_weight
-	) VALUES (
-		_get_string( 'test1' ) , _get_string( 'test2' ) , 1
-	);
-	SELECT diag_test_name( 'Resource definitions using the same name' );
-	PREPARE _test_this AS
-		INSERT INTO defs.resources (
-			resource_name_id , resource_description_id , resource_weight
-		) VALUES (
-			_get_string( 'test1' ) , _get_string( 'test3' ) , 1
-		);
-	SELECT throws_ok( '_test_this' , 23505 );
-	DEALLOCATE ALL;
-
-	/* Resource definitions using the same description */
-	SELECT diag_test_name( 'Resource definitions using the same description' );
-	PREPARE _test_this AS
-		INSERT INTO defs.resources (
-			resource_name_id , resource_description_id , resource_weight
-		) VALUES (
-			_get_string( 'test3' ) , _get_string( 'test2' ) , 1
-		);
-	SELECT throws_ok( '_test_this' , 23505 );
-	DEALLOCATE ALL;
-
-	/* Resources with distinct names and descriptions */
-	SELECT diag_test_name( 'Resources with distinct names and descriptions' );
-	PREPARE _test_this AS
-		INSERT INTO defs.resources (
-			resource_name_id , resource_description_id , resource_weight
-		) VALUES (
-			_get_string( 'test3' ) , _get_string( 'test4' ) , 1
-		);
-	SELECT lives_ok( '_test_this' );
-	DEALLOCATE ALL;
-	DELETE FROM defs.resources;
-
-
-	/* Resources with distinct categories */
-	INSERT INTO defs.resources (
-		resource_name_id , resource_description_id ,
-		resource_category_id , resource_weight
-	) VALUES (
-		_get_string( 'test1' ) , _get_string( 'test2' ) ,
-		_get_string( 'test3' ) , 1
-	);
-	SELECT diag_test_name( 'Resources with distinct categories' );
-	PREPARE _test_this AS
-		INSERT INTO defs.resources (
-			resource_name_id , resource_description_id ,
-			resource_category_id , resource_weight
-		) VALUES (
-			_get_string( 'test4' ) , _get_string( 'test5' ) ,
-			_get_string( 'test6' ) , 1
-		);
-	SELECT lives_ok( '_test_this' );
-	DEALLOCATE ALL;
-	DELETE FROM defs.resources WHERE resource_name_id = _get_string( 'test4' );
-
-	/* Resources in the same category */
-	SELECT diag_test_name( 'Resources in the same category' );
-	PREPARE _test_this AS
-		INSERT INTO defs.resources (
-			resource_name_id , resource_description_id ,
-			resource_category_id , resource_weight
-		) VALUES (
-			_get_string( 'test4' ) , _get_string( 'test5' ) ,
-			_get_string( 'test3' ) , 1
-		);
-	SELECT lives_ok( '_test_this' );
-	DEALLOCATE ALL;
-
-
-	/* Resource definition name deletion impossible */
-	SELECT diag_test_name( 'Resource definition name deletion impossible' );
-	PREPARE _test_this AS
-		DELETE FROM defs.strings WHERE id = _get_string( 'test1' );
-	SELECT throws_ok( '_test_this' , 23503 );
-	DEALLOCATE ALL;
-
-	/* Resource definition description deletion impossible */
-	SELECT diag_test_name( 'Resource definition description deletion impossible' );
-	PREPARE _test_this AS
-		DELETE FROM defs.strings WHERE id = _get_string( 'test2' );
-	SELECT throws_ok( '_test_this' , 23503 );
-	DEALLOCATE ALL;
-
-	/*
-	 * 17/ Make sure it is impossible to delete a string definition used as
-	 *     a resource category
-	 */
-	SELECT diag_test_name( 'Resource definition description deletion impossible' );
-	PREPARE _test_this AS
-		DELETE FROM defs.strings WHERE id = _get_string( 'test3' );
-	SELECT throws_ok( '_test_this' , 23503 );
-	DEALLOCATE ALL;
-
-
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/admin/030-data/075-resources/020-natural-resources.sql b/legacyworlds-server-data/db-structure/tests/admin/030-data/075-resources/020-natural-resources.sql
deleted file mode 100644
index b38b69c..0000000
--- a/legacyworlds-server-data/db-structure/tests/admin/030-data/075-resources/020-natural-resources.sql
+++ /dev/null
@@ -1,474 +0,0 @@
-/*
- * Test constraints and foreign keys on defs.natural_resources
- */
-BEGIN;
-	
-	/* We need a few strings to be used when creating resource definitions. */
-	\i utils/strings.sql
-	SELECT _create_test_strings( 4 );
-	
-	/*
-	 * We need a a pair of resource definitions to be used when creating
-	 * natural resources.
-	 */
-	INSERT INTO defs.resources (
-		resource_name_id , resource_description_id , resource_weight
-	) VALUES ( _get_string( 'test1' ) , _get_string( 'test2' ) , 1 );
-	INSERT INTO defs.resources (
-		resource_name_id , resource_description_id , resource_weight
-	) VALUES ( _get_string( 'test3' ) , _get_string( 'test4' ) , 2 );
-
-	
-	/****** TESTS BEGIN HERE ******/
-	SELECT plan( 33 );
-
-
-	SELECT diag_test_name( 'Valid natural resource definition' );
-	PREPARE _test_this AS
-		INSERT INTO defs.natural_resources (
-			resource_name_id , natres_p_presence , natres_quantity_avg ,
-			natres_quantity_dev , natres_difficulty_avg ,
-			natres_difficulty_dev , natres_recovery_avg ,
-			natres_recovery_dev
-		) VALUES (
-			_get_string( 'test1' ) , 0.5 , 100 , 1 , 0.5 , 0.05 , 0.5 , 0.05
-		);
-	SELECT lives_ok( '_test_this' );
-
-	SELECT diag_test_name( 'Duplicate natural resource definition' );
-	SELECT throws_ok( '_test_this' , 23505 );
-	DEALLOCATE ALL;
-
-	SELECT diag_test_name( 'Distinct natural resource definitions' );
-	PREPARE _test_this AS
-		INSERT INTO defs.natural_resources (
-			resource_name_id , natres_p_presence , natres_quantity_avg ,
-			natres_quantity_dev , natres_difficulty_avg ,
-			natres_difficulty_dev , natres_recovery_avg ,
-			natres_recovery_dev
-		) VALUES (
-			_get_string( 'test3' ) , 0.5 , 100 , 1 , 0.5 , 0.05 , 0.5 , 0.05
-		);
-	SELECT lives_ok( '_test_this' );
-	DEALLOCATE ALL;
-	DELETE FROM defs.natural_resources;
-
-
-	SELECT diag_test_name( 'Natural resource definition with missing resource definition' );
-	PREPARE _test_this AS
-		INSERT INTO defs.natural_resources(
-			resource_name_id , natres_p_presence , natres_quantity_avg ,
-			natres_quantity_dev , natres_difficulty_avg ,
-			natres_difficulty_dev , natres_recovery_avg ,
-			natres_recovery_dev
-		) VALUES (
-			_get_string( 'test2' ) , 0.5 , 100 , 1 , 0.5 , 0.05 , 0.5 , 0.05
-		);
-	SELECT throws_ok( '_test_this' , 23503 );
-	DEALLOCATE ALL;
-
-	SELECT diag_test_name( 'Natural resource definition with NULL resource definition' );
-	PREPARE _test_this AS
-		INSERT INTO defs.natural_resources(
-			resource_name_id , natres_p_presence , natres_quantity_avg ,
-			natres_quantity_dev , natres_difficulty_avg ,
-			natres_difficulty_dev , natres_recovery_avg ,
-			natres_recovery_dev
-		) VALUES (
-			NULL , 0.5 , 100 , 1 , 0.5 , 0.05 , 0.5 , 0.05
-		);
-	SELECT throws_ok( '_test_this' , 23502 );
-	DEALLOCATE ALL;
-
-	
-	SELECT diag_test_name( 'Natural resource definition with presence probability <= 0' );
-	PREPARE _test_this AS
-		INSERT INTO defs.natural_resources(
-			resource_name_id , natres_p_presence , natres_quantity_avg ,
-			natres_quantity_dev , natres_difficulty_avg ,
-			natres_difficulty_dev , natres_recovery_avg ,
-			natres_recovery_dev
-		) VALUES (
-			_get_string( 'test1' ) , 0 , 100 , 1 , 0.5 , 0.05 , 0.5 , 0.05
-		);
-	SELECT throws_ok( '_test_this' , 23514 );
-	DEALLOCATE ALL;
-
-	SELECT diag_test_name( 'Natural resource definition with presence probability >= 1' );
-	PREPARE _test_this AS
-		INSERT INTO defs.natural_resources(
-			resource_name_id , natres_p_presence , natres_quantity_avg ,
-			natres_quantity_dev , natres_difficulty_avg ,
-			natres_difficulty_dev , natres_recovery_avg ,
-			natres_recovery_dev
-		) VALUES (
-			_get_string( 'test1' ) , 1 , 100 , 1 , 0.5 , 0.05 , 0.5 , 0.05
-		);
-	SELECT throws_ok( '_test_this' , 23514 );
-	DEALLOCATE ALL;
-
-	SELECT diag_test_name( 'Natural resource definition with NULL presence probability' );
-	PREPARE _test_this AS
-		INSERT INTO defs.natural_resources(
-			resource_name_id , natres_p_presence , natres_quantity_avg ,
-			natres_quantity_dev , natres_difficulty_avg ,
-			natres_difficulty_dev , natres_recovery_avg ,
-			natres_recovery_dev
-		) VALUES (
-			_get_string( 'test1' ) , NULL , 100 , 1 , 0.5 , 0.05 , 0.5 , 0.05
-		);
-	SELECT throws_ok( '_test_this' , 23502 );
-	DEALLOCATE ALL;
-
-
-	SELECT diag_test_name( 'Natural resource definition with avg. quantity <= 0' );
-	PREPARE _test_this AS
-		INSERT INTO defs.natural_resources(
-			resource_name_id , natres_p_presence , natres_quantity_avg ,
-			natres_quantity_dev , natres_difficulty_avg ,
-			natres_difficulty_dev , natres_recovery_avg ,
-			natres_recovery_dev
-		) VALUES (
-			_get_string( 'test1' ) , 0.5 , 0 , 1 , 0.5 , 0.05 , 0.5 , 0.05
-		);
-	SELECT throws_ok( '_test_this' , 23514 );
-	DEALLOCATE ALL;
-
-	SELECT diag_test_name( 'Natural resource definition with NULL avg. quantity' );
-	PREPARE _test_this AS
-		INSERT INTO defs.natural_resources(
-			resource_name_id , natres_p_presence , natres_quantity_avg ,
-			natres_quantity_dev , natres_difficulty_avg ,
-			natres_difficulty_dev , natres_recovery_avg ,
-			natres_recovery_dev
-		) VALUES (
-			_get_string( 'test1' ) , 0.5 , NULL , 1 , 0.5 , 0.05 , 0.5 , 0.05
-		);
-	SELECT throws_ok( '_test_this' , 23502 );
-	DEALLOCATE ALL;
-
-
-
-	SELECT diag_test_name( 'Natural resource definition with quantity dev. < 0' );
-	PREPARE _test_this AS
-		INSERT INTO defs.natural_resources(
-			resource_name_id , natres_p_presence , natres_quantity_avg ,
-			natres_quantity_dev , natres_difficulty_avg ,
-			natres_difficulty_dev , natres_recovery_avg ,
-			natres_recovery_dev
-		) VALUES (
-			_get_string( 'test1' ) , 0.5 , 100 , -1 , 0.5 , 0.05 , 0.5 , 0.05
-		);
-	SELECT throws_ok( '_test_this' , 23514 );
-	DEALLOCATE ALL;
-
-	SELECT diag_test_name( 'Natural resource definition with NULL quantity dev.' );
-	PREPARE _test_this AS
-		INSERT INTO defs.natural_resources(
-			resource_name_id , natres_p_presence , natres_quantity_avg ,
-			natres_quantity_dev , natres_difficulty_avg ,
-			natres_difficulty_dev , natres_recovery_avg ,
-			natres_recovery_dev
-		) VALUES (
-			_get_string( 'test1' ) , 0.5 , 100 , NULL , 0.5 , 0.05 , 0.5 , 0.05
-		);
-	SELECT throws_ok( '_test_this' , 23502 );
-	DEALLOCATE ALL;
-
-	SELECT diag_test_name( 'Natural resource definition with quantity dev. = avg. quantity' );
-	PREPARE _test_this AS
-		INSERT INTO defs.natural_resources(
-			resource_name_id , natres_p_presence , natres_quantity_avg ,
-			natres_quantity_dev , natres_difficulty_avg ,
-			natres_difficulty_dev , natres_recovery_avg ,
-			natres_recovery_dev
-		) VALUES (
-			_get_string( 'test1' ) , 0.5 , 100 , 100 , 0.5 , 0.05 , 0.5 , 0.05
-		);
-	SELECT throws_ok( '_test_this' , 23514 );
-	DEALLOCATE ALL;
-
-	SELECT diag_test_name( 'Natural resource definition with quantity dev. = 0' );
-	PREPARE _test_this AS
-		INSERT INTO defs.natural_resources(
-			resource_name_id , natres_p_presence , natres_quantity_avg ,
-			natres_quantity_dev , natres_difficulty_avg ,
-			natres_difficulty_dev , natres_recovery_avg ,
-			natres_recovery_dev
-		) VALUES (
-			_get_string( 'test1' ) , 0.5 , 100 , 0 , 0.5 , 0.05 , 0.5 , 0.05
-		);
-	SELECT lives_ok( '_test_this' );
-	DEALLOCATE ALL;
-	DELETE FROM defs.natural_resources;
-
-
-
-	SELECT diag_test_name( 'Natural resource definition with avg. difficulty = 1' );
-	PREPARE _test_this AS
-		INSERT INTO defs.natural_resources(
-			resource_name_id , natres_p_presence , natres_quantity_avg ,
-			natres_quantity_dev , natres_difficulty_avg ,
-			natres_difficulty_dev , natres_recovery_avg ,
-			natres_recovery_dev
-		) VALUES (
-			_get_string( 'test1' ) , 0.5 , 100 , 1 , 1 , 0 , 0.5 , 0.05
-		);
-	SELECT lives_ok( '_test_this' );
-	DEALLOCATE ALL;
-	DELETE FROM defs.natural_resources;
-
-	SELECT diag_test_name( 'Natural resource definition with avg. difficulty = 0' );
-	PREPARE _test_this AS
-		INSERT INTO defs.natural_resources(
-			resource_name_id , natres_p_presence , natres_quantity_avg ,
-			natres_quantity_dev , natres_difficulty_avg ,
-			natres_difficulty_dev , natres_recovery_avg ,
-			natres_recovery_dev
-		) VALUES (
-			_get_string( 'test1' ) , 0.5 , 100 , 1 , 0 , 0 , 0.5 , 0.05
-		);
-	SELECT lives_ok( '_test_this' );
-	DEALLOCATE ALL;
-	DELETE FROM defs.natural_resources;
-
-	SELECT diag_test_name( 'Natural resource definition with avg. difficulty > 1' );
-	PREPARE _test_this AS
-		INSERT INTO defs.natural_resources(
-			resource_name_id , natres_p_presence , natres_quantity_avg ,
-			natres_quantity_dev , natres_difficulty_avg ,
-			natres_difficulty_dev , natres_recovery_avg ,
-			natres_recovery_dev
-		) VALUES (
-			_get_string( 'test1' ) , 0.5 , 100 , 1 , 1.0001 , 0 , 0.5 , 0.05
-		);
-	SELECT throws_ok( '_test_this' , 23514 );
-	DEALLOCATE ALL;
-
-
-	SELECT diag_test_name( 'Natural resource definition with avg. difficulty < 0' );
-	PREPARE _test_this AS
-		INSERT INTO defs.natural_resources(
-			resource_name_id , natres_p_presence , natres_quantity_avg ,
-			natres_quantity_dev , natres_difficulty_avg ,
-			natres_difficulty_dev , natres_recovery_avg ,
-			natres_recovery_dev
-		) VALUES (
-			_get_string( 'test1' ) , 0.5 , 100 , 1 , -0.0001 , 0 , 0.5 , 0.05
-		);
-	SELECT throws_ok( '_test_this' , 23514 );
-	DEALLOCATE ALL;
-
-	SELECT diag_test_name( 'Natural resource definition with NULL avg. difficulty' );
-	PREPARE _test_this AS
-		INSERT INTO defs.natural_resources(
-			resource_name_id , natres_p_presence , natres_quantity_avg ,
-			natres_quantity_dev , natres_difficulty_avg ,
-			natres_difficulty_dev , natres_recovery_avg ,
-			natres_recovery_dev
-		) VALUES (
-			_get_string( 'test1' ) , 0.5 , 100 , 1 , NULL , 0.05 , 0.5 , 0.05
-		);
-	SELECT throws_ok( '_test_this' , 23502 );
-	DEALLOCATE ALL;
-
-
-
-	SELECT diag_test_name( 'Natural resource definition with difficulty dev. < 0' );
-	PREPARE _test_this AS
-		INSERT INTO defs.natural_resources(
-			resource_name_id , natres_p_presence , natres_quantity_avg ,
-			natres_quantity_dev , natres_difficulty_avg ,
-			natres_difficulty_dev , natres_recovery_avg ,
-			natres_recovery_dev
-		) VALUES (
-			_get_string( 'test1' ) , 0.5 , 100 , 1 , 0.5 , -1 , 0.5 , 0.05
-		);
-	SELECT throws_ok( '_test_this' , 23514 );
-	DEALLOCATE ALL;
-
-	SELECT diag_test_name( 'Natural resource definition with avg. difficulty - difficulty dev. < 0' );
-	PREPARE _test_this AS
-		INSERT INTO defs.natural_resources(
-			resource_name_id , natres_p_presence , natres_quantity_avg ,
-			natres_quantity_dev , natres_difficulty_avg ,
-			natres_difficulty_dev , natres_recovery_avg ,
-			natres_recovery_dev
-		) VALUES (
-			_get_string( 'test1' ) , 0.5 , 100 , 1 , 0.25 , 0.5 , 0.5 , 0.05
-		);
-	SELECT throws_ok( '_test_this' , 23514 );
-	DEALLOCATE ALL;
-
-	SELECT diag_test_name( 'Natural resource definition with difficulty dev. + avg. difficulty > 1' );
-	PREPARE _test_this AS
-		INSERT INTO defs.natural_resources(
-			resource_name_id , natres_p_presence , natres_quantity_avg ,
-			natres_quantity_dev , natres_difficulty_avg ,
-			natres_difficulty_dev , natres_recovery_avg ,
-			natres_recovery_dev
-		) VALUES (
-			_get_string( 'test1' ) , 0.5 , 100 , 1 , 0.75 , 0.5 , 0.5 , 0.05
-		);
-	SELECT throws_ok( '_test_this' , 23514 );
-	DEALLOCATE ALL;
-
-	SELECT diag_test_name( 'Natural resource definition with NULL difficulty dev.' );
-	PREPARE _test_this AS
-		INSERT INTO defs.natural_resources(
-			resource_name_id , natres_p_presence , natres_quantity_avg ,
-			natres_quantity_dev , natres_difficulty_avg ,
-			natres_difficulty_dev , natres_recovery_avg ,
-			natres_recovery_dev
-		) VALUES (
-			_get_string( 'test1' ) , 0.5 , 100 , 1 , 0.5 , NULL , 0.5 , 0.05
-		);
-	SELECT throws_ok( '_test_this' , 23502 );
-	DEALLOCATE ALL;
-
-
-	SELECT diag_test_name( 'Natural resource definition with avg. recovery = 1' );
-	PREPARE _test_this AS
-		INSERT INTO defs.natural_resources(
-			resource_name_id , natres_p_presence , natres_quantity_avg ,
-			natres_quantity_dev , natres_difficulty_avg ,
-			natres_difficulty_dev , natres_recovery_avg ,
-			natres_recovery_dev
-		) VALUES (
-			_get_string( 'test1' ) , 0.5 , 100 , 1 , 0.5 , 0.05 ,
-			1 , 0
-		);
-	SELECT lives_ok( '_test_this' );
-	DEALLOCATE ALL;
-	DELETE FROM defs.natural_resources;
-
-	SELECT diag_test_name( 'Natural resource definition with avg. recovery = 0+' );
-	PREPARE _test_this AS
-		INSERT INTO defs.natural_resources(
-			resource_name_id , natres_p_presence , natres_quantity_avg ,
-			natres_quantity_dev , natres_difficulty_avg ,
-			natres_difficulty_dev , natres_recovery_avg ,
-			natres_recovery_dev
-		) VALUES (
-			_get_string( 'test1' ) , 0.5 , 100 , 1 , 0.5 , 0.05 ,
-			0.0001 , 0
-		);
-	SELECT lives_ok( '_test_this' );
-	DEALLOCATE ALL;
-	DELETE FROM defs.natural_resources;
-
-	SELECT diag_test_name( 'Natural resource definition with avg. recovery > 1' );
-	PREPARE _test_this AS
-		INSERT INTO defs.natural_resources(
-			resource_name_id , natres_p_presence , natres_quantity_avg ,
-			natres_quantity_dev , natres_difficulty_avg ,
-			natres_difficulty_dev , natres_recovery_avg ,
-			natres_recovery_dev
-		) VALUES (
-			_get_string( 'test1' ) , 0.5 , 100 , 1 , 0.5 , 0.05 ,
-			1.1 , 0
-		);
-	SELECT throws_ok( '_test_this' , 23514 );
-	DEALLOCATE ALL;
-
-	SELECT diag_test_name( 'Natural resource definition with avg. recovery <= 0' );
-	PREPARE _test_this AS
-		INSERT INTO defs.natural_resources(
-			resource_name_id , natres_p_presence , natres_quantity_avg ,
-			natres_quantity_dev , natres_difficulty_avg ,
-			natres_difficulty_dev , natres_recovery_avg ,
-			natres_recovery_dev
-		) VALUES (
-			_get_string( 'test1' ) , 0.5 , 100 , 1 , 0.5 , 0.05 ,
-			0 , 0
-		);
-	SELECT throws_ok( '_test_this' , 23514 );
-	DEALLOCATE ALL;
-
-	SELECT diag_test_name( 'Natural resource definition with NULL avg. recovery' );
-	PREPARE _test_this AS
-		INSERT INTO defs.natural_resources(
-			resource_name_id , natres_p_presence , natres_quantity_avg ,
-			natres_quantity_dev , natres_difficulty_avg ,
-			natres_difficulty_dev , natres_recovery_avg ,
-			natres_recovery_dev
-		) VALUES (
-			_get_string( 'test1' ) , 0.5 , 100 , 1 , 0.5 , 0.05 ,
-			NULL , 0.05
-		);
-	SELECT throws_ok( '_test_this' , 23502 );
-	DEALLOCATE ALL;
-
-
-	SELECT diag_test_name( 'Natural resource definition with recovery dev. < 0' );
-	PREPARE _test_this AS
-		INSERT INTO defs.natural_resources(
-			resource_name_id , natres_p_presence , natres_quantity_avg ,
-			natres_quantity_dev , natres_difficulty_avg ,
-			natres_difficulty_dev , natres_recovery_avg ,
-			natres_recovery_dev
-		) VALUES (
-			_get_string( 'test1' ) , 0.5 , 100 , 1 , 0.5 , 0.05 ,
-			0.5 , -1
-		);
-	SELECT throws_ok( '_test_this' , 23514 );
-	DEALLOCATE ALL;
-
-	SELECT diag_test_name( 'Natural resource definition with avg.recovery - recovery dev. <= 0' );
-	PREPARE _test_this AS
-		INSERT INTO defs.natural_resources(
-			resource_name_id , natres_p_presence , natres_quantity_avg ,
-			natres_quantity_dev , natres_difficulty_avg ,
-			natres_difficulty_dev , natres_recovery_avg ,
-			natres_recovery_dev
-		) VALUES (
-			_get_string( 'test1' ) , 0.5 , 100 , 1 , 0.5 , 0.05 ,
-			0.5 , 0.5
-		);
-	SELECT throws_ok( '_test_this' , 23514 );
-	DEALLOCATE ALL;
-
-	SELECT diag_test_name( 'Natural resource definition with avg.recovery - recovery dev. > 1' );
-	PREPARE _test_this AS
-		INSERT INTO defs.natural_resources(
-			resource_name_id , natres_p_presence , natres_quantity_avg ,
-			natres_quantity_dev , natres_difficulty_avg ,
-			natres_difficulty_dev , natres_recovery_avg ,
-			natres_recovery_dev
-		) VALUES (
-			_get_string( 'test1' ) , 0.5 , 100 , 1 , 0.5 , 0.05 ,
-			0.75 , 0.5
-		);
-	SELECT throws_ok( '_test_this' , 23514 );
-	DEALLOCATE ALL;
-
-	SELECT diag_test_name( 'Natural resource definition with NULL recovery dev.' );
-	PREPARE _test_this AS
-		INSERT INTO defs.natural_resources(
-			resource_name_id , natres_p_presence , natres_quantity_avg ,
-			natres_quantity_dev , natres_difficulty_avg ,
-			natres_difficulty_dev , natres_recovery_avg ,
-			natres_recovery_dev
-		) VALUES (
-			_get_string( 'test1' ) , 0.5 , 100 , 1 , 0.5 , 0.05 ,
-			0.5 , NULL
-		);
-	SELECT throws_ok( '_test_this' , 23502 );
-	DEALLOCATE ALL;
-
-
-	SELECT diag_test_name( 'Deletion of the base definition for a natural resource' );
-	INSERT INTO defs.natural_resources(
-		resource_name_id , natres_p_presence , natres_quantity_avg ,
-		natres_quantity_dev , natres_difficulty_avg ,
-		natres_difficulty_dev , natres_recovery_avg ,
-		natres_recovery_dev
-	) VALUES (
-		_get_string( 'test1' ) , 0.5 , 100 , 1 , 0.5 , 0.05 , 0.5 , 0.05
-	);
-	PREPARE _test_this AS
-		DELETE FROM defs.resources WHERE resource_name_id = _get_string( 'test1' );
-	SELECT throws_ok( '_test_this' , 23503 );
-
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/admin/030-data/100-universe/010-resource-providers.sql b/legacyworlds-server-data/db-structure/tests/admin/030-data/100-universe/010-resource-providers.sql
deleted file mode 100644
index 9e31d1d..0000000
--- a/legacyworlds-server-data/db-structure/tests/admin/030-data/100-universe/010-resource-providers.sql
+++ /dev/null
@@ -1,331 +0,0 @@
-/*
- * Test constraints and foreign keys on verse.resource_providers
- */
-BEGIN;
-	
-	/* We need a pair of resource definitions and a pair of planets. */
-	\i utils/strings.sql
-	\i utils/resources.sql
-	\i utils/accounts.sql
-	\i utils/naming.sql
-	\i utils/universe.sql
-	SELECT _create_natural_resources( 2 , 'testResource' );
-	SELECT _create_raw_planets( 2 , 'testPlanet' );
-	
-	
-	/****** TESTS BEGIN HERE ******/
-	SELECT plan( 22 );
-
-	
-	SELECT diag_test_name( 'Valid resource provider' );
-	PREPARE _test_this AS
-		INSERT INTO verse.resource_providers(
-				planet_id , resource_name_id ,
-				resprov_quantity_max , resprov_quantity ,
-				resprov_difficulty , resprov_recovery
-		) VALUES (
-			_get_map_name( 'testPlanet1' ) , _get_string( 'testResource1' ) ,
-			100 , 50 ,
-			0.5 , 0.5
-		);
-	SELECT lives_ok( '_test_this' );
-
-	SELECT diag_test_name( 'Duplicate resource provider' );
-	SELECT throws_ok( '_test_this' , 23505 );
-	DEALLOCATE ALL;
-
-	SELECT diag_test_name( 'Resource provider with same planet but different type' );
-	PREPARE _test_this AS
-		INSERT INTO verse.resource_providers(
-				planet_id , resource_name_id ,
-				resprov_quantity_max , resprov_quantity ,
-				resprov_difficulty , resprov_recovery
-		) VALUES (
-			_get_map_name( 'testPlanet1' ) , _get_string( 'testResource2' ) ,
-			100 , 50 ,
-			0.5 , 0.5
-		);
-	SELECT lives_ok( '_test_this' );
-	DEALLOCATE ALL;
-
-	SELECT diag_test_name( 'Resource provider with same type but different planet' );
-	PREPARE _test_this AS
-		INSERT INTO verse.resource_providers(
-				planet_id , resource_name_id ,
-				resprov_quantity_max , resprov_quantity ,
-				resprov_difficulty , resprov_recovery
-		) VALUES (
-			_get_map_name( 'testPlanet2' ) , _get_string( 'testResource1' ) ,
-			100 , 50 ,
-			0.5 , 0.5
-		);
-	SELECT lives_ok( '_test_this' );
-	DEALLOCATE ALL;
-	DELETE FROM verse.resource_providers;
-
-
-	SELECT diag_test_name( 'Resource provider with NULL planet identifier' );
-	PREPARE _test_this AS
-		INSERT INTO verse.resource_providers(
-				planet_id , resource_name_id ,
-				resprov_quantity_max , resprov_quantity ,
-				resprov_difficulty , resprov_recovery
-		) VALUES (
-			NULL , _get_string( 'testResource1' ) ,
-			100 , 50 ,
-			0.5 , 0.5
-		);
-	SELECT throws_ok( '_test_this' , 23502 );
-	DEALLOCATE ALL;
-	
-	SELECT diag_test_name( 'Resource provider with invalid planet identifier' );
-	PREPARE _test_this AS
-		INSERT INTO verse.resource_providers(
-				planet_id , resource_name_id ,
-				resprov_quantity_max , resprov_quantity ,
-				resprov_difficulty , resprov_recovery
-		) VALUES (
-			_get_bad_map_name( ) , _get_string( 'testResource1' ) ,
-			100 , 50 ,
-			0.5 , 0.5
-		);
-	SELECT throws_ok( '_test_this' , 23503 );
-	DEALLOCATE ALL;
-
-	
-	SELECT diag_test_name( 'Resource provider with NULL resource identifier' );
-	PREPARE _test_this AS
-		INSERT INTO verse.resource_providers(
-				planet_id , resource_name_id ,
-				resprov_quantity_max , resprov_quantity ,
-				resprov_difficulty , resprov_recovery
-
-		) VALUES (
-			_get_map_name( 'testPlanet1' ) , NULL ,
-			100 , 50 ,
-			0.5 , 0.5
-		);
-	SELECT throws_ok( '_test_this' , 23502 );
-	DEALLOCATE ALL;
-	
-	SELECT diag_test_name( 'Resource provider with invalid resource identifier' );
-	PREPARE _test_this AS
-		INSERT INTO verse.resource_providers(
-				planet_id , resource_name_id ,
-				resprov_quantity_max , resprov_quantity ,
-				resprov_difficulty , resprov_recovery
-		) VALUES (
-			_get_map_name( 'testPlanet1' ) , _get_bad_string( ) ,
-			100 , 50 ,
-			0.5 , 0.5
-		);
-	SELECT throws_ok( '_test_this' , 23503 );
-	DEALLOCATE ALL;
-
-
-	SELECT diag_test_name( 'Resource provider with NULL maximal quantity' );
-	PREPARE _test_this AS
-		INSERT INTO verse.resource_providers(
-				planet_id , resource_name_id ,
-				resprov_quantity_max , resprov_quantity ,
-				resprov_difficulty , resprov_recovery
-
-		) VALUES (
-			_get_map_name( 'testPlanet1' ) , _get_string( 'testResource1' ) ,
-			NULL , 50 ,
-			0.5 , 0.5
-		);
-	SELECT throws_ok( '_test_this' , 23502 );
-	DEALLOCATE ALL;
-
-	SELECT diag_test_name( 'Resource provider with maximal quantity <= 0' );
-	PREPARE _test_this AS
-		INSERT INTO verse.resource_providers(
-				planet_id , resource_name_id ,
-				resprov_quantity_max , resprov_quantity ,
-				resprov_difficulty , resprov_recovery
-		) VALUES (
-			_get_map_name( 'testPlanet1' ) , _get_string( 'testResource1' ) ,
-			0 , 0 ,
-			0.5 , 0.5
-		);
-	SELECT throws_ok( '_test_this' , 23514 );
-	DEALLOCATE ALL;
-
-
-	SELECT diag_test_name( 'Resource provider with NULL quantity' );
-	PREPARE _test_this AS
-		INSERT INTO verse.resource_providers(
-				planet_id , resource_name_id ,
-				resprov_quantity_max , resprov_quantity ,
-				resprov_difficulty , resprov_recovery
-		) VALUES (
-			_get_map_name( 'testPlanet1' ) , _get_string( 'testResource1' ) ,
-			100 , NULL ,
-			0.5 , 0.5
-		);
-	SELECT throws_ok( '_test_this' , 23502 );
-	DEALLOCATE ALL;
-
-	SELECT diag_test_name( 'Resource provider with quantity < 0' );
-	PREPARE _test_this AS
-		INSERT INTO verse.resource_providers(
-				planet_id , resource_name_id ,
-				resprov_quantity_max , resprov_quantity ,
-				resprov_difficulty , resprov_recovery
-		) VALUES (
-			_get_map_name( 'testPlanet1' ) , _get_string( 'testResource1' ) ,
-			100 , -1 ,
-			0.5 , 0.5
-		);
-	SELECT throws_ok( '_test_this' , 23514 );
-	DEALLOCATE ALL;
-
-	SELECT diag_test_name( 'Resource provider with quantity > max. quantity' );
-	PREPARE _test_this AS
-		INSERT INTO verse.resource_providers(
-				planet_id , resource_name_id ,
-				resprov_quantity_max , resprov_quantity ,
-				resprov_difficulty , resprov_recovery
-		) VALUES (
-			_get_map_name( 'testPlanet1' ) , _get_string( 'testResource1' ) ,
-			100 , 101 ,
-			0.5 , 0.5
-		);
-	SELECT throws_ok( '_test_this' , 23514 );
-	DEALLOCATE ALL;
-
-
-	SELECT diag_test_name( 'Resource provider with NULL difficulty' );
-	PREPARE _test_this AS
-		INSERT INTO verse.resource_providers(
-				planet_id , resource_name_id ,
-				resprov_quantity_max , resprov_quantity ,
-				resprov_difficulty , resprov_recovery
-		) VALUES (
-			_get_map_name( 'testPlanet1' ) , _get_string( 'testResource1' ) ,
-			100 , 50 ,
-			NULL , 0.5
-		);
-	SELECT throws_ok( '_test_this' , 23502 );
-	DEALLOCATE ALL;
-
-	SELECT diag_test_name( 'Resource provider with difficulty < 0' );
-	PREPARE _test_this AS
-		INSERT INTO verse.resource_providers(
-				planet_id , resource_name_id ,
-				resprov_quantity_max , resprov_quantity ,
-				resprov_difficulty , resprov_recovery
-		) VALUES (
-			_get_map_name( 'testPlanet1' ) , _get_string( 'testResource1' ) ,
-			100 , 50 ,
-			-0.5 , 0.5
-		);
-	SELECT throws_ok( '_test_this' , 23514 );
-	DEALLOCATE ALL;
-
-	SELECT diag_test_name( 'Resource provider with difficulty > 1' );
-	PREPARE _test_this AS
-		INSERT INTO verse.resource_providers(
-				planet_id , resource_name_id ,
-				resprov_quantity_max , resprov_quantity ,
-				resprov_difficulty , resprov_recovery
-		) VALUES (
-			_get_map_name( 'testPlanet1' ) , _get_string( 'testResource1' ) ,
-			100 , 50 ,
-			1.5 , 0.5
-		);
-	SELECT throws_ok( '_test_this' , 23514 );
-	DEALLOCATE ALL;
-	
-	SELECT diag_test_name( 'Resource provider with difficulty = 0' );
-	PREPARE _test_this AS
-		INSERT INTO verse.resource_providers(
-				planet_id , resource_name_id ,
-				resprov_quantity_max , resprov_quantity ,
-				resprov_difficulty , resprov_recovery
-		) VALUES (
-			_get_map_name( 'testPlanet1' ) , _get_string( 'testResource1' ) ,
-			100 , 50 ,
-			0 , 0.5
-		);
-	SELECT lives_ok( '_test_this' );
-	DEALLOCATE ALL;
-	DELETE FROM verse.resource_providers;
-
-	SELECT diag_test_name( 'Resource provider with difficulty = 1' );
-	PREPARE _test_this AS
-		INSERT INTO verse.resource_providers(
-				planet_id , resource_name_id ,
-				resprov_quantity_max , resprov_quantity ,
-				resprov_difficulty , resprov_recovery
-		) VALUES (
-			_get_map_name( 'testPlanet1' ) , _get_string( 'testResource1' ) ,
-			100 , 50 ,
-			1 , 0.5
-		);
-	SELECT lives_ok( '_test_this' );
-	DEALLOCATE ALL;
-	DELETE FROM verse.resource_providers;
-
-
-	SELECT diag_test_name( 'Resource provider with NULL recovery' );
-	PREPARE _test_this AS
-		INSERT INTO verse.resource_providers(
-				planet_id , resource_name_id ,
-				resprov_quantity_max , resprov_quantity ,
-				resprov_difficulty , resprov_recovery
-		) VALUES (
-			_get_map_name( 'testPlanet1' ) , _get_string( 'testResource1' ) ,
-			100 , 50 ,
-			0.5 , NULL
-		);
-	SELECT throws_ok( '_test_this' , 23502 );
-	DEALLOCATE ALL;
-
-	SELECT diag_test_name( 'Resource provider with recovery = 0' );
-	PREPARE _test_this AS
-		INSERT INTO verse.resource_providers(
-				planet_id , resource_name_id ,
-				resprov_quantity_max , resprov_quantity ,
-				resprov_difficulty , resprov_recovery
-		) VALUES (
-			_get_map_name( 'testPlanet1' ) , _get_string( 'testResource1' ) ,
-			100 , 50 ,
-			0.5 , 0
-		);
-	SELECT throws_ok( '_test_this' , 23514 );
-	DEALLOCATE ALL;
-
-	SELECT diag_test_name( 'Resource provider with recovery > 1' );
-	PREPARE _test_this AS
-		INSERT INTO verse.resource_providers(
-				planet_id , resource_name_id ,
-				resprov_quantity_max , resprov_quantity ,
-				resprov_difficulty , resprov_recovery
-		) VALUES (
-			_get_map_name( 'testPlanet1' ) , _get_string( 'testResource1' ) ,
-			100 , 50 ,
-			0.5 , 1.5
-		);
-	SELECT throws_ok( '_test_this' , 23514 );
-	DEALLOCATE ALL;
-
-	SELECT diag_test_name( 'Resource provider with recovery = 1' );
-	PREPARE _test_this AS
-		INSERT INTO verse.resource_providers(
-				planet_id , resource_name_id ,
-				resprov_quantity_max , resprov_quantity ,
-				resprov_difficulty , resprov_recovery
-		) VALUES (
-			_get_map_name( 'testPlanet1' ) , _get_string( 'testResource1' ) ,
-			100 , 50 ,
-			0.5 , 1
-		);
-	SELECT lives_ok( '_test_this' );
-	DEALLOCATE ALL;
-	DELETE FROM verse.resource_providers;
-
-
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/admin/030-data/100-universe/020-planet-resources.sql b/legacyworlds-server-data/db-structure/tests/admin/030-data/100-universe/020-planet-resources.sql
deleted file mode 100644
index e20ba17..0000000
--- a/legacyworlds-server-data/db-structure/tests/admin/030-data/100-universe/020-planet-resources.sql
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * Test constraints and foreign keys on verse.planet_resources
- */
-BEGIN;
-	/* We need a pair of resource definitions and a pair of planets. */
-	\i utils/strings.sql
-	\i utils/resources.sql
-	\i utils/accounts.sql
-	\i utils/naming.sql
-	\i utils/universe.sql
-	SELECT _create_natural_resources( 2 , 'testResource' );
-	SELECT _create_raw_planets( 2 , 'testPlanet' );
-
-	/****** TESTS BEGIN HERE ******/
-	SELECT plan( 16 );
-	
-	SELECT diag_test_name( 'verse.planet_resources - Valid record' );
-	SELECT lives_ok( $$
-		INSERT INTO verse.planet_resources(
-			planet_id , resource_name_id , pres_income , pres_upkeep
-		) VALUES (
-			_get_map_name( 'testPlanet1' ) , _get_string( 'testResource1' ) ,
-			0 , 0
-		); $$
-	);
-	DELETE FROM verse.planet_resources;
-
-	SELECT diag_test_name( 'verse.planet_resources - Inserting with default values' );
-	SELECT lives_ok( $$
-		INSERT INTO verse.planet_resources(
-			planet_id , resource_name_id
-		) VALUES (
-			_get_map_name( 'testPlanet1' ) , _get_string( 'testResource1' )
-		); $$
-	);
-	SELECT diag_test_name( 'verse.planet_resources - Default income = 0' );
-	SELECT is( pres_income , 0::DOUBLE PRECISION )
-		FROM verse.planet_resources;
-	SELECT diag_test_name( 'verse.planet_resources - Default upkeep = 0' );
-	SELECT is( pres_upkeep , 0::DOUBLE PRECISION )
-		FROM verse.planet_resources;
-	
-	SELECT diag_test_name( 'verse.planet_resources - Duplicate record' );
-	SELECT throws_ok($$
-		INSERT INTO verse.planet_resources(
-			planet_id , resource_name_id
-		) VALUES (
-			_get_map_name( 'testPlanet1' ) , _get_string( 'testResource1' )
-		); $$ , 23505 );
-	
-	SELECT diag_test_name( 'verse.planet_resources - Different planet, same resource' );
-	SELECT lives_ok( $$
-		INSERT INTO verse.planet_resources(
-			planet_id , resource_name_id
-		) VALUES (
-			_get_map_name( 'testPlanet2' ) , _get_string( 'testResource1' )
-		); $$
-	);
-	
-	SELECT diag_test_name( 'verse.planet_resources - Different resource, same planet' );
-	SELECT lives_ok( $$
-		INSERT INTO verse.planet_resources(
-			planet_id , resource_name_id
-		) VALUES (
-			_get_map_name( 'testPlanet1' ) , _get_string( 'testResource2' )
-		); $$
-	);
-
-	SELECT diag_test_name( 'verse.planet_resources - Different planet and resource' );
-	SELECT lives_ok( $$
-		INSERT INTO verse.planet_resources(
-			planet_id , resource_name_id
-		) VALUES (
-			_get_map_name( 'testPlanet2' ) , _get_string( 'testResource2' )
-		); $$
-	);
-	DELETE FROM verse.planet_resources;
-
-	SELECT diag_test_name( 'verse.planet_resources - NULL planet identifier' );
-	SELECT throws_ok( $$
-		INSERT INTO verse.planet_resources(
-			planet_id , resource_name_id
-		) VALUES (
-			NULL , _get_string( 'testResource1' )
-		); $$ , 23502
-	);
-
-	SELECT diag_test_name( 'verse.planet_resources - NULL resource identifier' );
-	SELECT throws_ok( $$
-		INSERT INTO verse.planet_resources(
-			planet_id , resource_name_id
-		) VALUES (
-			_get_map_name( 'testPlanet1' ) , NULL
-		); $$ , 23502
-	);
-
-	SELECT diag_test_name( 'verse.planet_resources - NULL income' );
-	SELECT throws_ok( $$
-		INSERT INTO verse.planet_resources(
-			planet_id , resource_name_id , pres_income
-		) VALUES (
-			_get_map_name( 'testPlanet1' ) , _get_string( 'testResource1' ) ,
-			NULL
-		); $$ , 23502
-	);
-
-	SELECT diag_test_name( 'verse.planet_resources - NULL upkeep' );
-	SELECT throws_ok( $$
-		INSERT INTO verse.planet_resources(
-			planet_id , resource_name_id , pres_upkeep
-		) VALUES (
-			_get_map_name( 'testPlanet1' ) , _get_string( 'testResource1' ) ,
-			NULL
-		); $$ , 23502
-	);
-
-	SELECT diag_test_name( 'verse.planet_resources - Invalid planet identifier' );
-	SELECT throws_ok( $$
-		INSERT INTO verse.planet_resources(
-			planet_id , resource_name_id
-		) VALUES (
-			_get_bad_map_name( ) , _get_string( 'testResource1' )
-		); $$ , 23503
-	);
-
-	SELECT diag_test_name( 'verse.planet_resources - Invalid resource identifier' );
-	SELECT throws_ok( $$
-		INSERT INTO verse.planet_resources(
-			planet_id , resource_name_id
-		) VALUES (
-			_get_map_name( 'testPlanet1' ) , _get_bad_string( )
-		); $$ , 23503
-	);
-
-	SELECT diag_test_name( 'verse.planet_resources - Income < 0' );
-	SELECT throws_ok( $$
-		INSERT INTO verse.planet_resources(
-			planet_id , resource_name_id , pres_income
-		) VALUES (
-			_get_map_name( 'testPlanet1' ) , _get_string( 'testResource1' ) ,
-			-1
-		); $$ , 23514
-	);
-
-	SELECT diag_test_name( 'verse.planet_resources - Upkeep > 0' );
-	SELECT throws_ok( $$
-		INSERT INTO verse.planet_resources(
-			planet_id , resource_name_id , pres_upkeep
-		) VALUES (
-			_get_map_name( 'testPlanet1' ) , _get_string( 'testResource1' ) ,
-			-1
-		); $$ , 23514
-	);
-
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/admin/030-data/110-empires/010-empire-resources.sql b/legacyworlds-server-data/db-structure/tests/admin/030-data/110-empires/010-empire-resources.sql
deleted file mode 100644
index 06ace16..0000000
--- a/legacyworlds-server-data/db-structure/tests/admin/030-data/110-empires/010-empire-resources.sql
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
- * Test constraints and foreign keys on emp.resources
- */
-BEGIN;
-
-	/* We need to create a pair of resources and a pair of empires */
-	\i utils/strings.sql
-	\i utils/resources.sql
-	\i utils/accounts.sql
-	\i utils/naming.sql
-	SELECT _create_natural_resources( 2 , 'testResource' );
-	SELECT _create_emp_names( 2 , 'testUser' );
-	INSERT INTO emp.empires ( name_id , cash )
-		SELECT id , 0 FROM naming.empire_names;
-
-	
-	
-	/****** TESTS BEGIN HERE ******/
-	SELECT plan( 16 );
-
-
-	SELECT diag_test_name( 'Valid empire resources record' );
-	PREPARE _test_this AS
-		INSERT INTO emp.resources (
-			empire_id , resource_name_id , empres_possessed , empres_owed
-		) VALUES (
-			_get_emp_name( 'testUser1' ) , _get_string( 'testResource1' ) ,
-			1 , 1
-		);
-	SELECT lives_ok( '_test_this' );
-	DELETE FROM emp.resources;
-	DEALLOCATE ALL;
-
-	INSERT INTO emp.resources (
-		empire_id , resource_name_id
-	) VALUES (
-		_get_emp_name( 'testUser1' ) , _get_string( 'testResource1' )
-	);
-	SELECT diag_test_name( 'Default possessed value in empire resources record' );
-	SELECT results_eq(
-		$$ SELECT empres_possessed FROM emp.resources $$ ,
-		$$ VALUES ( 0::DOUBLE PRECISION ) $$
-	);
-	SELECT diag_test_name( 'Default owed value in empire resources record' );
-	SELECT results_eq(
-		$$ SELECT empres_owed FROM emp.resources $$ ,
-		$$ VALUES ( 0::DOUBLE PRECISION ) $$
-	);
-	DELETE FROM emp.resources;
-
-	
-	SELECT diag_test_name( 'NULL empire identifier in empire resources record' );
-	PREPARE _test_this AS
-		INSERT INTO emp.resources (
-			empire_id , resource_name_id , empres_possessed , empres_owed
-		) VALUES (
-			NULL , _get_string( 'testResource1' ) ,
-			1 , 1
-		);
-	SELECT throws_ok( '_test_this' , 23502 );
-	DEALLOCATE ALL;
-
-	SELECT diag_test_name( 'Invalid empire identifier in empire resources record' );
-	PREPARE _test_this AS
-		INSERT INTO emp.resources (
-			empire_id , resource_name_id , empres_possessed , empres_owed
-		) VALUES (
-			_get_bad_emp_name( ) , _get_string( 'testResource1' ) ,
-			1 , 1
-		);
-	SELECT throws_ok( '_test_this' , 23503 );
-	DEALLOCATE ALL;
-
-
-	SELECT diag_test_name( 'NULL resource identifier in empire resources record' );
-	PREPARE _test_this AS
-		INSERT INTO emp.resources (
-			empire_id , resource_name_id , empres_possessed , empres_owed
-		) VALUES (
-			_get_emp_name( 'testUser1' ) , NULL ,
-			1 , 1
-		);
-	SELECT throws_ok( '_test_this' , 23502 );
-	DEALLOCATE ALL;
-
-	SELECT diag_test_name( 'Invalid resource identifier in empire resources record' );
-	PREPARE _test_this AS
-		INSERT INTO emp.resources (
-			empire_id , resource_name_id , empres_possessed , empres_owed
-		) VALUES (
-			_get_emp_name( 'testUser1' ) , _get_bad_string( ) ,
-			1 , 1
-		);
-	SELECT throws_ok( '_test_this' , 23503 );
-	DEALLOCATE ALL;
-
-	
-	SELECT diag_test_name( 'Duplicate empire resources record' );
-	PREPARE _test_this AS
-		INSERT INTO emp.resources (
-			empire_id , resource_name_id , empres_possessed , empres_owed
-		) VALUES (
-			_get_emp_name( 'testUser1' ) , _get_string( 'testResource1' ) ,
-			1 , 1
-		);
-	EXECUTE _test_this;
-	SELECT throws_ok( '_test_this' , 23505 );
-	DEALLOCATE ALL;
-
-	SELECT diag_test_name( 'Empire resources record with same empire but different types of resources' );
-	PREPARE _test_this AS
-		INSERT INTO emp.resources (
-			empire_id , resource_name_id , empres_possessed , empres_owed
-		) VALUES (
-			_get_emp_name( 'testUser1' ) , _get_string( 'testResource2' ) ,
-			1 , 1
-		);
-	SELECT lives_ok( '_test_this' );
-	DEALLOCATE ALL;
-
-	SELECT diag_test_name( 'Empire resources record with different empires but same type of resources' );
-	PREPARE _test_this AS
-		INSERT INTO emp.resources (
-			empire_id , resource_name_id , empres_possessed , empres_owed
-		) VALUES (
-			_get_emp_name( 'testUser2' ) , _get_string( 'testResource1' ) ,
-			1 , 1
-		);
-	SELECT lives_ok( '_test_this' );
-	DEALLOCATE ALL;
-	DELETE FROM emp.resources;
-
-
-	INSERT INTO emp.resources (
-		empire_id , resource_name_id
-	) VALUES (
-		_get_emp_name( 'testUser2' ) , _get_string( 'testResource1' )
-	);
-	SELECT diag_test_name( 'Empire deletion succeeds when empire resources records are present' );
-	PREPARE _test_this AS
-		DELETE FROM emp.empires WHERE name_id = _get_emp_name( 'testUser2' );
-	SELECT lives_ok( '_test_this' );
-	SELECT diag_test_name( 'Empire deletion causes empire resources record deletion' );
-	SELECT is_empty( 'SELECT * FROM emp.resources' );
-	DEALLOCATE ALL;
-
-
-	PREPARE _test_this AS
-		INSERT INTO emp.resources (
-			empire_id , resource_name_id , empres_possessed
-		) VALUES (
-			_get_emp_name( 'testUser1' ) , _get_string( 'testResource1' ) , NULL
-		);
-	SELECT diag_test_name( 'NULL possessed value in empire resources record' );
-	SELECT throws_ok( '_test_this' , 23502 );
-	DEALLOCATE ALL;
-
-	PREPARE _test_this AS
-		INSERT INTO emp.resources (
-			empire_id , resource_name_id , empres_possessed
-		) VALUES (
-			_get_emp_name( 'testUser1' ) , _get_string( 'testResource1' ) , -1
-		);
-	SELECT diag_test_name( 'Negative possessed value in empire resources record' );
-	SELECT throws_ok( '_test_this' , 23514 );
-	DEALLOCATE ALL;
-
-
-	PREPARE _test_this AS
-		INSERT INTO emp.resources (
-			empire_id , resource_name_id , empres_owed
-		) VALUES (
-			_get_emp_name( 'testUser1' ) , _get_string( 'testResource1' ) , NULL
-		);
-	SELECT diag_test_name( 'NULL owed value in empire resources record' );
-	SELECT throws_ok( '_test_this' , 23502 );
-	DEALLOCATE ALL;
-
-	PREPARE _test_this AS
-		INSERT INTO emp.resources (
-			empire_id , resource_name_id , empres_owed
-		) VALUES (
-			_get_emp_name( 'testUser1' ) , _get_string( 'testResource1' ) , -1
-		);
-	SELECT diag_test_name( 'Negative owed value in empire resources record' );
-	SELECT throws_ok( '_test_this' , 23514 );
-	DEALLOCATE ALL;
-
-
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/admin/030-data/110-empires/020-empire-mining-settings.sql b/legacyworlds-server-data/db-structure/tests/admin/030-data/110-empires/020-empire-mining-settings.sql
deleted file mode 100644
index 5ddf3c4..0000000
--- a/legacyworlds-server-data/db-structure/tests/admin/030-data/110-empires/020-empire-mining-settings.sql
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * Test constraints and foreign keys on emp.mining_settings
- */
-BEGIN;
-
-	/* We need to create a pair of resources and a pair of empires */
-	\i utils/strings.sql
-	\i utils/resources.sql
-	\i utils/accounts.sql
-	\i utils/naming.sql
-	SELECT _create_natural_resources( 2 , 'testResource' );
-	SELECT _create_emp_names( 2 , 'testUser' );
-	INSERT INTO emp.empires ( name_id , cash )
-		SELECT id , 0 FROM naming.empire_names;
-	
-	/****** TESTS BEGIN HERE ******/
-	SELECT plan( 13 );
-	
-	
-	SELECT diag_test_name( 'emp.mining_settings - Valid record' );
-	PREPARE _test_this AS
-		INSERT INTO emp.mining_settings(
-			empire_id , resource_name_id , empmset_weight
-		) VALUES (
-			_get_emp_name( 'testUser1' ) , _get_string( 'testResource1' ) , 0
-		);
-	SELECT lives_ok( '_test_this' );
-
-	SELECT diag_test_name( 'emp.mining_settings - Duplicate record' );
-	SELECT throws_ok( '_test_this' , 23505 );
-	DEALLOCATE ALL;
-
-	SELECT diag_test_name( 'emp.mining_settings - Same empire, different types' );
-	PREPARE _test_this AS
-		INSERT INTO emp.mining_settings(
-			empire_id , resource_name_id , empmset_weight
-		) VALUES (
-			_get_emp_name( 'testUser1' ) , _get_string( 'testResource2' ) , 0
-		);
-	SELECT lives_ok( '_test_this' );
-	DEALLOCATE ALL;
-
-	SELECT diag_test_name( 'emp.mining_settings - Same type, different empires' );
-	PREPARE _test_this AS
-		INSERT INTO emp.mining_settings(
-			empire_id , resource_name_id , empmset_weight
-		) VALUES (
-			_get_emp_name( 'testUser2' ) , _get_string( 'testResource1' ) , 0
-		);
-	SELECT lives_ok( '_test_this' );
-	DEALLOCATE ALL;
-	DELETE FROM emp.mining_settings;
-
-	SELECT diag_test_name( 'emp.mining_settings - Valid record with default weight' );
-	PREPARE _test_this AS
-		INSERT INTO emp.mining_settings(
-			empire_id , resource_name_id
-		) VALUES (
-			_get_emp_name( 'testUser1' ) , _get_string( 'testResource1' )
-		);
-	SELECT lives_ok( '_test_this' );
-	DEALLOCATE ALL;
-
-	SELECT diag_test_name( 'emp.mining_settings - Default weight = 2' );
-	SELECT is( empmset_weight , 2 ) FROM emp.mining_settings;
-	DELETE FROM emp.mining_settings;
-
-	SELECT diag_test_name( 'emp.mining_settings - NULL empire identifier' );
-	PREPARE _test_this AS
-		INSERT INTO emp.mining_settings(
-			empire_id , resource_name_id , empmset_weight
-		) VALUES (
-			NULL , _get_string( 'testResource1' ) , 0
-		);
-	SELECT throws_ok( '_test_this' , 23502 );
-	DEALLOCATE ALL;
-
-	SELECT diag_test_name( 'emp.mining_settings - Invalid empire identifier' );
-	PREPARE _test_this AS
-		INSERT INTO emp.mining_settings(
-			empire_id , resource_name_id , empmset_weight
-		) VALUES (
-			_get_bad_emp_name( ) , _get_string( 'testResource1' ) , 0
-		);
-	SELECT throws_ok( '_test_this' , 23503 );
-	DEALLOCATE ALL;
-
-
-	SELECT diag_test_name( 'emp.mining_settings - NULL resource identifier' );
-	PREPARE _test_this AS
-		INSERT INTO emp.mining_settings(
-			empire_id , resource_name_id , empmset_weight
-		) VALUES (
-			_get_emp_name( 'testUser1' ) , NULL , 0
-		);
-	SELECT throws_ok( '_test_this' , 23502 );
-	DEALLOCATE ALL;
-
-	SELECT diag_test_name( 'emp.mining_settings - Invalid resource identifier' );
-	PREPARE _test_this AS
-		INSERT INTO emp.mining_settings(
-			empire_id , resource_name_id , empmset_weight
-		) VALUES (
-			_get_emp_name( 'testUser1' ) , _get_bad_string( ) , 0
-		);
-	SELECT throws_ok( '_test_this' , 23503 );
-	DEALLOCATE ALL;
-
-
-	SELECT diag_test_name( 'emp.mining_settings - NULL weight' );
-	PREPARE _test_this AS
-		INSERT INTO emp.mining_settings(
-			empire_id , resource_name_id , empmset_weight
-		) VALUES (
-			_get_emp_name( 'testUser1' ) , _get_string( 'testResource1' ) , NULL
-		);
-	SELECT throws_ok( '_test_this' , 23502 );
-	DEALLOCATE ALL;
-
-	SELECT diag_test_name( 'emp.mining_settings - Weight < 0' );
-	PREPARE _test_this AS
-		INSERT INTO emp.mining_settings(
-			empire_id , resource_name_id , empmset_weight
-		) VALUES (
-			_get_emp_name( 'testUser1' ) , _get_string( 'testResource1' ) , -1
-		);
-	SELECT throws_ok( '_test_this' , 23514 );
-	DEALLOCATE ALL;
-
-	SELECT diag_test_name( 'emp.mining_settings - Weight > 4' );
-	PREPARE _test_this AS
-		INSERT INTO emp.mining_settings(
-			empire_id , resource_name_id , empmset_weight
-		) VALUES (
-			_get_emp_name( 'testUser1' ) , _get_string( 'testResource1' ) , 5
-		);
-	SELECT throws_ok( '_test_this' , 23514 );
-	DEALLOCATE ALL;
-
-
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/admin/030-data/110-empires/030-empire-planet-mining-settings.sql b/legacyworlds-server-data/db-structure/tests/admin/030-data/110-empires/030-empire-planet-mining-settings.sql
deleted file mode 100644
index 15137d8..0000000
--- a/legacyworlds-server-data/db-structure/tests/admin/030-data/110-empires/030-empire-planet-mining-settings.sql
+++ /dev/null
@@ -1,220 +0,0 @@
-/*
- * Test constraints and foreign keys on emp.planet_mining_settings
- */
-BEGIN;
-
-	/* We need to create a pair of resources, a pair of empires, a pair of planets, and resource providers */
-	\i utils/strings.sql
-	\i utils/resources.sql
-	\i utils/accounts.sql
-	\i utils/naming.sql
-	\i utils/universe.sql
-	SELECT _create_natural_resources( 2 , 'testResource' );
-	SELECT _create_emp_names( 2 , 'testUser' );
-	INSERT INTO emp.empires ( name_id , cash )
-		SELECT id , 0 FROM naming.empire_names;
-	SELECT _create_raw_planets( 2 , 'testPlanet' );
-	SELECT _create_resource_provider( 'testPlanet1' , 'testResource1' );
-	SELECT _create_resource_provider( 'testPlanet1' , 'testResource2' );
-	SELECT _create_resource_provider( 'testPlanet2' , 'testResource1' );
-	-- No provider for testResource2 on testPlanet2
-
-	/****** TESTS BEGIN HERE ******/
-	SELECT plan( 17 );
-
-
-	SELECT diag_test_name( 'emp.planet_mining_settings - Valid record' );
-	PREPARE _test_this AS
-		INSERT INTO emp.planet_mining_settings(
-			empire_id , planet_id ,
-			resource_name_id , emppmset_weight
-		) VALUES (
-			_get_emp_name( 'testUser1' ) , _get_map_name( 'testPlanet1' ) ,
-			_get_string( 'testResource1' ) , 0
-		);
-	SELECT lives_ok( '_test_this' );
-	
-	SELECT diag_test_name( 'emp.planet_mining_settings - Duplicate record' );
-	SELECT throws_ok( '_test_this' , 23505 );
-	DEALLOCATE ALL;
-
-	SELECT diag_test_name( 'emp.planet_mining_settings - Different types' );
-	PREPARE _test_this AS
-		INSERT INTO emp.planet_mining_settings(
-			empire_id , planet_id ,
-			resource_name_id , emppmset_weight
-		) VALUES (
-			_get_emp_name( 'testUser1' ) , _get_map_name( 'testPlanet1' ) ,
-			_get_string( 'testResource2' ) , 0
-		);
-	SELECT lives_ok( '_test_this' );
-	DEALLOCATE ALL;
-
-	SELECT diag_test_name( 'emp.planet_mining_settings - Different empires' );
-	PREPARE _test_this AS
-		INSERT INTO emp.planet_mining_settings(
-			empire_id , planet_id ,
-			resource_name_id , emppmset_weight
-		) VALUES (
-			_get_emp_name( 'testUser2' ) , _get_map_name( 'testPlanet1' ) ,
-			_get_string( 'testResource1' ) , 0
-		);
-	SELECT lives_ok( '_test_this' );
-	DEALLOCATE ALL;
-
-	SELECT diag_test_name( 'emp.planet_mining_settings - Different planets' );
-	PREPARE _test_this AS
-		INSERT INTO emp.planet_mining_settings(
-			empire_id , planet_id ,
-			resource_name_id , emppmset_weight
-		) VALUES (
-			_get_emp_name( 'testUser1' ) , _get_map_name( 'testPlanet2' ) ,
-			_get_string( 'testResource1' ) , 0
-		);
-	SELECT lives_ok( '_test_this' );
-	DEALLOCATE ALL;
-	DELETE FROM emp.planet_mining_settings;
-
-	SELECT diag_test_name( 'emp.planet_mining_settings - Valid record with default weight' );
-	PREPARE _test_this AS
-		INSERT INTO emp.planet_mining_settings(
-			empire_id , planet_id , resource_name_id
-		) VALUES (
-			_get_emp_name( 'testUser1' ) , _get_map_name( 'testPlanet1' ) ,
-			_get_string( 'testResource1' )
-		);
-	SELECT lives_ok( '_test_this' );
-	DEALLOCATE ALL;
-
-	SELECT diag_test_name( 'emp.planet_mining_settings - Default weight = 2' );
-	SELECT is( emppmset_weight , 2 ) FROM emp.planet_mining_settings;
-	DELETE FROM emp.planet_mining_settings;
-
-
-	SELECT diag_test_name( 'emp.planet_mining_settings - NULL empire identifier' );
-	PREPARE _test_this AS
-		INSERT INTO emp.planet_mining_settings(
-			empire_id , planet_id ,
-			resource_name_id , emppmset_weight
-		) VALUES (
-			NULL , _get_map_name( 'testPlanet2' ) ,
-			_get_string( 'testResource1' ) , 0
-		);
-	SELECT throws_ok( '_test_this' , 23502 );
-	DEALLOCATE ALL;
-
-	SELECT diag_test_name( 'emp.planet_mining_settings - Invalid empire identifier' );
-	PREPARE _test_this AS
-		INSERT INTO emp.planet_mining_settings(
-			empire_id , planet_id ,
-			resource_name_id , emppmset_weight
-		) VALUES (
-			_get_bad_emp_name( ) , _get_map_name( 'testPlanet2' ) ,
-			_get_string( 'testResource1' ) , 0
-		);
-	SELECT throws_ok( '_test_this' , 23503 );
-	DEALLOCATE ALL;
-
-
-	SELECT diag_test_name( 'emp.planet_mining_settings - NULL planet identifier' );
-	PREPARE _test_this AS
-		INSERT INTO emp.planet_mining_settings(
-			empire_id , planet_id ,
-			resource_name_id , emppmset_weight
-		) VALUES (
-			_get_emp_name( 'testUser1' ) , NULL ,
-			_get_string( 'testResource1' ) , 0
-		);
-	SELECT throws_ok( '_test_this' , 23502 );
-	DEALLOCATE ALL;
-
-	SELECT diag_test_name( 'emp.planet_mining_settings - Invalid planet identifier' );
-	PREPARE _test_this AS
-		INSERT INTO emp.planet_mining_settings(
-			empire_id , planet_id ,
-			resource_name_id , emppmset_weight
-		) VALUES (
-			_get_emp_name( 'testUser1' ) , _get_bad_map_name( ) ,
-			_get_string( 'testResource1' ) , 0
-		);
-	SELECT throws_ok( '_test_this' , 23503 );
-	DEALLOCATE ALL;
-
-
-	SELECT diag_test_name( 'emp.planet_mining_settings - NULL resource identifier' );
-	PREPARE _test_this AS
-		INSERT INTO emp.planet_mining_settings(
-			empire_id , planet_id ,
-			resource_name_id , emppmset_weight
-		) VALUES (
-			_get_emp_name( 'testUser1' ) , _get_map_name( 'testPlanet2' ) ,
-			NULL , 0
-		);
-	SELECT throws_ok( '_test_this' , 23502 );
-	DEALLOCATE ALL;
-
-	SELECT diag_test_name( 'emp.planet_mining_settings - Invalid resource identifier' );
-	PREPARE _test_this AS
-		INSERT INTO emp.planet_mining_settings(
-			empire_id , planet_id ,
-			resource_name_id , emppmset_weight
-		) VALUES (
-			_get_emp_name( 'testUser1' ) , _get_map_name( 'testPlanet2' ) ,
-			_get_bad_string( ) , 0
-		);
-	SELECT throws_ok( '_test_this' , 23503 );
-	DEALLOCATE ALL;
-
-
-	SELECT diag_test_name( 'emp.planet_mining_settings - Invalid resource provider identifier' );
-	PREPARE _test_this AS
-		INSERT INTO emp.planet_mining_settings(
-			empire_id , planet_id ,
-			resource_name_id , emppmset_weight
-		) VALUES (
-			_get_emp_name( 'testUser1' ) , _get_map_name( 'testPlanet2' ) ,
-			_get_string( 'testResource2' ) , 0
-		);
-	SELECT throws_ok( '_test_this' , 23503 );
-	DEALLOCATE ALL;
-
-
-	SELECT diag_test_name( 'emp.planet_mining_settings - NULL weight' );
-	PREPARE _test_this AS
-		INSERT INTO emp.planet_mining_settings(
-			empire_id , planet_id ,
-			resource_name_id , emppmset_weight
-		) VALUES (
-			_get_emp_name( 'testUser1' ) , _get_map_name( 'testPlanet1' ) ,
-			_get_string( 'testResource1' ) , NULL
-		);
-	SELECT throws_ok( '_test_this' , 23502 );
-	DEALLOCATE ALL;
-
-	SELECT diag_test_name( 'emp.planet_mining_settings - Weight < 0' );
-	PREPARE _test_this AS
-		INSERT INTO emp.planet_mining_settings(
-			empire_id , planet_id ,
-			resource_name_id , emppmset_weight
-		) VALUES (
-			_get_emp_name( 'testUser1' ) , _get_map_name( 'testPlanet1' ) ,
-			_get_string( 'testResource1' ) , -1
-		);
-	SELECT throws_ok( '_test_this' , 23514 );
-	DEALLOCATE ALL;
-
-	SELECT diag_test_name( 'emp.planet_mining_settings - Weight > 4' );
-	PREPARE _test_this AS
-		INSERT INTO emp.planet_mining_settings(
-			empire_id , planet_id ,
-			resource_name_id , emppmset_weight
-		) VALUES (
-			_get_emp_name( 'testUser1' ) , _get_map_name( 'testPlanet1' ) ,
-			_get_string( 'testResource1' ) , 5
-		);
-	SELECT throws_ok( '_test_this' , 23514 );
-	DEALLOCATE ALL;
-
-
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/admin/040-functions/003-updates/010-target-definition.sql b/legacyworlds-server-data/db-structure/tests/admin/040-functions/003-updates/010-target-definition.sql
deleted file mode 100644
index 5438a50..0000000
--- a/legacyworlds-server-data/db-structure/tests/admin/040-functions/003-updates/010-target-definition.sql
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Tests of the update target definitions
- */
-BEGIN;
-	-- Make sure we get rid of all existing definitions first
-	DELETE FROM sys.update_types;
-	DELETE FROM sys.update_targets;
-
-	-- Create a test schema & table which will be used as the target
-	CREATE SCHEMA test
-		CREATE TABLE test(
-			test_id		SERIAL NOT NULL PRIMARY KEY
-		)
-		CREATE TABLE test2(
-			test_id		SERIAL NOT NULL PRIMARY KEY
-		);
-
-	-- ***** TESTS BEGIN HERE *****
-	SELECT plan( 8 );
-
-	SELECT diag_test_name( 'Update target definitions - Failure if schema/table do not exist' );
-	SELECT throws_ok(
-			$$ INSERT INTO sys.update_targets(
-					updtgt_name , updtgt_schema , updtgt_table
-				) VALUES (
-					'Test' , 'test' , 'does_not_exist'
-				); $$ ,
-			23503
-		);
-
-	SELECT diag_test_name( 'Update target definitions - Successful insertion' );
-	SELECT lives_ok( $$
-		INSERT INTO sys.update_targets(
-				updtgt_name , updtgt_schema , updtgt_table
-			) VALUES (
-				'Test' , 'test' , 'test'
-			);
-	$$ );
-	SELECT diag_test_name( 'Update target definitions - Specific update table - Exists after insertion' );
-	SELECT has_table( 'test' , 'test_updates' , 'No specific update table' );
-	SELECT diag_test_name( 'Update target definitions - Specific update table - Primary key' );
-	SELECT index_is_primary( 'test' , 'test_updates' , 'test_updates_pkey' );
-	SELECT diag_test_name( 'Update target definitions - Specific update table - Primary key definition' );
-	SELECT has_index( 'test' , 'test_updates' , 'test_updates_pkey' ,
-		ARRAY[ 'updtgt_id' , 'updtype_id' , 'update_id' , 'test_id' ] );
-
-	SELECT diag_test_name( 'Update target definitions - Duplicate name' );
-	SELECT throws_ok( $$
-		INSERT INTO sys.update_targets(
-				updtgt_name , updtgt_schema , updtgt_table
-			) VALUES (
-				'Test' , 'test' , 'test2'
-			);
-	$$ , 23505 );
-
-	SELECT diag_test_name( 'Update target definitions - Duplicate table reference' );
-	SELECT throws_ok( $$
-		INSERT INTO sys.update_targets(
-				updtgt_name , updtgt_schema , updtgt_table
-			) VALUES (
-				'Test 2' , 'test' , 'test'
-			);
-	$$ , 23505 );
-
-	SELECT diag_test_name( 'Update target definitions - Deletion drops the specific update table' );
-	DELETE FROM sys.update_targets;
-	SELECT hasnt_table( 'test' , 'test_updates' , 'Specific update table still exists' );
-
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/admin/040-functions/003-updates/020-type-definitions.sql b/legacyworlds-server-data/db-structure/tests/admin/040-functions/003-updates/020-type-definitions.sql
deleted file mode 100644
index 895aa72..0000000
--- a/legacyworlds-server-data/db-structure/tests/admin/040-functions/003-updates/020-type-definitions.sql
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * Tests of the update type definitions
- */
-BEGIN;
-	-- Make sure we get rid of all existing definitions first
-	DELETE FROM sys.update_types;
-	DELETE FROM sys.update_targets;
-
-	-- Create a test schema & tables which will be used as targets
-	CREATE SCHEMA test
-		CREATE TABLE test(
-			test_id		SERIAL NOT NULL PRIMARY KEY
-		);
-
-	-- Create target definitions
-	INSERT INTO sys.update_targets(
-			updtgt_id , updtgt_name , updtgt_schema , updtgt_table
-		) VALUES (
-			1 , 'Test 1' , 'test' , 'test'
-		);
-
-	-- Create a dummy stored procedure in the sys schema
-	CREATE FUNCTION sys.dummy_update_func( c_tick BIGINT )
-			RETURNS INT LANGUAGE SQL AS 'SELECT 1;';
-
-	-- ***** TESTS BEGIN HERE *****
-	SELECT plan( 14 );
-	
-	SELECT diag_test_name( 'Update types - Definition with invalid target' );
-	SELECT throws_ok( $$
-		INSERT INTO sys.update_types(
-			updtype_id , updtgt_id , updtype_name , updtype_description , updtype_ordering
-		) VALUES (
-			1 , 5 , 'Test' , '' , 1
-		);
-	$$ , 23503 );
-	
-	SELECT diag_test_name( 'Update types - Definition with invalid stored procedure name' );
-	SELECT throws_ok( $$
-		INSERT INTO sys.update_types(
-			updtype_id , updtgt_id , updtype_name , updtype_description , updtype_ordering , updtype_proc_name
-		) VALUES (
-			1 , 5 , 'Test' , '' , 1 , 'does_not_exist'
-		);
-	$$ , 'P0001' );
-	
-	SELECT diag_test_name( 'Update types - Successful insertion with no procedure name' );
-	SELECT lives_ok( $$
-		INSERT INTO sys.update_types(
-			updtype_id , updtgt_id , updtype_name , updtype_description , updtype_ordering
-		) VALUES (
-			1 , 1 , 'Test' , '' , 1
-		);
-	$$ );
-	DELETE FROM sys.update_types;
-	
-	SELECT diag_test_name( 'Update types - Successful insertion with a procedure name' );
-	SELECT lives_ok( $$
-		INSERT INTO sys.update_types(
-			updtype_id , updtgt_id , updtype_name , updtype_description , updtype_ordering , updtype_proc_name
-		) VALUES (
-			1 , 1 , 'Test' , '' , 1 , 'dummy_update_func'
-		);
-	$$ );
-	
-	SELECT diag_test_name( 'Update types - Setting an existing row''s stored procedure to something invalid fails' );
-	SELECT throws_ok( $$
-		UPDATE sys.update_types
-			SET updtype_proc_name = 'does_not_exist'
-			WHERE updtype_id = 1
-	$$ , 'P0001' );
-
-	SELECT diag_test_name( 'Update types - Failure on duplicate name' );
-	SELECT throws_ok( $$
-		INSERT INTO sys.update_types(
-			updtype_id , updtgt_id , updtype_name , updtype_description , updtype_ordering
-		) VALUES (
-			2 , 1 , 'Test' , '' , 1
-		);
-	$$ , 23505 );
-
-	SELECT diag_test_name( 'Update types - Failure on duplicate stored procedure' );
-	SELECT throws_ok( $$
-		INSERT INTO sys.update_types(
-			updtype_id , updtgt_id , updtype_name , updtype_description , updtype_ordering , updtype_proc_name
-		) VALUES (
-			3 , 1 , 'Test 2' , '' , 1 , 'dummy_update_func'
-		);
-	$$ , 23505 );
-
-	SELECT diag_test_name( 'Update types - Target deletion fails if type definitions exist' );
-	SELECT throws_ok( $$ DELETE FROM sys.update_targets WHERE updtgt_id = 1 $$ , 23503 );
-
-	DELETE FROM sys.update_types;
-
-	INSERT INTO sys.update_types(
-		updtype_id , updtgt_id , updtype_name , updtype_description , updtype_ordering
-	) VALUES (
-			1 , 1 , 'Test 1' , '' , 1
-		) , (
-			2 , 1 , 'Test 3' , '' , 75
-		) , (
-			3 , 1 , 'Test 2' , '' , 2
-		);
-	SELECT diag_test_name( 'Update types - Ordering column is updated' );
-	SELECT set_eq(
-		$$ SELECT updtype_id , updtype_ordering FROM sys.update_types $$ ,
-		$$ VALUES ( 1 , 2 ) , ( 3 , 4 ) , ( 2 , 6 ) $$
-	);
-	DELETE FROM sys.update_types;
-	
-	
-	INSERT INTO test.test VALUES ( 1 ) , ( 2 );
-	INSERT INTO sys.update_types(
-		updtype_id , updtgt_id , updtype_name , updtype_description , updtype_ordering
-	) VALUES (
-			1 , 1 , 'Test 1' , '' , 1
-	);
-	SELECT diag_test_name( 'Update types - Type creation adds specific rows for missing items' );
-	SELECT set_eq(
-		$$ SELECT updtgt_id , updtype_id , test_id FROM test.test_updates $$ ,
-		$$ VALUES ( 1 , 1 , 1 ) , ( 1 , 1 , 2 ) $$
-	);
-	SELECT diag_test_name( 'Update types - Type creation adds genertic rows for missing items' );
-	SELECT set_eq(
-		$$ SELECT test_id , update_state , update_last
-				FROM test.test_updates
-					INNER JOIN sys.updates USING ( updtgt_id , updtype_id , update_id ) $$ ,
-		$$ VALUES ( 1 , 'FUTURE'::sys.update_state_type , -1 ) ,
-				( 2 , 'FUTURE'::sys.update_state_type , '-1' ) $$
-	);
-	
-	INSERT INTO test.test VALUES ( 3 );
-	SELECT diag_test_name( 'Update types - New items have automatically inserted update rows' );
-	SELECT set_eq(
-		$$ SELECT test_id , updtype_id , update_state , update_last
-				FROM test.test_updates
-					INNER JOIN sys.updates USING ( updtgt_id , updtype_id , update_id )
-				WHERE test_id = 3 $$ ,
-		$$ VALUES ( 3 , 1 , 'FUTURE'::sys.update_state_type , -1 ) $$
-	);
-
-	DELETE FROM sys.update_types WHERE updtype_id = 1;
-	SELECT diag_test_name( 'Update types - Type deletion cascades to specific rows' );
-	SELECT is_empty( $$ SELECT * FROM test.test_updates $$ );
-	SELECT diag_test_name( 'Update types - Type deletion cascades to generic rows' );
-	SELECT is_empty( $$ SELECT * FROM sys.updates $$ );
-
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/admin/040-functions/005-logs/010-write-sql-log.sql b/legacyworlds-server-data/db-structure/tests/admin/040-functions/005-logs/010-write-sql-log.sql
deleted file mode 100644
index e8bef15..0000000
--- a/legacyworlds-server-data/db-structure/tests/admin/040-functions/005-logs/010-write-sql-log.sql
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Test the sys.write_sql_log( ) function
- */
-BEGIN;
-	DELETE FROM sys.logs;
-	SELECT plan( 4 );
-	
-	SELECT diag_test_name( 'sys.write_sql_log( ) - Initial call' );
-	SELECT lives_ok(
-		$$ SELECT sys.write_sql_log( 'test' , 'WARNING'::log_level , 'test' ) $$
-	);
-	SELECT diag_test_name( 'sys.write_sql_log( ) - Contents of system log after call' );
-	SELECT is( COUNT(*)::INT , 1 ) FROM sys.logs;
-	DELETE FROM sys.logs;
-	
-	SELECT diag_test_name( 'sys.write_sql_log( ) - Two calls in sequence' );
-	SELECT lives_ok(
-		$$ SELECT sys.write_sql_log( 'test' , 'WARNING'::log_level , 'test' );
-		SELECT sys.write_sql_log( 'test' , 'WARNING'::log_level , 'test' ) $$
-	);
-	DELETE FROM sys.logs;
-
-	SELECT diag_test_name( 'sys.write_sql_log( ) - Calling and rolling back' );
-	SAVEPOINT before_log;
-		SELECT sys.write_sql_log( 'test' , 'WARNING'::log_level , 'test' );
-		SELECT sys.write_log( 'test' , 'WARNING'::log_level , 'test' );
-	ROLLBACK TO SAVEPOINT before_log;	
-	SELECT is( COUNT(*)::INT , 1 ) FROM sys.logs;
-	DELETE FROM sys.logs;
-
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/admin/040-functions/025-resources/005-add-resource-records.sql b/legacyworlds-server-data/db-structure/tests/admin/040-functions/025-resources/005-add-resource-records.sql
deleted file mode 100644
index 37103d7..0000000
--- a/legacyworlds-server-data/db-structure/tests/admin/040-functions/025-resources/005-add-resource-records.sql
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Test the defs.add_resource_records() function
- */
-BEGIN;
-	/* Remove foreign keys from empires and planets, then insert dummy records
-	 * into both tables.
-	 */
-	ALTER TABLE emp.empires
-		DROP CONSTRAINT fk_empires_name;
-	INSERT INTO emp.empires ( name_id , cash )
-		VALUES ( 1 , 0 );
-
-	ALTER TABLE verse.planets
-		DROP CONSTRAINT fk_planets_name ,
-		DROP CONSTRAINT fk_planets_system;
-	INSERT INTO verse.planets ( name_id , system_id , orbit , picture , population )
-		VALUES ( 1 , 1 , 1 , 1 , 1 );
-
-	/* Create a resource type and call the function */
-	\i utils/strings.sql
-	\i utils/resources.sql
-	SELECT _create_resources( 1 , 'test' );
-	SELECT defs.add_resource_records( _get_string( 'test1' ) );
-	
-	/***** TESTS BEGIN HERE *****/
-	SELECT plan( 2 );
-
-	SELECT diag_test_name( 'defs.add_resource_records() - Empire record created' );
-	SELECT is( COUNT(*)::INT , 1 )
-		FROM emp.resources
-		WHERE empire_id = 1 AND resource_name_id = _get_string( 'test1' );
-
-	SELECT diag_test_name( 'defs.add_resource_records() - Planet record created' );
-	SELECT is( COUNT(*)::INT , 1 )
-		FROM verse.planet_resources
-		WHERE planet_id = 1 AND resource_name_id = _get_string( 'test1' );
-
-	SELECT * FROM finish( );
-ROLLBACK;
diff --git a/legacyworlds-server-data/db-structure/tests/admin/040-functions/025-resources/010-uoc-resource-internal.sql b/legacyworlds-server-data/db-structure/tests/admin/040-functions/025-resources/010-uoc-resource-internal.sql
deleted file mode 100644
index 2c2d08c..0000000
--- a/legacyworlds-server-data/db-structure/tests/admin/040-functions/025-resources/010-uoc-resource-internal.sql
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Test the defs.uoc_resource_internal() function
- */
-BEGIN;
-	
-	/* We need a few strings to be used when creating resource definitions, and a natural resource. */
-	\i utils/strings.sql
-	\i utils/resources.sql
-	SELECT _create_test_strings( 7 );
-	SELECT _create_natural_resources( 1 , 'natRes' );
-
-	/****** TESTS BEGIN HERE ******/
-	SELECT plan( 17 );
-
-	SELECT diag_test_name( 'defs.uoc_resource_internal() - creation without category' );
-	SELECT is( defs.uoc_resource_internal( 'test3' , 'test4' , NULL , 1 ) , 'CREATED' );
-	SELECT diag_test_name( 'defs.uoc_resource_internal() - creation results without category' );
-	SELECT results_eq(
-		$$ SELECT resource_name_id , resource_description_id , resource_weight
-				FROM defs.resources
-				WHERE resource_name_id = _get_string( 'test3' )
-					AND resource_category_id IS NULL $$ ,
-		$$ VALUES ( _get_string( 'test3' ) , _get_string( 'test4' ) , 1 ) $$
-	);
-
-	SELECT diag_test_name( 'defs.uoc_resource_internal() - creation with category' );
-	SELECT is( defs.uoc_resource_internal( 'test5' , 'test6' , 'test7' , 1 ) , 'CREATED' );
-	SELECT diag_test_name( 'defs.uoc_resource_internal() - creation results with category' );
-	SELECT results_eq(
-		$$ SELECT * FROM defs.resources
-				WHERE resource_name_id = _get_string( 'test5' ) $$ ,
-		$$ VALUES ( _get_string( 'test5' ) , _get_string( 'test6' ) , _get_string( 'test7' ) , 1 ) $$
-	);
-
-	SELECT diag_test_name( 'defs.uoc_resource_internal() - update without category' );
-	SELECT is( defs.uoc_resource_internal( 'test3' , 'test7' , NULL , 2 ) , 'UPDATED' );
-	SELECT diag_test_name( 'defs.uoc_resource_internal() - update results without category' );
-	SELECT results_eq(
-		$$ SELECT resource_name_id , resource_description_id , resource_weight
-				FROM defs.resources
-				WHERE resource_name_id = _get_string( 'test3' )
-					AND resource_category_id IS NULL $$ ,
-		$$ VALUES ( _get_string( 'test3' ) , _get_string( 'test7' ) , 2 ) $$
-	);
-
-	SELECT diag_test_name( 'defs.uoc_resource_internal() - update with category' );
-	SELECT is( defs.uoc_resource_internal( 'test3' , 'test4' , 'test7' , 1 ) , 'UPDATED' );
-	SELECT diag_test_name( 'defs.uoc_resource_internal() - update results with category' );
-	SELECT results_eq(
-		$$ SELECT * FROM defs.resources
-				WHERE resource_name_id = _get_string( 'test3' ) $$ ,
-		$$ VALUES ( _get_string( 'test3' ) , _get_string( 'test4' ) , _get_string( 'test7' ) , 1 ) $$
-	);
-
-	SELECT diag_test_name( 'defs.uoc_resource_internal() - incorrect name string' );
-	SELECT is( defs.uoc_resource_internal( 'does-not-exist' , 'test2' , NULL , 1 ) , 'BAD_STRINGS' );
-	SELECT diag_test_name( 'defs.uoc_resource_internal() - incorrect description string' );
-	SELECT is( defs.uoc_resource_internal( 'test1' , 'does-not-exist' , NULL , 1 ) , 'BAD_STRINGS' );
-	SELECT diag_test_name( 'defs.uoc_resource_internal() - incorrect category string' );
-	SELECT is( defs.uoc_resource_internal( 'test1' , 'test2' , 'does-not-exist' , 1 ) , 'BAD_STRINGS' );
-
-	SELECT diag_test_name( 'defs.uoc_resource_internal() - duplicate description on new resource' );
-	SELECT is( defs.uoc_resource_internal( 'test1' , 'test4' , NULL , 1 ) , 'DUP_DESCR' );
-	SELECT diag_test_name( 'defs.uoc_resource_internal() - duplicate description on existing resource' );
-	SELECT is( defs.uoc_resource_internal( 'test5' , 'test4' , NULL , 1 ) , 'DUP_DESCR' );
-
-	SELECT diag_test_name( 'defs.uoc_resource_internal() - update on natural resource' );
-	SELECT is( defs.uoc_resource_internal( 'natRes1' , 'test2' , NULL , 1 ) , 'BAD_TYPE' );
-
-	SELECT diag_test_name( 'defs.uoc_resource_internal() - weight <= 0' );
-	SELECT is( defs.uoc_resource_internal( 'test1' , 'test2' , NULL , 0 ) , 'BAD_VALUE' );
-	
-	/* Reset resources, create temporary table, replace
-	 * defs.add_resource_records() to make sure it's called when needed (and
-	 * only then)
-	 */
-	DELETE FROM defs.natural_resources;
-	DELETE FROM defs.resources;
-	CREATE TEMPORARY TABLE arr_called( on_id INT ) ON COMMIT DROP;
-	CREATE OR REPLACE FUNCTION defs.add_resource_records( _resource INT )
-		RETURNS VOID
-		STRICT VOLATILE
-		SECURITY INVOKER
-	AS $$
-		INSERT INTO arr_called VALUES( $1 );
-	$$ LANGUAGE SQL;
-	ALTER TABLE emp.empires
-		DROP CONSTRAINT fk_empires_name;
-	INSERT INTO emp.empires ( name_id , cash )
-		VALUES ( 1 , 0 );
-
-	SELECT diag_test_name( 'defs.uoc_resource_internal() - defs.add_resource_record() called on new resource' );
-	SELECT defs.uoc_resource_internal( 'test1' , 'test4' , NULL , 1 );
-	SELECT is( COUNT(*)::INT , 1 )
-		FROM arr_called
-		WHERE on_id = _get_string( 'test1' );
-	DELETE FROM arr_called;
-
-	SELECT diag_test_name( 'defs.uoc_resource_internal() - defs.add_resource_record() not called on resource update' );
-	SELECT defs.uoc_resource_internal( 'test1' , 'test3' , NULL , 1 );
-	SELECT is( COUNT(*)::INT , 0 )
-		FROM arr_called
-		WHERE on_id = _get_string( 'test1' );
-	DELETE FROM arr_called;
-
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/admin/040-functions/025-resources/020-uoc-resource.sql b/legacyworlds-server-data/db-structure/tests/admin/040-functions/025-resources/020-uoc-resource.sql
deleted file mode 100644
index aa6af61..0000000
--- a/legacyworlds-server-data/db-structure/tests/admin/040-functions/025-resources/020-uoc-resource.sql
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Test the defs.uoc_resource() functions
- */
-BEGIN;
-	/* Create a fake internal function that will just push its parameters to
-	 * a temporary table.
-	 */
-	CREATE TEMPORARY TABLE calls_to_internal(
-		name TEXT , description TEXT , category TEXT , weight INT 
-	) ON COMMIT DROP;
-	CREATE OR REPLACE FUNCTION defs.uoc_resource_internal(
-				_name TEXT ,
-				_description TEXT ,
-				_category TEXT ,
-				_weight INT )
-		RETURNS defs.resource_update_result
-		CALLED ON NULL INPUT
-		VOLATILE
-		SECURITY INVOKER
-	AS $$
-		INSERT INTO calls_to_internal VALUES (
-			$1 , $2 , CASE WHEN $3 IS NULL THEN 'NULL' ELSE $3 END , $4
-		);
-		SELECT 'BAD_STRINGS'::defs.resource_update_result;
-	$$ LANGUAGE SQL;
-
-	/****** TESTS BEGIN HERE ******/
-	SELECT plan( 2 );
-
-	SELECT diag_test_name( 'defs.uoc_resource() - Calls internal function (without category)' );
-	SELECT defs.uoc_resource( 'a' , 'b' , 1 );
-	SELECT set_eq(
-		$$ SELECT * FROM calls_to_internal; $$ ,
-		$$ VALUES( 'a' , 'b' , 'NULL' , 1 ) $$
-	);
-	DELETE FROM calls_to_internal;
-
-	SELECT diag_test_name( 'defs.uoc_resource() - Calls internal function (without category)' );
-	SELECT defs.uoc_resource( 'a' , 'b' , 'c' , 1 );
-	SELECT set_eq(
-		$$ SELECT * FROM calls_to_internal; $$ ,
-		$$ VALUES( 'a' , 'b' , 'c' , 1 ) $$
-	);
-
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/admin/040-functions/025-resources/030-uoc-natres-internal.sql b/legacyworlds-server-data/db-structure/tests/admin/040-functions/025-resources/030-uoc-natres-internal.sql
deleted file mode 100644
index f9a67a4..0000000
--- a/legacyworlds-server-data/db-structure/tests/admin/040-functions/025-resources/030-uoc-natres-internal.sql
+++ /dev/null
@@ -1,209 +0,0 @@
-/*
- * Test the defs.uoc_natres_internal() function
- */
-BEGIN;
-	
-	/* We need a few strings to be used when creating resource definitions, and a basic resource. */
-	\i utils/strings.sql
-	\i utils/resources.sql
-	SELECT _create_test_strings( 7 );
-	SELECT _create_resources( 1 , 'basicRes' );
-
-	/****** TESTS BEGIN HERE ******/
-	SELECT plan( 39 );
-
-	SELECT diag_test_name( 'defs.uoc_natres_internal() - creation without category' );
-	SELECT is( defs.uoc_natres_internal( 'test3' , 'test4' , NULL , 1 ,
-		0.5 , 100 , 50 , 0.5 , 0.05 , 0.5 , 0.05 ) , 'CREATED' );
-	SELECT diag_test_name( 'defs.uoc_natres_internal() - creation results without category - basic' );
-	SELECT results_eq(
-		$$ SELECT resource_name_id , resource_description_id , resource_weight
-				FROM defs.resources
-				WHERE resource_name_id = _get_string( 'test3' )
-					AND resource_category_id IS NULL $$ ,
-		$$ VALUES ( _get_string( 'test3' ) , _get_string( 'test4' ) , 1 ) $$
-	);
-	SELECT diag_test_name( 'defs.uoc_natres_internal() - creation results without category - nat. res.' );
-	SELECT results_eq(
-		$$ SELECT * FROM defs.natural_resources
-				WHERE resource_name_id = _get_string( 'test3' ) $$ ,
-		$$ VALUES ( _get_string( 'test3' ) , 0.5::DOUBLE PRECISION , 100::DOUBLE PRECISION ,
-			50::DOUBLE PRECISION , 0.5::DOUBLE PRECISION , 0.05::DOUBLE PRECISION ,
-			0.5::DOUBLE PRECISION , 0.05::DOUBLE PRECISION ) $$
-	);
-
-	SELECT diag_test_name( 'defs.uoc_natres_internal() - creation with category' );
-	SELECT is( defs.uoc_natres_internal( 'test5' , 'test6' , 'test7' , 1 ,
-		0.5 , 100 , 50 , 0.5 , 0.05 , 0.5 , 0.05 ) , 'CREATED' );
-	SELECT diag_test_name( 'defs.uoc_natres_internal() - creation results with category - basic' );
-	SELECT results_eq(
-		$$ SELECT * FROM defs.resources
-				WHERE resource_name_id = _get_string( 'test5' ) $$ ,
-		$$ VALUES ( _get_string( 'test5' ) , _get_string( 'test6' ) , _get_string( 'test7' ) , 1 ) $$
-	);
-	SELECT diag_test_name( 'defs.uoc_natres_internal() - creation results with category - nat. res.' );
-	SELECT results_eq(
-		$$ SELECT * FROM defs.natural_resources
-				WHERE resource_name_id = _get_string( 'test5' ) $$ ,
-		$$ VALUES ( _get_string( 'test5' ) , 0.5::DOUBLE PRECISION , 100::DOUBLE PRECISION ,
-			50::DOUBLE PRECISION , 0.5::DOUBLE PRECISION , 0.05::DOUBLE PRECISION ,
-			0.5::DOUBLE PRECISION , 0.05::DOUBLE PRECISION ) $$
-	);
-
-	SELECT diag_test_name( 'defs.uoc_natres_internal() - update without category' );
-	SELECT is( defs.uoc_natres_internal( 'test3' , 'test7' , NULL , 2 ,
-		0.3 , 300 , 30 , 0.3 , 0.03 , 0.3 , 0.03 ) , 'UPDATED' );
-	SELECT diag_test_name( 'defs.uoc_natres_internal() - update results without category - basic' );
-	SELECT results_eq(
-		$$ SELECT resource_name_id , resource_description_id , resource_weight
-				FROM defs.resources
-				WHERE resource_name_id = _get_string( 'test3' )
-					AND resource_category_id IS NULL $$ ,
-		$$ VALUES ( _get_string( 'test3' ) , _get_string( 'test7' ) , 2 ) $$
-	);
-	SELECT diag_test_name( 'defs.uoc_natres_internal() - update results without category - nat. res.' );
-	SELECT results_eq(
-		$$ SELECT * FROM defs.natural_resources
-				WHERE resource_name_id = _get_string( 'test3' ) $$ ,
-		$$ VALUES ( _get_string( 'test3' ) , 0.3::DOUBLE PRECISION , 300::DOUBLE PRECISION ,
-			30::DOUBLE PRECISION , 0.3::DOUBLE PRECISION , 0.03::DOUBLE PRECISION ,
-			0.3::DOUBLE PRECISION , 0.03::DOUBLE PRECISION ) $$
-	);
-
-	SELECT diag_test_name( 'defs.uoc_natres_internal() - update with category' );
-	SELECT is( defs.uoc_natres_internal( 'test3' , 'test4' , 'test7' , 1 ,
-		0.5 , 100 , 50 , 0.5 , 0.05 , 0.5 , 0.05 ) , 'UPDATED' );
-	SELECT diag_test_name( 'defs.uoc_natres_internal() - update results with category' );
-	SELECT results_eq(
-		$$ SELECT * FROM defs.resources
-				WHERE resource_name_id = _get_string( 'test3' ) $$ ,
-		$$ VALUES ( _get_string( 'test3' ) , _get_string( 'test4' ) , _get_string( 'test7' ) , 1 ) $$
-	);
-	SELECT diag_test_name( 'defs.uoc_natres_internal() - update results with category - nat. res.' );
-	SELECT results_eq(
-		$$ SELECT * FROM defs.natural_resources
-				WHERE resource_name_id = _get_string( 'test3' ) $$ ,
-		$$ VALUES ( _get_string( 'test3' ) , 0.5::DOUBLE PRECISION , 100::DOUBLE PRECISION ,
-			50::DOUBLE PRECISION , 0.5::DOUBLE PRECISION , 0.05::DOUBLE PRECISION ,
-			0.5::DOUBLE PRECISION , 0.05::DOUBLE PRECISION ) $$
-	);
-
-	SELECT diag_test_name( 'defs.uoc_natres_internal() - incorrect name string' );
-	SELECT is( defs.uoc_natres_internal( 'does-not-exist' , 'test2' , NULL , 1 ,
-		0.5 , 100 , 50 , 0.5 , 0.05 , 0.5 , 0.05 ) , 'BAD_STRINGS' );
-	SELECT diag_test_name( 'defs.uoc_natres_internal() - incorrect description string' );
-	SELECT is( defs.uoc_natres_internal( 'test1' , 'does-not-exist' , NULL , 1 ,
-		0.5 , 100 , 50 , 0.5 , 0.05 , 0.5 , 0.05 ) , 'BAD_STRINGS' );
-	SELECT diag_test_name( 'defs.uoc_natres_internal() - incorrect category string' );
-	SELECT is( defs.uoc_natres_internal( 'test1' , 'test2' , 'does-not-exist' , 1 ,
-		0.5 , 100 , 50 , 0.5 , 0.05 , 0.5 , 0.05 ) , 'BAD_STRINGS' );
-
-	SELECT diag_test_name( 'defs.uoc_natres_internal() - duplicate description on new resource' );
-	SELECT is( defs.uoc_natres_internal( 'test1' , 'test4' , NULL , 1 ,
-		0.5 , 100 , 50 , 0.5 , 0.05 , 0.5 , 0.05 ) , 'DUP_DESCR' );
-	SELECT diag_test_name( 'defs.uoc_natres_internal() - duplicate description on existing resource' );
-	SELECT is( defs.uoc_natres_internal( 'test5' , 'test4' , NULL , 1 ,
-		0.5 , 100 , 50 , 0.5 , 0.05 , 0.5 , 0.05 ) , 'DUP_DESCR' );
-
-	SELECT diag_test_name( 'defs.uoc_natres_internal() - update on basic resource' );
-	SELECT is( defs.uoc_natres_internal( 'basicRes1' , 'test2' , NULL , 1 ,
-		0.5 , 100 , 50 , 0.5 , 0.05 , 0.5 , 0.05 ) , 'BAD_TYPE' );
-
-	SELECT diag_test_name( 'defs.uoc_natres_internal() - weight <= 0' );
-	SELECT is( defs.uoc_natres_internal( 'test5' , 'test2' , NULL , 0 ,
-		0.5 , 100 , 50 , 0.5 , 0.05 , 0.5 , 0.05 ) , 'BAD_VALUE' );
-
-	SELECT diag_test_name( 'defs.uoc_natres_internal() - P(presence) <= 0' );
-	SELECT is( defs.uoc_natres_internal( 'test5' , 'test2' , NULL , 1 ,
-		0 , 100 , 50 , 0.5 , 0.05 , 0.5 , 0.05 ) , 'BAD_VALUE' );
-	SELECT diag_test_name( 'defs.uoc_natres_internal() - P(presence) >= 1' );
-	SELECT is( defs.uoc_natres_internal( 'test5' , 'test2' , NULL , 1 ,
-		0 , 100 , 50 , 0.5 , 0.05 , 0.5 , 0.05 ) , 'BAD_VALUE' );
-
-	SELECT diag_test_name( 'defs.uoc_natres_internal() - max. quantity <= 0' );
-	SELECT is( defs.uoc_natres_internal( 'test5' , 'test2' , NULL , 1 ,
-		0.5 , 0 , 50 , 0.5 , 0.05 , 0.5 , 0.05 ) , 'BAD_VALUE' );
-	SELECT diag_test_name( 'defs.uoc_natres_internal() - quantity dev. < 0' );
-	SELECT is( defs.uoc_natres_internal( 'test5' , 'test2' , NULL , 1 ,
-		0.5 , 100 , -1 , 0.5 , 0.05 , 0.5 , 0.05 ) , 'BAD_VALUE' );
-	SELECT diag_test_name( 'defs.uoc_natres_internal() - quantity max. - dev. <= 0' );
-	SELECT is( defs.uoc_natres_internal( 'test5' , 'test2' , NULL , 1 ,
-		0.5 , 100 , 100 , 0.5 , 0.05 , 0.5 , 0.05 ) , 'BAD_VALUE' );
-
-	SELECT diag_test_name( 'defs.uoc_natres_internal() - difficulty max. = 0' );
-	SELECT is( defs.uoc_natres_internal( 'test5' , 'test2' , NULL , 1 ,
-		0.5 , 100 , 50 , 0 , 0 , 0.5 , 0.05 ) , 'UPDATED' );
-	SELECT diag_test_name( 'defs.uoc_natres_internal() - difficulty max. < 0' );
-	SELECT is( defs.uoc_natres_internal( 'test5' , 'test2' , NULL , 1 ,
-		0.5 , 100 , 50 , -0.00001 , 0 , 0.5 , 0.05 ) , 'BAD_VALUE' );
-	SELECT diag_test_name( 'defs.uoc_natres_internal() - difficulty max. = 1' );
-	SELECT is( defs.uoc_natres_internal( 'test5' , 'test2' , NULL , 1 ,
-		0.5 , 100 , 50 , 1 , 0 , 0.5 , 0.05 ) , 'UPDATED' );
-	SELECT diag_test_name( 'defs.uoc_natres_internal() - difficulty max. > 1' );
-	SELECT is( defs.uoc_natres_internal( 'test5' , 'test2' , NULL , 1 ,
-		0.5 , 100 , 50 , 1.00001 , 0 , 0.5 , 0.05 ) , 'BAD_VALUE' );
-	SELECT diag_test_name( 'defs.uoc_natres_internal() - difficulty dev. < 0' );
-	SELECT is( defs.uoc_natres_internal( 'test5' , 'test2' , NULL , 1 ,
-		0.5 , 100 , 50 , 0.5 , -1 , 0.5 , 0.05 ) , 'BAD_VALUE' );
-	SELECT diag_test_name( 'defs.uoc_natres_internal() - difficulty max. - dev. < 0' );
-	SELECT is( defs.uoc_natres_internal( 'test5' , 'test2' , NULL , 1 ,
-		0.5 , 100 , 50 , 0.25 , 0.5 , 0.5 , 0.05 ) , 'BAD_VALUE' );
-	SELECT diag_test_name( 'defs.uoc_natres_internal() - difficulty max. + dev. > 1' );
-	SELECT is( defs.uoc_natres_internal( 'test5' , 'test2' , NULL , 1 ,
-		0.5 , 100 , 50 , 0.75 , 0.5 , 0.5 , 0.05 ) , 'BAD_VALUE' );
-
-	SELECT diag_test_name( 'defs.uoc_natres_internal() - recovery max. <= 0' );
-	SELECT is( defs.uoc_natres_internal( 'test5' , 'test2' , NULL , 1 ,
-		0.5 , 100 , 50 , 0.5 , 0.05 , 0 , 0 ) , 'BAD_VALUE' );
-	SELECT diag_test_name( 'defs.uoc_natres_internal() - recovery max. = 1' );
-	SELECT is( defs.uoc_natres_internal( 'test5' , 'test2' , NULL , 1 ,
-		0.5 , 100 , 50 , 0.5 , 0.05 , 1 , 0 ) , 'UPDATED' );
-	SELECT diag_test_name( 'defs.uoc_natres_internal() - recovery max. > 1' );
-	SELECT is( defs.uoc_natres_internal( 'test5' , 'test2' , NULL , 1 ,
-		0.5 , 100 , 50 , 0.5 , 0.05 , 1.0001 , 0 ) , 'BAD_VALUE' );
-	SELECT diag_test_name( 'defs.uoc_natres_internal() - recovery dev. < 0' );
-	SELECT is( defs.uoc_natres_internal( 'test5' , 'test2' , NULL , 1 ,
-		0.5 , 100 , 50 , 0.5 , 0.05 , 0.5 , -0.25 ) , 'BAD_VALUE' );
-	SELECT diag_test_name( 'defs.uoc_natres_internal() - recovery max. - dev. <= 0' );
-	SELECT is( defs.uoc_natres_internal( 'test5' , 'test2' , NULL , 1 ,
-		0.5 , 100 , 50 , 0.5 , 0.05 , 0.25 , 0.25 ) , 'BAD_VALUE' );
-	SELECT diag_test_name( 'defs.uoc_natres_internal() - recovery max. + dev. > 1' );
-	SELECT is( defs.uoc_natres_internal( 'test5' , 'test2' , NULL , 1 ,
-		0.5 , 100 , 50 , 0.5 , 0.05 , 0.75 , 0.5 ) , 'BAD_VALUE' );
-
-	/* Reset resources, create temporary table, replace
-	 * defs.add_resource_records() to make sure it's called when needed (and
-	 * only then)
-	 */
-	DELETE FROM defs.natural_resources;
-	DELETE FROM defs.resources;
-	CREATE TEMPORARY TABLE arr_called( on_id INT ) ON COMMIT DROP;
-	CREATE OR REPLACE FUNCTION defs.add_resource_records( _resource INT )
-		RETURNS VOID
-		STRICT VOLATILE
-		SECURITY INVOKER
-	AS $$
-		INSERT INTO arr_called VALUES( $1 );
-	$$ LANGUAGE SQL;
-	ALTER TABLE emp.empires
-		DROP CONSTRAINT fk_empires_name;
-	INSERT INTO emp.empires ( name_id , cash )
-		VALUES ( 1 , 0 );
-
-	SELECT diag_test_name( 'defs.uoc_natres_internal() - defs.add_resource_record() called on new resource' );
-	SELECT defs.uoc_natres_internal( 'test1' , 'test2' , NULL , 1 ,
-		0.5 , 100 , 50 , 0.5 , 0.05 , 0.5 , 0.05 );
-	SELECT is( COUNT(*)::INT , 1 )
-		FROM arr_called
-		WHERE on_id = _get_string( 'test1' );
-	DELETE FROM arr_called;
-
-	SELECT diag_test_name( 'defs.uoc_natres_internal() - defs.add_resource_record() not called on resource update' );
-	SELECT defs.uoc_natres_internal( 'test1' , 'test3' , NULL , 1 ,
-		0.5 , 100 , 50 , 0.5 , 0.05 , 0.5 , 0.05 );
-	SELECT is( COUNT(*)::INT , 0 )
-		FROM arr_called
-		WHERE on_id = _get_string( 'test1' );
-
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/admin/040-functions/025-resources/040-uoc-natural-resource.sql b/legacyworlds-server-data/db-structure/tests/admin/040-functions/025-resources/040-uoc-natural-resource.sql
deleted file mode 100644
index b27130c..0000000
--- a/legacyworlds-server-data/db-structure/tests/admin/040-functions/025-resources/040-uoc-natural-resource.sql
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Test the defs.uoc_natural_resource() functions
- */
-BEGIN;
-	/* Create a fake internal function that will just push its parameters to
-	 * a temporary table.
-	 */
-	CREATE TEMPORARY TABLE calls_to_internal(
-		name TEXT ,
-		description TEXT ,
-		category TEXT ,
-		weight INT ,
-		presence DOUBLE PRECISION ,
-		quantity_avg DOUBLE PRECISION ,
-		quantity_dev DOUBLE PRECISION ,
-		difficulty_avg DOUBLE PRECISION ,
-		difficulty_dev DOUBLE PRECISION ,
-		recovery_avg DOUBLE PRECISION ,
-		recovery_dev DOUBLE PRECISION
-	) ON COMMIT DROP;
-	CREATE OR REPLACE FUNCTION defs.uoc_natres_internal(
-				_name TEXT ,
-				_description TEXT ,
-				_category TEXT ,
-				_weight INT ,
-				_presence DOUBLE PRECISION ,
-				_quantity_avg DOUBLE PRECISION ,
-				_quantity_dev DOUBLE PRECISION ,
-				_difficulty_avg DOUBLE PRECISION ,
-				_difficulty_dev DOUBLE PRECISION ,
-				_recovery_avg DOUBLE PRECISION ,
-				_recovery_dev DOUBLE PRECISION )
-		RETURNS defs.resource_update_result
-		CALLED ON NULL INPUT
-		VOLATILE
-		SECURITY INVOKER
-	AS $$
-		INSERT INTO calls_to_internal VALUES (
-			$1 , $2 , CASE WHEN $3 IS NULL THEN 'NULL' ELSE $3 END , $4 ,
-			$5 , $6 , $7 , $8 , $9 , $10 , $11
-		);
-		SELECT 'BAD_STRINGS'::defs.resource_update_result;
-	$$ LANGUAGE SQL;
-
-
-	/****** TESTS BEGIN HERE ******/
-	SELECT plan( 2 );
-
-	SELECT diag_test_name( 'defs.uoc_natural_resource() - Calls internal function (without category)' );
-	SELECT defs.uoc_natural_resource( 'a' , 'b' , 1 , 0.1 , 0.2 , 0.3 , 0.4 , 0.5 , 0.6 , 0.7 );
-	SELECT set_eq(
-		$$ SELECT * FROM calls_to_internal; $$ ,
-		$$ VALUES( 'a' , 'b' , 'NULL' , 1 , 0.1 , 0.2 , 0.3 , 0.4 , 0.5 , 0.6 , 0.7 ) $$
-	);
-	DELETE FROM calls_to_internal;
-
-	SELECT diag_test_name( 'defs.uoc_natural_resource() - Calls internal function (with category)' );
-	SELECT defs.uoc_natural_resource( 'a' , 'b' , 'c' , 1 , 0.1 , 0.2 , 0.3 , 0.4 , 0.5 , 0.6 , 0.7 );
-	SELECT set_eq(
-		$$ SELECT * FROM calls_to_internal; $$ ,
-		$$ VALUES( 'a' , 'b' , 'c' , 1 , 0.1 , 0.2 , 0.3 , 0.4 , 0.5 , 0.6 , 0.7 ) $$
-	);
-	DELETE FROM calls_to_internal;
-
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/admin/040-functions/025-resources/050-resource-category-weight-view.sql b/legacyworlds-server-data/db-structure/tests/admin/040-functions/025-resources/050-resource-category-weight-view.sql
deleted file mode 100644
index f5a59ba..0000000
--- a/legacyworlds-server-data/db-structure/tests/admin/040-functions/025-resources/050-resource-category-weight-view.sql
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Tests for defs.resource_category_weight_view
- */
-BEGIN;
-	/*
-	 * We need a few resources, with a known average per category. Some of the
-	 * resources must not belong to any category.
-	 */
-	\i utils/strings.sql
-	SELECT _create_test_strings( 5 , 'resource' );
-	SELECT _create_test_strings( 5 , 'resDesc' );
-	SELECT _create_test_strings( 2 , 'resCat' );
-	
-	INSERT INTO defs.resources(
-			resource_name_id , resource_description_id ,
-			resource_category_id , resource_weight
-		) VALUES (
-			_get_string( 'resource1' ) , _get_string( 'resDesc1' ) ,
-			_get_string( 'resCat1' ) , 2
-		) , (
-			_get_string( 'resource2' ) , _get_string( 'resDesc2' ) ,
-			_get_string( 'resCat1' ) , 4
-		) , (
-			_get_string( 'resource3' ) , _get_string( 'resDesc3' ) ,
-			_get_string( 'resCat2' ) , 3
-		) , (
-			_get_string( 'resource4' ) , _get_string( 'resDesc4' ) ,
-			_get_string( 'resCat2' ) , 5
-		) , (
-			_get_string( 'resource5' ) , _get_string( 'resDesc5' ) ,
-			NULL , 150
-		);
-
-	SELECT plan( 1 );
-	
-	SELECT diag_test_name( 'defs.resource_category_weight_view - Resulting set contains correct values' );
-	SELECT set_eq(
-		$$ SELECT * FROM defs.resource_category_weight_view $$ ,
-		$$ VALUES (
-			_get_string( 'resCat1' ) , 3
-		) , (
-			_get_string( 'resCat2' ) , 4
-		) $$
-	);
-
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/admin/040-functions/025-resources/060-ordered-resources-view.sql b/legacyworlds-server-data/db-structure/tests/admin/040-functions/025-resources/060-ordered-resources-view.sql
deleted file mode 100644
index aecee23..0000000
--- a/legacyworlds-server-data/db-structure/tests/admin/040-functions/025-resources/060-ordered-resources-view.sql
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Tests for defs.ordered_resources_view
- */
-BEGIN;
-
-	/* 
-	 * We need:
-	 *  - one resource without category with weight 1,
-	 *  - one resource with category 1 and weight 2,
-	 *  - one resource with weight 4 and no category,
-	 *  - two resourcew with weights 3 and 7 and category 2.
-	 */
-	\i utils/strings.sql
-	SELECT _create_test_strings( 5 , 'resource' );
-	SELECT _create_test_strings( 5 , 'resDesc' );
-	SELECT _create_test_strings( 2 , 'resCat' );
-	
-	INSERT INTO defs.resources(
-			resource_name_id , resource_description_id ,
-			resource_category_id , resource_weight
-		) VALUES (
-			_get_string( 'resource1' ) , _get_string( 'resDesc1' ) ,
-			NULL , 1
-		) , (
-			_get_string( 'resource2' ) , _get_string( 'resDesc2' ) ,
-			_get_string( 'resCat1' ) , 2
-		) , (
-			_get_string( 'resource3' ) , _get_string( 'resDesc3' ) ,
-			NULL , 4
-		) , (
-			_get_string( 'resource4' ) , _get_string( 'resDesc4' ) ,
-			_get_string( 'resCat2' ) , 3
-		) , (
-			_get_string( 'resource5' ) , _get_string( 'resDesc5' ) ,
-			_get_string( 'resCat2' ) , 7
-		);
-
-	SELECT plan( 1 );
-	SELECT diag_test_name( 'defs.ordered_resources_view - Resources are in the correct order' );
-	SELECT set_eq(
-		$$ SELECT resource_name_id , resource_ordering
-				FROM defs.ordered_resources_view $$ ,
-		$$ VALUES (
-			_get_string( 'resource1' ) , 1 
-		) , (
-			_get_string( 'resource2' ) , 2 
-		) , (
-			_get_string( 'resource3' ) , 3 
-		) , (
-			_get_string( 'resource4' ) , 4 
-		) , (
-			_get_string( 'resource5' ) , 5 
-		) $$
-	);
-
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/admin/040-functions/026-technology-dependencies/010-technologies-cache-entries.sql b/legacyworlds-server-data/db-structure/tests/admin/040-functions/026-technology-dependencies/010-technologies-cache-entries.sql
deleted file mode 100644
index 13dd5fb..0000000
--- a/legacyworlds-server-data/db-structure/tests/admin/040-functions/026-technology-dependencies/010-technologies-cache-entries.sql
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Make sure that inserting new technologies create corresponding dependency
- * cache entries, and that these entries are deleted along with the
- * technologies.
- */
-BEGIN;
-	\i utils/strings.sql
-
-	-- Make the columns we don't use in the technology definition table NULL-able
-	ALTER TABLE defs.technologies
-		ALTER technology_category_id DROP NOT NULL ,
-		ALTER technology_discovery_id DROP NOT NULL ,
-		ALTER technology_description_id DROP NOT NULL ,
-		ALTER technology_price DROP NOT NULL ,
-		ALTER technology_points DROP NOT NULL;
-
-	-- Create a string to use as the technology's name
-	SELECT _create_test_strings( 1 , 'tech' );
-	
-	-- Insert the new technology
-	INSERT INTO defs.technologies ( technology_name_id )
-		VALUES ( _get_string( 'tech1' ) );
-
-	-- ***** TESTS BEGIN HERE *****
-	SELECT plan( 2 );
-
-	SELECT diag_test_name( 'defs.technologies - Inserting creates cache entries' );
-	SELECT set_eq( $$
-		SELECT tdcache_reverse , ( tdcache_id_parent IS NULL ) AS no_parent ,
-					tdcache_depth , technology_name_id_copyof ,
-					( tdcache_id_copyof IS NULL ) AS not_a_copy ,
-					( techdep_id IS NULL ) AS not_a_dependency
-				FROM defs.techdep_cache
-				WHERE technology_name_id = _get_string( 'tech1' );
-	$$ , $$ VALUES (
-			FALSE , TRUE , 0 , _get_string( 'tech1' ) , TRUE , TRUE
-		) , (
-			TRUE , TRUE , 0 , _get_string( 'tech1' ) , TRUE , TRUE
-	) $$ );
-
-	SELECT diag_test_name( 'defs.technologies - Cache entries are deleted along with technologies' );
-	DELETE FROM defs.technologies WHERE technology_name_id = _get_string( 'tech1' );
-	SELECT is_empty( $$
-		SELECT * FROM defs.techdep_cache
-				WHERE technology_name_id = _get_string( 'tech1' );
-	$$ );
-
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/admin/040-functions/026-technology-dependencies/020-techdeps-cache-entries.sql b/legacyworlds-server-data/db-structure/tests/admin/040-functions/026-technology-dependencies/020-techdeps-cache-entries.sql
deleted file mode 100644
index af056ca..0000000
--- a/legacyworlds-server-data/db-structure/tests/admin/040-functions/026-technology-dependencies/020-techdeps-cache-entries.sql
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Make sure that inserting technology dependencies results in new entries in
- * the cache, and that the amount of entries in the cache grows according to
- * predictions.
- */
-BEGIN;
-	\i utils/strings.sql
-
-	-- Make the columns we don't use in the technology definition table NULL-able
-	ALTER TABLE defs.technologies
-		ALTER technology_category_id DROP NOT NULL ,
-		ALTER technology_discovery_id DROP NOT NULL ,
-		ALTER technology_description_id DROP NOT NULL ,
-		ALTER technology_price DROP NOT NULL ,
-		ALTER technology_points DROP NOT NULL;
-
-	-- Create a string to use as the technologies' names
-	SELECT _create_test_strings( 4 , 'tech' );
-	
-	-- Insert the technologies
-	INSERT INTO defs.technologies ( technology_name_id )
-		VALUES ( _get_string( 'tech1' ) ) , ( _get_string( 'tech2' ) ) ,
-				( _get_string( 'tech3' ) ) , ( _get_string( 'tech4' ) );
-
-	-- ***** TESTS BEGIN HERE *****
-	SELECT plan( 3 );
-
-	INSERT INTO defs.technology_dependencies ( technology_name_id , technology_name_id_depends )
-		VALUES ( _get_string( 'tech2' ) , _get_string( 'tech1' ) );
-	SELECT diag_test_name( 'defs.technology_dependencies - Dependencies create cache entries' );
-	SELECT set_eq( $$
-		SELECT technology_name_id , tdcache_reverse ,
-				( tdcache_id_parent IS NULL ) AS no_parent ,
-				tdcache_depth , technology_name_id_copyof ,
-				( tdcache_id_copyof IS NULL ) AS not_a_copy ,
-				( techdep_id IS NULL ) AS not_a_dependency
-			FROM defs.techdep_cache
-			WHERE technology_name_id IN ( _get_string( 'tech1' ) , _get_string( 'tech2' ) );
-	$$ , $$ VALUES (
-			_get_string( 'tech1' ) , FALSE , TRUE , 0 , _get_string( 'tech1' ) , TRUE , TRUE
-		) , (
-			_get_string( 'tech1' ) , TRUE , TRUE , 0 , _get_string( 'tech1' ) , TRUE , TRUE
-		) , (
-			_get_string( 'tech1' ) , TRUE , FALSE , 1 , _get_string( 'tech2' ) , FALSE , FALSE
-		) , (
-			_get_string( 'tech2' ) , TRUE , TRUE , 0 , _get_string( 'tech2' ) , TRUE , TRUE
-		) , (
-			_get_string( 'tech2' ) , FALSE , TRUE , 0 , _get_string( 'tech2' ) , TRUE , TRUE
-		) , (
-			_get_string( 'tech2' ) , FALSE , FALSE , 1 , _get_string( 'tech1' ) , FALSE , FALSE
-	) $$ );
-
-
-	DELETE FROM defs.technology_dependencies WHERE technology_name_id = _get_string( 'tech2' );
-	SELECT diag_test_name( 'defs.technologies - Cache entries are deleted along with dependencies' );
-	SELECT is_empty( $$
-		SELECT * FROM defs.techdep_cache
-			WHERE technology_name_id IN ( _get_string( 'tech1' ) , _get_string( 'tech2' ) )
-				AND tdcache_depth > 0;
-	$$ );
-
-	
-	/* Now insert the following dependencies:
-	 *	tech4 -> {tech3 , tech2}
-	 *	tech3 -> {tech1}
-	 *	tech2 -> {tech1}
-	 */
-	INSERT INTO defs.technology_dependencies ( technology_name_id , technology_name_id_depends )
-		VALUES ( _get_string( 'tech4' ) , _get_string( 'tech3' ) ) ,
-				( _get_string( 'tech4' ) , _get_string( 'tech2' ) ) ,
-				( _get_string( 'tech3' ) , _get_string( 'tech1' ) ) ,
-				( _get_string( 'tech2' ) , _get_string( 'tech1' ) );
-
-	/* Then check the amount of cache entries, as described below:
-	 *
-	 *	technology		reverse			entries / copies
-	 * ------------------------------------------------
-	 *	tech1			yes				5 / 4
-	 *	tech1			no				1 / 0
-	 *	tech2			yes				2 / 1
-	 *	tech2			no				2 / 1
-	 *	tech3			yes				2 / 1
-	 *	tech3			no				2 / 1
-	 *	tech4			yes				1 / 0
-	 *	tech4			no				5 / 4
-	 */
-	SELECT set_eq( $$
-		SELECT technology_name_id , tdcache_reverse ,
-				COUNT(*) AS total , COUNT( tdcache_id_copyof ) AS copies
-			FROM defs.techdep_cache
-			WHERE technology_name_id IN (
-					_get_string( 'tech1' ) , _get_string( 'tech2' ) ,
-					_get_string( 'tech3' ) , _get_string( 'tech4' )
-				)
-			GROUP BY technology_name_id , tdcache_reverse;
-	$$ , $$ VALUES (
-			_get_string( 'tech1' ) , TRUE , 5 , 4
-		) , (
-			_get_string( 'tech1' ) , FALSE , 1 , 0
-		) , (
-			_get_string( 'tech2' ) , TRUE , 2 , 1
-		) , (
-			_get_string( 'tech2' ) , FALSE , 2 , 1
-		) , (
-			_get_string( 'tech3' ) , TRUE , 2 , 1
-		) , (
-			_get_string( 'tech3' ) , FALSE , 2 , 1
-		) , (
-			_get_string( 'tech4' ) , TRUE , 1 , 0
-		) , (
-			_get_string( 'tech4' ) , FALSE , 5 , 4
-	) $$ );
-
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/admin/040-functions/026-technology-dependencies/030-techdeps-cycles.sql b/legacyworlds-server-data/db-structure/tests/admin/040-functions/026-technology-dependencies/030-techdeps-cycles.sql
deleted file mode 100644
index 7f0917f..0000000
--- a/legacyworlds-server-data/db-structure/tests/admin/040-functions/026-technology-dependencies/030-techdeps-cycles.sql
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Make sure that it is not possible to create cycles in dependencies.
- */
-BEGIN;
-	\i utils/strings.sql
-	-- Make the columns we don't use in the technology definition table NULL-able
-	ALTER TABLE defs.technologies
-		ALTER technology_category_id DROP NOT NULL ,
-		ALTER technology_discovery_id DROP NOT NULL ,
-		ALTER technology_description_id DROP NOT NULL ,
-		ALTER technology_price DROP NOT NULL ,
-		ALTER technology_points DROP NOT NULL;
-
-	-- Create strings to use as the technologies' names
-	SELECT _create_test_strings( 3 , 'tech' );
-	
-	-- Insert the technologies
-	INSERT INTO defs.technologies ( technology_name_id )
-		VALUES ( _get_string( 'tech1' ) ) ,
-				( _get_string( 'tech2' ) ) ,
-				( _get_string( 'tech3' ) );
-
-	-- ***** TESTS BEGIN HERE *****
-	SELECT plan( 3 );
-	
-	SELECT diag_test_name( 'defs.technology_dependencies - Dependency from A to A is rejected' );
-	SELECT throws_ok( $$
-		INSERT INTO defs.technology_dependencies ( technology_name_id , technology_name_id_depends )
-			VALUES ( _get_string( 'tech1' ) , _get_string( 'tech1' ) );
-	$$ , 23514 );
-
-	SELECT diag_test_name( 'defs.technology_dependencies - Direct dependency from A to B to A is rejected' );
-	INSERT INTO defs.technology_dependencies ( technology_name_id , technology_name_id_depends )
-		VALUES ( _get_string( 'tech2' ) , _get_string( 'tech1' ) );
-	SELECT throws_ok( $$
-		INSERT INTO defs.technology_dependencies ( technology_name_id , technology_name_id_depends )
-			VALUES ( _get_string( 'tech1' ) , _get_string( 'tech2' ) );
-	$$ , 23514 );
-
-	SELECT diag_test_name( 'defs.technology_dependencies - Indirect dependency from A to B to A is rejected' );
-	INSERT INTO defs.technology_dependencies ( technology_name_id , technology_name_id_depends )
-		VALUES ( _get_string( 'tech3' ) , _get_string( 'tech2' ) );
-	SELECT throws_ok( $$
-		INSERT INTO defs.technology_dependencies ( technology_name_id , technology_name_id_depends )
-			VALUES ( _get_string( 'tech1' ) , _get_string( 'tech3' ) );
-	$$ , 23514 );
-
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/admin/040-functions/026-technology-dependencies/040-techdeps-redundancy.sql b/legacyworlds-server-data/db-structure/tests/admin/040-functions/026-technology-dependencies/040-techdeps-redundancy.sql
deleted file mode 100644
index c065f02..0000000
--- a/legacyworlds-server-data/db-structure/tests/admin/040-functions/026-technology-dependencies/040-techdeps-redundancy.sql
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Make sure that it is not possible to create redundant dependencies
- */
-BEGIN;
-	\i utils/strings.sql
-	-- Make the columns we don't use in the technology definition table NULL-able
-	ALTER TABLE defs.technologies
-		ALTER technology_category_id DROP NOT NULL ,
-		ALTER technology_discovery_id DROP NOT NULL ,
-		ALTER technology_description_id DROP NOT NULL ,
-		ALTER technology_price DROP NOT NULL ,
-		ALTER technology_points DROP NOT NULL;
-
-	-- Create strings to use as the technologies' names
-	SELECT _create_test_strings( 3 , 'tech' );
-	
-	-- Insert the technologies
-	INSERT INTO defs.technologies ( technology_name_id )
-		VALUES ( _get_string( 'tech1' ) ) ,
-				( _get_string( 'tech2' ) ) ,
-				( _get_string( 'tech3' ) );
-
-	-- ***** TESTS BEGIN HERE *****
-	SELECT plan( 5 );
-
-	/*
-	 * Assuming we have tech2 -> {tech1} and tech3 -> {tech1}, it shouldn't be
-	 * possible to add dependencies between tech2 and tech3.
-	 */
-	INSERT INTO defs.technology_dependencies ( technology_name_id , technology_name_id_depends )
-		VALUES ( _get_string( 'tech2' ) , _get_string( 'tech1' ) ) ,
-				( _get_string( 'tech3' ) , _get_string( 'tech1' ) ); 
-	SELECT diag_test_name( 'defs.technology_dependencies - B -> A and C -> A, adding B -> C is redundant' );
-	SELECT throws_ok( $$
-		INSERT INTO defs.technology_dependencies ( technology_name_id , technology_name_id_depends )
-			VALUES ( _get_string( 'tech2' ) , _get_string( 'tech3' ) );
-	$$ , 23514 );
-	SELECT diag_test_name( 'defs.technology_dependencies - B -> A and C -> A, adding C -> B is redundant' );
-	SELECT throws_ok( $$
-		INSERT INTO defs.technology_dependencies ( technology_name_id , technology_name_id_depends )
-			VALUES ( _get_string( 'tech3' ) , _get_string( 'tech2' ) );
-	$$ , 23514 );
-	DELETE FROM defs.technology_dependencies;
-
-	/*
-	 * Assuming we have tech3 -> {tech2,tech1}, trying to add a dependency
-	 * between tech2 and tech1 would cause a redundancy.
-	 */
-	INSERT INTO defs.technology_dependencies ( technology_name_id , technology_name_id_depends )
-		VALUES ( _get_string( 'tech3' ) , _get_string( 'tech1' ) ) ,
-				( _get_string( 'tech3' ) , _get_string( 'tech2' ) ); 
-	SELECT diag_test_name( 'defs.technology_dependencies - C -> A and C -> B, adding A -> B is redundant' );
-	SELECT throws_ok( $$
-		INSERT INTO defs.technology_dependencies ( technology_name_id , technology_name_id_depends )
-			VALUES ( _get_string( 'tech1' ) , _get_string( 'tech2' ) );
-	$$ , 23514 );
-	SELECT diag_test_name( 'defs.technology_dependencies - C -> A and C -> B, adding B -> A is redundant' );
-	SELECT throws_ok( $$
-		INSERT INTO defs.technology_dependencies ( technology_name_id , technology_name_id_depends )
-			VALUES ( _get_string( 'tech2' ) , _get_string( 'tech1' ) );
-	$$ , 23514 );
-	DELETE FROM defs.technology_dependencies;
-
-	/*
-	 * Assuming we have tech3 -> {tech2} and tech2 -> {tech1}, trying to add a
-	 * dependency from tech3 to tech1 would cause a redundancy.
-	 */
-	INSERT INTO defs.technology_dependencies ( technology_name_id , technology_name_id_depends )
-		VALUES ( _get_string( 'tech3' ) , _get_string( 'tech2' ) ) ,
-				( _get_string( 'tech2' ) , _get_string( 'tech1' ) ); 
-	SELECT diag_test_name( 'defs.technology_dependencies - C -> B and B -> A, adding C -> A is redundant' );
-	SELECT throws_ok( $$
-		INSERT INTO defs.technology_dependencies ( technology_name_id , technology_name_id_depends )
-			VALUES ( _get_string( 'tech3' ) , _get_string( 'tech1' ) );
-	$$ , 23514 );
-	DELETE FROM defs.technology_dependencies;
-
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/admin/040-functions/026-technology-dependencies/050-technology-dependencies-view.sql b/legacyworlds-server-data/db-structure/tests/admin/040-functions/026-technology-dependencies/050-technology-dependencies-view.sql
deleted file mode 100644
index 879da1f..0000000
--- a/legacyworlds-server-data/db-structure/tests/admin/040-functions/026-technology-dependencies/050-technology-dependencies-view.sql
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Unit tests for defs.technology_dependencies_view
- */
-BEGIN;
-	\i utils/strings.sql
-	-- Make the columns we don't use in the technology definition table NULL-able
-	ALTER TABLE defs.technologies
-		ALTER technology_category_id DROP NOT NULL ,
-		ALTER technology_discovery_id DROP NOT NULL ,
-		ALTER technology_description_id DROP NOT NULL ,
-		ALTER technology_price DROP NOT NULL ,
-		ALTER technology_points DROP NOT NULL;
-
-	-- Create strings to use as the technologies' names
-	SELECT _create_test_strings( 4 , 'tech' );
-	
-	-- Insert the technologies
-	INSERT INTO defs.technologies ( technology_name_id )
-		VALUES ( _get_string( 'tech1' ) ) ,
-				( _get_string( 'tech2' ) ) ,
-				( _get_string( 'tech3' ) ) ,
-				( _get_string( 'tech4' ) );
-
-	-- Insert dependencies: tech3 -> {tech1,tech2} , tech4 -> {tech3}
-	INSERT INTO defs.technology_dependencies ( technology_name_id , technology_name_id_depends )
-		VALUES ( _get_string( 'tech3' ) , _get_string( 'tech1' ) ) ,
-			( _get_string( 'tech3' ) , _get_string( 'tech2' ) ) ,
-			( _get_string( 'tech4' ) , _get_string( 'tech3' ) );
-
-	-- ***** TESTS BEGIN HERE *****
-	SELECT plan( 3 );
-
-	SELECT diag_test_name( 'defs.technology_dependencies_view - Technologies with no dependencies' );
-	SELECT is( technology_dependencies , '' )
-		FROM defs.technology_dependencies_view
-		WHERE technology_name_id = _get_string( 'tech1' );
-
-	SELECT diag_test_name( 'defs.technology_dependencies_view - Technologies with a single dependency' );
-	SELECT is( technology_dependencies , 'tech3' )
-		FROM defs.technology_dependencies_view
-		WHERE technology_name_id = _get_string( 'tech4' );
-
-	SELECT diag_test_name( 'defs.technology_dependencies_view - Technologies with multiple dependencies' );
-	SELECT ok( technology_dependencies = 'tech1,tech2' OR technology_dependencies = 'tech2,tech1' )
-		FROM defs.technology_dependencies_view
-		WHERE technology_name_id = _get_string( 'tech3' );
-
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/admin/040-functions/030-tech/010-uoc-technology-create.sql b/legacyworlds-server-data/db-structure/tests/admin/040-functions/030-tech/010-uoc-technology-create.sql
deleted file mode 100644
index 3ac248f..0000000
--- a/legacyworlds-server-data/db-structure/tests/admin/040-functions/030-tech/010-uoc-technology-create.sql
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Test the defs.uoc_technology() function for new technologies
- */
-BEGIN;
-	\i utils/strings.sql
-
-	/*
-	 * We need a few test strings to play with. Each technology definition
-	 * uses four strings (name, category, discovery and description) so we'll
-	 * create 8.
-	 */
-	SELECT _create_test_strings( 8 , 's' );
-
-	/*
-	 * Manually insert an entry into the technologies table, using strings
-	 * 5-8 for the various fields.
-	 */
-	INSERT INTO defs.technologies (
-		technology_name_id , technology_category_id ,
-		technology_discovery_id , technology_description_id ,
-		technology_price , technology_points
-	) VALUES (
-		_get_string( 's5' ) , _get_string( 's6' ) ,
-		_get_string( 's7' ) , _get_string( 's8' ) ,
-		1 , 1
-	);
-
-	-- ***** TESTS BEGIN HERE *****
-	SELECT plan( 10 );
-
-	SELECT diag_test_name( 'defs.uoc_technology() - Creation - Invalid name string' );
-	SELECT is( defs.uoc_technology(
-			'does not exist' , 's2' , 's3' , 's4' , 1 , 1
-		)::TEXT , 'BAD_STRINGS' );
-
-	SELECT diag_test_name( 'defs.uoc_technology() - Creation - Invalid category string' );
-	SELECT is( defs.uoc_technology(
-			's1' , 'does not exist' , 's3' , 's4' , 1 , 1
-		)::TEXT , 'BAD_STRINGS' );
-
-	SELECT diag_test_name( 'defs.uoc_technology() - Creation - Invalid discovery string' );
-	SELECT is( defs.uoc_technology(
-			's1' , 's2' , 'does not exist' , 's4' , 1 , 1
-		)::TEXT , 'BAD_STRINGS' );
-
-	SELECT diag_test_name( 'defs.uoc_technology() - Creation - Invalid description string' );
-	SELECT is( defs.uoc_technology(
-			's1' , 's2' , 's3' , 'does not exist' , 1 , 1
-		)::TEXT , 'BAD_STRINGS' );
-
-	SELECT diag_test_name( 'defs.uoc_technology() - Creation - Invalid price' );
-	SELECT is( defs.uoc_technology(
-			's1' , 's2' , 's3' , 's4' , 0 , 1
-		)::TEXT , 'BAD_VALUE' );
-
-	SELECT diag_test_name( 'defs.uoc_technology() - Creation - Invalid research points' );
-	SELECT is( defs.uoc_technology(
-			's1' , 's2' , 's3' , 's4' , 1 , 0
-		)::TEXT , 'BAD_VALUE' );
-
-	SELECT diag_test_name( 'defs.uoc_technology() - Creation - Duplicate description string' );
-	SELECT is( defs.uoc_technology(
-			's1' , 's2' , 's7' , 's4' , 1 , 1
-		)::TEXT , 'DUP_STRING' );
-
-	SELECT diag_test_name( 'defs.uoc_technology() - Creation - Duplicate discovery string' );
-	SELECT is( defs.uoc_technology(
-			's1' , 's2' , 's3' , 's8' , 1 , 1
-		)::TEXT , 'DUP_STRING' );
-
-	SELECT diag_test_name( 'defs.uoc_technology() - Creation - Success' );
-	SELECT is( defs.uoc_technology(
-			's1' , 's2' , 's3' , 's4' , 2 , 3
-		)::TEXT , 'CREATED' );
-	SELECT diag_test_name( 'defs.uoc_technology() - Creation - Row exists after success' );
-	SELECT set_eq( $$
-		SELECT * FROM defs.technologies
-			WHERE technology_name_id = _get_string( 's1' )
-	$$ , $$ VALUES(
-			_get_string( 's1' ) , _get_string( 's2' ) ,
-			_get_string( 's3' ) , _get_string( 's4' ) ,
-			2 , 3
-	) $$ );
-
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/admin/040-functions/030-tech/020-uoc-technology-update.sql b/legacyworlds-server-data/db-structure/tests/admin/040-functions/030-tech/020-uoc-technology-update.sql
deleted file mode 100644
index 383e453..0000000
--- a/legacyworlds-server-data/db-structure/tests/admin/040-functions/030-tech/020-uoc-technology-update.sql
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Test the defs.uoc_technology() function for existing technologies
- */
-BEGIN;
-	\i utils/strings.sql
-
-	/*
-	 * We need a few test strings to play with. Each technology definition
-	 * uses four strings (name, category, discovery and description) so we'll
-	 * create 8.
-	 */
-	SELECT _create_test_strings( 8 , 's' );
-
-	/* Insert two entries. */
-	INSERT INTO defs.technologies (
-		technology_name_id , technology_category_id ,
-		technology_discovery_id , technology_description_id ,
-		technology_price , technology_points
-	) VALUES (
-		_get_string( 's1' ) , _get_string( 's2' ) ,
-		_get_string( 's3' ) , _get_string( 's4' ) ,
-		1 , 1
-	) , (
-		_get_string( 's5' ) , _get_string( 's6' ) ,
-		_get_string( 's7' ) , _get_string( 's8' ) ,
-		1 , 1
-	);
-
-	-- ***** TESTS BEGIN HERE *****
-	SELECT plan( 9 );
-
-	SELECT diag_test_name( 'defs.uoc_technology() - Update - Invalid category string' );
-	SELECT is( defs.uoc_technology(
-			's1' , 'does not exist' , 's3' , 's4' , 1 , 1
-		)::TEXT , 'BAD_STRINGS' );
-
-	SELECT diag_test_name( 'defs.uoc_technology() - Update - Invalid discovery string' );
-	SELECT is( defs.uoc_technology(
-			's1' , 's2' , 'does not exist' , 's4' , 1 , 1
-		)::TEXT , 'BAD_STRINGS' );
-
-	SELECT diag_test_name( 'defs.uoc_technology() - Update - Invalid description string' );
-	SELECT is( defs.uoc_technology(
-			's1' , 's2' , 's3' , 'does not exist' , 1 , 1
-		)::TEXT , 'BAD_STRINGS' );
-
-	SELECT diag_test_name( 'defs.uoc_technology() - Update - Invalid price' );
-	SELECT is( defs.uoc_technology(
-			's1' , 's2' , 's3' , 's4' , 0 , 1
-		)::TEXT , 'BAD_VALUE' );
-
-	SELECT diag_test_name( 'defs.uoc_technology() - Update - Invalid research points' );
-	SELECT is( defs.uoc_technology(
-			's1' , 's2' , 's3' , 's4' , 1 , 0
-		)::TEXT , 'BAD_VALUE' );
-
-	SELECT diag_test_name( 'defs.uoc_technology() - Update - Duplicate description string' );
-	SELECT is( defs.uoc_technology(
-			's1' , 's2' , 's7' , 's4' , 1 , 1
-		)::TEXT , 'DUP_STRING' );
-
-	SELECT diag_test_name( 'defs.uoc_technology() - Update - Duplicate discovery string' );
-	SELECT is( defs.uoc_technology(
-			's1' , 's2' , 's3' , 's8' , 1 , 1
-		)::TEXT , 'DUP_STRING' );
-
-	SELECT diag_test_name( 'defs.uoc_technology() - Update - Success' );
-	SELECT is( defs.uoc_technology(
-			's1' , 's4' , 's2' , 's3' , 2 , 3
-		)::TEXT , 'UPDATED' );
-	SELECT diag_test_name( 'defs.uoc_technology() - Update - Row contents after success' );
-	SELECT set_eq( $$
-		SELECT * FROM defs.technologies
-			WHERE technology_name_id = _get_string( 's1' )
-	$$ , $$ VALUES(
-			_get_string( 's1' ) , _get_string( 's4' ) ,
-			_get_string( 's2' ) , _get_string( 's3' ) ,
-			2 , 3
-	) $$ );
-
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/admin/040-functions/030-tech/030-uoc-technology-scale.sql b/legacyworlds-server-data/db-structure/tests/admin/040-functions/030-tech/030-uoc-technology-scale.sql
deleted file mode 100644
index 79722fa..0000000
--- a/legacyworlds-server-data/db-structure/tests/admin/040-functions/030-tech/030-uoc-technology-scale.sql
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Test the defs.uoc_technology() function when the points for a technology
- * are updated and empires are researching it.
- */
-BEGIN;
-	\i utils/strings.sql
-
-	/*
-	 * We need a few test strings to play with. Each technology definition
-	 * uses four strings (name, category, discovery and description) so we'll
-	 * create 4.
-	 */
-	SELECT _create_test_strings( 4 , 's' );
-
-	/* Insert one entry. */
-	INSERT INTO defs.technologies (
-		technology_name_id , technology_category_id ,
-		technology_discovery_id , technology_description_id ,
-		technology_price , technology_points
-	) VALUES (
-		_get_string( 's1' ) , _get_string( 's2' ) ,
-		_get_string( 's3' ) , _get_string( 's4' ) ,
-		1 , 100
-	);
-	
-	/* Remove foreign key to empires on empire technologies */
-	ALTER TABLE emp.technologies
-		DROP CONSTRAINT fk_emptech_empire;
-
-	/* Insert records for the new technology, with different states */
-	INSERT INTO emp.technologies (
-		empire_id , technology_name_id , emptech_state ,
-		emptech_points , emptech_priority
-	) VALUES (
-		1 , _get_string( 's1' ) , 'RESEARCH' , 50 , 2
-	) , (
-		2 , _get_string( 's1' ) , 'RESEARCH' , 0 , 2
-	);
-	
-	/* Now change the technology so it requires 1000 points */
-	SELECT defs.uoc_technology( 's1' , 's2' , 's3' , 's4' , 1 , 1000 );
-
-	-- ***** TESTS BEGIN HERE *****
-	SELECT no_plan( );
-	
-	SELECT diag_test_name( 'defs.uoc_technology() - Update - Scaling of in-progress research' );
-	SELECT set_eq( $$
-		SELECT empire_id , ROUND( emptech_points )::INT
-			FROM emp.technologies
-			WHERE emptech_state = 'RESEARCH'
-	$$ , $$ VALUES(
-		1 , 500
-	) , (
-		2 , 0
-	) $$ );
-
-	SELECT * FROM finish( );
-ROLLBACK;
diff --git a/legacyworlds-server-data/db-structure/tests/admin/040-functions/030-tech/040-techdep-add.sql b/legacyworlds-server-data/db-structure/tests/admin/040-functions/030-tech/040-techdep-add.sql
deleted file mode 100644
index c5236f7..0000000
--- a/legacyworlds-server-data/db-structure/tests/admin/040-functions/030-tech/040-techdep-add.sql
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Test the defs.techdep_add() function
- */
-BEGIN;
-	\i utils/strings.sql
-	-- Make the columns we don't use in the technology definition table NULL-able
-	ALTER TABLE defs.technologies
-		ALTER technology_category_id DROP NOT NULL ,
-		ALTER technology_discovery_id DROP NOT NULL ,
-		ALTER technology_description_id DROP NOT NULL ,
-		ALTER technology_price DROP NOT NULL ,
-		ALTER technology_points DROP NOT NULL;
-
-	-- Create strings to use as the technologies' names
-	SELECT _create_test_strings( 5 , 'tech' );
-	
-	-- Insert the technologies
-	INSERT INTO defs.technologies ( technology_name_id )
-		VALUES ( _get_string( 'tech1' ) ) ,
-				( _get_string( 'tech2' ) ) ,
-				( _get_string( 'tech3' ) ) ,
-				( _get_string( 'tech4' ) );
-
-	-- Add a few dependencies
-	INSERT INTO defs.technology_dependencies(
-			technology_name_id , technology_name_id_depends
-		) VALUES ( _get_string( 'tech3' ) , _get_string( 'tech2' ) ) , 
-			( _get_string( 'tech2' ) , _get_string( 'tech1' ) );
-
-
-	-- ***** TESTS BEGIN HERE *****
-	SELECT plan( 8 );
-	
-	SELECT diag_test_name( 'defs.techdep_add() - Bad dependent technology name' );
-	SELECT is( defs.techdep_add( 'does not exist' , 'tech2' )::TEXT , 'BAD_STRINGS' );
-
-	SELECT diag_test_name( 'defs.techdep_add() - Bad dependency name' );
-	SELECT is( defs.techdep_add( 'tech1' , 'does not exist' )::TEXT , 'BAD_STRINGS' );
-	
-	SELECT diag_test_name( 'defs.techdep_add() - Valid name that is not a technology' );
-	SELECT is( defs.techdep_add( 'tech5' , 'tech2' )::TEXT , 'BAD_STRINGS' );
-
-	SELECT diag_test_name( 'defs.techdep_add() - Duplicate dependency' );
-	SELECT is( defs.techdep_add( 'tech3' , 'tech2' )::TEXT , 'REDUNDANT' );
-
-	SELECT diag_test_name( 'defs.techdep_add() - Cyclic dependency' );
-	SELECT is( defs.techdep_add( 'tech2' , 'tech3' )::TEXT , 'CYCLE' );
-
-	SELECT diag_test_name( 'defs.techdep_add() - Redundant dependency' );
-	SELECT is( defs.techdep_add( 'tech3' , 'tech1' )::TEXT , 'REDUNDANT' );
-
-	SELECT diag_test_name( 'defs.techdep_add() - Success - Return value' );
-	SELECT is( defs.techdep_add( 'tech4' , 'tech1' )::TEXT , 'CREATED' );
-
-	SELECT diag_test_name( 'defs.techdep_add() - Success - Table entries' );
-	SELECT set_eq( $$
-		SELECT technology_name_id_depends
-			FROM defs.technology_dependencies
-			WHERE technology_name_id = _get_string( 'tech4' );
-	$$ , $$ VALUES(
-		_get_string( 'tech1' )
-	) $$ );
-
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/admin/040-functions/030-tech/050-techdep-remove.sql b/legacyworlds-server-data/db-structure/tests/admin/040-functions/030-tech/050-techdep-remove.sql
deleted file mode 100644
index b7da5be..0000000
--- a/legacyworlds-server-data/db-structure/tests/admin/040-functions/030-tech/050-techdep-remove.sql
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Test the defs.techdep_remove() function
- */
-BEGIN;
-	\i utils/strings.sql
-	-- Make the columns we don't use in the technology definition table NULL-able
-	ALTER TABLE defs.technologies
-		ALTER technology_category_id DROP NOT NULL ,
-		ALTER technology_discovery_id DROP NOT NULL ,
-		ALTER technology_description_id DROP NOT NULL ,
-		ALTER technology_price DROP NOT NULL ,
-		ALTER technology_points DROP NOT NULL;
-
-	-- Create strings to use as the technologies' names
-	SELECT _create_test_strings( 2 , 'tech' );
-	
-	-- Insert the technologies
-	INSERT INTO defs.technologies ( technology_name_id )
-		VALUES ( _get_string( 'tech1' ) ) ,
-				( _get_string( 'tech2' ) );
-
-	-- Add a dependency from tech2 to tech1
-	INSERT INTO defs.technology_dependencies(
-			technology_name_id , technology_name_id_depends
-		) VALUES ( _get_string( 'tech2' ) , _get_string( 'tech1' ) );
-
-
-	-- ***** TESTS BEGIN HERE *****
-	SELECT plan( 5 );
-	
-	SELECT diag_test_name( 'defs.techdep_remove() - Bad dependent technology name' );
-	SELECT is( defs.techdep_remove( 'does not exist' , 'tech1' )::TEXT , 'MISSING' );
-
-	SELECT diag_test_name( 'defs.techdep_remove() - Bad dependency name' );
-	SELECT is( defs.techdep_remove( 'tech2' , 'does not exist' )::TEXT , 'MISSING' );
-
-	SELECT diag_test_name( 'defs.techdep_remove() - Correct name but no dependency' );
-	SELECT is( defs.techdep_remove( 'tech1' , 'tech2' )::TEXT , 'MISSING' );
-	
-	SELECT diag_test_name( 'defs.techdep_remove() - Success - Return value' );
-	SELECT is( defs.techdep_remove( 'tech2' , 'tech1' )::TEXT , 'DELETED' );
-	
-	SELECT diag_test_name( 'defs.techdep_remove() - Success - Table contents' );
-	SELECT is_empty($$
-		SELECT * FROM defs.technology_dependencies
-			WHERE technology_name_id = _get_string( 'tech2' )
-				AND technology_name_id_depends = _get_string( 'tech1' );
-	$$);
-
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/admin/040-functions/030-tech/060-techdep-clear.sql b/legacyworlds-server-data/db-structure/tests/admin/040-functions/030-tech/060-techdep-clear.sql
deleted file mode 100644
index ef2dacc..0000000
--- a/legacyworlds-server-data/db-structure/tests/admin/040-functions/030-tech/060-techdep-clear.sql
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Test the defs.techdep_clear() function
- */
-BEGIN;
-	\i utils/strings.sql
-	-- Make the columns we don't use in the technology definition table NULL-able
-	ALTER TABLE defs.technologies
-		ALTER technology_category_id DROP NOT NULL ,
-		ALTER technology_discovery_id DROP NOT NULL ,
-		ALTER technology_description_id DROP NOT NULL ,
-		ALTER technology_price DROP NOT NULL ,
-		ALTER technology_points DROP NOT NULL;
-
-	-- Create strings to use as the technologies' names
-	SELECT _create_test_strings( 4 , 'tech' );
-	
-	-- Insert the technologies
-	INSERT INTO defs.technologies ( technology_name_id )
-		VALUES ( _get_string( 'tech1' ) ) ,
-				( _get_string( 'tech2' ) ) ,
-				( _get_string( 'tech3' ) ) ,
-				( _get_string( 'tech4' ) );
-
-	-- Add a chain of dependencies
-	INSERT INTO defs.technology_dependencies(
-			technology_name_id , technology_name_id_depends
-		) VALUES ( _get_string( 'tech2' ) , _get_string( 'tech1' ) ) ,
-			 ( _get_string( 'tech3' ) , _get_string( 'tech2' ) ) ,
-			 ( _get_string( 'tech4' ) , _get_string( 'tech3' ) );
-
-
-	-- ***** TESTS BEGIN HERE *****
-	SELECT plan( 4 );
-	
-	SELECT diag_test_name( 'defs.techdep_clear() - No failure on invalid technology name' );
-	SELECT lives_ok( $$
-		SELECT defs.techdep_clear( 'does not exist' )
-	$$ );
-
-	SELECT diag_test_name( 'defs.techdep_clear() - Successful call' );
-	SELECT lives_ok( $$
-		SELECT defs.techdep_clear( 'tech2' )
-	$$ );
-	
-	SELECT diag_test_name( 'defs.techdep_clear() - Cleared technology has no dependencies' );
-	SELECT is_empty( $$
-		SELECT * FROM defs.technology_dependencies
-			WHERE technology_name_id = _get_string( 'tech2' );
-	$$ );
-	
-	SELECT diag_test_name( 'defs.techdep_clear() - Cleared technology has no reverse dependencies' );
-	SELECT is_empty( $$
-		SELECT * FROM defs.technology_dependencies
-			WHERE technology_name_id_depends = _get_string( 'tech2' );
-	$$ );
-
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/admin/040-functions/040-empire/010-create-empire.sql b/legacyworlds-server-data/db-structure/tests/admin/040-functions/040-empire/010-create-empire.sql
deleted file mode 100644
index 9f7ba70..0000000
--- a/legacyworlds-server-data/db-structure/tests/admin/040-functions/040-empire/010-create-empire.sql
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * Test the emp.create_empire() function
- */
-BEGIN;
-	/* We need a pair of natural resources, a basic resource, a planet
-	 * and an empire name. We add a resource provider to the planet.
-	 */
-	\i utils/strings.sql
-	\i utils/resources.sql
-	\i utils/accounts.sql
-	\i utils/naming.sql
-	\i utils/universe.sql
-	SELECT _create_natural_resources( 2 , 'natRes' );
-	SELECT _create_resources( 1 , 'basicRes' );
-	SELECT _create_raw_planets( 1 , 'testPlanet' );
-	SELECT _create_emp_names( 1 , 'testEmp' );
-	
-	INSERT INTO verse.planet_resources( planet_id , resource_name_id )
-		SELECT name_id , resource_name_id
-			FROM verse.planets CROSS JOIN defs.resources;
-
-	INSERT INTO verse.resource_providers (
-			planet_id , resource_name_id , resprov_quantity_max ,
-			resprov_quantity , resprov_difficulty , resprov_recovery
-		) VALUES (
-			_get_map_name( 'testPlanet1' ) , _get_string( 'natRes1' ) , 100 ,
-			100 , 0.2 , 0.5
-		);
-
-	/*
-	 * We also need 3 technologies (tech1, tech2 and tech3), and a chain of
-	 * dependencies between them (i.e. tech3 -> tech2 -> tech1). Disabling
-	 * unused fields in defs.technologies makes things easier.
-	 */
-	ALTER TABLE defs.technologies
-		ALTER technology_category_id DROP NOT NULL ,
-		ALTER technology_discovery_id DROP NOT NULL ,
-		ALTER technology_description_id DROP NOT NULL ,
-		ALTER technology_price DROP NOT NULL ,
-		ALTER technology_points DROP NOT NULL;
-	SELECT _create_test_strings( 3 , 'tech' );
-	INSERT INTO defs.technologies ( technology_name_id )
-		VALUES ( _get_string( 'tech1' ) ) ,
-				( _get_string( 'tech2' ) ) ,
-				( _get_string( 'tech3' ) );
-	INSERT INTO defs.technology_dependencies(
-			technology_name_id , technology_name_id_depends
-		) VALUES ( _get_string( 'tech2' ) , _get_string( 'tech1' ) ) ,
-			 ( _get_string( 'tech3' ) , _get_string( 'tech2' ) );
-
-
-	/* We replace the emp.mining_get_input() and emp.mining_compute_extraction()
-	 * functions with something we control fully.
-	 */
-	CREATE OR REPLACE FUNCTION emp.mining_get_input( _empire INT )
-		RETURNS SETOF emp.planet_mining_type
-		LANGUAGE SQL
-	AS $$
-		SELECT _get_map_name( 'testPlanet1' ) AS planet ,
-			_get_string( 'natRes1' ) AS resource ,
-			NULL::DOUBLE PRECISION AS quantity , NULL::DOUBLE PRECISION AS quantity_max ,
-			NULL::DOUBLE PRECISION AS difficulty , NULL::INT AS empire ,
-			NULL::REAL AS happiness , NULL::DOUBLE PRECISION AS weight ,
-			NULL::DOUBLE PRECISION AS total_weight;
-	$$;
-
-	CREATE OR REPLACE FUNCTION emp.mining_compute_extraction( _input emp.planet_mining_type )
-			RETURNS DOUBLE PRECISION LANGUAGE SQL
-	AS $$
-		SELECT 42::DOUBLE PRECISION;
-	$$;
-
-	/***** TESTS BEGIN HERE *****/
-	SELECT plan( 9 );
-	
-	SELECT emp.create_empire( _get_emp_name( 'testEmp1' ) ,
-				_get_map_name( 'testPlanet1' ) ,
-				200.0 );
-
-	SELECT diag_test_name( 'emp.create_empire() - Empire exists' );
-	SELECT is( COUNT(*)::INT , 1 ) FROM emp.empires
-		WHERE name_id = _get_emp_name( 'testEmp1' );
-
-	SELECT diag_test_name( 'emp.create_empire() - Empire cash set' );
-	SELECT is( cash , 200.0::REAL ) FROM emp.empires
-		WHERE name_id = _get_emp_name( 'testEmp1' );
-
-	SELECT diag_test_name( 'emp.create_empire() - Empire debt set' );
-	SELECT is( debt , 0.0::REAL ) FROM emp.empires
-		WHERE name_id = _get_emp_name( 'testEmp1' );
-
-	SELECT diag_test_name( 'emp.create_empire() - Empire mining settings include all natural resources' );
-	SELECT is( COUNT(*)::INT , 2 )
-		FROM defs.natural_resources
-			INNER JOIN emp.mining_settings
-				USING ( resource_name_id )
-		WHERE empire_id = _get_emp_name( 'testEmp1' );
-
-	SELECT diag_test_name( 'emp.create_empire() - Empire mining settings do not include basic resources' );
-	SELECT is( COUNT(*)::INT , 2 )
-		FROM defs.resources
-			INNER JOIN emp.mining_settings
-				USING ( resource_name_id )
-		WHERE empire_id = _get_emp_name( 'testEmp1' );
-
-	SELECT diag_test_name( 'emp.create_empire() - Empire mining settings are all set to 2' );
-	SELECT is( COUNT( * )::INT , 0 )
-		FROM emp.mining_settings
-		WHERE empire_id = _get_emp_name( 'testEmp1' )
-			AND empmset_weight <> 2;
-
-	SELECT diag_test_name( 'emp.create_empire() - Empire resources have been initialised' );
-	SELECT is( COUNT(*)::INT , 3 )
-		FROM emp.resources
-		WHERE empire_id = _get_emp_name( 'testEmp1' );
-
-	SELECT diag_test_name( 'emp.create_empire() - Empire technologies have been initialised' );
-	SELECT set_eq( $$
-		SELECT technology_name_id , emptech_state::TEXT , emptech_points , emptech_priority
-			FROM emp.technologies
-			WHERE empire_id = _get_emp_name( 'testEmp1' );
-	$$ , $$ VALUES(
-		_get_string( 'tech1' ) , 'RESEARCH' , 0.0 , 2
-	) $$ );
-
-	SELECT diag_test_name( 'emp.create_empire() - Resource mining has been updated' );
-	SELECT is( pres_income::DOUBLE PRECISION , 42::DOUBLE PRECISION )
-		FROM verse.planet_resources
-		WHERE planet_id = _get_map_name( 'testPlanet1' )
-			AND resource_name_id = _get_string( 'natRes1' );
-
-	SELECT * FROM finish( );
-ROLLBACK;
diff --git a/legacyworlds-server-data/db-structure/tests/admin/040-functions/040-empire/020-planet-resources-view.sql b/legacyworlds-server-data/db-structure/tests/admin/040-functions/040-empire/020-planet-resources-view.sql
deleted file mode 100644
index 3130b92..0000000
--- a/legacyworlds-server-data/db-structure/tests/admin/040-functions/040-empire/020-planet-resources-view.sql
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Tests for emp.planet_resources_view
- */
-BEGIN;
-	/*
-	 * Create two empires, one with 2 planets, the other without. Add 2 planet
-	 * resources records.
-	 * 
-	 * Disable all foreign keys to avoid a lot of work.
-	 */
-
-	ALTER TABLE emp.planets
-		DROP CONSTRAINT fk_eplanets_empire ,
-		DROP CONSTRAINT fk_eplanets_planet;
-	ALTER TABLE verse.planet_resources
-		DROP CONSTRAINT fk_pres_planet ,
-		DROP CONSTRAINT fk_pres_resource;
-
-	INSERT INTO verse.planet_resources (
-			planet_id , resource_name_id , pres_income , pres_upkeep
-		) VALUES
-			( 1 , 1 , 1 , 2 ) , ( 1 , 2 , 3 , 4 ) ,
-			( 2 , 1 , 3 , 4 ) , ( 2 , 2 , 5 , 6 ) ,
-			( 3 , 1 , 0.1 / 720 , 0.4 / 720 ) ,
-			( 3 , 2 , 0.9 / 720, 0.9 / 720 );
-	INSERT INTO emp.planets( empire_id , planet_id )
-		VALUES ( 1 , 1 ) , ( 1 , 2 ) , ( 2 , 3 );
-
-
-	/***** TESTS BEGIN HERE *****/
-	SELECT plan( 3 );
-
-	SELECT diag_test_name( 'emp.planet_resources_view - Sums' );
-	SELECT set_eq(
-		$$ SELECT * FROM emp.planet_resources_view WHERE empire_id = 1 $$ ,
-		$$ VALUES ( 1 , 1 , 4 * 720 , 6 * 720 ) , ( 1 , 2 , 8 * 720 , 10 * 720 ) $$
-	);
-
-	SELECT diag_test_name( 'emp.planet_resources_view - Incomes are rounded down' );
-	SELECT set_eq(
-		$$ SELECT resource_name_id , planets_income
-			FROM emp.planet_resources_view
-			WHERE empire_id = 2 $$ ,
-		$$ VALUES ( 1 , 0 ) , ( 2 , 0 ) $$
-	);
-
-	SELECT diag_test_name( 'emp.planet_resources_view - Upkeeps are rounded up' );
-	SELECT set_eq(
-		$$ SELECT resource_name_id , planets_upkeep
-			FROM emp.planet_resources_view
-			WHERE empire_id = 2 $$ ,
-		$$ VALUES ( 1 , 1 ) , ( 2 , 1 ) $$
-	);
-
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/admin/040-functions/040-empire/030-resources-view.sql b/legacyworlds-server-data/db-structure/tests/admin/040-functions/040-empire/030-resources-view.sql
deleted file mode 100644
index 8a38970..0000000
--- a/legacyworlds-server-data/db-structure/tests/admin/040-functions/040-empire/030-resources-view.sql
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * Tests for emp.resources_view
- */
-BEGIN;
-
-	/*
-	 * We will use a fake emp.planet_resources_view to avoid having to set
-	 * planet resources.
-	 * 
-	 * In terms of data, we need two resources (one with a category, the other
-	 * without, and two empires (one with "planet resources", the other
-	 * without). Both empires will have mining settings for one of the resource
-	 * types.
-	 */
-
-	\i utils/strings.sql
-	SELECT _create_test_strings( 2 , 'resource' , 'Resource name ' );
-	SELECT _create_test_strings( 2 , 'rDesc' , 'Resource description ' );
-	SELECT _create_test_strings( 1 , 'rCat' , 'Resource category ' );
-	
-	INSERT INTO defs.resources (
-			resource_name_id , resource_description_id ,
-			resource_category_id , resource_weight
-		) VALUES (
-			_get_string( 'resource1' ) , _get_string( 'rDesc1' ) ,
-			_get_string( 'rCat1' ) , 2
-		) , (
-			_get_string( 'resource2' ) , _get_string( 'rDesc2' ) ,
-			NULL , 1
-		);
-
-	\i utils/accounts.sql
-	\i utils/naming.sql
-	SELECT _create_emp_names( 2 , 'emp' );
-	INSERT INTO emp.empires( name_id , cash )
-		SELECT id , 0 FROM naming.empire_names; 
-
-	ALTER TABLE emp.mining_settings DROP CONSTRAINT fk_empmset_resource;
-	INSERT INTO emp.mining_settings ( empire_id , resource_name_id , empmset_weight )
-		SELECT id , _get_string( 'resource1' ) , row_number( ) OVER ()
-			FROM naming.empire_names
-			ORDER BY id;
-
-	INSERT INTO emp.resources ( empire_id , resource_name_id , empres_possessed )
-		SELECT name_id , resource_name_id , 0.4 * row_number( ) OVER ()
-			FROM emp.empires
-				CROSS JOIN defs.resources
-			ORDER BY name_id , resource_name_id;
-
-
-	CREATE TABLE fake_planet_resources_view (
-		empire_id			INT ,
-		resource_name_id	INT ,
-		planets_income		BIGINT ,
-		planets_upkeep		BIGINT
-	);
-	
-	CREATE OR REPLACE VIEW emp.planet_resources_view
-		AS SELECT * FROM fake_planet_resources_view;
-
-	INSERT INTO fake_planet_resources_view
-		VALUES (
-			_get_emp_name( 'emp1' ) , _get_string( 'resource1' ) , 1 , 2
-		) , (
-			_get_emp_name( 'emp1' ) , _get_string( 'resource2' ) , 3 , 4
-		);
-
-
-	/***** TESTS BEGIN HERE *****/
-	SELECT plan( 13 );
-	
-	SELECT diag_test_name( 'emp.resources_view - One row per empire/resource combination' );
-	SELECT is( COUNT(*)::INT , 4 ) FROM emp.resources_view;
-	
-	SELECT diag_test_name( 'emp.resources_view - Resource ordering' );
-	SELECT set_eq(
-		$$ SELECT resource_identifier , row_number( ) OVER ( )
-			FROM emp.resources_view 
-			WHERE empire_id = _get_emp_name( 'emp1' ) $$ ,
-		$$ VALUES ( 'resource2' , 1 ) , ( 'resource1' , 2 ) $$
-	);
-	
-	SELECT diag_test_name( 'emp.resources_view - Name translation' );
-	SELECT is_empty( $$
-		SELECT *
-			FROM emp.resources_view
-			WHERE resource_name NOT LIKE 'Resource name %'
-	$$ );
-	
-	SELECT diag_test_name( 'emp.resources_view - Description translation' );
-	SELECT is_empty( $$
-		SELECT *
-			FROM emp.resources_view
-			WHERE resource_description NOT LIKE 'Resource description %'
-	$$ );
-	
-	SELECT diag_test_name( 'emp.resources_view - Category translation' );
-	SELECT is_empty( $$
-		SELECT *
-			FROM emp.resources_view
-			WHERE resource_identifier = 'resource1'
-				AND resource_category NOT LIKE 'Resource category %'
-	$$ );
-	
-	SELECT diag_test_name( 'emp.resources_view - NULL category -> NULL translation' );
-	SELECT is_empty( $$
-		SELECT *
-			FROM emp.resources_view
-			WHERE resource_identifier <> 'resource1'
-				AND resource_category IS NOT NULL
-	$$ );
-	
-	SELECT diag_test_name( 'emp.resources_view - Possessed quantities are rounded down' );
-	SELECT set_eq(
-		$$ SELECT empire_id , resource_identifier , empres_possessed
-			FROM emp.resources_view $$ ,
-		$$ VALUES (
-				_get_emp_name( 'emp1' ) , 'resource1' , 0
-			) , (
-				_get_emp_name( 'emp1' ) , 'resource2' , 0
-			) , (
-				_get_emp_name( 'emp2' ) , 'resource1' , 1
-			) , (
-				_get_emp_name( 'emp2' ) , 'resource2' , 1
-			) $$
-	);
-	
-	SELECT diag_test_name( 'emp.resources_view - Basic resources have NULL mining settings' );
-	SELECT is( COUNT(*)::INT , 2 )
-		FROM emp.resources_view
-		WHERE resource_identifier = 'resource2'
-			AND empmset_weight IS NULL;
-	
-	SELECT diag_test_name( 'emp.resources_view - Mining settings for natural resources' );
-	SELECT set_eq(
-		$$ SELECT empire_id , empmset_weight
-			FROM emp.resources_view
-			WHERE resource_identifier = 'resource1' $$ ,
-		$$ VALUES ( _get_emp_name( 'emp1' ) , 1 ) ,
-			( _get_emp_name( 'emp2' ) , 2 ) $$
-	);
-	SELECT is( COUNT(*)::INT , 2 )
-		FROM emp.resources_view
-		WHERE resource_identifier = 'resource1'
-			AND empmset_weight IS NOT NULL;
-	
-	SELECT diag_test_name( 'emp.resources_view - Planet upkeep/income is zero when there are no planets' );
-	SELECT is( COUNT(*)::INT , 2 )
-		FROM emp.resources_view
-		WHERE empire_id = _get_emp_name( 'emp2' )
-			AND planets_upkeep = 0
-			AND planets_income = 0;
-	
-	SELECT diag_test_name( 'emp.resources_view - Planet upkeep/income from planet resources view' );
-	SELECT set_eq(
-		$$ SELECT resource_identifier , planets_upkeep , planets_income
-			FROM emp.resources_view
-			WHERE empire_id = _get_emp_name( 'emp1' ) $$ ,
-		$$ VALUES ( 'resource1' , 2 , 1 ) , ( 'resource2' , 4 , 3 ) $$
-	);
-	
-	SELECT diag_test_name( 'emp.resources_view - FIXME - Fleets upkeep set to zero' );
-	SELECT is_empty(
-		$$ SELECT * FROM emp.resources_view
-			WHERE fleets_upkeep <> 0 $$
-	);
-
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/admin/040-functions/043-computation/010-get-random-part.sql b/legacyworlds-server-data/db-structure/tests/admin/040-functions/043-computation/010-get-random-part.sql
deleted file mode 100644
index 7192fee..0000000
--- a/legacyworlds-server-data/db-structure/tests/admin/040-functions/043-computation/010-get-random-part.sql
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Test the verse.get_random_part() function
- */
-BEGIN;
-	SELECT plan( 6 );
-
-	/* First set of tests: results of the function with a fake
-	 * verse.random_deviation() that always returns the minimal possible
-	 * value.
-	 */
-	CREATE OR REPLACE FUNCTION verse.random_deviation( _mean DOUBLE PRECISION , _deviation DOUBLE PRECISION )
-		RETURNS DOUBLE PRECISION
-		STRICT VOLATILE
-	AS $$
-		SELECT $1 - $2;
-	$$ LANGUAGE SQL;
-
-	SELECT diag_test_name( 'verse.get_random_part() - Single part, minimal random value' );
-	SELECT is( verse.get_random_part( 0.5 , 1 , 0.5 , 0.25 ) , 0.5::DOUBLE PRECISION );
-	SELECT diag_test_name( 'verse.get_random_part() - Two parts, some extra quantity, minimal random value' );
-	SELECT is( verse.get_random_part( 0.75 , 2 , 0.5 , 0.25 ) , 0.25::DOUBLE PRECISION );
-	SELECT diag_test_name( 'verse.get_random_part() - Two parts, maximal quantity, minimal random value' );
-	SELECT is( verse.get_random_part( 1.5 , 2 , 0.5 , 0.25 ) , 0.75::DOUBLE PRECISION );
-
-	/* Second set of tests: results of the function with a fake
-	 * verse.random_deviation() that always returns the maximal possible
-	 * value.
-	 */
-	CREATE OR REPLACE FUNCTION verse.random_deviation( _mean DOUBLE PRECISION , _deviation DOUBLE PRECISION )
-		RETURNS DOUBLE PRECISION
-		STRICT VOLATILE
-	AS $$
-		SELECT $1 + $2;
-	$$ LANGUAGE SQL;
-
-	SELECT diag_test_name( 'verse.get_random_part() - Single part, maximal random value' );
-	SELECT is( verse.get_random_part( 0.5 , 1 , 0.5 , 0.25 ) , 0.5::DOUBLE PRECISION );
-	SELECT diag_test_name( 'verse.get_random_part() - Two parts, some extra quantity, maximal random value' );
-	SELECT is( verse.get_random_part( 1 , 2 , 0.5 , 0.25 ) , 0.75::DOUBLE PRECISION );
-	SELECT diag_test_name( 'verse.get_random_part() - Two parts, minimal quantity, maximal random value' );
-	SELECT is( verse.get_random_part( 0.5 , 2 , 0.5 , 0.25 ) , 0.25::DOUBLE PRECISION );
-
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/admin/040-functions/043-computation/020-adjust-production.sql b/legacyworlds-server-data/db-structure/tests/admin/040-functions/043-computation/020-adjust-production.sql
deleted file mode 100644
index 7059de1..0000000
--- a/legacyworlds-server-data/db-structure/tests/admin/040-functions/043-computation/020-adjust-production.sql
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Test the verse.adjust_production() function
- */
-BEGIN;
-	-- Create a table of input values
-	CREATE TABLE test_input(
-		prod		REAL ,
-		happ		REAL
-	);
-	
-	-- Set the happiness strike level to 50%
-	SELECT sys.uoc_constant( 'game.happiness.strike' , '(test)' , 'Happiness' , 0.5 );
-	
-	-- ***** TESTS BEGIN HERE *****
-	SELECT plan( 3 );
-	
-	INSERT INTO test_input VALUES
-		( 10 , 1 ) , ( 100 , 1 ) ,
-		( 10 , 0.9 ) , ( 100 , 0.9 ) ,
-		( 10 , 0.8 ) , ( 100 , 0.8 ) ,
-		( 10 , 0.7 ) , ( 100 , 0.7 ) ,
-		( 10 , 0.6 ) , ( 100 , 0.6 ) ,
-		( 10 , 0.5 ) , ( 100 , 0.5 );
-	SELECT diag_test_name( 'verse.adjust_production() - Production is unaffected when happiness >= game.happiness.strike' );
-	SELECT is_empty(
-		$$ SELECT * FROM test_input WHERE prod <> verse.adjust_production( prod , happ ); $$
-	);
-	DELETE FROM test_input;
-	
-	INSERT INTO test_input VALUES
-		( 10 , 0.5 ) , ( 10 , 0.4 ) ,
-		( 10 , 0.3 ) , ( 10 , 0.2 ) ,
-		( 10 , 0.1 ) , ( 10 , 0 );
-	SELECT diag_test_name( 'verse.adjust_production() - Production is unaffected when happiness >= game.happiness.strike' );
-	SELECT set_eq(
-		$$ SELECT rank( ) OVER( ORDER BY happ ) AS r1 ,
-				rank( ) OVER ( ORDER BY verse.adjust_production( prod , happ ) ) AS r2
-			FROM test_input; $$ ,
-		$$ VALUES ( 1 , 1 ) , ( 2 , 2 ) , ( 3 , 3 ) , ( 4 , 4 ) , ( 5 , 5 ) , ( 6 , 6 ) $$ 
-	);
-	DELETE FROM test_input;
-
-	SELECT diag_test_name( 'verse.adjust_production() - Happiness = 0 => production = 0' );
-	INSERT INTO test_input VALUES
-		( 1 , 0 ) , ( 10 , 0 ) , ( 100 , 0 ) , ( 1000 , 0 ) , ( 10000 , 0 );
-	SELECT is_empty(
-		$$ SELECT * FROM test_input WHERE verse.adjust_production( prod , happ ) <> 0; $$
-	);
-
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/admin/040-functions/045-empire-research/010-technology-implement.sql b/legacyworlds-server-data/db-structure/tests/admin/040-functions/045-empire-research/010-technology-implement.sql
deleted file mode 100644
index 5ec2087..0000000
--- a/legacyworlds-server-data/db-structure/tests/admin/040-functions/045-empire-research/010-technology-implement.sql
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Unit tests for emp.technology_implement()
- */
-BEGIN;
-	\i utils/strings.sql
-	\i utils/resources.sql
-	\i utils/accounts.sql
-	\i utils/naming.sql
-	\i utils/universe.sql
-
-	/*
-	 * Create empires
-	 */
-	SELECT _create_emp_names( 4 , 'emp' );
-	INSERT INTO emp.empires ( name_id , cash )
-		SELECT id , 200 FROM naming.empire_names;
-
-	/*
-	 * We also need 3 technologies (tech1, tech2 and tech3), and some
-	 * dependencies between them: tech3 -> {tech2, tech1}). Disabling
-	 * unused fields in defs.technologies makes things easier.
-	 */
-	ALTER TABLE defs.technologies
-		ALTER technology_category_id DROP NOT NULL ,
-		ALTER technology_discovery_id DROP NOT NULL ,
-		ALTER technology_description_id DROP NOT NULL ,
-		ALTER technology_points DROP NOT NULL;
-	SELECT _create_test_strings( 3 , 'tech' );
-	INSERT INTO defs.technologies ( technology_name_id , technology_price )
-		VALUES ( _get_string( 'tech1' ) , 200 ) ,
-				( _get_string( 'tech2' ) , 200 ) ,
-				( _get_string( 'tech3' ) , 300 );
-	INSERT INTO defs.technology_dependencies(
-			technology_name_id , technology_name_id_depends
-		) VALUES ( _get_string( 'tech3' ) , _get_string( 'tech1' ) ) ,
-			 ( _get_string( 'tech3' ) , _get_string( 'tech2' ) );
-
-	/* Empire "emp1" has only in-progress research. */
-	INSERT INTO emp.technologies ( empire_id , technology_name_id )
-		VALUES( _get_emp_name( 'emp1' ) , _get_string( 'tech1' ) );
-
-	/* Empire "emp2" has a pending technology. */
-	INSERT INTO emp.technologies ( empire_id , technology_name_id , emptech_state , emptech_points , emptech_priority )
-		VALUES( _get_emp_name( 'emp2' ) , _get_string( 'tech1' ) , 'PENDING' , NULL , NULL );
-
-	/* Empire "emp3" has implemented 'tech1' and has 'tech2' as pending. */
-	INSERT INTO emp.technologies ( empire_id , technology_name_id , emptech_state , emptech_points , emptech_priority )
-		VALUES( _get_emp_name( 'emp3' ) , _get_string( 'tech1' ) , 'KNOWN' , NULL , NULL ) ,
-			( _get_emp_name( 'emp3' ) , _get_string( 'tech2' ) , 'PENDING' , NULL , NULL );
-
-	/* Empire "emp4" has implemented 'tech1' and 'tech2' and has 'tech3' as pending. */
-	INSERT INTO emp.technologies ( empire_id , technology_name_id , emptech_state , emptech_points , emptech_priority )
-		VALUES( _get_emp_name( 'emp4' ) , _get_string( 'tech1' ) , 'KNOWN' , NULL , NULL ) ,
-			( _get_emp_name( 'emp4' ) , _get_string( 'tech2' ) , 'KNOWN' , NULL , NULL ) ,
-			( _get_emp_name( 'emp4' ) , _get_string( 'tech3' ) , 'PENDING' , NULL , NULL );
-
-	-- ***** TESTS BEGIN HERE *****
-	SELECT plan( 10 );
-
-	SELECT diag_test_name( 'emp.technology_implement() - Call on in-progress research' );
-	SELECT ok( NOT emp.technology_implement( _get_emp_name( 'emp1' ) , 'tech1' ) );
-
-	SELECT diag_test_name( 'emp.technology_implement() - Call on unknown technology' );
-	SELECT ok( NOT emp.technology_implement( _get_emp_name( 'emp1' ) , 'tech2' ) );
-
-	SELECT diag_test_name( 'emp.technology_implement() - Call on implemented technology' );
-	SELECT ok( NOT emp.technology_implement( _get_emp_name( 'emp3' ) , 'tech1' ) );
-
-	SELECT diag_test_name( 'emp.technology_implement() - Call on pending technology - No new research - Return value' );
-	SELECT ok( emp.technology_implement( _get_emp_name( 'emp2' ) , 'tech1' ) );
-
-	SELECT diag_test_name( 'emp.technology_implement() - Call on pending technology - No new research - Table contents' );
-	SELECT set_eq( $$
-		SELECT technology_name_id , emptech_state::TEXT
-			FROM emp.technologies
-			WHERE empire_id = _get_emp_name( 'emp2' )
-	$$ , $$ VALUES(
-		_get_string( 'tech1' ) , 'KNOWN'
-	) $$ );
-
-	SELECT diag_test_name( 'emp.technology_implement() - Call on pending technology - No new research - Empire cash' );
-	SELECT is( cash , 0.0::REAL ) FROM emp.empires
-		WHERE name_id = _get_emp_name( 'emp2' );
-
-	SELECT diag_test_name( 'emp.technology_implement() - Call on pending technology - New research - Return value' );
-	SELECT ok( emp.technology_implement( _get_emp_name( 'emp3' ) , 'tech2' ) );
-
-	SELECT diag_test_name( 'emp.technology_implement() - Call on pending technology - New research - Table contents' );
-	SELECT set_eq( $$
-		SELECT technology_name_id , emptech_state::TEXT
-			FROM emp.technologies
-			WHERE empire_id = _get_emp_name( 'emp3' )
-	$$ , $$ VALUES(
-		_get_string( 'tech1' ) , 'KNOWN'
-	) , (
-		_get_string( 'tech2' ) , 'KNOWN'
-	) , (
-		_get_string( 'tech3' ) , 'RESEARCH'
-	) $$ );
-
-	SELECT diag_test_name( 'emp.technology_implement() - Call on pending technology - New research - Empire cash' );
-	SELECT is( cash , 0.0::REAL ) FROM emp.empires
-		WHERE name_id = _get_emp_name( 'emp3' );
-
-
-	SELECT diag_test_name( 'emp.technology_implement() - Call on pending technology when empire cash is too low' );
-	SELECT ok( NOT emp.technology_implement( _get_emp_name( 'emp4' ) , 'tech3' ) );
-
-	SELECT * FROM finish( );
-ROLLBACK;
diff --git a/legacyworlds-server-data/db-structure/tests/admin/040-functions/045-empire-research/020-technology-make-identifier.sql b/legacyworlds-server-data/db-structure/tests/admin/040-functions/045-empire-research/020-technology-make-identifier.sql
deleted file mode 100644
index 0ea818a..0000000
--- a/legacyworlds-server-data/db-structure/tests/admin/040-functions/045-empire-research/020-technology-make-identifier.sql
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * Unit tests for emp.technology_make_identifier()
- */
-BEGIN;
-	SELECT no_plan( );
-	
-	SELECT diag_test_name( 'emp.technology_make_identifier() - Identifier of visible technologies' );
-	SELECT is( emp.technology_make_identifier( 1 , 'test-string' , TRUE ) , 'test-string' );
-
-	SELECT diag_test_name( 'emp.technology_make_identifier() - Identifier of unknown technologies - 32 characters' );
-	SELECT is( length( emp.technology_make_identifier( 1 , 'test-string' , FALSE ) ) , 32 );
-
-	SELECT diag_test_name( 'emp.technology_make_identifier() - Identifier of unknown technologies - Contains hex value' );
-	SELECT ok( emp.technology_make_identifier( 1 , 'test-string' , FALSE ) !~ '[^a-f0-9]' );
-
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/admin/040-functions/045-empire-research/030-resprio-update-start.sql b/legacyworlds-server-data/db-structure/tests/admin/040-functions/045-empire-research/030-resprio-update-start.sql
deleted file mode 100644
index ea0cf98..0000000
--- a/legacyworlds-server-data/db-structure/tests/admin/040-functions/045-empire-research/030-resprio-update-start.sql
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Unit tests for emp.resprio_update_start()
- */
-BEGIN;
-	\i utils/strings.sql
-	\i utils/accounts.sql
-	\i utils/naming.sql
-
-	/* Create two empires */
-	SELECT _create_emp_names( 2 , 'emp' );
-	INSERT INTO emp.empires ( name_id , cash )
-		SELECT id , 200.0 FROM naming.empire_names;
-
-	/* Create 3 technologies after disabling unused fields */
-	ALTER TABLE defs.technologies
-		ALTER technology_category_id DROP NOT NULL ,
-		ALTER technology_discovery_id DROP NOT NULL ,
-		ALTER technology_description_id DROP NOT NULL ,
-		ALTER technology_price DROP NOT NULL ,
-		ALTER technology_points DROP NOT NULL;
-	SELECT _create_test_strings( 3 , 'tech' );
-	INSERT INTO defs.technologies ( technology_name_id )
-		VALUES ( _get_string( 'tech1' ) ) ,
-			( _get_string( 'tech2' ) ) ,
-			( _get_string( 'tech3' ) );
-
-	/* Replace identifier function with something easier to check */
-	CREATE OR REPLACE FUNCTION emp.technology_make_identifier(
-				_empire INT , _technology TEXT , _visible BOOLEAN )
-		RETURNS TEXT
-		LANGUAGE SQL
-		STRICT IMMUTABLE
-		SECURITY DEFINER
-	AS $technology_make_identifier$
-		SELECT $1::TEXT || ',' || $2 || ',' || $3::TEXT;
-	$technology_make_identifier$;
-
-	/* Replace the visibility view with plain SELECT's from a table.
-	 */
-	CREATE TABLE _fake_visibility(
-		empire_id			INT ,
-		technology_name_id	INT ,
-		emptech_visible		BOOLEAN
-	);
-	CREATE OR REPLACE VIEW emp.technology_visibility_view
-		AS SELECT * FROM _fake_visibility;
-
-	/* Insert empire state and data for fake views */
-	INSERT INTO emp.technologies (
-			empire_id , technology_name_id ,
-			emptech_state , emptech_points , emptech_priority
-		) VALUES (
-			_get_emp_name( 'emp1' ) , _get_string( 'tech1' ) ,
-			'KNOWN' , NULL , NULL
-		) , (
-			_get_emp_name( 'emp1' ) , _get_string( 'tech2' ) ,
-			'RESEARCH' , 123 , 0
-		) , (
-			_get_emp_name( 'emp1' ) , _get_string( 'tech3' ) ,
-			'RESEARCH' , 123 , 1
-		);
-	INSERT INTO _fake_visibility VALUES(
-		_get_emp_name( 'emp1' ) , _get_string( 'tech1' ) , TRUE 
-	) , (
-		_get_emp_name( 'emp1' ) , _get_string( 'tech2' ) , TRUE 
-	) , (
-		_get_emp_name( 'emp1' ) , _get_string( 'tech3' ) , FALSE 
-	);
-	
-	-- ***** TESTS BEGIN HERE *****
-	SELECT plan( 9 );
-
-	SELECT diag_test_name( 'emp.resprio_update_start() - Invalid empire - Return value' );
-	SELECT ok( NOT emp.resprio_update_start( _get_bad_emp_name() ) );
-	SELECT diag_test_name( 'emp.resprio_update_start() - Invalid empire - Temporary table exists' );
-	SELECT has_table( 'rprio_update' );
-	SELECT diag_test_name( 'emp.resprio_update_start() - Invalid empire - Temporary table is empty' );
-	SELECT is_empty( $$ SELECT * FROM rprio_update $$ );
-	DROP TABLE IF EXISTS rprio_update;
-
-	SELECT diag_test_name( 'emp.resprio_update_start() - Empire with no research - Return value' );
-	SELECT ok( NOT emp.resprio_update_start( _get_emp_name( 'emp2' ) ) );
-	SELECT diag_test_name( 'emp.resprio_update_start() - Empire with no research - Temporary table exists' );
-	SELECT has_table( 'rprio_update' );
-	SELECT diag_test_name( 'emp.resprio_update_start() - Empire with no research - Temporary table is empty' );
-	SELECT is_empty( $$ SELECT * FROM rprio_update $$ );
-	DROP TABLE IF EXISTS rprio_update;
-
-	SELECT diag_test_name( 'emp.resprio_update_start() - Empire with in-progress research - Return value' );
-	SELECT ok( emp.resprio_update_start( _get_emp_name( 'emp1' ) ) );
-	SELECT diag_test_name( 'emp.resprio_update_start() - Empire with in-progress research - Temporary table exists' );
-	SELECT has_table( 'rprio_update' );
-	SELECT diag_test_name( 'emp.resprio_update_start() - Empire with in-progress research - Temporary table contents' );
-	SELECT set_eq( $$
-		SELECT _empire_id , _technology_name_id , _emptech_id , _emptech_priority
-			FROM rprio_update
-	$$ , $$ VALUES(
-		_get_emp_name( 'emp1' ) , _get_string( 'tech2' ) , _get_emp_name( 'emp1' ) || ',tech2,true' , 0
-	) , (
-		_get_emp_name( 'emp1' ) , _get_string( 'tech3' ) , _get_emp_name( 'emp1' ) || ',tech3,false' , 1
-	) $$ );
-	DROP TABLE IF EXISTS rprio_update;
-
-	SELECT * FROM finish( );
-ROLLBACK;
diff --git a/legacyworlds-server-data/db-structure/tests/admin/040-functions/045-empire-research/040-resprio-update-set.sql b/legacyworlds-server-data/db-structure/tests/admin/040-functions/045-empire-research/040-resprio-update-set.sql
deleted file mode 100644
index e317a1c..0000000
--- a/legacyworlds-server-data/db-structure/tests/admin/040-functions/045-empire-research/040-resprio-update-set.sql
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Unit tests for emp.resprio_update_set( )
- */
-BEGIN;
-	/* Create a fake temporary table and insert some values */
-	CREATE TEMPORARY TABLE rprio_update(
-		_empire_id			INT ,
-		_technology_name_id	INT ,
-		_emptech_id			TEXT ,
-		_emptech_priority	INT
-	) ON COMMIT DROP;
-	INSERT INTO rprio_update
-		VALUES ( 1 , 1 , 'test' , 2 );
-
-	-- ***** TESTS BEGIN HERE *****
-	SELECT plan( 4 );
-
-	SELECT diag_test_name( 'emp.resprio_update_set() - Using a bad identifier - Return value' );
-	SELECT ok( NOT emp.resprio_update_set( 'bad identifier' , 3 ) );
-	SELECT diag_test_name( 'emp.resprio_update_set() - Using a bad identifier - Table contents' );
-	SELECT set_eq( $$
-		SELECT * FROM rprio_update
-	$$ , $$ VALUES(
-		1 , 1 , 'test' , 2
-	) $$ );
-
-	SELECT diag_test_name( 'emp.resprio_update_set() - Using a valid identifier - Return value' );
-	SELECT ok( emp.resprio_update_set( 'test' , 3 ) );
-	SELECT diag_test_name( 'emp.resprio_update_set() - Using a bad identifier - Table contents' );
-	SELECT set_eq( $$
-		SELECT * FROM rprio_update
-	$$ , $$ VALUES(
-		1 , 1 , 'test' , 3
-	) $$ );
-
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/admin/040-functions/045-empire-research/050-resprio-update-apply.sql b/legacyworlds-server-data/db-structure/tests/admin/040-functions/045-empire-research/050-resprio-update-apply.sql
deleted file mode 100644
index 11ec682..0000000
--- a/legacyworlds-server-data/db-structure/tests/admin/040-functions/045-empire-research/050-resprio-update-apply.sql
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Unit tests for emp.resprio_update_apply()
- */
-BEGIN;
-	\i utils/strings.sql
-	\i utils/accounts.sql
-	\i utils/naming.sql
-
-	/* Create a pair of empires, a technology, and some empire
-	 * research & technology records.
-	 */
-	SELECT _create_emp_names( 2 , 'emp' );
-	INSERT INTO emp.empires ( name_id , cash )
-		SELECT id , 200.0 FROM naming.empire_names;
-
-	ALTER TABLE defs.technologies
-		ALTER technology_category_id DROP NOT NULL ,
-		ALTER technology_discovery_id DROP NOT NULL ,
-		ALTER technology_description_id DROP NOT NULL ,
-		ALTER technology_price DROP NOT NULL ,
-		ALTER technology_points DROP NOT NULL;
-	SELECT _create_test_strings( 1 , 'tech' );
-	INSERT INTO defs.technologies ( technology_name_id )
-		VALUES ( _get_string( 'tech1' ) );
-
-	INSERT INTO emp.technologies(
-			empire_id , technology_name_id ,
-			emptech_state , emptech_points , emptech_priority
-		) VALUES (
-			_get_emp_name( 'emp1' ) , _get_string( 'tech1' ) ,
-			'RESEARCH' , 12 , 2 
-		) , (
-			_get_emp_name( 'emp2' ) , _get_string( 'tech1' ) ,
-			'RESEARCH' , 12 , 2 
-		);
-
-	/* Create a fake temporary table */
-	CREATE TEMPORARY TABLE rprio_update(
-		_empire_id			INT ,
-		_technology_name_id	INT ,
-		_emptech_id			TEXT ,
-		_emptech_priority	INT
-	) ON COMMIT DROP;
-
-	-- ***** TESTS BEGIN HERE *****
-	SELECT plan( 4 );
-
-	INSERT INTO rprio_update
-		VALUES ( _get_emp_name( 'emp1' ) , _get_string( 'tech1' ) , 'ignored' , 1 );
-	SELECT diag_test_name( 'emp.resprio_update_apply() - Applying a valid update - Return value' );
-	SELECT ok( emp.resprio_update_apply( ) );
-	SELECT diag_test_name( 'emp.resprio_update_apply() - Applying a valid update - Table contents' );
-	SELECT set_eq( $$
-		SELECT empire_id , emptech_priority
-			FROM emp.technologies
-			WHERE technology_name_id = _get_string( 'tech1' );
-	$$ , $$ VALUES(
-		_get_emp_name( 'emp1' ) , 1
-	) , (
-		_get_emp_name( 'emp2' ) , 2
-	) $$ );
-	DELETE FROM rprio_update;
-	UPDATE emp.technologies
-		SET emptech_priority = 2
-		WHERE technology_name_id = _get_string( 'tech1' );
-
-	INSERT INTO rprio_update
-		VALUES ( _get_emp_name( 'emp1' ) , _get_string( 'tech1' ) , 'ignored' , 15 );
-	SELECT diag_test_name( 'emp.resprio_update_apply() - Applying an invalid update - Return value' );
-	SELECT ok( NOT emp.resprio_update_apply( ) );
-	SELECT diag_test_name( 'emp.resprio_update_apply() - Applying an invalid update - Table contents' );
-	SELECT set_eq( $$
-		SELECT empire_id , emptech_priority
-			FROM emp.technologies
-	$$ , $$ VALUES(
-		_get_emp_name( 'emp1' ) , 2
-	) , (
-		_get_emp_name( 'emp2' ) , 2
-	) $$ );
-
-	SELECT * FROM finish( );
-ROLLBACK;
diff --git a/legacyworlds-server-data/db-structure/tests/admin/040-functions/045-empire-research/060-technology-visibility-view.sql b/legacyworlds-server-data/db-structure/tests/admin/040-functions/045-empire-research/060-technology-visibility-view.sql
deleted file mode 100644
index 1f0ab1a..0000000
--- a/legacyworlds-server-data/db-structure/tests/admin/040-functions/045-empire-research/060-technology-visibility-view.sql
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Unit tests for emp.technology_visibility_view
- */
-BEGIN;
-	\i utils/strings.sql
-	\i utils/accounts.sql
-	\i utils/naming.sql
-
-	/* Create a single empire */
-	SELECT _create_emp_names( 1 , 'emp' );
-	INSERT INTO emp.empires ( name_id , cash )
-		VALUES ( _get_emp_name( 'emp1' ) , 200 );
-
-	/*
-	 * Set visibility thresholds to either 50% or 100 points.
-	 */
-	SELECT sys.uoc_constant( 'game.research.visibility.points' , '(test)' , 'Test' , 100.0 );
-	SELECT sys.uoc_constant( 'game.research.visibility.ratio' , '(test)' , 'Test' , 0.5 );
-	
-	/* Create 6 technology definitions that will be used to test various
-	 * states: pending, known, 4 variants of research in progress (points
-	 * and ratio below thresholds, points below threshold, ratio below
-	 * threshold, both points and ratio above thresholds).
-	 * 
-	 * Disable all unused fields from the definition table.
-	 */
-	ALTER TABLE defs.technologies
-		ALTER technology_category_id DROP NOT NULL ,
-		ALTER technology_discovery_id DROP NOT NULL ,
-		ALTER technology_description_id DROP NOT NULL ,
-		ALTER technology_price DROP NOT NULL;
-	SELECT _create_test_strings( 6 , 'tech' );
-	INSERT INTO defs.technologies( technology_name_id , technology_points )
-		VALUES ( _get_string( 'tech1' ) , 100 ) ,
-			( _get_string( 'tech2' ) , 100 ) ,
-			( _get_string( 'tech3' ) , 100 ) ,
-			( _get_string( 'tech4' ) , 100 ) ,
-			( _get_string( 'tech5' ) , 1000 ) ,
-			( _get_string( 'tech6' ) , 1000 );
-
-	/* Insert empire state */
-	INSERT INTO emp.technologies (
-			empire_id , technology_name_id ,
-			emptech_state , emptech_points , emptech_priority
-		) VALUES (
-			_get_emp_name( 'emp1' ) , _get_string( 'tech1' ) ,
-			'KNOWN' , NULL , NULL
-		) , (
-			_get_emp_name( 'emp1' ) , _get_string( 'tech2' ) ,
-			'PENDING' , NULL , NULL
-		) , (
-			_get_emp_name( 'emp1' ) , _get_string( 'tech3' ) ,
-			'RESEARCH' , 10.0 , 2
-		) , (
-			_get_emp_name( 'emp1' ) , _get_string( 'tech4' ) ,
-			'RESEARCH' , 51.0 , 2
-		) , (
-			_get_emp_name( 'emp1' ) , _get_string( 'tech5' ) ,
-			'RESEARCH' , 101.0 , 2
-		) , (
-			_get_emp_name( 'emp1' ) , _get_string( 'tech6' ) ,
-			'RESEARCH' , 501.0 , 2
-		);
-
-	-- ***** TESTS BEGIN HERE *****
-	SELECT plan( 7 );
-
-	SELECT diag_test_name( 'emp.technology_visibility_view - All technologies are listed' );
-	SELECT is( COUNT( * )::INT , 6 )
-		FROM emp.technology_visibility_view
-		WHERE empire_id = _get_emp_name( 'emp1' );
-
-	SELECT diag_test_name( 'emp.technology_visibility_view - Known technologies are visible' );
-	SELECT ok( emptech_visible )
-		FROM emp.technology_visibility_view
-		WHERE technology_name_id = _get_string( 'tech1' )
-			AND empire_id = _get_emp_name( 'emp1' );
-
-	SELECT diag_test_name( 'emp.technology_visibility_view - Pending technologies are visible' );
-	SELECT ok( emptech_visible )
-		FROM emp.technology_visibility_view
-		WHERE technology_name_id = _get_string( 'tech2' )
-			AND empire_id = _get_emp_name( 'emp1' );
-
-	SELECT diag_test_name( 'emp.technology_visibility_view - In-progress technologies with both points and ratios below thresholds are not visible' );
-	SELECT ok( NOT emptech_visible )
-		FROM emp.technology_visibility_view
-		WHERE technology_name_id = _get_string( 'tech3' )
-			AND empire_id = _get_emp_name( 'emp1' );
-
-	SELECT diag_test_name( 'emp.technology_visibility_view - In-progress technologies with points below threshold are visible' );
-	SELECT ok( emptech_visible )
-		FROM emp.technology_visibility_view
-		WHERE technology_name_id = _get_string( 'tech4' )
-			AND empire_id = _get_emp_name( 'emp1' );
-
-	SELECT diag_test_name( 'emp.technology_visibility_view - In-progress technologies with ratio below threshold are visible' );
-	SELECT ok( emptech_visible )
-		FROM emp.technology_visibility_view
-		WHERE technology_name_id = _get_string( 'tech5' )
-			AND empire_id = _get_emp_name( 'emp1' );
-
-	SELECT diag_test_name( 'emp.technology_visibility_view - In-progress technologies with both points and ratios above threshold are visible' );
-	SELECT ok( emptech_visible )
-		FROM emp.technology_visibility_view
-		WHERE technology_name_id = _get_string( 'tech6' )
-			AND empire_id = _get_emp_name( 'emp1' );
-
-
-	SELECT * FROM finish( );
-ROLLBACK;
diff --git a/legacyworlds-server-data/db-structure/tests/admin/040-functions/045-empire-research/070-research-weights-view.sql b/legacyworlds-server-data/db-structure/tests/admin/040-functions/045-empire-research/070-research-weights-view.sql
deleted file mode 100644
index 442c361..0000000
--- a/legacyworlds-server-data/db-structure/tests/admin/040-functions/045-empire-research/070-research-weights-view.sql
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Test emp.research_weights_view
- */
-BEGIN;
-	/* Remove foreign keys from the empire research table */
-	ALTER TABLE emp.technologies
-		DROP CONSTRAINT fk_emptech_empire ,
-		DROP CONSTRAINT fk_emptech_technology;
-
-	/* Insert a few records */
-	DELETE FROM emp.technologies;
-	INSERT INTO emp.technologies (
-			empire_id , technology_name_id ,
-			emptech_state , emptech_points , emptech_priority
-		) VALUES
-			( 1 , 1 , 'RESEARCH' , 0 , 0 ) ,
-			( 1 , 2 , 'RESEARCH' , 0 , 1 ) ,
-			( 1 , 3 , 'RESEARCH' , 0 , 2 ) ,
-			( 1 , 4 , 'RESEARCH' , 0 , 3 ) ,
-			( 1 , 5 , 'RESEARCH' , 0 , 4 ) ,
-			( 1 , 6 , 'PENDING' , NULL , NULL ) ,
-			( 1 , 7 , 'KNOWN' , NULL , NULL );
-
-	/* Set the constant */
-	SELECT sys.uoc_constant( 'game.research.weightBase' , '(test)' , 'Test' , 10.0 );
-
-	/***** TESTS BEGIN HERE *****/
-	SELECT plan( 2 );
-
-	SELECT diag_test_name( 'emp.research_weights_view - Rows present' );
-	SELECT is( COUNT(*)::INT , 5 )
-		FROM emp.research_weights_view;
-
-	SELECT diag_test_name( 'emp.research_weights_view - weight = game.research.weightBase ^ priority' );
-	SELECT is_empty( $$
-		SELECT * FROM emp.research_weights_view
-			WHERE emptech_weight IS NULL
-				OR emptech_weight <> POW( 10 , technology_name_id - 1 )
-	$$ );
-
-	SELECT * FROM finish( );
-ROLLBACK;
diff --git a/legacyworlds-server-data/db-structure/tests/admin/040-functions/045-empire-research/080-research-total-weights-view.sql b/legacyworlds-server-data/db-structure/tests/admin/040-functions/045-empire-research/080-research-total-weights-view.sql
deleted file mode 100644
index 6e05a66..0000000
--- a/legacyworlds-server-data/db-structure/tests/admin/040-functions/045-empire-research/080-research-total-weights-view.sql
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Test emp.total_mining_weights_view
- */
-BEGIN;
-	/* Create a table which will server as an alternate source for
-	 * emp.total_weights_view ; the table is not temporary (PostgreSQL
-	 * won't allow replacing the view otherwise), but will be dropped
-	 * on rollback anyway. 
-	 */
-	CREATE TABLE fake_weights(
-		empire_id			INT ,
-		technology_name_id	INT ,
-		emptech_weight		DOUBLE PRECISION
-	);
-	
-	CREATE OR REPLACE VIEW emp.research_weights_view
-		AS SELECT * FROM fake_weights;
-
-	/* Insert fake records for two different empires */
-	INSERT INTO fake_weights VALUES
-		( 1 , 0 , 1 ) ,
-		( 1 , 1 , 2 ) ,
-		( 2 , 0 , 4 ) ,
-		( 2 , 1 , 5 );
-
-	/***** TESTS BEGIN HERE *****/
-	SELECT plan( 1 );
-	
-	SELECT set_eq(
-		$$ SELECT * FROM emp.research_total_weights_view $$ ,
-		$$ VALUES ( 1 , 3.0 ) , ( 2 , 9.0 ) $$
-	);
-
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/admin/040-functions/045-empire-research/090-technologies-view.sql b/legacyworlds-server-data/db-structure/tests/admin/040-functions/045-empire-research/090-technologies-view.sql
deleted file mode 100644
index 109f0be..0000000
--- a/legacyworlds-server-data/db-structure/tests/admin/040-functions/045-empire-research/090-technologies-view.sql
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Unit tests for emp.technologies_view
- */
-BEGIN;
-	\i utils/strings.sql
-	\i utils/accounts.sql
-	\i utils/naming.sql
-
-	/* Create three empires (easier to use as keys) */
-	SELECT _create_emp_names( 3 , 'emp' );
-	INSERT INTO emp.empires ( name_id , cash )
-		SELECT id , 200.0 FROM naming.empire_names;
-
-	/* Create a technology after disabling unused fields */
-	ALTER TABLE defs.technologies
-		ALTER technology_discovery_id DROP NOT NULL;
-	SELECT _create_test_strings( 1 , 'tech' );
-	SELECT _create_test_strings( 1 , 'techCategory' );
-	SELECT _create_test_strings( 1 , 'techDescription' );
-	INSERT INTO defs.technologies (
-			technology_name_id , technology_category_id , technology_description_id ,
-			technology_price , technology_points
-		) VALUES (
-			_get_string( 'tech1' ) , _get_string( 'techCategory1' ) , _get_string( 'techDescription1' ) ,
-			123 , 456
-		);
-
-	/* Replace identifier function with something easier to check */
-	CREATE OR REPLACE FUNCTION emp.technology_make_identifier(
-				_empire INT , _technology TEXT , _visible BOOLEAN )
-		RETURNS TEXT
-		LANGUAGE SQL
-		STRICT IMMUTABLE
-		SECURITY DEFINER
-	AS $technology_make_identifier$
-		SELECT $1::TEXT || ',' || $2 || ',' || $3::TEXT;
-	$technology_make_identifier$;
-
-	/* Replace both the visibility and dependencies views with plain SELECT's
-	 * from tables.
-	 */
-	CREATE TABLE _fake_visibility(
-		empire_id			INT ,
-		technology_name_id	INT ,
-		emptech_visible		BOOLEAN
-	);
-	CREATE OR REPLACE VIEW emp.technology_visibility_view
-		AS SELECT * FROM _fake_visibility;
-	CREATE TABLE _fake_deps(
-		technology_name_id		INT ,
-		technology_dependencies	TEXT
-	);
-	CREATE OR REPLACE VIEW defs.technology_dependencies_view
-		AS SELECT * FROM _fake_deps;
-
-	/* Insert empire states and data for fake views */
-	INSERT INTO emp.technologies (
-			empire_id , technology_name_id ,
-			emptech_state , emptech_points , emptech_priority
-		) VALUES (
-			_get_emp_name( 'emp1' ) , _get_string( 'tech1' ) ,
-			'KNOWN' , NULL , NULL
-		) , (
-			_get_emp_name( 'emp2' ) , _get_string( 'tech1' ) ,
-			'RESEARCH' , 228.9 , 0
-		) , (
-			_get_emp_name( 'emp3' ) , _get_string( 'tech1' ) ,
-			'RESEARCH' , 114 , 1
-		);
-	INSERT INTO _fake_visibility VALUES(
-		_get_emp_name( 'emp1' ) , _get_string( 'tech1' ) , TRUE 
-	) , (
-		_get_emp_name( 'emp2' ) , _get_string( 'tech1' ) , TRUE 
-	) , (
-		_get_emp_name( 'emp3' ) , _get_string( 'tech1' ) , FALSE 
-	);
-	INSERT INTO _fake_deps VALUES( _get_string( 'tech1' ) , 'deps are here' );
-	
-	-- ***** TESTS BEGIN HERE *****
-	SELECT plan( 3 );
-	
-	SELECT diag_test_name( 'emp.technologies_view - Known technology' );
-	SELECT set_eq( $$
-		SELECT emptech_id , emptech_state::TEXT , emptech_visible ,
-				technology_category , technology_name , technology_description ,
-				emptech_points , emptech_priority IS NULL AS ep_null ,
-				emptech_ratio IS NULL AS er_null ,
-				technology_price , technology_dependencies
-			FROM emp.technologies_view
-			WHERE empire_id = _get_emp_name( 'emp1' )
-	$$ , $$ VALUES(
-		_get_emp_name( 'emp1' ) || ',tech1,true' , 'KNOWN' , TRUE ,
-		'techCategory1' , 'tech1' , 'techDescription1' ,
-		456 ,  TRUE , TRUE , 123 , 'deps are here'
-	) $$ );
-	
-	SELECT diag_test_name( 'emp.technologies_view - In-progress, visible technology' );
-	SELECT set_eq( $$
-		SELECT emptech_id , emptech_state::TEXT , emptech_visible ,
-				technology_category , technology_name , technology_description ,
-				emptech_points , emptech_priority , emptech_ratio ,
-				technology_price , technology_dependencies
-			FROM emp.technologies_view
-			WHERE empire_id = _get_emp_name( 'emp2' )
-	$$ , $$ VALUES(
-		_get_emp_name( 'emp2' ) || ',tech1,true' , 'RESEARCH' , TRUE ,
-		'techCategory1' , 'tech1' , 'techDescription1' ,
-		228 ,  0 , 50 , 123 , 'deps are here'
-	) $$ );
-
-	SELECT diag_test_name( 'emp.technologies_view - In-progress, unknown technology' );
-	SELECT set_eq( $$
-		SELECT emptech_id , emptech_state::TEXT , emptech_visible ,
-				technology_category , technology_name IS NULL AS n1 , technology_description IS NULL AS n2 ,
-				emptech_points IS NULL AS n3 , emptech_priority , emptech_ratio ,
-				technology_price IS NULL AS n4, technology_dependencies
-			FROM emp.technologies_view
-			WHERE empire_id = _get_emp_name( 'emp3' )
-	$$ , $$ VALUES(
-		_get_emp_name( 'emp3' ) || ',tech1,false' , 'RESEARCH' , FALSE ,
-		'techCategory1' , TRUE, TRUE ,
-		TRUE , 1 , 25 , TRUE , 'deps are here'
-	) $$ );
-	SELECT * FROM finish( );
-ROLLBACK;
diff --git a/legacyworlds-server-data/db-structure/tests/admin/040-functions/053-generator-basics/010-list-random-planets-in.sql b/legacyworlds-server-data/db-structure/tests/admin/040-functions/053-generator-basics/010-list-random-planets-in.sql
deleted file mode 100644
index ba89819..0000000
--- a/legacyworlds-server-data/db-structure/tests/admin/040-functions/053-generator-basics/010-list-random-planets-in.sql
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Test the verse.list_random_planets_in() function
- */
-BEGIN;
-	
-	/* We need two systems with one planet each. Systems will be located at
-	 * (0,0) and (1,1).
-	 */
-	\i utils/strings.sql
-	\i utils/accounts.sql
-	\i utils/naming.sql
-	\i utils/universe.sql
-	SELECT _create_raw_planets( 10 , 'test' );
-
-	/***** TESTS BEGIN HERE *****/ 
-	SELECT plan( 5 );
-
-	SELECT diag_test_name( 'verse.list_random_planets_in() - Empty set if count = 0' );
-	SELECT is_empty( $$
-		SELECT * FROM verse.list_random_planets_in( ROW( 0 , 0 , 1 , 1 ) , 0 )
-	$$ );
-
-	SELECT diag_test_name( 'verse.list_random_planets_in() - Empty set if outside of existing universe' );
-	SELECT is_empty( $$
-		SELECT * FROM verse.list_random_planets_in( ROW( 2 , 2 , 3 , 3 ) , 2 )
-	$$ );
-
-	SELECT diag_test_name( 'verse.list_random_planets_in() - Requested count > actual count' );
-	SELECT is( COUNT(*) , 5::BIGINT )
-		FROM verse.list_random_planets_in( ROW( 1 , 1 , 2 , 2 ) , 7 );
-
-	SELECT diag_test_name( 'verse.list_random_planets_in() - Requested count = actual count' );
-	SELECT is( COUNT(*) , 5::BIGINT )
-		FROM verse.list_random_planets_in( ROW( 1 , 1 , 2 , 2 ) , 5 );
-
-	SELECT diag_test_name( 'verse.list_random_planets_in() - Requested count < actual count' );
-	SELECT is( COUNT(*) , 4::BIGINT )
-		FROM verse.list_random_planets_in( ROW( 1 , 1 , 2 , 2 ) , 4 );
-
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/admin/040-functions/055-generator-resources/010-collect-resprov-statistics.sql b/legacyworlds-server-data/db-structure/tests/admin/040-functions/055-generator-resources/010-collect-resprov-statistics.sql
deleted file mode 100644
index 2b61f59..0000000
--- a/legacyworlds-server-data/db-structure/tests/admin/040-functions/055-generator-resources/010-collect-resprov-statistics.sql
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Test the verse.collect_resprov_statistics( ) function
- */
-BEGIN;
-	\i utils/strings.sql
-	\i utils/resources.sql
-	\i utils/accounts.sql
-	\i utils/naming.sql
-	\i utils/universe.sql
-	SELECT _create_natural_resources( 2 , 'testResource' );
-	SELECT _create_raw_planets( 5 , 'testPlanet' );
-
-	/****** TESTS BEGIN HERE ******/
-	SELECT plan( 6 );
-
-	SELECT verse.collect_resprov_statistics( );
-	
-	SELECT diag_test_name( 'verse.collect_resprov_statistics( ) - Temporary table creation' );
-	SELECT has_table( 'rp_stats' );
-
-	SELECT diag_test_name( 'verse.collect_resprov_statistics( ) - Temporary table rows' );
-	SELECT is( COUNT(*)::INT , 2 ) FROM rp_stats;
-
-	SELECT diag_test_name( 'verse.collect_resprov_statistics( ) - rp_stats contains definition data' );
-	SELECT is( COUNT(*)::INT , 2 )
-		FROM (
-			SELECT ( d.natres_quantity_avg = s.quantity_avg
-					AND d.natres_quantity_dev = s.quantity_dev
-					AND d.natres_difficulty_avg = s.difficulty_avg
-					AND d.natres_difficulty_dev = s.difficulty_dev
-					AND d.natres_recovery_avg = s.recovery_avg
-					AND d.natres_recovery_dev = s.recovery_dev
-					AND d.natres_p_presence = s.presence ) AS ok
-				FROM rp_stats s
-					INNER JOIN defs.natural_resources d
-						USING ( resource_name_id )
-			) sq
-		WHERE sq.ok;
-
-	SELECT diag_test_name( 'verse.collect_resprov_statistics( ) - rp_stats contains planet counts' );
-	SELECT is( COUNT(*)::INT , 2 )
-		FROM (
-			SELECT planets = 5 AS ok
-				FROM rp_stats
-			) sq
-		WHERE sq.ok;
-
-	SELECT diag_test_name( 'verse.collect_resprov_statistics( ) - rp_stats sums at 0 with no providers' );
-	SELECT is( COUNT(*)::INT , 2 )
-		FROM (
-			SELECT ( providers = 0 AND quantity = 0
-					AND difficulty = 0 AND recovery = 0 ) AS ok
-				FROM rp_stats
-			) sq
-		WHERE sq.ok;
-
-	DROP TABLE rp_stats;
-	SELECT _create_resource_provider( 'testPlanet1' , 'testResource1' );
-	SELECT verse.collect_resprov_statistics( );
-
-	SELECT diag_test_name( 'verse.collect_resprov_statistics( ) - rp_stats sums' );
-	SELECT is( COUNT(*)::INT , 1 )
-		FROM (
-			SELECT ( resource_name_id = _get_string( 'testResource1' )
-					AND providers = 1 AND quantity = 100
-					AND difficulty = 0.5 AND recovery = 0.5 ) AS ok
-				FROM rp_stats
-			) sq
-		WHERE sq.ok;
-
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/admin/040-functions/055-generator-resources/020-compute-rpp-delta.sql b/legacyworlds-server-data/db-structure/tests/admin/040-functions/055-generator-resources/020-compute-rpp-delta.sql
deleted file mode 100644
index 2a14193..0000000
--- a/legacyworlds-server-data/db-structure/tests/admin/040-functions/055-generator-resources/020-compute-rpp-delta.sql
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Test the verse.compute_rpp_delta( ) function
- */
-BEGIN;
-	SELECT plan( 12 );
-	
-	/* First set of tests: results of the function with a fake
-	 * verse.random_deviation() that always returns the minimal possible
-	 * value.
-	 */
-	CREATE OR REPLACE FUNCTION verse.random_deviation( _mean DOUBLE PRECISION , _deviation DOUBLE PRECISION )
-		RETURNS DOUBLE PRECISION
-		STRICT VOLATILE
-	AS $$
-		SELECT $1 - $2;
-	$$ LANGUAGE SQL;
-
-	SELECT diag_test_name( 'verse.compute_rpp_delta( ) - No existing value, random at minimal value' );
-	SELECT is( verse.compute_rpp_delta( 0 , 10 , 0 , 1 , 0.5 )::NUMERIC , 5.0 );
-	SELECT diag_test_name( 'verse.compute_rpp_delta( ) - Existing value below minimum, random at minimal value' );
-	SELECT is( verse.compute_rpp_delta( 10 , 10 , 0 , 1 , 0.5 )::NUMERIC , 10.0 );
-	SELECT diag_test_name( 'verse.compute_rpp_delta( ) - Existing value at minimum, random at minimal value' );
-	SELECT is( verse.compute_rpp_delta( 10 , 10 , 5 , 1 , 0.5 )::NUMERIC , 5.0 );
-	SELECT diag_test_name( 'verse.compute_rpp_delta( ) - Existing value at average, random at minimal value' );
-	SELECT is( verse.compute_rpp_delta( 10 , 10 , 10 , 1 , 0.5 )::NUMERIC , 5.0 );
-	SELECT diag_test_name( 'verse.compute_rpp_delta( ) - Existing value at maximum, random at minimal value' );
-	SELECT is( verse.compute_rpp_delta( 10 , 10 , 15 , 1 , 0.5 )::NUMERIC , 5.0 );
-	SELECT diag_test_name( 'verse.compute_rpp_delta( ) - Existing value over maximum, random at minimal value' );
-	SELECT is( verse.compute_rpp_delta( 10 , 10 , 20 , 1 , 0.5 )::NUMERIC , 5.0 );
-
-	/* Second set of tests: results of the function with a fake
-	 * verse.random_deviation() that always returns the maximal possible
-	 * value.
-	 */
-	CREATE OR REPLACE FUNCTION verse.random_deviation( _mean DOUBLE PRECISION , _deviation DOUBLE PRECISION )
-		RETURNS DOUBLE PRECISION
-		STRICT VOLATILE
-	AS $$
-		SELECT $1 + $2;
-	$$ LANGUAGE SQL;
-
-	SELECT diag_test_name( 'verse.compute_rpp_delta( ) - No existing value, random at maximal value' );
-	SELECT is( verse.compute_rpp_delta( 0 , 10 , 0 , 1 , 0.5 )::NUMERIC , 15.0 );
-	SELECT diag_test_name( 'verse.compute_rpp_delta( ) - Existing value below minimum, random at maximal value' );
-	SELECT is( verse.compute_rpp_delta( 10 , 10 , 0 , 1 , 0.5 )::NUMERIC , 15.0 );
-	SELECT diag_test_name( 'verse.compute_rpp_delta( ) - Existing value at minimum, random at maximal value' );
-	SELECT is( verse.compute_rpp_delta( 10 , 10 , 5 , 1 , 0.5 )::NUMERIC , 15.0 );
-	SELECT diag_test_name( 'verse.compute_rpp_delta( ) - Existing value at average, random at maximal value' );
-	SELECT is( verse.compute_rpp_delta( 10 , 10 , 10 , 1 , 0.5 )::NUMERIC , 15.0 );
-	SELECT diag_test_name( 'verse.compute_rpp_delta( ) - Existing value at maximum, random at maximal value' );
-	SELECT is( verse.compute_rpp_delta( 10 , 10 , 15 , 1 , 0.5 )::NUMERIC , 15.0 );
-	SELECT diag_test_name( 'verse.compute_rpp_delta( ) - Existing value over maximum, random at maximal value' );
-	SELECT is( verse.compute_rpp_delta( 10 , 10 , 20 , 1 , 0.5 )::NUMERIC , 10.0 );
-
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/admin/040-functions/055-generator-resources/030-create-resource-provider.sql b/legacyworlds-server-data/db-structure/tests/admin/040-functions/055-generator-resources/030-create-resource-provider.sql
deleted file mode 100644
index 68f7eeb..0000000
--- a/legacyworlds-server-data/db-structure/tests/admin/040-functions/055-generator-resources/030-create-resource-provider.sql
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Test the verse.create_resource_provider( ) function
- */
-BEGIN;
-
-	/* Before any actual testing, we need to drop FK constraints on the RP
-	 * table and create a table which will contain the results of the
-	 * function.
-	 */
-
-	ALTER TABLE verse.resource_providers
-		DROP CONSTRAINT fk_resprov_planet ,
-		DROP CONSTRAINT fk_resprov_resource;
-
-	CREATE TEMPORARY TABLE test_result(
-			_providers_left	INT ,
-			_tot_quantity	DOUBLE PRECISION ,
-			_tot_difficulty	DOUBLE PRECISION ,
-			_tot_recovery	DOUBLE PRECISION
-	) ON COMMIT DROP;
-
-	/* Now we call the function using a crafted resource statistics row which
-	 * will make it easy to check the results.
-	 */
-	INSERT INTO test_result
-		SELECT * FROM verse.create_resource_provider( 12 ,
-			ROW( 34 , 0.0 , 0.0 , 0.0 , 0.0 , 5.0 , 0.0 , 0.0 , 0.75 , 0.0 , 0.0 , 0.5 , 0 ) ,
-			2 , 10 , 1.5 , 1 );
-
-
-	/***** TESTS BEGIN HERE *****/
-	SELECT plan( 11 );
-
-
-	SELECT diag_test_name( 'verse.create_resource_provider( ) - Output exists' );
-	SELECT is( COUNT(*)::INT , 1 ) FROM test_result;
-	SELECT diag_test_name( 'verse.create_resource_provider( ) - _providers_left updated' );
-	SELECT is( _providers_left , 1 ) FROM test_result;
-	SELECT diag_test_name( 'verse.create_resource_provider( ) - _tot_quantity updated' );
-	SELECT is( _tot_quantity::NUMERIC , 5.0 ) FROM test_result;
-	SELECT diag_test_name( 'verse.create_resource_provider( ) - _tot_difficulty updated' );
-	SELECT is( _tot_difficulty::NUMERIC , 0.75 ) FROM test_result;
-	SELECT diag_test_name( 'verse.create_resource_provider( ) - _tot_recovery updated' );
-	SELECT is( _tot_recovery::NUMERIC , 0.5 ) FROM test_result;
-
-	SELECT diag_test_name( 'verse.create_resource_provider( ) - Resource provider exists' );
-	SELECT is( COUNT(*)::INT , 1 ) FROM verse.resource_providers;
-	SELECT diag_test_name( 'verse.create_resource_provider( ) - Resource provider primary key' );
-	SELECT is( COUNT(*)::INT , 1 ) FROM verse.resource_providers
-		WHERE planet_id = 12 AND resource_name_id = 34;
-	SELECT diag_test_name( 'verse.create_resource_provider( ) - Resource provider is full' );
-	SELECT is( COUNT(*)::INT , 1 ) FROM verse.resource_providers
-		WHERE resprov_quantity = resprov_quantity_max;
-	SELECT diag_test_name( 'verse.create_resource_provider( ) - Resource provider maximal quantity' );
-	SELECT is( resprov_quantity_max::NUMERIC , 5.0 ) FROM verse.resource_providers;
-	SELECT diag_test_name( 'verse.create_resource_provider( ) - Resource provider extraction difficulty' );
-	SELECT is( resprov_difficulty::NUMERIC , 0.75 ) FROM verse.resource_providers;
-	SELECT diag_test_name( 'verse.create_resource_provider( ) - Resource provider recovery rate' );
-	SELECT is( resprov_recovery::NUMERIC , 0.5 ) FROM verse.resource_providers;
-
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/admin/040-functions/055-generator-resources/040-create-resource-providers-with-type.sql b/legacyworlds-server-data/db-structure/tests/admin/040-functions/055-generator-resources/040-create-resource-providers-with-type.sql
deleted file mode 100644
index d491740..0000000
--- a/legacyworlds-server-data/db-structure/tests/admin/040-functions/055-generator-resources/040-create-resource-providers-with-type.sql
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Check the variant of verse.create_resource_providers( ) which takes a
- * resource statistics record as a parameter.
- */
-BEGIN;
-
-	/* Temporary table which will store information about calls to the
-	 * verse.create_resource_provider( ) function
-	 */
-	CREATE TEMPORARY TABLE test_result(
-		planet		INT ,
-		resource	INT ,
-		quantity	DOUBLE PRECISION ,
-		difficulty	DOUBLE PRECISION ,
-		recovery	DOUBLE PRECISION
-	) ON COMMIT DROP;
-
-	/* Replace verse.list_random_planets_in() with a function that simply
-	 * counts.
-	 */
-	CREATE OR REPLACE FUNCTION verse.list_random_planets_in(
-				_area verse.generator_area_type ,
-				_count INT )
-			RETURNS SETOF INT
-			STRICT VOLATILE
-			SECURITY INVOKER
-		AS $list_random_planets_in$
-	DECLARE
-		i INT;
-	BEGIN
-		FOR i IN 1 .. _count
-		LOOP
-			RETURN NEXT i;
-		END LOOP;
-	END;
-	$list_random_planets_in$ LANGUAGE PLPGSQL;
-	
-	/* Replace verse.create_resource_provider( ) with a function that writes
-	 * to the test_result temporary table.
-	 */
-	CREATE OR REPLACE FUNCTION verse.create_resource_provider(
-			_planet					INT ,
-			_data					verse.resprov_generator_type ,
-			INOUT _providers_left	INT ,
-			INOUT _tot_quantity		DOUBLE PRECISION ,
-			INOUT _tot_difficulty	DOUBLE PRECISION ,
-			INOUT _tot_recovery		DOUBLE PRECISION )
-		STRICT VOLATILE
-		SECURITY INVOKER
-	AS $create_resource_provider$
-	BEGIN
-		INSERT INTO test_result VALUES(
-			_planet , _data.resource_name_id ,
-			_tot_quantity / _providers_left::DOUBLE PRECISION ,
-			_tot_difficulty / _providers_left::DOUBLE PRECISION ,
-			_tot_recovery / _providers_left::DOUBLE PRECISION
-		);
-		
-		_tot_quantity := ( _providers_left - 1 ) * _tot_quantity / _providers_left;
-		_tot_difficulty := ( _providers_left - 1 ) * _tot_difficulty / _providers_left;
-		_tot_recovery := ( _providers_left - 1 ) * _tot_recovery / _providers_left;
-		_providers_left := _providers_left - 1;
-	END;
-	$create_resource_provider$ LANGUAGE PLPGSQL;
-
-	/***** TESTS BEGIN HERE *****/
-	SELECT plan( 11 );
-
-
-	/* First set of test: empty universe */
-	SELECT verse.create_resource_providers(
-		ROW( 0 , 0 , 1 , 1 ) ,
-		ROW( 42 , 0.0 , 0.0 , 0.5 , 0.0 , 5.0 , 0.0 , 0.0 , 0.75 , 0.0 , 0.0 , 0.5 , 0 )
-	);
-
-	SELECT diag_test_name( 'verse.create_resource_provider( area , stats ) - Empty universe - Providers created' );
-	SELECT is( COUNT(*)::INT , 10 ) FROM test_result WHERE resource = 42;
-	SELECT diag_test_name( 'verse.create_resource_provider( area , stats ) - Empty universe - Planet identifiers' );
-	SELECT results_eq(
-		'SELECT planet FROM test_result ORDER BY planet' ,
-		ARRAY[ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 ] 
-	);	
-
-	SELECT diag_test_name( 'verse.create_resource_provider( area , stats ) - Empty universe - Total quantity' );
-	SELECT is( SUM(quantity)::NUMERIC , 50.0 ) FROM test_result;
-	SELECT diag_test_name( 'verse.create_resource_provider( area , stats ) - Empty universe - Quantity per planet' );
-	SELECT is( COUNT(*)::INT , 10 ) FROM test_result
-		WHERE quantity = 5;
-
-	SELECT diag_test_name( 'verse.create_resource_provider( area , stats ) - Empty universe - Total difficulty' );
-	SELECT is( SUM(difficulty)::NUMERIC , 7.5 ) FROM test_result;
-	SELECT diag_test_name( 'verse.create_resource_provider( area , stats ) - Empty universe - Difficulty per planet' );
-	SELECT is( COUNT(*)::INT , 10 ) FROM test_result
-		WHERE difficulty = 0.75;
-
-	SELECT diag_test_name( 'verse.create_resource_provider( area , stats ) - Empty universe - Total recovery rate' );
-	SELECT is( SUM(recovery)::NUMERIC , 5.0 ) FROM test_result;
-	SELECT diag_test_name( 'verse.create_resource_provider( area , stats ) - Empty universe - Recovery rate per planet' );
-	SELECT is( COUNT(*)::INT , 10 ) FROM test_result
-		WHERE recovery = 0.5;
-
-
-	/* Second set of tests: balancing providers presence */
-	SELECT diag_test_name( 'verse.create_resource_provider( area , stats ) - Providers created in balanced universe' );
-	DELETE FROM test_result;
-	SELECT verse.create_resource_providers(
-		ROW( 0 , 0 , 1 , 1 ) ,
-		ROW( 42 , 20.0 , 10.0 , 0.5 , 0.0 , 5.0 , 0.0 , 0.0 , 0.75 , 0.0 , 0.0 , 0.5 , 0 )
-	);
-	SELECT is( COUNT(*)::INT , 10 ) FROM test_result WHERE resource = 42;
-
-	SELECT diag_test_name( 'verse.create_resource_provider( area , stats ) - Providers created in universe with low providers count' );
-	DELETE FROM test_result;
-	SELECT verse.create_resource_providers(
-		ROW( 0 , 0 , 1 , 1 ) ,
-		ROW( 42 , 20.0 , 5.0 , 0.5 , 0.0 , 5.0 , 0.0 , 0.0 , 0.75 , 0.0 , 0.0 , 0.5 , 0 )
-	);
-	SELECT is( COUNT(*)::INT , 15 ) FROM test_result WHERE resource = 42;
-
-	SELECT diag_test_name( 'verse.create_resource_provider( area , stats ) - Providers created in universe with high providers count' );
-	DELETE FROM test_result;
-	SELECT verse.create_resource_providers(
-		ROW( 0 , 0 , 1 , 1 ) ,
-		ROW( 42 , 20.0 , 15.0 , 0.5 , 0.0 , 5.0 , 0.0 , 0.0 , 0.75 , 0.0 , 0.0 , 0.5 , 0 )
-	);
-	SELECT is( COUNT(*)::INT , 5 ) FROM test_result WHERE resource = 42;
-
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/admin/040-functions/055-generator-resources/050-create-resource-providers.sql b/legacyworlds-server-data/db-structure/tests/admin/040-functions/055-generator-resources/050-create-resource-providers.sql
deleted file mode 100644
index 6c5ea83..0000000
--- a/legacyworlds-server-data/db-structure/tests/admin/040-functions/055-generator-resources/050-create-resource-providers.sql
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Test the "main" verse.create_resource_providers( ) function
- */
-BEGIN;
-
-	/* Create a dummy rp_stats table that contains a few identifiers */
-	 CREATE TEMP TABLE rp_stats
-	 	OF verse.resprov_generator_type
-	 	ON COMMIT DROP;
-	 INSERT INTO rp_stats ( resource_name_id )
-	 	VALUES ( 1 ) , ( 2 ) , ( 3 ) , ( 4 );
-
-	 /* Replace the verse.create_resource_providers( area , type ) function
-	  * with a function that deletes the resource type it was given from
-	  * rp_stats.
-	  */
-	CREATE OR REPLACE FUNCTION verse.create_resource_providers(
-			_area verse.generator_area_type ,
-			_data verse.resprov_generator_type )
-		RETURNS VOID
-		STRICT VOLATILE
-		SECURITY INVOKER
-	AS $create_resource_providers$
-	BEGIN
-		DELETE FROM rp_stats WHERE resource_name_id = _data.resource_name_id;
-	END;
-	$create_resource_providers$ LANGUAGE PLPGSQL;
-
-	SELECT plan(1);
-	SELECT diag_test_name( 'verse.create_resource_providers( area ) - Calls to per-type function' );
-	SELECT verse.create_resource_providers( ROW( 0 , 0 , 1 , 1 ) );
-	SELECT is( COUNT(*)::INT , 0 ) FROM rp_stats;
-	
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/admin/040-functions/145-resource-providers/010-compute-provider-regeneration.sql b/legacyworlds-server-data/db-structure/tests/admin/040-functions/145-resource-providers/010-compute-provider-regeneration.sql
deleted file mode 100644
index f58a6c7..0000000
--- a/legacyworlds-server-data/db-structure/tests/admin/040-functions/145-resource-providers/010-compute-provider-regeneration.sql
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
- * Test the verse.compute_provider_regeneration() function
- */
-BEGIN;
-
-	/* Define the necessary constants using default values */
-	SELECT sys.uoc_constant( 'game.resources.recovery' , '(test)' , 'Resources' , 0.01 );
-	SELECT sys.uoc_constant( 'game.resources.recoveryDampening' , '(test)' , 'Resources' , 1.5 );
-	
-	/* Make sure the functions are not immutable during the tests */
-	ALTER FUNCTION sys.get_constant( TEXT ) VOLATILE;
-	ALTER FUNCTION verse.compute_provider_regeneration( DOUBLE PRECISION , DOUBLE PRECISION , DOUBLE PRECISION ) VOLATILE;
-	
-	/****** TESTS BEGIN HERE ******/
-	SELECT plan( 6 );
-
-
-	SELECT diag_test_name( 'verse.compute_provider_regeneration() - no regeneration at maximal quantity' );
-	CREATE FUNCTION _run_tests( ) RETURNS BOOLEAN AS $$
-	DECLARE
-		rr	DOUBLE PRECISION;
-	BEGIN
-		rr := 0.05;
-		WHILE rr < 1
-		LOOP
-			IF verse.compute_provider_regeneration( 100.0 , 100.0 , rr ) > 100.0
-			THEN
-				RETURN FALSE;
-			END IF;
-			rr := rr + 0.05;
-		END LOOP;
-		RETURN TRUE;
-	END;
-	$$ LANGUAGE PLPGSQL;
-	SELECT ok( _run_tests() );
-	DROP FUNCTION _run_tests( );
-
-
-	SELECT diag_test_name( 'verse.compute_provider_regeneration() - regeneration >= 0' );
-	CREATE FUNCTION _run_tests( ) RETURNS BOOLEAN AS $$
-	DECLARE
-		qt	DOUBLE PRECISION;
-		rr	DOUBLE PRECISION;
-	BEGIN
-		qt := 0;
-		WHILE qt < 100.0
-		LOOP
-			rr := 0.05;
-			WHILE rr < 1
-			LOOP
-				IF verse.compute_provider_regeneration( qt , 100.0 , rr ) <= qt
-				THEN
-					RETURN FALSE;
-				END IF;
-				rr := rr + 0.05;
-			END LOOP;
-			qt := qt + 5;
-		END LOOP;
-		RETURN TRUE;
-	END;
-	$$ LANGUAGE PLPGSQL;
-	SELECT ok( _run_tests() );
-	DROP FUNCTION _run_tests( );
-
-
-	SELECT diag_test_name( 'verse.compute_provider_regeneration() - higher quantity => slower regeneration' );
-	CREATE FUNCTION _run_tests( ) RETURNS BOOLEAN AS $$
-	DECLARE
-		pdiff	DOUBLE PRECISION;
-		diff	DOUBLE PRECISION;
-		qt		DOUBLE PRECISION;
-		rr		DOUBLE PRECISION;
-	BEGIN
-		rr := 0.05;
-		WHILE rr < 1
-		LOOP
-			qt := 0;
-			WHILE qt < 100.0
-			LOOP
-				diff := verse.compute_provider_regeneration( qt , 100.0 , rr ) - qt;
-				IF qt <> 0 AND diff >= pdiff
-				THEN
-					RETURN FALSE;
-				END IF;
-				pdiff := diff;
-				qt := qt + 5;
-			END LOOP;
-			rr := rr + 0.05;
-		END LOOP;
-		RETURN TRUE;
-	END;
-	$$ LANGUAGE PLPGSQL;
-	SELECT ok( _run_tests() );
-	DROP FUNCTION _run_tests( );
-
-
-	SELECT diag_test_name( 'verse.compute_provider_regeneration() - higher recovery rate => faster regeneration' );
-	CREATE FUNCTION _run_tests( ) RETURNS BOOLEAN AS $$
-	DECLARE
-		pdiff	DOUBLE PRECISION;
-		diff	DOUBLE PRECISION;
-		qt		DOUBLE PRECISION;
-		rr		DOUBLE PRECISION;
-	BEGIN
-		qt := 0;
-		WHILE qt < 100.0
-		LOOP
-			rr := 0.05;
-			WHILE rr < 1
-			LOOP
-				diff := verse.compute_provider_regeneration( qt , 100.0 , rr ) - qt;
-				IF rr > 0.06 AND diff <= pdiff
-				THEN
-					RETURN FALSE;
-				END IF;
-				pdiff := diff;
-				rr := rr + 0.05;
-			END LOOP;
-			qt := qt + 5;
-		END LOOP;
-		RETURN TRUE;
-	END;
-	$$ LANGUAGE PLPGSQL;
-	SELECT ok( _run_tests() );
-	DROP FUNCTION _run_tests( );
-
-
-	SELECT diag_test_name( 'verse.compute_provider_regeneration() - effect of game.resources.recovery' );
-	CREATE FUNCTION _run_tests( ) RETURNS BOOLEAN AS $$
-	DECLARE
-		pdiff	DOUBLE PRECISION;
-		diff	DOUBLE PRECISION;
-		qt		DOUBLE PRECISION;
-		rr		DOUBLE PRECISION;
-	BEGIN
-		qt := 0;
-		WHILE qt < 100.0
-		LOOP
-			rr := 0.01;
-			WHILE rr < 1
-			LOOP
-				UPDATE sys.constant_definitions
-					SET c_value = rr
-					WHERE name = 'game.resources.recovery';
-				diff := verse.compute_provider_regeneration( qt , 100.0 , 0.5 ) - qt;
-				IF rr > 0.011 AND diff <= pdiff
-				THEN
-					RETURN FALSE;
-				END IF;
-				pdiff := diff;
-				rr := rr + 0.01;
-			END LOOP;
-			qt := qt + 5;
-		END LOOP;
-		RETURN TRUE;
-	END;
-	$$ LANGUAGE PLPGSQL;
-	SELECT ok( _run_tests() );
-	DROP FUNCTION _run_tests( );
-	UPDATE sys.constant_definitions
-		SET c_value = 0.01
-		WHERE name = 'game.resources.recovery';
-
-
-
-	SELECT diag_test_name( 'verse.compute_provider_regeneration() - effect of game.resources.recoveryDampening' );
-	CREATE FUNCTION _run_tests( ) RETURNS BOOLEAN AS $$
-	DECLARE
-		pdiff	DOUBLE PRECISION;
-		diff	DOUBLE PRECISION;
-		qt		DOUBLE PRECISION;
-		rrd		DOUBLE PRECISION;
-	BEGIN
-		qt := 5;
-		WHILE qt < 100.0
-		LOOP
-			rrd := 1;
-			WHILE rrd < 3
-			LOOP
-				UPDATE sys.constant_definitions
-					SET c_value = rrd
-					WHERE name = 'game.resources.recoveryDampening';
-				diff := verse.compute_provider_regeneration( qt , 100.0 , 0.5 ) - qt;
-				IF rrd > 1.01 AND diff >= pdiff
-				THEN
-					RETURN FALSE;
-				END IF;
-				pdiff := diff;
-				rrd := rrd + 0.25;
-			END LOOP;
-			qt := qt + 5;
-		END LOOP;
-		RETURN TRUE;
-	END;
-	$$ LANGUAGE PLPGSQL;
-	SELECT ok( _run_tests() );
-	DROP FUNCTION _run_tests( );
-	UPDATE sys.constant_definitions
-		SET c_value = 1.5
-		WHERE name = 'game.resources.recoveryDampening';
-
-
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/admin/040-functions/145-resource-providers/020-mining-settings-view.sql b/legacyworlds-server-data/db-structure/tests/admin/040-functions/145-resource-providers/020-mining-settings-view.sql
deleted file mode 100644
index 0c60575..0000000
--- a/legacyworlds-server-data/db-structure/tests/admin/040-functions/145-resource-providers/020-mining-settings-view.sql
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Test the emp.mining_settings_view view
- */
-BEGIN;
-	/* Create 1 natural resource, 3 planets and 2 empire names */
-	\i utils/strings.sql
-	\i utils/resources.sql
-	\i utils/accounts.sql
-	\i utils/naming.sql
-	\i utils/universe.sql
-	SELECT _create_natural_resources( 1 , 'testResource' );
-	SELECT _create_raw_planets( 3 , 'testPlanet' );
-	SELECT _create_emp_names( 2 , 'testEmp' );
-
-	/*
-	 * Create an empire which possesses a planet, but has no planet-specific
-	 * mining settings. Modify the default empire-wide settings so we can
-	 * check the results.
-	 * 
-	 * The planet only has a resource provider for one type of resource.
-	 */
-	SELECT emp.create_empire( _get_emp_name( 'testEmp1' ) , _get_map_name( 'testPlanet1' ) , 1 );
-	UPDATE emp.mining_settings
-		SET empmset_weight = 3
-		WHERE empire_id = _get_emp_name( 'testEmp1' )
-			AND resource_name_id = _get_string( 'testResource1' );
-	INSERT INTO verse.resource_providers ( planet_id , resource_name_id ,
-			resprov_quantity_max , resprov_quantity ,
-			resprov_difficulty , resprov_recovery )
-		VALUES (
-			 _get_map_name( 'testPlanet1' ) ,  _get_string( 'testResource1' ) ,
-			 100 , 50 ,
-			 0.5 , 0.5
-		);
-
-	/*
-	 * Add a resource provider to the second planet; create an empire which
-	 * owns the planet and has planet-specific settings for the resource
-	 * provider.
-	 * 
-	 * This empire also has settings for the testPlanet1 planet.
-	 */
-	INSERT INTO verse.resource_providers ( planet_id , resource_name_id ,
-			resprov_quantity_max , resprov_quantity ,
-			resprov_difficulty , resprov_recovery )
-		VALUES (
-			 _get_map_name( 'testPlanet2' ) ,  _get_string( 'testResource1' ) ,
-			 100 , 50 ,
-			 0.5 , 0.5
-		);
-	SELECT emp.create_empire( _get_emp_name( 'testEmp2' ) , _get_map_name( 'testPlanet2' ) , 1 );
-	INSERT INTO emp.planet_mining_settings(
-			empire_id , planet_id , resource_name_id , emppmset_weight
-		) VALUES (
-			_get_emp_name( 'testEmp2' ) , _get_map_name( 'testPlanet2' ) ,
-			_get_string( 'testResource1' ) , 0
-		) , (
-			_get_emp_name( 'testEmp2' ) , _get_map_name( 'testPlanet1' ) ,
-			_get_string( 'testResource1' ) , 0
-		);
-
-	/*
-	 * While the last planet is not owned by any empire, make sure it has a
-	 * resource provider.
-	 */
-	INSERT INTO verse.resource_providers ( planet_id , resource_name_id ,
-			resprov_quantity_max , resprov_quantity ,
-			resprov_difficulty , resprov_recovery )
-		VALUES (
-			 _get_map_name( 'testPlanet3' ) ,  _get_string( 'testResource1' ) ,
-			 100 , 50 ,
-			 0.5 , 0.5
-		);
-
-
-	/***** TESTS BEGIN HERE *****/
-	SELECT plan( 6 );
-
-	SELECT diag_test_name( 'emp.mining_settings_view - Ignore neutral planets' );
-	SELECT is( COUNT(*)::INT , 0 )
-		FROM emp.mining_settings_view
-		WHERE planet_id = _get_map_name( 'testPlanet3' );
-
-	SELECT diag_test_name( 'emp.mining_settings_view - Only display provided resources' );
-	SELECT is( COUNT(*)::INT , 1 )
-		FROM emp.mining_settings_view
-		WHERE planet_id = _get_map_name( 'testPlanet1' );
-	SELECT diag_test_name( 'emp.mining_settings_view - Settings from empire-wide table' );
-	SELECT ok( NOT mset_specific )
-		FROM emp.mining_settings_view
-		WHERE planet_id = _get_map_name( 'testPlanet1' );
-	SELECT diag_test_name( 'emp.mining_settings_view - Value from empire-wide table' );
-	SELECT is( mset_weight , 3 )
-		FROM emp.mining_settings_view
-		WHERE planet_id = _get_map_name( 'testPlanet1' );
-		
-	SELECT diag_test_name( 'emp.mining_settings_view - Settings from planet-specific table' );
-	SELECT ok( mset_specific )
-		FROM emp.mining_settings_view
-		WHERE planet_id = _get_map_name( 'testPlanet2' );
-	SELECT diag_test_name( 'emp.mining_settings_view - Value from planet-specific table' );
-	SELECT is( mset_weight , 0 )
-		FROM emp.mining_settings_view
-		WHERE planet_id = _get_map_name( 'testPlanet2' );
-
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/admin/040-functions/145-resource-providers/030-get-extraction-factor.sql b/legacyworlds-server-data/db-structure/tests/admin/040-functions/145-resource-providers/030-get-extraction-factor.sql
deleted file mode 100644
index 9a9bb34..0000000
--- a/legacyworlds-server-data/db-structure/tests/admin/040-functions/145-resource-providers/030-get-extraction-factor.sql
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Test the verse.get_extraction_factor() function
- */
-BEGIN;
-	/* Drop foreign keys on resource providers, then fill the table with
-	 * values which can be used to test some fundamental properties of
-	 * the computation, then create a view that returns computation results.
-	 */
-	ALTER TABLE verse.resource_providers
-		DROP CONSTRAINT fk_resprov_planet ,
-		DROP CONSTRAINT fk_resprov_resource;
-
-	CREATE FUNCTION _fill_providers( )
-			RETURNS VOID
-		AS $$
-	DECLARE
-		i	INT;
-		j	INT;
-	BEGIN
-		FOR i IN 0 .. 10
-		LOOP
-			FOR j IN 0 .. 10
-			LOOP
-				INSERT INTO verse.resource_providers(
-						planet_id , resource_name_id ,
-						resprov_quantity_max , resprov_quantity ,
-						resprov_difficulty , resprov_recovery
-					) VALUES (
-						i , j , 100 , j * 10 , i * 0.1 , 0.5
-					);
-			END LOOP;
-		END LOOP;
-	END;
-	$$ LANGUAGE PLPGSQL;
-	SELECT _fill_providers( );
-	DROP FUNCTION _fill_providers( );
-	
-	CREATE VIEW extraction_factor_view
-		AS SELECT planet_id , resource_name_id ,
-				verse.get_extraction_factor(
-					resprov_quantity / resprov_quantity_max ,
-					resprov_difficulty
-				) AS resprov_extraction
-			FROM verse.resource_providers;
-	
-	
-	/***** TESTS BEGIN HERE *****/
-	SELECT plan( 6 );
-
-	SELECT diag_test_name( 'verse.get_extraction_factor() - Range');
-	SELECT is_empty($$
-		SELECT * FROM extraction_factor_view
-			WHERE resprov_extraction NOT BETWEEN 0 AND 1
-	$$);
-
-	SELECT diag_test_name( 'verse.get_extraction_factor() - Full provider with difficulty 0 => extraction is 1');
-	SELECT is( resprov_extraction , 1.0::DOUBLE PRECISION )
-		FROM extraction_factor_view
-		WHERE planet_id = 0 AND resource_name_id = 10;
-	SELECT diag_test_name( 'verse.get_extraction_factor() - Full provider with difficulty 1 => extraction is 0.5');
-	SELECT is( resprov_extraction , 0.5::DOUBLE PRECISION )
-		FROM extraction_factor_view
-		WHERE planet_id = 10 AND resource_name_id = 10;
-	SELECT diag_test_name( 'verse.get_extraction_factor() - Empty provider => extraction is 0');
-	SELECT is_empty($$
-		SELECT * FROM extraction_factor_view
-			WHERE resource_name_id = 0 AND resprov_extraction > 0
-	$$);
-
-	SELECT diag_test_name( 'verse.get_extraction_factor() - At same quantity ratio, higher difficulty => lower extraction');
-	SELECT is_empty($$
-		SELECT * FROM extraction_factor_view v1
-				INNER JOIN extraction_factor_view v2
-					ON v1.resource_name_id = v2.resource_name_id
-			WHERE v1.planet_id > v2.planet_id
-				AND v1.resprov_extraction > v2.resprov_extraction
-	$$);
-
-	SELECT diag_test_name( 'verse.get_extraction_factor() - At same difficulty, higher quantity ratio => higher extraction');
-	SELECT is_empty($$
-		SELECT * FROM extraction_factor_view v1
-				INNER JOIN extraction_factor_view v2
-					ON v1.planet_id = v2.planet_id
-			WHERE v1.resource_name_id > v2.resource_name_id
-				AND v1.resprov_extraction < v2.resprov_extraction
-	$$);
-
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/admin/040-functions/145-resource-providers/040-get-planet-resources.sql b/legacyworlds-server-data/db-structure/tests/admin/040-functions/145-resource-providers/040-get-planet-resources.sql
deleted file mode 100644
index 39a081b..0000000
--- a/legacyworlds-server-data/db-structure/tests/admin/040-functions/145-resource-providers/040-get-planet-resources.sql
+++ /dev/null
@@ -1,187 +0,0 @@
-/*
- * Tests for the emp.get_planet_resources() function
- */
-BEGIN;
-	/*
-	 * We need two planets, one being owned by some empire, the other being
-	 * neutral. Both planets' resource records must exist. Both planets will
-	 * also include resource providers which will serve as tests for the
-	 * various rounding which takes place.
-	 * 
-	 * To avoid having to define actual natural resources, we disable the
-	 * foreign keys on resource providers and mining settings. We can't do
-	 * that for the empire, tho: we need an actual account as the translations
-	 * must be looked up.
-	 */
-
-	\i utils/strings.sql
-	SELECT _create_test_strings( 3 , 'resource' , 'Resource name ' );
-	SELECT _create_test_strings( 3 , 'rDesc' , 'Resource description ' );
-	SELECT _create_test_strings( 1 , 'rCat' , 'Resource category ' );
-	
-	INSERT INTO defs.resources (
-			resource_name_id , resource_description_id ,
-			resource_category_id , resource_weight
-		) VALUES (
-			_get_string( 'resource1' ) , _get_string( 'rDesc1' ) ,
-			_get_string( 'rCat1' ) , 2
-		) , (
-			_get_string( 'resource2' ) , _get_string( 'rDesc2' ) ,
-			NULL , 1
-		) , (
-			_get_string( 'resource3' ) , _get_string( 'rDesc3' ) ,
-			NULL , 3
-		);
-
-	\i utils/accounts.sql
-	\i utils/naming.sql
-	SELECT _create_emp_names( 1 , 'emp' );
-	INSERT INTO emp.empires( name_id , cash )
-		VALUES( _get_emp_name( 'emp1' ) , 0 );
-
-	ALTER TABLE emp.mining_settings DROP CONSTRAINT fk_empmset_resource;
-	INSERT INTO emp.mining_settings ( empire_id , resource_name_id )
-		SELECT _get_emp_name( 'emp1' ) , resource_name_id
-			FROM defs.resources;
-
-	\i utils/universe.sql
-	SELECT _create_raw_planets( 2 , 'planet' );
-	
-	INSERT INTO verse.planet_resources (
-			planet_id , resource_name_id , pres_income , pres_upkeep
-		) VALUES (
-			_get_map_name( 'planet1' ) , _get_string( 'resource1' ) ,
-			99.4 / 720.0 , 99.4 / 720.0
-		) , (
-			_get_map_name( 'planet1' ) , _get_string( 'resource2' ) ,
-			99.5 / 720.0 , 99.5 / 720.0
-		) , (
-			_get_map_name( 'planet1' ) , _get_string( 'resource3' ) ,
-			99.6 / 720.0 , 99.6 / 720.0
-		);
-	INSERT INTO verse.planet_resources ( planet_id , resource_name_id )
-		SELECT _get_map_name( 'planet2' ) , resource_name_id
-			FROM defs.resources;
-
-	ALTER TABLE verse.resource_providers DROP CONSTRAINT fk_resprov_resource;
-	INSERT INTO verse.resource_providers(
-			planet_id , resource_name_id , resprov_quantity_max ,
-			resprov_quantity , resprov_difficulty , resprov_recovery
-		) VALUES (
-			_get_map_name( 'planet1' ) , _get_string( 'resource1' ) , 99.4 ,
-			99.4 , 0.494 , 0.5
-		) ,  (
-			_get_map_name( 'planet1' ) , _get_string( 'resource2' ) , 99.5 ,
-			99.5 , 0.495 , 0.5
-		) ,  (
-			_get_map_name( 'planet2' ) , _get_string( 'resource1' ) , 100 ,
-			100 , 0.5 , 0.5
-		);
-
-	INSERT INTO emp.planets ( empire_id , planet_id )
-		VALUES ( _get_emp_name( 'emp1' ) , _get_map_name( 'planet1' ) );
-
-
-	/***** TESTS BEGIN HERE *****/
-	SELECT plan( 13 );
-
-	SELECT diag_test_name( 'emp.get_planet_resources() - No results on missing planets' );
-	SELECT is_empty( $$ SELECT * FROM emp.get_planet_resources( _get_bad_map_name( ) ) $$ );
-
-	SELECT diag_test_name( 'emp.get_planet_resources() - No results on neutral planets' );
-	SELECT is_empty( $$ SELECT * FROM emp.get_planet_resources( _get_map_name( 'planet2' ) ) $$ );
-	
-	SELECT diag_test_name( 'emp.get_planet_resources() - One row per resource type' );
-	SELECT is( COUNT(*)::INT , 3 ) FROM emp.get_planet_resources( _get_map_name( 'planet1' ) );
-	
-	SELECT diag_test_name( 'emp.get_planet_resources() - Row ordering' );
-	SELECT set_eq(
-		$$ SELECT resource_identifier , row_number() OVER ( )
-			FROM emp.get_planet_resources( _get_map_name( 'planet1' ) ) $$ ,
-		$$ VALUES (
-			'resource1' , 2
-		) , (
-			'resource2' , 1 
-		) , (
-			'resource3' , 3 
-		) $$
-	);
-	
-	SELECT diag_test_name( 'emp.get_planet_resources() - Name translation' );
-	SELECT is_empty( $$
-		SELECT *
-			FROM emp.get_planet_resources( _get_map_name( 'planet1' ) )
-			WHERE resource_name NOT LIKE 'Resource name %'
-	$$ );
-	
-	SELECT diag_test_name( 'emp.get_planet_resources() - Description translation' );
-	SELECT is_empty( $$
-		SELECT *
-			FROM emp.get_planet_resources( _get_map_name( 'planet1' ) )
-			WHERE resource_description NOT LIKE 'Resource description %'
-	$$ );
-	
-	SELECT diag_test_name( 'emp.get_planet_resources() - Category translation' );
-	SELECT is_empty( $$
-		SELECT *
-			FROM emp.get_planet_resources( _get_map_name( 'planet1' ) )
-			WHERE resource_identifier = 'resource1'
-				AND resource_category NOT LIKE 'Resource category %'
-	$$ );
-	
-	SELECT diag_test_name( 'emp.get_planet_resources() - NULL category -> NULL translation' );
-	SELECT is_empty( $$
-		SELECT *
-			FROM emp.get_planet_resources( _get_map_name( 'planet1' ) )
-			WHERE resource_identifier <> 'resource1'
-				AND resource_category IS NOT NULL
-	$$ );
-	
-	SELECT diag_test_name( 'emp.get_planet_resources() - Upkeep is valid and rounded up' );
-	SELECT is_empty( $$
-		SELECT *
-			FROM emp.get_planet_resources( _get_map_name( 'planet1' ) )
-			WHERE pres_upkeep IS NULL OR pres_upkeep <> 100
-	$$ );
-	
-	SELECT diag_test_name( 'emp.get_planet_resources() - Income is valid and rounded down' );
-	SELECT is_empty( $$
-		SELECT * FROM emp.get_planet_resources( _get_map_name( 'planet1' ) )
-			WHERE pres_income IS NULL OR pres_income <> 99
-	$$ );
-	
-	SELECT diag_test_name( 'emp.get_planet_resources() - No mining-related fields when there is no resource provider' );
-	SELECT is_empty( $$
-		SELECT * FROM emp.get_planet_resources( _get_map_name( 'planet1' ) )
-			WHERE resource_identifier = 'resource3' AND NOT (
-					resprov_capacity IS NULL
-					AND resprov_quantity IS NULL 
-					AND resprov_difficulty IS NULL
-					AND mset_weight IS NULL
-				);
-	$$ );
-	
-	SELECT diag_test_name( 'emp.get_planet_resources() - Resource provider fields are present' );
-	SELECT is_empty( $$
-		SELECT * FROM emp.get_planet_resources( _get_map_name( 'planet1' ) )
-			WHERE resource_identifier <> 'resource3' AND (
-					resprov_capacity IS NULL
-					OR resprov_quantity IS NULL 
-					OR resprov_difficulty IS NULL
-					OR mset_weight IS NULL
-				);
-	$$ );
-
-	SELECT diag_test_name( 'emp.get_planet_resources() - Resource provider values' );
-	SELECT set_eq( $$
-		SELECT resource_identifier , resprov_capacity , resprov_quantity , resprov_difficulty
-			FROM emp.get_planet_resources( _get_map_name( 'planet1' ) )
-			WHERE resource_identifier <> 'resource3'
-	$$ , $$ VALUES (
-		'resource1' , 99 , 99 , 49
-	) , (
-		'resource2' , 100 , 100 , 50 
-	) $$ );
-
-	SELECT *  FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/admin/040-functions/145-resource-providers/050-scaled-mining-weights-view.sql b/legacyworlds-server-data/db-structure/tests/admin/040-functions/145-resource-providers/050-scaled-mining-weights-view.sql
deleted file mode 100644
index 3ab6c0f..0000000
--- a/legacyworlds-server-data/db-structure/tests/admin/040-functions/145-resource-providers/050-scaled-mining-weights-view.sql
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Test emp.scaled_mining_weights_view
- */
-BEGIN;
-	/* Create a table which will server as an alternate source for
-	 * emp.mining_settings_view ; the table is not temporary (PostgreSQL
-	 * won't allow replacing the view otherwise), but will be dropped
-	 * on rollback anyway. 
-	 */
-	CREATE TABLE fake_mining_settings(
-		planet_id			INT ,
-		resource_name_id	INT ,
-		mset_weight			INT ,
-		mset_specific		BOOLEAN
-	);
-
-	CREATE OR REPLACE VIEW emp.mining_settings_view
-		AS SELECT * FROM fake_mining_settings;
-
-	/* Insert fake records for each possible mining setting */
-	INSERT INTO fake_mining_settings VALUES
-		( 1 , 0 , 0 , FALSE ) ,
-		( 1 , 1 , 1 , FALSE ) ,
-		( 1 , 2 , 2 , FALSE ) ,
-		( 1 , 3 , 3 , FALSE ) ,
-		( 1 , 4 , 4 , FALSE );
-
-	/***** TESTS BEGIN HERE *****/
-	SELECT plan( 2 );
-
-	SELECT diag_test_name( 'emp.scaled_mining_weights_view - Rows present' );
-	SELECT isnt( COUNT(*)::INT , 0 )
-		FROM emp.scaled_mining_weights_view;
-
-	SELECT diag_test_name( 'emp.scaled_mining_weights_view - weight = game.resources.weightBase ^ setting' );
-	SELECT sys.uoc_constant( 'game.resources.weightBase' , '(test)' , 'Resources' , 10.0 );
-	SELECT is_empty( $$
-		SELECT * FROM emp.scaled_mining_weights_view
-			WHERE pmc_weight IS NULL
-				OR pmc_weight <> POW( 10 , resource_name_id )
-	$$ );
-
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/admin/040-functions/145-resource-providers/060-total-mining-weights-view.sql b/legacyworlds-server-data/db-structure/tests/admin/040-functions/145-resource-providers/060-total-mining-weights-view.sql
deleted file mode 100644
index 91e6ef8..0000000
--- a/legacyworlds-server-data/db-structure/tests/admin/040-functions/145-resource-providers/060-total-mining-weights-view.sql
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Test emp.total_mining_weights_view
- */
-BEGIN;
-	/* Create a table which will server as an alternate source for
-	 * emp.scaled_mining_weights_view ; the table is not temporary (PostgreSQL
-	 * won't allow replacing the view otherwise), but will be dropped
-	 * on rollback anyway. 
-	 */
-	CREATE TABLE fake_mining_weights(
-		planet_id			INT ,
-		resource_name_id	INT ,
-		pmc_weight			DOUBLE PRECISION
-	);
-	
-	CREATE OR REPLACE VIEW emp.scaled_mining_weights_view
-		AS SELECT * FROM fake_mining_weights;
-
-	/* Insert fake records for two different planets */
-	INSERT INTO fake_mining_weights VALUES
-		( 1 , 0 , 1 ) ,
-		( 1 , 1 , 2 ) ,
-		( 2 , 0 , 4 ) ,
-		( 2 , 1 , 5 );
-
-	/***** TESTS BEGIN HERE *****/
-	SELECT plan( 1 );
-	
-	SELECT set_eq(
-		$$ SELECT * FROM emp.total_mining_weights_view $$ ,
-		$$ VALUES ( 1 , 3.0 ) , ( 2 , 9.0 ) $$
-	);
-
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/admin/040-functions/145-resource-providers/070-mining-compute-extraction.sql b/legacyworlds-server-data/db-structure/tests/admin/040-functions/145-resource-providers/070-mining-compute-extraction.sql
deleted file mode 100644
index 8748a59..0000000
--- a/legacyworlds-server-data/db-structure/tests/admin/040-functions/145-resource-providers/070-mining-compute-extraction.sql
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Test the emp.mining_compute_extraction() function
- */
-BEGIN;
-
-	/* Define the necessary constant */
-	SELECT sys.uoc_constant( 'game.resources.extraction' , '(test)' , 'Resources' , 10 );
-	SELECT sys.uoc_constant( 'game.happiness.strike' , '(test)' , 'Resources' , 0.5 );
-	
-	/* Make sure the functions are not immutable during the tests */
-	ALTER FUNCTION sys.get_constant( TEXT ) VOLATILE;
-	ALTER FUNCTION emp.mining_compute_extraction( emp.planet_mining_type ) VOLATILE;
-	
-	/* Replace verse.get_raw_production() with a function that returns a
-	 * value from a "temporary" table.
-	 */
-	CREATE TABLE fake_mining_production( production REAL );
-	CREATE OR REPLACE FUNCTION verse.get_raw_production( pid INT , pt building_output_type )
-		RETURNS REAL LANGUAGE SQL VOLATILE AS 'SELECT production FROM fake_mining_production';
-	INSERT INTO fake_mining_production VALUES ( 100 );
-	
-	/* Create a table that is used as the input for tests */
-	CREATE TABLE tests_input OF emp.planet_mining_type;
-	
-	-- ***** TESTS BEGIN HERE *****
-	SELECT plan( 9 );
-
-	INSERT INTO tests_input VALUES
-		( 0 , 0 , 1000 , 1000 , 0 , NULL , NULL , NULL , NULL ) ,  
-		( 1 , 1 , 10000 , 10000 , 0 , NULL , NULL , NULL , NULL ) ,  
-		( 2 , 2 , 100000 , 100000 , 0 , NULL , NULL , NULL , NULL );
-
-	SELECT diag_test_name( 'emp.mining_compute_extraction() - No empire -> no extraction' );
-	SELECT is_empty( $$
-		SELECT *
-			FROM tests_input
-			WHERE emp.mining_compute_extraction( ROW(
-					planet , resource , quantity , quantity_max ,
-					difficulty , empire , happiness , weight ,
-					total_weight ) )
-				<> 0 $$ );
-
-	DELETE FROM tests_input;
-	INSERT INTO tests_input VALUES
-		( 0 , 0 , 1000 , 1000 , 0 , 1 , 1 , 1 , 1 ) ,  
-		( 1 , 1 , 10000 , 10000 , 0 , 1 , 1 , 1 , 1 ) ,  
-		( 2 , 2 , 100000 , 100000 , 0 , 1 , 1 , 1 , 1 );
-
-	SELECT diag_test_name( 'emp.mining_compute_extraction() - Extracted quantity > 0 if empire and resources are present' );
-	SELECT is_empty( $$
-		SELECT *
-			FROM tests_input
-			WHERE emp.mining_compute_extraction( ROW(
-					planet , resource , quantity , quantity_max ,
-					difficulty , empire , happiness , weight ,
-					total_weight ) )
-				= 0 $$ );
-
-	SELECT diag_test_name( 'emp.mining_compute_extraction() - Extracted quantity does not change for same initial ratio' );
-	SELECT is( COUNT( DISTINCT emp.mining_compute_extraction( ROW(
-							planet , resource , quantity , quantity_max ,
-							difficulty , empire , happiness , weight ,
-							total_weight ) )
-				)::INT , 1 ) FROM tests_input;
-
-	UPDATE tests_input SET weight = 1 + planet , total_weight = 3;
-	SELECT diag_test_name( 'emp.mining_compute_extraction() - Result increases when weight/total weight ratio increases' );
-	SELECT set_eq(
-		$$ SELECT rank() OVER ( ORDER BY weight ) AS r1 ,
-					rank() OVER( ORDER BY emp.mining_compute_extraction( ROW(
-							planet , resource , quantity , quantity_max ,
-							difficulty , empire , happiness , weight ,
-							total_weight ) ) ) AS r2
-				FROM tests_input $$ ,
-		$$ VALUES ( 1 , 1 ) , ( 2 , 2 ) , ( 3 , 3 ) $$
-	);
-
-	UPDATE tests_input SET weight = total_weight , happiness = 0.5 + 0.25 * planet;
-	SELECT diag_test_name( 'emp.mining_compute_extraction() - Happiness does not affect result when greater than strike level' );
-	SELECT is( COUNT( DISTINCT emp.mining_compute_extraction( ROW(
-							planet , resource , quantity , quantity_max ,
-							difficulty , empire , happiness , weight ,
-							total_weight ) )
-				)::INT , 1 ) FROM tests_input;
-
-	UPDATE tests_input SET weight = total_weight , happiness = 0.2 * planet;
-	SELECT diag_test_name( 'emp.mining_compute_extraction() - Result increases with happiness when lower than strike level' );
-	SELECT set_eq(
-		$$ SELECT rank() OVER ( ORDER BY happiness ) AS r1 ,
-					rank() OVER( ORDER BY emp.mining_compute_extraction( ROW(
-							planet , resource , quantity , quantity_max ,
-							difficulty , empire , happiness , weight ,
-							total_weight ) ) ) AS r2
-				FROM tests_input $$ ,
-		$$ VALUES ( 1 , 1 ) , ( 2 , 2 ) , ( 3 , 3 ) $$
-	);
-
-	UPDATE fake_mining_production SET production = 10000;
-	UPDATE tests_input SET quantity = 1 , quantity_max = 1 , happiness = 1;
-	SELECT diag_test_name( 'emp.mining_compute_extraction() - Result <= quantity' );
-	SELECT is_empty(
-		$$ SELECT * FROM tests_input
-			WHERE quantity < emp.mining_compute_extraction( ROW(
-							planet , resource , quantity , quantity_max ,
-							difficulty , empire , happiness , weight ,
-							total_weight ) ) $$
-	);
-
-	UPDATE fake_mining_production SET production = 1;
-	UPDATE tests_input SET quantity = 100 * planet , quantity_max = 200;
-	SELECT diag_test_name( 'emp.mining_compute_extraction() - Result decreases when quantity/capacity ratio decreases' );
-	SELECT set_eq(
-		$$ SELECT rank() OVER ( ORDER BY quantity ) AS r1 ,
-					rank() OVER( ORDER BY emp.mining_compute_extraction( ROW(
-							planet , resource , quantity , quantity_max ,
-							difficulty , empire , happiness , weight ,
-							total_weight ) ) ) AS r2
-				FROM tests_input $$ ,
-		$$ VALUES ( 1 , 1 ) , ( 2 , 2 ) , ( 3 , 3 ) $$
-	);
-
-	UPDATE tests_input SET quantity = quantity_max , difficulty = 0.33 * planet;
-	SELECT diag_test_name( 'emp.mining_compute_extraction() - Result decreases when difficulty increases' );
-	SELECT set_eq(
-		$$ SELECT rank() OVER ( ORDER BY difficulty DESC ) AS r1 ,
-					rank() OVER( ORDER BY emp.mining_compute_extraction( ROW(
-							planet , resource , quantity , quantity_max ,
-							difficulty , empire , happiness , weight ,
-							total_weight ) ) ) AS r2
-				FROM tests_input $$ ,
-		$$ VALUES ( 1 , 1 ) , ( 2 , 2 ) , ( 3 , 3 ) $$
-	);
-
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/admin/040-functions/145-resource-providers/080-verse-mining-get-input.sql b/legacyworlds-server-data/db-structure/tests/admin/040-functions/145-resource-providers/080-verse-mining-get-input.sql
deleted file mode 100644
index 89b9639..0000000
--- a/legacyworlds-server-data/db-structure/tests/admin/040-functions/145-resource-providers/080-verse-mining-get-input.sql
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Tests for the verse.mining_get_input() function
- */
-BEGIN;
-	\i utils/common-setup/setup-gu-pmc-get-data-test.sql
-	
-	SELECT plan( 9 );
-
-	SELECT diag_test_name( 'verse.mining_get_input() - Neutral planet without resource providers -> no rows' );
-	SELECT is_empty( $$ SELECT * FROM verse.mining_get_input( _get_map_name( 'planet1' ) ) $$ );
-
-	CREATE TEMPORARY TABLE test_results
-		AS SELECT * FROM verse.mining_get_input( _get_map_name( 'planet2' ) );
-	SELECT diag_test_name( 'verse.mining_get_input() - Neutral planet with resource providers - Rows included' );
-	SELECT is( COUNT(*)::INT , 2)
-		FROM test_results
-		WHERE planet = _get_map_name ( 'planet2' )
-			AND difficulty = 0.2 AND empire IS NULL
-			AND happiness IS NULL AND weight IS NULL
-			AND total_weight IS NULL;
-	SELECT diag_test_name( 'verse.mining_get_input() - Neutral planet with resource providers - No extra rows' );
-	SELECT is_empty( $$
-		SELECT * FROM test_results
-			WHERE NOT ( planet = _get_map_name ( 'planet2' )
-					AND difficulty = 0.2 AND empire IS NULL
-					AND happiness IS NULL AND weight IS NULL
-					AND total_weight IS NULL );
-	$$ );
-	DROP TABLE test_results;
-
-	CREATE TEMPORARY TABLE test_results
-		AS SELECT * FROM verse.mining_get_input( _get_map_name( 'planet3' ) );
-	SELECT diag_test_name( 'verse.mining_get_input() - Planet using empire settings - Rows included' );
-	SELECT is( COUNT(*)::INT , 2)
-		FROM test_results
-		WHERE planet = _get_map_name ( 'planet3' ) AND difficulty = 0.3
-			AND empire = _get_emp_name( 'empire1' )
-			AND happiness IS NOT NULL AND weight = 100
-			AND total_weight = 200;
-	SELECT diag_test_name( 'verse.mining_get_input() - Planet using empire settings - No extra rows' );
-	SELECT is_empty( $$
-		SELECT * FROM test_results
-			WHERE NOT ( planet = _get_map_name ( 'planet3' )
-					AND difficulty = 0.3
-					AND empire = _get_emp_name( 'empire1' )
-					AND happiness IS NOT NULL
-					AND weight = 100 AND total_weight = 200 );
-	$$ );
-	DROP TABLE test_results;
-
-	CREATE TEMPORARY TABLE test_results
-		AS SELECT * FROM verse.mining_get_input( _get_map_name( 'planet4' ) );
-	SELECT diag_test_name( 'verse.mining_get_input() - Planet using specific settings - Rows included' );
-	SELECT is( COUNT(*)::INT , 2)
-		FROM test_results
-		WHERE planet = _get_map_name ( 'planet4' ) AND difficulty = 0.4
-			AND empire = _get_emp_name( 'empire2' )
-			AND happiness IS NOT NULL AND (
-				( resource = _get_string( 'resource1' ) AND weight = 10 )
-				OR ( resource = _get_string( 'resource2' ) AND weight = 1000 ) )
-			AND total_weight = 1010;
-	SELECT diag_test_name( 'verse.mining_get_input() - Planet using specific settings - No extra rows' );
-	SELECT is_empty( $$
-		SELECT * FROM test_results
-			WHERE NOT ( planet = _get_map_name ( 'planet4' )
-					AND difficulty = 0.4 AND empire = _get_emp_name( 'empire2' )
-					AND happiness IS NOT NULL AND total_weight = 1010
-					AND ( ( resource = _get_string( 'resource1' ) AND weight = 10 )
-						OR ( resource = _get_string( 'resource2' ) AND weight = 1000 ) ) );
-	$$ );
-	DROP TABLE test_results;
-
-	SELECT diag_test_name( 'verse.mining_get_input() - Owned planet without resource providers -> no rows' );
-	SELECT is_empty( $$ SELECT * FROM verse.mining_get_input( _get_map_name( 'planet5' ) ) $$ );
-
-	CREATE TEMPORARY TABLE test_results
-		AS SELECT * FROM verse.mining_get_input( _get_map_name( 'planet6' ) );
-	SELECT diag_test_name( 'verse.mining_get_input() - Selects planets independently of update state' );
-	SELECT is( COUNT(*)::INT , 2)
-		FROM test_results
-		WHERE planet = _get_map_name ( 'planet6' ) AND difficulty = 0.6
-			AND empire = _get_emp_name( 'empire4' )
-			AND happiness IS NOT NULL AND weight = 100
-			AND total_weight = 200;
-	DROP TABLE test_results;
-
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/admin/040-functions/145-resource-providers/090-emp-mining-get-input.sql b/legacyworlds-server-data/db-structure/tests/admin/040-functions/145-resource-providers/090-emp-mining-get-input.sql
deleted file mode 100644
index bc5736a..0000000
--- a/legacyworlds-server-data/db-structure/tests/admin/040-functions/145-resource-providers/090-emp-mining-get-input.sql
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Tests for the emp.mining_get_input() function
- */
-BEGIN;
-	\i utils/common-setup/setup-gu-pmc-get-data-test.sql
-	
-	SELECT plan( 7 );
-
-	CREATE TEMPORARY TABLE test_results
-		AS SELECT * FROM emp.mining_get_input( _get_emp_name( 'empire1' ) );
-	SELECT diag_test_name( 'emp.mining_get_input() - Empire with a planet using empire settings - Rows included' );
-	SELECT is( COUNT(*)::INT , 2)
-		FROM test_results
-		WHERE planet = _get_map_name ( 'planet3' ) AND difficulty = 0.3
-			AND empire = _get_emp_name( 'empire1' )
-			AND happiness IS NOT NULL AND weight = 100
-			AND total_weight = 200;
-	SELECT diag_test_name( 'emp.mining_get_input() - Empire with a planet using empire settings - No extra rows' );
-	SELECT is_empty( $$
-		SELECT * FROM test_results
-			WHERE NOT ( planet = _get_map_name ( 'planet3' )
-					AND difficulty = 0.3
-					AND empire = _get_emp_name( 'empire1' )
-					AND happiness IS NOT NULL
-					AND weight = 100 AND total_weight = 200 );
-	$$ );
-	DROP TABLE test_results;
-
-	CREATE TEMPORARY TABLE test_results
-		AS SELECT * FROM emp.mining_get_input( _get_emp_name( 'empire2' ) );
-	SELECT diag_test_name( 'emp.mining_get_input() - Empire with a planet using specific settings - Rows included' );
-	SELECT is( COUNT(*)::INT , 2)
-		FROM test_results
-		WHERE planet = _get_map_name ( 'planet4' ) AND difficulty = 0.4
-			AND empire = _get_emp_name( 'empire2' )
-			AND happiness IS NOT NULL AND (
-				( resource = _get_string( 'resource1' ) AND weight = 10 )
-				OR ( resource = _get_string( 'resource2' ) AND weight = 1000 ) )
-			AND total_weight = 1010;
-	SELECT diag_test_name( 'emp.mining_get_input() - Empire with a planet using specific settings - No extra rows' );
-	SELECT is_empty( $$
-		SELECT * FROM test_results
-			WHERE NOT ( planet = _get_map_name ( 'planet4' )
-					AND difficulty = 0.4 AND empire = _get_emp_name( 'empire2' )
-					AND happiness IS NOT NULL AND total_weight = 1010
-					AND ( ( resource = _get_string( 'resource1' ) AND weight = 10 )
-						OR ( resource = _get_string( 'resource2' ) AND weight = 1000 ) ) );
-	$$ );
-	DROP TABLE test_results;
-
-	SELECT diag_test_name( 'emp.mining_get_input() - Owned planet without resource providers -> no rows' );
-	SELECT is_empty( $$ SELECT * FROM emp.mining_get_input( _get_emp_name( 'empire3' ) ) $$ );
-
-	CREATE TEMPORARY TABLE test_results
-		AS SELECT * FROM emp.mining_get_input( _get_emp_name( 'empire4' ) );
-	SELECT diag_test_name( 'emp.mining_get_input() - Selects planets independently of update state' );
-	SELECT is( COUNT(*)::INT , 2)
-		FROM test_results
-		WHERE planet = _get_map_name ( 'planet6' ) AND difficulty = 0.6
-			AND empire = _get_emp_name( 'empire4' )
-			AND happiness IS NOT NULL AND weight = 100
-			AND total_weight = 200;
-	DROP TABLE test_results;
-
-	SELECT diag_test_name( 'emp.mining_get_input() - Empire with no planets -> no rows' );
-	SELECT is_empty( $$ SELECT * FROM emp.mining_get_input( _get_emp_name( 'empire5' ) ) $$ );
-
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/admin/040-functions/147-empire-mining/010-mset-update-start.sql b/legacyworlds-server-data/db-structure/tests/admin/040-functions/147-empire-mining/010-mset-update-start.sql
deleted file mode 100644
index 8584f82..0000000
--- a/legacyworlds-server-data/db-structure/tests/admin/040-functions/147-empire-mining/010-mset-update-start.sql
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Test the emp.mset_update_start( INT ) function
- */
-BEGIN;
-	/* We need a pair of natural resources and an empire with mining settings. */
-	\i utils/strings.sql
-	\i utils/resources.sql
-	\i utils/accounts.sql
-	\i utils/naming.sql
-	\i utils/universe.sql
-	SELECT _create_natural_resources( 2 , 'natRes' );
-	SELECT _create_resources( 1 , 'basicRes' );
-	SELECT _create_raw_planets( 1 , 'testPlanet' );
-	SELECT _create_emp_names( 1 , 'testEmp' );
-	SELECT emp.create_empire( _get_emp_name( 'testEmp1' ) ,
-				_get_map_name( 'testPlanet1' ) ,
-				200.0 );
-
-	/***** TESTS BEGIN HERE *****/
-	SELECT plan( 6 );
-	
-	SELECT diag_test_name( 'emp.mset_update_start( INT ) - Return value on bad empire identifier' );
-	SELECT ok( NOT emp.mset_update_start( _get_bad_emp_name( ) ) );
-	SELECT diag_test_name( 'emp.mset_update_start( INT ) - Temporary table exists despite bad empire identifier' );
-	SELECT has_table( 'mset_update' );
-	DROP TABLE IF EXISTS mset_update;
-
-	
-	SELECT diag_test_name( 'emp.mset_update_start( INT ) - Return value on valid empire identifier' );
-	SELECT ok( emp.mset_update_start( _get_emp_name( 'testEmp1' ) ) );
-	SELECT diag_test_name( 'emp.mset_update_start( INT ) - Temporary table exists' );
-	SELECT has_table( 'mset_update' );
-	SELECT diag_test_name( 'emp.mset_update_start( INT ) - Temporary table contains all required entries' );
-	SELECT is( COUNT(*)::INT , 2 )
-		FROM mset_update
-		WHERE empire_id = _get_emp_name( 'testEmp1' );
-	SELECT diag_test_name( 'emp.mset_update_start( INT ) - Temporary table does not contain extra entries' );
-	SELECT is( COUNT(*)::INT , 0 )
-		FROM mset_update
-		WHERE empire_id <> _get_emp_name( 'testEmp1' );
-
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/admin/040-functions/147-empire-mining/015-mset-update-start-planet.sql b/legacyworlds-server-data/db-structure/tests/admin/040-functions/147-empire-mining/015-mset-update-start-planet.sql
deleted file mode 100644
index fa25e41..0000000
--- a/legacyworlds-server-data/db-structure/tests/admin/040-functions/147-empire-mining/015-mset-update-start-planet.sql
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Test the emp.mset_update_start( INT , INT ) function
- */
-BEGIN;
-	/* We need a pair of natural resources, an empire, a pair of planets with
-	 * resource providers. The empire must own one of the planets.
-	 */
-	\i utils/strings.sql
-	\i utils/resources.sql
-	\i utils/accounts.sql
-	\i utils/naming.sql
-	\i utils/universe.sql
-	SELECT _create_natural_resources( 2 , 'testResource' );
-	SELECT _create_raw_planets( 3 , 'testPlanet' );
-	SELECT _create_emp_names( 1 , 'testEmp' );
-	SELECT emp.create_empire( _get_emp_name( 'testEmp1' ) ,
-				_get_map_name( 'testPlanet1' ) ,
-				200.0 );
-	SELECT _create_resource_provider( 'testPlanet1' , 'testResource1' );
-	SELECT _create_resource_provider( 'testPlanet2' , 'testResource1' );
-	INSERT INTO emp.planets ( empire_id , planet_id )
-		VALUES ( _get_emp_name( 'testEmp1' ) , 	_get_map_name( 'testPlanet3' ) );
-
-	/***** TESTS BEGIN HERE *****/
-	SELECT plan( 16 );
-
-	SELECT diag_test_name( 'emp.mset_update_start( INT , INT ) - Return value on bad empire identifier' );
-	SELECT ok( NOT emp.mset_update_start( _get_bad_emp_name( ) , _get_map_name( 'testPlanet1' ) ) );
-	SELECT diag_test_name( 'emp.mset_update_start( INT , INT ) - Temporary table exists despite bad empire identifier' );
-	SELECT has_table( 'mset_update' );
-	DROP TABLE IF EXISTS mset_update;
-
-	SELECT diag_test_name( 'emp.mset_update_start( INT , INT ) - Return value on bad planet identifier' );
-	SELECT ok( NOT emp.mset_update_start( _get_emp_name( 'testEmp1' ) , _get_bad_map_name( ) ) );
-	SELECT diag_test_name( 'emp.mset_update_start( INT , INT ) - Temporary table exists despite bad planet identifier' );
-	SELECT has_table( 'mset_update' );
-	DROP TABLE IF EXISTS mset_update;
-
-	SELECT diag_test_name( 'emp.mset_update_start( INT , INT ) - Return value on unowned planet identifier' );
-	SELECT ok( NOT emp.mset_update_start( _get_emp_name( 'testEmp1' ) , _get_map_name( 'testPlanet2' ) ) );
-	SELECT diag_test_name( 'emp.mset_update_start( INT , INT ) - Temporary table exists despite unowned planet identifier' );
-	SELECT has_table( 'mset_update' );
-	DROP TABLE IF EXISTS mset_update;
-
-	SELECT diag_test_name( 'emp.mset_update_start( INT , INT ) - Return value on unowned planet identifier' );
-	SELECT ok( NOT emp.mset_update_start( _get_emp_name( 'testEmp1' ) , _get_map_name( 'testPlanet2' ) ) );
-	SELECT diag_test_name( 'emp.mset_update_start( INT , INT ) - Temporary table exists despite unowned planet identifier' );
-	SELECT has_table( 'mset_update' );
-	DROP TABLE IF EXISTS mset_update;
-
-	SELECT diag_test_name( 'emp.mset_update_start( INT , INT ) - Return value on planet with no resource providers' );
-	SELECT ok( NOT emp.mset_update_start( _get_emp_name( 'testEmp1' ) , _get_map_name( 'testPlanet3' ) ) );
-	SELECT diag_test_name( 'emp.mset_update_start( INT , INT ) - Temporary table exists despite planet with no resource providers' );
-	SELECT has_table( 'mset_update' );
-	DROP TABLE IF EXISTS mset_update;
-
-	
-	SELECT diag_test_name( 'emp.mset_update_start( INT , INT ) - Return value on valid identifiers but no existing settings' );
-	SELECT ok( NOT emp.mset_update_start( _get_emp_name( 'testEmp1' ) , _get_map_name( 'testPlanet1' ) ) );
-	SELECT diag_test_name( 'emp.mset_update_start( INT , INT ) - Temporary table exists despite lack of settings' );
-	SELECT has_table( 'mset_update' );
-	DROP TABLE IF EXISTS mset_update;
-
-	INSERT INTO emp.planet_mining_settings( empire_id , planet_id , resource_name_id )
-		SELECT _get_emp_name( 'testEmp1' ) , planet_id , resource_name_id
-			FROM verse.resource_providers
-			WHERE planet_id = _get_map_name( 'testPlanet1' );
-	SELECT diag_test_name( 'emp.mset_update_start( INT , INT ) - Return value on valid identifiers and existing settings' );
-	SELECT ok( emp.mset_update_start( _get_emp_name( 'testEmp1' ) , _get_map_name( 'testPlanet1' ) ) );
-	SELECT diag_test_name( 'emp.mset_update_start( INT , INT ) - Temporary table exists' );
-	SELECT has_table( 'mset_update' );
-	SELECT diag_test_name( 'emp.mset_update_start( INT , INT ) - Temporary table contains all required entries' );
-	SELECT is( COUNT(*)::INT , 1 )
-		FROM mset_update
-		WHERE empire_id = _get_emp_name( 'testEmp1' )
-			AND planet_id = _get_map_name( 'testPlanet1' );
-	SELECT diag_test_name( 'emp.mset_update_start( INT , INT ) - Temporary table does not contain extra entries' );
-	SELECT is( COUNT(*)::INT , 0 )
-		FROM mset_update
-		WHERE empire_id <> _get_emp_name( 'testEmp1' )
-			OR planet_id <> _get_map_name( 'testPlanet1' );
-
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/admin/040-functions/147-empire-mining/020-mset-update-set.sql b/legacyworlds-server-data/db-structure/tests/admin/040-functions/147-empire-mining/020-mset-update-set.sql
deleted file mode 100644
index 5009bb6..0000000
--- a/legacyworlds-server-data/db-structure/tests/admin/040-functions/147-empire-mining/020-mset-update-set.sql
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Test the emp.mset_update_set() function
- */
-BEGIN;
-	CREATE TEMPORARY TABLE mset_update(
-		empire_id			INT ,
-		resource_name		TEXT ,
-		empmset_weight		INT
-	) ON COMMIT DROP;
-	INSERT INTO mset_update VALUES ( 1 , 'a' , 0 ) , ( 1 , 'b' , 0 );
-	
-	/***** TESTS BEGIN HERE *****/
-	SELECT plan( 7 );
-	
-	SELECT diag_test_name( 'emp.mset_update_set( ) - Valid update' );
-	SELECT ok( emp.mset_update_set( 'a' , 1 ) );
-	SELECT diag_test_name( 'emp.mset_update_set( ) - Valid update results (1/2)' );
-	SELECT is( empmset_weight , 1 ) FROM mset_update WHERE resource_name = 'a';
-	SELECT diag_test_name( 'emp.mset_update_set( ) - Valid update results (2/2)' );
-	SELECT is( empmset_weight , 0 ) FROM mset_update WHERE resource_name = 'b';
-	DELETE FROM mset_update;
-
-	INSERT INTO mset_update VALUES ( 1 , 'a' , 0 ) , ( 1 , 'b' , 0 );
-	SELECT diag_test_name( 'emp.mset_update_set( ) - Update on unknown resource' );
-	SELECT ok( NOT emp.mset_update_set( 'c' , 1 ) );
-	SELECT diag_test_name( 'emp.mset_update_set( ) - Unknown resource update results (1/2)' );
-	SELECT is( empmset_weight , 0 ) FROM mset_update WHERE resource_name = 'a';
-	SELECT diag_test_name( 'emp.mset_update_set( ) - Unknown resource update results (2/2)' );
-	SELECT is( empmset_weight , 0 ) FROM mset_update WHERE resource_name = 'b';
-	DELETE FROM mset_update;
-
-	INSERT INTO mset_update VALUES ( 1 , 'a' , 0 ) , ( 1 , 'b' , 0 );
-	SELECT diag_test_name( 'emp.mset_update_set( ) - Update with invalid weight' );
-	SELECT ok( emp.mset_update_set( 'a' , -1 ) );
-
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/admin/040-functions/147-empire-mining/030-mset-update-apply.sql b/legacyworlds-server-data/db-structure/tests/admin/040-functions/147-empire-mining/030-mset-update-apply.sql
deleted file mode 100644
index d9088fa..0000000
--- a/legacyworlds-server-data/db-structure/tests/admin/040-functions/147-empire-mining/030-mset-update-apply.sql
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Test the emp.mset_update_apply() function
- */
-BEGIN;
-	/*
-	 * Create a pair of strings
-	 */
-	INSERT INTO defs.strings (name) VALUES ( 'a' ) , ( 'b' );
-
-	/*
-	 * Remove foreign keys from the empire mining settings table, insert some
-	 * data into it.
-	 */
-	ALTER TABLE emp.mining_settings
-		DROP CONSTRAINT fk_empmset_empire ,
-		DROP CONSTRAINT fk_empmset_resource;
-	INSERT INTO emp.mining_settings ( empire_id , resource_name_id )
-		SELECT 1 , id
-			FROM defs.strings
-			WHERE name IN ( 'a' , 'b' );
-
-	/* Create the temporary table */
-	CREATE TEMPORARY TABLE mset_update(
-		empire_id			INT ,
-		resource_name		TEXT ,
-		empmset_weight		INT
-	) ON COMMIT DROP;
-	INSERT INTO mset_update VALUES ( 1 , 'a' , 0 ) , ( 1 , 'b' , 4 );
-
-	/***** TESTS BEGIN HERE *****/
-	SELECT plan( 8 );
-
-	SELECT diag_test_name( 'emp.mset_update_apply() - Applying valid empire update' );
-	SELECT ok( emp.mset_update_apply( ) );
-	SELECT diag_test_name( 'emp.mset_update_apply() - Empire update results' );
-	SELECT set_eq(
-		$$ SELECT name , empmset_weight
-			FROM emp.mining_settings
-				INNER JOIN defs.strings
-					ON resource_name_id = id $$ ,
-		$$ VALUES ( 'a' , 0 ) , ( 'b' , 4 ) $$
-	);
-
-	/* Reset temporary table and settings */
-	DELETE FROM mset_update;
-	DELETE FROM emp.mining_settings;
-	INSERT INTO emp.mining_settings ( empire_id , resource_name_id )
-		SELECT 1 , id
-			FROM defs.strings
-			WHERE name IN ( 'a' , 'b' );
-
-	INSERT INTO mset_update VALUES ( 1 , 'a' , -1 ) , ( 1 , 'b' , 4 );
-	SELECT diag_test_name( 'emp.mset_update_apply() - Applying invalid empire update' );
-	SELECT ok( NOT emp.mset_update_apply( ) );
-	SELECT diag_test_name( 'emp.mset_update_apply() - Invalid empire update results' );
-	SELECT set_eq(
-		$$ SELECT name , empmset_weight
-			FROM emp.mining_settings
-				INNER JOIN defs.strings
-					ON resource_name_id = id $$ ,
-		$$ VALUES ( 'a' , 2 ) , ( 'b' , 2 ) $$
-	);
-
-
-	/* Re-create the temporary table to store planet mining settings, remove
-	 * constraints from the planet mining settings table, insert data into
-	 * both.
-	 */ 
-	ALTER TABLE emp.planet_mining_settings
-		DROP CONSTRAINT fk_emppmset_empire ,
-		DROP CONSTRAINT fk_emppmset_resource;
-	INSERT INTO emp.planet_mining_settings ( empire_id , planet_id , resource_name_id )
-		SELECT 1 , 1 , id
-			FROM defs.strings
-			WHERE name IN ( 'a' , 'b' );
-
-	DROP TABLE mset_update;
-	CREATE TEMPORARY TABLE mset_update(
-		empire_id			INT ,
-		planet_id			INT ,
-		resource_name		TEXT ,
-		empmset_weight		INT
-	) ON COMMIT DROP;
-	INSERT INTO mset_update VALUES ( 1 , 1 , 'a' , 0 ) , ( 1 , 1 , 'b' , 4 );
-
-	SELECT diag_test_name( 'emp.mset_update_apply() - Applying valid planet update' );
-	SELECT ok( emp.mset_update_apply( ) );
-	SELECT diag_test_name( 'emp.mset_update_apply() - Planet update results' );
-	SELECT set_eq(
-		$$ SELECT name , emppmset_weight
-			FROM emp.planet_mining_settings
-				INNER JOIN defs.strings
-					ON resource_name_id = id $$ ,
-		$$ VALUES ( 'a' , 0 ) , ( 'b' , 4 ) $$
-	);
-
-	/* Reset temporary table and settings */
-	DELETE FROM mset_update;
-	DELETE FROM emp.planet_mining_settings;
-	INSERT INTO emp.planet_mining_settings ( empire_id , planet_id , resource_name_id )
-		SELECT 1 , 1 , id
-			FROM defs.strings
-			WHERE name IN ( 'a' , 'b' );
-
-	INSERT INTO mset_update VALUES ( 1 , 1 , 'a' , -1 ) , ( 1 , 1 , 'b' , 4 );
-	SELECT diag_test_name( 'emp.mset_update_apply() - Applying invalid planet update' );
-	SELECT ok( NOT emp.mset_update_apply( ) );
-	SELECT diag_test_name( 'emp.mset_update_apply() - Invalid planet update results' );
-	SELECT set_eq(
-		$$ SELECT name , emppmset_weight
-			FROM emp.planet_mining_settings
-				INNER JOIN defs.strings
-					ON resource_name_id = id $$ ,
-		$$ VALUES ( 'a' , 2 ) , ( 'b' , 2 ) $$
-	);
-
-	SELECT * FROM finish( );
-ROLLBACK;
diff --git a/legacyworlds-server-data/db-structure/tests/admin/040-functions/147-empire-mining/040-mset-toggle-source.sql b/legacyworlds-server-data/db-structure/tests/admin/040-functions/147-empire-mining/040-mset-toggle-source.sql
deleted file mode 100644
index 1765070..0000000
--- a/legacyworlds-server-data/db-structure/tests/admin/040-functions/147-empire-mining/040-mset-toggle-source.sql
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Test the emp.mset_toggle_source( INT , INT ) function
- */
-BEGIN;
-	/*
-	 * Create a pair of natural resources, three planets, an empire owning two
-	 * of the planets, and resource providers for one of the resources on the
-	 * neutral planet and on one of the owned planets.
-	 */
-	\i utils/strings.sql
-	\i utils/resources.sql
-	\i utils/accounts.sql
-	\i utils/naming.sql
-	\i utils/universe.sql
-	SELECT _create_natural_resources( 2 , 'resource' );
-	SELECT _create_raw_planets( 3 , 'planet' );
-	SELECT _create_emp_names( 1 , 'empire' );
-	SELECT emp.create_empire( _get_emp_name( 'empire1' ) ,
-				_get_map_name( 'planet1' ) ,
-				200.0 );
-	SELECT _create_resource_provider( 'planet1' , 'resource1' );
-	SELECT _create_resource_provider( 'planet2' , 'resource1' );
-	INSERT INTO emp.planets ( empire_id , planet_id )
-		VALUES ( _get_emp_name( 'empire1' ) , 	_get_map_name( 'planet3' ) );
-
-
-	-- ***** TESTS BEGIN HERE *****
-	SELECT plan( 8 );
-	
-	SELECT diag_test_name( 'emp.mset_toggle_source() - Return value on bad empire identifier' );
-	SELECT ok( NOT emp.mset_toggle_source( _get_bad_emp_name( ) , _get_map_name( 'planet1' ) ) );
-	SELECT diag_test_name( 'emp.mset_toggle_source() - Return value on bad planbet identifier' );
-	SELECT ok( NOT emp.mset_toggle_source( _get_emp_name( 'empire1' ) , _get_bad_map_name( ) ) );
-
-	SELECT diag_test_name( 'emp.mset_toggle_source() - Return value when the empire does not own the planet' );
-	SELECT ok( NOT emp.mset_toggle_source( _get_emp_name( 'empire1' ) , _get_map_name( 'planet2' ) ) );
-	SELECT diag_test_name( 'emp.mset_toggle_source() - Return value when the planet has no resource providers' );
-	SELECT ok( NOT emp.mset_toggle_source( _get_emp_name( 'empire1' ) , _get_map_name( 'planet3' ) ) );
-
-	DELETE FROM emp.planet_mining_settings;
-	UPDATE emp.mining_settings
-		SET empmset_weight = 0;
-	SELECT diag_test_name( 'emp.mset_toggle_source() - Return value when activating' );
-	SELECT ok( emp.mset_toggle_source( _get_emp_name( 'empire1' ) , _get_map_name( 'planet1' ) ) );
-	SELECT diag_test_name( 'emp.mset_toggle_source() - Mining settings inserted after activation' );
-	SELECT set_eq(
-		$$ SELECT * FROM emp.planet_mining_settings $$ ,
-		$$ VALUES ( _get_emp_name( 'empire1' ) , _get_map_name( 'planet1' ) , _get_string( 'resource1' ) , 0 ) $$
-	);
-
-	DELETE FROM emp.planet_mining_settings;
-	INSERT INTO emp.planet_mining_settings VALUES (
-		_get_emp_name( 'empire1' ) , _get_map_name( 'planet1' ) , _get_string( 'resource1' ) , 2
-	);
-	SELECT diag_test_name( 'emp.mset_toggle_source() - Return value when de-activating' );
-	SELECT ok( emp.mset_toggle_source( _get_emp_name( 'empire1' ) , _get_map_name( 'planet1' ) ) );
-	SELECT diag_test_name( 'emp.mset_toggle_source() - Mining settings deleted after de-activation' );
-	SELECT is_empty( $$ SELECT * FROM emp.planet_mining_settings $$ );
-
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/admin/040-functions/167-planet-list/010-plist-resources-view.sql b/legacyworlds-server-data/db-structure/tests/admin/040-functions/167-planet-list/010-plist-resources-view.sql
deleted file mode 100644
index 86c18bf..0000000
--- a/legacyworlds-server-data/db-structure/tests/admin/040-functions/167-planet-list/010-plist-resources-view.sql
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Tests for emp.plist_resources_view
- */
-BEGIN;
-	\i utils/strings.sql
-	\i utils/resources.sql
-	\i utils/accounts.sql
-	\i utils/naming.sql
-	\i utils/universe.sql
-
-	/* Create a couple of resources, three planets and two empire names */
-	SELECT _create_resources( 2 , 'resource' );
-	SELECT _create_raw_planets( 3 , 'planet' );
-	SELECT _create_emp_names( 2 , 'empire' );
-
-	/* One of the empires possesses two planets */
-	SELECT emp.create_empire( _get_emp_name( 'empire1' ) ,
-				_get_map_name( 'planet1' ) ,
-				200.0 );
-	INSERT INTO emp.planets( empire_id , planet_id )
-		VALUES ( _get_emp_name( 'empire1' ) , _get_map_name( 'planet2' ) );
-
-	/* First planet has income for one resource and upkeep for the other */
-	INSERT INTO verse.planet_resources ( planet_id , resource_name_id , pres_income )
-		VALUES ( _get_map_name( 'planet1' ) , _get_string( 'resource1' ) , 0.23 );
-	INSERT INTO verse.planet_resources ( planet_id , resource_name_id , pres_upkeep )
-		VALUES ( _get_map_name( 'planet1' ) , _get_string( 'resource2' ) , 0.22 );
-
-	/* Second planet has no income or upkeep */
-	INSERT INTO verse.planet_resources ( planet_id , resource_name_id )
-		SELECT _get_map_name( 'planet2' ) , resource_name_id
-			FROM defs.resources;
-
-	/* The second empire has no planets */
-	INSERT INTO emp.empires( name_id , cash )
-		VALUES ( _get_emp_name( 'empire2' ) , 123 );
-
-	/* Third planet has income and upkeep for all resources */
-	INSERT INTO verse.planet_resources ( planet_id , resource_name_id , pres_income , pres_upkeep )
-		SELECT _get_map_name( 'planet3' ) , resource_name_id ,
-				4 + row_number( ) OVER( ) * 2 , row_number( ) OVER( ) * 2 + 5
-			FROM defs.resources;
-
-	-- ***** TESTS BEGIN HERE *****
-	SELECT plan( 4 );
-	
-	SELECT diag_test_name( 'emp.plist_resources_view - No rows for neutral planets' );
-	SELECT is_empty( $$
-		SELECT * FROM emp.plist_resources_view
-			WHERE planet_id = _get_map_name( 'planet3' );
-	$$ );
-
-	SELECT diag_test_name( 'emp.plist_resources_view - No rows for empires with no planets' );
-	SELECT is_empty( $$
-		SELECT * FROM emp.plist_resources_view
-			WHERE empire_id = _get_emp_name( 'empire2' );
-	$$ );
-
-	SELECT diag_test_name( 'emp.plist_resources_view - No rows for owned planets with zero income and upkeep' );
-	SELECT is_empty( $$
-		SELECT * FROM emp.plist_resources_view
-			WHERE planet_id = _get_map_name( 'planet2' );
-	$$ );
-
-	SELECT diag_test_name( 'emp.plist_resources_view - Rows for owned planets with income and upkeep' );
-	SELECT set_eq( $$
-		SELECT empire_id , resource_name , pres_income , pres_upkeep ,
-				civ_investment , mil_investment
-			FROM emp.plist_resources_view
-			WHERE planet_id = _get_map_name( 'planet1' );
-	$$ , $$ VALUES(
-			_get_emp_name( 'empire1' ) , 'Test string #1' , 165 , 0 , 0 , 0
-		) , (
-			_get_emp_name( 'empire1' ) , 'Test string #2' , 0 , 159 , 0 , 0
-	) $$ );
-
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/admin/040-functions/200-bugs/005-dump-emp-resources-view.sql b/legacyworlds-server-data/db-structure/tests/admin/040-functions/200-bugs/005-dump-emp-resources-view.sql
deleted file mode 100644
index cc2bd6d..0000000
--- a/legacyworlds-server-data/db-structure/tests/admin/040-functions/200-bugs/005-dump-emp-resources-view.sql
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Tests for bugs.dump_emp_resources_view
- */
-BEGIN;
-	/*
-	 * We need a basic resource type, a natural resource type, an empire and
-	 * the associated resources and mining settings records.
-	 */
-	\i utils/strings.sql
-	\i utils/resources.sql
-	\i utils/accounts.sql
-	\i utils/naming.sql
-	\i utils/universe.sql
-	SELECT _create_resources( 1 , 'resource' );
-	SELECT _create_natural_resources( 1 , 'natRes' );
-	SELECT _create_emp_names( 1 , 'empire' );
-	INSERT INTO emp.empires( name_id , cash )
-		VALUES ( _get_emp_name( 'empire1' ) , 0 );
-	INSERT INTO emp.resources(
-			empire_id , resource_name_id , empres_possessed , empres_owed
-		) VALUES (
-			_get_emp_name( 'empire1' ) , _get_string( 'resource1' ) , 1 , 2
-		) , (
-			_get_emp_name( 'empire1' ) , _get_string( 'natRes1' ) , 3 , 4
-		);
-	INSERT INTO emp.mining_settings (
-			empire_id , resource_name_id , empmset_weight
-		) VALUES (
-			_get_emp_name( 'empire1' ) , _get_string( 'natRes1' ) , 0
-		);
-
-
-	/***** TESTS BEGIN HERE *****/
-	SELECT plan( 2 );
-
-	SELECT diag_test_name( 'bugs.dump_emp_resources_view - Basic resources' );
-	SELECT set_eq( $$
-		SELECT empire_id , resource_name , empres_possessed , empres_owed
-			FROM bugs.dump_emp_resources_view
-			WHERE mining_priority IS NULL
-	$$ , $$ VALUES (
-		_get_emp_name( 'empire1' ) , 'resource1' , 1 , 2
-	) $$ );
-
-	SELECT diag_test_name( 'bugs.dump_emp_resources_view - Natural resources' );
-	SELECT set_eq( $$
-		SELECT empire_id , resource_name , empres_possessed , empres_owed ,
-				mining_priority
-			FROM bugs.dump_emp_resources_view
-			WHERE mining_priority IS NOT NULL
-	$$ , $$ VALUES (
-		_get_emp_name( 'empire1' ) , 'natRes1' , 3 , 4 , 0
-	) $$ );
-
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/admin/040-functions/200-bugs/010-dump-planet-resources-view.sql b/legacyworlds-server-data/db-structure/tests/admin/040-functions/200-bugs/010-dump-planet-resources-view.sql
deleted file mode 100644
index 011de9f..0000000
--- a/legacyworlds-server-data/db-structure/tests/admin/040-functions/200-bugs/010-dump-planet-resources-view.sql
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Tests for bugs.dump_planet_resources_view
- */
-BEGIN;
-	/*
-	 * We need a couple of resources (one natural, one basic), four planets
-	 * with valid planet resource records (three of the planets will have a
-	 * resource provider and one of them will have planet-specific mining
-	 * settings), three empires (owning a planet without resource provider,
-	 * with resource provider and with resource provider and mining settings,
-	 * respectively). 
-	 */
-	\i utils/strings.sql
-	\i utils/resources.sql
-	\i utils/accounts.sql
-	\i utils/naming.sql
-	\i utils/universe.sql
-	SELECT _create_natural_resources( 1 , 'natRes' );
-	SELECT _create_resources( 1 , 'basicRes' );
-	SELECT _create_raw_planets( 4 , 'planet' );
-	INSERT INTO verse.planet_resources(
-			planet_id , resource_name_id , pres_income , pres_upkeep
-		) VALUES (
-			_get_map_name( 'planet1' ) , _get_string( 'basicRes1' ) , 1 , 2
-		) , (
-			_get_map_name( 'planet1' ) , _get_string( 'natRes1' ) , 3 , 4
-		) , (
-			_get_map_name( 'planet2' ) , _get_string( 'basicRes1' ) , 5 , 6
-		) , (
-			_get_map_name( 'planet2' ) , _get_string( 'natRes1' ) , 7 , 8
-		) , (
-			_get_map_name( 'planet3' ) , _get_string( 'basicRes1' ) , 9 , 10
-		) , (
-			_get_map_name( 'planet3' ) , _get_string( 'natRes1' ) , 11 , 12
-		) , (
-			_get_map_name( 'planet4' ) , _get_string( 'basicRes1' ) , 13 , 14
-		) , (
-			_get_map_name( 'planet4' ) , _get_string( 'natRes1' ) , 15 , 16
-		);
-	SELECT _create_resource_provider( 'planet1' , 'natRes1' );
-	SELECT _create_resource_provider( 'planet3' , 'natRes1' );
-	SELECT _create_resource_provider( 'planet4' , 'natRes1' );
-
-	SELECT _create_emp_names( 3 , 'empire' );
-	SELECT emp.create_empire( _get_emp_name( 'empire1' ) ,
-				_get_map_name( 'planet1' ) ,
-				200.0 );
-	SELECT emp.create_empire( _get_emp_name( 'empire2' ) ,
-				_get_map_name( 'planet2' ) ,
-				200.0 );
-	SELECT emp.create_empire( _get_emp_name( 'empire3' ) ,
-				_get_map_name( 'planet4' ) ,
-				200.0 );
-				
-	INSERT INTO emp.planet_mining_settings(
-			empire_id , planet_id , resource_name_id , emppmset_weight
-		) VALUES (
-			_get_emp_name( 'empire3' ) , _get_map_name( 'planet4' ) ,
-			_get_string( 'natRes1' ) , 2
-		);
-
-
-
-	/***** TESTS BEGIN HERE *****/
-	SELECT plan( 3 );
-
-	SELECT diag_test_name( 'bugs.dump_planet_resources_view - Records without resource providers' );
-	SELECT set_eq( $$
-		SELECT empire_id , planet_id , resource_name , pres_income , pres_upkeep
-			FROM bugs.dump_planet_resources_view
-			WHERE resprov_quantity IS NULL
-	$$ , $$ VALUES (
-		_get_emp_name( 'empire1' ) , _get_map_name( 'planet1' ) , 'basicRes1' , 1 , 2
-	) , (
-		_get_emp_name( 'empire2' ) , _get_map_name( 'planet2' ) , 'basicRes1' , 5 , 6
-	) , (
-		_get_emp_name( 'empire2' ) , _get_map_name( 'planet2' ) , 'natRes1' , 7 , 8
-	) , (
-		_get_emp_name( 'empire3' ) , _get_map_name( 'planet4' ) , 'basicRes1' , 13 , 14
-	) $$ );
-
-	SELECT diag_test_name( 'bugs.dump_planet_resources_view - Records with resource providers, no settings' );
-	SELECT set_eq( $$
-		SELECT empire_id , planet_id , resource_name , pres_income , pres_upkeep
-			FROM bugs.dump_planet_resources_view
-			WHERE resprov_quantity IS NOT NULL
-				AND mining_priority IS NULL
-	$$ , $$ VALUES (
-		_get_emp_name( 'empire1' ) , _get_map_name( 'planet1' ) , 'natRes1' , 3 , 4
-	) $$ );
-
-	SELECT diag_test_name( 'bugs.dump_planet_resources_view - Records with resource providers and settings' );
-	SELECT set_eq( $$
-		SELECT empire_id , planet_id , resource_name , pres_income ,
-				pres_upkeep , mining_priority
-			FROM bugs.dump_planet_resources_view
-			WHERE resprov_quantity IS NOT NULL
-				AND mining_priority IS NOT NULL
-	$$ , $$ VALUES (
-		_get_emp_name( 'empire3' ) , _get_map_name( 'planet4' ) , 'natRes1' , 15 , 16 , 2
-	) $$ );
-
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/admin/050-updates/000-updates-ctrl/010-start-tick.sql b/legacyworlds-server-data/db-structure/tests/admin/050-updates/000-updates-ctrl/010-start-tick.sql
deleted file mode 100644
index 85e5731..0000000
--- a/legacyworlds-server-data/db-structure/tests/admin/050-updates/000-updates-ctrl/010-start-tick.sql
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Test the sys.start_tick() function
- */
-BEGIN;
-	-- Delete all registered update types and targets
-	DELETE FROM sys.update_types;
-	DELETE FROM sys.update_targets;
-	
-	-- Create a new update target / type which will be used in tests
-	CREATE SCHEMA test
-		CREATE TABLE test( test_id INT NOT NULL PRIMARY KEY );
-	INSERT INTO sys.update_targets VALUES ( 1 , 'Test' , 'test' , 'test' );
-	INSERT INTO sys.update_types VALUES ( 1 , 1 , 'Test' , 2 , '' , NULL , NULL );
-	
-	-- Insert a few update rows
-	INSERT INTO test.test VALUES ( 1 ) , ( 2 ) , ( 3 );
-
-	-- ***** TESTS BEGIN HERE *****
-	SELECT plan( 5 );
-	
-	UPDATE sys.status SET maintenance_start = now( ) , current_tick = NULL;
-	SELECT diag_test_name( 'sys.start_tick() - Ticks do not start if maintenance mode is active' );
-	SELECT ok( sys.start_tick( ) IS NULL );
-	
-	UPDATE sys.status SET maintenance_start = NULL , current_tick = next_tick;
-	SELECT diag_test_name( 'sys.start_tick() - Ticks do not start if current_tick is set' );
-	SELECT ok( sys.start_tick( ) IS NULL );
-	
-	UPDATE sys.status SET current_tick = NULL , next_tick = 2;
-	UPDATE sys.updates SET update_state = 'PROCESSED' , update_last = -1;
-	UPDATE sys.updates su SET update_last = 514
-		FROM test.test_updates tu
-		WHERE su.update_id = tu.update_id
-			AND tu.test_id = 3;
-	SELECT diag_test_name( 'sys.start_tick() - Returns next tick identifier when ticks can start' );
-	SELECT is( sys.start_tick( ) , 2::BIGINT );
-	SELECT diag_test_name( 'sys.start_tick() - System status is updated' );
-	SELECT set_eq(
-		$$ SELECT current_tick , next_tick FROM sys.status $$ ,
-		$$ VALUES ( 2 , 3 ) $$
-	);
-	SELECT diag_test_name( 'sys.start_tick() - Update rows are marked for processing when necessary' );
-	SELECT set_eq(
-		$$ SELECT test_id
-			FROM test.test_updates
-				INNER JOIN sys.updates
-					USING ( update_id , updtgt_id , updtype_id )
-			WHERE update_state = 'FUTURE' AND update_last = 2 $$ ,
-		$$ VALUES ( 1 ) , ( 2 ) $$
-	);
-
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/admin/050-updates/000-updates-ctrl/020-check-stuck-tick.sql b/legacyworlds-server-data/db-structure/tests/admin/050-updates/000-updates-ctrl/020-check-stuck-tick.sql
deleted file mode 100644
index cc5eaf9..0000000
--- a/legacyworlds-server-data/db-structure/tests/admin/050-updates/000-updates-ctrl/020-check-stuck-tick.sql
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Tests of the sys.check_stuck_tick() function
- */
-BEGIN;
-	-- Delete all registered update types and targets
-	DELETE FROM sys.update_types;
-	DELETE FROM sys.update_targets;
-	
-	-- Create a new update target / type which will be used in tests
-	CREATE SCHEMA test
-		CREATE TABLE test( test_id INT NOT NULL PRIMARY KEY );
-	INSERT INTO sys.update_targets VALUES ( 1 , 'Test' , 'test' , 'test' );
-	INSERT INTO sys.update_types VALUES ( 1 , 1 , 'Test' , 2 , '' , NULL , NULL );
-	
-	-- Insert a few update rows
-	INSERT INTO test.test VALUES ( 1 ) , ( 2 ) , ( 3 );
-
-	-- Replace sys.end_tick() with a function that inserts into some table
-	CREATE TABLE end_tick_calls( tick_id BIGINT NOT NULL );
-	CREATE OR REPLACE FUNCTION sys.end_tick( tick_id BIGINT )
-		RETURNS VOID LANGUAGE SQL
-		AS 'INSERT INTO end_tick_calls VALUES( $1 );';
-
-	-- ***** TESTS BEGIN HERE *****
-	SELECT plan( 8 );
-	
-	UPDATE sys.status SET maintenance_start = NULL , current_tick = NULL;
-	SELECT diag_test_name( 'sys.check_stuck_tick() - Returns NULL if no tick is in progress' );
-	SELECT ok( sys.check_stuck_tick() IS NULL );
-	SELECT diag_test_name( 'sys.check_stuck_tick() - Does not call sys.end_tick() if no tick is in progress' );
-	SELECT is_empty( $$ SELECT * FROM end_tick_calls $$ );
-	DELETE FROM end_tick_calls;
-
-	UPDATE sys.status SET maintenance_start = now( ) , current_tick = 2;
-	SELECT diag_test_name( 'sys.check_stuck_tick() - Returns NULL if maintenance mode is enabled' );
-	SELECT ok( sys.check_stuck_tick() IS NULL );
-	SELECT diag_test_name( 'sys.check_stuck_tick() - Does not call sys.end_tick() if maintenance mode is enabled' );
-	SELECT is_empty( $$ SELECT * FROM end_tick_calls $$ );
-	DELETE FROM end_tick_calls;
-
-	UPDATE sys.status SET maintenance_start = NULL , current_tick = 2;
-	UPDATE sys.updates SET update_state = 'PROCESSED' , update_last = 2;
-	SELECT diag_test_name( 'sys.check_stuck_tick() - Returns NULL if a tick is in progress but there are no updates left' );
-	SELECT ok( sys.check_stuck_tick() IS NULL );
-	SELECT diag_test_name( 'sys.check_stuck_tick() - Calls sys.end_tick() if a tick is in progress but there are no updates left' );
-	SELECT set_eq(
-		$$ SELECT * FROM end_tick_calls $$ ,
-		$$ VALUES ( 2 ) $$
-	);
-	DELETE FROM end_tick_calls;
-
-	UPDATE sys.status SET maintenance_start = NULL , current_tick = 2;
-	UPDATE sys.updates SET update_state = 'FUTURE' , update_last = 2;
-	SELECT diag_test_name( 'sys.check_stuck_tick() - Returns tick identifier if a tick is in progress and there are updates left' );
-	SELECT is( sys.check_stuck_tick() , 2::BIGINT );
-	SELECT diag_test_name( 'sys.check_stuck_tick() - Does not call sys.end_tick() if a tick is in progress and there are updates left' );
-	SELECT is_empty( $$ SELECT * FROM end_tick_calls $$ );
-
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/admin/050-updates/000-updates-ctrl/030-process-updates.sql b/legacyworlds-server-data/db-structure/tests/admin/050-updates/000-updates-ctrl/030-process-updates.sql
deleted file mode 100644
index ab25ff1..0000000
--- a/legacyworlds-server-data/db-structure/tests/admin/050-updates/000-updates-ctrl/030-process-updates.sql
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * Tests for the sys.process_updates() function
- */
-BEGIN;
-	-- Delete all registered update types and targets
-	DELETE FROM sys.update_types;
-	DELETE FROM sys.update_targets;
-	
-	-- Create a new update target / type which will be used in tests
-	CREATE SCHEMA test
-		CREATE TABLE test( test_id INT NOT NULL PRIMARY KEY );
-	INSERT INTO sys.update_targets VALUES ( 1 , 'Test' , 'test' , 'test' );
-	INSERT INTO sys.update_types VALUES ( 1 , 1 , 'Test 1' , 2 , '' , NULL , NULL );
-	INSERT INTO sys.update_types VALUES ( 2 , 1 , 'Test 2' , 4 , '' , NULL , NULL );
-
-	-- Replace sys.end_tick() with a function that inserts into some table
-	CREATE TABLE end_tick_calls( tick_id BIGINT NOT NULL );
-	CREATE OR REPLACE FUNCTION sys.end_tick( tick_id BIGINT )
-		RETURNS VOID LANGUAGE SQL
-		AS 'INSERT INTO end_tick_calls VALUES( $1 );';
-
-	-- Create a sys.process_dummy_update() function that inserts into some other table
-	CREATE TABLE process_update_calls( tick_id BIGINT NOT NULL );
-	CREATE OR REPLACE FUNCTION sys.process_dummy_update( tick_id BIGINT )
-		RETURNS VOID LANGUAGE SQL
-		AS 'INSERT INTO process_update_calls VALUES( $1 );';
-
-	-- Set the general batch size to 1
-	SELECT sys.uoc_constant( 'game.batchSize' , '(test)' , 'Game updates' , 1 );
-	
-	-- Insert a few entries in the test table
-	INSERT INTO test.test
-		SELECT * FROM generate_series( 1 , 10 );
-
-	-- ***** TESTS BEGIN HERE *****
-	SELECT plan( 21 );
-	
-	/*
-	 * Case:
-	 *		Updates have not been processed yet,
-	 *
-	 * Expected results:
-	 *		1) New updates of the first type have been marked for processing,
-	 *		2) The quantity of updates marked for processing corresponds to game.batchSize
-	 */
-	UPDATE sys.updates
-		SET update_state = 'FUTURE' , update_last = 1;
-	SELECT diag_test_name( 'sys.process_updates() - General batch size - Return value' );
-	SELECT ok( sys.process_updates( 1 ) = ROW( TRUE , 'Test 1'::TEXT ) );
-	SELECT diag_test_name( 'sys.process_updates() - General batch size - Update type' );
-	SELECT set_eq(
-		$$ SELECT DISTINCT updtype_id FROM sys.updates WHERE update_state = 'PROCESSING'; $$ ,
-		$$ VALUES ( 1 ) $$
-	);
-	SELECT diag_test_name( 'sys.process_updates() - General batch size - Update count' );
-	SELECT is( COUNT(*)::INT , 1 ) FROM sys.updates WHERE update_state = 'PROCESSING';
-	SELECT diag_test_name( 'sys.process_updates() - General batch size - sys.end_tick() not called' );
-	SELECT is_empty( $$ SELECT * FROM end_tick_calls $$ );
-	DELETE FROM end_tick_calls;
-
-	/*
-	 * Case:
-	 *		Updates have not been processed yet,
-	 *		Update type has a specific batch size,
-	 *
-	 * Expected results:
-	 *		1) New updates have been marked for processing,
-	 *		2) The quantity of updates marked for processing corresponds to the specific batch size 
-	 *		3) sys.end_tick() has not been called 
-	 */
-	UPDATE sys.update_types SET updtype_batch_size = 2 WHERE updtype_id = 1;
-	UPDATE sys.updates SET update_state = 'FUTURE' , update_last = 1;
-	SELECT diag_test_name( 'sys.process_updates() - Specific batch size - Return value' );
-	SELECT ok( sys.process_updates( 1 ) = ROW( TRUE , 'Test 1'::TEXT ) );
-	SELECT diag_test_name( 'sys.process_updates() - Specific batch size - Update type' );
-	SELECT set_eq(
-		$$ SELECT DISTINCT updtype_id FROM sys.updates WHERE update_state = 'PROCESSING'; $$ ,
-		$$ VALUES ( 1 ) $$
-	);
-	SELECT diag_test_name( 'sys.process_updates() - Specific batch size - Update count' );
-	SELECT is( COUNT(*)::INT , 2 ) FROM sys.updates WHERE update_state = 'PROCESSING';
-	SELECT diag_test_name( 'sys.process_updates() - Specific batch size - sys.end_tick() not called' );
-	SELECT is_empty( $$ SELECT * FROM end_tick_calls $$ );
-	DELETE FROM end_tick_calls;
-
-	/*
-	 * Case:
-	 *		Some but not all updates of the first type have been processed,
-	 *		Batch size is greater than the quantity of updates left to process for the type.
-	 *
-	 * Expected results:
-	 *		1) All updates of the first type are marked either for processing or as processed.
-	 *		2) sys.end_tick() has not been called
-	 */
-	UPDATE sys.update_types SET updtype_batch_size = 2 WHERE updtype_id = 1;
-	UPDATE sys.updates SET update_state = 'FUTURE' , update_last = 1;
-	UPDATE sys.updates
-		SET update_state = 'PROCESSED'
-		WHERE update_id IN (
-			SELECT update_id FROM sys.updates WHERE updtype_id = 1 LIMIT 9
-		);
-	UPDATE sys.update_types SET updtype_batch_size = 2 WHERE updtype_id = 1;
-	SELECT diag_test_name( 'sys.process_updates() - End of type updates - Return value' );
-	SELECT ok( sys.process_updates( 1 ) = ROW( TRUE , 'Test 1'::TEXT ) );
-	SELECT diag_test_name( 'sys.process_updates() - End of type updates - Update type' );
-	SELECT set_eq(
-		$$ SELECT DISTINCT updtype_id FROM sys.updates WHERE update_state <> 'FUTURE'; $$ ,
-		$$ VALUES ( 1 ) $$
-	);
-	SELECT diag_test_name( 'sys.process_updates() - End of type updates - Update count' );
-	SELECT is( COUNT(*)::INT , 10 ) FROM sys.updates WHERE update_state <> 'FUTURE';
-	SELECT diag_test_name( 'sys.process_updates() - End of type updates - sys.end_tick() not called' );
-	SELECT is_empty( $$ SELECT * FROM end_tick_calls $$ );
-	DELETE FROM end_tick_calls;
-
-	/*
-	 * Case:
-	 *		All updates of the first type have been processed.
-	 *		No updates of the second type have been processed.
-	 *
-	 * Expected results:
-	 *		1) Some updates from the second type have been marked for processing.
-	 *		2) sys.end_tick() has not been called 
-	 */
-	UPDATE sys.updates SET update_state = 'FUTURE' , update_last = 1;
-	UPDATE sys.updates
-		SET update_state = 'PROCESSED'
-		WHERE updtype_id = 1;
-	SELECT diag_test_name( 'sys.process_updates() - Update type transition - Return value' );
-	SELECT ok( sys.process_updates( 1 ) = ROW( TRUE , 'Test 2'::TEXT ) );
-	SELECT diag_test_name( 'sys.process_updates() - Update type transition - Update type' );
-	SELECT set_eq(
-		$$ SELECT DISTINCT updtype_id FROM sys.updates WHERE update_state = 'PROCESSING'; $$ ,
-		$$ VALUES ( 2 ) $$
-	);
-	SELECT diag_test_name( 'sys.process_updates() - Update type transition - Update count' );
-	SELECT is( COUNT(*)::INT , 1 ) FROM sys.updates WHERE update_state = 'PROCESSING';
-	SELECT diag_test_name( 'sys.process_updates() - Update type transition - sys.end_tick() not called' );
-	SELECT is_empty( $$ SELECT * FROM end_tick_calls $$ );
-	DELETE FROM end_tick_calls;
-
-	/*
-	 * Case:
-	 *		There no updates to process
-	 *		Updates are marked as 'PROCESSING'
-	 *
-	 * Expected results:
-	 *		1) _has_more return value is FALSE,
-	 *		2) All updates are marked as 'PROCESSED'
-	 *		3) sys.end_tick() has been called.
-	 */
-	UPDATE sys.updates SET update_state = 'PROCESSING' , update_last = 1;
-	SELECT diag_test_name( 'sys.process_updates() - No updates left - Return value' );
-	SELECT ok( sys.process_updates( 1 ) = ROW( FALSE , NULL::TEXT ) );
-	SELECT diag_test_name( 'sys.process_updates() - No updates left - All updates processed' );
-	SELECT is_empty( $$ SELECT * FROM sys.updates WHERE update_state <> 'PROCESSED' $$ );
-	SELECT diag_test_name( 'sys.process_updates() - No updates left - sys.end_tick() called' );
-	SELECT set_eq( $$ SELECT * FROM end_tick_calls $$ , $$ VALUES ( 1 ) $$ );
-	DELETE FROM end_tick_calls;
-	
-	/*
-	 * Case:
-	 *		The update type has an in-base processing function
-	 *
-	 * Expected result:
-	 *		1) _process_externally return value is NULL
-	 *		2) The processing function has been called.
-	 */
-	UPDATE sys.updates SET update_state = 'FUTURE' , update_last = 1;
-	UPDATE sys.update_types
-		SET updtype_batch_size = NULL , updtype_proc_name = 'process_dummy_update'
-		WHERE updtype_id = 1;
-	SELECT diag_test_name( 'sys.process_updates() - In-base processing - Return value' );
-	SELECT ok( sys.process_updates( 1 ) = ROW( TRUE , NULL::TEXT ) );
-	SELECT diag_test_name( 'sys.process_updates() - In-base processing - Processing function called' );
-	SELECT set_eq( $$ SELECT * FROM process_update_calls $$ , $$ VALUES ( 1 ) $$ );
-
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/admin/050-updates/003-core-update-targets/010-presence.sql b/legacyworlds-server-data/db-structure/tests/admin/050-updates/003-core-update-targets/010-presence.sql
deleted file mode 100644
index 595b988..0000000
--- a/legacyworlds-server-data/db-structure/tests/admin/050-updates/003-core-update-targets/010-presence.sql
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * Check that core update targets have been defined correctly
- */
-BEGIN;
-	SELECT plan( 3 );
-
-	SELECT diag_test_name( 'Update targets - Definitions present' );
-	SELECT is( COUNT(*)::INT , 2 ) FROM sys.update_targets;
-
-	SELECT diag_test_name( 'Update targets - verse.planets_updates exists' );
-	SELECT has_table( 'verse' , 'planets_updates' , 'Missing planets update table' );
-
-	SELECT diag_test_name( 'Update targets - emp.empires_updates exists' );
-	SELECT has_table( 'emp' , 'empires_updates' , 'Missing empires update table' );
-
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/admin/050-updates/015-empire-resources/010-process-empire-resources-updates.sql b/legacyworlds-server-data/db-structure/tests/admin/050-updates/015-empire-resources/010-process-empire-resources-updates.sql
deleted file mode 100644
index 969aa97..0000000
--- a/legacyworlds-server-data/db-structure/tests/admin/050-updates/015-empire-resources/010-process-empire-resources-updates.sql
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * Test the sys.process_empire_resources_updates() function
- */
-BEGIN;
-	/* Start by deleting all update types except for the one
-	 * we're interested in.
-	 */
-	DELETE FROM sys.update_types
-		WHERE updtype_name <> 'EmpireResources';
-
-	/* We need:
-	 *  - three types of resources,
-	 *  - three empires with resources records, and the corresponding update
-	 *    record,
-	 *  - three planets, set to belong to the aforementioned empires, with
-	 *    resources records attached. 
-	 */
-	\i utils/strings.sql
-	\i utils/resources.sql
-	\i utils/accounts.sql
-	\i utils/naming.sql
-	\i utils/universe.sql
-	SELECT _create_resources( 3 , 'testResource' );
-	SELECT _create_raw_planets( 3 , 'testPlanet' );
-	SELECT _create_emp_names( 3 , 'testEmp' );
-	INSERT INTO verse.planet_resources ( planet_id , resource_name_id )
-		SELECT _get_map_name( 'testPlanet1' ) , resource_name_id FROM defs.resources;
-	INSERT INTO verse.planet_resources ( planet_id , resource_name_id )
-		SELECT _get_map_name( 'testPlanet2' ) , resource_name_id FROM defs.resources;
-	INSERT INTO verse.planet_resources ( planet_id , resource_name_id )
-		SELECT _get_map_name( 'testPlanet3' ) , resource_name_id FROM defs.resources;
-
-	/* Set up the planets' resource records so that:
-	 *	- income > upkeep for testResource1 ,
-	 *	- income < upkeep for testResource2 ,
-	 *	- income = upkeep = 0 for testResource3 ,
-	 */
-	UPDATE verse.planet_resources SET pres_income = 12
-		WHERE resource_name_id = _get_string( 'testResource1' );
-	UPDATE verse.planet_resources SET pres_upkeep = 34
-		WHERE resource_name_id = _get_string( 'testResource2' );
-
-	/* Create testEmp1 empire */
-	SELECT emp.create_empire( _get_emp_name( 'testEmp1' ) , _get_map_name( 'testPlanet1' ) , 1 );
-
-	/* Create testEmp2 empire and add a vacation mode entry; also set the vacation.cashDivider constant */
-	SELECT emp.create_empire( _get_emp_name( 'testEmp2' ) , _get_map_name( 'testPlanet2' ) , 1 );
-	ALTER TABLE users.vacations
-		DROP CONSTRAINT fk_vacations_accounts;
-	INSERT INTO users.vacations ( account_id , since , status )
-		SELECT owner_id , now( ) , 'PROCESSED'
-			FROM naming.empire_names
-				WHERE id = _get_emp_name( 'testEmp2' );
-	SELECT sys.uoc_constant( 'vacation.cashDivider' , '(test)' , 'Resources' , 2 );
-
-	/* Make sure update 0 is set to be processed for testEmp1 */
-	UPDATE sys.updates
-		SET update_state = 'PROCESSING' , update_last = 0;
-
-	/* Create testEmp3 empire, make sure it will not be processed */
-	SELECT emp.create_empire( _get_emp_name( 'testEmp3' ) , _get_map_name( 'testPlanet3' ) , 1 );
-	UPDATE sys.updates _su
-		SET update_state = 'PROCESSED' , update_last = 0
-		FROM emp.empires_updates _eu
-		WHERE _eu.update_id = _su.update_id
-			AND _eu.name_id = _get_emp_name( 'testEmp3' );
-
-	/****** TESTS BEGIN HERE ******/
-	SELECT plan( 31 );
-
-	SELECT sys.process_empire_resources_updates( 10 );
-	SELECT diag_test_name( 'EMPIRE_RESOURCES update - Wrong update identifier (1/6)' );
-	SELECT is( empres_possessed , 0::DOUBLE PRECISION ) FROM emp.resources
-		WHERE resource_name_id = _get_string( 'testResource1' );
-	SELECT diag_test_name( 'EMPIRE_RESOURCES update - Wrong update identifier (2/6)' );
-	SELECT is( empres_owed , 0::DOUBLE PRECISION ) FROM emp.resources
-		WHERE resource_name_id = _get_string( 'testResource1' );
-	SELECT diag_test_name( 'EMPIRE_RESOURCES update - Wrong update identifier (3/6)' );
-	SELECT is( empres_possessed , 0::DOUBLE PRECISION ) FROM emp.resources
-		WHERE resource_name_id = _get_string( 'testResource2' );
-	SELECT diag_test_name( 'EMPIRE_RESOURCES update - Wrong update identifier (4/6)' );
-	SELECT is( empres_owed , 0::DOUBLE PRECISION ) FROM emp.resources
-		WHERE resource_name_id = _get_string( 'testResource2' );
-	SELECT diag_test_name( 'EMPIRE_RESOURCES update - Wrong update identifier (5/6)' );
-	SELECT is( empres_possessed , 0::DOUBLE PRECISION ) FROM emp.resources
-		WHERE resource_name_id = _get_string( 'testResource3' );
-	SELECT diag_test_name( 'EMPIRE_RESOURCES update - Wrong update identifier (6/6)' );
-	SELECT is( empres_owed , 0::DOUBLE PRECISION ) FROM emp.resources
-		WHERE resource_name_id = _get_string( 'testResource3' );
-
-	SELECT sys.process_empire_resources_updates( 0 );
-
-	SELECT diag_test_name( 'EMPIRE_RESOURCES update - Resource 1 - Possessed quantity increased' );
-	SELECT is( empres_possessed , 12::DOUBLE PRECISION ) FROM emp.resources
-		WHERE resource_name_id = _get_string( 'testResource1' )
-			AND empire_id = _get_emp_name( 'testEmp1' );
-	SELECT diag_test_name( 'EMPIRE_RESOURCES update - Resource 1 - Owed quantity unchanged' );
-	SELECT is( empres_owed , 0::DOUBLE PRECISION ) FROM emp.resources
-		WHERE resource_name_id = _get_string( 'testResource1' )
-			AND empire_id = _get_emp_name( 'testEmp1' );
-	SELECT diag_test_name( 'EMPIRE_RESOURCES update - Resource 2 - Possessed quantity unchanged' );
-	SELECT is( empres_possessed , 0::DOUBLE PRECISION ) FROM emp.resources
-		WHERE resource_name_id = _get_string( 'testResource2' )
-			AND empire_id = _get_emp_name( 'testEmp1' );
-	SELECT diag_test_name( 'EMPIRE_RESOURCES update - Resource 2 - Owed quantity increased' );
-	SELECT is( empres_owed , 34::DOUBLE PRECISION ) FROM emp.resources
-		WHERE resource_name_id = _get_string( 'testResource2' )
-			AND empire_id = _get_emp_name( 'testEmp1' );
-	SELECT diag_test_name( 'EMPIRE_RESOURCES update - Resource 3 - Possessed quantity unchanged' );
-	SELECT is( empres_possessed , 0::DOUBLE PRECISION ) FROM emp.resources
-		WHERE resource_name_id = _get_string( 'testResource3' )
-			AND empire_id = _get_emp_name( 'testEmp1' );
-	SELECT diag_test_name( 'EMPIRE_RESOURCES update - Resource 3 - Owed quantity unchanged' );
-	SELECT is( empres_owed , 0::DOUBLE PRECISION ) FROM emp.resources
-		WHERE resource_name_id = _get_string( 'testResource3' )
-			AND empire_id = _get_emp_name( 'testEmp1' );
-
-	SELECT diag_test_name( 'EMPIRE_RESOURCES update - Resource 1 / Vacation - Possessed quantity increased' );
-	SELECT is( empres_possessed , 6::DOUBLE PRECISION ) FROM emp.resources
-		WHERE resource_name_id = _get_string( 'testResource1' )
-			AND empire_id = _get_emp_name( 'testEmp2' );
-	SELECT diag_test_name( 'EMPIRE_RESOURCES update - Resource 1 / Vacation - Owed quantity unchanged' );
-	SELECT is( empres_owed , 0::DOUBLE PRECISION ) FROM emp.resources
-		WHERE resource_name_id = _get_string( 'testResource1' )
-			AND empire_id = _get_emp_name( 'testEmp2' );
-	SELECT diag_test_name( 'EMPIRE_RESOURCES update - Resource 2 / Vacation - Possessed quantity unchanged' );
-	SELECT is( empres_possessed , 0::DOUBLE PRECISION ) FROM emp.resources
-		WHERE resource_name_id = _get_string( 'testResource2' )
-			AND empire_id = _get_emp_name( 'testEmp2' );
-	SELECT diag_test_name( 'EMPIRE_RESOURCES update - Resource 2 / Vacation - Owed quantity increased' );
-	SELECT is( empres_owed , 17::DOUBLE PRECISION ) FROM emp.resources
-		WHERE resource_name_id = _get_string( 'testResource2' )
-			AND empire_id = _get_emp_name( 'testEmp2' );
-	SELECT diag_test_name( 'EMPIRE_RESOURCES update - Resource 3 / Vacation - Possessed quantity unchanged' );
-	SELECT is( empres_possessed , 0::DOUBLE PRECISION ) FROM emp.resources
-		WHERE resource_name_id = _get_string( 'testResource3' )
-			AND empire_id = _get_emp_name( 'testEmp2' );
-	SELECT diag_test_name( 'EMPIRE_RESOURCES update - Resource 3 / Vacation - Owed quantity unchanged' );
-	SELECT is( empres_owed , 0::DOUBLE PRECISION ) FROM emp.resources
-		WHERE resource_name_id = _get_string( 'testResource3' )
-			AND empire_id = _get_emp_name( 'testEmp2' );
-
-	SELECT diag_test_name( 'EMPIRE_RESOURCES update - Resources unchanged for already processed empire' );
-	SELECT is( SUM( empres_owed + empres_possessed ) , 0::DOUBLE PRECISION )
-		FROM emp.resources
-		WHERE empire_id = _get_emp_name( 'testEmp3' );
-
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/admin/050-updates/020-empire-research/010-gu-research-get-empires.sql b/legacyworlds-server-data/db-structure/tests/admin/050-updates/020-empire-research/010-gu-research-get-empires.sql
deleted file mode 100644
index ad02ba8..0000000
--- a/legacyworlds-server-data/db-structure/tests/admin/050-updates/020-empire-research/010-gu-research-get-empires.sql
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Test the sys.gu_research_get_empires() function
- */
-BEGIN;
-	\i utils/common-setup/setup-gu-research-get-empires-test.sql
-
-	SELECT plan( 2 );
-
-	SELECT diag_test_name( 'gu_research_get_empires() - Selected empires and vacation state' );
-	SELECT set_eq( $$
-		SELECT * FROM sys.gu_research_get_empires( 0::BIGINT );
-	$$ , $$ VALUES (
-		_get_emp_name( 'emp4') , FALSE
-	) , (
-		_get_emp_name( 'emp5') , TRUE
-	) $$ );
-
-	SELECT diag_test_name( 'gu_research_get_empires() - No results with "bad" update identifier' );
-	SELECT is_empty( $$
-		SELECT * FROM sys.gu_research_get_empires( 12::BIGINT );
-	$$ );
-
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/admin/050-updates/105-planet-resource-regeneration/010-process-planet-res-regen-updates.sql b/legacyworlds-server-data/db-structure/tests/admin/050-updates/105-planet-resource-regeneration/010-process-planet-res-regen-updates.sql
deleted file mode 100644
index 72c4188..0000000
--- a/legacyworlds-server-data/db-structure/tests/admin/050-updates/105-planet-resource-regeneration/010-process-planet-res-regen-updates.sql
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Test for the sys.process_planet_res_regen_updates() function
- */
-BEGIN;
-	/* Start by deleting all update types except for the one
-	 * we're interested in.
-	 */
-	DELETE FROM sys.update_types
-		WHERE updtype_name <> 'ResourceRegeneration';
-
-	/* We need to create a natural resource and a pair of planets */
-	\i utils/strings.sql
-	\i utils/resources.sql
-	\i utils/accounts.sql
-	\i utils/naming.sql
-	\i utils/universe.sql
-	SELECT _create_natural_resources( 1 , 'testResource' );
-	SELECT _create_raw_planets( 3 , 'testPlanet' );
-
-	/* Define the necessary constants using default values */
-	SELECT sys.uoc_constant( 'game.resources.recovery' , '(test)' , 'Resources' , 0.01 );
-	SELECT sys.uoc_constant( 'game.resources.recoveryDampening' , '(test)' , 'Resources' , 1.5 );
-	
-	/* Create resource providers */
-	INSERT INTO verse.resource_providers ( planet_id , resource_name_id ,
-			resprov_quantity_max , resprov_quantity ,
-			resprov_difficulty , resprov_recovery )
-		VALUES (
-			 _get_map_name( 'testPlanet1' ) ,  _get_string( 'testResource1' ) ,
-			 100 , 50 ,
-			 0.5 , 0.5
-		) , (
-			 _get_map_name( 'testPlanet2' ) ,  _get_string( 'testResource1' ) ,
-			 100 , 100 ,
-			 0.5 , 0.5
-		) , (
-			 _get_map_name( 'testPlanet3' ) ,  _get_string( 'testResource1' ) ,
-			 100 , 50 ,
-			 0.5 , 0.5
-		);
-	
-	/* Modify update records for the planets. Planets 1 and 2 will be processed,
-	 * planet testPlanet3 will not.
-	 */
-	UPDATE sys.updates su
-		SET update_state = 'PROCESSING' , update_last = 0
-		FROM verse.planets_updates vu
-		WHERE vu.update_id = su.update_id
-			AND vu.name_id <>  _get_map_name( 'testPlanet3' );
-	UPDATE sys.updates su
-		SET update_state = 'PROCESSED' , update_last = 0
-		FROM verse.planets_updates vu
-		WHERE vu.update_id = su.update_id
-			AND vu.name_id = _get_map_name( 'testPlanet3' );
-
-	/* Helper function that gets a provider's current quantity */
-	CREATE FUNCTION _get_quantity( _planet TEXT )
-		RETURNS DOUBLE PRECISION
-	AS $$
-		SELECT resprov_quantity FROM verse.resource_providers
-			WHERE planet_id = _get_map_name( $1 )
-				AND resource_name_id = _get_string( 'testResource1' );
-	$$ LANGUAGE SQL;
-
-	/****** TESTS BEGIN HERE ******/
-	SELECT plan( 6 );
-
-
-	SELECT sys.process_res_regen_updates( 10 );
-	SELECT diag_test_name( 'PLANET_RES_REGEN update - Wrong update identifier (1/3)' );
-	SELECT ok( _get_quantity( 'testPlanet1' ) = 50 );
-	SELECT diag_test_name( 'PLANET_RES_REGEN update - Wrong update identifier (2/3)' );
-	SELECT ok( _get_quantity( 'testPlanet2' ) = 100 );
-	SELECT diag_test_name( 'PLANET_RES_REGEN update - Wrong update identifier (3/3)' );
-	SELECT ok( _get_quantity( 'testPlanet3' ) = 50 );
-
-
-	SELECT sys.process_res_regen_updates( 0 );
-	SELECT diag_test_name( 'PLANET_RES_REGEN update - Processed planet with quantity < max.' );
-	SELECT ok( _get_quantity( 'testPlanet1' ) > 50 );
-	SELECT diag_test_name( 'PLANET_RES_REGEN update - Processed planet with quantity = max.' );
-	SELECT ok( _get_quantity( 'testPlanet2' ) = 100 );
-	SELECT diag_test_name( 'PLANET_RES_REGEN update - Already processed planet' );
-	SELECT ok( _get_quantity( 'testPlanet3' ) = 50 );
-
-
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/admin/050-updates/120-planet-mining/010-gu-pmc-get-data.sql b/legacyworlds-server-data/db-structure/tests/admin/050-updates/120-planet-mining/010-gu-pmc-get-data.sql
deleted file mode 100644
index 026aa34..0000000
--- a/legacyworlds-server-data/db-structure/tests/admin/050-updates/120-planet-mining/010-gu-pmc-get-data.sql
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Test the sys.gu_pmc_get_data() function
- */
-BEGIN;
-	\i utils/common-setup/setup-gu-pmc-get-data-test.sql
-
-	/* Select results into a temporary table */
-	CREATE TEMPORARY TABLE test_results
-		AS SELECT * FROM sys.gu_pmc_get_data( 0 );
-
-
-
-	/***** TESTS BEGIN HERE *****/
-	SELECT plan( 9 );
-	
-	SELECT diag_test_name( 'sys.gu_pmc_get_data() - Neutral planet without resource providers not included' );
-	SELECT is_empty( $$
-		SELECT * FROM test_results
-			WHERE planet = _get_map_name ( 'planet1' );
-	$$ );
-
-	SELECT diag_test_name( 'sys.gu_pmc_get_data() - Neutral planet with resource providers - Rows included' );
-	SELECT is( COUNT(*)::INT , 2)
-		FROM test_results
-		WHERE planet = _get_map_name ( 'planet2' )
-			AND difficulty = 0.2 AND empire IS NULL
-			AND happiness IS NULL AND weight IS NULL
-			AND total_weight IS NULL;
-	SELECT diag_test_name( 'sys.gu_pmc_get_data() - Neutral planet with resource providers - No extra rows' );
-	SELECT is_empty( $$
-		SELECT * FROM test_results
-			WHERE planet = _get_map_name ( 'planet2' )
-				AND NOT ( difficulty = 0.2 AND empire IS NULL
-					AND happiness IS NULL AND weight IS NULL
-					AND total_weight IS NULL );
-	$$ );
-
-	SELECT diag_test_name( 'sys.gu_pmc_get_data() - Planet using empire settings - Rows included' );
-	SELECT is( COUNT(*)::INT , 2)
-		FROM test_results
-		WHERE planet = _get_map_name ( 'planet3' ) AND difficulty = 0.3
-			AND empire = _get_emp_name( 'empire1' )
-			AND happiness IS NOT NULL AND weight = 100
-			AND total_weight = 200;
-	SELECT diag_test_name( 'sys.gu_pmc_get_data() - Planet using empire settings - No extra rows' );
-	SELECT is_empty( $$
-		SELECT * FROM test_results
-			WHERE planet = _get_map_name ( 'planet3' )
-				AND NOT ( difficulty = 0.3
-					AND empire = _get_emp_name( 'empire1' )
-					AND happiness IS NOT NULL
-					AND weight = 100 AND total_weight = 200 );
-	$$ );
-
-	SELECT diag_test_name( 'sys.gu_pmc_get_data() - Planet using specific settings - Rows included' );
-	SELECT is( COUNT(*)::INT , 2)
-		FROM test_results
-		WHERE planet = _get_map_name ( 'planet4' ) AND difficulty = 0.4
-			AND empire = _get_emp_name( 'empire2' )
-			AND happiness IS NOT NULL AND (
-				( resource = _get_string( 'resource1' ) AND weight = 10 )
-				OR ( resource = _get_string( 'resource2' ) AND weight = 1000 ) )
-			AND total_weight = 1010;
-	SELECT diag_test_name( 'sys.gu_pmc_get_data() - Planet using specific settings - No extra rows' );
-	SELECT is_empty( $$
-		SELECT * FROM test_results
-			WHERE planet = _get_map_name ( 'planet4' )
-				AND NOT ( difficulty = 0.4
-					AND empire = _get_emp_name( 'empire2' )
-					AND happiness IS NOT NULL
-					AND total_weight = 1010 AND (
-						( resource = _get_string( 'resource1' ) AND weight = 10 )
-						OR ( resource = _get_string( 'resource2' ) AND weight = 1000 ) ) );
-	$$ );
-	
-	SELECT diag_test_name( 'sys.gu_pmc_get_data() - Owned planet without resource providers not included' );
-	SELECT is_empty( $$
-		SELECT * FROM test_results
-			WHERE planet = _get_map_name ( 'planet5' );
-	$$ );
-	
-	SELECT diag_test_name( 'sys.gu_pmc_get_data() - Planet matching all criterias but marked as processed not included' );
-	SELECT is_empty( $$
-		SELECT * FROM test_results
-			WHERE planet = _get_map_name ( 'planet6' );
-	$$ );
-
-	SELECT * FROM finish( );
-ROLLBACK;
diff --git a/legacyworlds-server-data/db-structure/tests/admin/050-updates/120-planet-mining/020-process-planet-mining-updates.sql b/legacyworlds-server-data/db-structure/tests/admin/050-updates/120-planet-mining/020-process-planet-mining-updates.sql
deleted file mode 100644
index 3aabf15..0000000
--- a/legacyworlds-server-data/db-structure/tests/admin/050-updates/120-planet-mining/020-process-planet-mining-updates.sql
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Test the sys.process_planet_mining_updates() function
- */
-BEGIN;
-	/* Disable other update types */
-	DELETE FROM sys.update_types
-		WHERE updtype_name <> 'PlanetMining';
-
-	/* We need two planets with identicals resource records and resource providers. */
-	\i utils/strings.sql
-	\i utils/resources.sql
-	\i utils/accounts.sql
-	\i utils/naming.sql
-	\i utils/universe.sql
-
-	SELECT _create_natural_resources( 1 , 'resource' );
-	SELECT _create_raw_planets( 2 , 'planet' );
-
-	INSERT INTO verse.resource_providers (
-			planet_id , resource_name_id , resprov_quantity_max ,
-			resprov_quantity , resprov_difficulty , resprov_recovery
-		) VALUES (
-			_get_map_name( 'planet1' ) , _get_string( 'resource1' ) , 100 ,
-			100 , 0.2 , 0.5
-		) , (
-			_get_map_name( 'planet2' ) , _get_string( 'resource1' ) , 100 ,
-			100 , 0.2 , 0.5
-		);
-
-	INSERT INTO verse.planet_resources ( planet_id , resource_name_id , pres_income , pres_upkeep )
-		SELECT p.name_id , r.resource_name_id , 50 , 0
-			FROM verse.planets p CROSS JOIN defs.resources r;
-
-	/* First planet will be updated, second will not */
-	UPDATE sys.updates su
-		SET update_state = 'PROCESSING' , update_last = 0
-		FROM verse.planets_updates vu
-		WHERE vu.update_id = su.update_id
-			AND vu.name_id =  _get_map_name( 'planet1' );
-	UPDATE sys.updates su
-		SET update_state = 'PROCESSED' , update_last = 0
-		FROM verse.planets_updates vu
-		WHERE vu.update_id = su.update_id
-			AND vu.name_id = _get_map_name( 'planet2' );
-
-	/* Replace sys.gu_pmc_get_data() and emp.mining_compute_extraction(); both
-	 * functions will write to temporary tables. 
-	 */
-	CREATE TABLE _get_data_calls( tick BIGINT );
-	CREATE OR REPLACE FUNCTION sys.gu_pmc_get_data( _tick BIGINT )
-		RETURNS SETOF emp.planet_mining_type LANGUAGE SQL
-	AS $$
-		INSERT INTO _get_data_calls VALUES ( $1 );
-		SELECT _get_map_name( 'planet1' ) AS planet ,
-			_get_string( 'resource1' ) AS resource ,
-			NULL::DOUBLE PRECISION AS quantity , NULL::DOUBLE PRECISION AS quantity_max ,
-			NULL::DOUBLE PRECISION AS difficulty , NULL::INT AS empire ,
-			NULL::REAL AS happiness , NULL::DOUBLE PRECISION AS weight ,
-			NULL::DOUBLE PRECISION AS total_weight;
-	$$;
-	
-	CREATE OR REPLACE FUNCTION emp.mining_compute_extraction( _input emp.planet_mining_type )
-			RETURNS DOUBLE PRECISION LANGUAGE SQL
-	AS $$
-		SELECT 42::DOUBLE PRECISION;
-	$$;
-
-	/***** TESTS BEGIN HERE *****/
-	SELECT plan( 3 );
-	
-	SELECT sys.process_planet_mining_updates( 0 );
-
-	SELECT diag_test_name( 'sys.process_planet_mining_updates() - Resource providers updated' );
-	SELECT set_eq(
-		$$ SELECT planet_id , resprov_quantity FROM verse.resource_providers $$ ,
-		$$ VALUES ( _get_map_name( 'planet1' ) , 50 ) , ( _get_map_name( 'planet2' ) , 100 ) $$
-	);
-
-	SELECT diag_test_name( 'sys.process_planet_mining_updates() - Planet resources updated' );
-	SELECT set_eq(
-		$$ SELECT planet_id , pres_income FROM verse.planet_resources $$ ,
-		$$ VALUES ( _get_map_name( 'planet1' ) , 42 ) , ( _get_map_name( 'planet2' ) , 50 ) $$
-	);
-
-	SELECT diag_test_name( 'sys.process_planet_mining_updates() - Two calls to gu_pmc_get_data()' );
-	SELECT is( COUNT(*)::INT , 2 ) FROM _get_data_calls;
-
-	SELECT * FROM finish( );
-ROLLBACK;
diff --git a/legacyworlds-server-data/db-structure/tests/dirty/000-dirty-tests-self-check/prepare.sql b/legacyworlds-server-data/db-structure/tests/dirty/000-dirty-tests-self-check/prepare.sql
deleted file mode 100644
index d7d0d76..0000000
--- a/legacyworlds-server-data/db-structure/tests/dirty/000-dirty-tests-self-check/prepare.sql
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Dirty test system self-check
- *
- * Insert an address, it should exist during the main test. Also create a
- * function and a table which are used to synchronise execution.
- */
-BEGIN;
-	INSERT INTO users.addresses ( address )
-		VALUES ( 'prepare@example.org' );
-
-	CREATE TABLE _barriers( _barrier BIGINT );
-
-	CREATE FUNCTION _synchronise_tests( _lock BIGINT )
-		RETURNS VOID
-	AS $$
-	BEGIN
-		WHILE pg_try_advisory_lock( _lock )
-		LOOP
-			PERFORM pg_advisory_unlock( _lock );
-		END LOOP;
-	END;
-	$$ LANGUAGE PLPGSQL;
-COMMIT;
diff --git a/legacyworlds-server-data/db-structure/tests/dirty/000-dirty-tests-self-check/run-test.sql b/legacyworlds-server-data/db-structure/tests/dirty/000-dirty-tests-self-check/run-test.sql
deleted file mode 100644
index be13190..0000000
--- a/legacyworlds-server-data/db-structure/tests/dirty/000-dirty-tests-self-check/run-test.sql
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- * Dirty test system self-check
- *
- * Insert an address, it should exist during the main test.
- */
-BEGIN;
-	SELECT plan( 1 );
-
-	SELECT diag_test_name( 'Dirty test system self-check - prepare.sql was executed' );
-	SELECT is( COUNT(*)::INT , 1 )
-		FROM users.addresses
-		WHERE address = 'prepare@example.org';
-
-	SELECT * FROM finish( );
-ROLLBACK;
diff --git a/legacyworlds-server-data/db-structure/tests/dirty/010-mining-update-locks/prepare.sql b/legacyworlds-server-data/db-structure/tests/dirty/010-mining-update-locks/prepare.sql
deleted file mode 100644
index 674e320..0000000
--- a/legacyworlds-server-data/db-structure/tests/dirty/010-mining-update-locks/prepare.sql
+++ /dev/null
@@ -1,8 +0,0 @@
-/*
- * Prepare for the locking tests on sys.gu_pmc_get_data() 
- */
-BEGIN;
-	CREATE EXTENSION pageinspect;
-	\i utils/common-setup/setup-gu-pmc-get-data-test.sql
-	\i utils/locks-finder.sql
-COMMIT;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/dirty/010-mining-update-locks/run-test.sql b/legacyworlds-server-data/db-structure/tests/dirty/010-mining-update-locks/run-test.sql
deleted file mode 100644
index 1cb5b65..0000000
--- a/legacyworlds-server-data/db-structure/tests/dirty/010-mining-update-locks/run-test.sql
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Test the locks set by sys.gu_pmc_get_data( )
- */
-BEGIN;
-	SELECT * FROM sys.gu_pmc_get_data( 0 );
-	SELECT plan( 7 );
-
-	SELECT diag_test_name( 'sys.gu_pmc_get_data() - Locks on planets' );
-	SELECT set_eq ( $$
-			SELECT name_id , shared , exclusive
-				FROM verse.planets pl
-					INNER JOIN ( SELECT * FROM _get_locks_on( 'verse.planets' ) ) p
-						ON p.ctid = pl.ctid;
-		$$ , $$
-			VALUES ( _get_map_name( 'planet2' ) , TRUE , FALSE ) ,
-				( _get_map_name( 'planet3' ) , TRUE , FALSE ) ,
-				( _get_map_name( 'planet4' ) , TRUE , FALSE );
-		$$
-	);
-
-	SELECT diag_test_name( 'sys.gu_pmc_get_data() - Locks on resource providers' );
-	SELECT set_eq ( $$
-			SELECT planet_id , resource_name_id , shared , exclusive
-				FROM verse.resource_providers rp
-					INNER JOIN ( SELECT * FROM _get_locks_on( 'verse.resource_providers' ) ) p
-						ON p.ctid = rp.ctid;
-		$$ , $$
-			VALUES ( _get_map_name( 'planet2' ) , _get_string('resource1') , FALSE , TRUE ) ,
-				( _get_map_name( 'planet2' ) , _get_string('resource2') , FALSE , TRUE ) ,
-				( _get_map_name( 'planet3' ) , _get_string('resource1') , FALSE , TRUE ) ,
-				( _get_map_name( 'planet3' ) , _get_string('resource2') , FALSE , TRUE ) ,
-				( _get_map_name( 'planet4' ) , _get_string('resource1') , FALSE , TRUE ) ,
-				( _get_map_name( 'planet4' ) , _get_string('resource2') , FALSE , TRUE );
-		$$
-	);
-
-	SELECT diag_test_name( 'sys.gu_pmc_get_data() - Locks on planet resources' );
-	SELECT set_eq ( $$
-			SELECT planet_id , resource_name_id , shared , exclusive
-				FROM verse.planet_resources pr
-					INNER JOIN ( SELECT * FROM _get_locks_on( 'verse.planet_resources' ) ) p
-						ON p.ctid = pr.ctid;
-		$$ , $$
-			VALUES ( _get_map_name( 'planet2' ) , _get_string('resource1') , FALSE , TRUE ) ,
-				( _get_map_name( 'planet2' ) , _get_string('resource2') , FALSE , TRUE ) ,
-				( _get_map_name( 'planet3' ) , _get_string('resource1') , FALSE , TRUE ) ,
-				( _get_map_name( 'planet3' ) , _get_string('resource2') , FALSE , TRUE ) ,
-				( _get_map_name( 'planet4' ) , _get_string('resource1') , FALSE , TRUE ) ,
-				( _get_map_name( 'planet4' ) , _get_string('resource2') , FALSE , TRUE );
-		$$
-	);
-
-	SELECT diag_test_name( 'sys.gu_pmc_get_data() - Locks on empire planets' );
-	SELECT set_eq ( $$
-			SELECT planet_id , empire_id , shared , exclusive
-				FROM emp.planets ep
-					INNER JOIN ( SELECT * FROM _get_locks_on( 'emp.planets' ) ) p
-						ON p.ctid = ep.ctid;
-		$$ , $$
-			VALUES ( _get_map_name( 'planet3' ) , _get_emp_name('empire1' ) , TRUE , FALSE ) ,
-				( _get_map_name( 'planet4' ) , _get_emp_name('empire2' ) , TRUE , FALSE );
-		$$
-	);
-
-	SELECT diag_test_name( 'sys.gu_pmc_get_data() - Locks on mining settings' );
-	SELECT set_eq ( $$
-			SELECT empire_id , resource_name_id , shared , exclusive
-				FROM emp.mining_settings ms
-					INNER JOIN ( SELECT * FROM _get_locks_on( 'emp.mining_settings' ) ) p
-						ON p.ctid = ms.ctid;
-		$$ , $$
-			VALUES ( _get_emp_name('empire1' ) , _get_string( 'resource1' ) , TRUE , FALSE ) ,
-				( _get_emp_name('empire1' ) , _get_string( 'resource2' ) , TRUE , FALSE ) ,
-				( _get_emp_name('empire2' ) , _get_string( 'resource1' ) , TRUE , FALSE ) ,
-				( _get_emp_name('empire2' ) , _get_string( 'resource2' ) , TRUE , FALSE );
-		$$
-	);
-
-	SELECT diag_test_name( 'sys.gu_pmc_get_data() - Locks on planet mining settings' );
-	SELECT set_eq ( $$
-			SELECT empire_id , planet_id , resource_name_id , shared , exclusive
-				FROM emp.planet_mining_settings ms
-					INNER JOIN ( SELECT * FROM _get_locks_on( 'emp.planet_mining_settings' ) ) p
-						ON p.ctid = ms.ctid;
-		$$ , $$
-			VALUES ( _get_emp_name('empire2' ) , _get_map_name( 'planet4' ) , _get_string( 'resource1' ) , TRUE , FALSE ) ,
-				( _get_emp_name('empire2' ) , _get_map_name( 'planet4' ) , _get_string( 'resource2' ) , TRUE , FALSE );
-		$$
-	);
-
-	SELECT diag_test_name( 'sys.gu_pmc_get_data() - Locks on planet happiness records' );
-	SELECT set_eq ( $$
-			SELECT planet_id , shared , exclusive
-				FROM verse.planet_happiness pl
-					INNER JOIN ( SELECT * FROM _get_locks_on( 'verse.planet_happiness' ) ) p
-						ON p.ctid = pl.ctid;
-		$$ , $$
-			VALUES ( _get_map_name( 'planet3' ) , TRUE , FALSE ) ,
-				( _get_map_name( 'planet4' ) , TRUE , FALSE );
-		$$
-	);
-
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/dirty/run-dirty-tests.sh b/legacyworlds-server-data/db-structure/tests/dirty/run-dirty-tests.sh
deleted file mode 100755
index 07f1cf4..0000000
--- a/legacyworlds-server-data/db-structure/tests/dirty/run-dirty-tests.sh
+++ /dev/null
@@ -1,37 +0,0 @@
-#!/bin/bash
-
-if [ -z "$TEST_DATABASE" ]; then
-	echo "Missing TEST_DATABASE environment variable"
-	exit 1;
-fi
-
-echo
-echo 'Running "dirty" database tests'
-echo
-
-find -mindepth 1 -maxdepth 1 -type d | sort | while read testdir; do
-
-	[ -f "$testdir/run-test.sql" ] || continue
-
-	echo "Dirty test $testdir"
-	echo "--------------------------------------------"
-	echo
-
-	echo "Creating temporary database ..."
-	echo "DROP DATABASE IF EXISTS dirty_tests; CREATE DATABASE dirty_tests TEMPLATE $TEST_DATABASE;" \
-		| psql -vQUIET=1 -vON_ERROR_STOP=1 $TEST_DATABASE || exit 1
-
-	if [ -f "$testdir/prepare.sql" ]; then
-		echo "Preparing database ..."
-		( cd .. && exec psql -vQUIET=1 -vON_ERROR_STOP=1 --file "dirty/$testdir/prepare.sql" dirty_tests ) || exit 1
-	fi
-
-	echo "Running main test ..."
-	( cd .. && pg_prove -d dirty_tests dirty/$testdir/run-test.sql ) || exit 1
-
-	echo "Dropping temporary database ..."
-	echo -e "DROP DATABASE IF EXISTS dirty_tests;" \
-		| psql -vQUIET=1 -vON_ERROR_STOP=1 $TEST_DATABASE || exit 1
-
-	echo
-done
diff --git a/legacyworlds-server-data/db-structure/tests/pgtap.sql b/legacyworlds-server-data/db-structure/tests/pgtap.sql
deleted file mode 100644
index 5a14976..0000000
--- a/legacyworlds-server-data/db-structure/tests/pgtap.sql
+++ /dev/null
@@ -1,7402 +0,0 @@
--- This file defines pgTAP, a collection of functions for TAP-based unit
--- testing. It is distributed under the revised FreeBSD license. You can
--- find the original here:
---
--- http://github.com/theory/pgtap/raw/master/sql/pgtap.sql.in
---
--- The home page for the pgTAP project is:
---
--- http://pgtap.org/
-
-CREATE OR REPLACE FUNCTION pg_version()
-RETURNS text AS 'SELECT current_setting(''server_version'')'
-LANGUAGE SQL IMMUTABLE;
-
-CREATE OR REPLACE FUNCTION pg_version_num()
-RETURNS integer AS $$
-    SELECT s.a[1]::int * 10000
-           + COALESCE(substring(s.a[2] FROM '[[:digit:]]+')::int, 0) * 100
-           + COALESCE(substring(s.a[3] FROM '[[:digit:]]+')::int, 0)
-      FROM (
-          SELECT string_to_array(current_setting('server_version'), '.') AS a
-      ) AS s;
-$$ LANGUAGE SQL IMMUTABLE;
-
-CREATE OR REPLACE FUNCTION os_name()
-RETURNS TEXT AS 'SELECT ''''::text;'
-LANGUAGE SQL IMMUTABLE;
-
-CREATE OR REPLACE FUNCTION pgtap_version()
-RETURNS NUMERIC AS 'SELECT 0.90;'
-LANGUAGE SQL IMMUTABLE;
-
-CREATE OR REPLACE FUNCTION plan( integer )
-RETURNS TEXT AS $$
-DECLARE
-    rcount INTEGER;
-BEGIN
-    BEGIN
-        EXECUTE '
-            CREATE TEMP SEQUENCE __tcache___id_seq;
-            CREATE TEMP TABLE __tcache__ (
-                id    INTEGER NOT NULL DEFAULT nextval(''__tcache___id_seq''),
-                label TEXT    NOT NULL,
-                value INTEGER NOT NULL,
-                note  TEXT    NOT NULL DEFAULT ''''
-            );
-            CREATE UNIQUE INDEX __tcache___key ON __tcache__(id);
-            GRANT ALL ON TABLE __tcache__ TO PUBLIC;
-            GRANT ALL ON TABLE __tcache___id_seq TO PUBLIC;
-
-            CREATE TEMP SEQUENCE __tresults___numb_seq;
-            CREATE TEMP TABLE __tresults__ (
-                numb   INTEGER NOT NULL DEFAULT nextval(''__tresults___numb_seq''),
-                ok     BOOLEAN NOT NULL DEFAULT TRUE,
-                aok    BOOLEAN NOT NULL DEFAULT TRUE,
-                descr  TEXT    NOT NULL DEFAULT '''',
-                type   TEXT    NOT NULL DEFAULT '''',
-                reason TEXT    NOT NULL DEFAULT ''''
-            );
-            CREATE UNIQUE INDEX __tresults___key ON __tresults__(numb);
-            GRANT ALL ON TABLE __tresults__ TO PUBLIC;
-            GRANT ALL ON TABLE __tresults___numb_seq TO PUBLIC;
-        ';
-
-    EXCEPTION WHEN duplicate_table THEN
-        -- Raise an exception if there's already a plan.
-        EXECUTE 'SELECT TRUE FROM __tcache__ WHERE label = ''plan''';
-      GET DIAGNOSTICS rcount = ROW_COUNT;
-        IF rcount > 0 THEN
-           RAISE EXCEPTION 'You tried to plan twice!';
-        END IF;
-    END;
-
-    -- Save the plan and return.
-    PERFORM _set('plan', $1 );
-    RETURN '1..' || $1;
-END;
-$$ LANGUAGE plpgsql strict;
-
-CREATE OR REPLACE FUNCTION no_plan()
-RETURNS SETOF boolean AS $$
-BEGIN
-    PERFORM plan(0);
-    RETURN;
-END;
-$$ LANGUAGE plpgsql strict;
-
-CREATE OR REPLACE FUNCTION _get ( text )
-RETURNS integer AS $$
-DECLARE
-    ret integer;
-BEGIN
-    EXECUTE 'SELECT value FROM __tcache__ WHERE label = ' || quote_literal($1) || ' LIMIT 1' INTO ret;
-    RETURN ret;
-END;
-$$ LANGUAGE plpgsql strict;
-
-CREATE OR REPLACE FUNCTION _get_latest ( text )
-RETURNS integer[] AS $$
-DECLARE
-    ret integer[];
-BEGIN
-    EXECUTE 'SELECT ARRAY[ id, value] FROM __tcache__ WHERE label = ' ||
-    quote_literal($1) || ' AND id = (SELECT MAX(id) FROM __tcache__ WHERE label = ' ||
-    quote_literal($1) || ') LIMIT 1' INTO ret;
-    RETURN ret;
-END;
-$$ LANGUAGE plpgsql strict;
-
-CREATE OR REPLACE FUNCTION _get_latest ( text, integer )
-RETURNS integer AS $$
-DECLARE
-    ret integer;
-BEGIN
-    EXECUTE 'SELECT MAX(id) FROM __tcache__ WHERE label = ' ||
-    quote_literal($1) || ' AND value = ' || $2 INTO ret;
-    RETURN ret;
-END;
-$$ LANGUAGE plpgsql strict;
-
-CREATE OR REPLACE FUNCTION _get_note ( text )
-RETURNS text AS $$
-DECLARE
-    ret text;
-BEGIN
-    EXECUTE 'SELECT note FROM __tcache__ WHERE label = ' || quote_literal($1) || ' LIMIT 1' INTO ret;
-    RETURN ret;
-END;
-$$ LANGUAGE plpgsql strict;
-
-CREATE OR REPLACE FUNCTION _get_note ( integer )
-RETURNS text AS $$
-DECLARE
-    ret text;
-BEGIN
-    EXECUTE 'SELECT note FROM __tcache__ WHERE id = ' || $1 || ' LIMIT 1' INTO ret;
-    RETURN ret;
-END;
-$$ LANGUAGE plpgsql strict;
-
-CREATE OR REPLACE FUNCTION _set ( text, integer, text )
-RETURNS integer AS $$
-DECLARE
-    rcount integer;
-BEGIN
-    EXECUTE 'UPDATE __tcache__ SET value = ' || $2
-        || CASE WHEN $3 IS NULL THEN '' ELSE ', note = ' || quote_literal($3) END
-        || ' WHERE label = ' || quote_literal($1);
-    GET DIAGNOSTICS rcount = ROW_COUNT;
-    IF rcount = 0 THEN
-       RETURN _add( $1, $2, $3 );
-    END IF;
-    RETURN $2;
-END;
-$$ LANGUAGE plpgsql;
-
-CREATE OR REPLACE FUNCTION _set ( text, integer )
-RETURNS integer AS $$
-    SELECT _set($1, $2, '')
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION _set ( integer, integer )
-RETURNS integer AS $$
-BEGIN
-    EXECUTE 'UPDATE __tcache__ SET value = ' || $2
-        || ' WHERE id = ' || $1;
-    RETURN $2;
-END;
-$$ LANGUAGE plpgsql;
-
-CREATE OR REPLACE FUNCTION _add ( text, integer, text )
-RETURNS integer AS $$
-BEGIN
-    EXECUTE 'INSERT INTO __tcache__ (label, value, note) values (' ||
-    quote_literal($1) || ', ' || $2 || ', ' || quote_literal(COALESCE($3, '')) || ')';
-    RETURN $2;
-END;
-$$ LANGUAGE plpgsql;
-
-CREATE OR REPLACE FUNCTION _add ( text, integer )
-RETURNS integer AS $$
-    SELECT _add($1, $2, '')
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION add_result ( bool, bool, text, text, text )
-RETURNS integer AS $$
-BEGIN
-    EXECUTE 'INSERT INTO __tresults__ ( ok, aok, descr, type, reason )
-    VALUES( ' || $1 || ', '
-              || $2 || ', '
-              || quote_literal(COALESCE($3, '')) || ', '
-              || quote_literal($4) || ', '
-              || quote_literal($5) || ' )';
-    RETURN currval('__tresults___numb_seq');
-END;
-$$ LANGUAGE plpgsql;
-
-CREATE OR REPLACE FUNCTION num_failed ()
-RETURNS INTEGER AS $$
-DECLARE
-    ret integer;
-BEGIN
-    EXECUTE 'SELECT COUNT(*)::INTEGER FROM __tresults__ WHERE ok = FALSE' INTO ret;
-    RETURN ret;
-END;
-$$ LANGUAGE plpgsql strict;
-
-CREATE OR REPLACE FUNCTION _finish ( INTEGER, INTEGER, INTEGER)
-RETURNS SETOF TEXT AS $$
-DECLARE
-    curr_test ALIAS FOR $1;
-    exp_tests INTEGER := $2;
-    num_faild ALIAS FOR $3;
-    plural    CHAR;
-BEGIN
-    plural    := CASE exp_tests WHEN 1 THEN '' ELSE 's' END;
-
-    IF curr_test IS NULL THEN
-        RAISE EXCEPTION '# No tests run!';
-    END IF;
-
-    IF exp_tests = 0 OR exp_tests IS NULL THEN
-         -- No plan. Output one now.
-        exp_tests = curr_test;
-        RETURN NEXT '1..' || exp_tests;
-    END IF;
-
-    IF curr_test <> exp_tests THEN
-        RETURN NEXT diag(
-            'Looks like you planned ' || exp_tests || ' test' ||
-            plural || ' but ran ' || curr_test
-        );
-    ELSIF num_faild > 0 THEN
-        RETURN NEXT diag(
-            'Looks like you failed ' || num_faild || ' test' ||
-            CASE num_faild WHEN 1 THEN '' ELSE 's' END
-            || ' of ' || exp_tests
-        );
-    ELSE
-
-    END IF;
-    RETURN;
-END;
-$$ LANGUAGE plpgsql;
-
-CREATE OR REPLACE FUNCTION finish ()
-RETURNS SETOF TEXT AS $$
-    SELECT * FROM _finish(
-        _get('curr_test'),
-        _get('plan'),
-        num_failed()
-    );
-$$ LANGUAGE sql;
-
-CREATE OR REPLACE FUNCTION diag ( msg text )
-RETURNS TEXT AS $$
-    SELECT '# ' || replace(
-       replace(
-            replace( $1, E'\r\n', E'\n# ' ),
-            E'\n',
-            E'\n# '
-        ),
-        E'\r',
-        E'\n# '
-    );
-$$ LANGUAGE sql strict;
-
-CREATE OR REPLACE FUNCTION diag ( msg anyelement )
-RETURNS TEXT AS $$
-    SELECT diag($1::text);
-$$ LANGUAGE sql;
-
-CREATE OR REPLACE FUNCTION diag( VARIADIC text[] )
-RETURNS TEXT AS $$
-    SELECT diag(array_to_string($1, ''));
-$$ LANGUAGE sql;
-
-CREATE OR REPLACE FUNCTION diag( VARIADIC anyarray )
-RETURNS TEXT AS $$
-    SELECT diag(array_to_string($1, ''));
-$$ LANGUAGE sql;
-
-CREATE OR REPLACE FUNCTION ok ( boolean, text )
-RETURNS TEXT AS $$
-DECLARE
-   aok      ALIAS FOR $1;
-   descr    text := $2;
-   test_num INTEGER;
-   todo_why TEXT;
-   ok       BOOL;
-BEGIN
-   todo_why := _todo();
-   ok       := CASE
-       WHEN aok = TRUE THEN aok
-       WHEN todo_why IS NULL THEN COALESCE(aok, false)
-       ELSE TRUE
-    END;
-    IF _get('plan') IS NULL THEN
-        RAISE EXCEPTION 'You tried to run a test without a plan! Gotta have a plan';
-    END IF;
-
-    test_num := add_result(
-        ok,
-        COALESCE(aok, false),
-        descr,
-        CASE WHEN todo_why IS NULL THEN '' ELSE 'todo' END,
-        COALESCE(todo_why, '')
-    );
-
-    RETURN (CASE aok WHEN TRUE THEN '' ELSE 'not ' END)
-           || 'ok ' || _set( 'curr_test', test_num )
-           || CASE descr WHEN '' THEN '' ELSE COALESCE( ' - ' || substr(diag( descr ), 3), '' ) END
-           || COALESCE( ' ' || diag( 'TODO ' || todo_why ), '')
-           || CASE aok WHEN TRUE THEN '' ELSE E'\n' ||
-                diag('Failed ' ||
-                CASE WHEN todo_why IS NULL THEN '' ELSE '(TODO) ' END ||
-                'test ' || test_num ||
-                CASE descr WHEN '' THEN '' ELSE COALESCE(': "' || descr || '"', '') END ) ||
-                CASE WHEN aok IS NULL THEN E'\n' || diag('    (test result was NULL)') ELSE '' END
-           END;
-END;
-$$ LANGUAGE plpgsql;
-
-CREATE OR REPLACE FUNCTION ok ( boolean )
-RETURNS TEXT AS $$
-    SELECT ok( $1, NULL );
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION is (anyelement, anyelement, text)
-RETURNS TEXT AS $$
-DECLARE
-    result BOOLEAN;
-    output TEXT;
-BEGIN
-    -- Would prefer $1 IS NOT DISTINCT FROM, but that's not supported by 8.1.
-    result := NOT $1 IS DISTINCT FROM $2;
-    output := ok( result, $3 );
-    RETURN output || CASE result WHEN TRUE THEN '' ELSE E'\n' || diag(
-           '        have: ' || CASE WHEN $1 IS NULL THEN 'NULL' ELSE $1::text END ||
-        E'\n        want: ' || CASE WHEN $2 IS NULL THEN 'NULL' ELSE $2::text END
-    ) END;
-END;
-$$ LANGUAGE plpgsql;
-
-CREATE OR REPLACE FUNCTION is (anyelement, anyelement)
-RETURNS TEXT AS $$
-    SELECT is( $1, $2, NULL);
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION isnt (anyelement, anyelement, text)
-RETURNS TEXT AS $$
-DECLARE
-    result BOOLEAN;
-    output TEXT;
-BEGIN
-    result := $1 IS DISTINCT FROM $2;
-    output := ok( result, $3 );
-    RETURN output || CASE result WHEN TRUE THEN '' ELSE E'\n' || diag(
-           '        have: ' || COALESCE( $1::text, 'NULL' ) ||
-        E'\n        want: anything else'
-    ) END;
-END;
-$$ LANGUAGE plpgsql;
-
-CREATE OR REPLACE FUNCTION isnt (anyelement, anyelement)
-RETURNS TEXT AS $$
-    SELECT isnt( $1, $2, NULL);
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION _alike ( BOOLEAN, ANYELEMENT, TEXT, TEXT )
-RETURNS TEXT AS $$
-DECLARE
-    result ALIAS FOR $1;
-    got    ALIAS FOR $2;
-    rx     ALIAS FOR $3;
-    descr  ALIAS FOR $4;
-    output TEXT;
-BEGIN
-    output := ok( result, descr );
-    RETURN output || CASE result WHEN TRUE THEN '' ELSE E'\n' || diag(
-           '                  ' || COALESCE( quote_literal(got), 'NULL' ) ||
-       E'\n   doesn''t match: ' || COALESCE( quote_literal(rx), 'NULL' )
-    ) END;
-END;
-$$ LANGUAGE plpgsql;
-
-CREATE OR REPLACE FUNCTION matches ( anyelement, text, text )
-RETURNS TEXT AS $$
-    SELECT _alike( $1 ~ $2, $1, $2, $3 );
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION matches ( anyelement, text )
-RETURNS TEXT AS $$
-    SELECT _alike( $1 ~ $2, $1, $2, NULL );
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION imatches ( anyelement, text, text )
-RETURNS TEXT AS $$
-    SELECT _alike( $1 ~* $2, $1, $2, $3 );
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION imatches ( anyelement, text )
-RETURNS TEXT AS $$
-    SELECT _alike( $1 ~* $2, $1, $2, NULL );
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION alike ( anyelement, text, text )
-RETURNS TEXT AS $$
-    SELECT _alike( $1 ~~ $2, $1, $2, $3 );
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION alike ( anyelement, text )
-RETURNS TEXT AS $$
-    SELECT _alike( $1 ~~ $2, $1, $2, NULL );
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION ialike ( anyelement, text, text )
-RETURNS TEXT AS $$
-    SELECT _alike( $1 ~~* $2, $1, $2, $3 );
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION ialike ( anyelement, text )
-RETURNS TEXT AS $$
-    SELECT _alike( $1 ~~* $2, $1, $2, NULL );
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION _unalike ( BOOLEAN, ANYELEMENT, TEXT, TEXT )
-RETURNS TEXT AS $$
-DECLARE
-    result ALIAS FOR $1;
-    got    ALIAS FOR $2;
-    rx     ALIAS FOR $3;
-    descr  ALIAS FOR $4;
-    output TEXT;
-BEGIN
-    output := ok( result, descr );
-    RETURN output || CASE result WHEN TRUE THEN '' ELSE E'\n' || diag(
-           '                  ' || COALESCE( quote_literal(got), 'NULL' ) ||
-        E'\n         matches: ' || COALESCE( quote_literal(rx), 'NULL' )
-    ) END;
-END;
-$$ LANGUAGE plpgsql;
-
-CREATE OR REPLACE FUNCTION doesnt_match ( anyelement, text, text )
-RETURNS TEXT AS $$
-    SELECT _unalike( $1 !~ $2, $1, $2, $3 );
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION doesnt_match ( anyelement, text )
-RETURNS TEXT AS $$
-    SELECT _unalike( $1 !~ $2, $1, $2, NULL );
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION doesnt_imatch ( anyelement, text, text )
-RETURNS TEXT AS $$
-    SELECT _unalike( $1 !~* $2, $1, $2, $3 );
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION doesnt_imatch ( anyelement, text )
-RETURNS TEXT AS $$
-    SELECT _unalike( $1 !~* $2, $1, $2, NULL );
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION unalike ( anyelement, text, text )
-RETURNS TEXT AS $$
-    SELECT _unalike( $1 !~~ $2, $1, $2, $3 );
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION unalike ( anyelement, text )
-RETURNS TEXT AS $$
-    SELECT _unalike( $1 !~~ $2, $1, $2, NULL );
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION unialike ( anyelement, text, text )
-RETURNS TEXT AS $$
-    SELECT _unalike( $1 !~~* $2, $1, $2, $3 );
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION unialike ( anyelement, text )
-RETURNS TEXT AS $$
-    SELECT _unalike( $1 !~~* $2, $1, $2, NULL );
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION cmp_ok (anyelement, text, anyelement, text)
-RETURNS TEXT AS $$
-DECLARE
-    have   ALIAS FOR $1;
-    op     ALIAS FOR $2;
-    want   ALIAS FOR $3;
-    descr  ALIAS FOR $4;
-    result BOOLEAN;
-    output TEXT;
-BEGIN
-    EXECUTE 'SELECT ' ||
-            COALESCE(quote_literal( have ), 'NULL') || '::' || pg_typeof(have) || ' '
-            || op || ' ' ||
-            COALESCE(quote_literal( want ), 'NULL') || '::' || pg_typeof(want)
-       INTO result;
-    output := ok( COALESCE(result, FALSE), descr );
-    RETURN output || CASE result WHEN TRUE THEN '' ELSE E'\n' || diag(
-           '    ' || COALESCE( quote_literal(have), 'NULL' ) ||
-           E'\n        ' || op ||
-           E'\n    ' || COALESCE( quote_literal(want), 'NULL' )
-    ) END;
-END;
-$$ LANGUAGE plpgsql;
-
-CREATE OR REPLACE FUNCTION cmp_ok (anyelement, text, anyelement)
-RETURNS TEXT AS $$
-    SELECT cmp_ok( $1, $2, $3, NULL );
-$$ LANGUAGE sql;
-
-CREATE OR REPLACE FUNCTION pass ( text )
-RETURNS TEXT AS $$
-    SELECT ok( TRUE, $1 );
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION pass ()
-RETURNS TEXT AS $$
-    SELECT ok( TRUE, NULL );
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION fail ( text )
-RETURNS TEXT AS $$
-    SELECT ok( FALSE, $1 );
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION fail ()
-RETURNS TEXT AS $$
-    SELECT ok( FALSE, NULL );
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION todo ( why text, how_many int )
-RETURNS SETOF BOOLEAN AS $$
-BEGIN
-    PERFORM _add('todo', COALESCE(how_many, 1), COALESCE(why, ''));
-    RETURN;
-END;
-$$ LANGUAGE plpgsql;
-
-CREATE OR REPLACE FUNCTION todo ( how_many int, why text )
-RETURNS SETOF BOOLEAN AS $$
-BEGIN
-    PERFORM _add('todo', COALESCE(how_many, 1), COALESCE(why, ''));
-    RETURN;
-END;
-$$ LANGUAGE plpgsql;
-
-CREATE OR REPLACE FUNCTION todo ( why text )
-RETURNS SETOF BOOLEAN AS $$
-BEGIN
-    PERFORM _add('todo', 1, COALESCE(why, ''));
-    RETURN;
-END;
-$$ LANGUAGE plpgsql;
-
-CREATE OR REPLACE FUNCTION todo ( how_many int )
-RETURNS SETOF BOOLEAN AS $$
-BEGIN
-    PERFORM _add('todo', COALESCE(how_many, 1), '');
-    RETURN;
-END;
-$$ LANGUAGE plpgsql;
-
-CREATE OR REPLACE FUNCTION todo_start (text)
-RETURNS SETOF BOOLEAN AS $$
-BEGIN
-    PERFORM _add('todo', -1, COALESCE($1, ''));
-    RETURN;
-END;
-$$ LANGUAGE plpgsql;
-
-CREATE OR REPLACE FUNCTION todo_start ()
-RETURNS SETOF BOOLEAN AS $$
-BEGIN
-    PERFORM _add('todo', -1, '');
-    RETURN;
-END;
-$$ LANGUAGE plpgsql;
-
-CREATE OR REPLACE FUNCTION in_todo ()
-RETURNS BOOLEAN AS $$
-DECLARE
-    todos integer;
-BEGIN
-    todos := _get('todo');
-    RETURN CASE WHEN todos IS NULL THEN FALSE ELSE TRUE END;
-END;
-$$ LANGUAGE plpgsql;
-
-CREATE OR REPLACE FUNCTION todo_end ()
-RETURNS SETOF BOOLEAN AS $$
-DECLARE
-    id integer;
-BEGIN
-    id := _get_latest( 'todo', -1 );
-    IF id IS NULL THEN
-        RAISE EXCEPTION 'todo_end() called without todo_start()';
-    END IF;
-    EXECUTE 'DELETE FROM __tcache__ WHERE id = ' || id;
-    RETURN;
-END;
-$$ LANGUAGE plpgsql;
-
-CREATE OR REPLACE FUNCTION _todo()
-RETURNS TEXT AS $$
-DECLARE
-    todos INT[];
-    note text;
-BEGIN
-    -- Get the latest id and value, because todo() might have been called
-    -- again before the todos ran out for the first call to todo(). This
-    -- allows them to nest.
-    todos := _get_latest('todo');
-    IF todos IS NULL THEN
-        -- No todos.
-        RETURN NULL;
-    END IF;
-    IF todos[2] = 0 THEN
-        -- Todos depleted. Clean up.
-        EXECUTE 'DELETE FROM __tcache__ WHERE id = ' || todos[1];
-        RETURN NULL;
-    END IF;
-    -- Decrement the count of counted todos and return the reason.
-    IF todos[2] <> -1 THEN
-        PERFORM _set(todos[1], todos[2] - 1);
-    END IF;
-    note := _get_note(todos[1]);
-
-    IF todos[2] = 1 THEN
-        -- This was the last todo, so delete the record.
-        EXECUTE 'DELETE FROM __tcache__ WHERE id = ' || todos[1];
-    END IF;
-
-    RETURN note;
-END;
-$$ LANGUAGE plpgsql;
-
-CREATE OR REPLACE FUNCTION skip ( why text, how_many int )
-RETURNS TEXT AS $$
-DECLARE
-    output TEXT[];
-BEGIN
-    output := '{}';
-    FOR i IN 1..how_many LOOP
-        output = array_append(output, ok( TRUE, 'SKIP: ' || COALESCE( why, '') ) );
-    END LOOP;
-    RETURN array_to_string(output, E'\n');
-END;
-$$ LANGUAGE plpgsql;
-
-CREATE OR REPLACE FUNCTION skip ( text )
-RETURNS TEXT AS $$
-    SELECT ok( TRUE, 'SKIP: ' || $1 );
-$$ LANGUAGE sql;
-
-CREATE OR REPLACE FUNCTION skip( int, text )
-RETURNS TEXT AS 'SELECT skip($2, $1)'
-LANGUAGE sql;
-
-CREATE OR REPLACE FUNCTION skip( int )
-RETURNS TEXT AS 'SELECT skip(NULL, $1)'
-LANGUAGE sql;
-
-CREATE OR REPLACE FUNCTION _query( TEXT )
-RETURNS TEXT AS $$
-    SELECT CASE
-        WHEN $1 LIKE '"%' OR $1 !~ '[[:space:]]' THEN 'EXECUTE ' || $1
-        ELSE $1
-    END;
-$$ LANGUAGE SQL;
-
--- throws_ok ( sql, errcode, errmsg, description )
-CREATE OR REPLACE FUNCTION throws_ok ( TEXT, CHAR(5), TEXT, TEXT )
-RETURNS TEXT AS $$
-DECLARE
-    query     TEXT := _query($1);
-    errcode   ALIAS FOR $2;
-    errmsg    ALIAS FOR $3;
-    desctext  ALIAS FOR $4;
-    descr     TEXT;
-BEGIN
-    descr := COALESCE(
-          desctext,
-          'threw ' || errcode || ': ' || errmsg,
-          'threw ' || errcode,
-          'threw ' || errmsg,
-          'threw an exception'
-    );
-    EXECUTE query;
-    RETURN ok( FALSE, descr ) || E'\n' || diag(
-           '      caught: no exception' ||
-        E'\n      wanted: ' || COALESCE( errcode, 'an exception' )
-    );
-EXCEPTION WHEN OTHERS THEN
-    IF (errcode IS NULL OR SQLSTATE = errcode)
-        AND ( errmsg IS NULL OR SQLERRM = errmsg)
-    THEN
-        -- The expected errcode and/or message was thrown.
-        RETURN ok( TRUE, descr );
-    ELSE
-        -- This was not the expected errcode or errmsg.
-        RETURN ok( FALSE, descr ) || E'\n' || diag(
-               '      caught: ' || SQLSTATE || ': ' || SQLERRM ||
-            E'\n      wanted: ' || COALESCE( errcode, 'an exception' ) ||
-            COALESCE( ': ' || errmsg, '')
-        );
-    END IF;
-END;
-$$ LANGUAGE plpgsql;
-
--- throws_ok ( sql, errcode, errmsg )
--- throws_ok ( sql, errmsg, description )
-CREATE OR REPLACE FUNCTION throws_ok ( TEXT, TEXT, TEXT )
-RETURNS TEXT AS $$
-BEGIN
-    IF octet_length($2) = 5 THEN
-        RETURN throws_ok( $1, $2::char(5), $3, NULL );
-    ELSE
-        RETURN throws_ok( $1, NULL, $2, $3 );
-    END IF;
-END;
-$$ LANGUAGE plpgsql;
-
--- throws_ok ( query, errcode )
--- throws_ok ( query, errmsg )
-CREATE OR REPLACE FUNCTION throws_ok ( TEXT, TEXT )
-RETURNS TEXT AS $$
-BEGIN
-    IF octet_length($2) = 5 THEN
-        RETURN throws_ok( $1, $2::char(5), NULL, NULL );
-    ELSE
-        RETURN throws_ok( $1, NULL, $2, NULL );
-    END IF;
-END;
-$$ LANGUAGE plpgsql;
-
--- throws_ok ( sql )
-CREATE OR REPLACE FUNCTION throws_ok ( TEXT )
-RETURNS TEXT AS $$
-    SELECT throws_ok( $1, NULL, NULL, NULL );
-$$ LANGUAGE SQL;
-
--- Magically cast integer error codes.
--- throws_ok ( sql, errcode, errmsg, description )
-CREATE OR REPLACE FUNCTION throws_ok ( TEXT, int4, TEXT, TEXT )
-RETURNS TEXT AS $$
-    SELECT throws_ok( $1, $2::char(5), $3, $4 );
-$$ LANGUAGE SQL;
-
--- throws_ok ( sql, errcode, errmsg )
-CREATE OR REPLACE FUNCTION throws_ok ( TEXT, int4, TEXT )
-RETURNS TEXT AS $$
-    SELECT throws_ok( $1, $2::char(5), $3, NULL );
-$$ LANGUAGE SQL;
-
--- throws_ok ( sql, errcode )
-CREATE OR REPLACE FUNCTION throws_ok ( TEXT, int4 )
-RETURNS TEXT AS $$
-    SELECT throws_ok( $1, $2::char(5), NULL, NULL );
-$$ LANGUAGE SQL;
-
--- lives_ok( sql, description )
-CREATE OR REPLACE FUNCTION lives_ok ( TEXT, TEXT )
-RETURNS TEXT AS $$
-DECLARE
-    code  TEXT := _query($1);
-    descr ALIAS FOR $2;
-BEGIN
-    EXECUTE code;
-    RETURN ok( TRUE, descr );
-EXCEPTION WHEN OTHERS THEN
-    -- There should have been no exception.
-    RETURN ok( FALSE, descr ) || E'\n' || diag(
-           '        died: ' || SQLSTATE || ': ' || SQLERRM
-    );
-END;
-$$ LANGUAGE plpgsql;
-
--- lives_ok( sql )
-CREATE OR REPLACE FUNCTION lives_ok ( TEXT )
-RETURNS TEXT AS $$
-    SELECT lives_ok( $1, NULL );
-$$ LANGUAGE SQL;
-
--- performs_ok ( sql, milliseconds, description )
-CREATE OR REPLACE FUNCTION performs_ok ( TEXT, NUMERIC, TEXT )
-RETURNS TEXT AS $$
-DECLARE
-    query     TEXT := _query($1);
-    max_time  ALIAS FOR $2;
-    descr     ALIAS FOR $3;
-    starts_at TEXT;
-    act_time  NUMERIC;
-BEGIN
-    starts_at := timeofday();
-    EXECUTE query;
-    act_time := extract( millisecond from timeofday()::timestamptz - starts_at::timestamptz);
-    IF act_time < max_time THEN RETURN ok(TRUE, descr); END IF;
-    RETURN ok( FALSE, descr ) || E'\n' || diag(
-           '      runtime: ' || act_time || ' ms' ||
-        E'\n      exceeds: ' || max_time || ' ms'
-    );
-END;
-$$ LANGUAGE plpgsql;
-
--- performs_ok ( sql, milliseconds )
-CREATE OR REPLACE FUNCTION performs_ok ( TEXT, NUMERIC )
-RETURNS TEXT AS $$
-    SELECT performs_ok(
-        $1, $2, 'Should run in less than ' || $2 || ' ms'
-    );
-$$ LANGUAGE sql;
-
-CREATE OR REPLACE FUNCTION _rexists ( CHAR, NAME, NAME )
-RETURNS BOOLEAN AS $$
-    SELECT EXISTS(
-        SELECT true
-          FROM pg_catalog.pg_namespace n
-          JOIN pg_catalog.pg_class c ON n.oid = c.relnamespace
-         WHERE c.relkind = $1
-           AND n.nspname = $2
-           AND c.relname = $3
-    );
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION _rexists ( CHAR, NAME )
-RETURNS BOOLEAN AS $$
-    SELECT EXISTS(
-        SELECT true
-          FROM pg_catalog.pg_class c
-         WHERE c.relkind = $1
-           AND pg_catalog.pg_table_is_visible(c.oid)
-           AND c.relname = $2
-    );
-$$ LANGUAGE SQL;
-
--- has_table( schema, table, description )
-CREATE OR REPLACE FUNCTION has_table ( NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT ok( _rexists( 'r', $1, $2 ), $3 );
-$$ LANGUAGE SQL;
-
--- has_table( table, description )
-CREATE OR REPLACE FUNCTION has_table ( NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT ok( _rexists( 'r', $1 ), $2 );
-$$ LANGUAGE SQL;
-
--- has_table( table )
-CREATE OR REPLACE FUNCTION has_table ( NAME )
-RETURNS TEXT AS $$
-    SELECT has_table( $1, 'Table ' || quote_ident($1) || ' should exist' );
-$$ LANGUAGE SQL;
-
--- hasnt_table( schema, table, description )
-CREATE OR REPLACE FUNCTION hasnt_table ( NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT ok( NOT _rexists( 'r', $1, $2 ), $3 );
-$$ LANGUAGE SQL;
-
--- hasnt_table( table, description )
-CREATE OR REPLACE FUNCTION hasnt_table ( NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT ok( NOT _rexists( 'r', $1 ), $2 );
-$$ LANGUAGE SQL;
-
--- hasnt_table( table )
-CREATE OR REPLACE FUNCTION hasnt_table ( NAME )
-RETURNS TEXT AS $$
-    SELECT hasnt_table( $1, 'Table ' || quote_ident($1) || ' should not exist' );
-$$ LANGUAGE SQL;
-
--- has_view( schema, view, description )
-CREATE OR REPLACE FUNCTION has_view ( NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT ok( _rexists( 'v', $1, $2 ), $3 );
-$$ LANGUAGE SQL;
-
--- has_view( view, description )
-CREATE OR REPLACE FUNCTION has_view ( NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT ok( _rexists( 'v', $1 ), $2 );
-$$ LANGUAGE SQL;
-
--- has_view( view )
-CREATE OR REPLACE FUNCTION has_view ( NAME )
-RETURNS TEXT AS $$
-    SELECT has_view( $1, 'View ' || quote_ident($1) || ' should exist' );
-$$ LANGUAGE SQL;
-
--- hasnt_view( schema, view, description )
-CREATE OR REPLACE FUNCTION hasnt_view ( NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT ok( NOT _rexists( 'v', $1, $2 ), $3 );
-$$ LANGUAGE SQL;
-
--- hasnt_view( view, description )
-CREATE OR REPLACE FUNCTION hasnt_view ( NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT ok( NOT _rexists( 'v', $1 ), $2 );
-$$ LANGUAGE SQL;
-
--- hasnt_view( view )
-CREATE OR REPLACE FUNCTION hasnt_view ( NAME )
-RETURNS TEXT AS $$
-    SELECT hasnt_view( $1, 'View ' || quote_ident($1) || ' should not exist' );
-$$ LANGUAGE SQL;
-
--- has_sequence( schema, sequence, description )
-CREATE OR REPLACE FUNCTION has_sequence ( NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT ok( _rexists( 'S', $1, $2 ), $3 );
-$$ LANGUAGE SQL;
-
--- has_sequence( sequence, description )
-CREATE OR REPLACE FUNCTION has_sequence ( NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT ok( _rexists( 'S', $1 ), $2 );
-$$ LANGUAGE SQL;
-
--- has_sequence( sequence )
-CREATE OR REPLACE FUNCTION has_sequence ( NAME )
-RETURNS TEXT AS $$
-    SELECT has_sequence( $1, 'Sequence ' || quote_ident($1) || ' should exist' );
-$$ LANGUAGE SQL;
-
--- hasnt_sequence( schema, sequence, description )
-CREATE OR REPLACE FUNCTION hasnt_sequence ( NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT ok( NOT _rexists( 'S', $1, $2 ), $3 );
-$$ LANGUAGE SQL;
-
--- hasnt_sequence( sequence, description )
-CREATE OR REPLACE FUNCTION hasnt_sequence ( NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT ok( NOT _rexists( 'S', $1 ), $2 );
-$$ LANGUAGE SQL;
-
--- hasnt_sequence( sequence )
-CREATE OR REPLACE FUNCTION hasnt_sequence ( NAME )
-RETURNS TEXT AS $$
-    SELECT hasnt_sequence( $1, 'Sequence ' || quote_ident($1) || ' should not exist' );
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION _cexists ( NAME, NAME, NAME )
-RETURNS BOOLEAN AS $$
-    SELECT EXISTS(
-        SELECT true
-          FROM pg_catalog.pg_namespace n
-          JOIN pg_catalog.pg_class c ON n.oid = c.relnamespace
-          JOIN pg_catalog.pg_attribute a ON c.oid = a.attrelid
-         WHERE n.nspname = $1
-           AND c.relname = $2
-           AND a.attnum > 0
-           AND NOT a.attisdropped
-           AND a.attname = $3
-    );
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION _cexists ( NAME, NAME )
-RETURNS BOOLEAN AS $$
-    SELECT EXISTS(
-        SELECT true
-          FROM pg_catalog.pg_class c
-          JOIN pg_catalog.pg_attribute a ON c.oid = a.attrelid
-         WHERE c.relname = $1
-           AND pg_catalog.pg_table_is_visible(c.oid)
-           AND a.attnum > 0
-           AND NOT a.attisdropped
-           AND a.attname = $2
-    );
-$$ LANGUAGE SQL;
-
--- has_column( schema, table, column, description )
-CREATE OR REPLACE FUNCTION has_column ( NAME, NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT ok( _cexists( $1, $2, $3 ), $4 );
-$$ LANGUAGE SQL;
-
--- has_column( table, column, description )
-CREATE OR REPLACE FUNCTION has_column ( NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT ok( _cexists( $1, $2 ), $3 );
-$$ LANGUAGE SQL;
-
--- has_column( table, column )
-CREATE OR REPLACE FUNCTION has_column ( NAME, NAME )
-RETURNS TEXT AS $$
-    SELECT has_column( $1, $2, 'Column ' || quote_ident($1) || '.' || quote_ident($2) || ' should exist' );
-$$ LANGUAGE SQL;
-
--- hasnt_column( schema, table, column, description )
-CREATE OR REPLACE FUNCTION hasnt_column ( NAME, NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT ok( NOT _cexists( $1, $2, $3 ), $4 );
-$$ LANGUAGE SQL;
-
--- hasnt_column( table, column, description )
-CREATE OR REPLACE FUNCTION hasnt_column ( NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT ok( NOT _cexists( $1, $2 ), $3 );
-$$ LANGUAGE SQL;
-
--- hasnt_column( table, column )
-CREATE OR REPLACE FUNCTION hasnt_column ( NAME, NAME )
-RETURNS TEXT AS $$
-    SELECT hasnt_column( $1, $2, 'Column ' || quote_ident($1) || '.' || quote_ident($2) || ' should not exist' );
-$$ LANGUAGE SQL;
-
--- _col_is_null( schema, table, column, desc, null )
-CREATE OR REPLACE FUNCTION _col_is_null ( NAME, NAME, NAME, TEXT, bool )
-RETURNS TEXT AS $$
-BEGIN
-    IF NOT _cexists( $1, $2, $3 ) THEN
-        RETURN fail( $4 ) || E'\n'
-            || diag ('    Column ' || quote_ident($1) || '.' || quote_ident($2) || '.' || quote_ident($3) || ' does not exist' );
-    END IF;
-    RETURN ok(
-        EXISTS(
-            SELECT true
-              FROM pg_catalog.pg_namespace n
-              JOIN pg_catalog.pg_class c ON n.oid = c.relnamespace
-              JOIN pg_catalog.pg_attribute a ON c.oid = a.attrelid
-             WHERE n.nspname = $1
-               AND c.relname = $2
-               AND a.attnum  > 0
-               AND NOT a.attisdropped
-               AND a.attname    = $3
-               AND a.attnotnull = $5
-        ), $4
-    );
-END;
-$$ LANGUAGE plpgsql;
-
--- _col_is_null( table, column, desc, null )
-CREATE OR REPLACE FUNCTION _col_is_null ( NAME, NAME, TEXT, bool )
-RETURNS TEXT AS $$
-BEGIN
-    IF NOT _cexists( $1, $2 ) THEN
-        RETURN fail( $3 ) || E'\n'
-            || diag ('    Column ' || quote_ident($1) || '.' || quote_ident($2) || ' does not exist' );
-    END IF;
-    RETURN ok(
-        EXISTS(
-            SELECT true
-              FROM pg_catalog.pg_class c
-              JOIN pg_catalog.pg_attribute a ON c.oid = a.attrelid
-             WHERE pg_catalog.pg_table_is_visible(c.oid)
-               AND c.relname = $1
-               AND a.attnum > 0
-               AND NOT a.attisdropped
-               AND a.attname    = $2
-               AND a.attnotnull = $4
-        ), $3
-    );
-END;
-$$ LANGUAGE plpgsql;
-
--- col_not_null( schema, table, column, description )
-CREATE OR REPLACE FUNCTION col_not_null ( NAME, NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT _col_is_null( $1, $2, $3, $4, true );
-$$ LANGUAGE SQL;
-
--- col_not_null( table, column, description )
-CREATE OR REPLACE FUNCTION col_not_null ( NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT _col_is_null( $1, $2, $3, true );
-$$ LANGUAGE SQL;
-
--- col_not_null( table, column )
-CREATE OR REPLACE FUNCTION col_not_null ( NAME, NAME )
-RETURNS TEXT AS $$
-    SELECT _col_is_null( $1, $2, 'Column ' || quote_ident($1) || '.' || quote_ident($2) || ' should be NOT NULL', true );
-$$ LANGUAGE SQL;
-
--- col_is_null( schema, table, column, description )
-CREATE OR REPLACE FUNCTION col_is_null ( NAME, NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT _col_is_null( $1, $2, $3, $4, false );
-$$ LANGUAGE SQL;
-
--- col_is_null( schema, table, column )
-CREATE OR REPLACE FUNCTION col_is_null ( NAME, NAME, NAME )
-RETURNS TEXT AS $$
-    SELECT _col_is_null( $1, $2, $3, false );
-$$ LANGUAGE SQL;
-
--- col_is_null( table, column )
-CREATE OR REPLACE FUNCTION col_is_null ( NAME, NAME )
-RETURNS TEXT AS $$
-    SELECT _col_is_null( $1, $2, 'Column ' || quote_ident($1) || '.' || quote_ident($2) || ' should allow NULL', false );
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION display_type ( OID, INTEGER )
-RETURNS TEXT AS $$
-    SELECT COALESCE(substring(
-        pg_catalog.format_type($1, $2),
-        '(("(?!")([^"]|"")+"|[^.]+)([(][^)]+[)])?)$'
-    ), '')
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION display_type ( NAME, OID, INTEGER )
-RETURNS TEXT AS $$
-    SELECT CASE WHEN $1 IS NULL THEN '' ELSE quote_ident($1) || '.' END
-        || display_type($2, $3)
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION _get_col_type ( NAME, NAME, NAME )
-RETURNS TEXT AS $$
-    SELECT display_type(a.atttypid, a.atttypmod)
-      FROM pg_catalog.pg_namespace n
-      JOIN pg_catalog.pg_class c     ON n.oid = c.relnamespace
-      JOIN pg_catalog.pg_attribute a ON c.oid = a.attrelid
-     WHERE n.nspname = $1
-       AND c.relname = $2
-       AND a.attname = $3
-       AND attnum    > 0
-       AND NOT a.attisdropped
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION _get_col_type ( NAME, NAME )
-RETURNS TEXT AS $$
-    SELECT display_type(a.atttypid, a.atttypmod)
-      FROM pg_catalog.pg_attribute a
-      JOIN pg_catalog.pg_class c ON  a.attrelid = c.oid
-     WHERE pg_table_is_visible(c.oid)
-       AND c.relname = $1
-       AND a.attname = $2
-       AND attnum    > 0
-       AND NOT a.attisdropped
-       AND pg_type_is_visible(a.atttypid)
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION _get_col_ns_type ( NAME, NAME, NAME )
-RETURNS TEXT AS $$
-    SELECT display_type(tn.nspname, a.atttypid, a.atttypmod)
-      FROM pg_catalog.pg_namespace n
-      JOIN pg_catalog.pg_class c      ON n.oid = c.relnamespace
-      JOIN pg_catalog.pg_attribute a  ON c.oid = a.attrelid
-      JOIN pg_catalog.pg_type t       ON a.atttypid = t.oid
-      JOIN pg_catalog.pg_namespace tn ON t.typnamespace = tn.oid
-     WHERE n.nspname = $1
-       AND c.relname = $2
-       AND a.attname = $3
-       AND attnum    > 0
-       AND NOT a.attisdropped
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION _quote_ident_like(TEXT, TEXT)
-RETURNS TEXT AS $$
-DECLARE
-    have    TEXT;
-    pcision TEXT;
-BEGIN
-    -- Just return it if rhs isn't quoted.
-    IF $2 !~ '"' THEN RETURN $1; END IF;
-
-    -- If it's quoted ident without precision, return it quoted.
-    IF $2 ~ '"$' THEN RETURN quote_ident($1); END IF;
-
-    pcision := substring($1 FROM '[(][^")]+[)]$');
-
-    -- Just quote it if thre is no precision.
-    if pcision IS NULL THEN RETURN quote_ident($1); END IF;
-
-    -- Quote the non-precision part and concatenate with precision.
-    RETURN quote_ident(substring($1 FOR char_length($1) - char_length(pcision)))
-        || pcision;
-END;
-$$ LANGUAGE plpgsql;
-
--- col_type_is( schema, table, column, schema, type, description )
-CREATE OR REPLACE FUNCTION col_type_is ( NAME, NAME, NAME, NAME, TEXT, TEXT )
-RETURNS TEXT AS $$
-DECLARE
-    have_type TEXT := _get_col_ns_type($1, $2, $3);
-    want_type TEXT;
-BEGIN
-    IF have_type IS NULL THEN
-        RETURN fail( $6 ) || E'\n' || diag (
-            '   Column ' || COALESCE(quote_ident($1) || '.', '')
-            || quote_ident($2) || '.' || quote_ident($3) || ' does not exist'
-        );
-    END IF;
-
-    want_type := quote_ident($4) || '.' || _quote_ident_like($5, have_type);
-    IF have_type = want_type THEN
-        -- We're good to go.
-        RETURN ok( true, $6 );
-    END IF;
-
-    -- Wrong data type. tell 'em what we really got.
-    RETURN ok( false, $6 ) || E'\n' || diag(
-           '        have: ' || have_type ||
-        E'\n        want: ' || want_type
-    );
-END;
-$$ LANGUAGE plpgsql;
-
--- col_type_is( schema, table, column, schema, type )
-CREATE OR REPLACE FUNCTION col_type_is ( NAME, NAME, NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT col_type_is( $1, $2, $3, $4, $5, 'Column ' || quote_ident($1) || '.' || quote_ident($2)
-        || '.' || quote_ident($3) || ' should be type ' || quote_ident($4) || '.' || $5);
-$$ LANGUAGE SQL;
-
--- col_type_is( schema, table, column, type, description )
-CREATE OR REPLACE FUNCTION col_type_is ( NAME, NAME, NAME, TEXT, TEXT )
-RETURNS TEXT AS $$
-DECLARE
-    have_type TEXT;
-    want_type TEXT;
-BEGIN
-    -- Get the data type.
-    IF $1 IS NULL THEN
-        have_type := _get_col_type($2, $3);
-    ELSE
-        have_type := _get_col_type($1, $2, $3);
-    END IF;
-
-    IF have_type IS NULL THEN
-        RETURN fail( $5 ) || E'\n' || diag (
-            '   Column ' || COALESCE(quote_ident($1) || '.', '')
-            || quote_ident($2) || '.' || quote_ident($3) || ' does not exist'
-        );
-    END IF;
-
-    want_type := _quote_ident_like($4, have_type);
-    IF have_type = want_type THEN
-        -- We're good to go.
-        RETURN ok( true, $5 );
-    END IF;
-
-    -- Wrong data type. tell 'em what we really got.
-    RETURN ok( false, $5 ) || E'\n' || diag(
-           '        have: ' || have_type ||
-        E'\n        want: ' || want_type
-    );
-END;
-$$ LANGUAGE plpgsql;
-
--- col_type_is( schema, table, column, type )
-CREATE OR REPLACE FUNCTION col_type_is ( NAME, NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT col_type_is( $1, $2, $3, $4, 'Column ' || quote_ident($1) || '.' || quote_ident($2) || '.' || quote_ident($3) || ' should be type ' || $4 );
-$$ LANGUAGE SQL;
-
--- col_type_is( table, column, type, description )
-CREATE OR REPLACE FUNCTION col_type_is ( NAME, NAME, TEXT, TEXT )
-RETURNS TEXT AS $$
-    SELECT col_type_is( NULL, $1, $2, $3, $4 );
-$$ LANGUAGE SQL;
-
--- col_type_is( table, column, type )
-CREATE OR REPLACE FUNCTION col_type_is ( NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT col_type_is( $1, $2, $3, 'Column ' || quote_ident($1) || '.' || quote_ident($2) || ' should be type ' || $3 );
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION _has_def ( NAME, NAME, NAME )
-RETURNS boolean AS $$
-    SELECT a.atthasdef
-      FROM pg_catalog.pg_namespace n
-      JOIN pg_catalog.pg_class c ON n.oid = c.relnamespace
-      JOIN pg_catalog.pg_attribute a ON c.oid = a.attrelid
-     WHERE n.nspname = $1
-       AND c.relname = $2
-       AND a.attnum > 0
-       AND NOT a.attisdropped
-       AND a.attname = $3
-$$ LANGUAGE sql;
-
-CREATE OR REPLACE FUNCTION _has_def ( NAME, NAME )
-RETURNS boolean AS $$
-    SELECT a.atthasdef
-      FROM pg_catalog.pg_class c
-      JOIN pg_catalog.pg_attribute a ON c.oid = a.attrelid
-     WHERE c.relname = $1
-       AND a.attnum > 0
-       AND NOT a.attisdropped
-       AND a.attname = $2
-$$ LANGUAGE sql;
-
--- col_has_default( schema, table, column, description )
-CREATE OR REPLACE FUNCTION col_has_default ( NAME, NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-BEGIN
-    IF NOT _cexists( $1, $2, $3 ) THEN
-        RETURN fail( $4 ) || E'\n'
-            || diag ('    Column ' || quote_ident($1) || '.' || quote_ident($2) || '.' || quote_ident($3) || ' does not exist' );
-    END IF;
-    RETURN ok( _has_def( $1, $2, $3 ), $4 );
-END
-$$ LANGUAGE plpgsql;
-
--- col_has_default( table, column, description )
-CREATE OR REPLACE FUNCTION col_has_default ( NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-BEGIN
-    IF NOT _cexists( $1, $2 ) THEN
-        RETURN fail( $3 ) || E'\n'
-            || diag ('    Column ' || quote_ident($1) || '.' || quote_ident($2) || ' does not exist' );
-    END IF;
-    RETURN ok( _has_def( $1, $2 ), $3 );
-END;
-$$ LANGUAGE plpgsql;
-
--- col_has_default( table, column )
-CREATE OR REPLACE FUNCTION col_has_default ( NAME, NAME )
-RETURNS TEXT AS $$
-    SELECT col_has_default( $1, $2, 'Column ' || quote_ident($1) || '.' || quote_ident($2) || ' should have a default' );
-$$ LANGUAGE SQL;
-
--- col_hasnt_default( schema, table, column, description )
-CREATE OR REPLACE FUNCTION col_hasnt_default ( NAME, NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-BEGIN
-    IF NOT _cexists( $1, $2, $3 ) THEN
-        RETURN fail( $4 ) || E'\n'
-            || diag ('    Column ' || quote_ident($1) || '.' || quote_ident($2) || '.' || quote_ident($3) || ' does not exist' );
-    END IF;
-    RETURN ok( NOT _has_def( $1, $2, $3 ), $4 );
-END;
-$$ LANGUAGE plpgsql;
-
--- col_hasnt_default( table, column, description )
-CREATE OR REPLACE FUNCTION col_hasnt_default ( NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-BEGIN
-    IF NOT _cexists( $1, $2 ) THEN
-        RETURN fail( $3 ) || E'\n'
-            || diag ('    Column ' || quote_ident($1) || '.' || quote_ident($2) || ' does not exist' );
-    END IF;
-    RETURN ok( NOT _has_def( $1, $2 ), $3 );
-END;
-$$ LANGUAGE plpgsql;
-
--- col_hasnt_default( table, column )
-CREATE OR REPLACE FUNCTION col_hasnt_default ( NAME, NAME )
-RETURNS TEXT AS $$
-    SELECT col_hasnt_default( $1, $2, 'Column ' || quote_ident($1) || '.' || quote_ident($2) || ' should not have a default' );
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION _def_is( TEXT, TEXT, anyelement, TEXT )
-RETURNS TEXT AS $$
-DECLARE
-    thing text;
-BEGIN
-    IF $1 ~ '^[^'']+[(]' THEN
-        -- It's a functional default.
-        RETURN is( $1, $3, $4 );
-    END IF;
-
-    EXECUTE 'SELECT is('
-             || COALESCE($1, 'NULL' || '::' || $2) || '::' || $2 || ', '
-             || COALESCE(quote_literal($3), 'NULL') || '::' || $2 || ', '
-             || COALESCE(quote_literal($4), 'NULL')
-    || ')' INTO thing;
-    RETURN thing;
-END;
-$$ LANGUAGE plpgsql;
-
--- _cdi( schema, table, column, default, description )
-CREATE OR REPLACE FUNCTION _cdi ( NAME, NAME, NAME, anyelement, TEXT )
-RETURNS TEXT AS $$
-BEGIN
-    IF NOT _cexists( $1, $2, $3 ) THEN
-        RETURN fail( $5 ) || E'\n'
-            || diag ('    Column ' || quote_ident($1) || '.' || quote_ident($2) || '.' || quote_ident($3) || ' does not exist' );
-    END IF;
-
-    IF NOT _has_def( $1, $2, $3 ) THEN
-        RETURN fail( $5 ) || E'\n'
-            || diag ('    Column ' || quote_ident($1) || '.' || quote_ident($2) || '.' || quote_ident($3) || ' has no default' );
-    END IF;
-
-    RETURN _def_is(
-        pg_catalog.pg_get_expr(d.adbin, d.adrelid),
-        display_type(a.atttypid, a.atttypmod),
-        $4, $5
-    )
-      FROM pg_catalog.pg_namespace n, pg_catalog.pg_class c, pg_catalog.pg_attribute a,
-           pg_catalog.pg_attrdef d
-     WHERE n.oid = c.relnamespace
-       AND c.oid = a.attrelid
-       AND a.atthasdef
-       AND a.attrelid = d.adrelid
-       AND a.attnum = d.adnum
-       AND n.nspname = $1
-       AND c.relname = $2
-       AND a.attnum > 0
-       AND NOT a.attisdropped
-       AND a.attname = $3;
-END;
-$$ LANGUAGE plpgsql;
-
--- _cdi( table, column, default, description )
-CREATE OR REPLACE FUNCTION _cdi ( NAME, NAME, anyelement, TEXT )
-RETURNS TEXT AS $$
-BEGIN
-    IF NOT _cexists( $1, $2 ) THEN
-        RETURN fail( $4 ) || E'\n'
-            || diag ('    Column ' || quote_ident($1) || '.' || quote_ident($2) || ' does not exist' );
-    END IF;
-
-    IF NOT _has_def( $1, $2 ) THEN
-        RETURN fail( $4 ) || E'\n'
-            || diag ('    Column ' || quote_ident($1) || '.' || quote_ident($2) || ' has no default' );
-    END IF;
-
-    RETURN _def_is(
-        pg_catalog.pg_get_expr(d.adbin, d.adrelid),
-        display_type(a.atttypid, a.atttypmod),
-        $3, $4
-    )
-      FROM pg_catalog.pg_class c, pg_catalog.pg_attribute a, pg_catalog.pg_attrdef d
-     WHERE c.oid = a.attrelid
-       AND pg_table_is_visible(c.oid)
-       AND a.atthasdef
-       AND a.attrelid = d.adrelid
-       AND a.attnum = d.adnum
-       AND c.relname = $1
-       AND a.attnum > 0
-       AND NOT a.attisdropped
-       AND a.attname = $2;
-END;
-$$ LANGUAGE plpgsql;
-
--- _cdi( table, column, default )
-CREATE OR REPLACE FUNCTION _cdi ( NAME, NAME, anyelement )
-RETURNS TEXT AS $$
-    SELECT col_default_is(
-        $1, $2, $3,
-        'Column ' || quote_ident($1) || '.' || quote_ident($2) || ' should default to '
-        || COALESCE( quote_literal($3), 'NULL')
-    );
-$$ LANGUAGE sql;
-
--- col_default_is( schema, table, column, default, description )
-CREATE OR REPLACE FUNCTION col_default_is ( NAME, NAME, NAME, anyelement, TEXT )
-RETURNS TEXT AS $$
-    SELECT _cdi( $1, $2, $3, $4, $5 );
-$$ LANGUAGE sql;
-
--- col_default_is( schema, table, column, default, description )
-CREATE OR REPLACE FUNCTION col_default_is ( NAME, NAME, NAME, TEXT, TEXT )
-RETURNS TEXT AS $$
-    SELECT _cdi( $1, $2, $3, $4, $5 );
-$$ LANGUAGE sql;
-
--- col_default_is( table, column, default, description )
-CREATE OR REPLACE FUNCTION col_default_is ( NAME, NAME, anyelement, TEXT )
-RETURNS TEXT AS $$
-    SELECT _cdi( $1, $2, $3, $4 );
-$$ LANGUAGE sql;
-
--- col_default_is( table, column, default, description )
-CREATE OR REPLACE FUNCTION col_default_is ( NAME, NAME, TEXT, TEXT )
-RETURNS TEXT AS $$
-    SELECT _cdi( $1, $2, $3, $4 );
-$$ LANGUAGE sql;
-
--- col_default_is( table, column, default )
-CREATE OR REPLACE FUNCTION col_default_is ( NAME, NAME, anyelement )
-RETURNS TEXT AS $$
-    SELECT _cdi( $1, $2, $3 );
-$$ LANGUAGE sql;
-
--- col_default_is( table, column, default::text )
-CREATE OR REPLACE FUNCTION col_default_is ( NAME, NAME, text )
-RETURNS TEXT AS $$
-    SELECT _cdi( $1, $2, $3 );
-$$ LANGUAGE sql;
-
--- _hasc( schema, table, constraint_type )
-CREATE OR REPLACE FUNCTION _hasc ( NAME, NAME, CHAR )
-RETURNS BOOLEAN AS $$
-    SELECT EXISTS(
-            SELECT true
-              FROM pg_catalog.pg_namespace n
-              JOIN pg_catalog.pg_class c      ON c.relnamespace = n.oid
-              JOIN pg_catalog.pg_constraint x ON c.oid = x.conrelid
-             WHERE c.relhaspkey = true
-               AND n.nspname = $1
-               AND c.relname = $2
-               AND x.contype = $3
-    );
-$$ LANGUAGE sql;
-
--- _hasc( table, constraint_type )
-CREATE OR REPLACE FUNCTION _hasc ( NAME, CHAR )
-RETURNS BOOLEAN AS $$
-    SELECT EXISTS(
-            SELECT true
-              FROM pg_catalog.pg_class c
-              JOIN pg_catalog.pg_constraint x ON c.oid = x.conrelid
-             WHERE c.relhaspkey = true
-               AND pg_table_is_visible(c.oid)
-               AND c.relname = $1
-               AND x.contype = $2
-    );
-$$ LANGUAGE sql;
-
--- has_pk( schema, table, description )
-CREATE OR REPLACE FUNCTION has_pk ( NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT ok( _hasc( $1, $2, 'p' ), $3 );
-$$ LANGUAGE sql;
-
--- has_pk( table, description )
-CREATE OR REPLACE FUNCTION has_pk ( NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT ok( _hasc( $1, 'p' ), $2 );
-$$ LANGUAGE sql;
-
--- has_pk( table )
-CREATE OR REPLACE FUNCTION has_pk ( NAME )
-RETURNS TEXT AS $$
-    SELECT has_pk( $1, 'Table ' || quote_ident($1) || ' should have a primary key' );
-$$ LANGUAGE sql;
-
--- hasnt_pk( schema, table, description )
-CREATE OR REPLACE FUNCTION hasnt_pk ( NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT ok( NOT _hasc( $1, $2, 'p' ), $3 );
-$$ LANGUAGE sql;
-
--- hasnt_pk( table, description )
-CREATE OR REPLACE FUNCTION hasnt_pk ( NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT ok( NOT _hasc( $1, 'p' ), $2 );
-$$ LANGUAGE sql;
-
--- hasnt_pk( table )
-CREATE OR REPLACE FUNCTION hasnt_pk ( NAME )
-RETURNS TEXT AS $$
-    SELECT hasnt_pk( $1, 'Table ' || quote_ident($1) || ' should not have a primary key' );
-$$ LANGUAGE sql;
-
-CREATE OR REPLACE FUNCTION _ident_array_to_string( name[], text )
-RETURNS text AS $$
-    SELECT array_to_string(ARRAY(
-        SELECT quote_ident($1[i])
-          FROM generate_series(1, array_upper($1, 1)) s(i)
-         ORDER BY i
-    ), $2);
-$$ LANGUAGE SQL immutable;
-
--- Borrowed from newsysviews: http://pgfoundry.org/projects/newsysviews/
-CREATE OR REPLACE FUNCTION _pg_sv_column_array( OID, SMALLINT[] )
-RETURNS NAME[] AS $$
-    SELECT ARRAY(
-        SELECT a.attname
-          FROM pg_catalog.pg_attribute a
-          JOIN generate_series(1, array_upper($2, 1)) s(i) ON a.attnum = $2[i]
-         WHERE attrelid = $1
-         ORDER BY i
-    )
-$$ LANGUAGE SQL stable;
-
--- Borrowed from newsysviews: http://pgfoundry.org/projects/newsysviews/
-CREATE OR REPLACE FUNCTION _pg_sv_table_accessible( OID, OID )
-RETURNS BOOLEAN AS $$
-    SELECT CASE WHEN has_schema_privilege($1, 'USAGE') THEN (
-                  has_table_privilege($2, 'SELECT')
-               OR has_table_privilege($2, 'INSERT')
-               or has_table_privilege($2, 'UPDATE')
-               OR has_table_privilege($2, 'DELETE')
-               OR has_table_privilege($2, 'RULE')
-               OR has_table_privilege($2, 'REFERENCES')
-               OR has_table_privilege($2, 'TRIGGER')
-           ) ELSE FALSE
-    END;
-$$ LANGUAGE SQL immutable strict;
-
--- Borrowed from newsysviews: http://pgfoundry.org/projects/newsysviews/
-CREATE OR REPLACE VIEW pg_all_foreign_keys
-AS
-  SELECT n1.nspname                                   AS fk_schema_name,
-         c1.relname                                   AS fk_table_name,
-         k1.conname                                   AS fk_constraint_name,
-         c1.oid                                       AS fk_table_oid,
-         _pg_sv_column_array(k1.conrelid,k1.conkey)   AS fk_columns,
-         n2.nspname                                   AS pk_schema_name,
-         c2.relname                                   AS pk_table_name,
-         k2.conname                                   AS pk_constraint_name,
-         c2.oid                                       AS pk_table_oid,
-         ci.relname                                   AS pk_index_name,
-         _pg_sv_column_array(k1.confrelid,k1.confkey) AS pk_columns,
-         CASE k1.confmatchtype WHEN 'f' THEN 'FULL'
-                               WHEN 'p' THEN 'PARTIAL'
-                               WHEN 'u' THEN 'NONE'
-                               else null
-         END AS match_type,
-         CASE k1.confdeltype WHEN 'a' THEN 'NO ACTION'
-                             WHEN 'c' THEN 'CASCADE'
-                             WHEN 'd' THEN 'SET DEFAULT'
-                             WHEN 'n' THEN 'SET NULL'
-                             WHEN 'r' THEN 'RESTRICT'
-                             else null
-         END AS on_delete,
-         CASE k1.confupdtype WHEN 'a' THEN 'NO ACTION'
-                             WHEN 'c' THEN 'CASCADE'
-                             WHEN 'd' THEN 'SET DEFAULT'
-                             WHEN 'n' THEN 'SET NULL'
-                             WHEN 'r' THEN 'RESTRICT'
-                             ELSE NULL
-         END AS on_update,
-         k1.condeferrable AS is_deferrable,
-         k1.condeferred   AS is_deferred
-    FROM pg_catalog.pg_constraint k1
-    JOIN pg_catalog.pg_namespace n1 ON (n1.oid = k1.connamespace)
-    JOIN pg_catalog.pg_class c1     ON (c1.oid = k1.conrelid)
-    JOIN pg_catalog.pg_class c2     ON (c2.oid = k1.confrelid)
-    JOIN pg_catalog.pg_namespace n2 ON (n2.oid = c2.relnamespace)
-    JOIN pg_catalog.pg_depend d     ON (
-                 d.classid = 'pg_constraint'::regclass
-             AND d.objid = k1.oid
-             AND d.objsubid = 0
-             AND d.deptype = 'n'
-             AND d.refclassid = 'pg_class'::regclass
-             AND d.refobjsubid=0
-         )
-    JOIN pg_catalog.pg_class ci ON (ci.oid = d.refobjid AND ci.relkind = 'i')
-    LEFT JOIN pg_depend d2      ON (
-                 d2.classid = 'pg_class'::regclass
-             AND d2.objid = ci.oid
-             AND d2.objsubid = 0
-             AND d2.deptype = 'i'
-             AND d2.refclassid = 'pg_constraint'::regclass
-             AND d2.refobjsubid = 0
-         )
-    LEFT JOIN pg_catalog.pg_constraint k2 ON (
-                 k2.oid = d2.refobjid
-             AND k2.contype IN ('p', 'u')
-         )
-   WHERE k1.conrelid != 0
-     AND k1.confrelid != 0
-     AND k1.contype = 'f'
-     AND _pg_sv_table_accessible(n1.oid, c1.oid);
-
--- _keys( schema, table, constraint_type )
-CREATE OR REPLACE FUNCTION _keys ( NAME, NAME, CHAR )
-RETURNS SETOF NAME[] AS $$
-    SELECT _pg_sv_column_array(x.conrelid,x.conkey)
-      FROM pg_catalog.pg_namespace n
-      JOIN pg_catalog.pg_class c       ON n.oid = c.relnamespace
-      JOIN pg_catalog.pg_constraint x  ON c.oid = x.conrelid
-     WHERE n.nspname = $1
-       AND c.relname = $2
-       AND x.contype = $3
-$$ LANGUAGE sql;
-
--- _keys( table, constraint_type )
-CREATE OR REPLACE FUNCTION _keys ( NAME, CHAR )
-RETURNS SETOF NAME[] AS $$
-    SELECT _pg_sv_column_array(x.conrelid,x.conkey)
-      FROM pg_catalog.pg_class c
-      JOIN pg_catalog.pg_constraint x  ON c.oid = x.conrelid
-       AND c.relname = $1
-       AND x.contype = $2
-$$ LANGUAGE sql;
-
--- _ckeys( schema, table, constraint_type )
-CREATE OR REPLACE FUNCTION _ckeys ( NAME, NAME, CHAR )
-RETURNS NAME[] AS $$
-    SELECT * FROM _keys($1, $2, $3) LIMIT 1;
-$$ LANGUAGE sql;
-
--- _ckeys( table, constraint_type )
-CREATE OR REPLACE FUNCTION _ckeys ( NAME, CHAR )
-RETURNS NAME[] AS $$
-    SELECT * FROM _keys($1, $2) LIMIT 1;
-$$ LANGUAGE sql;
-
--- col_is_pk( schema, table, column, description )
-CREATE OR REPLACE FUNCTION col_is_pk ( NAME, NAME, NAME[], TEXT )
-RETURNS TEXT AS $$
-    SELECT is( _ckeys( $1, $2, 'p' ), $3, $4 );
-$$ LANGUAGE sql;
-
--- col_is_pk( table, column, description )
-CREATE OR REPLACE FUNCTION col_is_pk ( NAME, NAME[], TEXT )
-RETURNS TEXT AS $$
-    SELECT is( _ckeys( $1, 'p' ), $2, $3 );
-$$ LANGUAGE sql;
-
--- col_is_pk( table, column[] )
-CREATE OR REPLACE FUNCTION col_is_pk ( NAME, NAME[] )
-RETURNS TEXT AS $$
-    SELECT col_is_pk( $1, $2, 'Columns ' || quote_ident($1) || '(' || _ident_array_to_string($2, ', ') || ') should be a primary key' );
-$$ LANGUAGE sql;
-
--- col_is_pk( schema, table, column, description )
-CREATE OR REPLACE FUNCTION col_is_pk ( NAME, NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT col_is_pk( $1, $2, ARRAY[$3], $4 );
-$$ LANGUAGE sql;
-
--- col_is_pk( table, column, description )
-CREATE OR REPLACE FUNCTION col_is_pk ( NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT col_is_pk( $1, ARRAY[$2], $3 );
-$$ LANGUAGE sql;
-
--- col_is_pk( table, column )
-CREATE OR REPLACE FUNCTION col_is_pk ( NAME, NAME )
-RETURNS TEXT AS $$
-    SELECT col_is_pk( $1, $2, 'Column ' || quote_ident($1) || '(' || quote_ident($2) || ') should be a primary key' );
-$$ LANGUAGE sql;
-
--- col_isnt_pk( schema, table, column, description )
-CREATE OR REPLACE FUNCTION col_isnt_pk ( NAME, NAME, NAME[], TEXT )
-RETURNS TEXT AS $$
-    SELECT isnt( _ckeys( $1, $2, 'p' ), $3, $4 );
-$$ LANGUAGE sql;
-
--- col_isnt_pk( table, column, description )
-CREATE OR REPLACE FUNCTION col_isnt_pk ( NAME, NAME[], TEXT )
-RETURNS TEXT AS $$
-    SELECT isnt( _ckeys( $1, 'p' ), $2, $3 );
-$$ LANGUAGE sql;
-
--- col_isnt_pk( table, column[] )
-CREATE OR REPLACE FUNCTION col_isnt_pk ( NAME, NAME[] )
-RETURNS TEXT AS $$
-    SELECT col_isnt_pk( $1, $2, 'Columns ' || quote_ident($1) || '(' || _ident_array_to_string($2, ', ') || ') should not be a primary key' );
-$$ LANGUAGE sql;
-
--- col_isnt_pk( schema, table, column, description )
-CREATE OR REPLACE FUNCTION col_isnt_pk ( NAME, NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT col_isnt_pk( $1, $2, ARRAY[$3], $4 );
-$$ LANGUAGE sql;
-
--- col_isnt_pk( table, column, description )
-CREATE OR REPLACE FUNCTION col_isnt_pk ( NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT col_isnt_pk( $1, ARRAY[$2], $3 );
-$$ LANGUAGE sql;
-
--- col_isnt_pk( table, column )
-CREATE OR REPLACE FUNCTION col_isnt_pk ( NAME, NAME )
-RETURNS TEXT AS $$
-    SELECT col_isnt_pk( $1, $2, 'Column ' || quote_ident($1) || '(' || quote_ident($2) || ') should not be a primary key' );
-$$ LANGUAGE sql;
-
--- has_fk( schema, table, description )
-CREATE OR REPLACE FUNCTION has_fk ( NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT ok( _hasc( $1, $2, 'f' ), $3 );
-$$ LANGUAGE sql;
-
--- has_fk( table, description )
-CREATE OR REPLACE FUNCTION has_fk ( NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT ok( _hasc( $1, 'f' ), $2 );
-$$ LANGUAGE sql;
-
--- has_fk( table )
-CREATE OR REPLACE FUNCTION has_fk ( NAME )
-RETURNS TEXT AS $$
-    SELECT has_fk( $1, 'Table ' || quote_ident($1) || ' should have a foreign key constraint' );
-$$ LANGUAGE sql;
-
--- hasnt_fk( schema, table, description )
-CREATE OR REPLACE FUNCTION hasnt_fk ( NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT ok( NOT _hasc( $1, $2, 'f' ), $3 );
-$$ LANGUAGE sql;
-
--- hasnt_fk( table, description )
-CREATE OR REPLACE FUNCTION hasnt_fk ( NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT ok( NOT _hasc( $1, 'f' ), $2 );
-$$ LANGUAGE sql;
-
--- hasnt_fk( table )
-CREATE OR REPLACE FUNCTION hasnt_fk ( NAME )
-RETURNS TEXT AS $$
-    SELECT hasnt_fk( $1, 'Table ' || quote_ident($1) || ' should not have a foreign key constraint' );
-$$ LANGUAGE sql;
-
-CREATE OR REPLACE FUNCTION _fkexists ( NAME, NAME, NAME[] )
-RETURNS BOOLEAN AS $$
-    SELECT EXISTS(
-        SELECT TRUE
-           FROM pg_all_foreign_keys
-          WHERE fk_schema_name    = $1
-            AND quote_ident(fk_table_name)     = quote_ident($2)
-            AND fk_columns = $3
-    );
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION _fkexists ( NAME, NAME[] )
-RETURNS BOOLEAN AS $$
-    SELECT EXISTS(
-        SELECT TRUE
-           FROM pg_all_foreign_keys
-          WHERE quote_ident(fk_table_name)     = quote_ident($1)
-            AND fk_columns = $2
-    );
-$$ LANGUAGE SQL;
-
--- col_is_fk( schema, table, column, description )
-CREATE OR REPLACE FUNCTION col_is_fk ( NAME, NAME, NAME[], TEXT )
-RETURNS TEXT AS $$
-DECLARE
-    names text[];
-BEGIN
-    IF _fkexists($1, $2, $3) THEN
-        RETURN pass( $4 );
-    END IF;
-
-    -- Try to show the columns.
-    SELECT ARRAY(
-        SELECT _ident_array_to_string(fk_columns, ', ')
-          FROM pg_all_foreign_keys
-         WHERE fk_schema_name = $1
-           AND fk_table_name  = $2
-         ORDER BY fk_columns
-    ) INTO names;
-
-    IF names[1] IS NOT NULL THEN
-        RETURN fail($4) || E'\n' || diag(
-            '    Table ' || quote_ident($1) || '.' || quote_ident($2) || E' has foreign key constraints on these columns:\n        '
-            ||  array_to_string( names, E'\n        ' )
-        );
-    END IF;
-
-    -- No FKs in this table.
-    RETURN fail($4) || E'\n' || diag(
-        '    Table ' || quote_ident($1) || '.' || quote_ident($2) || ' has no foreign key columns'
-    );
-END;
-$$ LANGUAGE plpgsql;
-
--- col_is_fk( table, column, description )
-CREATE OR REPLACE FUNCTION col_is_fk ( NAME, NAME[], TEXT )
-RETURNS TEXT AS $$
-DECLARE
-    names text[];
-BEGIN
-    IF _fkexists($1, $2) THEN
-        RETURN pass( $3 );
-    END IF;
-
-    -- Try to show the columns.
-    SELECT ARRAY(
-        SELECT _ident_array_to_string(fk_columns, ', ')
-          FROM pg_all_foreign_keys
-         WHERE fk_table_name  = $1
-         ORDER BY fk_columns
-    ) INTO names;
-
-    IF NAMES[1] IS NOT NULL THEN
-        RETURN fail($3) || E'\n' || diag(
-            '    Table ' || quote_ident($1) || E' has foreign key constraints on these columns:\n        '
-            || array_to_string( names, E'\n        ' )
-        );
-    END IF;
-
-    -- No FKs in this table.
-    RETURN fail($3) || E'\n' || diag(
-        '    Table ' || quote_ident($1) || ' has no foreign key columns'
-    );
-END;
-$$ LANGUAGE plpgsql;
-
--- col_is_fk( table, column[] )
-CREATE OR REPLACE FUNCTION col_is_fk ( NAME, NAME[] )
-RETURNS TEXT AS $$
-    SELECT col_is_fk( $1, $2, 'Columns ' || quote_ident($1) || '(' || _ident_array_to_string($2, ', ') || ') should be a foreign key' );
-$$ LANGUAGE sql;
-
--- col_is_fk( schema, table, column, description )
-CREATE OR REPLACE FUNCTION col_is_fk ( NAME, NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT col_is_fk( $1, $2, ARRAY[$3], $4 );
-$$ LANGUAGE sql;
-
--- col_is_fk( table, column, description )
-CREATE OR REPLACE FUNCTION col_is_fk ( NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT col_is_fk( $1, ARRAY[$2], $3 );
-$$ LANGUAGE sql;
-
--- col_is_fk( table, column )
-CREATE OR REPLACE FUNCTION col_is_fk ( NAME, NAME )
-RETURNS TEXT AS $$
-    SELECT col_is_fk( $1, $2, 'Column ' || quote_ident($1) || '(' || quote_ident($2) || ') should be a foreign key' );
-$$ LANGUAGE sql;
-
--- col_isnt_fk( schema, table, column, description )
-CREATE OR REPLACE FUNCTION col_isnt_fk ( NAME, NAME, NAME[], TEXT )
-RETURNS TEXT AS $$
-    SELECT ok( NOT _fkexists( $1, $2, $3 ), $4 );
-$$ LANGUAGE SQL;
-
--- col_isnt_fk( table, column, description )
-CREATE OR REPLACE FUNCTION col_isnt_fk ( NAME, NAME[], TEXT )
-RETURNS TEXT AS $$
-    SELECT ok( NOT _fkexists( $1, $2 ), $3 );
-$$ LANGUAGE SQL;
-
--- col_isnt_fk( table, column[] )
-CREATE OR REPLACE FUNCTION col_isnt_fk ( NAME, NAME[] )
-RETURNS TEXT AS $$
-    SELECT col_isnt_fk( $1, $2, 'Columns ' || quote_ident($1) || '(' || _ident_array_to_string($2, ', ') || ') should not be a foreign key' );
-$$ LANGUAGE sql;
-
--- col_isnt_fk( schema, table, column, description )
-CREATE OR REPLACE FUNCTION col_isnt_fk ( NAME, NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT col_isnt_fk( $1, $2, ARRAY[$3], $4 );
-$$ LANGUAGE sql;
-
--- col_isnt_fk( table, column, description )
-CREATE OR REPLACE FUNCTION col_isnt_fk ( NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT col_isnt_fk( $1, ARRAY[$2], $3 );
-$$ LANGUAGE sql;
-
--- col_isnt_fk( table, column )
-CREATE OR REPLACE FUNCTION col_isnt_fk ( NAME, NAME )
-RETURNS TEXT AS $$
-    SELECT col_isnt_fk( $1, $2, 'Column ' || quote_ident($1) || '(' || quote_ident($2) || ') should not be a foreign key' );
-$$ LANGUAGE sql;
-
--- has_unique( schema, table, description )
-CREATE OR REPLACE FUNCTION has_unique ( TEXT, TEXT, TEXT )
-RETURNS TEXT AS $$
-    SELECT ok( _hasc( $1, $2, 'u' ), $3 );
-$$ LANGUAGE sql;
-
--- has_unique( table, description )
-CREATE OR REPLACE FUNCTION has_unique ( TEXT, TEXT )
-RETURNS TEXT AS $$
-    SELECT ok( _hasc( $1, 'u' ), $2 );
-$$ LANGUAGE sql;
-
--- has_unique( table )
-CREATE OR REPLACE FUNCTION has_unique ( TEXT )
-RETURNS TEXT AS $$
-    SELECT has_unique( $1, 'Table ' || quote_ident($1) || ' should have a unique constraint' );
-$$ LANGUAGE sql;
-
-CREATE OR REPLACE FUNCTION _constraint ( NAME, NAME, CHAR, NAME[], TEXT, TEXT )
-RETURNS TEXT AS $$
-DECLARE
-    akey NAME[];
-    keys TEXT[] := '{}';
-    have TEXT;
-BEGIN
-    FOR akey IN SELECT * FROM _keys($1, $2, $3) LOOP
-        IF akey = $4 THEN RETURN pass($5); END IF;
-        keys = keys || akey::text;
-    END LOOP;
-    IF array_upper(keys, 0) = 1 THEN
-        have := 'No ' || $6 || ' constriants';
-    ELSE
-        have := array_to_string(keys, E'\n              ');
-    END IF;
-
-    RETURN fail($5) || E'\n' || diag(
-             '        have: ' || have
-       || E'\n        want: ' || CASE WHEN $4 IS NULL THEN 'NULL' ELSE $4::text END
-    );
-END;
-$$ LANGUAGE plpgsql;
-
-CREATE OR REPLACE FUNCTION _constraint ( NAME, CHAR, NAME[], TEXT, TEXT )
-RETURNS TEXT AS $$
-DECLARE
-    akey NAME[];
-    keys TEXT[] := '{}';
-    have TEXT;
-BEGIN
-    FOR akey IN SELECT * FROM _keys($1, $2) LOOP
-        IF akey = $3 THEN RETURN pass($4); END IF;
-        keys = keys || akey::text;
-    END LOOP;
-    IF array_upper(keys, 0) = 1 THEN
-        have := 'No ' || $5 || ' constriants';
-    ELSE
-        have := array_to_string(keys, E'\n              ');
-    END IF;
-
-    RETURN fail($4) || E'\n' || diag(
-             '        have: ' || have
-       || E'\n        want: ' || CASE WHEN $3 IS NULL THEN 'NULL' ELSE $3::text END
-    );
-END;
-$$ LANGUAGE plpgsql;
-
--- col_is_unique( schema, table, column, description )
-CREATE OR REPLACE FUNCTION col_is_unique ( NAME, NAME, NAME[], TEXT )
-RETURNS TEXT AS $$
-    SELECT _constraint( $1, $2, 'u', $3, $4, 'unique' );
-$$ LANGUAGE sql;
-
--- col_is_unique( table, column, description )
-CREATE OR REPLACE FUNCTION col_is_unique ( NAME, NAME[], TEXT )
-RETURNS TEXT AS $$
-    SELECT _constraint( $1, 'u', $2, $3, 'unique' );
-$$ LANGUAGE sql;
-
--- col_is_unique( table, column[] )
-CREATE OR REPLACE FUNCTION col_is_unique ( NAME, NAME[] )
-RETURNS TEXT AS $$
-    SELECT col_is_unique( $1, $2, 'Columns ' || quote_ident($1) || '(' || _ident_array_to_string($2, ', ') || ') should have a unique constraint' );
-$$ LANGUAGE sql;
-
--- col_is_unique( schema, table, column, description )
-CREATE OR REPLACE FUNCTION col_is_unique ( NAME, NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT col_is_unique( $1, $2, ARRAY[$3], $4 );
-$$ LANGUAGE sql;
-
--- col_is_unique( table, column, description )
-CREATE OR REPLACE FUNCTION col_is_unique ( NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT col_is_unique( $1, ARRAY[$2], $3 );
-$$ LANGUAGE sql;
-
--- col_is_unique( table, column )
-CREATE OR REPLACE FUNCTION col_is_unique ( NAME, NAME )
-RETURNS TEXT AS $$
-    SELECT col_is_unique( $1, $2, 'Column ' || quote_ident($1) || '(' || quote_ident($2) || ') should have a unique constraint' );
-$$ LANGUAGE sql;
-
--- has_check( schema, table, description )
-CREATE OR REPLACE FUNCTION has_check ( NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT ok( _hasc( $1, $2, 'c' ), $3 );
-$$ LANGUAGE sql;
-
--- has_check( table, description )
-CREATE OR REPLACE FUNCTION has_check ( NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT ok( _hasc( $1, 'c' ), $2 );
-$$ LANGUAGE sql;
-
--- has_check( table )
-CREATE OR REPLACE FUNCTION has_check ( NAME )
-RETURNS TEXT AS $$
-    SELECT has_check( $1, 'Table ' || quote_ident($1) || ' should have a check constraint' );
-$$ LANGUAGE sql;
-
--- col_has_check( schema, table, column, description )
-CREATE OR REPLACE FUNCTION col_has_check ( NAME, NAME, NAME[], TEXT )
-RETURNS TEXT AS $$
-    SELECT _constraint( $1, $2, 'c', $3, $4, 'check' );
-$$ LANGUAGE sql;
-
--- col_has_check( table, column, description )
-CREATE OR REPLACE FUNCTION col_has_check ( NAME, NAME[], TEXT )
-RETURNS TEXT AS $$
-    SELECT _constraint( $1, 'c', $2, $3, 'check' );
-$$ LANGUAGE sql;
-
--- col_has_check( table, column[] )
-CREATE OR REPLACE FUNCTION col_has_check ( NAME, NAME[] )
-RETURNS TEXT AS $$
-    SELECT col_has_check( $1, $2, 'Columns ' || quote_ident($1) || '(' || _ident_array_to_string($2, ', ') || ') should have a check constraint' );
-$$ LANGUAGE sql;
-
--- col_has_check( schema, table, column, description )
-CREATE OR REPLACE FUNCTION col_has_check ( NAME, NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT col_has_check( $1, $2, ARRAY[$3], $4 );
-$$ LANGUAGE sql;
-
--- col_has_check( table, column, description )
-CREATE OR REPLACE FUNCTION col_has_check ( NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT col_has_check( $1, ARRAY[$2], $3 );
-$$ LANGUAGE sql;
-
--- col_has_check( table, column )
-CREATE OR REPLACE FUNCTION col_has_check ( NAME, NAME )
-RETURNS TEXT AS $$
-    SELECT col_has_check( $1, $2, 'Column ' || quote_ident($1) || '(' || quote_ident($2) || ') should have a check constraint' );
-$$ LANGUAGE sql;
-
--- fk_ok( fk_schema, fk_table, fk_column[], pk_schema, pk_table, pk_column[], description )
-CREATE OR REPLACE FUNCTION fk_ok ( NAME, NAME, NAME[], NAME, NAME, NAME[], TEXT )
-RETURNS TEXT AS $$
-DECLARE
-    sch  name;
-    tab  name;
-    cols name[];
-BEGIN
-    SELECT pk_schema_name, pk_table_name, pk_columns
-      FROM pg_all_foreign_keys
-      WHERE fk_schema_name = $1
-        AND fk_table_name  = $2
-        AND fk_columns     = $3
-      INTO sch, tab, cols;
-
-    RETURN is(
-        -- have
-        quote_ident($1) || '.' || quote_ident($2) || '(' || _ident_array_to_string( $3, ', ' )
-        || ') REFERENCES ' || COALESCE ( sch || '.' || tab || '(' || _ident_array_to_string( cols, ', ' ) || ')', 'NOTHING' ),
-        -- want
-        quote_ident($1) || '.' || quote_ident($2) || '(' || _ident_array_to_string( $3, ', ' )
-        || ') REFERENCES ' ||
-        $4 || '.' || $5 || '(' || _ident_array_to_string( $6, ', ' ) || ')',
-        $7
-    );
-END;
-$$ LANGUAGE plpgsql;
-
--- fk_ok( fk_table, fk_column[], pk_table, pk_column[], description )
-CREATE OR REPLACE FUNCTION fk_ok ( NAME, NAME[], NAME, NAME[], TEXT )
-RETURNS TEXT AS $$
-DECLARE
-    tab  name;
-    cols name[];
-BEGIN
-    SELECT pk_table_name, pk_columns
-      FROM pg_all_foreign_keys
-      WHERE fk_table_name = $1
-        AND fk_columns    = $2
-      INTO tab, cols;
-
-    RETURN is(
-        -- have
-        $1 || '(' || _ident_array_to_string( $2, ', ' )
-        || ') REFERENCES ' || COALESCE( tab || '(' || _ident_array_to_string( cols, ', ' ) || ')', 'NOTHING'),
-        -- want
-        $1 || '(' || _ident_array_to_string( $2, ', ' )
-        || ') REFERENCES ' ||
-        $3 || '(' || _ident_array_to_string( $4, ', ' ) || ')',
-        $5
-    );
-END;
-$$ LANGUAGE plpgsql;
-
--- fk_ok( fk_schema, fk_table, fk_column[], fk_schema, pk_table, pk_column[] )
-CREATE OR REPLACE FUNCTION fk_ok ( NAME, NAME, NAME[], NAME, NAME, NAME[] )
-RETURNS TEXT AS $$
-    SELECT fk_ok( $1, $2, $3, $4, $5, $6,
-        quote_ident($1) || '.' || quote_ident($2) || '(' || _ident_array_to_string( $3, ', ' )
-        || ') should reference ' ||
-        $4 || '.' || $5 || '(' || _ident_array_to_string( $6, ', ' ) || ')'
-    );
-$$ LANGUAGE sql;
-
--- fk_ok( fk_table, fk_column[], pk_table, pk_column[] )
-CREATE OR REPLACE FUNCTION fk_ok ( NAME, NAME[], NAME, NAME[] )
-RETURNS TEXT AS $$
-    SELECT fk_ok( $1, $2, $3, $4,
-        $1 || '(' || _ident_array_to_string( $2, ', ' )
-        || ') should reference ' ||
-        $3 || '(' || _ident_array_to_string( $4, ', ' ) || ')'
-    );
-$$ LANGUAGE sql;
-
--- fk_ok( fk_schema, fk_table, fk_column, pk_schema, pk_table, pk_column, description )
-CREATE OR REPLACE FUNCTION fk_ok ( NAME, NAME, NAME, NAME, NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT fk_ok( $1, $2, ARRAY[$3], $4, $5, ARRAY[$6], $7 );
-$$ LANGUAGE sql;
-
--- fk_ok( fk_schema, fk_table, fk_column, pk_schema, pk_table, pk_column )
-CREATE OR REPLACE FUNCTION fk_ok ( NAME, NAME, NAME, NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT fk_ok( $1, $2, ARRAY[$3], $4, $5, ARRAY[$6] );
-$$ LANGUAGE sql;
-
--- fk_ok( fk_table, fk_column, pk_table, pk_column, description )
-CREATE OR REPLACE FUNCTION fk_ok ( NAME, NAME, NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT fk_ok( $1, ARRAY[$2], $3, ARRAY[$4], $5 );
-$$ LANGUAGE sql;
-
--- fk_ok( fk_table, fk_column, pk_table, pk_column )
-CREATE OR REPLACE FUNCTION fk_ok ( NAME, NAME, NAME, NAME )
-RETURNS TEXT AS $$
-    SELECT fk_ok( $1, ARRAY[$2], $3, ARRAY[$4] );
-$$ LANGUAGE sql;
-
-CREATE OR REPLACE VIEW tap_funky
- AS SELECT p.oid         AS oid,
-           n.nspname     AS schema,
-           p.proname     AS name,
-           array_to_string(p.proargtypes::regtype[], ',') AS args,
-           CASE p.proretset WHEN TRUE THEN 'setof ' ELSE '' END
-             || p.prorettype::regtype AS returns,
-           p.prolang     AS langoid,
-           p.proisstrict AS is_strict,
-           p.proisagg    AS is_agg,
-           p.prosecdef   AS is_definer,
-           p.proretset   AS returns_set,
-           p.provolatile::char AS volatility,
-           pg_catalog.pg_function_is_visible(p.oid) AS is_visible
-      FROM pg_catalog.pg_proc p
-      JOIN pg_catalog.pg_namespace n ON p.pronamespace = n.oid
-;
-
-CREATE OR REPLACE FUNCTION _got_func ( NAME, NAME, NAME[] )
-RETURNS BOOLEAN AS $$
-    SELECT EXISTS(
-        SELECT TRUE
-          FROM tap_funky
-         WHERE schema = $1
-           AND name   = $2
-           AND args   = array_to_string($3, ',')
-    );
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION _got_func ( NAME, NAME )
-RETURNS BOOLEAN AS $$
-    SELECT EXISTS( SELECT TRUE FROM tap_funky WHERE schema = $1 AND name = $2 );
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION _got_func ( NAME, NAME[] )
-RETURNS BOOLEAN AS $$
-    SELECT EXISTS(
-        SELECT TRUE
-          FROM tap_funky
-         WHERE name = $1
-           AND args = array_to_string($2, ',')
-           AND is_visible
-    );
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION _got_func ( NAME )
-RETURNS BOOLEAN AS $$
-    SELECT EXISTS( SELECT TRUE FROM tap_funky WHERE name = $1 AND is_visible);
-$$ LANGUAGE SQL;
-
--- has_function( schema, function, args[], description )
-CREATE OR REPLACE FUNCTION has_function ( NAME, NAME, NAME[], TEXT )
-RETURNS TEXT AS $$
-    SELECT ok( _got_func($1, $2, $3), $4 );
-$$ LANGUAGE SQL;
-
--- has_function( schema, function, args[] )
-CREATE OR REPLACE FUNCTION has_function( NAME, NAME, NAME[] )
-RETURNS TEXT AS $$
-    SELECT ok(
-        _got_func($1, $2, $3),
-        'Function ' || quote_ident($1) || '.' || quote_ident($2) || '(' ||
-        array_to_string($3, ', ') || ') should exist'
-    );
-$$ LANGUAGE sql;
-
--- has_function( schema, function, description )
-CREATE OR REPLACE FUNCTION has_function ( NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT ok( _got_func($1, $2), $3 );
-$$ LANGUAGE SQL;
-
--- has_function( schema, function )
-CREATE OR REPLACE FUNCTION has_function( NAME, NAME )
-RETURNS TEXT AS $$
-    SELECT ok(
-        _got_func($1, $2),
-        'Function ' || quote_ident($1) || '.' || quote_ident($2) || '() should exist'
-    );
-$$ LANGUAGE sql;
-
--- has_function( function, args[], description )
-CREATE OR REPLACE FUNCTION has_function ( NAME, NAME[], TEXT )
-RETURNS TEXT AS $$
-    SELECT ok( _got_func($1, $2), $3 );
-$$ LANGUAGE SQL;
-
--- has_function( function, args[] )
-CREATE OR REPLACE FUNCTION has_function( NAME, NAME[] )
-RETURNS TEXT AS $$
-    SELECT ok(
-        _got_func($1, $2),
-        'Function ' || quote_ident($1) || '(' ||
-        array_to_string($2, ', ') || ') should exist'
-    );
-$$ LANGUAGE sql;
-
--- has_function( function, description )
-CREATE OR REPLACE FUNCTION has_function( NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT ok( _got_func($1), $2 );
-$$ LANGUAGE sql;
-
--- has_function( function )
-CREATE OR REPLACE FUNCTION has_function( NAME )
-RETURNS TEXT AS $$
-    SELECT ok( _got_func($1), 'Function ' || quote_ident($1) || '() should exist' );
-$$ LANGUAGE sql;
-
--- hasnt_function( schema, function, args[], description )
-CREATE OR REPLACE FUNCTION hasnt_function ( NAME, NAME, NAME[], TEXT )
-RETURNS TEXT AS $$
-    SELECT ok( NOT _got_func($1, $2, $3), $4 );
-$$ LANGUAGE SQL;
-
--- hasnt_function( schema, function, args[] )
-CREATE OR REPLACE FUNCTION hasnt_function( NAME, NAME, NAME[] )
-RETURNS TEXT AS $$
-    SELECT ok(
-        NOT _got_func($1, $2, $3),
-        'Function ' || quote_ident($1) || '.' || quote_ident($2) || '(' ||
-        array_to_string($3, ', ') || ') should not exist'
-    );
-$$ LANGUAGE sql;
-
--- hasnt_function( schema, function, description )
-CREATE OR REPLACE FUNCTION hasnt_function ( NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT ok( NOT _got_func($1, $2), $3 );
-$$ LANGUAGE SQL;
-
--- hasnt_function( schema, function )
-CREATE OR REPLACE FUNCTION hasnt_function( NAME, NAME )
-RETURNS TEXT AS $$
-    SELECT ok(
-        NOT _got_func($1, $2),
-        'Function ' || quote_ident($1) || '.' || quote_ident($2) || '() should not exist'
-    );
-$$ LANGUAGE sql;
-
--- hasnt_function( function, args[], description )
-CREATE OR REPLACE FUNCTION hasnt_function ( NAME, NAME[], TEXT )
-RETURNS TEXT AS $$
-    SELECT ok( NOT _got_func($1, $2), $3 );
-$$ LANGUAGE SQL;
-
--- hasnt_function( function, args[] )
-CREATE OR REPLACE FUNCTION hasnt_function( NAME, NAME[] )
-RETURNS TEXT AS $$
-    SELECT ok(
-        NOT _got_func($1, $2),
-        'Function ' || quote_ident($1) || '(' ||
-        array_to_string($2, ', ') || ') should not exist'
-    );
-$$ LANGUAGE sql;
-
--- hasnt_function( function, description )
-CREATE OR REPLACE FUNCTION hasnt_function( NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT ok( NOT _got_func($1), $2 );
-$$ LANGUAGE sql;
-
--- hasnt_function( function )
-CREATE OR REPLACE FUNCTION hasnt_function( NAME )
-RETURNS TEXT AS $$
-    SELECT ok( NOT _got_func($1), 'Function ' || quote_ident($1) || '() should not exist' );
-$$ LANGUAGE sql;
-
-CREATE OR REPLACE FUNCTION _pg_sv_type_array( OID[] )
-RETURNS NAME[] AS $$
-    SELECT ARRAY(
-        SELECT t.typname
-          FROM pg_catalog.pg_type t
-          JOIN generate_series(1, array_upper($1, 1)) s(i) ON t.oid = $1[i]
-         ORDER BY i
-    )
-$$ LANGUAGE SQL stable;
-
--- can( schema, functions[], description )
-CREATE OR REPLACE FUNCTION can ( NAME, NAME[], TEXT )
-RETURNS TEXT AS $$
-DECLARE
-    missing text[];
-BEGIN
-    SELECT ARRAY(
-        SELECT quote_ident($2[i])
-          FROM generate_series(1, array_upper($2, 1)) s(i)
-          LEFT JOIN tap_funky ON name = $2[i] AND schema = $1
-         WHERE oid IS NULL
-         GROUP BY $2[i], s.i
-         ORDER BY MIN(s.i)
-    ) INTO missing;
-    IF missing[1] IS NULL THEN
-        RETURN ok( true, $3 );
-    END IF;
-    RETURN ok( false, $3 ) || E'\n' || diag(
-        '    ' || quote_ident($1) || '.' ||
-        array_to_string( missing, E'() missing\n    ' || quote_ident($1) || '.') ||
-        '() missing'
-    );
-END;
-$$ LANGUAGE plpgsql;
-
--- can( schema, functions[] )
-CREATE OR REPLACE FUNCTION can ( NAME, NAME[] )
-RETURNS TEXT AS $$
-    SELECT can( $1, $2, 'Schema ' || quote_ident($1) || ' can' );
-$$ LANGUAGE sql;
-
--- can( functions[], description )
-CREATE OR REPLACE FUNCTION can ( NAME[], TEXT )
-RETURNS TEXT AS $$
-DECLARE
-    missing text[];
-BEGIN
-    SELECT ARRAY(
-        SELECT quote_ident($1[i])
-          FROM generate_series(1, array_upper($1, 1)) s(i)
-          LEFT JOIN pg_catalog.pg_proc p
-            ON $1[i] = p.proname
-           AND pg_catalog.pg_function_is_visible(p.oid)
-         WHERE p.oid IS NULL
-         ORDER BY s.i
-    ) INTO missing;
-    IF missing[1] IS NULL THEN
-        RETURN ok( true, $2 );
-    END IF;
-    RETURN ok( false, $2 ) || E'\n' || diag(
-        '    ' ||
-        array_to_string( missing, E'() missing\n    ') ||
-        '() missing'
-    );
-END;
-$$ LANGUAGE plpgsql;
-
--- can( functions[] )
-CREATE OR REPLACE FUNCTION can ( NAME[] )
-RETURNS TEXT AS $$
-    SELECT can( $1, 'Schema ' || _ident_array_to_string(current_schemas(true), ' or ') || ' can' );
-$$ LANGUAGE sql;
-
-CREATE OR REPLACE FUNCTION _ikeys( NAME, NAME, NAME)
-RETURNS NAME[] AS $$
-    SELECT ARRAY(
-        SELECT a.attname
-          FROM pg_catalog.pg_index x
-          JOIN pg_catalog.pg_class ct    ON ct.oid = x.indrelid
-          JOIN pg_catalog.pg_class ci    ON ci.oid = x.indexrelid
-          JOIN pg_catalog.pg_namespace n ON n.oid = ct.relnamespace
-          JOIN pg_catalog.pg_attribute a ON ct.oid = a.attrelid
-          JOIN generate_series(0, current_setting('max_index_keys')::int - 1) s(i)
-            ON a.attnum = x.indkey[s.i]
-         WHERE ct.relname = $2
-           AND ci.relname = $3
-           AND n.nspname  = $1
-         ORDER BY s.i
-    );
-$$ LANGUAGE sql;
-
-CREATE OR REPLACE FUNCTION _ikeys( NAME, NAME)
-RETURNS NAME[] AS $$
-    SELECT ARRAY(
-        SELECT a.attname
-          FROM pg_catalog.pg_index x
-          JOIN pg_catalog.pg_class ct    ON ct.oid = x.indrelid
-          JOIN pg_catalog.pg_class ci    ON ci.oid = x.indexrelid
-          JOIN pg_catalog.pg_attribute a ON ct.oid = a.attrelid
-          JOIN generate_series(0, current_setting('max_index_keys')::int - 1) s(i)
-            ON a.attnum = x.indkey[s.i]
-         WHERE ct.relname = $1
-           AND ci.relname = $2
-           AND pg_catalog.pg_table_is_visible(ct.oid)
-         ORDER BY s.i
-    );
-$$ LANGUAGE sql;
-
-CREATE OR REPLACE FUNCTION _have_index( NAME, NAME, NAME)
-RETURNS BOOLEAN AS $$
-    SELECT EXISTS (
-    SELECT TRUE
-      FROM pg_catalog.pg_index x
-      JOIN pg_catalog.pg_class ct    ON ct.oid = x.indrelid
-      JOIN pg_catalog.pg_class ci    ON ci.oid = x.indexrelid
-      JOIN pg_catalog.pg_namespace n ON n.oid = ct.relnamespace
-     WHERE ct.relname = $2
-       AND ci.relname = $3
-       AND n.nspname  = $1
-    );
-$$ LANGUAGE sql;
-
-CREATE OR REPLACE FUNCTION _have_index( NAME, NAME)
-RETURNS BOOLEAN AS $$
-    SELECT EXISTS (
-    SELECT TRUE
-      FROM pg_catalog.pg_index x
-      JOIN pg_catalog.pg_class ct    ON ct.oid = x.indrelid
-      JOIN pg_catalog.pg_class ci    ON ci.oid = x.indexrelid
-     WHERE ct.relname = $1
-       AND ci.relname = $2
-    );
-$$ LANGUAGE sql;
-
-CREATE OR REPLACE FUNCTION _iexpr( NAME, NAME, NAME)
-RETURNS TEXT AS $$
-    SELECT pg_catalog.pg_get_expr( x.indexprs, ct.oid )
-      FROM pg_catalog.pg_index x
-      JOIN pg_catalog.pg_class ct    ON ct.oid = x.indrelid
-      JOIN pg_catalog.pg_class ci    ON ci.oid = x.indexrelid
-      JOIN pg_catalog.pg_namespace n ON n.oid = ct.relnamespace
-     WHERE ct.relname = $2
-       AND ci.relname = $3
-       AND n.nspname  = $1
-$$ LANGUAGE sql;
-
-CREATE OR REPLACE FUNCTION _iexpr( NAME, NAME)
-RETURNS TEXT AS $$
-    SELECT pg_catalog.pg_get_expr( x.indexprs, ct.oid )
-      FROM pg_catalog.pg_index x
-      JOIN pg_catalog.pg_class ct ON ct.oid = x.indrelid
-      JOIN pg_catalog.pg_class ci ON ci.oid = x.indexrelid
-     WHERE ct.relname = $1
-       AND ci.relname = $2
-       AND pg_catalog.pg_table_is_visible(ct.oid)
-$$ LANGUAGE sql;
-
--- has_index( schema, table, index, columns[], description )
-CREATE OR REPLACE FUNCTION has_index ( NAME, NAME, NAME, NAME[], text )
-RETURNS TEXT AS $$
-DECLARE
-     index_cols name[];
-BEGIN
-    index_cols := _ikeys($1, $2, $3 );
-
-    IF index_cols IS NULL OR index_cols = '{}'::name[] THEN
-        RETURN ok( false, $5 ) || E'\n'
-            || diag( 'Index ' || quote_ident($3) || ' ON ' || quote_ident($1) || '.' || quote_ident($2) || ' not found');
-    END IF;
-
-    RETURN is(
-        quote_ident($3) || ' ON ' || quote_ident($1) || '.' || quote_ident($2) || '(' || _ident_array_to_string( index_cols, ', ' ) || ')',
-        quote_ident($3) || ' ON ' || quote_ident($1) || '.' || quote_ident($2) || '(' || _ident_array_to_string( $4, ', ' ) || ')',
-        $5
-    );
-END;
-$$ LANGUAGE plpgsql;
-
--- has_index( schema, table, index, columns[] )
-CREATE OR REPLACE FUNCTION has_index ( NAME, NAME, NAME, NAME[] )
-RETURNS TEXT AS $$
-   SELECT has_index( $1, $2, $3, $4, 'Index ' || quote_ident($3) || ' should exist' );
-$$ LANGUAGE sql;
-
--- has_index( schema, table, index, column/expression, description )
-CREATE OR REPLACE FUNCTION has_index ( NAME, NAME, NAME, NAME, text )
-RETURNS TEXT AS $$
-DECLARE
-    expr text;
-BEGIN
-    IF $4 NOT LIKE '%(%' THEN
-        -- Not a functional index.
-        RETURN has_index( $1, $2, $3, ARRAY[$4], $5 );
-    END IF;
-
-    -- Get the functional expression.
-    expr := _iexpr($1, $2, $3);
-
-    IF expr IS NULL THEN
-        RETURN ok( false, $5 ) || E'\n'
-            || diag( 'Index ' || quote_ident($3) || ' ON ' || quote_ident($1) || '.' || quote_ident($2) || ' not found');
-    END IF;
-
-    RETURN is(
-        quote_ident($3) || ' ON ' || quote_ident($1) || '.' || quote_ident($2) || '(' || expr || ')',
-        quote_ident($3) || ' ON ' || quote_ident($1) || '.' || quote_ident($2) || '(' || $4 || ')',
-        $5
-    );
-END;
-$$ LANGUAGE plpgsql;
-
--- has_index( schema, table, index, columns/expression )
-CREATE OR REPLACE FUNCTION has_index ( NAME, NAME, NAME, NAME )
-RETURNS TEXT AS $$
-   SELECT has_index( $1, $2, $3, $4, 'Index ' || quote_ident($3) || ' should exist' );
-$$ LANGUAGE sql;
-
--- has_index( table, index, columns[], description )
-CREATE OR REPLACE FUNCTION has_index ( NAME, NAME, NAME[], text )
-RETURNS TEXT AS $$
-DECLARE
-     index_cols name[];
-BEGIN
-    index_cols := _ikeys($1, $2 );
-
-    IF index_cols IS NULL OR index_cols = '{}'::name[] THEN
-        RETURN ok( false, $4 ) || E'\n'
-            || diag( 'Index ' || quote_ident($2) || ' ON ' || quote_ident($1) || ' not found');
-    END IF;
-
-    RETURN is(
-        quote_ident($2) || ' ON ' || quote_ident($1) || '(' || _ident_array_to_string( index_cols, ', ' ) || ')',
-        quote_ident($2) || ' ON ' || quote_ident($1) || '(' || _ident_array_to_string( $3, ', ' ) || ')',
-        $4
-    );
-END;
-$$ LANGUAGE plpgsql;
-
--- has_index( table, index, columns[], description )
-CREATE OR REPLACE FUNCTION has_index ( NAME, NAME, NAME[] )
-RETURNS TEXT AS $$
-   SELECT has_index( $1, $2, $3, 'Index ' || quote_ident($2) || ' should exist' );
-$$ LANGUAGE sql;
-
--- _is_schema( schema )
-CREATE OR REPLACE FUNCTION _is_schema( NAME )
-returns boolean AS $$
-    SELECT EXISTS(
-        SELECT true
-          FROM pg_catalog.pg_namespace
-          WHERE nspname = $1
-    );
-$$ LANGUAGE sql;
-
--- has_index( table, index, column/expression, description )
--- has_index( schema, table, index, column/expression )
-CREATE OR REPLACE FUNCTION has_index ( NAME, NAME, NAME, text )
-RETURNS TEXT AS $$
-DECLARE
-    want_expr text;
-    descr text;
-    have_expr text;
-    idx name;
-    tab text;
-BEGIN
-    IF $3 NOT LIKE '%(%' THEN
-        -- Not a functional index.
-        IF _is_schema( $1 ) THEN
-            -- Looking for schema.table index.
-            RETURN ok ( _have_index( $1, $2, $3 ), $4);
-        END IF;
-        -- Looking for particular columns.
-        RETURN has_index( $1, $2, ARRAY[$3], $4 );
-    END IF;
-
-    -- Get the functional expression.
-    IF _is_schema( $1 ) THEN
-        -- Looking for an index within a schema.
-        have_expr := _iexpr($1, $2, $3);
-        want_expr := $4;
-        descr     := 'Index ' || quote_ident($3) || ' should exist';
-        idx       := $3;
-        tab       := quote_ident($1) || '.' || quote_ident($2);
-    ELSE
-        -- Looking for an index without a schema spec.
-        have_expr := _iexpr($1, $2);
-        want_expr := $3;
-        descr     := $4;
-        idx       := $2;
-        tab       := quote_ident($1);
-    END IF;
-
-    IF have_expr IS NULL THEN
-        RETURN ok( false, descr ) || E'\n'
-            || diag( 'Index ' || idx || ' ON ' || tab || ' not found');
-    END IF;
-
-    RETURN is(
-        quote_ident(idx) || ' ON ' || tab || '(' || have_expr || ')',
-        quote_ident(idx) || ' ON ' || tab || '(' || want_expr || ')',
-        descr
-    );
-END;
-$$ LANGUAGE plpgsql;
-
--- has_index( table, index, column/expression )
--- has_index( schema, table, index )
-CREATE OR REPLACE FUNCTION has_index ( NAME, NAME, NAME )
-RETURNS TEXT AS $$
-BEGIN
-   IF _is_schema($1) THEN
-       -- ( schema, table, index )
-       RETURN ok( _have_index( $1, $2, $3 ), 'Index ' || quote_ident($3) || ' should exist' );
-   ELSE
-       -- ( table, index, column/expression )
-       RETURN has_index( $1, $2, $3, 'Index ' || quote_ident($2) || ' should exist' );
-   END IF;
-END;
-$$ LANGUAGE plpgsql;
-
--- has_index( table, index, description )
-CREATE OR REPLACE FUNCTION has_index ( NAME, NAME, text )
-RETURNS TEXT AS $$
-    SELECT CASE WHEN $3 LIKE '%(%'
-           THEN has_index( $1, $2, $3::name )
-           ELSE ok( _have_index( $1, $2 ), $3 )
-           END;
-$$ LANGUAGE sql;
-
--- has_index( table, index )
-CREATE OR REPLACE FUNCTION has_index ( NAME, NAME )
-RETURNS TEXT AS $$
-    SELECT ok( _have_index( $1, $2 ), 'Index ' || quote_ident($2) || ' should exist' );
-$$ LANGUAGE sql;
-
--- hasnt_index( schema, table, index, description )
-CREATE OR REPLACE FUNCTION hasnt_index ( NAME, NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-BEGIN
-    RETURN ok( NOT _have_index( $1, $2, $3 ), $4 );
-END;
-$$ LANGUAGE plpgSQL;
-
--- hasnt_index( schema, table, index )
-CREATE OR REPLACE FUNCTION hasnt_index ( NAME, NAME, NAME )
-RETURNS TEXT AS $$
-    SELECT ok(
-        NOT _have_index( $1, $2, $3 ),
-        'Index ' || quote_ident($3) || ' should not exist'
-    );
-$$ LANGUAGE SQL;
-
--- hasnt_index( table, index, description )
-CREATE OR REPLACE FUNCTION hasnt_index ( NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT ok( NOT _have_index( $1, $2 ), $3 );
-$$ LANGUAGE SQL;
-
--- hasnt_index( table, index )
-CREATE OR REPLACE FUNCTION hasnt_index ( NAME, NAME )
-RETURNS TEXT AS $$
-    SELECT ok(
-        NOT _have_index( $1, $2 ),
-        'Index ' || quote_ident($2) || ' should not exist'
-    );
-$$ LANGUAGE SQL;
-
--- index_is_unique( schema, table, index, description )
-CREATE OR REPLACE FUNCTION index_is_unique ( NAME, NAME, NAME, text )
-RETURNS TEXT AS $$
-DECLARE
-    res boolean;
-BEGIN
-    SELECT x.indisunique
-      FROM pg_catalog.pg_index x
-      JOIN pg_catalog.pg_class ct    ON ct.oid = x.indrelid
-      JOIN pg_catalog.pg_class ci    ON ci.oid = x.indexrelid
-      JOIN pg_catalog.pg_namespace n ON n.oid = ct.relnamespace
-     WHERE ct.relname = $2
-       AND ci.relname = $3
-       AND n.nspname  = $1
-      INTO res;
-
-      RETURN ok( COALESCE(res, false), $4 );
-END;
-$$ LANGUAGE plpgsql;
-
--- index_is_unique( schema, table, index )
-CREATE OR REPLACE FUNCTION index_is_unique ( NAME, NAME, NAME )
-RETURNS TEXT AS $$
-    SELECT index_is_unique(
-        $1, $2, $3,
-        'Index ' || quote_ident($3) || ' should be unique'
-    );
-$$ LANGUAGE sql;
-
--- index_is_unique( table, index )
-CREATE OR REPLACE FUNCTION index_is_unique ( NAME, NAME )
-RETURNS TEXT AS $$
-DECLARE
-    res boolean;
-BEGIN
-    SELECT x.indisunique
-      FROM pg_catalog.pg_index x
-      JOIN pg_catalog.pg_class ct ON ct.oid = x.indrelid
-      JOIN pg_catalog.pg_class ci ON ci.oid = x.indexrelid
-     WHERE ct.relname = $1
-       AND ci.relname = $2
-       AND pg_catalog.pg_table_is_visible(ct.oid)
-      INTO res;
-
-      RETURN ok(
-          COALESCE(res, false),
-          'Index ' || quote_ident($2) || ' should be unique'
-      );
-END;
-$$ LANGUAGE plpgsql;
-
--- index_is_unique( index )
-CREATE OR REPLACE FUNCTION index_is_unique ( NAME )
-RETURNS TEXT AS $$
-DECLARE
-    res boolean;
-BEGIN
-    SELECT x.indisunique
-      FROM pg_catalog.pg_index x
-      JOIN pg_catalog.pg_class ci ON ci.oid = x.indexrelid
-      JOIN pg_catalog.pg_class ct ON ct.oid = x.indrelid
-     WHERE ci.relname = $1
-       AND pg_catalog.pg_table_is_visible(ct.oid)
-      INTO res;
-
-      RETURN ok(
-          COALESCE(res, false),
-          'Index ' || quote_ident($1) || ' should be unique'
-      );
-END;
-$$ LANGUAGE plpgsql;
-
--- index_is_primary( schema, table, index, description )
-CREATE OR REPLACE FUNCTION index_is_primary ( NAME, NAME, NAME, text )
-RETURNS TEXT AS $$
-DECLARE
-    res boolean;
-BEGIN
-    SELECT x.indisprimary
-      FROM pg_catalog.pg_index x
-      JOIN pg_catalog.pg_class ct    ON ct.oid = x.indrelid
-      JOIN pg_catalog.pg_class ci    ON ci.oid = x.indexrelid
-      JOIN pg_catalog.pg_namespace n ON n.oid = ct.relnamespace
-     WHERE ct.relname = $2
-       AND ci.relname = $3
-       AND n.nspname  = $1
-      INTO res;
-
-      RETURN ok( COALESCE(res, false), $4 );
-END;
-$$ LANGUAGE plpgsql;
-
--- index_is_primary( schema, table, index )
-CREATE OR REPLACE FUNCTION index_is_primary ( NAME, NAME, NAME )
-RETURNS TEXT AS $$
-    SELECT index_is_primary(
-        $1, $2, $3,
-        'Index ' || quote_ident($3) || ' should be on a primary key'
-    );
-$$ LANGUAGE sql;
-
--- index_is_primary( table, index )
-CREATE OR REPLACE FUNCTION index_is_primary ( NAME, NAME )
-RETURNS TEXT AS $$
-DECLARE
-    res boolean;
-BEGIN
-    SELECT x.indisprimary
-      FROM pg_catalog.pg_index x
-      JOIN pg_catalog.pg_class ct ON ct.oid = x.indrelid
-      JOIN pg_catalog.pg_class ci ON ci.oid = x.indexrelid
-     WHERE ct.relname = $1
-       AND ci.relname = $2
-       AND pg_catalog.pg_table_is_visible(ct.oid)
-     INTO res;
-
-      RETURN ok(
-          COALESCE(res, false),
-          'Index ' || quote_ident($2) || ' should be on a primary key'
-      );
-END;
-$$ LANGUAGE plpgsql;
-
--- index_is_primary( index )
-CREATE OR REPLACE FUNCTION index_is_primary ( NAME )
-RETURNS TEXT AS $$
-DECLARE
-    res boolean;
-BEGIN
-    SELECT x.indisprimary
-      FROM pg_catalog.pg_index x
-      JOIN pg_catalog.pg_class ci ON ci.oid = x.indexrelid
-      JOIN pg_catalog.pg_class ct ON ct.oid = x.indrelid
-     WHERE ci.relname = $1
-       AND pg_catalog.pg_table_is_visible(ct.oid)
-      INTO res;
-
-      RETURN ok(
-          COALESCE(res, false),
-          'Index ' || quote_ident($1) || ' should be on a primary key'
-      );
-END;
-$$ LANGUAGE plpgsql;
-
--- is_clustered( schema, table, index, description )
-CREATE OR REPLACE FUNCTION is_clustered ( NAME, NAME, NAME, text )
-RETURNS TEXT AS $$
-DECLARE
-    res boolean;
-BEGIN
-    SELECT x.indisclustered
-      FROM pg_catalog.pg_index x
-      JOIN pg_catalog.pg_class ct    ON ct.oid = x.indrelid
-      JOIN pg_catalog.pg_class ci    ON ci.oid = x.indexrelid
-      JOIN pg_catalog.pg_namespace n ON n.oid = ct.relnamespace
-     WHERE ct.relname = $2
-       AND ci.relname = $3
-       AND n.nspname  = $1
-      INTO res;
-
-      RETURN ok( COALESCE(res, false), $4 );
-END;
-$$ LANGUAGE plpgsql;
-
--- is_clustered( schema, table, index )
-CREATE OR REPLACE FUNCTION is_clustered ( NAME, NAME, NAME )
-RETURNS TEXT AS $$
-    SELECT is_clustered(
-        $1, $2, $3,
-        'Table ' || quote_ident($1) || '.' || quote_ident($2) ||
-        ' should be clustered on index ' || quote_ident($3)
-    );
-$$ LANGUAGE sql;
-
--- is_clustered( table, index )
-CREATE OR REPLACE FUNCTION is_clustered ( NAME, NAME )
-RETURNS TEXT AS $$
-DECLARE
-    res boolean;
-BEGIN
-    SELECT x.indisclustered
-      FROM pg_catalog.pg_index x
-      JOIN pg_catalog.pg_class ct ON ct.oid = x.indrelid
-      JOIN pg_catalog.pg_class ci ON ci.oid = x.indexrelid
-     WHERE ct.relname = $1
-       AND ci.relname = $2
-      INTO res;
-
-      RETURN ok(
-          COALESCE(res, false),
-          'Table ' || quote_ident($1) || ' should be clustered on index ' || quote_ident($2)
-      );
-END;
-$$ LANGUAGE plpgsql;
-
--- is_clustered( index )
-CREATE OR REPLACE FUNCTION is_clustered ( NAME )
-RETURNS TEXT AS $$
-DECLARE
-    res boolean;
-BEGIN
-    SELECT x.indisclustered
-      FROM pg_catalog.pg_index x
-      JOIN pg_catalog.pg_class ci ON ci.oid = x.indexrelid
-     WHERE ci.relname = $1
-      INTO res;
-
-      RETURN ok(
-          COALESCE(res, false),
-          'Table should be clustered on index ' || quote_ident($1)
-      );
-END;
-$$ LANGUAGE plpgsql;
-
--- index_is_type( schema, table, index, type, description )
-CREATE OR REPLACE FUNCTION index_is_type ( NAME, NAME, NAME, NAME, text )
-RETURNS TEXT AS $$
-DECLARE
-    aname name;
-BEGIN
-    SELECT am.amname
-      FROM pg_catalog.pg_index x
-      JOIN pg_catalog.pg_class ct    ON ct.oid = x.indrelid
-      JOIN pg_catalog.pg_class ci    ON ci.oid = x.indexrelid
-      JOIN pg_catalog.pg_namespace n ON n.oid = ct.relnamespace
-      JOIN pg_catalog.pg_am am       ON ci.relam = am.oid
-     WHERE ct.relname = $2
-       AND ci.relname = $3
-       AND n.nspname  = $1
-      INTO aname;
-
-      return is( aname, $4, $5 );
-END;
-$$ LANGUAGE plpgsql;
-
--- index_is_type( schema, table, index, type )
-CREATE OR REPLACE FUNCTION index_is_type ( NAME, NAME, NAME, NAME )
-RETURNS TEXT AS $$
-    SELECT index_is_type(
-        $1, $2, $3, $4,
-        'Index ' || quote_ident($3) || ' should be a ' || quote_ident($4) || ' index'
-    );
-$$ LANGUAGE SQL;
-
--- index_is_type( table, index, type )
-CREATE OR REPLACE FUNCTION index_is_type ( NAME, NAME, NAME )
-RETURNS TEXT AS $$
-DECLARE
-    aname name;
-BEGIN
-    SELECT am.amname
-      FROM pg_catalog.pg_index x
-      JOIN pg_catalog.pg_class ct ON ct.oid = x.indrelid
-      JOIN pg_catalog.pg_class ci ON ci.oid = x.indexrelid
-      JOIN pg_catalog.pg_am am    ON ci.relam = am.oid
-     WHERE ct.relname = $1
-       AND ci.relname = $2
-      INTO aname;
-
-      return is(
-          aname, $3,
-          'Index ' || quote_ident($2) || ' should be a ' || quote_ident($3) || ' index'
-      );
-END;
-$$ LANGUAGE plpgsql;
-
--- index_is_type( index, type )
-CREATE OR REPLACE FUNCTION index_is_type ( NAME, NAME )
-RETURNS TEXT AS $$
-DECLARE
-    aname name;
-BEGIN
-    SELECT am.amname
-      FROM pg_catalog.pg_index x
-      JOIN pg_catalog.pg_class ci ON ci.oid = x.indexrelid
-      JOIN pg_catalog.pg_am am    ON ci.relam = am.oid
-     WHERE ci.relname = $1
-      INTO aname;
-
-      return is(
-          aname, $2,
-          'Index ' || quote_ident($1) || ' should be a ' || quote_ident($2) || ' index'
-      );
-END;
-$$ LANGUAGE plpgsql;
-
-CREATE OR REPLACE FUNCTION _trig ( NAME, NAME, NAME )
-RETURNS BOOLEAN AS $$
-    SELECT EXISTS(
-        SELECT true
-          FROM pg_catalog.pg_trigger t
-          JOIN pg_catalog.pg_class c     ON c.oid = t.tgrelid
-          JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
-         WHERE n.nspname = $1
-           AND c.relname = $2
-           AND t.tgname  = $3
-    );
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION _trig ( NAME, NAME )
-RETURNS BOOLEAN AS $$
-    SELECT EXISTS(
-        SELECT true
-          FROM pg_catalog.pg_trigger t
-          JOIN pg_catalog.pg_class c     ON c.oid = t.tgrelid
-         WHERE c.relname = $1
-           AND t.tgname  = $2
-    );
-$$ LANGUAGE SQL;
-
--- has_trigger( schema, table, trigger, description )
-CREATE OR REPLACE FUNCTION has_trigger ( NAME, NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT ok( _trig($1, $2, $3), $4);
-$$ LANGUAGE SQL;
-
--- has_trigger( schema, table, trigger )
-CREATE OR REPLACE FUNCTION has_trigger ( NAME, NAME, NAME )
-RETURNS TEXT AS $$
-    SELECT has_trigger(
-        $1, $2, $3,
-        'Table ' || quote_ident($1) || '.' || quote_ident($2) || ' should have trigger ' || quote_ident($3)
-    );
-$$ LANGUAGE sql;
-
--- has_trigger( table, trigger, description )
-CREATE OR REPLACE FUNCTION has_trigger ( NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT ok( _trig($1, $2), $3);
-$$ LANGUAGE sql;
-
--- has_trigger( table, trigger )
-CREATE OR REPLACE FUNCTION has_trigger ( NAME, NAME )
-RETURNS TEXT AS $$
-    SELECT ok( _trig($1, $2), 'Table ' || quote_ident($1) || ' should have trigger ' || quote_ident($2));
-$$ LANGUAGE SQL;
-
--- hasnt_trigger( schema, table, trigger, description )
-CREATE OR REPLACE FUNCTION hasnt_trigger ( NAME, NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT ok( NOT _trig($1, $2, $3), $4);
-$$ LANGUAGE SQL;
-
--- hasnt_trigger( schema, table, trigger )
-CREATE OR REPLACE FUNCTION hasnt_trigger ( NAME, NAME, NAME )
-RETURNS TEXT AS $$
-    SELECT ok(
-        NOT _trig($1, $2, $3),
-        'Table ' || quote_ident($1) || '.' || quote_ident($2) || ' should not have trigger ' || quote_ident($3)
-    );
-$$ LANGUAGE sql;
-
--- hasnt_trigger( table, trigger, description )
-CREATE OR REPLACE FUNCTION hasnt_trigger ( NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT ok( NOT _trig($1, $2), $3);
-$$ LANGUAGE sql;
-
--- hasnt_trigger( table, trigger )
-CREATE OR REPLACE FUNCTION hasnt_trigger ( NAME, NAME )
-RETURNS TEXT AS $$
-    SELECT ok( NOT _trig($1, $2), 'Table ' || quote_ident($1) || ' should not have trigger ' || quote_ident($2));
-$$ LANGUAGE SQL;
-
--- trigger_is( schema, table, trigger, schema, function, description )
-CREATE OR REPLACE FUNCTION trigger_is ( NAME, NAME, NAME, NAME, NAME, text )
-RETURNS TEXT AS $$
-DECLARE
-    pname text;
-BEGIN
-    SELECT quote_ident(ni.nspname) || '.' || quote_ident(p.proname)
-      FROM pg_catalog.pg_trigger t
-      JOIN pg_catalog.pg_class ct     ON ct.oid = t.tgrelid
-      JOIN pg_catalog.pg_namespace nt ON nt.oid = ct.relnamespace
-      JOIN pg_catalog.pg_proc p       ON p.oid = t.tgfoid
-      JOIN pg_catalog.pg_namespace ni ON ni.oid = p.pronamespace
-     WHERE nt.nspname = $1
-       AND ct.relname = $2
-       AND t.tgname   = $3
-      INTO pname;
-
-    RETURN is( pname, quote_ident($4) || '.' || quote_ident($5), $6 );
-END;
-$$ LANGUAGE plpgsql;
-
--- trigger_is( schema, table, trigger, schema, function )
-CREATE OR REPLACE FUNCTION trigger_is ( NAME, NAME, NAME, NAME, NAME )
-RETURNS TEXT AS $$
-    SELECT trigger_is(
-        $1, $2, $3, $4, $5,
-        'Trigger ' || quote_ident($3) || ' should call ' || quote_ident($4) || '.' || quote_ident($5) || '()'
-    );
-$$ LANGUAGE sql;
-
--- trigger_is( table, trigger, function, description )
-CREATE OR REPLACE FUNCTION trigger_is ( NAME, NAME, NAME, text )
-RETURNS TEXT AS $$
-DECLARE
-    pname text;
-BEGIN
-    SELECT p.proname
-      FROM pg_catalog.pg_trigger t
-      JOIN pg_catalog.pg_class ct ON ct.oid = t.tgrelid
-      JOIN pg_catalog.pg_proc p   ON p.oid = t.tgfoid
-     WHERE ct.relname = $1
-       AND t.tgname   = $2
-       AND pg_catalog.pg_table_is_visible(ct.oid)
-      INTO pname;
-
-    RETURN is( pname, $3::text, $4 );
-END;
-$$ LANGUAGE plpgsql;
-
--- trigger_is( table, trigger, function )
-CREATE OR REPLACE FUNCTION trigger_is ( NAME, NAME, NAME )
-RETURNS TEXT AS $$
-    SELECT trigger_is(
-        $1, $2, $3,
-        'Trigger ' || quote_ident($2) || ' should call ' || quote_ident($3) || '()'
-    );
-$$ LANGUAGE sql;
-
--- has_schema( schema, description )
-CREATE OR REPLACE FUNCTION has_schema( NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT ok(
-        EXISTS(
-            SELECT true
-              FROM pg_catalog.pg_namespace
-             WHERE nspname = $1
-        ), $2
-    );
-$$ LANGUAGE sql;
-
--- has_schema( schema )
-CREATE OR REPLACE FUNCTION has_schema( NAME )
-RETURNS TEXT AS $$
-    SELECT has_schema( $1, 'Schema ' || quote_ident($1) || ' should exist' );
-$$ LANGUAGE sql;
-
--- hasnt_schema( schema, description )
-CREATE OR REPLACE FUNCTION hasnt_schema( NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT ok(
-        NOT EXISTS(
-            SELECT true
-              FROM pg_catalog.pg_namespace
-             WHERE nspname = $1
-        ), $2
-    );
-$$ LANGUAGE sql;
-
--- hasnt_schema( schema )
-CREATE OR REPLACE FUNCTION hasnt_schema( NAME )
-RETURNS TEXT AS $$
-    SELECT hasnt_schema( $1, 'Schema ' || quote_ident($1) || ' should not exist' );
-$$ LANGUAGE sql;
-
--- has_tablespace( tablespace, location, description )
-CREATE OR REPLACE FUNCTION has_tablespace( NAME, TEXT, TEXT )
-RETURNS TEXT AS $$
-    SELECT ok(
-        EXISTS(
-            SELECT true
-              FROM pg_catalog.pg_tablespace
-             WHERE spcname = $1
-               AND spclocation = $2
-        ), $3
-    );
-$$ LANGUAGE sql;
-
--- has_tablespace( tablespace, description )
-CREATE OR REPLACE FUNCTION has_tablespace( NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT ok(
-        EXISTS(
-            SELECT true
-              FROM pg_catalog.pg_tablespace
-             WHERE spcname = $1
-        ), $2
-    );
-$$ LANGUAGE sql;
-
--- has_tablespace( tablespace )
-CREATE OR REPLACE FUNCTION has_tablespace( NAME )
-RETURNS TEXT AS $$
-    SELECT has_tablespace( $1, 'Tablespace ' || quote_ident($1) || ' should exist' );
-$$ LANGUAGE sql;
-
--- hasnt_tablespace( tablespace, description )
-CREATE OR REPLACE FUNCTION hasnt_tablespace( NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT ok(
-        NOT EXISTS(
-            SELECT true
-              FROM pg_catalog.pg_tablespace
-             WHERE spcname = $1
-        ), $2
-    );
-$$ LANGUAGE sql;
-
--- hasnt_tablespace( tablespace )
-CREATE OR REPLACE FUNCTION hasnt_tablespace( NAME )
-RETURNS TEXT AS $$
-    SELECT hasnt_tablespace( $1, 'Tablespace ' || quote_ident($1) || ' should not exist' );
-$$ LANGUAGE sql;
-
-CREATE OR REPLACE FUNCTION _has_type( NAME, NAME, CHAR[] )
-RETURNS BOOLEAN AS $$
-    SELECT EXISTS(
-        SELECT true
-          FROM pg_catalog.pg_type t
-          JOIN pg_catalog.pg_namespace n ON t.typnamespace = n.oid
-         WHERE t.typisdefined
-           AND n.nspname = $1
-           AND t.typname = $2
-           AND t.typtype = ANY( COALESCE($3, ARRAY['b', 'c', 'd', 'p', 'e']) )
-    );
-$$ LANGUAGE sql;
-
-CREATE OR REPLACE FUNCTION _has_type( NAME, CHAR[] )
-RETURNS BOOLEAN AS $$
-    SELECT EXISTS(
-        SELECT true
-          FROM pg_catalog.pg_type t
-         WHERE t.typisdefined
-           AND pg_catalog.pg_type_is_visible(t.oid)
-           AND t.typname = $1
-           AND t.typtype = ANY( COALESCE($2, ARRAY['b', 'c', 'd', 'p', 'e']) )
-    );
-$$ LANGUAGE sql;
-
--- has_type( schema, type, description )
-CREATE OR REPLACE FUNCTION has_type( NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT ok( _has_type( $1, $2, NULL ), $3 );
-$$ LANGUAGE sql;
-
--- has_type( schema, type )
-CREATE OR REPLACE FUNCTION has_type( NAME, NAME )
-RETURNS TEXT AS $$
-    SELECT has_type( $1, $2, 'Type ' || quote_ident($1) || '.' || quote_ident($2) || ' should exist' );
-$$ LANGUAGE sql;
-
--- has_type( type, description )
-CREATE OR REPLACE FUNCTION has_type( NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT ok( _has_type( $1, NULL ), $2 );
-$$ LANGUAGE sql;
-
--- has_type( type )
-CREATE OR REPLACE FUNCTION has_type( NAME )
-RETURNS TEXT AS $$
-    SELECT ok( _has_type( $1, NULL ), ('Type ' || quote_ident($1) || ' should exist')::text );
-$$ LANGUAGE sql;
-
--- hasnt_type( schema, type, description )
-CREATE OR REPLACE FUNCTION hasnt_type( NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT ok( NOT _has_type( $1, $2, NULL ), $3 );
-$$ LANGUAGE sql;
-
--- hasnt_type( schema, type )
-CREATE OR REPLACE FUNCTION hasnt_type( NAME, NAME )
-RETURNS TEXT AS $$
-    SELECT hasnt_type( $1, $2, 'Type ' || quote_ident($1) || '.' || quote_ident($2) || ' should not exist' );
-$$ LANGUAGE sql;
-
--- hasnt_type( type, description )
-CREATE OR REPLACE FUNCTION hasnt_type( NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT ok( NOT _has_type( $1, NULL ), $2 );
-$$ LANGUAGE sql;
-
--- hasnt_type( type )
-CREATE OR REPLACE FUNCTION hasnt_type( NAME )
-RETURNS TEXT AS $$
-    SELECT ok( NOT _has_type( $1, NULL ), ('Type ' || quote_ident($1) || ' should not exist')::text );
-$$ LANGUAGE sql;
-
--- has_domain( schema, domain, description )
-CREATE OR REPLACE FUNCTION has_domain( NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT ok( _has_type( $1, $2, ARRAY['d'] ), $3 );
-$$ LANGUAGE sql;
-
--- has_domain( schema, domain )
-CREATE OR REPLACE FUNCTION has_domain( NAME, NAME )
-RETURNS TEXT AS $$
-    SELECT has_domain( $1, $2, 'Domain ' || quote_ident($1) || '.' || quote_ident($2) || ' should exist' );
-$$ LANGUAGE sql;
-
--- has_domain( domain, description )
-CREATE OR REPLACE FUNCTION has_domain( NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT ok( _has_type( $1, ARRAY['d'] ), $2 );
-$$ LANGUAGE sql;
-
--- has_domain( domain )
-CREATE OR REPLACE FUNCTION has_domain( NAME )
-RETURNS TEXT AS $$
-    SELECT ok( _has_type( $1, ARRAY['d'] ), ('Domain ' || quote_ident($1) || ' should exist')::text );
-$$ LANGUAGE sql;
-
--- hasnt_domain( schema, domain, description )
-CREATE OR REPLACE FUNCTION hasnt_domain( NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT ok( NOT _has_type( $1, $2, ARRAY['d'] ), $3 );
-$$ LANGUAGE sql;
-
--- hasnt_domain( schema, domain )
-CREATE OR REPLACE FUNCTION hasnt_domain( NAME, NAME )
-RETURNS TEXT AS $$
-    SELECT hasnt_domain( $1, $2, 'Domain ' || quote_ident($1) || '.' || quote_ident($2) || ' should not exist' );
-$$ LANGUAGE sql;
-
--- hasnt_domain( domain, description )
-CREATE OR REPLACE FUNCTION hasnt_domain( NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT ok( NOT _has_type( $1, ARRAY['d'] ), $2 );
-$$ LANGUAGE sql;
-
--- hasnt_domain( domain )
-CREATE OR REPLACE FUNCTION hasnt_domain( NAME )
-RETURNS TEXT AS $$
-    SELECT ok( NOT _has_type( $1, ARRAY['d'] ), ('Domain ' || quote_ident($1) || ' should not exist')::text );
-$$ LANGUAGE sql;
-
--- has_enum( schema, enum, description )
-CREATE OR REPLACE FUNCTION has_enum( NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT ok( _has_type( $1, $2, ARRAY['e'] ), $3 );
-$$ LANGUAGE sql;
-
--- has_enum( schema, enum )
-CREATE OR REPLACE FUNCTION has_enum( NAME, NAME )
-RETURNS TEXT AS $$
-    SELECT has_enum( $1, $2, 'Enum ' || quote_ident($1) || '.' || quote_ident($2) || ' should exist' );
-$$ LANGUAGE sql;
-
--- has_enum( enum, description )
-CREATE OR REPLACE FUNCTION has_enum( NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT ok( _has_type( $1, ARRAY['e'] ), $2 );
-$$ LANGUAGE sql;
-
--- has_enum( enum )
-CREATE OR REPLACE FUNCTION has_enum( NAME )
-RETURNS TEXT AS $$
-    SELECT ok( _has_type( $1, ARRAY['e'] ), ('Enum ' || quote_ident($1) || ' should exist')::text );
-$$ LANGUAGE sql;
-
--- hasnt_enum( schema, enum, description )
-CREATE OR REPLACE FUNCTION hasnt_enum( NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT ok( NOT _has_type( $1, $2, ARRAY['e'] ), $3 );
-$$ LANGUAGE sql;
-
--- hasnt_enum( schema, enum )
-CREATE OR REPLACE FUNCTION hasnt_enum( NAME, NAME )
-RETURNS TEXT AS $$
-    SELECT hasnt_enum( $1, $2, 'Enum ' || quote_ident($1) || '.' || quote_ident($2) || ' should not exist' );
-$$ LANGUAGE sql;
-
--- hasnt_enum( enum, description )
-CREATE OR REPLACE FUNCTION hasnt_enum( NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT ok( NOT _has_type( $1, ARRAY['e'] ), $2 );
-$$ LANGUAGE sql;
-
--- hasnt_enum( enum )
-CREATE OR REPLACE FUNCTION hasnt_enum( NAME )
-RETURNS TEXT AS $$
-    SELECT ok( NOT _has_type( $1, ARRAY['e'] ), ('Enum ' || quote_ident($1) || ' should not exist')::text );
-$$ LANGUAGE sql;
-
--- enum_has_labels( schema, enum, labels, description )
-CREATE OR REPLACE FUNCTION enum_has_labels( NAME, NAME, NAME[], TEXT )
-RETURNS TEXT AS $$
-    SELECT is(
-        ARRAY(
-            SELECT e.enumlabel
-              FROM pg_catalog.pg_type t
-              JOIN pg_catalog.pg_enum e      ON t.oid = e.enumtypid
-              JOIN pg_catalog.pg_namespace n ON t.typnamespace = n.oid
-              WHERE t.typisdefined
-               AND n.nspname = $1
-               AND t.typname = $2
-               AND t.typtype = 'e'
-             ORDER BY e.oid
-        ),
-        $3,
-        $4
-    );
-$$ LANGUAGE sql;
-
--- enum_has_labels( schema, enum, labels )
-CREATE OR REPLACE FUNCTION enum_has_labels( NAME, NAME, NAME[] )
-RETURNS TEXT AS $$
-    SELECT enum_has_labels(
-        $1, $2, $3,
-        'Enum ' || quote_ident($1) || '.' || quote_ident($2) || ' should have labels (' || array_to_string( $3, ', ' ) || ')'
-    );
-$$ LANGUAGE sql;
-
--- enum_has_labels( enum, labels, description )
-CREATE OR REPLACE FUNCTION enum_has_labels( NAME, NAME[], TEXT )
-RETURNS TEXT AS $$
-    SELECT is(
-        ARRAY(
-            SELECT e.enumlabel
-              FROM pg_catalog.pg_type t
-              JOIN pg_catalog.pg_enum e ON t.oid = e.enumtypid
-              WHERE t.typisdefined
-               AND pg_catalog.pg_type_is_visible(t.oid)
-               AND t.typname = $1
-               AND t.typtype = 'e'
-             ORDER BY e.oid
-        ),
-        $2,
-        $3
-    );
-$$ LANGUAGE sql;
-
--- enum_has_labels( enum, labels )
-CREATE OR REPLACE FUNCTION enum_has_labels( NAME, NAME[] )
-RETURNS TEXT AS $$
-    SELECT enum_has_labels(
-        $1, $2,
-        'Enum ' || quote_ident($1) || ' should have labels (' || array_to_string( $2, ', ' ) || ')'
-    );
-$$ LANGUAGE sql;
-
-CREATE OR REPLACE FUNCTION _has_role( NAME )
-RETURNS BOOLEAN AS $$
-    SELECT EXISTS(
-        SELECT true
-          FROM pg_catalog.pg_roles
-         WHERE rolname = $1
-    );
-$$ LANGUAGE sql STRICT;
-
--- has_role( role, description )
-CREATE OR REPLACE FUNCTION has_role( NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT ok( _has_role($1), $2 );
-$$ LANGUAGE sql;
-
--- has_role( role )
-CREATE OR REPLACE FUNCTION has_role( NAME )
-RETURNS TEXT AS $$
-    SELECT ok( _has_role($1), 'Role ' || quote_ident($1) || ' should exist' );
-$$ LANGUAGE sql;
-
--- hasnt_role( role, description )
-CREATE OR REPLACE FUNCTION hasnt_role( NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT ok( NOT _has_role($1), $2 );
-$$ LANGUAGE sql;
-
--- hasnt_role( role )
-CREATE OR REPLACE FUNCTION hasnt_role( NAME )
-RETURNS TEXT AS $$
-    SELECT ok( NOT _has_role($1), 'Role ' || quote_ident($1) || ' should not exist' );
-$$ LANGUAGE sql;
-
-CREATE OR REPLACE FUNCTION _has_user( NAME )
-RETURNS BOOLEAN AS $$
-    SELECT EXISTS( SELECT true FROM pg_catalog.pg_user WHERE usename = $1);
-$$ LANGUAGE sql STRICT;
-
--- has_user( user, description )
-CREATE OR REPLACE FUNCTION has_user( NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT ok( _has_user($1), $2 );
-$$ LANGUAGE sql;
-
--- has_user( user )
-CREATE OR REPLACE FUNCTION has_user( NAME )
-RETURNS TEXT AS $$
-    SELECT ok( _has_user( $1 ), 'User ' || quote_ident($1) || ' should exist');
-$$ LANGUAGE sql;
-
--- hasnt_user( user, description )
-CREATE OR REPLACE FUNCTION hasnt_user( NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT ok( NOT _has_user($1), $2 );
-$$ LANGUAGE sql;
-
--- hasnt_user( user )
-CREATE OR REPLACE FUNCTION hasnt_user( NAME )
-RETURNS TEXT AS $$
-    SELECT ok( NOT _has_user( $1 ), 'User ' || quote_ident($1) || ' should not exist');
-$$ LANGUAGE sql;
-
-CREATE OR REPLACE FUNCTION _is_super( NAME )
-RETURNS BOOLEAN AS $$
-    SELECT rolsuper
-      FROM pg_catalog.pg_roles
-     WHERE rolname = $1
-$$ LANGUAGE sql STRICT;
-
--- is_superuser( user, description )
-CREATE OR REPLACE FUNCTION is_superuser( NAME, TEXT )
-RETURNS TEXT AS $$
-DECLARE
-    is_super boolean := _is_super($1);
-BEGIN
-    IF is_super IS NULL THEN
-        RETURN fail( $2 ) || E'\n' || diag( '    User ' || quote_ident($1) || ' does not exist') ;
-    END IF;
-    RETURN ok( is_super, $2 );
-END;
-$$ LANGUAGE plpgsql;
-
--- is_superuser( user )
-CREATE OR REPLACE FUNCTION is_superuser( NAME )
-RETURNS TEXT AS $$
-    SELECT is_superuser( $1, 'User ' || quote_ident($1) || ' should be a super user' );
-$$ LANGUAGE sql;
-
--- isnt_superuser( user, description )
-CREATE OR REPLACE FUNCTION isnt_superuser( NAME, TEXT )
-RETURNS TEXT AS $$
-DECLARE
-    is_super boolean := _is_super($1);
-BEGIN
-    IF is_super IS NULL THEN
-        RETURN fail( $2 ) || E'\n' || diag( '    User ' || quote_ident($1) || ' does not exist') ;
-    END IF;
-    RETURN ok( NOT is_super, $2 );
-END;
-$$ LANGUAGE plpgsql;
-
--- isnt_superuser( user )
-CREATE OR REPLACE FUNCTION isnt_superuser( NAME )
-RETURNS TEXT AS $$
-    SELECT isnt_superuser( $1, 'User ' || quote_ident($1) || ' should not be a super user' );
-$$ LANGUAGE sql;
-
-CREATE OR REPLACE FUNCTION _has_group( NAME )
-RETURNS BOOLEAN AS $$
-    SELECT EXISTS(
-        SELECT true
-          FROM pg_catalog.pg_group
-         WHERE groname = $1
-    );
-$$ LANGUAGE sql STRICT;
-
--- has_group( group, description )
-CREATE OR REPLACE FUNCTION has_group( NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT ok( _has_group($1), $2 );
-$$ LANGUAGE sql;
-
--- has_group( group )
-CREATE OR REPLACE FUNCTION has_group( NAME )
-RETURNS TEXT AS $$
-    SELECT ok( _has_group($1), 'Group ' || quote_ident($1) || ' should exist' );
-$$ LANGUAGE sql;
-
--- hasnt_group( group, description )
-CREATE OR REPLACE FUNCTION hasnt_group( NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT ok( NOT _has_group($1), $2 );
-$$ LANGUAGE sql;
-
--- hasnt_group( group )
-CREATE OR REPLACE FUNCTION hasnt_group( NAME )
-RETURNS TEXT AS $$
-    SELECT ok( NOT _has_group($1), 'Group ' || quote_ident($1) || ' should not exist' );
-$$ LANGUAGE sql;
-
-CREATE OR REPLACE FUNCTION _grolist ( NAME )
-RETURNS oid[] AS $$
-    SELECT ARRAY(
-        SELECT member
-          FROM pg_catalog.pg_auth_members m
-          JOIN pg_catalog.pg_roles r ON m.roleid = r.oid
-         WHERE r.rolname =  $1
-    );
-$$ LANGUAGE sql;
-
--- is_member_of( group, user[], description )
-CREATE OR REPLACE FUNCTION is_member_of( NAME, NAME[], TEXT )
-RETURNS TEXT AS $$
-DECLARE
-    missing text[];
-BEGIN
-    IF NOT _has_role($1) THEN
-        RETURN fail( $3 ) || E'\n' || diag (
-            '    Role ' || quote_ident($1) || ' does not exist'
-        );
-    END IF;
-
-    SELECT ARRAY(
-        SELECT quote_ident($2[i])
-          FROM generate_series(1, array_upper($2, 1)) s(i)
-          LEFT JOIN pg_catalog.pg_user ON usename = $2[i]
-         WHERE usesysid IS NULL
-            OR NOT usesysid = ANY ( _grolist($1) )
-         ORDER BY s.i
-    ) INTO missing;
-    IF missing[1] IS NULL THEN
-        RETURN ok( true, $3 );
-    END IF;
-    RETURN ok( false, $3 ) || E'\n' || diag(
-        '    Users missing from the ' || quote_ident($1) || E' group:\n        ' ||
-        array_to_string( missing, E'\n        ')
-    );
-END;
-$$ LANGUAGE plpgsql;
-
--- is_member_of( group, user, description )
-CREATE OR REPLACE FUNCTION is_member_of( NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT is_member_of( $1, ARRAY[$2], $3 );
-$$ LANGUAGE SQL;
-
--- is_member_of( group, user[] )
-CREATE OR REPLACE FUNCTION is_member_of( NAME, NAME[] )
-RETURNS TEXT AS $$
-    SELECT is_member_of( $1, $2, 'Should have members of group ' || quote_ident($1) );
-$$ LANGUAGE SQL;
-
--- is_member_of( group, user )
-CREATE OR REPLACE FUNCTION is_member_of( NAME, NAME )
-RETURNS TEXT AS $$
-    SELECT is_member_of( $1, ARRAY[$2] );
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION _cmp_types(oid, name)
-RETURNS BOOLEAN AS $$
-DECLARE
-    dtype TEXT := display_type($1, NULL);
-BEGIN
-    RETURN dtype = _quote_ident_like($2, dtype);
-END;
-$$ LANGUAGE plpgsql;
-
-CREATE OR REPLACE FUNCTION _cast_exists ( NAME, NAME, NAME, NAME )
-RETURNS BOOLEAN AS $$
-    SELECT EXISTS (
-       SELECT TRUE
-         FROM pg_catalog.pg_cast c
-         JOIN pg_catalog.pg_proc p ON c.castfunc = p.oid
-         JOIN pg_catalog.pg_namespace n ON p.pronamespace = n.oid
-        WHERE _cmp_types(castsource, $1)
-          AND _cmp_types(casttarget, $2)
-          AND n.nspname   = $3
-          AND p.proname   = $4
-   );
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION _cast_exists ( NAME, NAME, NAME )
-RETURNS BOOLEAN AS $$
-    SELECT EXISTS (
-       SELECT TRUE
-         FROM pg_catalog.pg_cast c
-         JOIN pg_catalog.pg_proc p ON c.castfunc = p.oid
-        WHERE _cmp_types(castsource, $1)
-          AND _cmp_types(casttarget, $2)
-          AND p.proname   = $3
-   );
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION _cast_exists ( NAME, NAME )
-RETURNS BOOLEAN AS $$
-    SELECT EXISTS (
-       SELECT TRUE
-         FROM pg_catalog.pg_cast c
-        WHERE _cmp_types(castsource, $1)
-          AND _cmp_types(casttarget, $2)
-   );
-$$ LANGUAGE SQL;
-
--- has_cast( source_type, target_type, schema, function, description )
-CREATE OR REPLACE FUNCTION has_cast ( NAME, NAME, NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-   SELECT ok( _cast_exists( $1, $2, $3, $4 ), $5 );
-$$ LANGUAGE SQL;
-
--- has_cast( source_type, target_type, schema, function )
-CREATE OR REPLACE FUNCTION has_cast ( NAME, NAME, NAME, NAME )
-RETURNS TEXT AS $$
-   SELECT ok(
-       _cast_exists( $1, $2, $3, $4 ),
-        'Cast (' || quote_ident($1) || ' AS ' || quote_ident($2)
-        || ') WITH FUNCTION ' || quote_ident($3)
-        || '.' || quote_ident($4) || '() should exist'
-    );
-$$ LANGUAGE SQL;
-
--- has_cast( source_type, target_type, function, description )
-CREATE OR REPLACE FUNCTION has_cast ( NAME, NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-   SELECT ok( _cast_exists( $1, $2, $3 ), $4 );
-$$ LANGUAGE SQL;
-
--- has_cast( source_type, target_type, function )
-CREATE OR REPLACE FUNCTION has_cast ( NAME, NAME, NAME )
-RETURNS TEXT AS $$
-   SELECT ok(
-        _cast_exists( $1, $2, $3 ),
-        'Cast (' || quote_ident($1) || ' AS ' || quote_ident($2)
-        || ') WITH FUNCTION ' || quote_ident($3) || '() should exist'
-    );
-$$ LANGUAGE SQL;
-
--- has_cast( source_type, target_type, description )
-CREATE OR REPLACE FUNCTION has_cast ( NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT ok( _cast_exists( $1, $2 ), $3 );
-$$ LANGUAGE SQL;
-
--- has_cast( source_type, target_type )
-CREATE OR REPLACE FUNCTION has_cast ( NAME, NAME )
-RETURNS TEXT AS $$
-    SELECT ok(
-        _cast_exists( $1, $2 ),
-        'Cast (' || quote_ident($1) || ' AS ' || quote_ident($2)
-        || ') should exist'
-    );
-$$ LANGUAGE SQL;
-
--- hasnt_cast( source_type, target_type, schema, function, description )
-CREATE OR REPLACE FUNCTION hasnt_cast ( NAME, NAME, NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-   SELECT ok( NOT _cast_exists( $1, $2, $3, $4 ), $5 );
-$$ LANGUAGE SQL;
-
--- hasnt_cast( source_type, target_type, schema, function )
-CREATE OR REPLACE FUNCTION hasnt_cast ( NAME, NAME, NAME, NAME )
-RETURNS TEXT AS $$
-   SELECT ok(
-       NOT _cast_exists( $1, $2, $3, $4 ),
-        'Cast (' || quote_ident($1) || ' AS ' || quote_ident($2)
-        || ') WITH FUNCTION ' || quote_ident($3)
-        || '.' || quote_ident($4) || '() should not exist'
-    );
-$$ LANGUAGE SQL;
-
--- hasnt_cast( source_type, target_type, function, description )
-CREATE OR REPLACE FUNCTION hasnt_cast ( NAME, NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-   SELECT ok( NOT _cast_exists( $1, $2, $3 ), $4 );
-$$ LANGUAGE SQL;
-
--- hasnt_cast( source_type, target_type, function )
-CREATE OR REPLACE FUNCTION hasnt_cast ( NAME, NAME, NAME )
-RETURNS TEXT AS $$
-   SELECT ok(
-        NOT _cast_exists( $1, $2, $3 ),
-        'Cast (' || quote_ident($1) || ' AS ' || quote_ident($2)
-        || ') WITH FUNCTION ' || quote_ident($3) || '() should not exist'
-    );
-$$ LANGUAGE SQL;
-
--- hasnt_cast( source_type, target_type, description )
-CREATE OR REPLACE FUNCTION hasnt_cast ( NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT ok( NOT _cast_exists( $1, $2 ), $3 );
-$$ LANGUAGE SQL;
-
--- hasnt_cast( source_type, target_type )
-CREATE OR REPLACE FUNCTION hasnt_cast ( NAME, NAME )
-RETURNS TEXT AS $$
-    SELECT ok(
-        NOT _cast_exists( $1, $2 ),
-        'Cast (' || quote_ident($1) || ' AS ' || quote_ident($2)
-        || ') should not exist'
-    );
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION _expand_context( char )
-RETURNS text AS $$
-   SELECT CASE $1
-          WHEN 'i' THEN 'implicit'
-          WHEN 'a' THEN 'assignment'
-          WHEN 'e' THEN 'explicit'
-          ELSE          'unknown' END
-$$ LANGUAGE SQL IMMUTABLE;
-
-CREATE OR REPLACE FUNCTION _get_context( NAME, NAME )
-RETURNS "char" AS $$
-   SELECT c.castcontext
-     FROM pg_catalog.pg_cast c
-    WHERE _cmp_types(castsource, $1)
-      AND _cmp_types(casttarget, $2)
-$$ LANGUAGE SQL;
-
--- cast_context_is( source_type, target_type, context, description )
-CREATE OR REPLACE FUNCTION cast_context_is( NAME, NAME, TEXT, TEXT )
-RETURNS TEXT AS $$
-DECLARE
-    want char = substring(LOWER($3) FROM 1 FOR 1);
-    have char := _get_context($1, $2);
-BEGIN
-    IF have IS NOT NULL THEN
-        RETURN is( _expand_context(have), _expand_context(want), $4 );
-    END IF;
-
-    RETURN ok( false, $4 ) || E'\n' || diag(
-       '    Cast (' || quote_ident($1) || ' AS ' || quote_ident($2)
-      || ') does not exist'
-    );
-END;
-$$ LANGUAGE plpgsql;
-
--- cast_context_is( source_type, target_type, context )
-CREATE OR REPLACE FUNCTION cast_context_is( NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT cast_context_is(
-        $1, $2, $3,
-        'Cast (' || quote_ident($1) || ' AS ' || quote_ident($2)
-        || ') context should be ' || _expand_context(substring(LOWER($3) FROM 1 FOR 1))
-    );
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION _op_exists ( NAME, NAME, NAME, NAME, NAME )
-RETURNS BOOLEAN AS $$
-    SELECT EXISTS (
-       SELECT TRUE
-         FROM pg_catalog.pg_operator o
-         JOIN pg_catalog.pg_namespace n ON o.oprnamespace = n.oid
-        WHERE n.nspname = $2
-          AND o.oprname = $3
-          AND CASE o.oprkind WHEN 'l' THEN $1 IS NULL
-              ELSE _cmp_types(o.oprleft, $1) END
-          AND CASE o.oprkind WHEN 'r' THEN $4 IS NULL
-              ELSE _cmp_types(o.oprright, $4) END
-          AND _cmp_types(o.oprresult, $5)
-   );
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION _op_exists ( NAME, NAME, NAME, NAME )
-RETURNS BOOLEAN AS $$
-    SELECT EXISTS (
-       SELECT TRUE
-         FROM pg_catalog.pg_operator o
-        WHERE pg_catalog.pg_operator_is_visible(o.oid)
-          AND o.oprname = $2
-          AND CASE o.oprkind WHEN 'l' THEN $1 IS NULL
-              ELSE _cmp_types(o.oprleft, $1) END
-          AND CASE o.oprkind WHEN 'r' THEN $3 IS NULL
-              ELSE _cmp_types(o.oprright, $3) END
-          AND _cmp_types(o.oprresult, $4)
-   );
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION _op_exists ( NAME, NAME, NAME )
-RETURNS BOOLEAN AS $$
-    SELECT EXISTS (
-       SELECT TRUE
-         FROM pg_catalog.pg_operator o
-        WHERE pg_catalog.pg_operator_is_visible(o.oid)
-          AND o.oprname = $2
-          AND CASE o.oprkind WHEN 'l' THEN $1 IS NULL
-              ELSE _cmp_types(o.oprleft, $1) END
-          AND CASE o.oprkind WHEN 'r' THEN $3 IS NULL
-              ELSE _cmp_types(o.oprright, $3) END
-   );
-$$ LANGUAGE SQL;
-
--- has_operator( left_type, schema, name, right_type, return_type, description )
-CREATE OR REPLACE FUNCTION has_operator ( NAME, NAME, NAME, NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT ok( _op_exists($1, $2, $3, $4, $5 ), $6 );
-$$ LANGUAGE SQL;
-
--- has_operator( left_type, schema, name, right_type, return_type )
-CREATE OR REPLACE FUNCTION has_operator ( NAME, NAME, NAME, NAME, NAME )
-RETURNS TEXT AS $$
-    SELECT ok(
-         _op_exists($1, $2, $3, $4, $5 ),
-        'Operator ' || quote_ident($2) || '.' || $3 || '(' || $1 || ',' || $4
-        || ') RETURNS ' || $5 || ' should exist'
-    );
-$$ LANGUAGE SQL;
-
--- has_operator( left_type, name, right_type, return_type, description )
-CREATE OR REPLACE FUNCTION has_operator ( NAME, NAME, NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT ok( _op_exists($1, $2, $3, $4 ), $5 );
-$$ LANGUAGE SQL;
-
--- has_operator( left_type, name, right_type, return_type )
-CREATE OR REPLACE FUNCTION has_operator ( NAME, NAME, NAME, NAME )
-RETURNS TEXT AS $$
-    SELECT ok(
-         _op_exists($1, $2, $3, $4 ),
-        'Operator ' ||  $2 || '(' || $1 || ',' || $3
-        || ') RETURNS ' || $4 || ' should exist'
-    );
-$$ LANGUAGE SQL;
-
--- has_operator( left_type, name, right_type, description )
-CREATE OR REPLACE FUNCTION has_operator ( NAME, NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT ok( _op_exists($1, $2, $3 ), $4 );
-$$ LANGUAGE SQL;
-
--- has_operator( left_type, name, right_type )
-CREATE OR REPLACE FUNCTION has_operator ( NAME, NAME, NAME )
-RETURNS TEXT AS $$
-    SELECT ok(
-         _op_exists($1, $2, $3 ),
-        'Operator ' ||  $2 || '(' || $1 || ',' || $3
-        || ') should exist'
-    );
-$$ LANGUAGE SQL;
-
--- has_leftop( schema, name, right_type, return_type, description )
-CREATE OR REPLACE FUNCTION has_leftop ( NAME, NAME, NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT ok( _op_exists(NULL, $1, $2, $3, $4), $5 );
-$$ LANGUAGE SQL;
-
--- has_leftop( schema, name, right_type, return_type )
-CREATE OR REPLACE FUNCTION has_leftop ( NAME, NAME, NAME, NAME )
-RETURNS TEXT AS $$
-    SELECT ok(
-         _op_exists(NULL, $1, $2, $3, $4 ),
-        'Left operator ' || quote_ident($1) || '.' || $2 || '(NONE,'
-        || $3 || ') RETURNS ' || $4 || ' should exist'
-    );
-$$ LANGUAGE SQL;
-
--- has_leftop( name, right_type, return_type, description )
-CREATE OR REPLACE FUNCTION has_leftop ( NAME, NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT ok( _op_exists(NULL, $1, $2, $3), $4 );
-$$ LANGUAGE SQL;
-
--- has_leftop( name, right_type, return_type )
-CREATE OR REPLACE FUNCTION has_leftop ( NAME, NAME, NAME )
-RETURNS TEXT AS $$
-    SELECT ok(
-         _op_exists(NULL, $1, $2, $3 ),
-        'Left operator ' || $1 || '(NONE,' || $2 || ') RETURNS ' || $3 || ' should exist'
-    );
-$$ LANGUAGE SQL;
-
--- has_leftop( name, right_type, description )
-CREATE OR REPLACE FUNCTION has_leftop ( NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT ok( _op_exists(NULL, $1, $2), $3 );
-$$ LANGUAGE SQL;
-
--- has_leftop( name, right_type )
-CREATE OR REPLACE FUNCTION has_leftop ( NAME, NAME )
-RETURNS TEXT AS $$
-    SELECT ok(
-         _op_exists(NULL, $1, $2 ),
-        'Left operator ' || $1 || '(NONE,' || $2 || ') should exist'
-    );
-$$ LANGUAGE SQL;
-
--- has_rightop( left_type, schema, name, return_type, description )
-CREATE OR REPLACE FUNCTION has_rightop ( NAME, NAME, NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT ok( _op_exists( $1, $2, $3, NULL, $4), $5 );
-$$ LANGUAGE SQL;
-
--- has_rightop( left_type, schema, name, return_type )
-CREATE OR REPLACE FUNCTION has_rightop ( NAME, NAME, NAME, NAME )
-RETURNS TEXT AS $$
-    SELECT ok(
-         _op_exists($1, $2, $3, NULL, $4 ),
-        'Right operator ' || quote_ident($2) || '.' || $3 || '('
-        || $1 || ',NONE) RETURNS ' || $4 || ' should exist'
-    );
-$$ LANGUAGE SQL;
-
--- has_rightop( left_type, name, return_type, description )
-CREATE OR REPLACE FUNCTION has_rightop ( NAME, NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT ok( _op_exists( $1, $2, NULL, $3), $4 );
-$$ LANGUAGE SQL;
-
--- has_rightop( left_type, name, return_type )
-CREATE OR REPLACE FUNCTION has_rightop ( NAME, NAME, NAME )
-RETURNS TEXT AS $$
-    SELECT ok(
-         _op_exists($1, $2, NULL, $3 ),
-        'Right operator ' || $2 || '('
-        || $1 || ',NONE) RETURNS ' || $3 || ' should exist'
-    );
-$$ LANGUAGE SQL;
-
--- has_rightop( left_type, name, description )
-CREATE OR REPLACE FUNCTION has_rightop ( NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT ok( _op_exists( $1, $2, NULL), $3 );
-$$ LANGUAGE SQL;
-
--- has_rightop( left_type, name )
-CREATE OR REPLACE FUNCTION has_rightop ( NAME, NAME )
-RETURNS TEXT AS $$
-    SELECT ok(
-         _op_exists($1, $2, NULL ),
-        'Right operator ' || $2 || '(' || $1 || ',NONE) should exist'
-    );
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION _are ( text, name[], name[], TEXT )
-RETURNS TEXT AS $$
-DECLARE
-    what    ALIAS FOR $1;
-    extras  ALIAS FOR $2;
-    missing ALIAS FOR $3;
-    descr   ALIAS FOR $4;
-    msg     TEXT    := '';
-    res     BOOLEAN := TRUE;
-BEGIN
-    IF extras[1] IS NOT NULL THEN
-        res = FALSE;
-        msg := E'\n' || diag(
-            '    Extra ' || what || E':\n        '
-            ||  _ident_array_to_string( extras, E'\n        ' )
-        );
-    END IF;
-    IF missing[1] IS NOT NULL THEN
-        res = FALSE;
-        msg := msg || E'\n' || diag(
-            '    Missing ' || what || E':\n        '
-            ||  _ident_array_to_string( missing, E'\n        ' )
-        );
-    END IF;
-
-    RETURN ok(res, descr) || msg;
-END;
-$$ LANGUAGE plpgsql;
-
--- tablespaces_are( tablespaces, description )
-CREATE OR REPLACE FUNCTION tablespaces_are ( NAME[], TEXT )
-RETURNS TEXT AS $$
-    SELECT _are(
-        'tablespaces',
-        ARRAY(
-            SELECT spcname
-              FROM pg_catalog.pg_tablespace
-            EXCEPT
-            SELECT $1[i]
-              FROM generate_series(1, array_upper($1, 1)) s(i)
-        ),
-        ARRAY(
-            SELECT $1[i]
-               FROM generate_series(1, array_upper($1, 1)) s(i)
-            EXCEPT
-            SELECT spcname
-              FROM pg_catalog.pg_tablespace
-        ),
-        $2
-    );
-$$ LANGUAGE SQL;
-
--- tablespaces_are( tablespaces )
-CREATE OR REPLACE FUNCTION tablespaces_are ( NAME[] )
-RETURNS TEXT AS $$
-    SELECT tablespaces_are( $1, 'There should be the correct tablespaces' );
-$$ LANGUAGE SQL;
-
--- schemas_are( schemas, description )
-CREATE OR REPLACE FUNCTION schemas_are ( NAME[], TEXT )
-RETURNS TEXT AS $$
-    SELECT _are(
-        'schemas',
-        ARRAY(
-            SELECT nspname
-              FROM pg_catalog.pg_namespace
-             WHERE nspname NOT LIKE 'pg_%'
-               AND nspname <> 'information_schema'
-             EXCEPT
-            SELECT $1[i]
-              FROM generate_series(1, array_upper($1, 1)) s(i)
-        ),
-        ARRAY(
-            SELECT $1[i]
-              FROM generate_series(1, array_upper($1, 1)) s(i)
-            EXCEPT
-            SELECT nspname
-              FROM pg_catalog.pg_namespace
-             WHERE nspname NOT LIKE 'pg_%'
-               AND nspname <> 'information_schema'
-        ),
-        $2
-    );
-$$ LANGUAGE SQL;
-
--- schemas_are( schemas )
-CREATE OR REPLACE FUNCTION schemas_are ( NAME[] )
-RETURNS TEXT AS $$
-    SELECT schemas_are( $1, 'There should be the correct schemas' );
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION _extras ( CHAR, NAME, NAME[] )
-RETURNS NAME[] AS $$
-    SELECT ARRAY(
-        SELECT c.relname
-          FROM pg_catalog.pg_namespace n
-          JOIN pg_catalog.pg_class c ON n.oid = c.relnamespace
-         WHERE c.relkind = $1
-           AND n.nspname = $2
-           AND c.relname NOT IN('pg_all_foreign_keys', 'tap_funky', '__tresults___numb_seq', '__tcache___id_seq')
-        EXCEPT
-        SELECT $3[i]
-          FROM generate_series(1, array_upper($3, 1)) s(i)
-    );
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION _extras ( CHAR, NAME[] )
-RETURNS NAME[] AS $$
-    SELECT ARRAY(
-        SELECT c.relname
-          FROM pg_catalog.pg_namespace n
-          JOIN pg_catalog.pg_class c ON n.oid = c.relnamespace
-         WHERE pg_catalog.pg_table_is_visible(c.oid)
-           AND n.nspname <> 'pg_catalog'
-           AND c.relkind = $1
-           AND c.relname NOT IN ('__tcache__', '__tresults__', 'pg_all_foreign_keys', 'tap_funky', '__tresults___numb_seq', '__tcache___id_seq')
-        EXCEPT
-        SELECT $2[i]
-          FROM generate_series(1, array_upper($2, 1)) s(i)
-    );
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION _missing ( CHAR, NAME, NAME[] )
-RETURNS NAME[] AS $$
-    SELECT ARRAY(
-        SELECT $3[i]
-          FROM generate_series(1, array_upper($3, 1)) s(i)
-        EXCEPT
-        SELECT c.relname
-          FROM pg_catalog.pg_namespace n
-          JOIN pg_catalog.pg_class c ON n.oid = c.relnamespace
-         WHERE c.relkind = $1
-           AND n.nspname = $2
-    );
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION _missing ( CHAR, NAME[] )
-RETURNS NAME[] AS $$
-    SELECT ARRAY(
-        SELECT $2[i]
-          FROM generate_series(1, array_upper($2, 1)) s(i)
-        EXCEPT
-        SELECT c.relname
-          FROM pg_catalog.pg_namespace n
-          JOIN pg_catalog.pg_class c ON n.oid = c.relnamespace
-         WHERE pg_catalog.pg_table_is_visible(c.oid)
-           AND n.nspname NOT IN ('pg_catalog', 'information_schema')
-           AND c.relkind = $1
-    );
-$$ LANGUAGE SQL;
-
--- tables_are( schema, tables, description )
-CREATE OR REPLACE FUNCTION tables_are ( NAME, NAME[], TEXT )
-RETURNS TEXT AS $$
-    SELECT _are( 'tables', _extras('r', $1, $2), _missing('r', $1, $2), $3);
-$$ LANGUAGE SQL;
-
--- tables_are( tables, description )
-CREATE OR REPLACE FUNCTION tables_are ( NAME[], TEXT )
-RETURNS TEXT AS $$
-    SELECT _are( 'tables', _extras('r', $1), _missing('r', $1), $2);
-$$ LANGUAGE SQL;
-
--- tables_are( schema, tables )
-CREATE OR REPLACE FUNCTION tables_are ( NAME, NAME[] )
-RETURNS TEXT AS $$
-    SELECT _are(
-        'tables', _extras('r', $1, $2), _missing('r', $1, $2),
-        'Schema ' || quote_ident($1) || ' should have the correct tables'
-    );
-$$ LANGUAGE SQL;
-
--- tables_are( tables )
-CREATE OR REPLACE FUNCTION tables_are ( NAME[] )
-RETURNS TEXT AS $$
-    SELECT _are(
-        'tables', _extras('r', $1), _missing('r', $1),
-        'Search path ' || pg_catalog.current_setting('search_path') || ' should have the correct tables'
-    );
-$$ LANGUAGE SQL;
-
--- views_are( schema, views, description )
-CREATE OR REPLACE FUNCTION views_are ( NAME, NAME[], TEXT )
-RETURNS TEXT AS $$
-    SELECT _are( 'views', _extras('v', $1, $2), _missing('v', $1, $2), $3);
-$$ LANGUAGE SQL;
-
--- views_are( views, description )
-CREATE OR REPLACE FUNCTION views_are ( NAME[], TEXT )
-RETURNS TEXT AS $$
-    SELECT _are( 'views', _extras('v', $1), _missing('v', $1), $2);
-$$ LANGUAGE SQL;
-
--- views_are( schema, views )
-CREATE OR REPLACE FUNCTION views_are ( NAME, NAME[] )
-RETURNS TEXT AS $$
-    SELECT _are(
-        'views', _extras('v', $1, $2), _missing('v', $1, $2),
-        'Schema ' || quote_ident($1) || ' should have the correct views'
-    );
-$$ LANGUAGE SQL;
-
--- views_are( views )
-CREATE OR REPLACE FUNCTION views_are ( NAME[] )
-RETURNS TEXT AS $$
-    SELECT _are(
-        'views', _extras('v', $1), _missing('v', $1),
-        'Search path ' || pg_catalog.current_setting('search_path') || ' should have the correct views'
-    );
-$$ LANGUAGE SQL;
-
--- sequences_are( schema, sequences, description )
-CREATE OR REPLACE FUNCTION sequences_are ( NAME, NAME[], TEXT )
-RETURNS TEXT AS $$
-    SELECT _are( 'sequences', _extras('S', $1, $2), _missing('S', $1, $2), $3);
-$$ LANGUAGE SQL;
-
--- sequences_are( sequences, description )
-CREATE OR REPLACE FUNCTION sequences_are ( NAME[], TEXT )
-RETURNS TEXT AS $$
-    SELECT _are( 'sequences', _extras('S', $1), _missing('S', $1), $2);
-$$ LANGUAGE SQL;
-
--- sequences_are( schema, sequences )
-CREATE OR REPLACE FUNCTION sequences_are ( NAME, NAME[] )
-RETURNS TEXT AS $$
-    SELECT _are(
-        'sequences', _extras('S', $1, $2), _missing('S', $1, $2),
-        'Schema ' || quote_ident($1) || ' should have the correct sequences'
-    );
-$$ LANGUAGE SQL;
-
--- sequences_are( sequences )
-CREATE OR REPLACE FUNCTION sequences_are ( NAME[] )
-RETURNS TEXT AS $$
-    SELECT _are(
-        'sequences', _extras('S', $1), _missing('S', $1),
-        'Search path ' || pg_catalog.current_setting('search_path') || ' should have the correct sequences'
-    );
-$$ LANGUAGE SQL;
-
--- functions_are( schema, functions[], description )
-CREATE OR REPLACE FUNCTION functions_are ( NAME, NAME[], TEXT )
-RETURNS TEXT AS $$
-    SELECT _are(
-        'functions',
-        ARRAY(
-            SELECT name FROM tap_funky WHERE schema = $1
-            EXCEPT
-            SELECT $2[i]
-              FROM generate_series(1, array_upper($2, 1)) s(i)
-        ),
-        ARRAY(
-            SELECT $2[i]
-               FROM generate_series(1, array_upper($2, 1)) s(i)
-            EXCEPT
-            SELECT name FROM tap_funky WHERE schema = $1
-        ),
-        $3
-    );
-$$ LANGUAGE SQL;
-
--- functions_are( schema, functions[] )
-CREATE OR REPLACE FUNCTION functions_are ( NAME, NAME[] )
-RETURNS TEXT AS $$
-    SELECT functions_are( $1, $2, 'Schema ' || quote_ident($1) || ' should have the correct functions' );
-$$ LANGUAGE SQL;
-
--- functions_are( functions[], description )
-CREATE OR REPLACE FUNCTION functions_are ( NAME[], TEXT )
-RETURNS TEXT AS $$
-    SELECT _are(
-        'functions',
-        ARRAY(
-            SELECT name FROM tap_funky WHERE is_visible
-            AND schema NOT IN ('pg_catalog', 'information_schema')
-            EXCEPT
-            SELECT $1[i]
-              FROM generate_series(1, array_upper($1, 1)) s(i)
-        ),
-        ARRAY(
-            SELECT $1[i]
-               FROM generate_series(1, array_upper($1, 1)) s(i)
-            EXCEPT
-            SELECT name FROM tap_funky WHERE is_visible
-            AND schema NOT IN ('pg_catalog', 'information_schema')
-        ),
-        $2
-    );
-$$ LANGUAGE SQL;
-
--- functions_are( functions[] )
-CREATE OR REPLACE FUNCTION functions_are ( NAME[] )
-RETURNS TEXT AS $$
-    SELECT functions_are( $1, 'Search path ' || pg_catalog.current_setting('search_path') || ' should have the correct functions' );
-$$ LANGUAGE SQL;
-
--- indexes_are( schema, table, indexes[], description )
-CREATE OR REPLACE FUNCTION indexes_are( NAME, NAME, NAME[], TEXT )
-RETURNS TEXT AS $$
-    SELECT _are(
-        'indexes',
-        ARRAY(
-            SELECT ci.relname
-              FROM pg_catalog.pg_index x
-              JOIN pg_catalog.pg_class ct    ON ct.oid = x.indrelid
-              JOIN pg_catalog.pg_class ci    ON ci.oid = x.indexrelid
-              JOIN pg_catalog.pg_namespace n ON n.oid = ct.relnamespace
-             WHERE ct.relname = $2
-               AND n.nspname  = $1
-            EXCEPT
-            SELECT $3[i]
-              FROM generate_series(1, array_upper($3, 1)) s(i)
-        ),
-        ARRAY(
-            SELECT $3[i]
-              FROM generate_series(1, array_upper($3, 1)) s(i)
-            EXCEPT
-            SELECT ci.relname
-              FROM pg_catalog.pg_index x
-              JOIN pg_catalog.pg_class ct    ON ct.oid = x.indrelid
-              JOIN pg_catalog.pg_class ci    ON ci.oid = x.indexrelid
-              JOIN pg_catalog.pg_namespace n ON n.oid = ct.relnamespace
-             WHERE ct.relname = $2
-               AND n.nspname  = $1
-        ),
-        $4
-    );
-$$ LANGUAGE SQL;
-
--- indexes_are( schema, table, indexes[] )
-CREATE OR REPLACE FUNCTION indexes_are( NAME, NAME, NAME[] )
-RETURNS TEXT AS $$
-    SELECT indexes_are( $1, $2, $3, 'Table ' || quote_ident($1) || '.' || quote_ident($2) || ' should have the correct indexes' );
-$$ LANGUAGE SQL;
-
--- indexes_are( table, indexes[], description )
-CREATE OR REPLACE FUNCTION indexes_are( NAME, NAME[], TEXT )
-RETURNS TEXT AS $$
-    SELECT _are(
-        'indexes',
-        ARRAY(
-            SELECT ci.relname
-              FROM pg_catalog.pg_index x
-              JOIN pg_catalog.pg_class ct ON ct.oid = x.indrelid
-              JOIN pg_catalog.pg_class ci ON ci.oid = x.indexrelid
-              JOIN pg_catalog.pg_namespace n ON n.oid = ct.relnamespace
-             WHERE ct.relname = $1
-               AND pg_catalog.pg_table_is_visible(ct.oid)
-               AND n.nspname NOT IN ('pg_catalog', 'information_schema')
-            EXCEPT
-            SELECT $2[i]
-              FROM generate_series(1, array_upper($2, 1)) s(i)
-        ),
-        ARRAY(
-            SELECT $2[i]
-              FROM generate_series(1, array_upper($2, 1)) s(i)
-            EXCEPT
-            SELECT ci.relname
-              FROM pg_catalog.pg_index x
-              JOIN pg_catalog.pg_class ct ON ct.oid = x.indrelid
-              JOIN pg_catalog.pg_class ci ON ci.oid = x.indexrelid
-              JOIN pg_catalog.pg_namespace n ON n.oid = ct.relnamespace
-             WHERE ct.relname = $1
-               AND pg_catalog.pg_table_is_visible(ct.oid)
-               AND n.nspname NOT IN ('pg_catalog', 'information_schema')
-        ),
-        $3
-    );
-$$ LANGUAGE SQL;
-
--- indexes_are( table, indexes[] )
-CREATE OR REPLACE FUNCTION indexes_are( NAME, NAME[] )
-RETURNS TEXT AS $$
-    SELECT indexes_are( $1, $2, 'Table ' || quote_ident($1) || ' should have the correct indexes' );
-$$ LANGUAGE SQL;
-
--- users_are( users[], description )
-CREATE OR REPLACE FUNCTION users_are( NAME[], TEXT )
-RETURNS TEXT AS $$
-    SELECT _are(
-        'users',
-        ARRAY(
-            SELECT usename
-              FROM pg_catalog.pg_user
-            EXCEPT
-            SELECT $1[i]
-              FROM generate_series(1, array_upper($1, 1)) s(i)
-        ),
-        ARRAY(
-            SELECT $1[i]
-              FROM generate_series(1, array_upper($1, 1)) s(i)
-            EXCEPT
-            SELECT usename
-              FROM pg_catalog.pg_user
-        ),
-        $2
-    );
-$$ LANGUAGE SQL;
-
--- users_are( users[] )
-CREATE OR REPLACE FUNCTION users_are( NAME[] )
-RETURNS TEXT AS $$
-    SELECT users_are( $1, 'There should be the correct users' );
-$$ LANGUAGE SQL;
-
--- groups_are( groups[], description )
-CREATE OR REPLACE FUNCTION groups_are( NAME[], TEXT )
-RETURNS TEXT AS $$
-    SELECT _are(
-        'groups',
-        ARRAY(
-            SELECT groname
-              FROM pg_catalog.pg_group
-            EXCEPT
-            SELECT $1[i]
-              FROM generate_series(1, array_upper($1, 1)) s(i)
-        ),
-        ARRAY(
-            SELECT $1[i]
-              FROM generate_series(1, array_upper($1, 1)) s(i)
-            EXCEPT
-            SELECT groname
-              FROM pg_catalog.pg_group
-        ),
-        $2
-    );
-$$ LANGUAGE SQL;
-
--- groups_are( groups[] )
-CREATE OR REPLACE FUNCTION groups_are( NAME[] )
-RETURNS TEXT AS $$
-    SELECT groups_are( $1, 'There should be the correct groups' );
-$$ LANGUAGE SQL;
-
--- languages_are( languages[], description )
-CREATE OR REPLACE FUNCTION languages_are( NAME[], TEXT )
-RETURNS TEXT AS $$
-    SELECT _are(
-        'languages',
-        ARRAY(
-            SELECT lanname
-              FROM pg_catalog.pg_language
-             WHERE lanispl
-            EXCEPT
-            SELECT $1[i]
-              FROM generate_series(1, array_upper($1, 1)) s(i)
-        ),
-        ARRAY(
-            SELECT $1[i]
-              FROM generate_series(1, array_upper($1, 1)) s(i)
-            EXCEPT
-            SELECT lanname
-              FROM pg_catalog.pg_language
-             WHERE lanispl
-        ),
-        $2
-    );
-$$ LANGUAGE SQL;
-
--- languages_are( languages[] )
-CREATE OR REPLACE FUNCTION languages_are( NAME[] )
-RETURNS TEXT AS $$
-    SELECT languages_are( $1, 'There should be the correct procedural languages' );
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION _is_trusted( NAME )
-RETURNS BOOLEAN AS $$
-    SELECT lanpltrusted FROM pg_catalog.pg_language WHERE lanname = $1;
-$$ LANGUAGE SQL;
-
--- has_language( language, description)
-CREATE OR REPLACE FUNCTION has_language( NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT ok( _is_trusted($1) IS NOT NULL, $2 );
-$$ LANGUAGE SQL;
-
--- has_language( language )
-CREATE OR REPLACE FUNCTION has_language( NAME )
-RETURNS TEXT AS $$
-    SELECT ok( _is_trusted($1) IS NOT NULL, 'Procedural language ' || quote_ident($1) || ' should exist' );
-$$ LANGUAGE SQL;
-
--- hasnt_language( language, description)
-CREATE OR REPLACE FUNCTION hasnt_language( NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT ok( _is_trusted($1) IS NULL, $2 );
-$$ LANGUAGE SQL;
-
--- hasnt_language( language )
-CREATE OR REPLACE FUNCTION hasnt_language( NAME )
-RETURNS TEXT AS $$
-    SELECT ok( _is_trusted($1) IS NULL, 'Procedural language ' || quote_ident($1) || ' should not exist' );
-$$ LANGUAGE SQL;
-
--- language_is_trusted( language, description )
-CREATE OR REPLACE FUNCTION language_is_trusted( NAME, TEXT )
-RETURNS TEXT AS $$
-DECLARE
-    is_trusted boolean := _is_trusted($1);
-BEGIN
-    IF is_trusted IS NULL THEN
-        RETURN fail( $2 ) || E'\n' || diag( '    Procedural language ' || quote_ident($1) || ' does not exist') ;
-    END IF;
-    RETURN ok( is_trusted, $2 );
-END;
-$$ LANGUAGE plpgsql;
-
--- language_is_trusted( language )
-CREATE OR REPLACE FUNCTION language_is_trusted( NAME )
-RETURNS TEXT AS $$
-    SELECT language_is_trusted($1, 'Procedural language ' || quote_ident($1) || ' should be trusted' );
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION _opc_exists( NAME, NAME )
-RETURNS BOOLEAN AS $$
-    SELECT EXISTS (
-        SELECT TRUE
-          FROM pg_catalog.pg_opclass oc
-          JOIN pg_catalog.pg_namespace n ON oc.opcnamespace = n.oid
-         WHERE n.nspname  = COALESCE($1, n.nspname)
-           AND oc.opcname = $2
-    );
-$$ LANGUAGE SQL;
-
--- has_opclass( schema, name, description )
-CREATE OR REPLACE FUNCTION has_opclass( NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT ok( _opc_exists( $1, $2 ), $3 );
-$$ LANGUAGE SQL;
-
--- has_opclass( schema, name )
-CREATE OR REPLACE FUNCTION has_opclass( NAME, NAME )
-RETURNS TEXT AS $$
-    SELECT ok( _opc_exists( $1, $2 ), 'Operator class ' || quote_ident($1) || '.' || quote_ident($2) || ' should exist' );
-$$ LANGUAGE SQL;
-
--- has_opclass( name, description )
-CREATE OR REPLACE FUNCTION has_opclass( NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT ok( _opc_exists( NULL, $1 ), $2)
-$$ LANGUAGE SQL;
-
--- has_opclass( name )
-CREATE OR REPLACE FUNCTION has_opclass( NAME )
-RETURNS TEXT AS $$
-    SELECT ok( _opc_exists( NULL, $1 ), 'Operator class ' || quote_ident($1) || ' should exist' );
-$$ LANGUAGE SQL;
-
--- hasnt_opclass( schema, name, description )
-CREATE OR REPLACE FUNCTION hasnt_opclass( NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT ok( NOT _opc_exists( $1, $2 ), $3 );
-$$ LANGUAGE SQL;
-
--- hasnt_opclass( schema, name )
-CREATE OR REPLACE FUNCTION hasnt_opclass( NAME, NAME )
-RETURNS TEXT AS $$
-    SELECT ok( NOT _opc_exists( $1, $2 ), 'Operator class ' || quote_ident($1) || '.' || quote_ident($2) || ' should exist' );
-$$ LANGUAGE SQL;
-
--- hasnt_opclass( name, description )
-CREATE OR REPLACE FUNCTION hasnt_opclass( NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT ok( NOT _opc_exists( NULL, $1 ), $2)
-$$ LANGUAGE SQL;
-
--- hasnt_opclass( name )
-CREATE OR REPLACE FUNCTION hasnt_opclass( NAME )
-RETURNS TEXT AS $$
-    SELECT ok( NOT _opc_exists( NULL, $1 ), 'Operator class ' || quote_ident($1) || ' should exist' );
-$$ LANGUAGE SQL;
-
--- opclasses_are( schema, opclasses[], description )
-CREATE OR REPLACE FUNCTION opclasses_are ( NAME, NAME[], TEXT )
-RETURNS TEXT AS $$
-    SELECT _are(
-        'operator classes',
-        ARRAY(
-            SELECT oc.opcname
-              FROM pg_catalog.pg_opclass oc
-              JOIN pg_catalog.pg_namespace n ON oc.opcnamespace = n.oid
-             WHERE n.nspname  = $1
-            EXCEPT
-            SELECT $2[i]
-              FROM generate_series(1, array_upper($2, 1)) s(i)
-        ),
-        ARRAY(
-            SELECT $2[i]
-               FROM generate_series(1, array_upper($2, 1)) s(i)
-            EXCEPT
-            SELECT oc.opcname
-              FROM pg_catalog.pg_opclass oc
-              JOIN pg_catalog.pg_namespace n ON oc.opcnamespace = n.oid
-             WHERE n.nspname  = $1
-        ),
-        $3
-    );
-$$ LANGUAGE SQL;
-
--- opclasses_are( schema, opclasses[] )
-CREATE OR REPLACE FUNCTION opclasses_are ( NAME, NAME[] )
-RETURNS TEXT AS $$
-    SELECT opclasses_are( $1, $2, 'Schema ' || quote_ident($1) || ' should have the correct operator classes' );
-$$ LANGUAGE SQL;
-
--- opclasses_are( opclasses[], description )
-CREATE OR REPLACE FUNCTION opclasses_are ( NAME[], TEXT )
-RETURNS TEXT AS $$
-    SELECT _are(
-        'operator classes',
-        ARRAY(
-            SELECT oc.opcname
-              FROM pg_catalog.pg_opclass oc
-              JOIN pg_catalog.pg_namespace n ON oc.opcnamespace = n.oid
-               AND n.nspname NOT IN ('pg_catalog', 'information_schema')
-               AND pg_catalog.pg_opclass_is_visible(oc.oid)
-            EXCEPT
-            SELECT $1[i]
-              FROM generate_series(1, array_upper($1, 1)) s(i)
-        ),
-        ARRAY(
-            SELECT $1[i]
-               FROM generate_series(1, array_upper($1, 1)) s(i)
-            EXCEPT
-            SELECT oc.opcname
-              FROM pg_catalog.pg_opclass oc
-              JOIN pg_catalog.pg_namespace n ON oc.opcnamespace = n.oid
-               AND n.nspname NOT IN ('pg_catalog', 'information_schema')
-               AND pg_catalog.pg_opclass_is_visible(oc.oid)
-        ),
-        $2
-    );
-$$ LANGUAGE SQL;
-
--- opclasses_are( opclasses[] )
-CREATE OR REPLACE FUNCTION opclasses_are ( NAME[] )
-RETURNS TEXT AS $$
-    SELECT opclasses_are( $1, 'Search path ' || pg_catalog.current_setting('search_path') || ' should have the correct operator classes' );
-$$ LANGUAGE SQL;
-
--- rules_are( schema, table, rules[], description )
-CREATE OR REPLACE FUNCTION rules_are( NAME, NAME, NAME[], TEXT )
-RETURNS TEXT AS $$
-    SELECT _are(
-        'rules',
-        ARRAY(
-            SELECT r.rulename
-              FROM pg_catalog.pg_rewrite r
-              JOIN pg_catalog.pg_class c     ON c.oid = r.ev_class
-              JOIN pg_catalog.pg_namespace n ON c.relnamespace = n.oid
-             WHERE c.relname = $2
-               AND n.nspname = $1
-            EXCEPT
-            SELECT $3[i]
-              FROM generate_series(1, array_upper($3, 1)) s(i)
-        ),
-        ARRAY(
-            SELECT $3[i]
-              FROM generate_series(1, array_upper($3, 1)) s(i)
-            EXCEPT
-            SELECT r.rulename
-              FROM pg_catalog.pg_rewrite r
-              JOIN pg_catalog.pg_class c     ON c.oid = r.ev_class
-              JOIN pg_catalog.pg_namespace n ON c.relnamespace = n.oid
-             WHERE c.relname = $2
-               AND n.nspname = $1
-        ),
-        $4
-    );
-$$ LANGUAGE SQL;
-
--- rules_are( schema, table, rules[] )
-CREATE OR REPLACE FUNCTION rules_are( NAME, NAME, NAME[] )
-RETURNS TEXT AS $$
-    SELECT rules_are( $1, $2, $3, 'Relation ' || quote_ident($1) || '.' || quote_ident($2) || ' should have the correct rules' );
-$$ LANGUAGE SQL;
-
--- rules_are( table, rules[], description )
-CREATE OR REPLACE FUNCTION rules_are( NAME, NAME[], TEXT )
-RETURNS TEXT AS $$
-    SELECT _are(
-        'rules',
-        ARRAY(
-            SELECT r.rulename
-              FROM pg_catalog.pg_rewrite r
-              JOIN pg_catalog.pg_class c     ON c.oid = r.ev_class
-              JOIN pg_catalog.pg_namespace n ON c.relnamespace = n.oid
-             WHERE c.relname = $1
-               AND n.nspname NOT IN ('pg_catalog', 'information_schema')
-               AND pg_catalog.pg_table_is_visible(c.oid)
-            EXCEPT
-            SELECT $2[i]
-              FROM generate_series(1, array_upper($2, 1)) s(i)
-        ),
-        ARRAY(
-            SELECT $2[i]
-              FROM generate_series(1, array_upper($2, 1)) s(i)
-            EXCEPT
-            SELECT r.rulename
-              FROM pg_catalog.pg_rewrite r
-              JOIN pg_catalog.pg_class c     ON c.oid = r.ev_class
-              JOIN pg_catalog.pg_namespace n ON c.relnamespace = n.oid
-               AND c.relname = $1
-               AND n.nspname NOT IN ('pg_catalog', 'information_schema')
-               AND pg_catalog.pg_table_is_visible(c.oid)
-        ),
-        $3
-    );
-$$ LANGUAGE SQL;
-
--- rules_are( table, rules[] )
-CREATE OR REPLACE FUNCTION rules_are( NAME, NAME[] )
-RETURNS TEXT AS $$
-    SELECT rules_are( $1, $2, 'Relation ' || quote_ident($1) || ' should have the correct rules' );
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION _is_instead( NAME, NAME, NAME )
-RETURNS BOOLEAN AS $$
-    SELECT r.is_instead
-      FROM pg_catalog.pg_rewrite r
-      JOIN pg_catalog.pg_class c     ON c.oid = r.ev_class
-      JOIN pg_catalog.pg_namespace n ON c.relnamespace = n.oid
-     WHERE r.rulename = $3
-       AND c.relname  = $2
-       AND n.nspname  = $1
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION _is_instead( NAME, NAME )
-RETURNS BOOLEAN AS $$
-    SELECT r.is_instead
-      FROM pg_catalog.pg_rewrite r
-      JOIN pg_catalog.pg_class c     ON c.oid = r.ev_class
-     WHERE r.rulename = $2
-       AND c.relname  = $1
-       AND pg_catalog.pg_table_is_visible(c.oid)
-$$ LANGUAGE SQL;
-
--- has_rule( schema, table, rule, description )
-CREATE OR REPLACE FUNCTION has_rule( NAME, NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT ok( _is_instead($1, $2, $3) IS NOT NULL, $4 );
-$$ LANGUAGE SQL;
-
--- has_rule( schema, table, rule )
-CREATE OR REPLACE FUNCTION has_rule( NAME, NAME, NAME )
-RETURNS TEXT AS $$
-    SELECT ok( _is_instead($1, $2, $3) IS NOT NULL, 'Relation ' || quote_ident($1) || '.' || quote_ident($2) || ' should have rule ' || quote_ident($3) );
-$$ LANGUAGE SQL;
-
--- has_rule( table, rule, description )
-CREATE OR REPLACE FUNCTION has_rule( NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT ok( _is_instead($1, $2) IS NOT NULL, $3 );
-$$ LANGUAGE SQL;
-
--- has_rule( table, rule )
-CREATE OR REPLACE FUNCTION has_rule( NAME, NAME )
-RETURNS TEXT AS $$
-    SELECT ok( _is_instead($1, $2) IS NOT NULL, 'Relation ' || quote_ident($1) || ' should have rule ' || quote_ident($2) );
-$$ LANGUAGE SQL;
-
--- hasnt_rule( schema, table, rule, description )
-CREATE OR REPLACE FUNCTION hasnt_rule( NAME, NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT ok( _is_instead($1, $2, $3) IS NULL, $4 );
-$$ LANGUAGE SQL;
-
--- hasnt_rule( schema, table, rule )
-CREATE OR REPLACE FUNCTION hasnt_rule( NAME, NAME, NAME )
-RETURNS TEXT AS $$
-    SELECT ok( _is_instead($1, $2, $3) IS NULL, 'Relation ' || quote_ident($1) || '.' || quote_ident($2) || ' should not have rule ' || quote_ident($3) );
-$$ LANGUAGE SQL;
-
--- hasnt_rule( table, rule, description )
-CREATE OR REPLACE FUNCTION hasnt_rule( NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT ok( _is_instead($1, $2) IS NULL, $3 );
-$$ LANGUAGE SQL;
-
--- hasnt_rule( table, rule )
-CREATE OR REPLACE FUNCTION hasnt_rule( NAME, NAME )
-RETURNS TEXT AS $$
-    SELECT ok( _is_instead($1, $2) IS NULL, 'Relation ' || quote_ident($1) || ' should not have rule ' || quote_ident($2) );
-$$ LANGUAGE SQL;
-
--- rule_is_instead( schema, table, rule, description )
-CREATE OR REPLACE FUNCTION rule_is_instead( NAME, NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-DECLARE
-    is_it boolean := _is_instead($1, $2, $3);
-BEGIN
-    IF is_it IS NOT NULL THEN RETURN ok( is_it, $4 ); END IF;
-    RETURN ok( FALSE, $4 ) || E'\n' || diag(
-        '    Rule ' || quote_ident($3) || ' does not exist'
-    );
-END;
-$$ LANGUAGE plpgsql;
-
--- rule_is_instead( schema, table, rule )
-CREATE OR REPLACE FUNCTION rule_is_instead( NAME, NAME, NAME )
-RETURNS TEXT AS $$
-    SELECT rule_is_instead( $1, $2, $3, 'Rule ' || quote_ident($3) || ' on relation ' || quote_ident($1) || '.' || quote_ident($2) || ' should be an INSTEAD rule' );
-$$ LANGUAGE SQL;
-
--- rule_is_instead( table, rule, description )
-CREATE OR REPLACE FUNCTION rule_is_instead( NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-DECLARE
-    is_it boolean := _is_instead($1, $2);
-BEGIN
-    IF is_it IS NOT NULL THEN RETURN ok( is_it, $3 ); END IF;
-    RETURN ok( FALSE, $3 ) || E'\n' || diag(
-        '    Rule ' || quote_ident($2) || ' does not exist'
-    );
-END;
-$$ LANGUAGE plpgsql;
-
--- rule_is_instead( table, rule )
-CREATE OR REPLACE FUNCTION rule_is_instead( NAME, NAME )
-RETURNS TEXT AS $$
-    SELECT rule_is_instead($1, $2, 'Rule ' || quote_ident($2) || ' on relation ' || quote_ident($1) || ' should be an INSTEAD rule' );
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION _expand_on( char )
-RETURNS text AS $$
-   SELECT CASE $1
-          WHEN '1' THEN 'SELECT'
-          WHEN '2' THEN 'UPDATE'
-          WHEN '3' THEN 'INSERT'
-          WHEN '4' THEN 'DELETE'
-          ELSE          'UNKNOWN' END
-$$ LANGUAGE SQL IMMUTABLE;
-
-CREATE OR REPLACE FUNCTION _contract_on( TEXT )
-RETURNS "char" AS $$
-   SELECT CASE substring(LOWER($1) FROM 1 FOR 1)
-          WHEN 's' THEN '1'::"char"
-          WHEN 'u' THEN '2'::"char"
-          WHEN 'i' THEN '3'::"char"
-          WHEN 'd' THEN '4'::"char"
-          ELSE          '0'::"char" END
-$$ LANGUAGE SQL IMMUTABLE;
-
-CREATE OR REPLACE FUNCTION _rule_on( NAME, NAME, NAME )
-RETURNS "char" AS $$
-    SELECT r.ev_type
-      FROM pg_catalog.pg_rewrite r
-      JOIN pg_catalog.pg_class c     ON c.oid = r.ev_class
-      JOIN pg_catalog.pg_namespace n ON c.relnamespace = n.oid
-     WHERE r.rulename = $3
-       AND c.relname  = $2
-       AND n.nspname  = $1
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION _rule_on( NAME, NAME )
-RETURNS "char" AS $$
-    SELECT r.ev_type
-      FROM pg_catalog.pg_rewrite r
-      JOIN pg_catalog.pg_class c     ON c.oid = r.ev_class
-     WHERE r.rulename = $2
-       AND c.relname  = $1
-$$ LANGUAGE SQL;
-
--- rule_is_on( schema, table, rule, event, description )
-CREATE OR REPLACE FUNCTION rule_is_on( NAME, NAME, NAME, TEXT, TEXT )
-RETURNS TEXT AS $$
-DECLARE
-    want char := _contract_on($4);
-    have char := _rule_on($1, $2, $3);
-BEGIN
-    IF have IS NOT NULL THEN
-        RETURN is( _expand_on(have), _expand_on(want), $5 );
-    END IF;
-
-    RETURN ok( false, $5 ) || E'\n' || diag(
-        '    Rule ' || quote_ident($3) || ' does not exist on '
-        || quote_ident($1) || '.' || quote_ident($2)
-    );
-END;
-$$ LANGUAGE plpgsql;
-
--- rule_is_on( schema, table, rule, event )
-CREATE OR REPLACE FUNCTION rule_is_on( NAME, NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT rule_is_on(
-        $1, $2, $3, $4,
-        'Rule ' || quote_ident($3) || ' should be on ' || _expand_on(_contract_on($4)::char)
-        || ' to ' || quote_ident($1) || '.' || quote_ident($2)
-    );
-$$ LANGUAGE SQL;
-
--- rule_is_on( table, rule, event, description )
-CREATE OR REPLACE FUNCTION rule_is_on( NAME, NAME, TEXT, TEXT )
-RETURNS TEXT AS $$
-DECLARE
-    want char := _contract_on($3);
-    have char := _rule_on($1, $2);
-BEGIN
-    IF have IS NOT NULL THEN
-        RETURN is( _expand_on(have), _expand_on(want), $4 );
-    END IF;
-
-    RETURN ok( false, $4 ) || E'\n' || diag(
-        '    Rule ' || quote_ident($2) || ' does not exist on '
-        || quote_ident($1)
-    );
-END;
-$$ LANGUAGE plpgsql;
-
--- rule_is_on( table, rule, event )
-CREATE OR REPLACE FUNCTION rule_is_on( NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT rule_is_on(
-        $1, $2, $3,
-        'Rule ' || quote_ident($2) || ' should be on '
-        || _expand_on(_contract_on($3)::char) || ' to ' || quote_ident($1)
-    );
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION _nosuch( NAME, NAME, NAME[])
-RETURNS TEXT AS $$
-    SELECT E'\n' || diag(
-        '    Function '
-          || CASE WHEN $1 IS NOT NULL THEN quote_ident($1) || '.' ELSE '' END
-          || quote_ident($2) || '('
-          || array_to_string($3, ', ') || ') does not exist'
-    );
-$$ LANGUAGE SQL IMMUTABLE;
-
-CREATE OR REPLACE FUNCTION _func_compare( NAME, NAME, NAME[], anyelement, anyelement, TEXT)
-RETURNS TEXT AS $$
-    SELECT CASE WHEN $4 IS NULL
-      THEN ok( FALSE, $6 ) || _nosuch($1, $2, $3)
-      ELSE is( $4, $5, $6 )
-      END;
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION _func_compare( NAME, NAME, NAME[], boolean, TEXT)
-RETURNS TEXT AS $$
-    SELECT CASE WHEN $4 IS NULL
-      THEN ok( FALSE, $5 ) || _nosuch($1, $2, $3)
-      ELSE ok( $4, $5 )
-      END;
-$$ LANGUAGE sql;
-
-CREATE OR REPLACE FUNCTION _func_compare( NAME, NAME, anyelement, anyelement, TEXT)
-RETURNS TEXT AS $$
-    SELECT CASE WHEN $3 IS NULL
-      THEN ok( FALSE, $5 ) || _nosuch($1, $2, '{}')
-      ELSE is( $3, $4, $5 )
-      END;
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION _func_compare( NAME, NAME, boolean, TEXT)
-RETURNS TEXT AS $$
-    SELECT CASE WHEN $3 IS NULL
-      THEN ok( FALSE, $4 ) || _nosuch($1, $2, '{}')
-      ELSE ok( $3, $4 )
-      END;
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION _lang ( NAME, NAME, NAME[] )
-RETURNS NAME AS $$
-    SELECT l.lanname
-      FROM tap_funky f
-      JOIN pg_catalog.pg_language l ON f.langoid = l.oid
-     WHERE f.schema = $1
-       and f.name   = $2
-       AND f.args   = array_to_string($3, ',')
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION _lang ( NAME, NAME )
-RETURNS NAME AS $$
-    SELECT l.lanname
-      FROM tap_funky f
-      JOIN pg_catalog.pg_language l ON f.langoid = l.oid
-     WHERE f.schema = $1
-       and f.name   = $2
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION _lang ( NAME, NAME[] )
-RETURNS NAME AS $$
-    SELECT l.lanname
-      FROM tap_funky f
-      JOIN pg_catalog.pg_language l ON f.langoid = l.oid
-     WHERE f.name = $1
-       AND f.args = array_to_string($2, ',')
-       AND f.is_visible;
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION _lang ( NAME )
-RETURNS NAME AS $$
-    SELECT l.lanname
-      FROM tap_funky f
-      JOIN pg_catalog.pg_language l ON f.langoid = l.oid
-     WHERE f.name = $1
-       AND f.is_visible;
-$$ LANGUAGE SQL;
-
--- function_lang_is( schema, function, args[], language, description )
-CREATE OR REPLACE FUNCTION function_lang_is( NAME, NAME, NAME[], NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT _func_compare($1, $2, $3, _lang($1, $2, $3), $4, $5 );
-$$ LANGUAGE SQL;
-
--- function_lang_is( schema, function, args[], language )
-CREATE OR REPLACE FUNCTION function_lang_is( NAME, NAME, NAME[], NAME )
-RETURNS TEXT AS $$
-    SELECT function_lang_is(
-        $1, $2, $3, $4,
-        'Function ' || quote_ident($1) || '.' || quote_ident($2) || '(' ||
-        array_to_string($3, ', ') || ') should be written in ' || quote_ident($4)
-    );
-$$ LANGUAGE SQL;
-
--- function_lang_is( schema, function, language, description )
-CREATE OR REPLACE FUNCTION function_lang_is( NAME, NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT _func_compare($1, $2, _lang($1, $2), $3, $4 );
-$$ LANGUAGE SQL;
-
--- function_lang_is( schema, function, language )
-CREATE OR REPLACE FUNCTION function_lang_is( NAME, NAME, NAME )
-RETURNS TEXT AS $$
-    SELECT function_lang_is(
-        $1, $2, $3,
-        'Function ' || quote_ident($1) || '.' || quote_ident($2)
-        || '() should be written in ' || quote_ident($3)
-    );
-$$ LANGUAGE SQL;
-
--- function_lang_is( function, args[], language, description )
-CREATE OR REPLACE FUNCTION function_lang_is( NAME, NAME[], NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT _func_compare(NULL, $1, $2, _lang($1, $2), $3, $4 );
-$$ LANGUAGE SQL;
-
--- function_lang_is( function, args[], language )
-CREATE OR REPLACE FUNCTION function_lang_is( NAME, NAME[], NAME )
-RETURNS TEXT AS $$
-    SELECT function_lang_is(
-        $1, $2, $3,
-        'Function ' || quote_ident($1) || '(' ||
-        array_to_string($2, ', ') || ') should be written in ' || quote_ident($3)
-    );
-$$ LANGUAGE SQL;
-
--- function_lang_is( function, language, description )
-CREATE OR REPLACE FUNCTION function_lang_is( NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT _func_compare(NULL, $1, _lang($1), $2, $3 );
-$$ LANGUAGE SQL;
-
--- function_lang_is( function, language )
-CREATE OR REPLACE FUNCTION function_lang_is( NAME, NAME )
-RETURNS TEXT AS $$
-    SELECT function_lang_is(
-        $1, $2,
-        'Function ' || quote_ident($1)
-        || '() should be written in ' || quote_ident($2)
-    );
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION _returns ( NAME, NAME, NAME[] )
-RETURNS TEXT AS $$
-    SELECT returns
-      FROM tap_funky
-     WHERE schema = $1
-       AND name   = $2
-       AND args   = array_to_string($3, ',')
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION _returns ( NAME, NAME )
-RETURNS TEXT AS $$
-    SELECT returns FROM tap_funky WHERE schema = $1 AND name = $2
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION _returns ( NAME, NAME[] )
-RETURNS TEXT AS $$
-    SELECT returns
-      FROM tap_funky
-     WHERE name = $1
-       AND args = array_to_string($2, ',')
-       AND is_visible;
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION _returns ( NAME )
-RETURNS TEXT AS $$
-    SELECT returns FROM tap_funky WHERE name = $1 AND is_visible;
-$$ LANGUAGE SQL;
-
--- function_returns( schema, function, args[], type, description )
-CREATE OR REPLACE FUNCTION function_returns( NAME, NAME, NAME[], TEXT, TEXT )
-RETURNS TEXT AS $$
-    SELECT _func_compare($1, $2, $3, _returns($1, $2, $3), $4, $5 );
-$$ LANGUAGE SQL;
-
--- function_returns( schema, function, args[], type )
-CREATE OR REPLACE FUNCTION function_returns( NAME, NAME, NAME[], TEXT )
-RETURNS TEXT AS $$
-    SELECT function_returns(
-        $1, $2, $3, $4,
-        'Function ' || quote_ident($1) || '.' || quote_ident($2) || '(' ||
-        array_to_string($3, ', ') || ') should return ' || $4
-    );
-$$ LANGUAGE SQL;
-
--- function_returns( schema, function, type, description )
-CREATE OR REPLACE FUNCTION function_returns( NAME, NAME, TEXT, TEXT )
-RETURNS TEXT AS $$
-    SELECT _func_compare($1, $2, _returns($1, $2), $3, $4 );
-$$ LANGUAGE SQL;
-
--- function_returns( schema, function, type )
-CREATE OR REPLACE FUNCTION function_returns( NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT function_returns(
-        $1, $2, $3,
-        'Function ' || quote_ident($1) || '.' || quote_ident($2)
-        || '() should return ' || $3
-    );
-$$ LANGUAGE SQL;
-
--- function_returns( function, args[], type, description )
-CREATE OR REPLACE FUNCTION function_returns( NAME, NAME[], TEXT, TEXT )
-RETURNS TEXT AS $$
-    SELECT _func_compare(NULL, $1, $2, _returns($1, $2), $3, $4 );
-$$ LANGUAGE SQL;
-
--- function_returns( function, args[], type )
-CREATE OR REPLACE FUNCTION function_returns( NAME, NAME[], TEXT )
-RETURNS TEXT AS $$
-    SELECT function_returns(
-        $1, $2, $3,
-        'Function ' || quote_ident($1) || '(' ||
-        array_to_string($2, ', ') || ') should return ' || $3
-    );
-$$ LANGUAGE SQL;
-
--- function_returns( function, type, description )
-CREATE OR REPLACE FUNCTION function_returns( NAME, TEXT, TEXT )
-RETURNS TEXT AS $$
-    SELECT _func_compare(NULL, $1, _returns($1), $2, $3 );
-$$ LANGUAGE SQL;
-
--- function_returns( function, type )
-CREATE OR REPLACE FUNCTION function_returns( NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT function_returns(
-        $1, $2,
-        'Function ' || quote_ident($1) || '() should return ' || $2
-    );
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION _definer ( NAME, NAME, NAME[] )
-RETURNS BOOLEAN AS $$
-    SELECT is_definer
-      FROM tap_funky
-     WHERE schema = $1
-       AND name   = $2
-       AND args   = array_to_string($3, ',')
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION _definer ( NAME, NAME )
-RETURNS BOOLEAN AS $$
-    SELECT is_definer FROM tap_funky WHERE schema = $1 AND name = $2
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION _definer ( NAME, NAME[] )
-RETURNS BOOLEAN AS $$
-    SELECT is_definer
-      FROM tap_funky
-     WHERE name = $1
-       AND args = array_to_string($2, ',')
-       AND is_visible;
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION _definer ( NAME )
-RETURNS BOOLEAN AS $$
-    SELECT is_definer FROM tap_funky WHERE name = $1 AND is_visible;
-$$ LANGUAGE SQL;
-
--- is_definer( schema, function, args[], description )
-CREATE OR REPLACE FUNCTION is_definer ( NAME, NAME, NAME[], TEXT )
-RETURNS TEXT AS $$
-    SELECT _func_compare($1, $2, $3, _definer($1, $2, $3), $4 );
-$$ LANGUAGE SQL;
-
--- is_definer( schema, function, args[] )
-CREATE OR REPLACE FUNCTION is_definer( NAME, NAME, NAME[] )
-RETURNS TEXT AS $$
-    SELECT ok(
-        _definer($1, $2, $3),
-        'Function ' || quote_ident($1) || '.' || quote_ident($2) || '(' ||
-        array_to_string($3, ', ') || ') should be security definer'
-    );
-$$ LANGUAGE sql;
-
--- is_definer( schema, function, description )
-CREATE OR REPLACE FUNCTION is_definer ( NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT _func_compare($1, $2, _definer($1, $2), $3 );
-$$ LANGUAGE SQL;
-
--- is_definer( schema, function )
-CREATE OR REPLACE FUNCTION is_definer( NAME, NAME )
-RETURNS TEXT AS $$
-    SELECT ok(
-        _definer($1, $2),
-        'Function ' || quote_ident($1) || '.' || quote_ident($2) || '() should be security definer'
-    );
-$$ LANGUAGE sql;
-
--- is_definer( function, args[], description )
-CREATE OR REPLACE FUNCTION is_definer ( NAME, NAME[], TEXT )
-RETURNS TEXT AS $$
-    SELECT _func_compare(NULL, $1, $2, _definer($1, $2), $3 );
-$$ LANGUAGE SQL;
-
--- is_definer( function, args[] )
-CREATE OR REPLACE FUNCTION is_definer( NAME, NAME[] )
-RETURNS TEXT AS $$
-    SELECT ok(
-        _definer($1, $2),
-        'Function ' || quote_ident($1) || '(' ||
-        array_to_string($2, ', ') || ') should be security definer'
-    );
-$$ LANGUAGE sql;
-
--- is_definer( function, description )
-CREATE OR REPLACE FUNCTION is_definer( NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT _func_compare(NULL, $1, _definer($1), $2 );
-$$ LANGUAGE sql;
-
--- is_definer( function )
-CREATE OR REPLACE FUNCTION is_definer( NAME )
-RETURNS TEXT AS $$
-    SELECT ok( _definer($1), 'Function ' || quote_ident($1) || '() should be security definer' );
-$$ LANGUAGE sql;
-
-CREATE OR REPLACE FUNCTION _agg ( NAME, NAME, NAME[] )
-RETURNS BOOLEAN AS $$
-    SELECT is_agg
-      FROM tap_funky
-     WHERE schema = $1
-       AND name   = $2
-       AND args   = array_to_string($3, ',')
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION _agg ( NAME, NAME )
-RETURNS BOOLEAN AS $$
-    SELECT is_agg FROM tap_funky WHERE schema = $1 AND name = $2
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION _agg ( NAME, NAME[] )
-RETURNS BOOLEAN AS $$
-    SELECT is_agg
-      FROM tap_funky
-     WHERE name = $1
-       AND args = array_to_string($2, ',')
-       AND is_visible;
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION _agg ( NAME )
-RETURNS BOOLEAN AS $$
-    SELECT is_agg FROM tap_funky WHERE name = $1 AND is_visible;
-$$ LANGUAGE SQL;
-
--- is_aggregate( schema, function, args[], description )
-CREATE OR REPLACE FUNCTION is_aggregate ( NAME, NAME, NAME[], TEXT )
-RETURNS TEXT AS $$
-    SELECT _func_compare($1, $2, $3, _agg($1, $2, $3), $4 );
-$$ LANGUAGE SQL;
-
--- is_aggregate( schema, function, args[] )
-CREATE OR REPLACE FUNCTION is_aggregate( NAME, NAME, NAME[] )
-RETURNS TEXT AS $$
-    SELECT ok(
-        _agg($1, $2, $3),
-        'Function ' || quote_ident($1) || '.' || quote_ident($2) || '(' ||
-        array_to_string($3, ', ') || ') should be an aggregate function'
-    );
-$$ LANGUAGE sql;
-
--- is_aggregate( schema, function, description )
-CREATE OR REPLACE FUNCTION is_aggregate ( NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT _func_compare($1, $2, _agg($1, $2), $3 );
-$$ LANGUAGE SQL;
-
--- is_aggregate( schema, function )
-CREATE OR REPLACE FUNCTION is_aggregate( NAME, NAME )
-RETURNS TEXT AS $$
-    SELECT ok(
-        _agg($1, $2),
-        'Function ' || quote_ident($1) || '.' || quote_ident($2) || '() should be an aggregate function'
-    );
-$$ LANGUAGE sql;
-
--- is_aggregate( function, args[], description )
-CREATE OR REPLACE FUNCTION is_aggregate ( NAME, NAME[], TEXT )
-RETURNS TEXT AS $$
-    SELECT _func_compare(NULL, $1, $2, _agg($1, $2), $3 );
-$$ LANGUAGE SQL;
-
--- is_aggregate( function, args[] )
-CREATE OR REPLACE FUNCTION is_aggregate( NAME, NAME[] )
-RETURNS TEXT AS $$
-    SELECT ok(
-        _agg($1, $2),
-        'Function ' || quote_ident($1) || '(' ||
-        array_to_string($2, ', ') || ') should be an aggregate function'
-    );
-$$ LANGUAGE sql;
-
--- is_aggregate( function, description )
-CREATE OR REPLACE FUNCTION is_aggregate( NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT _func_compare(NULL, $1, _agg($1), $2 );
-$$ LANGUAGE sql;
-
--- is_aggregate( function )
-CREATE OR REPLACE FUNCTION is_aggregate( NAME )
-RETURNS TEXT AS $$
-    SELECT ok( _agg($1), 'Function ' || quote_ident($1) || '() should be an aggregate function' );
-$$ LANGUAGE sql;
-
-CREATE OR REPLACE FUNCTION _strict ( NAME, NAME, NAME[] )
-RETURNS BOOLEAN AS $$
-    SELECT is_strict
-      FROM tap_funky
-     WHERE schema = $1
-       AND name   = $2
-       AND args   = array_to_string($3, ',')
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION _strict ( NAME, NAME )
-RETURNS BOOLEAN AS $$
-    SELECT is_strict FROM tap_funky WHERE schema = $1 AND name = $2
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION _strict ( NAME, NAME[] )
-RETURNS BOOLEAN AS $$
-    SELECT is_strict
-      FROM tap_funky
-     WHERE name = $1
-       AND args = array_to_string($2, ',')
-       AND is_visible;
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION _strict ( NAME )
-RETURNS BOOLEAN AS $$
-    SELECT is_strict FROM tap_funky WHERE name = $1 AND is_visible;
-$$ LANGUAGE SQL;
-
--- is_strict( schema, function, args[], description )
-CREATE OR REPLACE FUNCTION is_strict ( NAME, NAME, NAME[], TEXT )
-RETURNS TEXT AS $$
-    SELECT _func_compare($1, $2, $3, _strict($1, $2, $3), $4 );
-$$ LANGUAGE SQL;
-
--- is_strict( schema, function, args[] )
-CREATE OR REPLACE FUNCTION is_strict( NAME, NAME, NAME[] )
-RETURNS TEXT AS $$
-    SELECT ok(
-        _strict($1, $2, $3),
-        'Function ' || quote_ident($1) || '.' || quote_ident($2) || '(' ||
-        array_to_string($3, ', ') || ') should be strict'
-    );
-$$ LANGUAGE sql;
-
--- is_strict( schema, function, description )
-CREATE OR REPLACE FUNCTION is_strict ( NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT _func_compare($1, $2, _strict($1, $2), $3 );
-$$ LANGUAGE SQL;
-
--- is_strict( schema, function )
-CREATE OR REPLACE FUNCTION is_strict( NAME, NAME )
-RETURNS TEXT AS $$
-    SELECT ok(
-        _strict($1, $2),
-        'Function ' || quote_ident($1) || '.' || quote_ident($2) || '() should be strict'
-    );
-$$ LANGUAGE sql;
-
--- is_strict( function, args[], description )
-CREATE OR REPLACE FUNCTION is_strict ( NAME, NAME[], TEXT )
-RETURNS TEXT AS $$
-    SELECT _func_compare(NULL, $1, $2, _strict($1, $2), $3 );
-$$ LANGUAGE SQL;
-
--- is_strict( function, args[] )
-CREATE OR REPLACE FUNCTION is_strict( NAME, NAME[] )
-RETURNS TEXT AS $$
-    SELECT ok(
-        _strict($1, $2),
-        'Function ' || quote_ident($1) || '(' ||
-        array_to_string($2, ', ') || ') should be strict'
-    );
-$$ LANGUAGE sql;
-
--- is_strict( function, description )
-CREATE OR REPLACE FUNCTION is_strict( NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT _func_compare(NULL, $1, _strict($1), $2 );
-$$ LANGUAGE sql;
-
--- is_strict( function )
-CREATE OR REPLACE FUNCTION is_strict( NAME )
-RETURNS TEXT AS $$
-    SELECT ok( _strict($1), 'Function ' || quote_ident($1) || '() should be strict' );
-$$ LANGUAGE sql;
-
-CREATE OR REPLACE FUNCTION _expand_vol( char )
-RETURNS TEXT AS $$
-   SELECT CASE $1
-          WHEN 'i' THEN 'IMMUTABLE'
-          WHEN 's' THEN 'STABLE'
-          WHEN 'v' THEN 'VOLATILE'
-          ELSE          'UNKNOWN' END
-$$ LANGUAGE SQL IMMUTABLE;
-
-CREATE OR REPLACE FUNCTION _refine_vol( text )
-RETURNS text AS $$
-    SELECT _expand_vol(substring(LOWER($1) FROM 1 FOR 1)::char);
-$$ LANGUAGE SQL IMMUTABLE;
-
-CREATE OR REPLACE FUNCTION _vol ( NAME, NAME, NAME[] )
-RETURNS TEXT AS $$
-    SELECT _expand_vol(volatility)
-      FROM tap_funky f
-     WHERE f.schema = $1
-       and f.name   = $2
-       AND f.args   = array_to_string($3, ',')
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION _vol ( NAME, NAME )
-RETURNS TEXT AS $$
-    SELECT _expand_vol(volatility) FROM tap_funky f
-     WHERE f.schema = $1 and f.name = $2
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION _vol ( NAME, NAME[] )
-RETURNS TEXT AS $$
-    SELECT _expand_vol(volatility)
-      FROM tap_funky f
-     WHERE f.name = $1
-       AND f.args = array_to_string($2, ',')
-       AND f.is_visible;
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION _vol ( NAME )
-RETURNS TEXT AS $$
-    SELECT _expand_vol(volatility) FROM tap_funky f
-     WHERE f.name = $1 AND f.is_visible;
-$$ LANGUAGE SQL;
-
--- volatility_is( schema, function, args[], volatility, description )
-CREATE OR REPLACE FUNCTION volatility_is( NAME, NAME, NAME[], TEXT, TEXT )
-RETURNS TEXT AS $$
-    SELECT _func_compare($1, $2, $3, _vol($1, $2, $3), _refine_vol($4), $5 );
-$$ LANGUAGE SQL;
-
--- volatility_is( schema, function, args[], volatility )
-CREATE OR REPLACE FUNCTION volatility_is( NAME, NAME, NAME[], TEXT )
-RETURNS TEXT AS $$
-    SELECT volatility_is(
-        $1, $2, $3, $4,
-        'Function ' || quote_ident($1) || '.' || quote_ident($2) || '(' ||
-        array_to_string($3, ', ') || ') should be ' || _refine_vol($4)
-    );
-$$ LANGUAGE SQL;
-
--- volatility_is( schema, function, volatility, description )
-CREATE OR REPLACE FUNCTION volatility_is( NAME, NAME, TEXT, TEXT )
-RETURNS TEXT AS $$
-    SELECT _func_compare($1, $2, _vol($1, $2), _refine_vol($3), $4 );
-$$ LANGUAGE SQL;
-
--- volatility_is( schema, function, volatility )
-CREATE OR REPLACE FUNCTION volatility_is( NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT volatility_is(
-        $1, $2, $3,
-        'Function ' || quote_ident($1) || '.' || quote_ident($2)
-        || '() should be ' || _refine_vol($3)
-    );
-$$ LANGUAGE SQL;
-
--- volatility_is( function, args[], volatility, description )
-CREATE OR REPLACE FUNCTION volatility_is( NAME, NAME[], TEXT, TEXT )
-RETURNS TEXT AS $$
-    SELECT _func_compare(NULL, $1, $2, _vol($1, $2), _refine_vol($3), $4 );
-$$ LANGUAGE SQL;
-
--- volatility_is( function, args[], volatility )
-CREATE OR REPLACE FUNCTION volatility_is( NAME, NAME[], TEXT )
-RETURNS TEXT AS $$
-    SELECT volatility_is(
-        $1, $2, $3,
-        'Function ' || quote_ident($1) || '(' ||
-        array_to_string($2, ', ') || ') should be ' || _refine_vol($3)
-    );
-$$ LANGUAGE SQL;
-
--- volatility_is( function, volatility, description )
-CREATE OR REPLACE FUNCTION volatility_is( NAME, TEXT, TEXT )
-RETURNS TEXT AS $$
-    SELECT _func_compare(NULL, $1, _vol($1), _refine_vol($2), $3 );
-$$ LANGUAGE SQL;
-
--- volatility_is( function, volatility )
-CREATE OR REPLACE FUNCTION volatility_is( NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT volatility_is(
-        $1, $2,
-        'Function ' || quote_ident($1) || '() should be ' || _refine_vol($2)
-    );
-$$ LANGUAGE SQL;
-
--- check_test( test_output, pass, name, description, diag, match_diag )
-CREATE OR REPLACE FUNCTION check_test( TEXT, BOOLEAN, TEXT, TEXT, TEXT, BOOLEAN )
-RETURNS SETOF TEXT AS $$
-DECLARE
-    tnumb   INTEGER;
-    aok     BOOLEAN;
-    adescr  TEXT;
-    res     BOOLEAN;
-    descr   TEXT;
-    adiag   TEXT;
-    have    ALIAS FOR $1;
-    eok     ALIAS FOR $2;
-    name    ALIAS FOR $3;
-    edescr  ALIAS FOR $4;
-    ediag   ALIAS FOR $5;
-    matchit ALIAS FOR $6;
-BEGIN
-    -- What test was it that just ran?
-    tnumb := currval('__tresults___numb_seq');
-
-    -- Fetch the results.
-    EXECUTE 'SELECT aok, descr FROM __tresults__ WHERE numb = ' || tnumb
-       INTO aok, adescr;
-
-    -- Now delete those results.
-    EXECUTE 'DELETE FROM __tresults__ WHERE numb = ' || tnumb;
-    EXECUTE 'ALTER SEQUENCE __tresults___numb_seq RESTART WITH ' || tnumb;
-
-    -- Set up the description.
-    descr := coalesce( name || ' ', 'Test ' ) || 'should ';
-
-    -- So, did the test pass?
-    RETURN NEXT is(
-        aok,
-        eok,
-        descr || CASE eok WHEN true then 'pass' ELSE 'fail' END
-    );
-
-    -- Was the description as expected?
-    IF edescr IS NOT NULL THEN
-        RETURN NEXT is(
-            adescr,
-            edescr,
-            descr || 'have the proper description'
-        );
-    END IF;
-
-    -- Were the diagnostics as expected?
-    IF ediag IS NOT NULL THEN
-        -- Remove ok and the test number.
-        adiag := substring(
-            have
-            FROM CASE WHEN aok THEN 4 ELSE 9 END + char_length(tnumb::text)
-        );
-
-        -- Remove the description, if there is one.
-        IF adescr <> '' THEN
-            adiag := substring( adiag FROM 3 + char_length( diag( adescr ) ) );
-        END IF;
-
-        -- Remove failure message from ok().
-        IF NOT aok THEN
-           adiag := substring(
-               adiag
-               FROM 14 + char_length(tnumb::text)
-                       + CASE adescr WHEN '' THEN 3 ELSE 3 + char_length( diag( adescr ) ) END
-           );
-        END IF;
-
-        -- Remove the #s.
-        adiag := replace( substring(adiag from 3), E'\n# ', E'\n' );
-
-        -- Now compare the diagnostics.
-        IF matchit THEN
-            RETURN NEXT matches(
-                adiag,
-                ediag,
-                descr || 'have the proper diagnostics'
-            );
-        ELSE
-            RETURN NEXT is(
-                adiag,
-                ediag,
-                descr || 'have the proper diagnostics'
-            );
-        END IF;
-    END IF;
-
-    -- And we're done
-    RETURN;
-END;
-$$ LANGUAGE plpgsql;
-
--- check_test( test_output, pass, name, description, diag )
-CREATE OR REPLACE FUNCTION check_test( TEXT, BOOLEAN, TEXT, TEXT, TEXT )
-RETURNS SETOF TEXT AS $$
-    SELECT * FROM check_test( $1, $2, $3, $4, $5, FALSE );
-$$ LANGUAGE sql;
-
--- check_test( test_output, pass, name, description )
-CREATE OR REPLACE FUNCTION check_test( TEXT, BOOLEAN, TEXT, TEXT )
-RETURNS SETOF TEXT AS $$
-    SELECT * FROM check_test( $1, $2, $3, $4, NULL, FALSE );
-$$ LANGUAGE sql;
-
--- check_test( test_output, pass, name )
-CREATE OR REPLACE FUNCTION check_test( TEXT, BOOLEAN, TEXT )
-RETURNS SETOF TEXT AS $$
-    SELECT * FROM check_test( $1, $2, $3, NULL, NULL, FALSE );
-$$ LANGUAGE sql;
-
--- check_test( test_output, pass )
-CREATE OR REPLACE FUNCTION check_test( TEXT, BOOLEAN )
-RETURNS SETOF TEXT AS $$
-    SELECT * FROM check_test( $1, $2, NULL, NULL, NULL, FALSE );
-$$ LANGUAGE sql;
-
-
-CREATE OR REPLACE FUNCTION findfuncs( NAME, TEXT )
-RETURNS TEXT[] AS $$
-    SELECT ARRAY(
-        SELECT DISTINCT quote_ident(n.nspname) || '.' || quote_ident(p.proname) AS pname
-          FROM pg_catalog.pg_proc p
-          JOIN pg_catalog.pg_namespace n ON p.pronamespace = n.oid
-         WHERE n.nspname = $1
-           AND p.proname ~ $2
-         ORDER BY pname
-    );
-$$ LANGUAGE sql;
-
-CREATE OR REPLACE FUNCTION findfuncs( TEXT )
-RETURNS TEXT[] AS $$
-    SELECT ARRAY(
-        SELECT DISTINCT quote_ident(n.nspname) || '.' || quote_ident(p.proname) AS pname
-          FROM pg_catalog.pg_proc p
-          JOIN pg_catalog.pg_namespace n ON p.pronamespace = n.oid
-         WHERE pg_catalog.pg_function_is_visible(p.oid)
-           AND p.proname ~ $1
-         ORDER BY pname
-    );
-$$ LANGUAGE sql;
-
-CREATE OR REPLACE FUNCTION _runem( text[], boolean )
-RETURNS SETOF TEXT AS $$
-DECLARE
-    tap    text;
-    lbound int := array_lower($1, 1);
-BEGIN
-    IF lbound IS NULL THEN RETURN; END IF;
-    FOR i IN lbound..array_upper($1, 1) LOOP
-        -- Send the name of the function to diag if warranted.
-        IF $2 THEN RETURN NEXT diag( $1[i] || '()' ); END IF;
-        -- Execute the tap function and return its results.
-        FOR tap IN EXECUTE 'SELECT * FROM ' || $1[i] || '()' LOOP
-            RETURN NEXT tap;
-        END LOOP;
-    END LOOP;
-    RETURN;
-END;
-$$ LANGUAGE plpgsql;
-
-CREATE OR REPLACE FUNCTION _is_verbose()
-RETURNS BOOLEAN AS $$
-    SELECT current_setting('client_min_messages') NOT IN (
-        'warning', 'error', 'fatal', 'panic'
-    );
-$$ LANGUAGE sql STABLE;
-
--- do_tap( schema, pattern )
-CREATE OR REPLACE FUNCTION do_tap( name, text )
-RETURNS SETOF TEXT AS $$
-    SELECT * FROM _runem( findfuncs($1, $2), _is_verbose() );
-$$ LANGUAGE sql;
-
--- do_tap( schema )
-CREATE OR REPLACE FUNCTION do_tap( name )
-RETURNS SETOF TEXT AS $$
-    SELECT * FROM _runem( findfuncs($1, '^test'), _is_verbose() );
-$$ LANGUAGE sql;
-
--- do_tap( pattern )
-CREATE OR REPLACE FUNCTION do_tap( text )
-RETURNS SETOF TEXT AS $$
-    SELECT * FROM _runem( findfuncs($1), _is_verbose() );
-$$ LANGUAGE sql;
-
--- do_tap()
-CREATE OR REPLACE FUNCTION do_tap( )
-RETURNS SETOF TEXT AS $$
-    SELECT * FROM _runem( findfuncs('^test'), _is_verbose());
-$$ LANGUAGE sql;
-
-CREATE OR REPLACE FUNCTION _currtest()
-RETURNS INTEGER AS $$
-BEGIN
-    RETURN currval('__tresults___numb_seq');
-EXCEPTION
-    WHEN object_not_in_prerequisite_state THEN RETURN 0;
-END;
-$$ LANGUAGE plpgsql;
-
-CREATE OR REPLACE FUNCTION _cleanup()
-RETURNS boolean AS $$
-    DROP TABLE __tresults__;
-    DROP SEQUENCE __tresults___numb_seq;
-    DROP TABLE __tcache__;
-    DROP SEQUENCE __tcache___id_seq;
-    SELECT TRUE;
-$$ LANGUAGE sql;
-
--- diag_test_name ( test_name )
-CREATE OR REPLACE FUNCTION diag_test_name(TEXT)
-RETURNS TEXT AS $$
-    SELECT diag($1 || '()');
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION _runner( text[], text[], text[], text[], text[] )
-RETURNS SETOF TEXT AS $$
-DECLARE
-    startup  ALIAS FOR $1;
-    shutdown ALIAS FOR $2;
-    setup    ALIAS FOR $3;
-    teardown ALIAS FOR $4;
-    tests    ALIAS FOR $5;
-    tap      text;
-    verbos   boolean := _is_verbose(); -- verbose is a reserved word in 8.5.
-    num_faild INTEGER := 0;
-BEGIN
-    BEGIN
-        -- No plan support.
-        PERFORM * FROM no_plan();
-        FOR tap IN SELECT * FROM _runem(startup, false) LOOP RETURN NEXT tap; END LOOP;
-    EXCEPTION
-        -- Catch all exceptions and simply rethrow custom exceptions. This
-        -- will roll back everything in the above block.
-        WHEN raise_exception THEN
-            RAISE EXCEPTION '%', SQLERRM;
-    END;
-
-    BEGIN
-        FOR i IN 1..array_upper(tests, 1) LOOP
-            BEGIN
-                -- What test are we running?
-                IF verbos THEN RETURN NEXT diag_test_name(tests[i]); END IF;
-
-                -- Run the setup functions.
-                FOR tap IN SELECT * FROM _runem(setup, false) LOOP RETURN NEXT tap; END LOOP;
-
-                -- Run the actual test function.
-                FOR tap IN EXECUTE 'SELECT * FROM ' || tests[i] || '()' LOOP
-                    RETURN NEXT tap;
-                END LOOP;
-
-                -- Run the teardown functions.
-                FOR tap IN SELECT * FROM _runem(teardown, false) LOOP RETURN NEXT tap; END LOOP;
-
-                -- Remember how many failed and then roll back.
-                num_faild := num_faild + num_failed();
-                RAISE EXCEPTION '__TAP_ROLLBACK__';
-
-            EXCEPTION WHEN raise_exception THEN
-                IF SQLERRM <> '__TAP_ROLLBACK__' THEN
-                    -- We didn't raise it, so propagate it.
-                    RAISE EXCEPTION '%', SQLERRM;
-                END IF;
-            END;
-        END LOOP;
-
-        -- Run the shutdown functions.
-        FOR tap IN SELECT * FROM _runem(shutdown, false) LOOP RETURN NEXT tap; END LOOP;
-
-        -- Raise an exception to rollback any changes.
-        RAISE EXCEPTION '__TAP_ROLLBACK__';
-    EXCEPTION WHEN raise_exception THEN
-        IF SQLERRM <> '__TAP_ROLLBACK__' THEN
-            -- We didn't raise it, so propagate it.
-            RAISE EXCEPTION '%', SQLERRM;
-        END IF;
-    END;
-    -- Finish up.
-    FOR tap IN SELECT * FROM _finish( currval('__tresults___numb_seq')::integer, 0, num_faild ) LOOP
-        RETURN NEXT tap;
-    END LOOP;
-
-    -- Clean up and return.
-    PERFORM _cleanup();
-    RETURN;
-END;
-$$ LANGUAGE plpgsql;
-
--- runtests( schema, match )
-CREATE OR REPLACE FUNCTION runtests( NAME, TEXT )
-RETURNS SETOF TEXT AS $$
-    SELECT * FROM _runner(
-        findfuncs( $1, '^startup' ),
-        findfuncs( $1, '^shutdown' ),
-        findfuncs( $1, '^setup' ),
-        findfuncs( $1, '^teardown' ),
-        findfuncs( $1, $2 )
-    );
-$$ LANGUAGE sql;
-
--- runtests( schema )
-CREATE OR REPLACE FUNCTION runtests( NAME )
-RETURNS SETOF TEXT AS $$
-    SELECT * FROM runtests( $1, '^test' );
-$$ LANGUAGE sql;
-
--- runtests( match )
-CREATE OR REPLACE FUNCTION runtests( TEXT )
-RETURNS SETOF TEXT AS $$
-    SELECT * FROM _runner(
-        findfuncs( '^startup' ),
-        findfuncs( '^shutdown' ),
-        findfuncs( '^setup' ),
-        findfuncs( '^teardown' ),
-        findfuncs( $1 )
-    );
-$$ LANGUAGE sql;
-
--- runtests( )
-CREATE OR REPLACE FUNCTION runtests( )
-RETURNS SETOF TEXT AS $$
-    SELECT * FROM runtests( '^test' );
-$$ LANGUAGE sql;
-
-CREATE OR REPLACE FUNCTION _temptable ( TEXT, TEXT )
-RETURNS TEXT AS $$
-BEGIN
-    EXECUTE 'CREATE TEMP TABLE ' || $2 || ' AS ' || _query($1);
-    return $2;
-END;
-$$ LANGUAGE plpgsql;
-
-CREATE OR REPLACE FUNCTION _temptable ( anyarray, TEXT )
-RETURNS TEXT AS $$
-BEGIN
-    CREATE TEMP TABLE _____coltmp___ AS
-    SELECT $1[i]
-    FROM generate_series(array_lower($1, 1), array_upper($1, 1)) s(i);
-    EXECUTE 'ALTER TABLE _____coltmp___ RENAME TO ' || $2;
-    return $2;
-END;
-$$ LANGUAGE plpgsql;
-
-CREATE OR REPLACE FUNCTION _temptypes( TEXT )
-RETURNS TEXT AS $$
-    SELECT array_to_string(ARRAY(
-        SELECT pg_catalog.format_type(a.atttypid, a.atttypmod)
-          FROM pg_catalog.pg_attribute a
-          JOIN pg_catalog.pg_class c ON a.attrelid = c.oid
-         WHERE c.oid = ('pg_temp.' || $1)::pg_catalog.regclass
-           AND attnum > 0
-           AND NOT attisdropped
-         ORDER BY attnum
-    ), ',');
-$$ LANGUAGE sql;
-
-CREATE OR REPLACE FUNCTION _docomp( TEXT, TEXT, TEXT, TEXT )
-RETURNS TEXT AS $$
-DECLARE
-    have    ALIAS FOR $1;
-    want    ALIAS FOR $2;
-    extras  TEXT[]  := '{}';
-    missing TEXT[]  := '{}';
-    res     BOOLEAN := TRUE;
-    msg     TEXT    := '';
-    rec     RECORD;
-BEGIN
-    BEGIN
-        -- Find extra records.
-        FOR rec in EXECUTE 'SELECT * FROM ' || have || ' EXCEPT ' || $4
-                        || 'SELECT * FROM ' || want LOOP
-            extras := extras || rec::text;
-        END LOOP;
-
-        -- Find missing records.
-        FOR rec in EXECUTE 'SELECT * FROM ' || want || ' EXCEPT ' || $4
-                        || 'SELECT * FROM ' || have LOOP
-            missing := missing || rec::text;
-        END LOOP;
-
-        -- Drop the temporary tables.
-        EXECUTE 'DROP TABLE ' || have;
-        EXECUTE 'DROP TABLE ' || want;
-    EXCEPTION WHEN syntax_error OR datatype_mismatch THEN
-        msg := E'\n' || diag(
-            E'    Columns differ between queries:\n'
-            || '        have: (' || _temptypes(have) || E')\n'
-            || '        want: (' || _temptypes(want) || ')'
-        );
-        EXECUTE 'DROP TABLE ' || have;
-        EXECUTE 'DROP TABLE ' || want;
-        RETURN ok(FALSE, $3) || msg;
-    END;
-
-    -- What extra records do we have?
-    IF extras[1] IS NOT NULL THEN
-        res := FALSE;
-        msg := E'\n' || diag(
-            E'    Extra records:\n        '
-            ||  array_to_string( extras, E'\n        ' )
-        );
-    END IF;
-
-    -- What missing records do we have?
-    IF missing[1] IS NOT NULL THEN
-        res := FALSE;
-        msg := msg || E'\n' || diag(
-            E'    Missing records:\n        '
-            ||  array_to_string( missing, E'\n        ' )
-        );
-    END IF;
-
-    RETURN ok(res, $3) || msg;
-END;
-$$ LANGUAGE plpgsql;
-
-CREATE OR REPLACE FUNCTION _relcomp( TEXT, TEXT, TEXT, TEXT )
-RETURNS TEXT AS $$
-    SELECT _docomp(
-        _temptable( $1, '__taphave__' ),
-        _temptable( $2, '__tapwant__' ),
-        $3, $4
-    );
-$$ LANGUAGE sql;
-
-CREATE OR REPLACE FUNCTION _relcomp( TEXT, anyarray, TEXT, TEXT )
-RETURNS TEXT AS $$
-    SELECT _docomp(
-        _temptable( $1, '__taphave__' ),
-        _temptable( $2, '__tapwant__' ),
-        $3, $4
-    );
-$$ LANGUAGE sql;
-
--- set_eq( sql, sql, description )
-CREATE OR REPLACE FUNCTION set_eq( TEXT, TEXT, TEXT )
-RETURNS TEXT AS $$
-    SELECT _relcomp( $1, $2, $3, '' );
-$$ LANGUAGE sql;
-
--- set_eq( sql, sql )
-CREATE OR REPLACE FUNCTION set_eq( TEXT, TEXT )
-RETURNS TEXT AS $$
-    SELECT _relcomp( $1, $2, NULL::text, '' );
-$$ LANGUAGE sql;
-
--- set_eq( sql, array, description )
-CREATE OR REPLACE FUNCTION set_eq( TEXT, anyarray, TEXT )
-RETURNS TEXT AS $$
-    SELECT _relcomp( $1, $2, $3, '' );
-$$ LANGUAGE sql;
-
--- set_eq( sql, array )
-CREATE OR REPLACE FUNCTION set_eq( TEXT, anyarray )
-RETURNS TEXT AS $$
-    SELECT _relcomp( $1, $2, NULL::text, '' );
-$$ LANGUAGE sql;
-
--- bag_eq( sql, sql, description )
-CREATE OR REPLACE FUNCTION bag_eq( TEXT, TEXT, TEXT )
-RETURNS TEXT AS $$
-    SELECT _relcomp( $1, $2, $3, 'ALL ' );
-$$ LANGUAGE sql;
-
--- bag_eq( sql, sql )
-CREATE OR REPLACE FUNCTION bag_eq( TEXT, TEXT )
-RETURNS TEXT AS $$
-    SELECT _relcomp( $1, $2, NULL::text, 'ALL ' );
-$$ LANGUAGE sql;
-
--- bag_eq( sql, array, description )
-CREATE OR REPLACE FUNCTION bag_eq( TEXT, anyarray, TEXT )
-RETURNS TEXT AS $$
-    SELECT _relcomp( $1, $2, $3, 'ALL ' );
-$$ LANGUAGE sql;
-
--- bag_eq( sql, array )
-CREATE OR REPLACE FUNCTION bag_eq( TEXT, anyarray )
-RETURNS TEXT AS $$
-    SELECT _relcomp( $1, $2, NULL::text, 'ALL ' );
-$$ LANGUAGE sql;
-
-CREATE OR REPLACE FUNCTION _do_ne( TEXT, TEXT, TEXT, TEXT )
-RETURNS TEXT AS $$
-DECLARE
-    have    ALIAS FOR $1;
-    want    ALIAS FOR $2;
-    extras  TEXT[]  := '{}';
-    missing TEXT[]  := '{}';
-    res     BOOLEAN := TRUE;
-    msg     TEXT    := '';
-BEGIN
-    BEGIN
-        -- Find extra records.
-        EXECUTE 'SELECT EXISTS ( '
-             || '( SELECT * FROM ' || have || ' EXCEPT ' || $4
-             || '  SELECT * FROM ' || want
-             || ' ) UNION ( '
-             || '  SELECT * FROM ' || want || ' EXCEPT ' || $4
-             || '  SELECT * FROM ' || have
-             || ' ) LIMIT 1 )' INTO res;
-
-        -- Drop the temporary tables.
-        EXECUTE 'DROP TABLE ' || have;
-        EXECUTE 'DROP TABLE ' || want;
-    EXCEPTION WHEN syntax_error OR datatype_mismatch THEN
-        msg := E'\n' || diag(
-            E'    Columns differ between queries:\n'
-            || '        have: (' || _temptypes(have) || E')\n'
-            || '        want: (' || _temptypes(want) || ')'
-        );
-        EXECUTE 'DROP TABLE ' || have;
-        EXECUTE 'DROP TABLE ' || want;
-        RETURN ok(FALSE, $3) || msg;
-    END;
-
-    -- Return the value from the query.
-    RETURN ok(res, $3);
-END;
-$$ LANGUAGE plpgsql;
-
-CREATE OR REPLACE FUNCTION _relne( TEXT, TEXT, TEXT, TEXT )
-RETURNS TEXT AS $$
-    SELECT _do_ne(
-        _temptable( $1, '__taphave__' ),
-        _temptable( $2, '__tapwant__' ),
-        $3, $4
-    );
-$$ LANGUAGE sql;
-
-CREATE OR REPLACE FUNCTION _relne( TEXT, anyarray, TEXT, TEXT )
-RETURNS TEXT AS $$
-    SELECT _do_ne(
-        _temptable( $1, '__taphave__' ),
-        _temptable( $2, '__tapwant__' ),
-        $3, $4
-    );
-$$ LANGUAGE sql;
-
--- set_ne( sql, sql, description )
-CREATE OR REPLACE FUNCTION set_ne( TEXT, TEXT, TEXT )
-RETURNS TEXT AS $$
-    SELECT _relne( $1, $2, $3, '' );
-$$ LANGUAGE sql;
-
--- set_ne( sql, sql )
-CREATE OR REPLACE FUNCTION set_ne( TEXT, TEXT )
-RETURNS TEXT AS $$
-    SELECT _relne( $1, $2, NULL::text, '' );
-$$ LANGUAGE sql;
-
--- set_ne( sql, array, description )
-CREATE OR REPLACE FUNCTION set_ne( TEXT, anyarray, TEXT )
-RETURNS TEXT AS $$
-    SELECT _relne( $1, $2, $3, '' );
-$$ LANGUAGE sql;
-
--- set_ne( sql, array )
-CREATE OR REPLACE FUNCTION set_ne( TEXT, anyarray )
-RETURNS TEXT AS $$
-    SELECT _relne( $1, $2, NULL::text, '' );
-$$ LANGUAGE sql;
-
--- bag_ne( sql, sql, description )
-CREATE OR REPLACE FUNCTION bag_ne( TEXT, TEXT, TEXT )
-RETURNS TEXT AS $$
-    SELECT _relne( $1, $2, $3, 'ALL ' );
-$$ LANGUAGE sql;
-
--- bag_ne( sql, sql )
-CREATE OR REPLACE FUNCTION bag_ne( TEXT, TEXT )
-RETURNS TEXT AS $$
-    SELECT _relne( $1, $2, NULL::text, 'ALL ' );
-$$ LANGUAGE sql;
-
--- bag_ne( sql, array, description )
-CREATE OR REPLACE FUNCTION bag_ne( TEXT, anyarray, TEXT )
-RETURNS TEXT AS $$
-    SELECT _relne( $1, $2, $3, 'ALL ' );
-$$ LANGUAGE sql;
-
--- bag_ne( sql, array )
-CREATE OR REPLACE FUNCTION bag_ne( TEXT, anyarray )
-RETURNS TEXT AS $$
-    SELECT _relne( $1, $2, NULL::text, 'ALL ' );
-$$ LANGUAGE sql;
-
-CREATE OR REPLACE FUNCTION _relcomp( TEXT, TEXT, TEXT, TEXT, TEXT )
-RETURNS TEXT AS $$
-DECLARE
-    have    TEXT    := _temptable( $1, '__taphave__' );
-    want    TEXT    := _temptable( $2, '__tapwant__' );
-    results TEXT[]  := '{}';
-    res     BOOLEAN := TRUE;
-    msg     TEXT    := '';
-    rec     RECORD;
-BEGIN
-    BEGIN
-        -- Find relevant records.
-        FOR rec in EXECUTE 'SELECT * FROM ' || want || ' ' || $4
-                       || ' SELECT * FROM ' || have LOOP
-            results := results || rec::text;
-        END LOOP;
-
-        -- Drop the temporary tables.
-        EXECUTE 'DROP TABLE ' || have;
-        EXECUTE 'DROP TABLE ' || want;
-    EXCEPTION WHEN syntax_error OR datatype_mismatch THEN
-        msg := E'\n' || diag(
-            E'    Columns differ between queries:\n'
-            || '        have: (' || _temptypes(have) || E')\n'
-            || '        want: (' || _temptypes(want) || ')'
-        );
-        EXECUTE 'DROP TABLE ' || have;
-        EXECUTE 'DROP TABLE ' || want;
-        RETURN ok(FALSE, $3) || msg;
-    END;
-
-    -- What records do we have?
-    IF results[1] IS NOT NULL THEN
-        res := FALSE;
-        msg := msg || E'\n' || diag(
-            '    ' || $5 || E' records:\n        '
-            ||  array_to_string( results, E'\n        ' )
-        );
-    END IF;
-
-    RETURN ok(res, $3) || msg;
-END;
-$$ LANGUAGE plpgsql;
-
--- set_has( sql, sql, description )
-CREATE OR REPLACE FUNCTION set_has( TEXT, TEXT, TEXT )
-RETURNS TEXT AS $$
-    SELECT _relcomp( $1, $2, $3, 'EXCEPT', 'Missing' );
-$$ LANGUAGE sql;
-
--- set_has( sql, sql )
-CREATE OR REPLACE FUNCTION set_has( TEXT, TEXT )
-RETURNS TEXT AS $$
-    SELECT _relcomp( $1, $2, NULL::TEXT, 'EXCEPT', 'Missing' );
-$$ LANGUAGE sql;
-
--- bag_has( sql, sql, description )
-CREATE OR REPLACE FUNCTION bag_has( TEXT, TEXT, TEXT )
-RETURNS TEXT AS $$
-    SELECT _relcomp( $1, $2, $3, 'EXCEPT ALL', 'Missing' );
-$$ LANGUAGE sql;
-
--- bag_has( sql, sql )
-CREATE OR REPLACE FUNCTION bag_has( TEXT, TEXT )
-RETURNS TEXT AS $$
-    SELECT _relcomp( $1, $2, NULL::TEXT, 'EXCEPT ALL', 'Missing' );
-$$ LANGUAGE sql;
-
--- set_hasnt( sql, sql, description )
-CREATE OR REPLACE FUNCTION set_hasnt( TEXT, TEXT, TEXT )
-RETURNS TEXT AS $$
-    SELECT _relcomp( $1, $2, $3, 'INTERSECT', 'Extra' );
-$$ LANGUAGE sql;
-
--- set_hasnt( sql, sql )
-CREATE OR REPLACE FUNCTION set_hasnt( TEXT, TEXT )
-RETURNS TEXT AS $$
-    SELECT _relcomp( $1, $2, NULL::TEXT, 'INTERSECT', 'Extra' );
-$$ LANGUAGE sql;
-
--- bag_hasnt( sql, sql, description )
-CREATE OR REPLACE FUNCTION bag_hasnt( TEXT, TEXT, TEXT )
-RETURNS TEXT AS $$
-    SELECT _relcomp( $1, $2, $3, 'INTERSECT ALL', 'Extra' );
-$$ LANGUAGE sql;
-
--- bag_hasnt( sql, sql )
-CREATE OR REPLACE FUNCTION bag_hasnt( TEXT, TEXT )
-RETURNS TEXT AS $$
-    SELECT _relcomp( $1, $2, NULL::TEXT, 'INTERSECT ALL', 'Extra' );
-$$ LANGUAGE sql;
-
--- results_eq( cursor, cursor, description )
-CREATE OR REPLACE FUNCTION results_eq( refcursor, refcursor, text )
-RETURNS TEXT AS $$
-DECLARE
-    have       ALIAS FOR $1;
-    want       ALIAS FOR $2;
-    have_rec   RECORD;
-    want_rec   RECORD;
-    have_found BOOLEAN;
-    want_found BOOLEAN;
-    rownum     INTEGER := 1;
-BEGIN
-    FETCH have INTO have_rec;
-    have_found := FOUND;
-    FETCH want INTO want_rec;
-    want_found := FOUND;
-    WHILE have_found OR want_found LOOP
-        IF have_rec IS DISTINCT FROM want_rec OR have_found <> want_found THEN
-            RETURN ok( false, $3 ) || E'\n' || diag(
-                '    Results differ beginning at row ' || rownum || E':\n' ||
-                '        have: ' || CASE WHEN have_found THEN have_rec::text ELSE 'NULL' END || E'\n' ||
-                '        want: ' || CASE WHEN want_found THEN want_rec::text ELSE 'NULL' END
-            );
-        END IF;
-        rownum = rownum + 1;
-        FETCH have INTO have_rec;
-        have_found := FOUND;
-        FETCH want INTO want_rec;
-        want_found := FOUND;
-    END LOOP;
-
-    RETURN ok( true, $3 );
-EXCEPTION
-    WHEN datatype_mismatch THEN
-        RETURN ok( false, $3 ) || E'\n' || diag(
-            E'    Columns differ between queries:\n' ||
-            '        have: ' || CASE WHEN have_found THEN have_rec::text ELSE 'NULL' END || E'\n' ||
-            '        want: ' || CASE WHEN want_found THEN want_rec::text ELSE 'NULL' END
-        );
-END;
-$$ LANGUAGE plpgsql;
-
--- results_eq( cursor, cursor )
-CREATE OR REPLACE FUNCTION results_eq( refcursor, refcursor )
-RETURNS TEXT AS $$
-    SELECT results_eq( $1, $2, NULL::text );
-$$ LANGUAGE sql;
-
--- results_eq( sql, sql, description )
-CREATE OR REPLACE FUNCTION results_eq( TEXT, TEXT, TEXT )
-RETURNS TEXT AS $$
-DECLARE
-    have REFCURSOR;
-    want REFCURSOR;
-    res  TEXT;
-BEGIN
-    OPEN have FOR EXECUTE _query($1);
-    OPEN want FOR EXECUTE _query($2);
-    res := results_eq(have, want, $3);
-    CLOSE have;
-    CLOSE want;
-    RETURN res;
-END;
-$$ LANGUAGE plpgsql;
-
--- results_eq( sql, sql )
-CREATE OR REPLACE FUNCTION results_eq( TEXT, TEXT )
-RETURNS TEXT AS $$
-    SELECT results_eq( $1, $2, NULL::text );
-$$ LANGUAGE sql;
-
--- results_eq( sql, array, description )
-CREATE OR REPLACE FUNCTION results_eq( TEXT, anyarray, TEXT )
-RETURNS TEXT AS $$
-DECLARE
-    have REFCURSOR;
-    want REFCURSOR;
-    res  TEXT;
-BEGIN
-    OPEN have FOR EXECUTE _query($1);
-    OPEN want FOR SELECT $2[i]
-    FROM generate_series(array_lower($2, 1), array_upper($2, 1)) s(i);
-    res := results_eq(have, want, $3);
-    CLOSE have;
-    CLOSE want;
-    RETURN res;
-END;
-$$ LANGUAGE plpgsql;
-
--- results_eq( sql, array )
-CREATE OR REPLACE FUNCTION results_eq( TEXT, anyarray )
-RETURNS TEXT AS $$
-    SELECT results_eq( $1, $2, NULL::text );
-$$ LANGUAGE sql;
-
--- results_eq( sql, cursor, description )
-CREATE OR REPLACE FUNCTION results_eq( TEXT, refcursor, TEXT )
-RETURNS TEXT AS $$
-DECLARE
-    have REFCURSOR;
-    res  TEXT;
-BEGIN
-    OPEN have FOR EXECUTE _query($1);
-    res := results_eq(have, $2, $3);
-    CLOSE have;
-    RETURN res;
-END;
-$$ LANGUAGE plpgsql;
-
--- results_eq( sql, cursor )
-CREATE OR REPLACE FUNCTION results_eq( TEXT, refcursor )
-RETURNS TEXT AS $$
-    SELECT results_eq( $1, $2, NULL::text );
-$$ LANGUAGE sql;
-
--- results_eq( cursor, sql, description )
-CREATE OR REPLACE FUNCTION results_eq( refcursor, TEXT, TEXT )
-RETURNS TEXT AS $$
-DECLARE
-    want REFCURSOR;
-    res  TEXT;
-BEGIN
-    OPEN want FOR EXECUTE _query($2);
-    res := results_eq($1, want, $3);
-    CLOSE want;
-    RETURN res;
-END;
-$$ LANGUAGE plpgsql;
-
--- results_eq( cursor, sql )
-CREATE OR REPLACE FUNCTION results_eq( refcursor, TEXT )
-RETURNS TEXT AS $$
-    SELECT results_eq( $1, $2, NULL::text );
-$$ LANGUAGE sql;
-
--- results_eq( cursor, array, description )
-CREATE OR REPLACE FUNCTION results_eq( refcursor, anyarray, TEXT )
-RETURNS TEXT AS $$
-DECLARE
-    want REFCURSOR;
-    res  TEXT;
-BEGIN
-    OPEN want FOR SELECT $2[i]
-    FROM generate_series(array_lower($2, 1), array_upper($2, 1)) s(i);
-    res := results_eq($1, want, $3);
-    CLOSE want;
-    RETURN res;
-END;
-$$ LANGUAGE plpgsql;
-
--- results_eq( cursor, array )
-CREATE OR REPLACE FUNCTION results_eq( refcursor, anyarray )
-RETURNS TEXT AS $$
-    SELECT results_eq( $1, $2, NULL::text );
-$$ LANGUAGE sql;
-
--- results_ne( cursor, cursor, description )
-CREATE OR REPLACE FUNCTION results_ne( refcursor, refcursor, text )
-RETURNS TEXT AS $$
-DECLARE
-    have       ALIAS FOR $1;
-    want       ALIAS FOR $2;
-    have_rec   RECORD;
-    want_rec   RECORD;
-    have_found BOOLEAN;
-    want_found BOOLEAN;
-BEGIN
-    FETCH have INTO have_rec;
-    have_found := FOUND;
-    FETCH want INTO want_rec;
-    want_found := FOUND;
-    WHILE have_found OR want_found LOOP
-        IF have_rec IS DISTINCT FROM want_rec OR have_found <> want_found THEN
-            RETURN ok( true, $3 );
-        ELSE
-            FETCH have INTO have_rec;
-            have_found := FOUND;
-            FETCH want INTO want_rec;
-            want_found := FOUND;
-        END IF;
-    END LOOP;
-    RETURN ok( false, $3 );
-EXCEPTION
-    WHEN datatype_mismatch THEN
-        RETURN ok( false, $3 ) || E'\n' || diag(
-            E'    Columns differ between queries:\n' ||
-            '        have: ' || CASE WHEN have_found THEN have_rec::text ELSE 'NULL' END || E'\n' ||
-            '        want: ' || CASE WHEN want_found THEN want_rec::text ELSE 'NULL' END
-        );
-END;
-$$ LANGUAGE plpgsql;
-
--- results_ne( cursor, cursor )
-CREATE OR REPLACE FUNCTION results_ne( refcursor, refcursor )
-RETURNS TEXT AS $$
-    SELECT results_ne( $1, $2, NULL::text );
-$$ LANGUAGE sql;
-
--- results_ne( sql, sql, description )
-CREATE OR REPLACE FUNCTION results_ne( TEXT, TEXT, TEXT )
-RETURNS TEXT AS $$
-DECLARE
-    have REFCURSOR;
-    want REFCURSOR;
-    res  TEXT;
-BEGIN
-    OPEN have FOR EXECUTE _query($1);
-    OPEN want FOR EXECUTE _query($2);
-    res := results_ne(have, want, $3);
-    CLOSE have;
-    CLOSE want;
-    RETURN res;
-END;
-$$ LANGUAGE plpgsql;
-
--- results_ne( sql, sql )
-CREATE OR REPLACE FUNCTION results_ne( TEXT, TEXT )
-RETURNS TEXT AS $$
-    SELECT results_ne( $1, $2, NULL::text );
-$$ LANGUAGE sql;
-
--- results_ne( sql, array, description )
-CREATE OR REPLACE FUNCTION results_ne( TEXT, anyarray, TEXT )
-RETURNS TEXT AS $$
-DECLARE
-    have REFCURSOR;
-    want REFCURSOR;
-    res  TEXT;
-BEGIN
-    OPEN have FOR EXECUTE _query($1);
-    OPEN want FOR SELECT $2[i]
-    FROM generate_series(array_lower($2, 1), array_upper($2, 1)) s(i);
-    res := results_ne(have, want, $3);
-    CLOSE have;
-    CLOSE want;
-    RETURN res;
-END;
-$$ LANGUAGE plpgsql;
-
--- results_ne( sql, array )
-CREATE OR REPLACE FUNCTION results_ne( TEXT, anyarray )
-RETURNS TEXT AS $$
-    SELECT results_ne( $1, $2, NULL::text );
-$$ LANGUAGE sql;
-
--- results_ne( sql, cursor, description )
-CREATE OR REPLACE FUNCTION results_ne( TEXT, refcursor, TEXT )
-RETURNS TEXT AS $$
-DECLARE
-    have REFCURSOR;
-    res  TEXT;
-BEGIN
-    OPEN have FOR EXECUTE _query($1);
-    res := results_ne(have, $2, $3);
-    CLOSE have;
-    RETURN res;
-END;
-$$ LANGUAGE plpgsql;
-
--- results_ne( sql, cursor )
-CREATE OR REPLACE FUNCTION results_ne( TEXT, refcursor )
-RETURNS TEXT AS $$
-    SELECT results_ne( $1, $2, NULL::text );
-$$ LANGUAGE sql;
-
--- results_ne( cursor, sql, description )
-CREATE OR REPLACE FUNCTION results_ne( refcursor, TEXT, TEXT )
-RETURNS TEXT AS $$
-DECLARE
-    want REFCURSOR;
-    res  TEXT;
-BEGIN
-    OPEN want FOR EXECUTE _query($2);
-    res := results_ne($1, want, $3);
-    CLOSE want;
-    RETURN res;
-END;
-$$ LANGUAGE plpgsql;
-
--- results_ne( cursor, sql )
-CREATE OR REPLACE FUNCTION results_ne( refcursor, TEXT )
-RETURNS TEXT AS $$
-    SELECT results_ne( $1, $2, NULL::text );
-$$ LANGUAGE sql;
-
--- results_ne( cursor, array, description )
-CREATE OR REPLACE FUNCTION results_ne( refcursor, anyarray, TEXT )
-RETURNS TEXT AS $$
-DECLARE
-    want REFCURSOR;
-    res  TEXT;
-BEGIN
-    OPEN want FOR SELECT $2[i]
-    FROM generate_series(array_lower($2, 1), array_upper($2, 1)) s(i);
-    res := results_ne($1, want, $3);
-    CLOSE want;
-    RETURN res;
-END;
-$$ LANGUAGE plpgsql;
-
--- results_ne( cursor, array )
-CREATE OR REPLACE FUNCTION results_ne( refcursor, anyarray )
-RETURNS TEXT AS $$
-    SELECT results_ne( $1, $2, NULL::text );
-$$ LANGUAGE sql;
-
--- isa_ok( value, regtype, description )
-CREATE OR REPLACE FUNCTION isa_ok( anyelement, regtype, TEXT )
-RETURNS TEXT AS $$
-DECLARE
-    typeof regtype := pg_typeof($1);
-BEGIN
-    IF typeof = $2 THEN RETURN ok(true, $3 || ' isa ' || $2 ); END IF;
-    RETURN ok(false, $3 || ' isa ' || $2 ) || E'\n' ||
-        diag('    ' || $3 || ' isn''t a "' || $2 || '" it''s a "' || typeof || '"');
-END;
-$$ LANGUAGE plpgsql;
-
--- isa_ok( value, regtype )
-CREATE OR REPLACE FUNCTION isa_ok( anyelement, regtype )
-RETURNS TEXT AS $$
-    SELECT isa_ok($1, $2, 'the value');
-$$ LANGUAGE sql;
-
--- is_empty( sql, description )
-CREATE OR REPLACE FUNCTION is_empty( TEXT, TEXT )
-RETURNS TEXT AS $$
-DECLARE
-    extras  TEXT[]  := '{}';
-    res     BOOLEAN := TRUE;
-    msg     TEXT    := '';
-    rec     RECORD;
-BEGIN
-    -- Find extra records.
-    FOR rec in EXECUTE _query($1) LOOP
-        extras := extras || rec::text;
-    END LOOP;
-
-    -- What extra records do we have?
-    IF extras[1] IS NOT NULL THEN
-        res := FALSE;
-        msg := E'\n' || diag(
-            E'    Unexpected records:\n        '
-            ||  array_to_string( extras, E'\n        ' )
-        );
-    END IF;
-
-    RETURN ok(res, $2) || msg;
-END;
-$$ LANGUAGE plpgsql;
-
--- is_empty( sql )
-CREATE OR REPLACE FUNCTION is_empty( TEXT )
-RETURNS TEXT AS $$
-    SELECT is_empty( $1, NULL );
-$$ LANGUAGE sql;
-
--- collect_tap( tap, tap, tap )
-CREATE OR REPLACE FUNCTION collect_tap( VARIADIC text[] )
-RETURNS TEXT AS $$
-    SELECT array_to_string($1, E'\n');
-$$ LANGUAGE sql;
-
--- collect_tap( tap[] )
-CREATE OR REPLACE FUNCTION collect_tap( VARCHAR[] )
-RETURNS TEXT AS $$
-    SELECT array_to_string($1, E'\n');
-$$ LANGUAGE sql;
-
-CREATE OR REPLACE FUNCTION _tlike ( BOOLEAN, TEXT, TEXT, TEXT )
-RETURNS TEXT AS $$
-    SELECT ok( $1, $4 ) || CASE WHEN $1 THEN '' ELSE E'\n' || diag(
-           '   error message: ' || COALESCE( quote_literal($2), 'NULL' ) ||
-       E'\n   doesn''t match: ' || COALESCE( quote_literal($3), 'NULL' )
-    ) END;
-$$ LANGUAGE sql;
-
--- throws_like ( sql, pattern, description )
-CREATE OR REPLACE FUNCTION throws_like ( TEXT, TEXT, TEXT )
-RETURNS TEXT AS $$
-BEGIN
-    EXECUTE _query($1);
-    RETURN ok( FALSE, $3 ) || E'\n' || diag( '    no exception thrown' );
-EXCEPTION WHEN OTHERS THEN
-    return _tlike( SQLERRM ~~ $2, SQLERRM, $2, $3 );
-END;
-$$ LANGUAGE plpgsql;
-
--- throws_like ( sql, pattern )
-CREATE OR REPLACE FUNCTION throws_like ( TEXT, TEXT )
-RETURNS TEXT AS $$
-    SELECT throws_like($1, $2, 'Should throw exception like ' || quote_literal($2) );
-$$ LANGUAGE sql;
-
--- throws_ilike ( sql, pattern, description )
-CREATE OR REPLACE FUNCTION throws_ilike ( TEXT, TEXT, TEXT )
-RETURNS TEXT AS $$
-BEGIN
-    EXECUTE _query($1);
-    RETURN ok( FALSE, $3 ) || E'\n' || diag( '    no exception thrown' );
-EXCEPTION WHEN OTHERS THEN
-    return _tlike( SQLERRM ~~* $2, SQLERRM, $2, $3 );
-END;
-$$ LANGUAGE plpgsql;
-
--- throws_ilike ( sql, pattern )
-CREATE OR REPLACE FUNCTION throws_ilike ( TEXT, TEXT )
-RETURNS TEXT AS $$
-    SELECT throws_ilike($1, $2, 'Should throw exception like ' || quote_literal($2) );
-$$ LANGUAGE sql;
-
--- throws_matching ( sql, pattern, description )
-CREATE OR REPLACE FUNCTION throws_matching ( TEXT, TEXT, TEXT )
-RETURNS TEXT AS $$
-BEGIN
-    EXECUTE _query($1);
-    RETURN ok( FALSE, $3 ) || E'\n' || diag( '    no exception thrown' );
-EXCEPTION WHEN OTHERS THEN
-    return _tlike( SQLERRM ~ $2, SQLERRM, $2, $3 );
-END;
-$$ LANGUAGE plpgsql;
-
--- throws_matching ( sql, pattern )
-CREATE OR REPLACE FUNCTION throws_matching ( TEXT, TEXT )
-RETURNS TEXT AS $$
-    SELECT throws_matching($1, $2, 'Should throw exception matching ' || quote_literal($2) );
-$$ LANGUAGE sql;
-
--- throws_imatching ( sql, pattern, description )
-CREATE OR REPLACE FUNCTION throws_imatching ( TEXT, TEXT, TEXT )
-RETURNS TEXT AS $$
-BEGIN
-    EXECUTE _query($1);
-    RETURN ok( FALSE, $3 ) || E'\n' || diag( '    no exception thrown' );
-EXCEPTION WHEN OTHERS THEN
-    return _tlike( SQLERRM ~* $2, SQLERRM, $2, $3 );
-END;
-$$ LANGUAGE plpgsql;
-
--- throws_imatching ( sql, pattern )
-CREATE OR REPLACE FUNCTION throws_imatching ( TEXT, TEXT )
-RETURNS TEXT AS $$
-    SELECT throws_imatching($1, $2, 'Should throw exception matching ' || quote_literal($2) );
-$$ LANGUAGE sql;
-
--- roles_are( roles[], description )
-CREATE OR REPLACE FUNCTION roles_are( NAME[], TEXT )
-RETURNS TEXT AS $$
-    SELECT _are(
-        'roles',
-        ARRAY(
-            SELECT rolname
-              FROM pg_catalog.pg_roles
-            EXCEPT
-            SELECT $1[i]
-              FROM generate_series(1, array_upper($1, 1)) s(i)
-        ),
-        ARRAY(
-            SELECT $1[i]
-              FROM generate_series(1, array_upper($1, 1)) s(i)
-            EXCEPT
-            SELECT rolname
-              FROM pg_catalog.pg_roles
-        ),
-        $2
-    );
-$$ LANGUAGE SQL;
-
--- roles_are( roles[] )
-CREATE OR REPLACE FUNCTION roles_are( NAME[] )
-RETURNS TEXT AS $$
-    SELECT roles_are( $1, 'There should be the correct roles' );
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION _types_are ( NAME, NAME[], TEXT, CHAR[] )
-RETURNS TEXT AS $$
-    SELECT _are(
-        'types',
-        ARRAY(
-            SELECT t.typname
-              FROM pg_catalog.pg_type t
-              LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace
-             WHERE (
-                     t.typrelid = 0
-                 OR (SELECT c.relkind = 'c' FROM pg_catalog.pg_class c WHERE c.oid = t.typrelid)
-             )
-               AND NOT EXISTS(SELECT 1 FROM pg_catalog.pg_type el WHERE el.oid = t.typelem AND el.typarray = t.oid)
-               AND n.nspname = $1
-               AND t.typtype = ANY( COALESCE($4, ARRAY['b', 'c', 'd', 'p', 'e']) )
-            EXCEPT
-            SELECT $2[i]
-              FROM generate_series(1, array_upper($2, 1)) s(i)
-        ),
-        ARRAY(
-            SELECT $2[i]
-               FROM generate_series(1, array_upper($2, 1)) s(i)
-            EXCEPT
-            SELECT t.typname
-              FROM pg_catalog.pg_type t
-              LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace
-             WHERE (
-                     t.typrelid = 0
-                 OR (SELECT c.relkind = 'c' FROM pg_catalog.pg_class c WHERE c.oid = t.typrelid)
-             )
-               AND NOT EXISTS(SELECT 1 FROM pg_catalog.pg_type el WHERE el.oid = t.typelem AND el.typarray = t.oid)
-               AND n.nspname = $1
-               AND t.typtype = ANY( COALESCE($4, ARRAY['b', 'c', 'd', 'p', 'e']) )
-        ),
-        $3
-    );
-$$ LANGUAGE SQL;
-
--- types_are( schema, types[], description )
-CREATE OR REPLACE FUNCTION types_are ( NAME, NAME[], TEXT )
-RETURNS TEXT AS $$
-    SELECT _types_are( $1, $2, $3, NULL );
-$$ LANGUAGE SQL;
-
--- types_are( schema, types[] )
-CREATE OR REPLACE FUNCTION types_are ( NAME, NAME[] )
-RETURNS TEXT AS $$
-    SELECT _types_are( $1, $2, 'Schema ' || quote_ident($1) || ' should have the correct types', NULL );
-$$ LANGUAGE SQL;
-
--- types_are( types[], description )
-CREATE OR REPLACE FUNCTION _types_are ( NAME[], TEXT, CHAR[] )
-RETURNS TEXT AS $$
-    SELECT _are(
-        'types',
-        ARRAY(
-            SELECT t.typname
-              FROM pg_catalog.pg_type t
-              LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace
-             WHERE (
-                     t.typrelid = 0
-                 OR (SELECT c.relkind = 'c' FROM pg_catalog.pg_class c WHERE c.oid = t.typrelid)
-             )
-               AND NOT EXISTS(SELECT 1 FROM pg_catalog.pg_type el WHERE el.oid = t.typelem AND el.typarray = t.oid)
-               AND n.nspname NOT IN ('pg_catalog', 'information_schema')
-               AND pg_catalog.pg_type_is_visible(t.oid)
-               AND t.typtype = ANY( COALESCE($3, ARRAY['b', 'c', 'd', 'p', 'e']) )
-            EXCEPT
-            SELECT $1[i]
-              FROM generate_series(1, array_upper($1, 1)) s(i)
-        ),
-        ARRAY(
-            SELECT $1[i]
-               FROM generate_series(1, array_upper($1, 1)) s(i)
-            EXCEPT
-            SELECT t.typname
-              FROM pg_catalog.pg_type t
-              LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace
-             WHERE (
-                     t.typrelid = 0
-                 OR (SELECT c.relkind = 'c' FROM pg_catalog.pg_class c WHERE c.oid = t.typrelid)
-             )
-               AND NOT EXISTS(SELECT 1 FROM pg_catalog.pg_type el WHERE el.oid = t.typelem AND el.typarray = t.oid)
-               AND n.nspname NOT IN ('pg_catalog', 'information_schema')
-               AND pg_catalog.pg_type_is_visible(t.oid)
-               AND t.typtype = ANY( COALESCE($3, ARRAY['b', 'c', 'd', 'p', 'e']) )
-        ),
-        $2
-    );
-$$ LANGUAGE SQL;
-
-
--- types_are( types[], description )
-CREATE OR REPLACE FUNCTION types_are ( NAME[], TEXT )
-RETURNS TEXT AS $$
-    SELECT _types_are( $1, $2, NULL );
-$$ LANGUAGE SQL;
-
--- types_are( types[] )
-CREATE OR REPLACE FUNCTION types_are ( NAME[] )
-RETURNS TEXT AS $$
-    SELECT _types_are( $1, 'Search path ' || pg_catalog.current_setting('search_path') || ' should have the correct types', NULL );
-$$ LANGUAGE SQL;
-
--- domains_are( schema, domains[], description )
-CREATE OR REPLACE FUNCTION domains_are ( NAME, NAME[], TEXT )
-RETURNS TEXT AS $$
-    SELECT _types_are( $1, $2, $3, ARRAY['d'] );
-$$ LANGUAGE SQL;
-
--- domains_are( schema, domains[] )
-CREATE OR REPLACE FUNCTION domains_are ( NAME, NAME[] )
-RETURNS TEXT AS $$
-    SELECT _types_are( $1, $2, 'Schema ' || quote_ident($1) || ' should have the correct domains', ARRAY['d'] );
-$$ LANGUAGE SQL;
-
--- domains_are( domains[], description )
-CREATE OR REPLACE FUNCTION domains_are ( NAME[], TEXT )
-RETURNS TEXT AS $$
-    SELECT _types_are( $1, $2, ARRAY['d'] );
-$$ LANGUAGE SQL;
-
--- domains_are( domains[] )
-CREATE OR REPLACE FUNCTION domains_are ( NAME[] )
-RETURNS TEXT AS $$
-    SELECT _types_are( $1, 'Search path ' || pg_catalog.current_setting('search_path') || ' should have the correct domains', ARRAY['d'] );
-$$ LANGUAGE SQL;
-
--- enums_are( schema, enums[], description )
-CREATE OR REPLACE FUNCTION enums_are ( NAME, NAME[], TEXT )
-RETURNS TEXT AS $$
-    SELECT _types_are( $1, $2, $3, ARRAY['e'] );
-$$ LANGUAGE SQL;
-
--- enums_are( schema, enums[] )
-CREATE OR REPLACE FUNCTION enums_are ( NAME, NAME[] )
-RETURNS TEXT AS $$
-    SELECT _types_are( $1, $2, 'Schema ' || quote_ident($1) || ' should have the correct enums', ARRAY['e'] );
-$$ LANGUAGE SQL;
-
--- enums_are( enums[], description )
-CREATE OR REPLACE FUNCTION enums_are ( NAME[], TEXT )
-RETURNS TEXT AS $$
-    SELECT _types_are( $1, $2, ARRAY['e'] );
-$$ LANGUAGE SQL;
-
--- enums_are( enums[] )
-CREATE OR REPLACE FUNCTION enums_are ( NAME[] )
-RETURNS TEXT AS $$
-    SELECT _types_are( $1, 'Search path ' || pg_catalog.current_setting('search_path') || ' should have the correct enums', ARRAY['e'] );
-$$ LANGUAGE SQL;
-
--- _dexists( schema, domain )
-CREATE OR REPLACE FUNCTION _dexists ( NAME, NAME )
-RETURNS BOOLEAN AS $$
-   SELECT EXISTS(
-       SELECT true
-         FROM pg_catalog.pg_namespace n
-         JOIN pg_catalog.pg_type t on n.oid = t.typnamespace
-        WHERE n.nspname = $1
-          AND t.typname = $2
-   );
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION _dexists ( NAME )
-RETURNS BOOLEAN AS $$
-   SELECT EXISTS(
-       SELECT true
-         FROM pg_catalog.pg_type t
-        WHERE t.typname = $1
-          AND pg_catalog.pg_type_is_visible(t.oid)
-   );
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION _get_dtype( NAME, TEXT, BOOLEAN )
-RETURNS TEXT AS $$
-    SELECT display_type(CASE WHEN $3 THEN tn.nspname ELSE NULL END, t.oid, t.typtypmod)
-      FROM pg_catalog.pg_type d
-      JOIN pg_catalog.pg_namespace dn ON d.typnamespace = dn.oid
-      JOIN pg_catalog.pg_type t       ON d.typbasetype  = t.oid
-      JOIN pg_catalog.pg_namespace tn ON d.typnamespace = tn.oid
-     WHERE d.typisdefined
-       AND dn.nspname = $1
-       AND d.typname  = LOWER($2)
-       AND d.typtype  = 'd'
-$$ LANGUAGE sql;
-
-CREATE OR REPLACE FUNCTION _get_dtype( NAME )
-RETURNS TEXT AS $$
-    SELECT display_type(t.oid, t.typtypmod)
-      FROM pg_catalog.pg_type d
-      JOIN pg_catalog.pg_type t  ON d.typbasetype  = t.oid
-     WHERE d.typisdefined
-       AND d.typname = LOWER($1)
-       AND d.typtype = 'd'
-$$ LANGUAGE sql;
-
--- domain_type_is( schema, domain, schema, type, description )
-CREATE OR REPLACE FUNCTION domain_type_is( NAME, TEXT, NAME, TEXT, TEXT )
-RETURNS TEXT AS $$
-DECLARE
-    actual_type TEXT := _get_dtype($1, $2, true);
-BEGIN
-    IF actual_type IS NULL THEN
-        RETURN fail( $5 ) || E'\n' || diag (
-            '   Domain ' || quote_ident($1) || '.' || $2
-            || ' does not exist'
-        );
-    END IF;
-
-    RETURN is( actual_type, quote_ident($3) || '.' || _quote_ident_like($4, actual_type), $5 );
-END;
-$$ LANGUAGE plpgsql;
-
--- domain_type_is( schema, domain, schema, type )
-CREATE OR REPLACE FUNCTION domain_type_is( NAME, TEXT, NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT domain_type_is(
-        $1, $2, $3, $4,
-        'Domain ' || quote_ident($1) || '.' || $2
-        || ' should extend type ' || quote_ident($3) || '.' || $4
-    );
-$$ LANGUAGE SQL;
-
--- domain_type_is( schema, domain, type, description )
-CREATE OR REPLACE FUNCTION domain_type_is( NAME, TEXT, TEXT, TEXT )
-RETURNS TEXT AS $$
-DECLARE
-    actual_type TEXT := _get_dtype($1, $2, false);
-BEGIN
-    IF actual_type IS NULL THEN
-        RETURN fail( $4 ) || E'\n' || diag (
-            '   Domain ' || quote_ident($1) || '.' || $2
-            || ' does not exist'
-        );
-    END IF;
-
-    RETURN is( actual_type, _quote_ident_like($3, actual_type), $4 );
-END;
-$$ LANGUAGE plpgsql;
-
--- domain_type_is( schema, domain, type )
-CREATE OR REPLACE FUNCTION domain_type_is( NAME, TEXT, TEXT )
-RETURNS TEXT AS $$
-    SELECT domain_type_is(
-        $1, $2, $3,
-        'Domain ' || quote_ident($1) || '.' || $2
-        || ' should extend type ' || $3
-    );
-$$ LANGUAGE SQL;
-
--- domain_type_is( domain, type, description )
-CREATE OR REPLACE FUNCTION domain_type_is( TEXT, TEXT, TEXT )
-RETURNS TEXT AS $$
-DECLARE
-    actual_type TEXT := _get_dtype($1);
-BEGIN
-    IF actual_type IS NULL THEN
-        RETURN fail( $3 ) || E'\n' || diag (
-            '   Domain ' ||  $1 || ' does not exist'
-        );
-    END IF;
-
-    RETURN is( actual_type, _quote_ident_like($2, actual_type), $3 );
-END;
-$$ LANGUAGE plpgsql;
-
--- domain_type_is( domain, type )
-CREATE OR REPLACE FUNCTION domain_type_is( TEXT, TEXT )
-RETURNS TEXT AS $$
-    SELECT domain_type_is(
-        $1, $2,
-        'Domain ' || $1 || ' should extend type ' || $2
-    );
-$$ LANGUAGE SQL;
-
--- domain_type_isnt( schema, domain, schema, type, description )
-CREATE OR REPLACE FUNCTION domain_type_isnt( NAME, TEXT, NAME, TEXT, TEXT )
-RETURNS TEXT AS $$
-DECLARE
-    actual_type TEXT := _get_dtype($1, $2, true);
-BEGIN
-    IF actual_type IS NULL THEN
-        RETURN fail( $5 ) || E'\n' || diag (
-            '   Domain ' || quote_ident($1) || '.' || $2
-            || ' does not exist'
-        );
-    END IF;
-
-    RETURN isnt( actual_type, quote_ident($3) || '.' || _quote_ident_like($4, actual_type), $5 );
-END;
-$$ LANGUAGE plpgsql;
-
--- domain_type_isnt( schema, domain, schema, type )
-CREATE OR REPLACE FUNCTION domain_type_isnt( NAME, TEXT, NAME, TEXT )
-RETURNS TEXT AS $$
-    SELECT domain_type_isnt(
-        $1, $2, $3, $4,
-        'Domain ' || quote_ident($1) || '.' || $2
-        || ' should not extend type ' || quote_ident($3) || '.' || $4
-    );
-$$ LANGUAGE SQL;
-
--- domain_type_isnt( schema, domain, type, description )
-CREATE OR REPLACE FUNCTION domain_type_isnt( NAME, TEXT, TEXT, TEXT )
-RETURNS TEXT AS $$
-DECLARE
-    actual_type TEXT := _get_dtype($1, $2, false);
-BEGIN
-    IF actual_type IS NULL THEN
-        RETURN fail( $4 ) || E'\n' || diag (
-            '   Domain ' || quote_ident($1) || '.' || $2
-            || ' does not exist'
-        );
-    END IF;
-
-    RETURN isnt( actual_type, _quote_ident_like($3, actual_type), $4 );
-END;
-$$ LANGUAGE plpgsql;
-
--- domain_type_isnt( schema, domain, type )
-CREATE OR REPLACE FUNCTION domain_type_isnt( NAME, TEXT, TEXT )
-RETURNS TEXT AS $$
-    SELECT domain_type_isnt(
-        $1, $2, $3,
-        'Domain ' || quote_ident($1) || '.' || $2
-        || ' should not extend type ' || $3
-    );
-$$ LANGUAGE SQL;
-
--- domain_type_isnt( domain, type, description )
-CREATE OR REPLACE FUNCTION domain_type_isnt( TEXT, TEXT, TEXT )
-RETURNS TEXT AS $$
-DECLARE
-    actual_type TEXT := _get_dtype($1);
-BEGIN
-    IF actual_type IS NULL THEN
-        RETURN fail( $3 ) || E'\n' || diag (
-            '   Domain ' ||  $1 || ' does not exist'
-        );
-    END IF;
-
-    RETURN isnt( actual_type, _quote_ident_like($2, actual_type), $3 );
-END;
-$$ LANGUAGE plpgsql;
-
--- domain_type_isnt( domain, type )
-CREATE OR REPLACE FUNCTION domain_type_isnt( TEXT, TEXT )
-RETURNS TEXT AS $$
-    SELECT domain_type_isnt(
-        $1, $2,
-        'Domain ' || $1 || ' should not extend type ' || $2
-    );
-$$ LANGUAGE SQL;
-
--- row_eq( sql, record, description )
-CREATE OR REPLACE FUNCTION row_eq( TEXT, anyelement, TEXT )
-RETURNS TEXT AS $$
-DECLARE
-    rec    RECORD;
-BEGIN
-    EXECUTE _query($1) INTO rec;
-    IF NOT rec IS DISTINCT FROM $2 THEN RETURN ok(true, $3); END IF;
-    RETURN ok(false, $3 ) || E'\n' || diag(
-           '        have: ' || CASE WHEN rec IS NULL THEN 'NULL' ELSE rec::text END ||
-        E'\n        want: ' || CASE WHEN $2  IS NULL THEN 'NULL' ELSE $2::text  END
-    );
-END;
-$$ LANGUAGE plpgsql;
-
--- row_eq( sql, record )
-CREATE OR REPLACE FUNCTION row_eq( TEXT, anyelement )
-RETURNS TEXT AS $$
-    SELECT row_eq($1, $2, NULL );
-$$ LANGUAGE sql;
-
--- triggers_are( schema, table, triggers[], description )
-CREATE OR REPLACE FUNCTION triggers_are( NAME, NAME, NAME[], TEXT )
-RETURNS TEXT AS $$
-    SELECT _are(
-        'triggers',
-        ARRAY(
-            SELECT t.tgname
-              FROM pg_catalog.pg_trigger t
-              JOIN pg_catalog.pg_class c     ON c.oid = t.tgrelid
-              JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
-             WHERE n.nspname = $1
-               AND c.relname = $2
-            EXCEPT
-            SELECT $3[i]
-              FROM generate_series(1, array_upper($3, 1)) s(i)
-        ),
-        ARRAY(
-            SELECT $3[i]
-              FROM generate_series(1, array_upper($3, 1)) s(i)
-            EXCEPT
-            SELECT t.tgname
-              FROM pg_catalog.pg_trigger t
-              JOIN pg_catalog.pg_class c     ON c.oid = t.tgrelid
-              JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
-             WHERE n.nspname = $1
-               AND c.relname = $2
-        ),
-        $4
-    );
-$$ LANGUAGE SQL;
-
--- triggers_are( schema, table, triggers[] )
-CREATE OR REPLACE FUNCTION triggers_are( NAME, NAME, NAME[] )
-RETURNS TEXT AS $$
-    SELECT triggers_are( $1, $2, $3, 'Table ' || quote_ident($1) || '.' || quote_ident($2) || ' should have the correct triggers' );
-$$ LANGUAGE SQL;
-
--- triggers_are( table, triggers[], description )
-CREATE OR REPLACE FUNCTION triggers_are( NAME, NAME[], TEXT )
-RETURNS TEXT AS $$
-    SELECT _are(
-        'triggers',
-        ARRAY(
-            SELECT t.tgname
-              FROM pg_catalog.pg_trigger t
-              JOIN pg_catalog.pg_class c ON c.oid = t.tgrelid
-              JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
-             WHERE c.relname = $1
-               AND n.nspname NOT IN ('pg_catalog', 'information_schema')
-            EXCEPT
-            SELECT $2[i]
-              FROM generate_series(1, array_upper($2, 1)) s(i)
-        ),
-        ARRAY(
-            SELECT $2[i]
-              FROM generate_series(1, array_upper($2, 1)) s(i)
-            EXCEPT
-            SELECT t.tgname
-              FROM pg_catalog.pg_trigger t
-              JOIN pg_catalog.pg_class c ON c.oid = t.tgrelid
-              JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
-               AND n.nspname NOT IN ('pg_catalog', 'information_schema')
-        ),
-        $3
-    );
-$$ LANGUAGE SQL;
-
--- triggers_are( table, triggers[] )
-CREATE OR REPLACE FUNCTION triggers_are( NAME, NAME[] )
-RETURNS TEXT AS $$
-    SELECT triggers_are( $1, $2, 'Table ' || quote_ident($1) || ' should have the correct triggers' );
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION _areni ( text, text[], text[], TEXT )
-RETURNS TEXT AS $$
-DECLARE
-    what    ALIAS FOR $1;
-    extras  ALIAS FOR $2;
-    missing ALIAS FOR $3;
-    descr   ALIAS FOR $4;
-    msg     TEXT    := '';
-    res     BOOLEAN := TRUE;
-BEGIN
-    IF extras[1] IS NOT NULL THEN
-        res = FALSE;
-        msg := E'\n' || diag(
-            '    Extra ' || what || E':\n        '
-            ||  array_to_string( extras, E'\n        ' )
-        );
-    END IF;
-    IF missing[1] IS NOT NULL THEN
-        res = FALSE;
-        msg := msg || E'\n' || diag(
-            '    Missing ' || what || E':\n        '
-            ||  array_to_string( missing, E'\n        ' )
-        );
-    END IF;
-
-    RETURN ok(res, descr) || msg;
-END;
-$$ LANGUAGE plpgsql;
-
-
--- casts_are( casts[], description )
-CREATE OR REPLACE FUNCTION casts_are ( TEXT[], TEXT )
-RETURNS TEXT AS $$
-    SELECT _areni(
-        'casts',
-        ARRAY(
-            SELECT display_type(castsource, NULL) || ' AS ' || display_type(casttarget, NULL)
-              FROM pg_catalog.pg_cast c
-            EXCEPT
-            SELECT $1[i]
-              FROM generate_series(1, array_upper($1, 1)) s(i)
-        ),
-        ARRAY(
-            SELECT $1[i]
-              FROM generate_series(1, array_upper($1, 1)) s(i)
-            EXCEPT
-            SELECT display_type(castsource, NULL) || ' AS ' || display_type(casttarget, NULL)
-              FROM pg_catalog.pg_cast c
-        ),
-        $2
-    );
-$$ LANGUAGE sql;
-
--- casts_are( casts[] )
-CREATE OR REPLACE FUNCTION casts_are ( TEXT[] )
-RETURNS TEXT AS $$
-    SELECT casts_are( $1, 'There should be the correct casts');
-$$ LANGUAGE SQL;
-
-CREATE OR REPLACE FUNCTION display_oper ( NAME, OID )
-RETURNS TEXT AS $$
-    SELECT $1 || substring($2::regoperator::text, '[(][^)]+[)]$')
-$$ LANGUAGE SQL;
-
--- operators_are( schema, operators[], description )
-CREATE OR REPLACE FUNCTION operators_are( NAME, TEXT[], TEXT )
-RETURNS TEXT AS $$
-    SELECT _areni(
-        'operators',
-        ARRAY(
-            SELECT display_oper(o.oprname, o.oid) || ' RETURNS ' || o.oprresult::regtype
-              FROM pg_catalog.pg_operator o
-              JOIN pg_catalog.pg_namespace n ON o.oprnamespace = n.oid
-             WHERE n.nspname = $1
-            EXCEPT
-            SELECT $2[i]
-              FROM generate_series(1, array_upper($2, 1)) s(i)
-        ),
-        ARRAY(
-            SELECT $2[i]
-              FROM generate_series(1, array_upper($2, 1)) s(i)
-            EXCEPT
-            SELECT display_oper(o.oprname, o.oid) || ' RETURNS ' || o.oprresult::regtype
-              FROM pg_catalog.pg_operator o
-              JOIN pg_catalog.pg_namespace n ON o.oprnamespace = n.oid
-             WHERE n.nspname = $1
-        ),
-        $3
-    );
-$$ LANGUAGE SQL;
-
--- operators_are( schema, operators[] )
-CREATE OR REPLACE FUNCTION operators_are ( NAME, TEXT[] )
-RETURNS TEXT AS $$
-    SELECT operators_are($1, $2, 'Schema ' || quote_ident($1) || ' should have the correct operators' );
-$$ LANGUAGE SQL;
-
--- operators_are( operators[], description )
-CREATE OR REPLACE FUNCTION operators_are( TEXT[], TEXT )
-RETURNS TEXT AS $$
-    SELECT _areni(
-        'operators',
-        ARRAY(
-            SELECT display_oper(o.oprname, o.oid) || ' RETURNS ' || o.oprresult::regtype
-              FROM pg_catalog.pg_operator o
-              JOIN pg_catalog.pg_namespace n ON o.oprnamespace = n.oid
-             WHERE pg_catalog.pg_operator_is_visible(o.oid)
-               AND n.nspname NOT IN ('pg_catalog', 'information_schema')
-            EXCEPT
-            SELECT $1[i]
-              FROM generate_series(1, array_upper($1, 1)) s(i)
-        ),
-        ARRAY(
-            SELECT $1[i]
-              FROM generate_series(1, array_upper($1, 1)) s(i)
-            EXCEPT
-            SELECT display_oper(o.oprname, o.oid) || ' RETURNS ' || o.oprresult::regtype
-              FROM pg_catalog.pg_operator o
-              JOIN pg_catalog.pg_namespace n ON o.oprnamespace = n.oid
-             WHERE pg_catalog.pg_operator_is_visible(o.oid)
-               AND n.nspname NOT IN ('pg_catalog', 'information_schema')
-        ),
-        $2
-    );
-$$ LANGUAGE SQL;
-
--- operators_are( operators[] )
-CREATE OR REPLACE FUNCTION operators_are ( TEXT[] )
-RETURNS TEXT AS $$
-    SELECT operators_are($1, 'There should be the correct operators')
-$$ LANGUAGE SQL;
-
--- columns_are( schema, table, columns[], description )
-CREATE OR REPLACE FUNCTION columns_are( NAME, NAME, NAME[], TEXT )
-RETURNS TEXT AS $$
-    SELECT _are(
-        'columns',
-        ARRAY(
-            SELECT a.attname
-              FROM pg_catalog.pg_namespace n
-              JOIN pg_catalog.pg_class c ON n.oid = c.relnamespace
-              JOIN pg_catalog.pg_attribute a ON c.oid = a.attrelid
-             WHERE n.nspname = $1
-               AND c.relname = $2
-               AND a.attnum > 0
-               AND NOT a.attisdropped
-            EXCEPT
-            SELECT $3[i]
-              FROM generate_series(1, array_upper($3, 1)) s(i)
-        ),
-        ARRAY(
-            SELECT $3[i]
-              FROM generate_series(1, array_upper($3, 1)) s(i)
-            EXCEPT
-            SELECT a.attname
-              FROM pg_catalog.pg_namespace n
-              JOIN pg_catalog.pg_class c ON n.oid = c.relnamespace
-              JOIN pg_catalog.pg_attribute a ON c.oid = a.attrelid
-             WHERE n.nspname = $1
-               AND c.relname = $2
-               AND a.attnum > 0
-               AND NOT a.attisdropped
-        ),
-        $4
-    );
-$$ LANGUAGE SQL;
-
--- columns_are( schema, table, columns[] )
-CREATE OR REPLACE FUNCTION columns_are( NAME, NAME, NAME[] )
-RETURNS TEXT AS $$
-    SELECT columns_are( $1, $2, $3, 'Table ' || quote_ident($1) || '.' || quote_ident($2) || ' should have the correct columns' );
-$$ LANGUAGE SQL;
-
--- columns_are( table, columns[], description )
-CREATE OR REPLACE FUNCTION columns_are( NAME, NAME[], TEXT )
-RETURNS TEXT AS $$
-    SELECT _are(
-        'columns',
-        ARRAY(
-            SELECT a.attname
-              FROM pg_catalog.pg_namespace n
-              JOIN pg_catalog.pg_class c ON n.oid = c.relnamespace
-              JOIN pg_catalog.pg_attribute a ON c.oid = a.attrelid
-             WHERE n.nspname NOT IN ('pg_catalog', 'information_schema')
-               AND pg_catalog.pg_table_is_visible(c.oid)
-               AND c.relname = $1
-               AND a.attnum > 0
-               AND NOT a.attisdropped
-            EXCEPT
-            SELECT $2[i]
-              FROM generate_series(1, array_upper($2, 1)) s(i)
-        ),
-        ARRAY(
-            SELECT $2[i]
-              FROM generate_series(1, array_upper($2, 1)) s(i)
-            EXCEPT
-            SELECT a.attname
-              FROM pg_catalog.pg_namespace n
-              JOIN pg_catalog.pg_class c ON n.oid = c.relnamespace
-              JOIN pg_catalog.pg_attribute a ON c.oid = a.attrelid
-             WHERE n.nspname NOT IN ('pg_catalog', 'information_schema')
-               AND pg_catalog.pg_table_is_visible(c.oid)
-               AND c.relname = $1
-               AND a.attnum > 0
-               AND NOT a.attisdropped
-        ),
-        $3
-    );
-$$ LANGUAGE SQL;
-
--- columns_are( table, columns[] )
-CREATE OR REPLACE FUNCTION columns_are( NAME, NAME[] )
-RETURNS TEXT AS $$
-    SELECT columns_are( $1, $2, 'Table ' || quote_ident($1) || ' should have the correct columns' );
-$$ LANGUAGE SQL;
-
--- _get_db_owner( dbname )
-CREATE OR REPLACE FUNCTION _get_db_owner( NAME )
-RETURNS NAME AS $$
-    SELECT pg_catalog.pg_get_userbyid(datdba)
-      FROM pg_catalog.pg_database
-     WHERE datname = $1;
-$$ LANGUAGE SQL;
-
--- db_owner_is ( dbname, user, description )
-CREATE OR REPLACE FUNCTION db_owner_is ( NAME, NAME, TEXT )
-RETURNS TEXT AS $$
-DECLARE
-    dbowner NAME := _get_db_owner($1);
-BEGIN
-    -- Make sure the database exists.
-    IF dbowner IS NULL THEN
-        RETURN ok(FALSE, $3) || E'\n' || diag(
-            E'    Database ' || quote_ident($1) || ' does not exist'
-        );
-    END IF;
-
-    RETURN is(dbowner, $2, $3);
-END;
-$$ LANGUAGE plpgsql;
-
--- db_owner_is ( dbname, user )
-CREATE OR REPLACE FUNCTION db_owner_is ( NAME, NAME )
-RETURNS TEXT AS $$
-    SELECT db_owner_is(
-        $1, $2,
-        'Database ' || quote_ident($1) || ' should be owned by ' || quote_ident($2)
-    );
-$$ LANGUAGE sql;
-
diff --git a/legacyworlds-server-data/db-structure/tests/user/020-extensions/010-dblink.sql b/legacyworlds-server-data/db-structure/tests/user/020-extensions/010-dblink.sql
deleted file mode 100644
index 271e969..0000000
--- a/legacyworlds-server-data/db-structure/tests/user/020-extensions/010-dblink.sql
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Test the configuration of the dblink extension from the user's perspective
- */
-BEGIN;
-	SELECT plan( 3 );
-	
-	SELECT diag_test_name( 'dblink - Connection' );
-	SELECT lives_ok(
-		$$ SELECT dblink_connect( 'cn_logging' , 'srv_logging' ) $$
-	);
-	
-	SELECT diag_test_name( 'dblink - Remote user = local user' );
-	SELECT is( username , current_user::TEXT )
-		FROM dblink( 'cn_logging' , 'SELECT current_user' )
-			AS ( username TEXT );
-
-	SELECT diag_test_name( 'dblink - Disconnection' );
-	SELECT lives_ok(
-		$$ SELECT dblink_disconnect( 'cn_logging' ) $$
-	);
-	
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/user/030-data/075-resources/010-defs-resources.sql b/legacyworlds-server-data/db-structure/tests/user/030-data/075-resources/010-defs-resources.sql
deleted file mode 100644
index c04c7eb..0000000
--- a/legacyworlds-server-data/db-structure/tests/user/030-data/075-resources/010-defs-resources.sql
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Test privileges on defs.resources
- */
-BEGIN;
-	SELECT plan( 4 );
-	
-	SELECT diag_test_name( 'defs.resources - INSERT privileges' );
-	SELECT throws_ok(
-		$$ INSERT INTO defs.resources(
-			resource_name_id , resource_description_id , resource_weight
-		) VALUES (
-			1 , 2 , 1
-		); $$ ,
-		42501 );
-
-	SELECT diag_test_name( 'defs.resources - UPDATE privileges' );
-	SELECT throws_ok(
-		$$ UPDATE defs.resources SET resource_weight = 10; $$ ,
-		42501 );
-
-	SELECT diag_test_name( 'defs.resources - SELECT privileges' );
-	SELECT throws_ok(
-		$$ SELECT * FROM defs.resources; $$ ,
-		42501 );
-
-	SELECT diag_test_name( 'defs.resources - DELETE privileges' );
-	SELECT throws_ok(
-		$$ DELETE FROM defs.resources; $$ ,
-		42501 );
-
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/user/030-data/075-resources/020-defs-natural-resources.sql b/legacyworlds-server-data/db-structure/tests/user/030-data/075-resources/020-defs-natural-resources.sql
deleted file mode 100644
index 40894ba..0000000
--- a/legacyworlds-server-data/db-structure/tests/user/030-data/075-resources/020-defs-natural-resources.sql
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Test privileges on defs.natural_resources
- */
-BEGIN;
-	SELECT plan( 4 );
-	
-	SELECT diag_test_name( 'defs.natural_resources - INSERT privileges' );
-	SELECT throws_ok(
-		$$ INSERT INTO defs.natural_resources( resource_name_id ) VALUES ( 1 ); $$ ,
-		42501 );
-
-	SELECT diag_test_name( 'defs.natural_resources - UPDATE privileges' );
-	SELECT throws_ok(
-		$$ UPDATE defs.natural_resources SET natres_p_presence = 0.5; $$ ,
-		42501 );
-
-	SELECT diag_test_name( 'defs.natural_resources - SELECT privileges' );
-	SELECT throws_ok(
-		$$ SELECT * FROM defs.natural_resources; $$ ,
-		42501 );
-
-	SELECT diag_test_name( 'defs.natural_resources - DELETE privileges' );
-	SELECT throws_ok(
-		$$ DELETE FROM defs.natural_resources; $$ ,
-		42501 );
-
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/user/030-data/100-universe/010-verse-resource-providers.sql b/legacyworlds-server-data/db-structure/tests/user/030-data/100-universe/010-verse-resource-providers.sql
deleted file mode 100644
index 227789b..0000000
--- a/legacyworlds-server-data/db-structure/tests/user/030-data/100-universe/010-verse-resource-providers.sql
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Test privileges on verse.resource_providers
- */
-BEGIN;
-	SELECT plan( 4 );
-	
-	SELECT diag_test_name( 'verse.resource_providers - INSERT privileges' );
-	SELECT throws_ok(
-		$$ INSERT INTO verse.resource_providers( resource_name_id ) VALUES ( 1 ); $$ ,
-		42501 );
-
-	SELECT diag_test_name( 'verse.resource_providers - UPDATE privileges' );
-	SELECT throws_ok(
-		$$ UPDATE verse.resource_providers SET resprov_quantity = 42; $$ ,
-		42501 );
-
-	SELECT diag_test_name( 'verse.resource_providers - SELECT privileges' );
-	SELECT throws_ok(
-		$$ SELECT * FROM verse.resource_providers; $$ ,
-		42501 );
-
-	SELECT diag_test_name( 'verse.resource_providers - DELETE privileges' );
-	SELECT throws_ok(
-		$$ DELETE FROM verse.resource_providers; $$ ,
-		42501 );
-
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/user/030-data/100-universe/020-verse-planet-resources.sql b/legacyworlds-server-data/db-structure/tests/user/030-data/100-universe/020-verse-planet-resources.sql
deleted file mode 100644
index 00fa1e4..0000000
--- a/legacyworlds-server-data/db-structure/tests/user/030-data/100-universe/020-verse-planet-resources.sql
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Test privileges on verse.planet_resources
- */
-BEGIN;
-	SELECT plan( 4 );
-	
-	SELECT diag_test_name( 'verse.planet_resources - INSERT privileges' );
-	SELECT throws_ok(
-		$$ INSERT INTO verse.planet_resources( resource_name_id ) VALUES ( 1 ); $$ ,
-		42501 );
-
-	SELECT diag_test_name( 'verse.resource_providers - UPDATE privileges' );
-	SELECT throws_ok(
-		$$ UPDATE verse.planet_resources SET pres_income = 42; $$ ,
-		42501 );
-
-	SELECT diag_test_name( 'verse.planet_resources - SELECT privileges' );
-	SELECT throws_ok(
-		$$ SELECT * FROM verse.planet_resources; $$ ,
-		42501 );
-
-	SELECT diag_test_name( 'verse.planet_resources - DELETE privileges' );
-	SELECT throws_ok(
-		$$ DELETE FROM verse.planet_resources; $$ ,
-		42501 );
-
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/user/030-data/110-empires/010-empire-resources.sql b/legacyworlds-server-data/db-structure/tests/user/030-data/110-empires/010-empire-resources.sql
deleted file mode 100644
index b565b91..0000000
--- a/legacyworlds-server-data/db-structure/tests/user/030-data/110-empires/010-empire-resources.sql
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Test privileges on emp.resources
- */
-BEGIN;
-	SELECT plan( 4 );
-	
-	SELECT diag_test_name( 'emp.resources - INSERT privileges' );
-	SELECT throws_ok(
-		$$ INSERT INTO emp.resources( resource_name_id ) VALUES ( 1 ); $$ ,
-		42501 );
-
-	SELECT diag_test_name( 'emp.resources - UPDATE privileges' );
-	SELECT throws_ok(
-		$$ UPDATE emp.resources SET empres_possessed = 42; $$ ,
-		42501 );
-
-	SELECT diag_test_name( 'emp.resources - SELECT privileges' );
-	SELECT throws_ok(
-		$$ SELECT * FROM emp.resources; $$ ,
-		42501 );
-
-	SELECT diag_test_name( 'emp.resources - DELETE privileges' );
-	SELECT throws_ok(
-		$$ DELETE FROM emp.resources; $$ ,
-		42501 );
-
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/user/030-data/110-empires/020-empire-mining-settings.sql b/legacyworlds-server-data/db-structure/tests/user/030-data/110-empires/020-empire-mining-settings.sql
deleted file mode 100644
index 040d66b..0000000
--- a/legacyworlds-server-data/db-structure/tests/user/030-data/110-empires/020-empire-mining-settings.sql
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Test privileges on emp.mining_settings
- */
-BEGIN;
-	SELECT plan( 4 );
-	
-	SELECT diag_test_name( 'emp.mining_settings - INSERT privileges' );
-	SELECT throws_ok(
-		$$ INSERT INTO emp.mining_settings( resource_name_id ) VALUES ( 1 ); $$ ,
-		42501 );
-
-	SELECT diag_test_name( 'emp.mining_settings - UPDATE privileges' );
-	SELECT throws_ok(
-		$$ UPDATE emp.mining_settings SET empmset_weight = 42; $$ ,
-		42501 );
-
-	SELECT diag_test_name( 'emp.mining_settings - SELECT privileges' );
-	SELECT throws_ok(
-		$$ SELECT * FROM emp.mining_settings; $$ ,
-		42501 );
-
-	SELECT diag_test_name( 'emp.mining_settings - DELETE privileges' );
-	SELECT throws_ok(
-		$$ DELETE FROM emp.mining_settings; $$ ,
-		42501 );
-
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/user/030-data/110-empires/030-empire-planet-mining-settings.sql b/legacyworlds-server-data/db-structure/tests/user/030-data/110-empires/030-empire-planet-mining-settings.sql
deleted file mode 100644
index 34d1e27..0000000
--- a/legacyworlds-server-data/db-structure/tests/user/030-data/110-empires/030-empire-planet-mining-settings.sql
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Test privileges on emp.planet_mining_settings
- */
-BEGIN;
-	SELECT plan( 4 );
-	
-	SELECT diag_test_name( 'emp.planet_mining_settings - INSERT privileges' );
-	SELECT throws_ok(
-		$$ INSERT INTO emp.planet_mining_settings( resource_name_id ) VALUES ( 1 ); $$ ,
-		42501 );
-
-	SELECT diag_test_name( 'emp.planet_mining_settings - UPDATE privileges' );
-	SELECT throws_ok(
-		$$ UPDATE emp.planet_mining_settings SET emppmset_weight = 42; $$ ,
-		42501 );
-
-	SELECT diag_test_name( 'emp.planet_mining_settings - SELECT privileges' );
-	SELECT throws_ok(
-		$$ SELECT * FROM emp.planet_mining_settings; $$ ,
-		42501 );
-
-	SELECT diag_test_name( 'emp.planet_mining_settings - DELETE privileges' );
-	SELECT throws_ok(
-		$$ DELETE FROM emp.planet_mining_settings; $$ ,
-		42501 );
-
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/user/030-data/145-updates/010-update-targets.sql b/legacyworlds-server-data/db-structure/tests/user/030-data/145-updates/010-update-targets.sql
deleted file mode 100644
index 70343c3..0000000
--- a/legacyworlds-server-data/db-structure/tests/user/030-data/145-updates/010-update-targets.sql
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Test privileges on sys.update_targets
- */
-BEGIN;
-	SELECT plan( 4 );
-	
-	SELECT diag_test_name( 'sys.update_targets - No INSERT privilege' );
-	SELECT throws_ok(
-		$$ INSERT INTO sys.update_targets DEFAULT VALUES; $$ ,
-		42501 );
-
-	SELECT diag_test_name( 'sys.update_targets - No UPDATE privilege' );
-	SELECT throws_ok(
-		$$ UPDATE sys.update_targets SET updtgt_id = 42; $$ ,
-		42501 );
-
-	SELECT diag_test_name( 'sys.update_targets - No SELECT privilege' );
-	SELECT throws_ok(
-		$$ SELECT * FROM sys.update_targets; $$ ,
-		42501 );
-
-	SELECT diag_test_name( 'sys.update_targets - No DELETE privilege' );
-	SELECT throws_ok(
-		$$ DELETE FROM sys.update_targets; $$ ,
-		42501 );
-
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/user/030-data/145-updates/020-update-types.sql b/legacyworlds-server-data/db-structure/tests/user/030-data/145-updates/020-update-types.sql
deleted file mode 100644
index fc33d56..0000000
--- a/legacyworlds-server-data/db-structure/tests/user/030-data/145-updates/020-update-types.sql
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Test privileges on sys.update_types
- */
-BEGIN;
-	SELECT plan( 4 );
-	
-	SELECT diag_test_name( 'sys.update_types - No INSERT privilege' );
-	SELECT throws_ok(
-		$$ INSERT INTO sys.update_types DEFAULT VALUES; $$ ,
-		42501 );
-
-	SELECT diag_test_name( 'sys.update_types - No UPDATE privilege' );
-	SELECT throws_ok(
-		$$ UPDATE sys.update_types SET updtgt_id = 42; $$ ,
-		42501 );
-
-	SELECT diag_test_name( 'sys.update_types - No SELECT privilege' );
-	SELECT throws_ok(
-		$$ SELECT * FROM sys.update_types; $$ ,
-		42501 );
-
-	SELECT diag_test_name( 'sys.update_types - No DELETE privilege' );
-	SELECT throws_ok(
-		$$ DELETE FROM sys.update_types; $$ ,
-		42501 );
-
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/user/030-data/145-updates/030-updates.sql b/legacyworlds-server-data/db-structure/tests/user/030-data/145-updates/030-updates.sql
deleted file mode 100644
index cc86cb3..0000000
--- a/legacyworlds-server-data/db-structure/tests/user/030-data/145-updates/030-updates.sql
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Test privileges on sys.updates
- */
-BEGIN;
-	SELECT plan( 4 );
-	
-	SELECT diag_test_name( 'sys.updates - No INSERT privilege' );
-	SELECT throws_ok(
-		$$ INSERT INTO sys.updates DEFAULT VALUES; $$ ,
-		42501 );
-
-	SELECT diag_test_name( 'sys.updates - No UPDATE privilege' );
-	SELECT throws_ok(
-		$$ UPDATE sys.updates SET updtgt_id = 42; $$ ,
-		42501 );
-
-	SELECT diag_test_name( 'sys.updates - No SELECT privilege' );
-	SELECT throws_ok(
-		$$ SELECT * FROM sys.updates; $$ ,
-		42501 );
-
-	SELECT diag_test_name( 'sys.updates - No DELETE privilege' );
-	SELECT throws_ok(
-		$$ DELETE FROM sys.updates; $$ ,
-		42501 );
-
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/user/030-data/150-logs/010-sys-logs.sql b/legacyworlds-server-data/db-structure/tests/user/030-data/150-logs/010-sys-logs.sql
deleted file mode 100644
index 78a8f77..0000000
--- a/legacyworlds-server-data/db-structure/tests/user/030-data/150-logs/010-sys-logs.sql
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Test privileges on sys.logs
- */
-BEGIN;
-	SELECT plan( 4 );
-	
-	SELECT diag_test_name( 'sys.logs - INSERT privileges' );
-	SELECT throws_ok(
-		$$ INSERT INTO sys.logs( component , level , message )
-			VALUES ( 'test' , 'WARNING'::log_level , 'test' );
-		$$ , 42501 );
-
-	SELECT diag_test_name( 'sys.logs - UPDATE privileges' );
-	SELECT throws_ok(
-		$$ UPDATE sys.logs SET component = 'retest'; $$ ,
-		42501 );
-
-	SELECT diag_test_name( 'sys.logs - SELECT privileges' );
-	SELECT lives_ok(
-		$$ SELECT * FROM sys.logs; $$
-	);
-
-	SELECT diag_test_name( 'sys.logs - DELETE privileges' );
-	SELECT throws_ok(
-		$$ DELETE FROM sys.logs; $$ ,
-		42501 );
-
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/user/040-functions/003-updates/010-get-table-pkey.sql b/legacyworlds-server-data/db-structure/tests/user/040-functions/003-updates/010-get-table-pkey.sql
deleted file mode 100644
index ef222fc..0000000
--- a/legacyworlds-server-data/db-structure/tests/user/040-functions/003-updates/010-get-table-pkey.sql
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
- * Test privileges on sys.get_table_pkey()
- */
-BEGIN;
-	SELECT plan( 1 );
-
-	SELECT diag_test_name( 'sys.get_table_pkey() - No EXECUTE privilege' );
-	SELECT throws_ok( $$ SELECT sys.get_table_pkey( 'a' , 'b' ) $$ , 42501 );
-	
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/user/040-functions/003-updates/020-tgf-speupd-before-insert.sql b/legacyworlds-server-data/db-structure/tests/user/040-functions/003-updates/020-tgf-speupd-before-insert.sql
deleted file mode 100644
index dae5ca2..0000000
--- a/legacyworlds-server-data/db-structure/tests/user/040-functions/003-updates/020-tgf-speupd-before-insert.sql
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
- * Test privileges on sys.tgf_speupd_before_insert()
- */
-BEGIN;
-	SELECT plan( 1 );
-
-	SELECT diag_test_name( 'sys.tgf_speupd_before_insert() - No EXECUTE privilege' );
-	SELECT throws_ok( $$ SELECT sys.tgf_speupd_before_insert( ) $$ , 42501 );
-	
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/user/040-functions/003-updates/030-tgf-speupd-after-delete.sql b/legacyworlds-server-data/db-structure/tests/user/040-functions/003-updates/030-tgf-speupd-after-delete.sql
deleted file mode 100644
index 431a387..0000000
--- a/legacyworlds-server-data/db-structure/tests/user/040-functions/003-updates/030-tgf-speupd-after-delete.sql
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
- * Test privileges on sys.tgf_speupd_after_delete()
- */
-BEGIN;
-	SELECT plan( 1 );
-
-	SELECT diag_test_name( 'sys.tgf_speupd_after_delete() - No EXECUTE privilege' );
-	SELECT throws_ok( $$ SELECT sys.tgf_speupd_after_delete( ) $$ , 42501 );
-	
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/user/040-functions/003-updates/040-insert-missing-updates.sql b/legacyworlds-server-data/db-structure/tests/user/040-functions/003-updates/040-insert-missing-updates.sql
deleted file mode 100644
index 2b22f82..0000000
--- a/legacyworlds-server-data/db-structure/tests/user/040-functions/003-updates/040-insert-missing-updates.sql
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
- * Test privileges on sys.insert_missing_updates()
- */
-BEGIN;
-	SELECT plan( 1 );
-
-	SELECT diag_test_name( 'sys.insert_missing_updates() - No EXECUTE privilege' );
-	SELECT throws_ok( $$ SELECT sys.insert_missing_updates( 1 ) $$ , 42501 );
-	
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/user/040-functions/003-updates/050-tgf-insert-missing-updates.sql b/legacyworlds-server-data/db-structure/tests/user/040-functions/003-updates/050-tgf-insert-missing-updates.sql
deleted file mode 100644
index 26f9c10..0000000
--- a/legacyworlds-server-data/db-structure/tests/user/040-functions/003-updates/050-tgf-insert-missing-updates.sql
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
- * Test privileges on sys.tgf_insert_missing_updates()
- */
-BEGIN;
-	SELECT plan( 1 );
-
-	SELECT diag_test_name( 'sys.tgf_insert_missing_updates() - No EXECUTE privilege' );
-	SELECT throws_ok( $$ SELECT sys.tgf_insert_missing_updates( ) $$ , 42501 );
-	
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/user/040-functions/003-updates/060-tgf-updtype-after-insert-row.sql b/legacyworlds-server-data/db-structure/tests/user/040-functions/003-updates/060-tgf-updtype-after-insert-row.sql
deleted file mode 100644
index 5fce32c..0000000
--- a/legacyworlds-server-data/db-structure/tests/user/040-functions/003-updates/060-tgf-updtype-after-insert-row.sql
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
- * Test privileges on sys.tgf_updtype_after_insert_row()
- */
-BEGIN;
-	SELECT plan( 1 );
-
-	SELECT diag_test_name( 'sys.tgf_updtype_after_insert_row() - No EXECUTE privilege' );
-	SELECT throws_ok( $$ SELECT sys.tgf_updtype_after_insert_row( ) $$ , 42501 );
-	
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/user/040-functions/003-updates/070-tgf-check-update-type-proc.sql b/legacyworlds-server-data/db-structure/tests/user/040-functions/003-updates/070-tgf-check-update-type-proc.sql
deleted file mode 100644
index 064dbdc..0000000
--- a/legacyworlds-server-data/db-structure/tests/user/040-functions/003-updates/070-tgf-check-update-type-proc.sql
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
- * Test privileges on sys.tgf_check_update_type_proc()
- */
-BEGIN;
-	SELECT plan( 1 );
-
-	SELECT diag_test_name( 'sys.tgf_check_update_type_proc() - No EXECUTE privilege' );
-	SELECT throws_ok( $$ SELECT sys.tgf_check_update_type_proc( ) $$ , 42501 );
-	
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/user/040-functions/003-updates/080-tgf-reorder-update-types.sql b/legacyworlds-server-data/db-structure/tests/user/040-functions/003-updates/080-tgf-reorder-update-types.sql
deleted file mode 100644
index bb27646..0000000
--- a/legacyworlds-server-data/db-structure/tests/user/040-functions/003-updates/080-tgf-reorder-update-types.sql
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
- * Test privileges on sys.tgf_reorder_update_types()
- */
-BEGIN;
-	SELECT plan( 1 );
-
-	SELECT diag_test_name( 'sys.tgf_reorder_update_types() - No EXECUTE privilege' );
-	SELECT throws_ok( $$ SELECT sys.tgf_reorder_update_types( ) $$ , 42501 );
-	
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/user/040-functions/003-updates/090-tgf-updtgt-before-insert.sql b/legacyworlds-server-data/db-structure/tests/user/040-functions/003-updates/090-tgf-updtgt-before-insert.sql
deleted file mode 100644
index 5b6ea64..0000000
--- a/legacyworlds-server-data/db-structure/tests/user/040-functions/003-updates/090-tgf-updtgt-before-insert.sql
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
- * Test privileges on sys.tgf_updtgt_before_insert()
- */
-BEGIN;
-	SELECT plan( 1 );
-
-	SELECT diag_test_name( 'sys.tgf_updtgt_before_insert() - No EXECUTE privilege' );
-	SELECT throws_ok( $$ SELECT sys.tgf_updtgt_before_insert( ) $$ , 42501 );
-	
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/user/040-functions/003-updates/100-tgf-updtgt-after-insert.sql b/legacyworlds-server-data/db-structure/tests/user/040-functions/003-updates/100-tgf-updtgt-after-insert.sql
deleted file mode 100644
index 6da4cfa..0000000
--- a/legacyworlds-server-data/db-structure/tests/user/040-functions/003-updates/100-tgf-updtgt-after-insert.sql
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
- * Test privileges on sys.tgf_updtgt_after_insert()
- */
-BEGIN;
-	SELECT plan( 1 );
-
-	SELECT diag_test_name( 'sys.tgf_updtgt_after_insert() - No EXECUTE privilege' );
-	SELECT throws_ok( $$ SELECT sys.tgf_updtgt_after_insert( ) $$ , 42501 );
-	
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/user/040-functions/003-updates/110-tgf-updtgt-after-delete.sql b/legacyworlds-server-data/db-structure/tests/user/040-functions/003-updates/110-tgf-updtgt-after-delete.sql
deleted file mode 100644
index 0d1c554..0000000
--- a/legacyworlds-server-data/db-structure/tests/user/040-functions/003-updates/110-tgf-updtgt-after-delete.sql
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
- * Test privileges on sys.tgf_updtgt_after_delete()
- */
-BEGIN;
-	SELECT plan( 1 );
-
-	SELECT diag_test_name( 'sys.tgf_updtgt_after_delete() - No EXECUTE privilege' );
-	SELECT throws_ok( $$ SELECT sys.tgf_updtgt_after_delete( ) $$ , 42501 );
-	
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/user/040-functions/003-updates/120-register-update-type.sql b/legacyworlds-server-data/db-structure/tests/user/040-functions/003-updates/120-register-update-type.sql
deleted file mode 100644
index f25b59e..0000000
--- a/legacyworlds-server-data/db-structure/tests/user/040-functions/003-updates/120-register-update-type.sql
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
- * Test privileges on sys.register_update_type()
- */
-BEGIN;
-	SELECT plan( 1 );
-
-	SELECT diag_test_name( 'sys.register_update_type() - No EXECUTE privilege' );
-	SELECT throws_ok( $$ SELECT sys.register_update_type( '' , '' , '' , 'x' ) $$ , 42501 );
-	
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/user/040-functions/005-logs/010-write-sql-log.sql b/legacyworlds-server-data/db-structure/tests/user/040-functions/005-logs/010-write-sql-log.sql
deleted file mode 100644
index 3996f8a..0000000
--- a/legacyworlds-server-data/db-structure/tests/user/040-functions/005-logs/010-write-sql-log.sql
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * Test the sys.write_sql_log( ) function
- */
-BEGIN;
-	SELECT plan( 1 );
-	
-	SELECT diag_test_name( 'sys.write_sql_log( ) - Privileges' );
-	SELECT lives_ok(
-		$$ SELECT sys.write_sql_log( 'test' , 'WARNING'::log_level , 'test' ) $$
-	);
-
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/user/040-functions/025-resources/005-add-resource-records.sql b/legacyworlds-server-data/db-structure/tests/user/040-functions/025-resources/005-add-resource-records.sql
deleted file mode 100644
index ee0a892..0000000
--- a/legacyworlds-server-data/db-structure/tests/user/040-functions/025-resources/005-add-resource-records.sql
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * Test privileges on defs.add_resource_records()
- */
-BEGIN;
-
-	SELECT plan( 1 );
-	
-	SELECT diag_test_name( 'defs.add_resource_records() - Privileges' );
-	PREPARE _test_this AS
-		SELECT defs.add_resource_records( 1 );
-	SELECT throws_ok( '_test_this' , 42501 );
-	
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/user/040-functions/025-resources/010-uoc-resource-internal.sql b/legacyworlds-server-data/db-structure/tests/user/040-functions/025-resources/010-uoc-resource-internal.sql
deleted file mode 100644
index c66b9dc..0000000
--- a/legacyworlds-server-data/db-structure/tests/user/040-functions/025-resources/010-uoc-resource-internal.sql
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * Test privileges on defs.uoc_resource_internal()
- */
-BEGIN;
-
-	SELECT plan( 1 );
-	
-	SELECT diag_test_name( 'defs.uoc_resource_internal() - Privileges' );
-	PREPARE _test_this AS
-		SELECT defs.uoc_resource_internal( 'test1' , 'test2' , NULL , 1 );
-	SELECT throws_ok( '_test_this' , 42501 );
-	
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/user/040-functions/025-resources/020-uoc-resource.sql b/legacyworlds-server-data/db-structure/tests/user/040-functions/025-resources/020-uoc-resource.sql
deleted file mode 100644
index 56053d4..0000000
--- a/legacyworlds-server-data/db-structure/tests/user/040-functions/025-resources/020-uoc-resource.sql
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * Test privileges on defs.uoc_resource()
- */
-BEGIN;
-	SELECT plan( 2 );
-	
-	SELECT diag_test_name( 'defs.uoc_resource() - Privileges (without category)' );
-	SELECT is( defs.uoc_resource( 'test1' , 'test2' , 1 ) , 'BAD_STRINGS' );
-	
-	SELECT diag_test_name( 'defs.uoc_resource() - Privileges (with category)' );
-	SELECT is( defs.uoc_resource( 'test1' , 'test2' , 'test3' , 1 ) , 'BAD_STRINGS' );
-	
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/user/040-functions/025-resources/030-uoc-natres-internal.sql b/legacyworlds-server-data/db-structure/tests/user/040-functions/025-resources/030-uoc-natres-internal.sql
deleted file mode 100644
index 1a321e5..0000000
--- a/legacyworlds-server-data/db-structure/tests/user/040-functions/025-resources/030-uoc-natres-internal.sql
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * Test privileges on defs.uoc_natres_internal()
- */
-BEGIN;
-
-	SELECT plan( 1 );
-	
-	SELECT diag_test_name( 'defs.uoc_natres_internal() - Privileges' );
-	PREPARE _test_this AS
-		SELECT defs.uoc_natres_internal( 'test1' , 'test2' , NULL , 1 ,
-				0.5 , 100 , 50 , 0.5 , 0.1 , 0.5 , 0.1
-			);
-	SELECT throws_ok( '_test_this' , 42501 );
-	
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/user/040-functions/025-resources/040-uoc-natural-resource.sql b/legacyworlds-server-data/db-structure/tests/user/040-functions/025-resources/040-uoc-natural-resource.sql
deleted file mode 100644
index dee7b74..0000000
--- a/legacyworlds-server-data/db-structure/tests/user/040-functions/025-resources/040-uoc-natural-resource.sql
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * Test privileges on defs.uoc_natural_resource()
- */
-BEGIN;
-	SELECT plan( 2 );
-	
-	SELECT diag_test_name( 'defs.uoc_natural_resource() - Privileges (without category)' );
-	SELECT is( defs.uoc_natural_resource( 'test1' , 'test2' , 1 ,
-			0.5 , 100 , 50 , 0.5 , 0.1 , 0.5 , 0.1
-		) , 'BAD_STRINGS' );
-	
-	SELECT diag_test_name( 'defs.uoc_natural_resource() - Privileges (with category)' );
-	SELECT is( defs.uoc_natural_resource( 'test1' , 'test2' , 'test3' , 1 ,
-			0.5 , 100 , 50 , 0.5 , 0.1 , 0.5 , 0.1
-		) , 'BAD_STRINGS' );
-	
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/user/040-functions/025-resources/050-resource-category-weight-view.sql b/legacyworlds-server-data/db-structure/tests/user/040-functions/025-resources/050-resource-category-weight-view.sql
deleted file mode 100644
index 17df905..0000000
--- a/legacyworlds-server-data/db-structure/tests/user/040-functions/025-resources/050-resource-category-weight-view.sql
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
- * Test privileges on defs.resource_category_weight_view
- */
-BEGIN;
-	SELECT plan( 1 );
-
-	SELECT diag_test_name( 'defs.resource_category_weight_view - Privileges' );
-	SELECT throws_ok( 'SELECT * FROM defs.resource_category_weight_view' , 42501 );
-	
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/user/040-functions/025-resources/060-ordered-resources-view.sql b/legacyworlds-server-data/db-structure/tests/user/040-functions/025-resources/060-ordered-resources-view.sql
deleted file mode 100644
index a632f1f..0000000
--- a/legacyworlds-server-data/db-structure/tests/user/040-functions/025-resources/060-ordered-resources-view.sql
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
- * Test privileges on defs.ordered_resources_view
- */
-BEGIN;
-	SELECT plan( 1 );
-
-	SELECT diag_test_name( 'defs.ordered_resources_view - Privileges' );
-	SELECT throws_ok( 'SELECT * FROM defs.ordered_resources_view' , 42501 );
-	
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/user/040-functions/026-technology-dependencies/010-tdcache-copy-tree.sql b/legacyworlds-server-data/db-structure/tests/user/040-functions/026-technology-dependencies/010-tdcache-copy-tree.sql
deleted file mode 100644
index 75b1d8c..0000000
--- a/legacyworlds-server-data/db-structure/tests/user/040-functions/026-technology-dependencies/010-tdcache-copy-tree.sql
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * Test privileges on defs.tdcache_copy_tree( )
- */
-BEGIN;
-
-	SELECT plan( 1 );
-	
-	SELECT diag_test_name( 'defs.tdcache_copy_tree( ) - No EXECUTE privilege' );
-	SELECT throws_ok( $$
-		SELECT defs.tdcache_copy_tree( FALSE , 1 , 2 , 3 , 4 , 5 );
-	$$ , 42501 );
-	
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/user/040-functions/026-technology-dependencies/020-tdcache-set-child.sql b/legacyworlds-server-data/db-structure/tests/user/040-functions/026-technology-dependencies/020-tdcache-set-child.sql
deleted file mode 100644
index c9b9ca9..0000000
--- a/legacyworlds-server-data/db-structure/tests/user/040-functions/026-technology-dependencies/020-tdcache-set-child.sql
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * Test privileges on defs.tdcache_set_child( )
- */
-BEGIN;
-
-	SELECT plan( 1 );
-	
-	SELECT diag_test_name( 'defs.tdcache_set_child( ) - No EXECUTE privilege' );
-	SELECT throws_ok( $$
-		SELECT defs.tdcache_set_child( FALSE , 1 , 2 , 3 );
-	$$ , 42501 );
-	
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/user/040-functions/026-technology-dependencies/030-tgf-technologies-ai.sql b/legacyworlds-server-data/db-structure/tests/user/040-functions/026-technology-dependencies/030-tgf-technologies-ai.sql
deleted file mode 100644
index 6232dfc..0000000
--- a/legacyworlds-server-data/db-structure/tests/user/040-functions/026-technology-dependencies/030-tgf-technologies-ai.sql
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * Test privileges on defs.tgf_technologies_ai( )
- */
-BEGIN;
-
-	SELECT plan( 1 );
-	
-	SELECT diag_test_name( 'defs.tgf_technologies_ai( ) - No EXECUTE privilege' );
-	SELECT throws_ok( $$
-		SELECT defs.tgf_technologies_ai( );
-	$$ , 42501 );
-	
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/user/040-functions/026-technology-dependencies/040-tgf-techdeps-bi.sql b/legacyworlds-server-data/db-structure/tests/user/040-functions/026-technology-dependencies/040-tgf-techdeps-bi.sql
deleted file mode 100644
index 90a7a72..0000000
--- a/legacyworlds-server-data/db-structure/tests/user/040-functions/026-technology-dependencies/040-tgf-techdeps-bi.sql
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * Test privileges on defs.tgf_techdeps_bi( )
- */
-BEGIN;
-
-	SELECT plan( 1 );
-	
-	SELECT diag_test_name( 'defs.tgf_techdeps_bi( ) - No EXECUTE privilege' );
-	SELECT throws_ok( $$
-		SELECT defs.tgf_techdeps_bi( );
-	$$ , 42501 );
-	
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/user/040-functions/026-technology-dependencies/050-tgf-techdeps-ai.sql b/legacyworlds-server-data/db-structure/tests/user/040-functions/026-technology-dependencies/050-tgf-techdeps-ai.sql
deleted file mode 100644
index ec4bc01..0000000
--- a/legacyworlds-server-data/db-structure/tests/user/040-functions/026-technology-dependencies/050-tgf-techdeps-ai.sql
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * Test privileges on defs.tgf_techdeps_ai( )
- */
-BEGIN;
-
-	SELECT plan( 1 );
-	
-	SELECT diag_test_name( 'defs.tgf_techdeps_ai( ) - No EXECUTE privilege' );
-	SELECT throws_ok( $$
-		SELECT defs.tgf_techdeps_ai( );
-	$$ , 42501 );
-	
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/user/040-functions/026-technology-dependencies/060-technology-dependencies-view.sql b/legacyworlds-server-data/db-structure/tests/user/040-functions/026-technology-dependencies/060-technology-dependencies-view.sql
deleted file mode 100644
index 6a016de..0000000
--- a/legacyworlds-server-data/db-structure/tests/user/040-functions/026-technology-dependencies/060-technology-dependencies-view.sql
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- * Test privileges on defs.technology_dependencies_view
- */
-BEGIN;
-	\i utils/strings.sql
-
-	SELECT plan( 1 );
-
-	SELECT diag_test_name( 'defs.technology_dependencies_view - No SELECT privilege' );
-	SELECT throws_ok( $$
-		SELECT * FROM defs.technology_dependencies_view;
-	$$ , 42501 );
-
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/user/040-functions/030-tech/010-uoc-technology.sql b/legacyworlds-server-data/db-structure/tests/user/040-functions/030-tech/010-uoc-technology.sql
deleted file mode 100644
index aa26d1b..0000000
--- a/legacyworlds-server-data/db-structure/tests/user/040-functions/030-tech/010-uoc-technology.sql
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * Test privileges on defs.uoc_technology()
- */
-BEGIN;
-	SELECT plan( 1 );
-	
-	SELECT diag_test_name( 'defs.uoc_technology() - EXECUTE privilege' );
-	SELECT lives_ok( $$
-		SELECT defs.uoc_technology( '' , '' , '' , '' , 1 , 2 );
-	$$ );
-	
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/user/040-functions/030-tech/020-techdep-add.sql b/legacyworlds-server-data/db-structure/tests/user/040-functions/030-tech/020-techdep-add.sql
deleted file mode 100644
index f516d51..0000000
--- a/legacyworlds-server-data/db-structure/tests/user/040-functions/030-tech/020-techdep-add.sql
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * Test privileges on defs.techdep_add()
- */
-BEGIN;
-	SELECT plan( 1 );
-	
-	SELECT diag_test_name( 'defs.techdep_add() - EXECUTE privilege' );
-	SELECT lives_ok( $$
-		SELECT defs.techdep_add( '' , '' );
-	$$ );
-	
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/user/040-functions/030-tech/030-techdep-remove.sql b/legacyworlds-server-data/db-structure/tests/user/040-functions/030-tech/030-techdep-remove.sql
deleted file mode 100644
index a94ba9f..0000000
--- a/legacyworlds-server-data/db-structure/tests/user/040-functions/030-tech/030-techdep-remove.sql
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * Test privileges on defs.techdep_remove()
- */
-BEGIN;
-	SELECT plan( 1 );
-	
-	SELECT diag_test_name( 'defs.techdep_remove() - EXECUTE privilege' );
-	SELECT lives_ok( $$
-		SELECT defs.techdep_remove( '' , '' );
-	$$ );
-	
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/user/040-functions/030-tech/040-techdep-clear.sql b/legacyworlds-server-data/db-structure/tests/user/040-functions/030-tech/040-techdep-clear.sql
deleted file mode 100644
index fb9f70b..0000000
--- a/legacyworlds-server-data/db-structure/tests/user/040-functions/030-tech/040-techdep-clear.sql
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * Test privileges on defs.techdep_remove()
- */
-BEGIN;
-	SELECT plan( 1 );
-	
-	SELECT diag_test_name( 'defs.techdep_clear() - EXECUTE privilege' );
-	SELECT lives_ok( $$
-		SELECT defs.techdep_clear( '' );
-	$$ );
-	
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/user/040-functions/040-empire/010-create-empire.sql b/legacyworlds-server-data/db-structure/tests/user/040-functions/040-empire/010-create-empire.sql
deleted file mode 100644
index 11e01b6..0000000
--- a/legacyworlds-server-data/db-structure/tests/user/040-functions/040-empire/010-create-empire.sql
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * Test privileges on emp.create_empire()
- */
-BEGIN;
-
-	SELECT plan( 1 );
-	
-	SELECT diag_test_name( 'emp.create_empire() - Privileges' );
-	SELECT throws_ok( $$
-			SELECT emp.create_empire( 1 , 1 , 200.0 )
-		$$ , 42501 );
-	
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/user/040-functions/040-empire/020-planet-resources-view.sql b/legacyworlds-server-data/db-structure/tests/user/040-functions/040-empire/020-planet-resources-view.sql
deleted file mode 100644
index 619ad96..0000000
--- a/legacyworlds-server-data/db-structure/tests/user/040-functions/040-empire/020-planet-resources-view.sql
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
- * Test privileges on emp.planet_resources_view
- */
-BEGIN;
-	SELECT plan( 1 );
-
-	SELECT diag_test_name( 'emp.planet_resources_view - Privileges' );
-	SELECT throws_ok( 'SELECT * FROM emp.planet_resources_view' , 42501 );
-	
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/user/040-functions/040-empire/030-resources-view.sql b/legacyworlds-server-data/db-structure/tests/user/040-functions/040-empire/030-resources-view.sql
deleted file mode 100644
index 817d0e1..0000000
--- a/legacyworlds-server-data/db-structure/tests/user/040-functions/040-empire/030-resources-view.sql
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
- * Test privileges on emp.resources_view
- */
-BEGIN;
-	SELECT plan( 1 );
-
-	SELECT diag_test_name( 'emp.resources_view - Privileges' );
-	SELECT lives_ok( 'SELECT * FROM emp.resources_view' );
-	
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/user/040-functions/043-computation/010-get-random-part.sql b/legacyworlds-server-data/db-structure/tests/user/040-functions/043-computation/010-get-random-part.sql
deleted file mode 100644
index 5ce2907..0000000
--- a/legacyworlds-server-data/db-structure/tests/user/040-functions/043-computation/010-get-random-part.sql
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * Test privileges on verse.get_random_part()
- */
-BEGIN;
-
-	SELECT plan( 1 );
-	
-	SELECT diag_test_name( 'verse.get_random_part( ) - Privileges' );
-	PREPARE _test_this AS
-		SELECT verse.get_random_part( 0.5 , 1 , 0.5 , 0.25 );
-	SELECT throws_ok( '_test_this' , 42501 );
-	
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/user/040-functions/043-computation/020-adjust-production.sql b/legacyworlds-server-data/db-structure/tests/user/040-functions/043-computation/020-adjust-production.sql
deleted file mode 100644
index 95ecf3e..0000000
--- a/legacyworlds-server-data/db-structure/tests/user/040-functions/043-computation/020-adjust-production.sql
+++ /dev/null
@@ -1,12 +0,0 @@
-/*
- * Test privileges on verse.adjust_production()
- */
-BEGIN;
-
-	SELECT plan( 1 );
-	
-	SELECT diag_test_name( 'verse.adjust_production( ) - EXECUTE privilege' );
-	SELECT lives_ok( $$ SELECT verse.adjust_production( 1 , 1 ) $$ );
-	
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/user/040-functions/045-empire-research/010-technology-implement.sql b/legacyworlds-server-data/db-structure/tests/user/040-functions/045-empire-research/010-technology-implement.sql
deleted file mode 100644
index 57097ce..0000000
--- a/legacyworlds-server-data/db-structure/tests/user/040-functions/045-empire-research/010-technology-implement.sql
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * Test privileges on emp.technology_implement()
- */
-BEGIN;
-	SELECT plan( 1 );
-	
-	SELECT diag_test_name( 'emp.technology_implement() - EXECUTE privilege' );
-	SELECT lives_ok( $$
-		SELECT emp.technology_implement( 1 , '' );
-	$$ );
-	
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/user/040-functions/045-empire-research/020-technology-make-identifier.sql b/legacyworlds-server-data/db-structure/tests/user/040-functions/045-empire-research/020-technology-make-identifier.sql
deleted file mode 100644
index 92cd282..0000000
--- a/legacyworlds-server-data/db-structure/tests/user/040-functions/045-empire-research/020-technology-make-identifier.sql
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * Test privileges on emp.technology_make_identifier()
- */
-BEGIN;
-
-	SELECT plan( 1 );
-	
-	SELECT diag_test_name( 'emp.technology_make_identifier() - EXECUTE privilege' );
-	SELECT lives_ok( $$
-		SELECT emp.technology_make_identifier( 1 , '' , FALSE );
-	$$ );
-	
-	SELECT * FROM finish( );
-ROLLBACK;
diff --git a/legacyworlds-server-data/db-structure/tests/user/040-functions/045-empire-research/030-resprio-update-start.sql b/legacyworlds-server-data/db-structure/tests/user/040-functions/045-empire-research/030-resprio-update-start.sql
deleted file mode 100644
index cc97c3f..0000000
--- a/legacyworlds-server-data/db-structure/tests/user/040-functions/045-empire-research/030-resprio-update-start.sql
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * Test privileges on emp.resprio_update_start()
- */
-BEGIN;
-	SELECT plan( 1 );
-	
-	SELECT diag_test_name( 'emp.resprio_update_start() - EXECUTE privilege' );
-	SELECT lives_ok( $$
-		SELECT emp.resprio_update_start( 1 );
-	$$ );
-	
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/user/040-functions/045-empire-research/040-resprio-update-set.sql b/legacyworlds-server-data/db-structure/tests/user/040-functions/045-empire-research/040-resprio-update-set.sql
deleted file mode 100644
index c0de9d5..0000000
--- a/legacyworlds-server-data/db-structure/tests/user/040-functions/045-empire-research/040-resprio-update-set.sql
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- * Test privileges on emp.resprio_update_set()
- */
-BEGIN;
-	SELECT emp.resprio_update_start( 1 );
-
-	SELECT plan( 1 );
-
-	SELECT diag_test_name( 'emp.resprio_update_set() - EXECUTE privilege' );
-	SELECT lives_ok( $$
-		SELECT emp.resprio_update_set( '' , 1 );
-	$$ );
-	
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/user/040-functions/045-empire-research/050-resprio-update-apply.sql b/legacyworlds-server-data/db-structure/tests/user/040-functions/045-empire-research/050-resprio-update-apply.sql
deleted file mode 100644
index 93684c5..0000000
--- a/legacyworlds-server-data/db-structure/tests/user/040-functions/045-empire-research/050-resprio-update-apply.sql
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- * Test privileges on emp.resprio_update_apply()
- */
-BEGIN;
-	SELECT emp.resprio_update_start( 1 );
-
-	SELECT plan( 1 );
-
-	SELECT diag_test_name( 'emp.resprio_update_apply() - EXECUTE privilege' );
-	SELECT lives_ok( $$
-		SELECT emp.resprio_update_apply( );
-	$$ );
-	
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/user/040-functions/045-empire-research/060-technology-visibility-view.sql b/legacyworlds-server-data/db-structure/tests/user/040-functions/045-empire-research/060-technology-visibility-view.sql
deleted file mode 100644
index 5c2062c..0000000
--- a/legacyworlds-server-data/db-structure/tests/user/040-functions/045-empire-research/060-technology-visibility-view.sql
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- * Test privileges on emp.technology_visibility_view
- */
-BEGIN;
-	\i utils/strings.sql
-
-	SELECT plan( 1 );
-
-	SELECT diag_test_name( 'emp.technology_visibility_view - No SELECT privilege' );
-	SELECT throws_ok( $$
-		SELECT * FROM emp.technology_visibility_view;
-	$$ , 42501 );
-
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/user/040-functions/045-empire-research/070-research-weights-view.sql b/legacyworlds-server-data/db-structure/tests/user/040-functions/045-empire-research/070-research-weights-view.sql
deleted file mode 100644
index 807548c..0000000
--- a/legacyworlds-server-data/db-structure/tests/user/040-functions/045-empire-research/070-research-weights-view.sql
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- * Test privileges on emp.research_weights_view
- */
-BEGIN;
-	\i utils/strings.sql
-
-	SELECT plan( 1 );
-
-	SELECT diag_test_name( 'emp.research_weights_view - No SELECT privilege' );
-	SELECT throws_ok( $$
-		SELECT * FROM emp.research_weights_view;
-	$$ , 42501 );
-
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/user/040-functions/045-empire-research/080-research-total-weights-view.sql b/legacyworlds-server-data/db-structure/tests/user/040-functions/045-empire-research/080-research-total-weights-view.sql
deleted file mode 100644
index d2767f6..0000000
--- a/legacyworlds-server-data/db-structure/tests/user/040-functions/045-empire-research/080-research-total-weights-view.sql
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- * Test privileges on emp.research_total_weights_view
- */
-BEGIN;
-	\i utils/strings.sql
-
-	SELECT plan( 1 );
-
-	SELECT diag_test_name( 'emp.research_total_weights_view - No SELECT privilege' );
-	SELECT throws_ok( $$
-		SELECT * FROM emp.research_total_weights_view;
-	$$ , 42501 );
-
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/user/040-functions/045-empire-research/090-technologies-view.sql b/legacyworlds-server-data/db-structure/tests/user/040-functions/045-empire-research/090-technologies-view.sql
deleted file mode 100644
index cf52fd8..0000000
--- a/legacyworlds-server-data/db-structure/tests/user/040-functions/045-empire-research/090-technologies-view.sql
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- * Test privileges on emp.technologies_view
- */
-BEGIN;
-	\i utils/strings.sql
-
-	SELECT plan( 1 );
-
-	SELECT diag_test_name( 'emp.technologies_view - SELECT privilege' );
-	SELECT lives_ok( $$
-		SELECT * FROM emp.technologies_view;
-	$$ );
-
-	SELECT * FROM finish( );
-ROLLBACK;
diff --git a/legacyworlds-server-data/db-structure/tests/user/040-functions/053-generator-basics/010-list-random-planets-in.sql b/legacyworlds-server-data/db-structure/tests/user/040-functions/053-generator-basics/010-list-random-planets-in.sql
deleted file mode 100644
index 0f124ca..0000000
--- a/legacyworlds-server-data/db-structure/tests/user/040-functions/053-generator-basics/010-list-random-planets-in.sql
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * Test privileges on verse.list_random_planets_in()
- */
-BEGIN;
-
-	SELECT plan( 1 );
-	
-	SELECT diag_test_name( 'verse.list_random_planets_in( ) - Privileges' );
-	PREPARE _test_this AS
-		SELECT * FROM verse.list_random_planets_in( ROW( 2 , 2 , 3 , 3 ) , 2 );
-	SELECT throws_ok( '_test_this' , 42501 );
-	
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/user/040-functions/055-generator-resources/010-collect-resprov-statistics.sql b/legacyworlds-server-data/db-structure/tests/user/040-functions/055-generator-resources/010-collect-resprov-statistics.sql
deleted file mode 100644
index a47c717..0000000
--- a/legacyworlds-server-data/db-structure/tests/user/040-functions/055-generator-resources/010-collect-resprov-statistics.sql
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * Test privileges on verse.collect_resprov_statistics()
- */
-BEGIN;
-
-	SELECT plan( 1 );
-	
-	SELECT diag_test_name( 'verse.collect_resprov_statistics( ) - Privileges' );
-	PREPARE _test_this AS
-		SELECT verse.collect_resprov_statistics( );
-	SELECT throws_ok( '_test_this' , 42501 );
-	
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/user/040-functions/055-generator-resources/020-compute-rpp-delta.sql b/legacyworlds-server-data/db-structure/tests/user/040-functions/055-generator-resources/020-compute-rpp-delta.sql
deleted file mode 100644
index f309075..0000000
--- a/legacyworlds-server-data/db-structure/tests/user/040-functions/055-generator-resources/020-compute-rpp-delta.sql
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * Test privileges on verse.compute_rpp_delta( )
- */
-BEGIN;
-
-	SELECT plan( 1 );
-	
-	SELECT diag_test_name( 'verse.compute_rpp_delta( ) - Privileges' );
-	PREPARE _test_this AS
-		SELECT verse.compute_rpp_delta( 10 , 10 , 20 , 1 , 0.5 );
-	SELECT throws_ok( '_test_this' , 42501 );
-	
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/user/040-functions/055-generator-resources/030-create-resource-provider.sql b/legacyworlds-server-data/db-structure/tests/user/040-functions/055-generator-resources/030-create-resource-provider.sql
deleted file mode 100644
index 0c1368f..0000000
--- a/legacyworlds-server-data/db-structure/tests/user/040-functions/055-generator-resources/030-create-resource-provider.sql
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * Test privileges on verse.create_resource_provider( )
- */
-BEGIN;
-
-	SELECT plan( 1 );
-	
-	SELECT diag_test_name( 'verse.create_resource_provider( ) - Privileges' );
-	PREPARE _test_this AS
-		SELECT * FROM verse.create_resource_provider( 12 ,
-			ROW( 34 , 0.0 , 0.0 , 0.0 , 0.0 , 5.0 , 0.0 , 0.0 , 0.75 , 0.0 , 0.0 , 0.5 , 0 ) ,
-			2 , 10 , 1.5 , 1 );
-	SELECT throws_ok( '_test_this' , 42501 );
-	
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/user/040-functions/055-generator-resources/040-create-resource-providers-with-type.sql b/legacyworlds-server-data/db-structure/tests/user/040-functions/055-generator-resources/040-create-resource-providers-with-type.sql
deleted file mode 100644
index 5081dd8..0000000
--- a/legacyworlds-server-data/db-structure/tests/user/040-functions/055-generator-resources/040-create-resource-providers-with-type.sql
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * Test privileges on the variant of verse.create_resource_providers( ) which
- * takes a resource statistics record as a parameter.
- */
-BEGIN;
-
-	SELECT plan( 1 );
-	
-	SELECT diag_test_name( 'verse.create_resource_providers( area , type ) - Privileges' );
-	PREPARE _test_this AS
-		SELECT verse.create_resource_providers(
-			ROW( 0 , 0 , 1 , 1 ) ,
-			ROW( 42 , 0.0 , 0.0 , 0.5 , 0.0 , 5.0 , 0.0 , 0.0 , 0.75 , 0.0 , 0.0 , 0.5 , 0 )
-		);
-	SELECT throws_ok( '_test_this' , 42501 );
-	
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/user/040-functions/055-generator-resources/050-create-resource-providers.sql b/legacyworlds-server-data/db-structure/tests/user/040-functions/055-generator-resources/050-create-resource-providers.sql
deleted file mode 100644
index a1b1cf7..0000000
--- a/legacyworlds-server-data/db-structure/tests/user/040-functions/055-generator-resources/050-create-resource-providers.sql
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * Test privileges on the "main" verse.create_resource_providers( ) function
- */
-BEGIN;
-
-	SELECT plan( 1 );
-	
-	SELECT diag_test_name( 'verse.create_resource_providers( area ) - Privileges' );
-	PREPARE _test_this AS
-		SELECT verse.create_resource_providers( ROW( 0 , 0 , 1 , 1 ) );
-	SELECT throws_ok( '_test_this' , 42501 );
-	
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/user/040-functions/145-resource-providers/010-compute-provider-regeneration.sql b/legacyworlds-server-data/db-structure/tests/user/040-functions/145-resource-providers/010-compute-provider-regeneration.sql
deleted file mode 100644
index cce7c93..0000000
--- a/legacyworlds-server-data/db-structure/tests/user/040-functions/145-resource-providers/010-compute-provider-regeneration.sql
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
- * Test privileges on verse.compute_provider_regeneration()
- */
-BEGIN;
-	SELECT plan( 1 );
-
-	SELECT diag_test_name( 'verse.compute_provider_regeneration() - Privileges' );
-	SELECT throws_ok( 'SELECT verse.compute_provider_regeneration( 100.0 , 100.0 , 0.5 )' , 42501 );
-	
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/user/040-functions/145-resource-providers/020-mining-settings-view.sql b/legacyworlds-server-data/db-structure/tests/user/040-functions/145-resource-providers/020-mining-settings-view.sql
deleted file mode 100644
index 6540213..0000000
--- a/legacyworlds-server-data/db-structure/tests/user/040-functions/145-resource-providers/020-mining-settings-view.sql
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
- * Test privileges on emp.mining_settings_view
- */
-BEGIN;
-	SELECT plan( 1 );
-
-	SELECT diag_test_name( 'emp.mining_settings_view - Privileges' );
-	SELECT lives_ok( 'SELECT * FROM emp.mining_settings_view' );
-	
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/user/040-functions/145-resource-providers/030-get-extraction-factor.sql b/legacyworlds-server-data/db-structure/tests/user/040-functions/145-resource-providers/030-get-extraction-factor.sql
deleted file mode 100644
index 880a55e..0000000
--- a/legacyworlds-server-data/db-structure/tests/user/040-functions/145-resource-providers/030-get-extraction-factor.sql
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * Test privileges on verse.get_extraction_factor()
- */
-BEGIN;
-	SELECT plan( 1 );
-
-	SELECT diag_test_name( 'verse.get_extraction_factor() - Privileges' );
-	SELECT throws_ok( $$
-		SELECT verse.get_extraction_factor( 0.5 , 0.5 )
-	$$ , 42501 );
-	
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/user/040-functions/145-resource-providers/040-get-planet-resources.sql b/legacyworlds-server-data/db-structure/tests/user/040-functions/145-resource-providers/040-get-planet-resources.sql
deleted file mode 100644
index e2ed935..0000000
--- a/legacyworlds-server-data/db-structure/tests/user/040-functions/145-resource-providers/040-get-planet-resources.sql
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * Test privileges on emp.get_planet_resources()
- */
-BEGIN;
-	SELECT plan( 1 );
-
-	SELECT diag_test_name( 'emp.get_planet_resources() - Privileges' );
-	SELECT lives_ok( $$
-		SELECT emp.get_planet_resources( 1 )
-	$$ );
-	
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/user/040-functions/145-resource-providers/050-scaled-mining-weights-view.sql b/legacyworlds-server-data/db-structure/tests/user/040-functions/145-resource-providers/050-scaled-mining-weights-view.sql
deleted file mode 100644
index 76f2b0e..0000000
--- a/legacyworlds-server-data/db-structure/tests/user/040-functions/145-resource-providers/050-scaled-mining-weights-view.sql
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
- * Test privileges on emp.scaled_mining_weights_view
- */
-BEGIN;
-	SELECT plan( 1 );
-
-	SELECT diag_test_name( 'emp.scaled_mining_weights_view - No SELECT privilege' );
-	SELECT throws_ok( 'SELECT * FROM emp.scaled_mining_weights_view' , 42501 );
-	
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/user/040-functions/145-resource-providers/060-total-mining-weights-view.sql b/legacyworlds-server-data/db-structure/tests/user/040-functions/145-resource-providers/060-total-mining-weights-view.sql
deleted file mode 100644
index 5d0f0ae..0000000
--- a/legacyworlds-server-data/db-structure/tests/user/040-functions/145-resource-providers/060-total-mining-weights-view.sql
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
- * Test privileges on emp.total_mining_weights_view
- */
-BEGIN;
-	SELECT plan( 1 );
-
-	SELECT diag_test_name( 'emp.total_mining_weights_view - No SELECT privilege' );
-	SELECT throws_ok( 'SELECT * FROM emp.total_mining_weights_view' , 42501 );
-	
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/user/040-functions/145-resource-providers/070-mining-compute-extraction.sql b/legacyworlds-server-data/db-structure/tests/user/040-functions/145-resource-providers/070-mining-compute-extraction.sql
deleted file mode 100644
index 64a95e3..0000000
--- a/legacyworlds-server-data/db-structure/tests/user/040-functions/145-resource-providers/070-mining-compute-extraction.sql
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * Test privileges on emp.mining_compute_extraction()
- */
-BEGIN;
-	SELECT plan( 1 );
-
-	SELECT diag_test_name( 'emp.mining_compute_extraction() - No EXECUTE privilege' );
-	SELECT throws_ok( $$
-		SELECT emp.mining_compute_extraction( ROW( 1 , 2 , 3 , 4 , 5 , NULL , NULL , NULL , NULL ) )
-	$$ , 42501 );
-	
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/user/040-functions/145-resource-providers/080-verse-mining-get-input.sql b/legacyworlds-server-data/db-structure/tests/user/040-functions/145-resource-providers/080-verse-mining-get-input.sql
deleted file mode 100644
index 95a1561..0000000
--- a/legacyworlds-server-data/db-structure/tests/user/040-functions/145-resource-providers/080-verse-mining-get-input.sql
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * Test privileges on verse.mining_get_input()
- */
-BEGIN;
-	SELECT plan( 1 );
-
-	SELECT diag_test_name( 'verse.mining_get_input() - No EXECUTE privilege' );
-	SELECT throws_ok( $$
-		SELECT verse.mining_get_input( 1 )
-	$$ , 42501 );
-	
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/user/040-functions/145-resource-providers/090-emp-mining-get-input.sql b/legacyworlds-server-data/db-structure/tests/user/040-functions/145-resource-providers/090-emp-mining-get-input.sql
deleted file mode 100644
index ac77387..0000000
--- a/legacyworlds-server-data/db-structure/tests/user/040-functions/145-resource-providers/090-emp-mining-get-input.sql
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * Test privileges on emp.mining_get_input()
- */
-BEGIN;
-	SELECT plan( 1 );
-
-	SELECT diag_test_name( 'emp.mining_get_input() - No EXECUTE privilege' );
-	SELECT throws_ok( $$
-		SELECT emp.mining_get_input( 1 )
-	$$ , 42501 );
-	
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/user/040-functions/147-empire-mining/010-mset-update-start.sql b/legacyworlds-server-data/db-structure/tests/user/040-functions/147-empire-mining/010-mset-update-start.sql
deleted file mode 100644
index 598c26b..0000000
--- a/legacyworlds-server-data/db-structure/tests/user/040-functions/147-empire-mining/010-mset-update-start.sql
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * Test privileges on emp.mset_update_start( INT )
- */
-BEGIN;
-
-	SELECT plan( 1 );
-	
-	SELECT diag_test_name( 'emp.mset_update_start( INT ) - Privileges' );
-	SELECT lives_ok( $$
-			SELECT emp.mset_update_start( 1 )
-		$$ );
-	
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/user/040-functions/147-empire-mining/015-mset-update-start-planet.sql b/legacyworlds-server-data/db-structure/tests/user/040-functions/147-empire-mining/015-mset-update-start-planet.sql
deleted file mode 100644
index cf0e1ec..0000000
--- a/legacyworlds-server-data/db-structure/tests/user/040-functions/147-empire-mining/015-mset-update-start-planet.sql
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * Test privileges on emp.mset_update_start( INT , INT )
- */
-BEGIN;
-
-	SELECT plan( 1 );
-	
-	SELECT diag_test_name( 'emp.mset_update_start( INT , INT ) - Privileges' );
-	SELECT lives_ok( $$
-			SELECT emp.mset_update_start( 1 , 1 )
-		$$ );
-	
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/user/040-functions/147-empire-mining/020-mset-update-set.sql b/legacyworlds-server-data/db-structure/tests/user/040-functions/147-empire-mining/020-mset-update-set.sql
deleted file mode 100644
index 633ccae..0000000
--- a/legacyworlds-server-data/db-structure/tests/user/040-functions/147-empire-mining/020-mset-update-set.sql
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * Test privileges on emp.mset_update_set()
- */
-BEGIN;
-	SELECT emp.mset_update_start( 1 );
-	SELECT plan( 1 );
-	
-	SELECT diag_test_name( 'emp.mset_update_set() - Privileges' );
-	SELECT lives_ok( $$
-			SELECT emp.mset_update_set( 'a' , -1 )
-		$$ );
-	
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/user/040-functions/147-empire-mining/030-mset-update-apply.sql b/legacyworlds-server-data/db-structure/tests/user/040-functions/147-empire-mining/030-mset-update-apply.sql
deleted file mode 100644
index 6f349fb..0000000
--- a/legacyworlds-server-data/db-structure/tests/user/040-functions/147-empire-mining/030-mset-update-apply.sql
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- * Test privileges on emp.mset_update_set()
- */
-BEGIN;
-	SELECT emp.mset_update_start( 1 );
-
-	SELECT plan( 1 );
-	
-	SELECT diag_test_name( 'emp.mset_update_apply() - Privileges' );
-	SELECT lives_ok( $$
-			SELECT emp.mset_update_apply( )
-		$$ );
-	
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/user/040-functions/147-empire-mining/040-mset-toggle-source.sql b/legacyworlds-server-data/db-structure/tests/user/040-functions/147-empire-mining/040-mset-toggle-source.sql
deleted file mode 100644
index fcb9e61..0000000
--- a/legacyworlds-server-data/db-structure/tests/user/040-functions/147-empire-mining/040-mset-toggle-source.sql
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- * Test privileges on emp.mset_toggle_source( INT , INT )
- */
-BEGIN;
-	SELECT emp.mset_update_start( 1 );
-
-	SELECT plan( 1 );
-	
-	SELECT diag_test_name( 'emp.mset_toggle_source() - Privileges' );
-	SELECT lives_ok( $$
-			SELECT emp.mset_toggle_source( 1 , 1 )
-		$$ );
-	
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/user/040-functions/167-planet-list/010-plist-resources-view.sql b/legacyworlds-server-data/db-structure/tests/user/040-functions/167-planet-list/010-plist-resources-view.sql
deleted file mode 100644
index ddd0cb9..0000000
--- a/legacyworlds-server-data/db-structure/tests/user/040-functions/167-planet-list/010-plist-resources-view.sql
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
- * Test privileges on emp.plist_resources_view
- */
-BEGIN;
-	SELECT plan( 1 );
-
-	SELECT diag_test_name( 'emp.plist_resources_view - SELECT privilege' );
-	SELECT lives_ok( 'SELECT * FROM emp.plist_resources_view' );
-	
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/user/040-functions/200-bugs/005-dump-emp-resources-view.sql b/legacyworlds-server-data/db-structure/tests/user/040-functions/200-bugs/005-dump-emp-resources-view.sql
deleted file mode 100644
index a1eb0f8..0000000
--- a/legacyworlds-server-data/db-structure/tests/user/040-functions/200-bugs/005-dump-emp-resources-view.sql
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
- * Test privileges on bugs.dump_emp_resources_view
- */
-BEGIN;
-	SELECT plan( 1 );
-
-	SELECT diag_test_name( 'bugs.dump_emp_resources_view - Privileges' );
-	SELECT lives_ok( 'SELECT * FROM bugs.dump_emp_resources_view' );
-	
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/user/040-functions/200-bugs/010-dump-planet-resources-view.sql b/legacyworlds-server-data/db-structure/tests/user/040-functions/200-bugs/010-dump-planet-resources-view.sql
deleted file mode 100644
index 5100491..0000000
--- a/legacyworlds-server-data/db-structure/tests/user/040-functions/200-bugs/010-dump-planet-resources-view.sql
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
- * Test privileges on bugs.dump_planet_resources_view
- */
-BEGIN;
-	SELECT plan( 1 );
-
-	SELECT diag_test_name( 'bugs.dump_planet_resources_view - Privileges' );
-	SELECT lives_ok( 'SELECT * FROM bugs.dump_planet_resources_view' );
-	
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/user/050-updates/000-updates-ctrl/010-start-tick.sql b/legacyworlds-server-data/db-structure/tests/user/050-updates/000-updates-ctrl/010-start-tick.sql
deleted file mode 100644
index cb763fb..0000000
--- a/legacyworlds-server-data/db-structure/tests/user/050-updates/000-updates-ctrl/010-start-tick.sql
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
- * Test privileges on sys.start_tick()
- */
-BEGIN;
-	SELECT plan( 1 );
-
-	SELECT diag_test_name( 'sys.start_tick() - EXECUTE privilege' );
-	SELECT lives_ok( 'SELECT sys.start_tick( )' );
-	
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/user/050-updates/000-updates-ctrl/020-check-stuck-tick.sql b/legacyworlds-server-data/db-structure/tests/user/050-updates/000-updates-ctrl/020-check-stuck-tick.sql
deleted file mode 100644
index 5799b95..0000000
--- a/legacyworlds-server-data/db-structure/tests/user/050-updates/000-updates-ctrl/020-check-stuck-tick.sql
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
- * Test privileges on sys.check_stuck_tick()
- */
-BEGIN;
-	SELECT plan( 1 );
-
-	SELECT diag_test_name( 'sys.check_stuck_tick() - EXECUTE privilege' );
-	SELECT lives_ok( 'SELECT sys.check_stuck_tick( )' );
-	
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/user/050-updates/000-updates-ctrl/030-process-updates.sql b/legacyworlds-server-data/db-structure/tests/user/050-updates/000-updates-ctrl/030-process-updates.sql
deleted file mode 100644
index 5416d6c..0000000
--- a/legacyworlds-server-data/db-structure/tests/user/050-updates/000-updates-ctrl/030-process-updates.sql
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
- * Test privileges on sys.process_updates()
- */
-BEGIN;
-	SELECT plan( 1 );
-
-	SELECT diag_test_name( 'sys.process_updates() - EXECUTE privilege' );
-	SELECT lives_ok( 'SELECT sys.process_updates( 1 )' );
-	
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/user/050-updates/015-empire-resources/010-process-empire-resources-updates.sql b/legacyworlds-server-data/db-structure/tests/user/050-updates/015-empire-resources/010-process-empire-resources-updates.sql
deleted file mode 100644
index eba8788..0000000
--- a/legacyworlds-server-data/db-structure/tests/user/050-updates/015-empire-resources/010-process-empire-resources-updates.sql
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
- * Test privileges on sys.process_empire_resources_updates()
- */
-BEGIN;
-	SELECT plan( 1 );
-
-	SELECT diag_test_name( 'sys.process_empire_resources_updates() - No EXECUTE privilege' );
-	SELECT throws_ok( 'SELECT sys.process_empire_resources_updates( 1 )' , 42501 );
-	
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/user/050-updates/020-empire-research/010-gu-research-get-empires.sql b/legacyworlds-server-data/db-structure/tests/user/050-updates/020-empire-research/010-gu-research-get-empires.sql
deleted file mode 100644
index 0830456..0000000
--- a/legacyworlds-server-data/db-structure/tests/user/050-updates/020-empire-research/010-gu-research-get-empires.sql
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
- * Test privileges on sys.gu_research_get_empires()
- */
-BEGIN;
-	SELECT plan( 1 );
-
-	SELECT diag_test_name( 'sys.gu_research_get_empires() - Privileges' );
-	SELECT throws_ok( 'SELECT sys.gu_research_get_empires( 0::BIGINT )' , 42501 );
-	
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/user/050-updates/105-planet-resource-regeneration/010-process-res-regen-updates.sql b/legacyworlds-server-data/db-structure/tests/user/050-updates/105-planet-resource-regeneration/010-process-res-regen-updates.sql
deleted file mode 100644
index cb4bcd6..0000000
--- a/legacyworlds-server-data/db-structure/tests/user/050-updates/105-planet-resource-regeneration/010-process-res-regen-updates.sql
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
- * Test privileges on sys.process_res_regen_updates()
- */
-BEGIN;
-	SELECT plan( 1 );
-
-	SELECT diag_test_name( 'sys.process_res_regen_updates() - Privileges' );
-	SELECT throws_ok( 'SELECT sys.process_res_regen_updates( 1 )' , 42501 );
-	
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/user/050-updates/120-planet-mining/010-gu-pmc-get-data.sql b/legacyworlds-server-data/db-structure/tests/user/050-updates/120-planet-mining/010-gu-pmc-get-data.sql
deleted file mode 100644
index 9407cfb..0000000
--- a/legacyworlds-server-data/db-structure/tests/user/050-updates/120-planet-mining/010-gu-pmc-get-data.sql
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
- * Test privileges on sys.gu_pmc_get_data( )
- */
-BEGIN;
-	SELECT plan( 1 );
-
-	SELECT diag_test_name( 'sys.gu_pmc_get_data - Privileges' );
-	SELECT throws_ok( 'SELECT * FROM sys.gu_pmc_get_data( 0 )' , 42501 );
-	
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/user/050-updates/120-planet-mining/020-process-planet-mining-updates.sql b/legacyworlds-server-data/db-structure/tests/user/050-updates/120-planet-mining/020-process-planet-mining-updates.sql
deleted file mode 100644
index 03c1616..0000000
--- a/legacyworlds-server-data/db-structure/tests/user/050-updates/120-planet-mining/020-process-planet-mining-updates.sql
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
- * Test privileges on sys.process_planet_mining_updates( )
- */
-BEGIN;
-	SELECT plan( 1 );
-
-	SELECT diag_test_name( 'sys.process_planet_mining_updates() - Privileges' );
-	SELECT throws_ok( 'SELECT * FROM sys.process_planet_mining_updates( 0 )' , 42501 );
-	
-	SELECT * FROM finish( );
-ROLLBACK;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/utils/accounts.sql b/legacyworlds-server-data/db-structure/tests/utils/accounts.sql
deleted file mode 100644
index b93c82a..0000000
--- a/legacyworlds-server-data/db-structure/tests/utils/accounts.sql
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Utility functions used by unit tests
- *
- * User accounts
- */
-
-
-/*
- * Find a test address
- */
-CREATE FUNCTION _find_address( TEXT ) RETURNS INT AS $$
-	SELECT id FROM users.addresses WHERE address = $1 || '@example.org';
-$$ LANGUAGE SQL;
-
-
-/*
- * Create a set of user addresses using some prefix
- */
-CREATE FUNCTION _create_addresses( _quantity INT , _prefix TEXT )
-		RETURNS VOID
-	AS $$
-DECLARE
-	i	INT;
-BEGIN
-	i := 0;
-	WHILE i < _quantity
-	LOOP
-		i := i + 1;
-		BEGIN
-			INSERT INTO users.addresses ( address )
-				VALUES ( _prefix || i::TEXT || '@example.org' );
-		EXCEPTION
-			WHEN unique_violation THEN
-				-- Address already exists, that's nice
-		END;
-	END LOOP;
-END;
-$$ LANGUAGE plpgsql;
-
-
-/*
- * Create a set of user accounts
- */
-CREATE FUNCTION _create_accounts( _quantity INT , _prefix TEXT )
-		RETURNS VOID
-	AS $$
-DECLARE
-	i	INT;
-BEGIN
-	PERFORM _create_test_strings( 0 );
-	PERFORM _create_addresses( _quantity , _prefix );
-	i := 0;
-	WHILE i < _quantity
-	LOOP
-		i := i + 1;
-		BEGIN
-			INSERT INTO users.credentials (
-				address_id , pass_md5 , pass_sha1 , language_id , credits
-			) VALUES (
-				_find_address( _prefix || i::TEXT ) , '' , '' , _get_language( 't' ) , 0
-			);
-		EXCEPTION
-			WHEN unique_violation THEN
-				-- Account already exists
-		END;
-	END LOOP;
-END;
-$$ LANGUAGE plpgsql;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/utils/common-setup/setup-gu-pmc-get-data-test.sql b/legacyworlds-server-data/db-structure/tests/utils/common-setup/setup-gu-pmc-get-data-test.sql
deleted file mode 100644
index 11bb7b4..0000000
--- a/legacyworlds-server-data/db-structure/tests/utils/common-setup/setup-gu-pmc-get-data-test.sql
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * We need rows in quite a few tables to make sure locking works as
- * advertised.
- *
- * - First we will need a planet with no resource providers. This one
- *   shouldn't be selected at all.
- * 
- * - We need a planet with resource providers, but no owning empire. The
- *   planet will be selected, but all fields that are obtained from the
- *   empire's data will be NULL.
- *
- * - We need a planet owned by an empire for which empire-wide settings
- *   will be used.
- *
- * - We need a planet owned by an empire but that uses planet-specific
- *   settings.
- *
- * - We need a planet with no resource providers owned by an empire. This
- *   one shouldn't be selected.
- *
- * - Finally, we need a planet that matches the criterias but isn't
- *   scheduled for an update at the time. 
- *
- * FIXME: cannot test where the happiness column comes from until values
- *		  all use DOUBLE PRECISION.
- */
-
-DELETE FROM sys.update_types
-	WHERE updtype_name <> 'PlanetMining';
-
-\i utils/strings.sql
-\i utils/resources.sql
-\i utils/accounts.sql
-\i utils/naming.sql
-\i utils/universe.sql
-
-SELECT sys.uoc_constant( 'game.resources.weightBase' , '(test)' , 'Resources' , 10.0 );
-SELECT _create_natural_resources( 2 , 'resource' );
-SELECT _create_raw_planets( 6 , 'planet' );
-SELECT _create_emp_names( 5 , 'empire' );
-INSERT INTO emp.empires ( name_id , cash )
-	SELECT id , 0 FROM naming.empire_names;
-
-/* Planet #2 */
-INSERT INTO verse.resource_providers (
-		planet_id , resource_name_id , resprov_quantity_max ,
-		resprov_quantity , resprov_difficulty , resprov_recovery
-	) VALUES (
-		_get_map_name( 'planet2' ) , _get_string( 'resource1' ) , 100 ,
-		100 , 0.2 , 0.5
-	) , (
-		_get_map_name( 'planet2' ) , _get_string( 'resource2' ) , 100 ,
-		100 , 0.2 , 0.5
-	);
-
-/* Planet #3 */
-INSERT INTO verse.resource_providers (
-		planet_id , resource_name_id , resprov_quantity_max ,
-		resprov_quantity , resprov_difficulty , resprov_recovery
-	) VALUES (
-		_get_map_name( 'planet3' ) , _get_string( 'resource1' ) , 100 ,
-		100 , 0.3 , 0.5
-	) , (
-		_get_map_name( 'planet3' ) , _get_string( 'resource2' ) , 100 ,
-		100 , 0.3 , 0.5
-	);
-INSERT INTO verse.planet_happiness ( planet_id , current , target )
-	VALUES ( _get_map_name( 'planet3' ) , 0.3 , 0.3 );
-INSERT INTO emp.planets ( empire_id , planet_id )
-	VALUES ( _get_emp_name( 'empire1' ) , _get_map_name( 'planet3' ) );
-INSERT INTO emp.mining_settings( empire_id , resource_name_id , empmset_weight )
-	VALUES (
-		_get_emp_name( 'empire1' ) , _get_string( 'resource1' ) , 2
-	) , (
-		_get_emp_name( 'empire1' ) , _get_string( 'resource2' ) , 2
-	);
-
-/* Planet #4 */
-INSERT INTO verse.resource_providers (
-		planet_id , resource_name_id , resprov_quantity_max ,
-		resprov_quantity , resprov_difficulty , resprov_recovery
-	) VALUES (
-		_get_map_name( 'planet4' ) , _get_string( 'resource1' ) , 100 ,
-		100 , 0.4 , 0.5
-	) , (
-		_get_map_name( 'planet4' ) , _get_string( 'resource2' ) , 100 ,
-		100 , 0.4 , 0.5
-	);
-INSERT INTO verse.planet_happiness ( planet_id , current , target )
-	VALUES ( _get_map_name( 'planet4' ) , 0.4 , 0.4 );
-INSERT INTO emp.planets ( empire_id , planet_id )
-	VALUES ( _get_emp_name( 'empire2' ) , _get_map_name( 'planet4' ) );
-INSERT INTO emp.mining_settings( empire_id , resource_name_id , empmset_weight )
-	VALUES (
-		_get_emp_name( 'empire2' ) , _get_string( 'resource1' ) , 2
-	) , (
-		_get_emp_name( 'empire2' ) , _get_string( 'resource2' ) , 2
-	);
-INSERT INTO emp.planet_mining_settings(
-		empire_id , planet_id , resource_name_id , emppmset_weight
-	) VALUES (
-			_get_emp_name( 'empire2' ) , _get_map_name( 'planet4' ) , _get_string( 'resource1' ) , 1
-		) , (
-			_get_emp_name( 'empire2' ) , _get_map_name( 'planet4' ) , _get_string( 'resource2' ) , 3
-		);
-
-/* Planet #5 */
-INSERT INTO verse.planet_happiness ( planet_id , current , target )
-	VALUES ( _get_map_name( 'planet5' ) , 0.5 , 0.5 );
-INSERT INTO emp.planets ( empire_id , planet_id )
-	VALUES ( _get_emp_name( 'empire3' ) , _get_map_name( 'planet5' ) );
-INSERT INTO emp.mining_settings( empire_id , resource_name_id , empmset_weight )
-	VALUES (
-		_get_emp_name( 'empire3' ) , _get_string( 'resource1' ) , 2
-	) , (
-		_get_emp_name( 'empire3' ) , _get_string( 'resource2' ) , 2
-	);
-
-/* Planet #6 */
-INSERT INTO verse.resource_providers (
-		planet_id , resource_name_id , resprov_quantity_max ,
-		resprov_quantity , resprov_difficulty , resprov_recovery
-	) VALUES (
-		_get_map_name( 'planet6' ) , _get_string( 'resource1' ) , 100 ,
-		100 , 0.6 , 0.5
-	) , (
-		_get_map_name( 'planet6' ) , _get_string( 'resource2' ) , 100 ,
-		100 , 0.6 , 0.5
-	);
-INSERT INTO verse.planet_happiness ( planet_id , current , target )
-	VALUES ( _get_map_name( 'planet6' ) , 0.6 , 0.6 );
-INSERT INTO emp.planets ( empire_id , planet_id )
-	VALUES ( _get_emp_name( 'empire4' ) , _get_map_name( 'planet6' ) );
-INSERT INTO emp.mining_settings( empire_id , resource_name_id , empmset_weight )
-	VALUES (
-		_get_emp_name( 'empire4' ) , _get_string( 'resource1' ) , 2
-	) , (
-		_get_emp_name( 'empire4' ) , _get_string( 'resource2' ) , 2
-	);
-
-/* Insert planet resource records */
-INSERT INTO verse.planet_resources ( planet_id , resource_name_id , pres_income , pres_upkeep )
-	SELECT p.name_id , r.resource_name_id , 42 , 0
-		FROM verse.planets p CROSS JOIN defs.resources r;
-
-/* Modify update records for the planets. Planet 6 is not to be processed.
- */
-UPDATE sys.updates su
-	SET update_state = 'PROCESSING' , update_last = 0
-	FROM verse.planets_updates vu
-	WHERE vu.update_id = su.update_id
-		AND vu.name_id <>  _get_map_name( 'planet6' );
-UPDATE sys.updates su
-	SET update_state = 'PROCESSED' , update_last = 0
-	FROM verse.planets_updates vu
-	WHERE vu.update_id = su.update_id
-		AND vu.name_id = _get_map_name( 'planet6' );
diff --git a/legacyworlds-server-data/db-structure/tests/utils/common-setup/setup-gu-research-get-empires-test.sql b/legacyworlds-server-data/db-structure/tests/utils/common-setup/setup-gu-research-get-empires-test.sql
deleted file mode 100644
index 9c22e59..0000000
--- a/legacyworlds-server-data/db-structure/tests/utils/common-setup/setup-gu-research-get-empires-test.sql
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * Common setup for research update locking and empire selection
- * --------------------------------------------------------------
- *
- * Empires are selected when:
- *		- they are part of the current update batch,
- *		- they possess planets,
- *		- they have in-progress research entries.
- * All related data is locked: the update entries, empire, empire technology
- * records, technology definitions, planets (including ownership records and
- * happiness records), as well as the empire's name and associated account.
- */
-
--- Make sure the only update type left is EmpireResearch
-DELETE FROM sys.update_types
-	WHERE updtype_name <> 'EmpireResearch';
-
-\i utils/strings.sql
-\i utils/resources.sql
-\i utils/accounts.sql
-\i utils/naming.sql
-\i utils/universe.sql
-
--- Create some technology definitions, dropping constraints on unused columns
-ALTER TABLE defs.technologies
-	ALTER technology_description_id DROP NOT NULL ,
-	ALTER technology_discovery_id DROP NOT NULL ,
-	ALTER technology_category_id DROP NOT NULL ,
-	ALTER technology_price DROP NOT NULL;
-SELECT _create_test_strings( 3 , 'tech' );
-INSERT INTO defs.technologies ( technology_name_id , technology_points )
-	SELECT id , 100.0 FROM defs.strings
-		WHERE name LIKE 'tech%';
-
--- Create the empire names and planets
-SELECT _create_emp_names( 6 , 'emp' );
-SELECT _create_raw_planets( 4 , 'planet' );
-INSERT INTO verse.planet_happiness( planet_id , target , current )
-	SELECT id , 0.75 , 1500
-		FROM naming.map_names
-		WHERE name LIKE 'planet%';
-
-
-/*
- * Empire 1 has no planets and no in-progress research. It will not be
- * selected or locked.
- */
-INSERT INTO emp.empires( name_id , cash )
-	VALUES( _get_emp_name( 'emp1' ) , 100.0 );
-INSERT INTO emp.technologies (
-		empire_id , technology_name_id ,
-		emptech_state , emptech_points , emptech_priority )
-	SELECT _get_emp_name( 'emp1' ) , technology_name_id , 'KNOWN' , NULL , NULL
-		FROM defs.technologies;
-
-/*
- * Empire 2 has planets, but no in-progress research. It will not be
- * selected.
- */
-INSERT INTO emp.empires( name_id , cash )
-	VALUES( _get_emp_name( 'emp2' ) , 100.0 );
-INSERT INTO emp.technologies (
-		empire_id , technology_name_id ,
-		emptech_state , emptech_points , emptech_priority )
-	SELECT _get_emp_name( 'emp2' ) , technology_name_id , 'KNOWN' , NULL , NULL
-		FROM defs.technologies;
-INSERT INTO emp.planets( empire_id , planet_id )
-	VALUES( _get_emp_name( 'emp2' ) , _get_map_name( 'planet1' ) );
-
-/*
- * Empire 3 has in-progress research, but no planets. It will not be selected.
- */
-INSERT INTO emp.empires( name_id , cash )
-	VALUES( _get_emp_name( 'emp3' ) , 100.0 );
-INSERT INTO emp.technologies ( empire_id , technology_name_id )
-	SELECT _get_emp_name( 'emp3' ) , technology_name_id
-		FROM defs.technologies;
-
-/*
- * Empire 4 has in-progress research and planets. It has no vacation mode
- * record. It will be selected.
- */
-INSERT INTO emp.empires( name_id , cash )
-	VALUES( _get_emp_name( 'emp4' ) , 100.0 );
-INSERT INTO emp.technologies ( empire_id , technology_name_id )
-	SELECT _get_emp_name( 'emp4' ) , technology_name_id
-		FROM defs.technologies;
-INSERT INTO emp.planets( empire_id , planet_id )
-	VALUES( _get_emp_name( 'emp4' ) , _get_map_name( 'planet2' ) );
-
-/*
- * Empire 5 has in-progress research, planets and a vacation mode record.
- * It will be selected.
- * 
- * Note: we need to add an entry to users.active_accounts for vacation mode
- * records to work.
- */
-INSERT INTO emp.empires( name_id , cash )
-	VALUES( _get_emp_name( 'emp5' ) , 100.0 );
-INSERT INTO emp.technologies ( empire_id , technology_name_id )
-	SELECT _get_emp_name( 'emp5' ) , technology_name_id
-		FROM defs.technologies;
-INSERT INTO emp.planets( empire_id , planet_id )
-	VALUES( _get_emp_name( 'emp5' ) , _get_map_name( 'planet3' ) );
-INSERT INTO users.active_accounts( credentials_id ,vacation_credits )
-	SELECT id , 12
-		FROM users.addresses
-		WHERE address = 'emp5@example.org';
-INSERT INTO users.vacations ( account_id , since , status )
-	SELECT id , NOW() , 'PROCESSED'
-		FROM users.addresses
-		WHERE address = 'emp5@example.org';
-
-/*
- * Empire 6 is similar to empire 4, but will not be marked for update in the
- * current batch.
- */
-INSERT INTO emp.empires( name_id , cash )
-	VALUES( _get_emp_name( 'emp6' ) , 100.0 );
-INSERT INTO emp.technologies ( empire_id , technology_name_id )
-	SELECT _get_emp_name( 'emp6' ) , technology_name_id
-		FROM defs.technologies;
-INSERT INTO emp.planets( empire_id , planet_id )
-	VALUES( _get_emp_name( 'emp6' ) , _get_map_name( 'planet4' ) );
-
-
-/* Speaking of current batch - set it up */
-UPDATE sys.updates su
-	SET update_state = 'PROCESSING' , update_last = 0
-	FROM emp.empires_updates eu
-	WHERE eu.update_id = su.update_id
-		AND eu.name_id <>  _get_emp_name( 'emp6' );
-UPDATE sys.updates su
-	SET update_state = 'PROCESSED' , update_last = 0
-	FROM emp.empires_updates eu
-	WHERE eu.update_id = su.update_id
-		AND eu.name_id =  _get_emp_name( 'emp6' );
diff --git a/legacyworlds-server-data/db-structure/tests/utils/locks-finder.sql b/legacyworlds-server-data/db-structure/tests/utils/locks-finder.sql
deleted file mode 100644
index bcbea18..0000000
--- a/legacyworlds-server-data/db-structure/tests/utils/locks-finder.sql
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Utility functions used by unit tests 
- *
- * Row lock checks
- */
-
-CREATE TYPE _locks_entry AS (
-	ctid		tid ,
-	shared		BOOLEAN ,
-	exclusive	BOOLEAN
-);
-
-CREATE OR REPLACE FUNCTION _get_locks_on(
-			IN _table		TEXT )
-		RETURNS SETOF _locks_entry
-		STRICT VOLATILE
-	AS $$
-
-DECLARE
-	_page		INT;
-	_pages		INT;
-	_record		RECORD;
-	_return		_locks_entry;
-
-BEGIN
-	SELECT INTO _pages pg_relation_size( _table ) / 8192;
-
-	FOR _page IN 0 .. ( _pages - 1 )
-	LOOP
-	
-		FOR _record IN SELECT t_ctid , t_infomask
-				FROM heap_page_items( get_raw_page( _table , _page ) )
-				WHERE t_xmax::text::int > ( txid_current( ) & x'ffffffff'::bigint )
-		LOOP
-			_return := ROW( _record.t_ctid ,
-				_record.t_infomask & x'80'::int <> 0 ,
-				_record.t_infomask & x'40'::int <> 0 );
-			RETURN NEXT _return;
-		END LOOP;
-
-	END LOOP;
-END;
-$$ LANGUAGE PLPGSQL;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/utils/naming.sql b/legacyworlds-server-data/db-structure/tests/utils/naming.sql
deleted file mode 100644
index 56efb0a..0000000
--- a/legacyworlds-server-data/db-structure/tests/utils/naming.sql
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Utility functions used by unit tests
- *
- * Naming system
- */
-
-
-/*
- * Obtain a map name identifier
- */
-CREATE FUNCTION _get_map_name( TEXT ) RETURNS INT AS $$
-	SELECT id FROM naming.map_names WHERE name = $1;
-$$ LANGUAGE SQL;
-
-
-/*
- * Obtain a map name identifier that does not exist
- */
-CREATE FUNCTION _get_bad_map_name( ) RETURNS INT AS $$
-	SELECT MAX( id ) + 1 FROM naming.map_names;
-$$ LANGUAGE SQL;
-
-
-/*
- * Create a few map names using a prefix
- */
-CREATE FUNCTION _create_map_names( _quantity INT , _prefix TEXT )
-		RETURNS VOID
-	AS $$
-DECLARE
-	i	INT;
-BEGIN
-	i := 0;
-	WHILE i < _quantity
-	LOOP
-		i := i + 1;
-		BEGIN
-			INSERT INTO naming.map_names (name) VALUES ( _prefix || i::TEXT );
-		EXCEPTION
-			WHEN unique_violation THEN
-				-- Ignore the error
-		END;
-	END LOOP;
-END;
-$$ LANGUAGE PLPGSQL;
-
-
-/*
- * Get the empire that belongs to some user, based on that user's email
- */
-CREATE FUNCTION _get_emp_name( TEXT ) RETURNS INT AS $$
-	SELECT id FROM naming.empire_names WHERE owner_id = _find_address( $1 );
-$$ LANGUAGE SQL;
-
-
-/*
- * Obtain a map name identifier that does not exist
- */
-CREATE FUNCTION _get_bad_emp_name( ) RETURNS INT AS $$
-	SELECT MAX( id ) + 1 FROM naming.empire_names;
-$$ LANGUAGE SQL;
-
-
-/*
- * Create a few empire names using a prefix for user accounts.
- * Empires are named "testX" independently of the user accounts.
- */
-CREATE FUNCTION _create_emp_names( _quantity INT , _prefix TEXT )
-		RETURNS VOID
-	AS $$
-DECLARE
-	i	INT;
-	j	INT;
-BEGIN
-	PERFORM _create_accounts( _quantity , _prefix );
-	i := 0;
-	WHILE i < _quantity
-	LOOP
-		i := i + 1;
-		j := 0;
-		LOOP
-			BEGIN
-				INSERT INTO naming.empire_names ( owner_id , name )
-					VALUES ( _find_address( _prefix || i::TEXT ) , 'test' || j::TEXT );
-				EXIT;
-			EXCEPTION
-				WHEN unique_violation THEN
-					j := j + 1;
-			END;
-		END LOOP;
-	END LOOP;
-END;
-$$ LANGUAGE PLPGSQL;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/utils/resources.sql b/legacyworlds-server-data/db-structure/tests/utils/resources.sql
deleted file mode 100644
index 8cc3415..0000000
--- a/legacyworlds-server-data/db-structure/tests/utils/resources.sql
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Utility functions used by unit tests
- *
- * Resources and natural resources
- */
-
-
-/*
- * Function that creates some quantity of resources
- * All resources are created using the specified prefix for the strings
- */
-CREATE FUNCTION _create_resources( _quantity INT , _prefix TEXT )
-		RETURNS VOID
-	AS $$
-DECLARE
-	i	INT;
-BEGIN
-	PERFORM _create_test_strings( _quantity , _prefix );
-	PERFORM _create_test_strings( _quantity , _prefix || 'Description' );
-	
-	i := 0;
-	WHILE i < _quantity
-	LOOP
-		i := i + 1;
-		INSERT INTO defs.resources (
-			resource_name_id , resource_description_id , resource_weight
-		) VALUES (
-			_get_string( _prefix || i::TEXT ) ,
-			_get_string( _prefix || 'Description' || i::TEXT ) ,
-			i
-		);
-	END LOOP;
-END;
-$$ LANGUAGE PLPGSQL;
-
-
-/*
- * Function that creates some quantity of /natural/ resources
- * All resources are created using the specified prefix for the strings
- */
-CREATE FUNCTION _create_natural_resources( _quantity INT , _prefix TEXT )
-		RETURNS VOID
-	AS $$
-DECLARE
-	i	INT;
-BEGIN
-	PERFORM _create_resources( _quantity , _prefix );
-
-	i := 0;
-	WHILE i < _quantity
-	LOOP
-		i := i + 1;
-		INSERT INTO defs.natural_resources(
-			resource_name_id , natres_p_presence , natres_quantity_avg ,
-			natres_quantity_dev , natres_difficulty_avg ,
-			natres_difficulty_dev , natres_recovery_avg ,
-			natres_recovery_dev
-		) VALUES (
-			_get_string( _prefix || i::TEXT ) , 0.5 , 100 , 1 , 0.5 , 0.05 , 0.5 , 0.05
-		);
-	END LOOP;
-END;
-$$ LANGUAGE PLPGSQL;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/tests/utils/strings.sql b/legacyworlds-server-data/db-structure/tests/utils/strings.sql
deleted file mode 100644
index 3303ae3..0000000
--- a/legacyworlds-server-data/db-structure/tests/utils/strings.sql
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Utility functions used by unit tests
- *
- * I18N string creation and access
- */
-
-
-/*
- * Function that returns an invalid string identifier.
- */
-CREATE FUNCTION _get_bad_string( ) RETURNS INT AS $$
-	SELECT MAX( id ) + 1 FROM defs.strings;
-$$ LANGUAGE SQL;
-
-
-/*
- * Function that returns a language's identifier
- */
-CREATE FUNCTION _get_language( TEXT ) RETURNS INT AS $$
-	SELECT id FROM defs.languages WHERE language = $1;
-$$ LANGUAGE SQL;
-
-
-/*
- * Function that returns a string's identifier
- */
-CREATE FUNCTION _get_string( TEXT ) RETURNS INT AS $$
-	SELECT id FROM defs.strings WHERE name = $1;
-$$ LANGUAGE SQL;
-
-
-/*
- * Function that creates some quantity of test strings using a specific prefix
- * and translation prefix.
- */
-CREATE FUNCTION _create_test_strings( _quantity INT , _prefix TEXT , _trans TEXT )
-		RETURNS VOID
-	AS $$
-DECLARE
-	i	INT;
-BEGIN
-	PERFORM defs.uoc_language( 't' , 'Test' );
-
-	i := 0;
-	WHILE i < _quantity
-	LOOP
-		i := i + 1;
-		PERFORM defs.uoc_translation( 't' , _prefix || i::TEXT ,
-			_trans || i::TEXT );
-	END LOOP;
-END;
-$$ LANGUAGE PLPGSQL;
-
-/*
- * Function that creates some quantity of test strings using a specific prefix
- */
-CREATE FUNCTION _create_test_strings( _quantity INT , _prefix TEXT )
-	RETURNS VOID
-AS $$
-	SELECT _create_test_strings( $1 , $2 , 'Test string #' );
-$$ LANGUAGE SQL;
-
-
-/*
- * Function that creates some quantity of test strings
- */
-CREATE FUNCTION _create_test_strings( _quantity INT )
-	RETURNS VOID
-AS $$
-	SELECT _create_test_strings( $1 , 'test' );
-$$ LANGUAGE SQL;
-
diff --git a/legacyworlds-server-data/db-structure/tests/utils/universe.sql b/legacyworlds-server-data/db-structure/tests/utils/universe.sql
deleted file mode 100644
index 8a2a4bc..0000000
--- a/legacyworlds-server-data/db-structure/tests/utils/universe.sql
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Utility functions used by unit tests
- *
- * Universe
- */
-
-/*
- * Create a new system at some coordinates and return its identifier
- */
-CREATE FUNCTION _create_system( INT , INT ) RETURNS INT AS $$
-	INSERT INTO verse.systems ( x , y )
-		VALUES ( $1 , $2 )
-		RETURNING id;
-$$ LANGUAGE SQL;
-
-
-/*
- * Create "raw" planets
- */
-CREATE FUNCTION _create_raw_planets( _quantity INT , _prefix TEXT )
-		RETURNS VOID
-	AS $$
-DECLARE
-	_system	INT;
-	_orbit	INT;
-	i		INT;
-BEGIN
-	PERFORM _create_map_names( _quantity , _prefix );
-	
-	i := 0;
-	WHILE i < _quantity
-	LOOP
-		i := i + 1;
-		
-		IF _system IS NULL
-		THEN
-			_system := _create_system( i , i );
-			_orbit := 1;
-		END IF;
-		
-		INSERT INTO verse.planets(
-			name_id , system_id , orbit , picture , population
-		) VALUES (
-			_get_map_name( _prefix || i::TEXT ) , _system , _orbit , 1 , 1
-		);
-		
-		IF _orbit = 5
-		THEN
-			_system := NULL;
-		ELSE
-			_orbit := _orbit + 1;
-		END IF;
-	END LOOP;
-END;
-$$ LANGUAGE PLPGSQL;
-
-
-/*
- * Create a resource provider
- */
-CREATE FUNCTION _create_resource_provider( TEXT , TEXT ) RETURNS VOID AS $$
-	INSERT INTO verse.resource_providers(
-		planet_id , resource_name_id ,
-		resprov_quantity_max , resprov_quantity ,
-		resprov_difficulty , resprov_recovery
-	) VALUES (
-		_get_map_name( $1 ) , _get_string( $2 ) ,
-		100 , 50 ,
-		0.5 , 0.5
-	);
-$$ LANGUAGE SQL;
\ No newline at end of file
diff --git a/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/GeneralInformation.java b/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/GeneralInformation.java
deleted file mode 100644
index afd37d3..0000000
--- a/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/GeneralInformation.java
+++ /dev/null
@@ -1,104 +0,0 @@
-package com.deepclone.lw.sqld.game;
-
-
-public class GeneralInformation
-{
-	private String name;
-
-	private String language;
-
-	private Character status;
-
-	private String tag;
-
-	private long cash;
-
-	private long nextTick;
-
-	private int accountId;
-
-
-	public String getName( )
-	{
-		return this.name;
-	}
-
-
-	public void setName( String name )
-	{
-		this.name = name;
-	}
-
-
-	public String getLanguage( )
-	{
-		return this.language;
-	}
-
-
-	public void setLanguage( String language )
-	{
-		this.language = language;
-	}
-
-
-	public Character getStatus( )
-	{
-		return this.status;
-	}
-
-
-	public void setStatus( Character status )
-	{
-		this.status = status;
-	}
-
-
-	public String getTag( )
-	{
-		return this.tag;
-	}
-
-
-	public void setTag( String tag )
-	{
-		this.tag = tag;
-	}
-
-
-	public long getCash( )
-	{
-		return this.cash;
-	}
-
-
-	public void setCash( long cash )
-	{
-		this.cash = cash;
-	}
-
-
-	public long getNextTick( )
-	{
-		return this.nextTick;
-	}
-
-
-	public void setNextTick( long nextTick )
-	{
-		this.nextTick = nextTick;
-	}
-
-
-	public int getAccountId( )
-	{
-		return this.accountId;
-	}
-
-
-	public void setAccountId( int accountId )
-	{
-		this.accountId = accountId;
-	}
-
-}
diff --git a/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/sys/GameUpdateResult.java b/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/sys/GameUpdateResult.java
deleted file mode 100644
index 5388528..0000000
--- a/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/sys/GameUpdateResult.java
+++ /dev/null
@@ -1,82 +0,0 @@
-package com.deepclone.lw.sqld.sys;
-
-
-/**
- * The result of a game update
- * 
- * <p>
- * This class is used to transmit the results of the game updates processor. The results may
- * indicate:
- * <ul>
- * <li>a finished game update cycle that needs no further processing,
- * <li>an in-progress update cycle for which further in-base processing is needed,
- * <li>an in-progress update cycle where some processing must be done in the server.
- * </ul>
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-public class GameUpdateResult
-{
-
-	/** Whether the update cycle is finished */
-	private final boolean finished;
-
-	/**
-	 * Name of the type of processing that needs to be run on the server, or <code>null</code> if
-	 * the update is finished or was processed in-base
-	 */
-	private final String localExecution;
-
-
-	/**
-	 * Initialise a "finished" game update result
-	 * 
-	 * <p>
-	 * This constructor will set {@link #finished} to <code>true</code> and {@link #localExecution}
-	 * to <code>null</code>.
-	 */
-	public GameUpdateResult( )
-	{
-		this.finished = true;
-		this.localExecution = null;
-	}
-
-
-	/**
-	 * Initialise an "incomplete" game update result
-	 * 
-	 * <p>
-	 * This constructor will set {@link #finished} to <code>false</code> and {@link #localExecution}
-	 * to the parameter's value.
-	 * 
-	 * @param localExecution
-	 *            the name of the type of processing to be executed on the server, or
-	 *            <code>null</code> if the update was processed in-base.
-	 */
-	public GameUpdateResult( String localExecution )
-	{
-		this.finished = false;
-		this.localExecution = localExecution;
-	}
-
-
-	/**
-	 * @return <code>true</code> if the update cycle was completed or <code>false</code> if further
-	 *         processing is required.
-	 */
-	public boolean isFinished( )
-	{
-		return this.finished;
-	}
-
-
-	/**
-	 * @return Name of the type of processing that needs to be run on the server, or
-	 *         <code>null</code> if the update is finished or was processed in-base
-	 */
-	public String getLocalExecution( )
-	{
-		return this.localExecution;
-	}
-
-}
diff --git a/legacyworlds-server-data/src/main/resources/.empty b/legacyworlds-server-data/src/main/resources/.empty
deleted file mode 100644
index e69de29..0000000
diff --git a/legacyworlds-server-data/src/test/java/.empty b/legacyworlds-server-data/src/test/java/.empty
deleted file mode 100644
index e69de29..0000000
diff --git a/legacyworlds-server-data/src/test/resources/.empty b/legacyworlds-server-data/src/test/resources/.empty
deleted file mode 100644
index e69de29..0000000
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/bt/EmpireSummary.java b/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/bt/EmpireSummary.java
deleted file mode 100644
index 8efd0c6..0000000
--- a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/bt/EmpireSummary.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package com.deepclone.lw.interfaces.bt;
-
-
-/**
- * Empire XML summary generator
- * 
- * <p>
- * This interface corresponds to the component which generates XML dumps of an empire's state to be
- * included in bug reports.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-public interface EmpireSummary
-{
-
-	/**
-	 * Generate an empire's XML summary
-	 * 
-	 * <p>
-	 * This method retrieves all necessary data from the database and converts it into an XML dump
-	 * to be used in the bug report.
-	 * 
-	 * @param empireId
-	 *            the empire's identifier
-	 * 
-	 * @return the XML summary of the empire's current state
-	 */
-	public String getSummary( int empireId );
-
-}
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/resources/MiningSettingsDAO.java b/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/resources/MiningSettingsDAO.java
deleted file mode 100644
index 4281198..0000000
--- a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/resources/MiningSettingsDAO.java
+++ /dev/null
@@ -1,93 +0,0 @@
-package com.deepclone.lw.interfaces.game.resources;
-
-
-/**
- * Data access object for mining settings
- * 
- * <p>
- * This interface provides methods which call stored procedures that control mining settings for
- * both empires and planets.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-public interface MiningSettingsDAO
-{
-
-	/**
-	 * Start an empire settings update
-	 * 
-	 * <p>
-	 * Start an empire settings update by calling the <code>emp.mset_update_start(INT)</code> stored
-	 * procedure.
-	 * 
-	 * @param empire
-	 *            the identifier of the empire whose settings will be updated
-	 * 
-	 * @return <code>true</code> on success, <code>false</code> on failure
-	 */
-	public boolean startUpdate( int empire );
-
-
-	/**
-	 * Start a planet settings update
-	 * 
-	 * <p>
-	 * Start a planet settings update by calling the <code>emp.mset_update_start(INT,INT)</code>
-	 * stored procedure.
-	 * 
-	 * @param empire
-	 *            the identifier of the empire who supposedly owns the planet
-	 * @param planet
-	 *            the identifier of the planet whose settings will be changed
-	 * 
-	 * @return <code>true</code> if the planet belongs to the specified empire and has specific
-	 *         mining settings
-	 */
-	public boolean startUpdate( int empire , int planet );
-
-
-	/**
-	 * Set the new extraction priority of a resource
-	 * 
-	 * <p>
-	 * Call the <code>emp.mset_update_set(TEXT,INT)</code> stored procedure to set the new
-	 * extraction priority for some type of resources. An mining settings update (empire- or
-	 * planet-wide) must have been initiated before this method is called.
-	 * 
-	 * @param resource
-	 *            the identifier of the resource
-	 * @param priority
-	 *            the new extraction priority for the resource
-	 * 
-	 * @return <code>true</code> on success, <code>false</code> if the resource did not exist.
-	 */
-	public boolean setNewPriority( String resource , int priority );
-
-
-	/**
-	 * Apply the current settings update
-	 * 
-	 * <p>
-	 * This method applies a previously initiated mining settings update by calling the
-	 * <code>emp.mset_update_apply()</code> stored procedure.
-	 * 
-	 * @return <code>true</code> on success, <code>false</code> if one of the priorities was
-	 *         invalid.
-	 */
-	public boolean applyUpdate( );
-
-
-	/**
-	 * Toggle the source of a planet's mining settings
-	 * 
-	 * <p>
-	 * Call the <code>emp.mset_toggle_source(INT,INT)</code> stored procedure to toggle the source
-	 * of a planet's mining priorities.
-	 * 
-	 * @param empire
-	 *            the empire's identifier
-	 * @param planet
-	 *            the planet's identifier
-	 */
-	public void togglePlanet( int empire , int planet );
-}
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/resources/ResourcesController.java b/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/resources/ResourcesController.java
deleted file mode 100644
index 940dc45..0000000
--- a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/resources/ResourcesController.java
+++ /dev/null
@@ -1,62 +0,0 @@
-package com.deepclone.lw.interfaces.game.resources;
-
-
-import java.util.Map;
-
-
-
-/**
- * Resources control interface
- * 
- * <p>
- * This interface corresponds to the component which controls resources from the game's point of
- * view. It contains methods that update mining settings.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-public interface ResourcesController
-{
-
-	/**
-	 * Update an empire's mining settings
-	 * 
-	 * @param empireId
-	 *            the empire's identifier
-	 * @param settings
-	 *            the new settings
-	 */
-	public void updateEmpireSettings( int empireId , Map< String , Integer > settings );
-
-
-	/**
-	 * Toggle the source of a planet's mining priorities
-	 * 
-	 * <p>
-	 * If the planet is currently using specific priorities, it will revert to empire-wide settings,
-	 * and vice-versa. The planet must belong to the specified empire.
-	 * 
-	 * @param empire
-	 *            the empire's identifier
-	 * @param planet
-	 *            the planet's identifier
-	 */
-	public void togglePlanet( int empire , int planet );
-
-
-	/**
-	 * Update a planet's mining settings
-	 * 
-	 * <p>
-	 * If the planet is using specific mining priorities and belongs to the specified empire, update
-	 * its mining priorities.
-	 * 
-	 * @param empire
-	 *            the empire's identifier
-	 * @param planet
-	 *            the planet's identifier
-	 * @param settings
-	 *            the new priorities
-	 */
-	public void updatePlanetSettings( int empire , int planet , Map< String , Integer > settings );
-
-}
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/resources/ResourcesInformationDAO.java b/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/resources/ResourcesInformationDAO.java
deleted file mode 100644
index 44acfd1..0000000
--- a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/resources/ResourcesInformationDAO.java
+++ /dev/null
@@ -1,57 +0,0 @@
-package com.deepclone.lw.interfaces.game.resources;
-
-
-import java.util.List;
-import java.util.Map;
-
-import com.deepclone.lw.cmd.player.gdata.PlanetListResourceRecord;
-import com.deepclone.lw.cmd.player.gdata.empire.EmpireResourceRecord;
-import com.deepclone.lw.cmd.player.gdata.planets.PlanetResourceRecord;
-
-
-
-/**
- * Resources information access component interface
- * 
- * <p>
- * This interface defines the methods which execute the queries required to extract information
- * about resources from the database.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-public interface ResourcesInformationDAO
-{
-
-	/**
-	 * Obtain resources information for a planet
-	 * 
-	 * @param planet
-	 *            the planet to obtain information about
-	 * 
-	 * @return the list of planetary resource records
-	 */
-	public List< PlanetResourceRecord > getPlanetInformation( int planet );
-
-
-	/**
-	 * Obtain resources information for an empire
-	 * 
-	 * @param empire
-	 *            the empire to obtain information about
-	 * 
-	 * @return the list of empire economic records
-	 */
-	public List< EmpireResourceRecord > getEmpireInformation( int empire );
-
-
-	/**
-	 * Obtain resources information for an empire's planet list
-	 * 
-	 * @param empire
-	 *            the empire whose planet list is being generated
-	 * 
-	 * @return a map of planet list resource records associating planet identifiers to lists of
-	 *         resource records
-	 */
-	public Map< Integer , List< PlanetListResourceRecord > > getPlanetListData( int empire );
-}
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/technologies/PlayerTechnologiesDAO.java b/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/technologies/PlayerTechnologiesDAO.java
deleted file mode 100644
index e0c349e..0000000
--- a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/technologies/PlayerTechnologiesDAO.java
+++ /dev/null
@@ -1,92 +0,0 @@
-package com.deepclone.lw.interfaces.game.technologies;
-
-
-import java.util.List;
-
-import com.deepclone.lw.cmd.player.gdata.empire.ResearchData;
-
-
-
-/**
- * Player-oriented data access interface for technologies
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-public interface PlayerTechnologiesDAO
-{
-
-	/**
-	 * Obtain the list of technologies for an empire
-	 * 
-	 * <p>
-	 * Query the database for technology entries as seen from an empire's perspective. The
-	 * technologies will be returned with I18N string identifiers for categories, names and
-	 * descriptions (unless the details are not available).
-	 * 
-	 * @param empire
-	 *            the empire's identifier
-	 * 
-	 * @return the list of technology entries
-	 */
-	public List< ResearchData > getResearchData( int empire );
-
-
-	/**
-	 * Start a research priority update
-	 * 
-	 * <p>
-	 * This method initialises a research priorities update by calling the appropriate stored
-	 * procedure.
-	 * 
-	 * @param empire
-	 *            the empire for which an update is being performed
-	 * 
-	 * @return <code>true</code> on success, <code>false</code> on failure
-	 */
-	public boolean startPriorityUpdate( int empire );
-
-
-	/**
-	 * Upload a single research priority
-	 * 
-	 * <p>
-	 * This method uploads the priority for one of the in-progress research items. It must be called
-	 * only after a research priority update has been initiated.
-	 * 
-	 * @param identifier
-	 *            the technology's identifier
-	 * @param priority
-	 *            the research priority
-	 * 
-	 * @return <code>true</code> on success, <code>false</code> on failure
-	 */
-	public boolean uploadResearchPriority( String identifier , int priority );
-
-
-	/**
-	 * Apply an in-progress research priority update
-	 * 
-	 * <p>
-	 * This method applies a previously uploaded set of research priority updates.
-	 * 
-	 * @return <code>true</code> on success, <code>false</code> on failure
-	 */
-	public boolean applyPriorityUpdate( );
-
-
-	/**
-	 * Implement a technology
-	 * 
-	 * <p>
-	 * This method calls the stored procedure which causes an empire to implement a technology.
-	 * 
-	 * @param empire
-	 *            the empire's identifier
-	 * @param technology
-	 *            the technology's identifier
-	 * 
-	 * @return <code>true</code> on success, <code>false</code> on failure
-	 */
-	public boolean implement( int empire , String technology );
-
-}
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/technologies/ResearchController.java b/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/technologies/ResearchController.java
deleted file mode 100644
index e32d840..0000000
--- a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/technologies/ResearchController.java
+++ /dev/null
@@ -1,69 +0,0 @@
-package com.deepclone.lw.interfaces.game.technologies;
-
-
-import java.util.Map;
-
-import com.deepclone.lw.cmd.player.tech.GetResearchCommand;
-import com.deepclone.lw.cmd.player.tech.GetResearchResponse;
-
-
-
-/**
- * Research control interface
- * 
- * <p>
- * This interface is implemented by the component which allows empires (and therefore players) to
- * view the research state and control it.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-public interface ResearchController
-{
-
-	/**
-	 * Obtain the state of an empire's research
-	 * 
-	 * <p>
-	 * This method must be overridden to generate the response to a {@link GetResearchCommand}.
-	 * 
-	 * @param empire
-	 *            the empire's identifier
-	 * 
-	 * @return the appropriate {@link GetResearchResponse} instance
-	 */
-	public GetResearchResponse getResearchData( int empire );
-
-
-	/**
-	 * Update research priorities
-	 * 
-	 * <p>
-	 * This method must be implemented so it updates research priorities for an empire.
-	 * 
-	 * @param empire
-	 *            the empire to update
-	 * @param priorities
-	 *            the new research priorities, as a map associating technology identifiers to
-	 *            priority values
-	 * 
-	 * @return <code>true</code> on success, <code>false</code> otherwise
-	 */
-	public boolean updatePriorities( int empire , Map< String , Integer > priorities );
-
-
-	/**
-	 * Implement a technology
-	 * 
-	 * <p>
-	 * This method implements a technology which has been fully researched.
-	 * 
-	 * @param empire
-	 *            the empire trying to implement a technology
-	 * @param technology
-	 *            the technology's identifier
-	 * 
-	 * @return <code>true</code> on success, <code>false</code> otherwise
-	 */
-	public boolean implement( int empire , String technology );
-
-}
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/updates/GameUpdateProcessor.java b/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/updates/GameUpdateProcessor.java
deleted file mode 100644
index 9008c4f..0000000
--- a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/updates/GameUpdateProcessor.java
+++ /dev/null
@@ -1,75 +0,0 @@
-package com.deepclone.lw.interfaces.game.updates;
-
-
-/**
- * Game update processor
- * 
- * <p>
- * The game update processor allows game update cycles to be executed. It also provides the ability
- * to terminated an existing update cycle.
- * 
- * <p>
- * The game update processor includes a locking mechanism which can be used to prevent two
- * components (for example the game update ticker task and the administration interface) from
- * executing game updates simultaneously.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-public interface GameUpdateProcessor
-{
-
-	/**
-	 * Try locking the game update processor
-	 * 
-	 * <p>
-	 * Test and set the processor's lock. This lock is not re-entrant and should only be called once
-	 * per locking thread.
-	 * 
-	 * @return <code>true</code> if the lock was acquired, <code>false</code> it some other
-	 *         component had already locked the processor.
-	 */
-	public boolean tryLock( );
-
-
-	/**
-	 * Unlock the game update processor
-	 * 
-	 * <p>
-	 * Reset the processor's lock. This method should be called from the thread which actually
-	 * locked the processor in the first place, although that will not be checked.
-	 * 
-	 * @throws IllegalStateException
-	 *             if the processor is not locked.
-	 */
-	public void unlock( )
-			throws IllegalStateException;
-
-
-	/**
-	 * End the previous update cycle
-	 * 
-	 * <p>
-	 * Check if an update cycle had already started. If such is the case, execute all remaining
-	 * update batches.
-	 * 
-	 * @return <code>true</code> if an update cycle was processed or if the system is under
-	 *         maintenance, <code>false</code> otherwise.
-	 */
-	public boolean endPreviousCycle( );
-
-
-	/**
-	 * Execute a full update cycle
-	 * 
-	 * <p>
-	 * Check for an update cycle that was already started. If one exists, finish it. Otherwise,
-	 * start a new cycle and execute all batches in separate transactions.
-	 * 
-	 * <p>
-	 * Update cycles will not be processed if the system is under maintenance. In addition, if the
-	 * system enters maintenance mode while updates are being processed, the processing will stop
-	 * after the current batch.
-	 */
-	public void executeUpdateCycle( );
-
-}
\ No newline at end of file
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/updates/UpdateBatchProcessor.java b/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/updates/UpdateBatchProcessor.java
deleted file mode 100644
index a295193..0000000
--- a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/updates/UpdateBatchProcessor.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package com.deepclone.lw.interfaces.game.updates;
-
-
-/**
- * Update batch processor interface
- * 
- * <p>
- * This interface must be implemented by all components which provide support for server-side game
- * updates processing. The components will be gathered automatically when the server initialises.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- * 
- */
-public interface UpdateBatchProcessor
-{
-
-	/**
-	 * Obtain the component's supported update type
-	 * 
-	 * <p>
-	 * This method must be implemented to return a string which corresponds to the name of the
-	 * update type in the database's <code>sys.update_types</code> registry table.
-	 * 
-	 * @return the update type supported by the component
-	 */
-	public String getUpdateType( );
-
-
-	/**
-	 * Process a batch of updates
-	 * 
-	 * <p>
-	 * This method is called by the main update processor in the transaction during which items from
-	 * the batch will have been marked for processing. It should process the update, but it must not
-	 * modify the update rows in the <code>sys.updates</code> table.
-	 * 
-	 * @param tickId
-	 *            the identifier of the current game update cycle
-	 */
-	public void processBatch( long tickId );
-
-}
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/updates/UpdatesDAO.java b/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/updates/UpdatesDAO.java
deleted file mode 100644
index 7c48c40..0000000
--- a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/updates/UpdatesDAO.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package com.deepclone.lw.interfaces.game.updates;
-
-
-import com.deepclone.lw.sqld.sys.GameUpdateResult;
-
-
-
-/**
- * Game updates data access
- * 
- * <p>
- * This interface allows access to the data and stored procedure which constitute the game update
- * sub-system.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-public interface UpdatesDAO
-{
-
-	/**
-	 * Run a batch of game updates
-	 * 
-	 * <p>
-	 * Execute a batch of game updates for the current game update cycle. The value returned by this
-	 * method determines whether the caller should call the method again, and if so whether it needs
-	 * to do some in-server processing.
-	 * 
-	 * @param tickId
-	 *            the identifier of the current game update cycle
-	 * 
-	 * @return the results of the game update processor
-	 */
-	public GameUpdateResult processUpdates( long tickId );
-}
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/naming/ObjectNameValidator.java b/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/naming/ObjectNameValidator.java
deleted file mode 100644
index 12b88de..0000000
--- a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/naming/ObjectNameValidator.java
+++ /dev/null
@@ -1,55 +0,0 @@
-package com.deepclone.lw.interfaces.naming;
-
-
-import com.deepclone.lw.cmd.ObjectNameError;
-
-
-
-/**
- * Object name validator
- * 
- * <p>
- * This interface corresponds to a component which can be used to "pre-validate" the names of
- * objects (empires, map objects, fleets, etc...). It does not check for banned or duplicate names.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-public interface ObjectNameValidator
-{
-
-	/**
-	 * Validate a name using the component's defaults
-	 * 
-	 * <p>
-	 * Check the name's validity. The name must match the usual naming constraints (valid
-	 * characters, no sequences of white space, name starts with an alphabetic character) and its
-	 * length is checked against the component's default constraints.
-	 * 
-	 * @param name
-	 *            the name to validate
-	 * 
-	 * @return the validation error if one occurred, or <code>null</code> if the name is valid
-	 */
-	public ObjectNameError validate( String name );
-
-
-	/**
-	 * Validate a name using specific length constraints
-	 * 
-	 * <p>
-	 * Check the name's validity. The name must match the usual naming constraints (valid
-	 * characters, no sequences of white space, name starts with an alphabetic character) and its
-	 * length is checked against the specific constraints given as arguments.
-	 * 
-	 * @param name
-	 *            the name to validate
-	 * @param minLength
-	 *            the minimal accepted length
-	 * @param maxLength
-	 *            the maximal accepted length
-	 * 
-	 * @return the validation error if one occurred, or <code>null</code> if the name is valid
-	 */
-	public ObjectNameError validate( String name , int minLength , int maxLength );
-
-}
\ No newline at end of file
diff --git a/legacyworlds-server-interfaces/src/main/resources/.empty b/legacyworlds-server-interfaces/src/main/resources/.empty
deleted file mode 100644
index e69de29..0000000
diff --git a/legacyworlds-server-interfaces/src/test/java/.empty b/legacyworlds-server-interfaces/src/test/java/.empty
deleted file mode 100644
index e69de29..0000000
diff --git a/legacyworlds-server-interfaces/src/test/resources/.empty b/legacyworlds-server-interfaces/src/test/resources/.empty
deleted file mode 100644
index e69de29..0000000
diff --git a/legacyworlds-server-main/data/event-definitions.xml b/legacyworlds-server-main/data/event-definitions.xml
deleted file mode 100644
index 6cfb70a..0000000
--- a/legacyworlds-server-main/data/event-definitions.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<lw-event-definitions xmlns="http://www.deepclone.com/lw/b6/m2/event-definitions"
-		xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-		xsi:schemaLocation="http://www.deepclone.com/lw/b6/m2/event-definitions event-definitions.xsd">
-
-	<!-- An item in one of the build queues has been completed -->
-	<evdef id="bq-progress" priority="0" i18n-strings="evtBQProgress">
-		<boolean id="is-military" />
-		<boolean id="is-construction" />
-		<entity id="planet" entity-type="PLN" required="0" /> 
-		<text id="planet-name" max-length="20" />
-		<i18n id="nature" />
-	</evdef>
-
-	<!-- A build queue is empty -->
-	<evdef id="bq-empty" priority="1" i18n-strings="evtBQEmpty">
-		<boolean id="is-military" />
-		<entity id="planet" entity-type="PLN" required="0" /> 
-		<text id="planet-name" max-length="20" />
-	</evdef>
-	
-	<!-- A research is ready to be implemented -->
-	<evdef id="research-complete" i18n-strings="evtResearch">
-		<i18n id="technology" />
-	</evdef>
-
-</lw-event-definitions>
diff --git a/legacyworlds-server-main/data/event-definitions.xsd b/legacyworlds-server-main/data/event-definitions.xsd
deleted file mode 100644
index 417a9f8..0000000
--- a/legacyworlds-server-main/data/event-definitions.xsd
+++ /dev/null
@@ -1,110 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<xs:schema xmlns="http://www.deepclone.com/lw/b6/m2/event-definitions"
-	xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.deepclone.com/lw/b6/m2/event-definitions"
-	xmlns:tns="http://www.deepclone.com/lw/b6/m2/event-definitions"
-	elementFormDefault="qualified" attributeFormDefault="unqualified">
-
-	<!-- Root element, contains a sequence of event definitions -->
-	<xs:element name="lw-event-definitions">
-		<xs:complexType>
-			<xs:sequence>
-				<xs:element name="evdef" type="evdef" minOccurs="0"
-					maxOccurs="unbounded" />
-			</xs:sequence>
-		</xs:complexType>
-	</xs:element>
-
-	<!-- Event definitions. Needs an ID and an I18N base, may also provide information 
-		about the event's priority. May contain a list of field definitions. -->
-	<xs:complexType name="evdef">
-		<xs:sequence>
-			<xs:group ref="evdef-field" minOccurs="0" maxOccurs="unbounded" />
-		</xs:sequence>
-		<xs:attribute name="id" use="required" type="xs:token" />
-		<xs:attribute name="priority" use="optional" default="2"
-			type="priority-value" />
-		<xs:attribute name="adjustable" use="optional" type="xs:boolean"
-			default="true" />
-		<xs:attribute name="i18n-strings" use="required" type="xs:token" />
-	</xs:complexType>
-
-	<!-- Priority values are integers in [0;4] -->
-	<xs:simpleType name="priority-value">
-		<xs:restriction base="xs:integer">
-			<xs:minInclusive value="0" />
-			<xs:maxInclusive value="4" />
-		</xs:restriction>
-	</xs:simpleType>
-
-	<!-- Field definitions -->
-	<xs:group name="evdef-field">
-		<xs:choice>
-			<xs:element name="boolean" type="field-base" />
-			<xs:element name="i18n" type="field-base" />
-			<xs:element name="integer" type="field-integer" />
-			<xs:element name="real" type="field-real" />
-			<xs:element name="text" type="field-text" />
-			<xs:element name="entity" type="field-entity" />
-		</xs:choice>
-	</xs:group>
-
-	<!-- Common parts for all field definitions -->
-	<xs:complexType name="field-base">
-		<xs:attribute name="id" use="required" type="xs:token" />
-		<xs:attribute name="required" use="optional" type="xs:boolean"
-			default="true" />
-	</xs:complexType>
-
-	<!-- Integer field definition -->
-	<xs:complexType name="field-integer">
-		<xs:complexContent>
-			<xs:extension base="field-base">
-				<xs:attribute name="min" use="optional" type="xs:integer" />
-				<xs:attribute name="max" use="optional" type="xs:integer" />
-			</xs:extension>
-		</xs:complexContent>
-	</xs:complexType>
-
-	<!-- Real field definition -->
-	<xs:complexType name="field-real">
-		<xs:complexContent>
-			<xs:extension base="field-base">
-				<xs:attribute name="min" use="optional" type="xs:double" />
-				<xs:attribute name="max" use="optional" type="xs:double" />
-			</xs:extension>
-		</xs:complexContent>
-	</xs:complexType>
-
-	<!-- Text field definition -->
-	<xs:complexType name="field-text">
-		<xs:complexContent>
-			<xs:extension base="field-base">
-				<xs:attribute name="min-length" use="optional" type="xs:integer" />
-				<xs:attribute name="max-length" use="optional" type="xs:integer" />
-			</xs:extension>
-		</xs:complexContent>
-	</xs:complexType>
-
-	<!-- Entity field definition -->
-	<xs:complexType name="field-entity">
-		<xs:complexContent>
-			<xs:extension base="field-base">
-				<xs:attribute name="entity-type" use="required" type="entity-types" />
-			</xs:extension>
-		</xs:complexContent>
-	</xs:complexType>
-
-	<!-- Supported entity types -->
-	<xs:simpleType name="entity-types">
-		<xs:restriction base="xs:string">
-			<xs:enumeration value="EMP" />
-			<xs:enumeration value="PLN" />
-			<xs:enumeration value="FLT" />
-			<xs:enumeration value="ALL" />
-			<xs:enumeration value="BAT" />
-			<xs:enumeration value="ADM" />
-			<xs:enumeration value="BUG" />
-		</xs:restriction>
-	</xs:simpleType>
-
-</xs:schema>
\ No newline at end of file
diff --git a/legacyworlds-server-main/data/resources.xml b/legacyworlds-server-main/data/resources.xml
deleted file mode 100644
index 6f4646e..0000000
--- a/legacyworlds-server-main/data/resources.xml
+++ /dev/null
@@ -1,44 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<lw-resources xmlns="http://www.deepclone.com/lw/b6/m2/resources"
-	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	xsi:schemaLocation="http://www.deepclone.com/lw/b6/m2/resources resources.xsd">
-
-	<basic-resource name="rnMoney" description="rdMoney"
-		weight="1" />
-
-	<natural-resource name="rnTitanium" description="rdTitanium"
-		category="rcMinerals" weight="1" presence-probability="0.5">
-		<quantity average="50000" deviation="5000" />
-		<difficulty average="0.1" deviation="0.05" />
-		<recovery average="0.2" deviation="0.05" />
-	</natural-resource>
-
-	<natural-resource name="rnCopper" description="rdCopper"
-			category="rcMinerals" weight="2" presence-probability="0.6">
-		<quantity average="75000" deviation="7500" />
-		<difficulty average="0.15" deviation="0.075" />
-		<recovery average="0.2" deviation="0.05" />
-	</natural-resource>
-
-	<natural-resource name="rnStrentium" description="rdStrentium"
-			category="rcMinerals" weight="3" presence-probability="0.3">
-		<quantity average="30000" deviation="5000" />
-		<difficulty average="0.4" deviation="0.1" />
-		<recovery average="0.15" deviation="0.05" />
-	</natural-resource>
-
-	<natural-resource name="rnDororhium" description="rdDororhium"
-			category="rcMinerals" weight="4" presence-probability="0.1">
-		<quantity average="15000" deviation="2500" />
-		<difficulty average="0.7" deviation="0.15" />
-		<recovery average="0.15" deviation="0.05" />
-	</natural-resource>
-
-	<natural-resource name="rnNothentium" description="rdNothentium"
-			category="rcMinerals" weight="5" presence-probability="0.05">
-		<quantity average="10000" deviation="2500" />
-		<difficulty average="0.85" deviation="0.15" />
-		<recovery average="0.1" deviation="0.05" />
-	</natural-resource>
-
-</lw-resources>
\ No newline at end of file
diff --git a/legacyworlds-server-main/data/resources.xsd b/legacyworlds-server-main/data/resources.xsd
deleted file mode 100644
index a0a46f2..0000000
--- a/legacyworlds-server-main/data/resources.xsd
+++ /dev/null
@@ -1,44 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<xs:schema xmlns="http://www.deepclone.com/lw/b6/m2/resources"
-	targetNamespace="http://www.deepclone.com/lw/b6/m2/resources"
-xmlns:xs="http://www.w3.org/2001/XMLSchema"
-	elementFormDefault="qualified" attributeFormDefault="unqualified">
-
-	<xs:element name="lw-resources">
-		<xs:complexType>
-			<xs:sequence>
-				<xs:element name="basic-resource" type="basic-resource"
-					minOccurs="0" maxOccurs="unbounded" />
-				<xs:element name="natural-resource" type="natural-resource"
-					minOccurs="0" maxOccurs="unbounded" />
-			</xs:sequence>
-		</xs:complexType>
-	</xs:element>
-
-	<xs:complexType name="basic-resource">
-		<xs:attribute name="name" use="required" type="xs:token" />
-		<xs:attribute name="description" use="required" type="xs:token" />
-		<xs:attribute name="category" use="optional" type="xs:token" />
-		<xs:attribute name="weight" use="required" type="xs:integer" />
-	</xs:complexType>
-
-	<xs:complexType name="natural-resource">
-		<xs:complexContent>
-			<xs:extension base="basic-resource">
-				<xs:sequence>
-					<xs:element name="quantity" type="resource-parameter" />
-					<xs:element name="difficulty" type="resource-parameter" />
-					<xs:element name="recovery" type="resource-parameter" />
-				</xs:sequence>
-				<xs:attribute name="presence-probability" use="required"
-					type="xs:decimal" />
-			</xs:extension>
-		</xs:complexContent>
-	</xs:complexType>
-
-	<xs:complexType name="resource-parameter">
-		<xs:attribute name="average" use="required" type="xs:decimal" />
-		<xs:attribute name="deviation" use="required" type="xs:decimal" />
-	</xs:complexType>
-
-</xs:schema>
\ No newline at end of file
diff --git a/legacyworlds-server-main/data/tech-graph.xml b/legacyworlds-server-main/data/tech-graph.xml
deleted file mode 100644
index 4f54016..0000000
--- a/legacyworlds-server-main/data/tech-graph.xml
+++ /dev/null
@@ -1,42 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<lw-tech-graph xmlns="http://www.deepclone.com/lw/b6/m2/tech-graph"
-	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	xsi:schemaLocation="http://www.deepclone.com/lw/b6/m2/tech-graph tech-graph.xsd">
-
-	<!-- Military technologies (cruisers, battle cruisers, dreadnoughts) -->
-
-	<technology name="cruisersTech" category="milTech"
-		description="cruisersTechDescription" discovery="cruisersTechDescription"
-		points="25000" cost="10000" />
-
-	<technology name="bCruisersTech" category="milTech"
-		description="bCruisersTechDescription" discovery="bCruisersTechDescription"
-		points="900000" cost="400000">
-		<depends-on>cruisersTech</depends-on>
-	</technology>
-
-	<technology name="dreadnoughtsTech" category="milTech"
-		description="dreadnoughtsTechDescription" discovery="dreadnoughtsTechDescription"
-		points="2250000" cost="1012500">
-		<depends-on>bCruisersTech</depends-on>
-	</technology>
-
-	<!-- Civilian technologies (industrial factories, corpse re-animation, bio-turrets -->
-
-	<technology name="indFactTech" category="civTech"
-		description="indFactTechDescription" discovery="indFactTechDescription"
-		points="10000" cost="5000" />
-
-	<technology name="reanimationTech" category="civTech"
-		description="reanimationTechDescription" discovery="reanimationTechDescription"
-		points="562500" cost="281250">
-		<depends-on>indFactTech</depends-on>
-	</technology>
-
-	<technology name="superTurretTech" category="civTech"
-		description="superTurretTechDescription" discovery="superTurretTechDescription"
-		points="1350000" cost="607500">
-		<depends-on>reanimationTech</depends-on>
-	</technology>
-
-</lw-tech-graph>
\ No newline at end of file
diff --git a/legacyworlds-server-main/data/tech-graph.xsd b/legacyworlds-server-main/data/tech-graph.xsd
deleted file mode 100644
index 4c3b555..0000000
--- a/legacyworlds-server-main/data/tech-graph.xsd
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<xs:schema xmlns="http://www.deepclone.com/lw/b6/m2/tech-graph"
-	targetNamespace="http://www.deepclone.com/lw/b6/m2/tech-graph"
-	xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified"
-	attributeFormDefault="unqualified">
-
-	<xs:element name="lw-tech-graph">
-		<xs:complexType>
-			<xs:sequence>
-				<xs:element name="technology" type="technology-description"
-					minOccurs="1" maxOccurs="unbounded">
-				</xs:element>
-			</xs:sequence>
-		</xs:complexType>
-	</xs:element>
-
-	<xs:simpleType name="positive-long">
-		<xs:restriction base="xs:long">
-			<xs:minExclusive value="0"></xs:minExclusive>
-		</xs:restriction>
-	</xs:simpleType>
-
-	<xs:complexType name="technology-description">
-		<xs:sequence>
-			<xs:element name="depends-on" type="xs:token" minOccurs="0"
-				maxOccurs="unbounded" />
-		</xs:sequence>
-		<xs:attribute name="name" use="required" type="xs:token" />
-		<xs:attribute name="category" use="required" type="xs:token" />
-		<xs:attribute name="description" use="required" type="xs:token" />
-		<xs:attribute name="discovery" use="required" type="xs:token" />
-		<xs:attribute name="cost" use="required" type="positive-long" />
-		<xs:attribute name="points" use="required" type="positive-long" />
-	</xs:complexType>
-</xs:schema>
\ No newline at end of file
diff --git a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/ImportEvents.java b/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/ImportEvents.java
deleted file mode 100644
index 92401fd..0000000
--- a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/ImportEvents.java
+++ /dev/null
@@ -1,715 +0,0 @@
-package com.deepclone.lw.cli;
-
-
-import java.io.File;
-import java.util.Map;
-
-import javax.sql.DataSource;
-
-import org.apache.log4j.Logger;
-import org.postgresql.util.PGobject;
-import org.springframework.context.ApplicationContext;
-import org.springframework.context.support.AbstractApplicationContext;
-import org.springframework.context.support.ClassPathXmlApplicationContext;
-import org.springframework.context.support.FileSystemXmlApplicationContext;
-import org.springframework.transaction.PlatformTransactionManager;
-import org.springframework.transaction.TransactionStatus;
-import org.springframework.transaction.support.TransactionCallback;
-import org.springframework.transaction.support.TransactionTemplate;
-
-import com.deepclone.lw.cli.xmlimport.EventDefinitionLoader;
-import com.deepclone.lw.cli.xmlimport.data.DataImportException;
-import com.deepclone.lw.cli.xmlimport.data.evdef.EntityEventField;
-import com.deepclone.lw.cli.xmlimport.data.evdef.EventDefinition;
-import com.deepclone.lw.cli.xmlimport.data.evdef.EventDefinitions;
-import com.deepclone.lw.cli.xmlimport.data.evdef.EventFieldBase;
-import com.deepclone.lw.cli.xmlimport.data.evdef.IntegerEventField;
-import com.deepclone.lw.cli.xmlimport.data.evdef.RealEventField;
-import com.deepclone.lw.cli.xmlimport.data.evdef.TextEventField;
-import com.deepclone.lw.utils.StoredProc;
-
-
-
-public class ImportEvents
-		extends CLITool
-{
-
-	/**
-	 * Error codes that may be returned by the various import stored procedures; see the
-	 * corresponding SQL code for details about each value.
-	 */
-	private static enum SPErrorCode {
-		OK ,
-		BAD_ID ,
-		BAD_STRINGS ,
-		DUPLICATE ,
-		BAD_SPEC ,
-		NO_DATA
-	};
-
-	/** Logging system */
-	private final Logger logger = Logger.getLogger( ImportResources.class );
-
-	/** File to read the definitions from */
-	private File file;
-
-	/** Spring transaction template */
-	private TransactionTemplate tTemplate;
-
-	/** Error counter */
-	private int errors = 0;
-
-	/** Skipped definitions counter */
-	private int skipped = 0;
-
-	/** Successful imports counter */
-	private int successful = 0;
-
-	/** Stored procedure that starts recording an event definition */
-	private StoredProc fEvdefStart;
-
-	/** Stored procedure that finalises an event definition's recording */
-	private StoredProc fEvdefFinalise;
-
-	/** Stored procedure that defines a boolean field */
-	private StoredProc fEvdefAddfldBool;
-
-	/** Stored procedure that defines an I18N reference field */
-	private StoredProc fEvdefAddfldI18N;
-
-	/** Stored procedure that defines an entity reference field */
-	private StoredProc fEvdefAddfldEntity;
-
-	/** Unbounded integer field definition procedure */
-	private StoredProc fEvdefAddfldInt;
-
-	/** Stored procedure that defines an integer field with a lower bound */
-	private StoredProc fEvdefAddfldIntMin;
-
-	/** Stored procedure that defines an integer field with a higher bound */
-	private StoredProc fEvdefAddfldIntMax;
-
-	/** Stored procedure that defines a bounded integer field */
-	private StoredProc fEvdefAddfldIntRange;
-
-	/** Unbounded double precision field definition procedure */
-	private StoredProc fEvdefAddfldReal;
-
-	/** Stored procedure that defines a double precision field with a lower bound */
-	private StoredProc fEvdefAddfldRealMin;
-
-	/** Stored procedure that defines a double precision field with a higher bound */
-	private StoredProc fEvdefAddfldRealMax;
-
-	/** Stored procedure that defines a bounded double precision field */
-	private StoredProc fEvdefAddfldRealRange;
-
-	/** Unbounded text field definition procedure */
-	private StoredProc fEvdefAddfldText;
-
-	/** Stored procedure that defines a text field with a minimum length */
-	private StoredProc fEvdefAddfldTextMin;
-
-	/** Stored procedure that defines a text field with a maximal length */
-	private StoredProc fEvdefAddfldTextMax;
-
-	/** Stored procedure that defines a bounded text field */
-	private StoredProc fEvdefAddfldTextRange;
-
-
-	/**
-	 * Obtain the name of the definitions file
-	 * 
-	 * <p>
-	 * Check the command line options, setting the definitions file accordingly.
-	 */
-	@Override
-	public boolean setOptions( String... options )
-	{
-		if ( options.length != 1 ) {
-			return false;
-		}
-		this.file = new File( options[ 0 ] );
-		if ( ! ( this.file.isFile( ) && this.file.canRead( ) ) ) {
-			return false;
-		}
-		return true;
-	}
-
-
-	/**
-	 * Run the event definitions import tool
-	 * 
-	 * <p>
-	 * Loads the data file, then connects to the database and creates all missing definitions.
-	 */
-	@Override
-	public void run( )
-	{
-		EventDefinitions data;
-		try {
-			data = new EventDefinitionLoader( this.file ).load( );
-		} catch ( DataImportException e ) {
-			this.logger.error( "Error while loading event definitions" , e );
-			return;
-		}
-
-		AbstractApplicationContext ctx = this.createContext( );
-		this.createTemplates( ctx );
-		this.executeImportTransaction( data );
-		ToolBase.destroyContext( ctx );
-	}
-
-
-	/**
-	 * Create the Spring context
-	 * 
-	 * <p>
-	 * Load the definition of the data source as a Spring context, then adds the transaction
-	 * management component.
-	 * 
-	 * @return the Spring application context
-	 */
-	private ClassPathXmlApplicationContext createContext( )
-	{
-		FileSystemXmlApplicationContext ctx = new FileSystemXmlApplicationContext( new String[] {
-			this.getDataSource( )
-		} );
-		ctx.refresh( );
-
-		return new ClassPathXmlApplicationContext( new String[] {
-			"configuration/transactions.xml"
-		} , true , ctx );
-	}
-
-
-	/**
-	 * Create database access templates
-	 * 
-	 * <p>
-	 * Initialise the transaction template and the four stored procedure definitions.
-	 * 
-	 * @param ctx
-	 *            the Spring application context
-	 */
-	private void createTemplates( ApplicationContext ctx )
-	{
-		DataSource dSource = ctx.getBean( DataSource.class );
-		PlatformTransactionManager tManager = ctx.getBean( PlatformTransactionManager.class );
-
-		this.fEvdefStart = new StoredProc( dSource , "events" , "evdef_start" )
-				.addParameter( "_id" , java.sql.Types.VARCHAR ).addParameter( "_prio" , java.sql.Types.INTEGER )
-				.addParameter( "_adj" , java.sql.Types.BOOLEAN ).addParameter( "_i18n" , java.sql.Types.VARCHAR )
-				.addOutput( "_error" , java.sql.Types.OTHER );
-
-		this.fEvdefFinalise = new StoredProc( dSource , "events" , "evdef_finalise" ).addOutput( "_error" ,
-				java.sql.Types.OTHER ).addOutput( "_fld" , java.sql.Types.VARCHAR );
-
-		this.fEvdefAddfldBool = new StoredProc( dSource , "events" , "evdef_addfld_bool" )
-				.addParameter( "_id" , java.sql.Types.VARCHAR ).addParameter( "_optional" , java.sql.Types.BOOLEAN )
-				.addOutput( "_error" , java.sql.Types.OTHER );
-
-		this.fEvdefAddfldI18N = new StoredProc( dSource , "events" , "evdef_addfld_i18n" )
-				.addParameter( "_id" , java.sql.Types.VARCHAR ).addParameter( "_optional" , java.sql.Types.BOOLEAN )
-				.addOutput( "_error" , java.sql.Types.OTHER );
-
-		this.fEvdefAddfldEntity = new StoredProc( dSource , "events" , "evdef_addfld_entity" )
-				.addParameter( "_id" , java.sql.Types.VARCHAR ).addParameter( "_optional" , java.sql.Types.BOOLEAN )
-				.addParameter( "_etype" , "events.entity_field_type" ).addOutput( "_error" , java.sql.Types.OTHER );
-
-		this.fEvdefAddfldInt = new StoredProc( dSource , "events" , "evdef_addfld_int" )
-				.addParameter( "_id" , java.sql.Types.VARCHAR ).addParameter( "_optional" , java.sql.Types.BOOLEAN )
-				.addOutput( "_error" , java.sql.Types.OTHER );
-		this.fEvdefAddfldIntMin = new StoredProc( dSource , "events" , "evdef_addfld_int_min" )
-				.addParameter( "_id" , java.sql.Types.VARCHAR ).addParameter( "_optional" , java.sql.Types.BOOLEAN )
-				.addParameter( "_min" , java.sql.Types.INTEGER ).addOutput( "_error" , java.sql.Types.OTHER );
-		this.fEvdefAddfldIntMax = new StoredProc( dSource , "events" , "evdef_addfld_int_max" )
-				.addParameter( "_id" , java.sql.Types.VARCHAR ).addParameter( "_optional" , java.sql.Types.BOOLEAN )
-				.addParameter( "_max" , java.sql.Types.INTEGER ).addOutput( "_error" , java.sql.Types.OTHER );
-		this.fEvdefAddfldIntRange = new StoredProc( dSource , "events" , "evdef_addfld_int_range" )
-				.addParameter( "_id" , java.sql.Types.VARCHAR ).addParameter( "_optional" , java.sql.Types.BOOLEAN )
-				.addParameter( "_min" , java.sql.Types.INTEGER ).addParameter( "_max" , java.sql.Types.INTEGER )
-				.addOutput( "_error" , java.sql.Types.OTHER );
-
-		this.fEvdefAddfldReal = new StoredProc( dSource , "events" , "evdef_addfld_real" )
-				.addParameter( "_id" , java.sql.Types.VARCHAR ).addParameter( "_optional" , java.sql.Types.BOOLEAN )
-				.addOutput( "_error" , java.sql.Types.OTHER );
-		this.fEvdefAddfldRealMin = new StoredProc( dSource , "events" , "evdef_addfld_real_min" )
-				.addParameter( "_id" , java.sql.Types.VARCHAR ).addParameter( "_optional" , java.sql.Types.BOOLEAN )
-				.addParameter( "_min" , java.sql.Types.DOUBLE ).addOutput( "_error" , java.sql.Types.OTHER );
-		this.fEvdefAddfldRealMax = new StoredProc( dSource , "events" , "evdef_addfld_real_max" )
-				.addParameter( "_id" , java.sql.Types.VARCHAR ).addParameter( "_optional" , java.sql.Types.BOOLEAN )
-				.addParameter( "_max" , java.sql.Types.DOUBLE ).addOutput( "_error" , java.sql.Types.OTHER );
-		this.fEvdefAddfldRealRange = new StoredProc( dSource , "events" , "evdef_addfld_real_range" )
-				.addParameter( "_id" , java.sql.Types.VARCHAR ).addParameter( "_optional" , java.sql.Types.BOOLEAN )
-				.addParameter( "_min" , java.sql.Types.DOUBLE ).addParameter( "_max" , java.sql.Types.DOUBLE )
-				.addOutput( "_error" , java.sql.Types.OTHER );
-
-		this.fEvdefAddfldText = new StoredProc( dSource , "events" , "evdef_addfld_text" )
-				.addParameter( "_id" , java.sql.Types.VARCHAR ).addParameter( "_optional" , java.sql.Types.BOOLEAN )
-				.addOutput( "_error" , java.sql.Types.OTHER );
-		this.fEvdefAddfldTextMin = new StoredProc( dSource , "events" , "evdef_addfld_text_min" )
-				.addParameter( "_id" , java.sql.Types.VARCHAR ).addParameter( "_optional" , java.sql.Types.BOOLEAN )
-				.addParameter( "_min" , java.sql.Types.INTEGER ).addOutput( "_error" , java.sql.Types.OTHER );
-		this.fEvdefAddfldTextMax = new StoredProc( dSource , "events" , "evdef_addfld_text_max" )
-				.addParameter( "_id" , java.sql.Types.VARCHAR ).addParameter( "_optional" , java.sql.Types.BOOLEAN )
-				.addParameter( "_max" , java.sql.Types.INTEGER ).addOutput( "_error" , java.sql.Types.OTHER );
-		this.fEvdefAddfldTextRange = new StoredProc( dSource , "events" , "evdef_addfld_text_range" )
-				.addParameter( "_id" , java.sql.Types.VARCHAR ).addParameter( "_optional" , java.sql.Types.BOOLEAN )
-				.addParameter( "_min" , java.sql.Types.INTEGER ).addParameter( "_max" , java.sql.Types.INTEGER )
-				.addOutput( "_error" , java.sql.Types.OTHER );
-
-		this.tTemplate = new TransactionTemplate( tManager );
-	}
-
-
-	/**
-	 * Execute the event definitions importation transaction
-	 * 
-	 * <p>
-	 * Run a transaction and execute the importation code inside it. Roll back if anything goes
-	 * wrong.
-	 * 
-	 * @param data
-	 *            the event definitions top-level instance
-	 */
-	private void executeImportTransaction( final EventDefinitions data )
-	{
-		boolean rv = this.tTemplate.execute( new TransactionCallback< Boolean >( ) {
-			@Override
-			public Boolean doInTransaction( TransactionStatus status )
-			{
-				boolean rv = ImportEvents.this.doTransaction( data );
-				if ( !rv ) {
-					status.setRollbackOnly( );
-				}
-				return rv;
-			}
-		} );
-
-		if ( rv ) {
-			this.logger.info( "Import complete; " + this.successful + " new type(s), " + this.skipped + " skipped" );
-		} else {
-			this.logger.error( this.errors + " error(s) occurred, no changes were made" );
-		}
-	}
-
-
-	/**
-	 * Import transaction body
-	 * 
-	 * <p>
-	 * Import all definitions and handle exceptions.
-	 * 
-	 * @param data
-	 *            the event definitions top-level instance
-	 * @return <code>true</code> on success, <code>false</code> otherwise
-	 */
-	private boolean doTransaction( EventDefinitions data )
-	{
-		try {
-			this.importDefinitions( data );
-			return this.errors == 0;
-		} catch ( RuntimeException e ) {
-			this.logger.error( "Caught runtime exception" , e );
-			this.errors ++;
-		}
-		return false;
-	}
-
-
-	/**
-	 * Extract the error code from a stored procedure's return value
-	 * 
-	 * <p>
-	 * This method is used to extract the error code from the maps returned by a definition stored
-	 * procedure's execution.
-	 * 
-	 * @param result
-	 *            the map returned by the stored procedure's execution
-	 * 
-	 * @return the error code
-	 */
-	private SPErrorCode getSPResult( Map< String , Object > result )
-	{
-		return SPErrorCode.valueOf( ( (PGobject) result.get( "_error" ) ).getValue( ) );
-	}
-
-
-	/**
-	 * Import all event definitions from the top-level importable instance
-	 * 
-	 * <p>
-	 * This method iterates through all of the definitions, trying to import each of them.
-	 * 
-	 * @param data
-	 *            the top-level importable instance
-	 */
-	private void importDefinitions( EventDefinitions data )
-	{
-		for ( EventDefinition evdef : data ) {
-			this.importDefinition( evdef );
-		}
-	}
-
-
-	/**
-	 * Try to import an event definition
-	 * 
-	 * <p>
-	 * This method will attempt to import an event definition. It will increase the state counters (
-	 * {@link #errors}, {@link #skipped} and {@link #successful}) depending on the results.
-	 * 
-	 * @param evdef
-	 *            the event definition to import
-	 */
-	private void importDefinition( EventDefinition evdef )
-	{
-		boolean ok;
-
-		// Start the import
-		try {
-			this.startImport( evdef );
-			ok = true;
-		} catch ( DataImportException e ) {
-			this.logger.error( e.getMessage( ) );
-			ok = false;
-		}
-
-		// Import all fields
-		if ( ok ) {
-			for ( EventFieldBase field : evdef ) {
-				ok = ok && this.importField( evdef , field );
-				if ( !ok ) {
-					break;
-				}
-			}
-		}
-
-		// Finalise the operation
-		boolean wasNew = false;
-		try {
-			wasNew = this.endImport( evdef );
-		} catch ( DataImportException e ) {
-			if ( ok ) {
-				this.logger.error( e.getMessage( ) );
-				ok = false;
-			}
-		}
-
-		// Update counters and print to log
-		if ( ok ) {
-			if ( wasNew ) {
-				this.logger.info( evdef.getIdentifier( ) + ": new event definition imported" );
-				this.successful++;
-			} else {
-				this.logger.warn( evdef.getIdentifier( ) + ": event definition exists (skipped)" );
-				this.skipped++;
-			}
-		} else {
-			this.errors++;
-		}
-	}
-
-
-	/**
-	 * Start importing an event definition
-	 * 
-	 * <p>
-	 * This method calls the <code>events.evdef_start()</code> stored procedure to initialise the
-	 * event definition registration, and handles its return value.
-	 * 
-	 * @param evdef
-	 *            the event definition instance from the XML definition
-	 * 
-	 * @throws DataImportException
-	 *             if the definition's identifier is invalid or if one of the internationalised
-	 *             strings is missing
-	 */
-	private void startImport( EventDefinition evdef )
-			throws DataImportException
-	{
-		SPErrorCode ec;
-		ec = this.getSPResult( this.fEvdefStart.execute( evdef.getIdentifier( ) , evdef.getPriority( ) ,
-				evdef.isAdjustable( ) , evdef.getI18NStrings( ) ) );
-
-		switch ( ec ) {
-			case OK:
-				break;
-
-			case BAD_ID:
-				throw new DataImportException( evdef.getIdentifier( ) + ": bad event type identifier" );
-
-			case BAD_STRINGS:
-				throw new DataImportException( evdef.getIdentifier( ) + ": I18N strings not found" );
-
-			default:
-				throw new RuntimeException( "Unsupported return value for events.evdef_start(): " + ec.toString( ) );
-		}
-	}
-
-
-	/**
-	 * Import a field definition
-	 * 
-	 * <p>
-	 * Call the appropriate field definition importation method depending on the field's type.
-	 * 
-	 * @param evdef
-	 *            the event definition
-	 * @param field
-	 *            the field definition
-	 * 
-	 * @return <code>true</code> on success, <code>false</code> if something went wrong
-	 */
-	private boolean importField( EventDefinition evdef , EventFieldBase field )
-	{
-		SPErrorCode ec;
-		switch ( field.getType( ) ) {
-			case BOOLEAN:
-				ec = this.importBooleanField( field );
-				break;
-
-			case I18N:
-				ec = this.importI18NField( field );
-				break;
-
-			case ENTITY:
-				ec = this.importEntityField( (EntityEventField) field );
-				break;
-
-			case INTEGER:
-				ec = this.importIntegerField( (IntegerEventField) field );
-				break;
-
-			case REAL:
-				ec = this.importRealField( (RealEventField) field );
-				break;
-
-			case TEXT:
-				ec = this.importTextField( (TextEventField) field );
-				break;
-
-			default:
-				throw new RuntimeException( "Unsupported field type " + field.getType( ).toString( ) );
-		}
-
-		switch ( ec ) {
-			case OK:
-				return true;
-
-			case BAD_ID:
-				this.logger.error( evdef.getIdentifier( ) + ": bad field identifier '" + field.getIdentifier( ) + "'" );
-				break;
-
-			default:
-				throw new RuntimeException( "Unsupported return value for field definition procedure: " + ec.toString( ) );
-		}
-		return false;
-	}
-
-
-	/**
-	 * Import a boolean field
-	 * 
-	 * <p>
-	 * This method calls <code>events.evdef_addfld_bool</code> to register a new boolean field.
-	 * 
-	 * @param field
-	 *            the field's definition
-	 * 
-	 * @return the stored procedure's error code
-	 */
-	private SPErrorCode importBooleanField( EventFieldBase field )
-	{
-		return this.getSPResult( this.fEvdefAddfldBool.execute( field.getIdentifier( ) , !field.isRequired( ) ) );
-	}
-
-
-	/**
-	 * Import an I18N reference field
-	 * 
-	 * <p>
-	 * This method calls <code>events.evdef_addfld_i18n</code> to register a new I18N reference
-	 * field.
-	 * 
-	 * @param field
-	 *            the field's definition
-	 * 
-	 * @return the stored procedure's error code
-	 */
-	private SPErrorCode importI18NField( EventFieldBase field )
-	{
-		return this.getSPResult( this.fEvdefAddfldI18N.execute( field.getIdentifier( ) , !field.isRequired( ) ) );
-	}
-
-
-	/**
-	 * Import an entity reference field
-	 * 
-	 * <p>
-	 * This method calls <code>events.evdef_addfld_entity</code> to register a new entity reference
-	 * field.
-	 * 
-	 * @param field
-	 *            the field's definition
-	 * 
-	 * @return the stored procedure's error code
-	 */
-	private SPErrorCode importEntityField( EntityEventField field )
-	{
-		return this.getSPResult( this.fEvdefAddfldEntity.execute( field.getIdentifier( ) , !field.isRequired( ) ,
-				field.getEntityType( ) ) );
-	}
-
-
-	/**
-	 * Import an integer field definition
-	 * 
-	 * <p>
-	 * This method calls one of the integer field definitions stored procedures, depending on the
-	 * definition's parameters.
-	 * 
-	 * @param field
-	 *            the field's definition
-	 * 
-	 * @return the stored procedure's error code
-	 */
-	private SPErrorCode importIntegerField( IntegerEventField field )
-	{
-		String id = field.getIdentifier( );
-		boolean opt = !field.isRequired( );
-		Integer min = field.getMin( );
-		Integer max = field.getMax( );
-
-		Map< String , Object > result;
-		if ( min == null && max == null ) {
-			result = this.fEvdefAddfldInt.execute( id , opt );
-		} else if ( min == null ) {
-			result = this.fEvdefAddfldIntMax.execute( id , opt , max );
-		} else if ( max == null ) {
-			result = this.fEvdefAddfldIntMin.execute( id , opt , min );
-		} else {
-			result = this.fEvdefAddfldIntRange.execute( id , opt , min , max );
-		}
-
-		return this.getSPResult( result );
-	}
-
-
-	/**
-	 * Import a double precision field definition
-	 * 
-	 * <p>
-	 * This method calls one of the double precision field definitions stored procedures, depending
-	 * on the definition's parameters.
-	 * 
-	 * @param field
-	 *            the field's definition
-	 * 
-	 * @return the stored procedure's error code
-	 */
-	private SPErrorCode importRealField( RealEventField field )
-	{
-		String id = field.getIdentifier( );
-		boolean opt = !field.isRequired( );
-		Double min = field.getMin( );
-		Double max = field.getMax( );
-
-		Map< String , Object > result;
-		if ( min == null && max == null ) {
-			result = this.fEvdefAddfldReal.execute( id , opt );
-		} else if ( min == null ) {
-			result = this.fEvdefAddfldRealMax.execute( id , opt , max );
-		} else if ( max == null ) {
-			result = this.fEvdefAddfldRealMin.execute( id , opt , min );
-		} else {
-			result = this.fEvdefAddfldRealRange.execute( id , opt , min , max );
-		}
-
-		return this.getSPResult( result );
-	}
-
-
-	/**
-	 * Import a text field definition
-	 * 
-	 * <p>
-	 * This method calls one of the text field definitions stored procedures, depending on the
-	 * definition's parameters.
-	 * 
-	 * @param field
-	 *            the field's definition
-	 * 
-	 * @return the stored procedure's error code
-	 */
-	private SPErrorCode importTextField( TextEventField field )
-	{
-		String id = field.getIdentifier( );
-		boolean opt = !field.isRequired( );
-		Integer min = field.getMinLength( );
-		Integer max = field.getMaxLength( );
-
-		Map< String , Object > result;
-		if ( min == null && max == null ) {
-			result = this.fEvdefAddfldText.execute( id , opt );
-		} else if ( min == null ) {
-			result = this.fEvdefAddfldTextMax.execute( id , opt , max );
-		} else if ( max == null ) {
-			result = this.fEvdefAddfldTextMin.execute( id , opt , min );
-		} else {
-			result = this.fEvdefAddfldTextRange.execute( id , opt , min , max );
-		}
-
-		return this.getSPResult( result );
-	}
-
-
-	/**
-	 * Finalise the current event definition
-	 * 
-	 * <p>
-	 * This method calls the <code>events.evdef_finalise()</code> stored procedure, and handles its
-	 * return values.
-	 * 
-	 * @param evdef
-	 *            the event definition from the XML file
-	 * 
-	 * @return <code>true</code> if the definition was finalised or if it had no effect (except for
-	 *         cleanup) due to a previous error, <code>false</code> if the definition already
-	 *         existed and was skipped.
-	 * 
-	 * @throws DataImportException
-	 *             if the event's specification is invalid, if a field name is duplicated, or if a
-	 *             field's specification is invalid.
-	 */
-	private boolean endImport( EventDefinition evdef )
-			throws DataImportException
-	{
-		Map< String , Object > result = this.fEvdefFinalise.execute( );
-		SPErrorCode ec = this.getSPResult( result );
-		String field = (String) result.get( "_fld" );
-
-		switch ( ec ) {
-			case OK:
-			case NO_DATA:
-				return true;
-
-			case BAD_SPEC:
-				if ( field == null ) {
-					throw new DataImportException( evdef.getIdentifier( ) + ": bad event type specification" );
-				}
-				throw new DataImportException( evdef.getIdentifier( ) + ": bad field specification (" + field + ")" );
-
-			case DUPLICATE:
-				if ( field == null ) {
-					return false;
-				}
-				throw new DataImportException( evdef.getIdentifier( ) + ": duplicate field name " + field );
-
-			default:
-				throw new RuntimeException( "Unsupported return value for events.evdef_finalise(): " + ec.toString( ) );
-		}
-	}
-
-}
diff --git a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/ImportResources.java b/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/ImportResources.java
deleted file mode 100644
index ab2bb0a..0000000
--- a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/ImportResources.java
+++ /dev/null
@@ -1,372 +0,0 @@
-package com.deepclone.lw.cli;
-
-
-import java.io.File;
-
-import javax.sql.DataSource;
-
-import org.apache.log4j.Logger;
-import org.postgresql.util.PGobject;
-import org.springframework.context.ApplicationContext;
-import org.springframework.context.support.AbstractApplicationContext;
-import org.springframework.context.support.ClassPathXmlApplicationContext;
-import org.springframework.context.support.FileSystemXmlApplicationContext;
-import org.springframework.transaction.PlatformTransactionManager;
-import org.springframework.transaction.TransactionStatus;
-import org.springframework.transaction.support.TransactionCallback;
-import org.springframework.transaction.support.TransactionTemplate;
-
-import com.deepclone.lw.cli.xmlimport.ResourceLoader;
-import com.deepclone.lw.cli.xmlimport.data.DataImportException;
-import com.deepclone.lw.cli.xmlimport.data.resources.BasicResource;
-import com.deepclone.lw.cli.xmlimport.data.resources.NaturalResource;
-import com.deepclone.lw.cli.xmlimport.data.resources.Resources;
-import com.deepclone.lw.cli.xmlimport.data.resources.UOCResourceErrorCode;
-import com.deepclone.lw.utils.StoredProc;
-
-
-
-/**
- * Resources import tool
- * 
- * <p>
- * This class defines the body of the resource import tool. It loads the data file specified on the
- * command line, validates it and then loads the resource definitions into the database.
- * 
- * @author <a href="mailto:tim@mitheren.com">T. Rosser</a>
- */
-public class ImportResources
-		extends CLITool
-{
-	/** Logging system */
-	private final Logger logger = Logger.getLogger( ImportResources.class );
-
-	/** File to read the definitions from */
-	private File file;
-
-	/** Spring transaction template */
-	private TransactionTemplate tTemplate;
-
-	/** Basic resource with category update or create stored procedure */
-	private StoredProc uocBasicResourceWithCategory;
-
-	/** Basic resource without category update or create stored procedure */
-	private StoredProc uocBasicResourceWithoutCategory;
-
-	/** Natural resource with category update or create stored procedure */
-	private StoredProc uocNaturalResourceWithCategory;
-
-	/** Natural resource without category update or create stored procedure */
-	private StoredProc uocNaturalResourceWithoutCategory;
-
-
-	/**
-	 * Create the Spring context
-	 * 
-	 * <p>
-	 * Load the definition of the data source as a Spring context, then adds the transaction
-	 * management component.
-	 * 
-	 * @return the Spring application context
-	 */
-	private ClassPathXmlApplicationContext createContext( )
-	{
-		FileSystemXmlApplicationContext ctx = new FileSystemXmlApplicationContext( new String[] {
-			this.getDataSource( )
-		} );
-		ctx.refresh( );
-
-		return new ClassPathXmlApplicationContext( new String[] {
-			"configuration/transactions.xml"
-		} , true , ctx );
-	}
-
-
-	/**
-	 * Create database access templates
-	 * 
-	 * <p>
-	 * Initialise the transaction template and the four stored procedure definitions.
-	 * 
-	 * @param ctx
-	 *            the Spring application context
-	 */
-	private void createTemplates( ApplicationContext ctx )
-	{
-		DataSource dSource = ctx.getBean( DataSource.class );
-		PlatformTransactionManager tManager = ctx.getBean( PlatformTransactionManager.class );
-
-		this.uocBasicResourceWithoutCategory = new StoredProc( dSource , "defs" , "uoc_resource" )
-				.addParameter( "_name" , java.sql.Types.VARCHAR )
-				.addParameter( "_description" , java.sql.Types.VARCHAR )
-				.addParameter( "_weight" , java.sql.Types.INTEGER ).addOutput( "_return" , java.sql.Types.OTHER );
-
-		this.uocBasicResourceWithCategory = new StoredProc( dSource , "defs" , "uoc_resource" )
-				.addParameter( "_name" , java.sql.Types.VARCHAR )
-				.addParameter( "_description" , java.sql.Types.VARCHAR )
-				.addParameter( "_category" , java.sql.Types.VARCHAR ).addParameter( "_weight" , java.sql.Types.INTEGER )
-				.addOutput( "_return" , java.sql.Types.OTHER );
-
-		this.uocNaturalResourceWithoutCategory = new StoredProc( dSource , "defs" , "uoc_natural_resource" )
-				.addParameter( "_name" , java.sql.Types.VARCHAR )
-				.addParameter( "_description" , java.sql.Types.VARCHAR )
-				.addParameter( "_weight" , java.sql.Types.INTEGER ).addParameter( "_presence" , java.sql.Types.DOUBLE )
-				.addParameter( "_quantity_avg" , java.sql.Types.DOUBLE )
-				.addParameter( "_quantity_dev" , java.sql.Types.DOUBLE )
-				.addParameter( "_difficulty_avg" , java.sql.Types.DOUBLE )
-				.addParameter( "_difficulty_dev" , java.sql.Types.DOUBLE )
-				.addParameter( "_recovery_avg" , java.sql.Types.DOUBLE )
-				.addParameter( "_recovery_dev" , java.sql.Types.DOUBLE ).addOutput( "_return" , java.sql.Types.OTHER );
-
-		this.uocNaturalResourceWithCategory = new StoredProc( dSource , "defs" , "uoc_natural_resource" )
-				.addParameter( "_name" , java.sql.Types.VARCHAR )
-				.addParameter( "_description" , java.sql.Types.VARCHAR )
-				.addParameter( "_category" , java.sql.Types.VARCHAR ).addParameter( "_weight" , java.sql.Types.INTEGER )
-				.addParameter( "_presence" , java.sql.Types.DOUBLE )
-				.addParameter( "_quantity_avg" , java.sql.Types.DOUBLE )
-				.addParameter( "_quantity_dev" , java.sql.Types.DOUBLE )
-				.addParameter( "_difficulty_avg" , java.sql.Types.DOUBLE )
-				.addParameter( "_difficulty_dev" , java.sql.Types.DOUBLE )
-				.addParameter( "_recovery_avg" , java.sql.Types.DOUBLE )
-				.addParameter( "_recovery_dev" , java.sql.Types.DOUBLE ).addOutput( "_return" , java.sql.Types.OTHER );
-
-		this.tTemplate = new TransactionTemplate( tManager );
-	}
-
-
-	/**
-	 * Import all resource definitions
-	 * 
-	 * <p>
-	 * Import all resource definitions from the top-level Resources data instance based on the type
-	 * of resource, and whether or not it has a category.
-	 * 
-	 * @param data
-	 *            the top level Resources data instance
-	 * 
-	 * @throws DataImportException
-	 *             when some external resource definition fails to load
-	 */
-	private void importResources( Resources data )
-			throws DataImportException
-	{
-		for ( BasicResource br : data ) {
-			if ( br instanceof NaturalResource ) {
-				if ( br.getCategory( ) == null ) {
-					this.importNaturalResourceWithoutCategory( (NaturalResource) br );
-				} else {
-					this.importNaturalResourceWithCategory( (NaturalResource) br );
-				}
-			} else {
-				if ( br.getCategory( ) == null ) {
-					this.importBasicResourceWithoutCategory( br );
-				} else {
-					this.importBasicResourceWithCategory( br );
-				}
-			}
-		}
-	}
-
-
-	/**
-	 * Import a Natural Resource
-	 * 
-	 * <p>
-	 * Import a natural resource that does not have a defined category.
-	 * 
-	 * @param nr
-	 *            the resources definition data
-	 * 
-	 * @throws DataImportException
-	 *             when some external resource definition fails to load
-	 */
-	private void importNaturalResourceWithoutCategory( NaturalResource nr )
-			throws DataImportException
-	{
-		UOCResourceErrorCode err = UOCResourceErrorCode.valueOf( ( (PGobject) this.uocNaturalResourceWithoutCategory
-				.execute( nr.getName( ) , nr.getDescription( ) , nr.getWeight( ) , nr.getPresenceProbability( ) ,
-						nr.getQuantity( ).getAverage( ) , nr.getQuantity( ).getDeviation( ) ,
-						nr.getDifficulty( ).getAverage( ) , nr.getDifficulty( ).getDeviation( ) ,
-						nr.getRecovery( ).getAverage( ) , nr.getRecovery( ).getDeviation( ) ).get( "_return" ) )
-				.getValue( ) );
-
-		if ( !err.equals( UOCResourceErrorCode.CREATED ) && !err.equals( UOCResourceErrorCode.UPDATED ) ) {
-			throw new DataImportException( "uocNaturalResourceWithoutCategory returned error code " + err.toString( ) );
-		}
-	}
-
-
-	/**
-	 * Import a Natural Resource
-	 * 
-	 * <p>
-	 * Import a natural resource that does have a defined category.
-	 * 
-	 * @param nr
-	 *            the resources definition data
-	 * 
-	 * @throws DataImportException
-	 *             when some external resource definition fails to load
-	 */
-	private void importNaturalResourceWithCategory( NaturalResource nr )
-			throws DataImportException
-	{
-		UOCResourceErrorCode err = UOCResourceErrorCode.valueOf( ( (PGobject) this.uocNaturalResourceWithCategory
-				.execute( nr.getName( ) , nr.getDescription( ) , nr.getCategory( ) , nr.getWeight( ) ,
-						nr.getPresenceProbability( ) , nr.getQuantity( ).getAverage( ) ,
-						nr.getQuantity( ).getDeviation( ) , nr.getDifficulty( ).getAverage( ) ,
-						nr.getDifficulty( ).getDeviation( ) , nr.getRecovery( ).getAverage( ) ,
-						nr.getRecovery( ).getDeviation( ) ).get( "_return" ) ).getValue( ) );
-
-		if ( !err.equals( UOCResourceErrorCode.CREATED ) && !err.equals( UOCResourceErrorCode.UPDATED ) ) {
-			throw new DataImportException( "uocNaturalResourceWithCategory returned error code " + err.toString( ) );
-		}
-	}
-
-
-	/**
-	 * Import a Basic Resource
-	 * 
-	 * <p>
-	 * Import a basic resource that does not have a defined category.
-	 * 
-	 * @param br
-	 *            the resources definition data
-	 * 
-	 * @throws DataImportException
-	 *             when some external resource definition fails to load
-	 */
-	private void importBasicResourceWithoutCategory( BasicResource br )
-			throws DataImportException
-	{
-		UOCResourceErrorCode err = UOCResourceErrorCode.valueOf( ( (PGobject) this.uocBasicResourceWithoutCategory
-				.execute( br.getName( ) , br.getDescription( ) , br.getWeight( ) ).get( "_return" ) ).getValue( ) );
-
-		if ( !err.equals( UOCResourceErrorCode.CREATED ) && !err.equals( UOCResourceErrorCode.UPDATED ) ) {
-			throw new DataImportException( "uocBasicResourceWithoutCategory returned error code " + err.toString( ) );
-		}
-	}
-
-
-	/**
-	 * Import a Basic Resource
-	 * 
-	 * <p>
-	 * Import a basic resource that does not have a defined category.
-	 * 
-	 * @param br
-	 *            the resources definition data
-	 * 
-	 * @throws DataImportException
-	 *             when some external resource definition fails to load
-	 */
-	private void importBasicResourceWithCategory( BasicResource br )
-			throws DataImportException
-	{
-		UOCResourceErrorCode err = UOCResourceErrorCode
-				.valueOf( ( (PGobject) this.uocBasicResourceWithCategory.execute( br.getName( ) , br.getDescription( ) ,
-						br.getCategory( ) , br.getWeight( ) ).get( "_return" ) ).getValue( ) );
-
-		if ( !err.equals( UOCResourceErrorCode.CREATED ) && !err.equals( UOCResourceErrorCode.UPDATED ) ) {
-			throw new DataImportException( "uocBasicResourceWithCategory returned error code " + err.toString( ) );
-		}
-	}
-
-
-	/**
-	 * Run the resource definitions import tool
-	 * 
-	 * <p>
-	 * Loads the data file, the connects to the database and creates or updates all definitions.
-	 */
-	@Override
-	public void run( )
-	{
-		Resources data;
-		try {
-			data = new ResourceLoader( this.file ).load( );
-		} catch ( DataImportException e ) {
-			System.err.println( "Error while loading '" + this.file + "': " + e.getMessage( ) );
-			this.logger.error( "Error while loading resources data" , e );
-			return;
-		}
-
-		AbstractApplicationContext ctx = this.createContext( );
-		this.createTemplates( ctx );
-		this.executeImportTransaction( data );
-		ToolBase.destroyContext( ctx );
-	}
-
-
-	/**
-	 * Execute the resource definitions importation transaction
-	 * 
-	 * <p>
-	 * Run a transaction and execute the importation code inside it. Roll back if anything goes
-	 * wrong.
-	 * 
-	 * @param data
-	 *            the Resources definitions instance
-	 */
-	private void executeImportTransaction( final Resources data )
-	{
-		boolean rv = this.tTemplate.execute( new TransactionCallback< Boolean >( ) {
-			@Override
-			public Boolean doInTransaction( TransactionStatus status )
-			{
-				boolean rv = ImportResources.this.doTransaction( data );
-				if ( !rv ) {
-					status.setRollbackOnly( );
-				}
-				return rv;
-			}
-		} );
-		if ( rv ) {
-			this.logger.info( "Resource import successful" );
-		}
-	}
-
-
-	/**
-	 * Import transaction body
-	 * 
-	 * <p>
-	 * Import all definitions and handle exceptions.
-	 * 
-	 * @param data
-	 *            the Resources definitions instance
-	 * @return
-	 */
-	private boolean doTransaction( Resources data )
-	{
-		try {
-			this.importResources( data );
-			return true;
-		} catch ( RuntimeException e ) {
-			this.logger.error( "Caught runtime exception" , e );
-		} catch ( DataImportException e ) {
-			this.logger.error( "Error while importing resources" , e );
-		}
-		return false;
-	}
-
-
-	/**
-	 * Obtain the name of the definitions file
-	 * 
-	 * <p>
-	 * Check the command line options, setting the definitions file accordingly.
-	 */
-	@Override
-	public boolean setOptions( String... options )
-	{
-		if ( options.length != 1 ) {
-			return false;
-		}
-		this.file = new File( options[ 0 ] );
-		if ( ! ( this.file.isFile( ) && this.file.canRead( ) ) ) {
-			return false;
-		}
-		return true;
-	}
-}
diff --git a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/ImportTechGraph.java b/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/ImportTechGraph.java
deleted file mode 100644
index c912c05..0000000
--- a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/ImportTechGraph.java
+++ /dev/null
@@ -1,326 +0,0 @@
-package com.deepclone.lw.cli;
-
-
-import java.io.File;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import javax.sql.DataSource;
-
-import org.apache.log4j.Logger;
-import org.postgresql.util.PGobject;
-import org.springframework.context.ApplicationContext;
-import org.springframework.context.support.AbstractApplicationContext;
-import org.springframework.context.support.ClassPathXmlApplicationContext;
-import org.springframework.context.support.FileSystemXmlApplicationContext;
-import org.springframework.transaction.PlatformTransactionManager;
-import org.springframework.transaction.TransactionStatus;
-import org.springframework.transaction.support.TransactionCallback;
-import org.springframework.transaction.support.TransactionTemplate;
-
-import com.deepclone.lw.cli.xmlimport.TechnologyLoader;
-import com.deepclone.lw.cli.xmlimport.data.DataImportException;
-import com.deepclone.lw.cli.xmlimport.data.techs.Technologies;
-import com.deepclone.lw.cli.xmlimport.data.techs.Technology;
-import com.deepclone.lw.cli.xmlimport.data.techs.TechnologyDefinitionResult;
-import com.deepclone.lw.utils.StoredProc;
-
-
-
-/**
- * Technology graph import tool
- * 
- * <p>
- * This class defines the body of the technology graph import tool. It loads the data file specified
- * on the command line, validates it and then loads the technology definitions and dependencies into
- * the database.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-public class ImportTechGraph
-		extends CLITool
-{
-	/** Logging system */
-	private final Logger logger = Logger.getLogger( ImportTechGraph.class );
-
-	/** File to read the definitions from */
-	private File file;
-
-	/** Spring transaction template */
-	private TransactionTemplate tTemplate;
-
-	/** Technology creation or update stored procedure */
-	private StoredProc fUocTechnology;
-
-	/** Stored procedure that removes all dependencies from a technology */
-	private StoredProc fTechdepClear;
-
-	/** Stored procedure that adds a dependency to a technology */
-	private StoredProc fTechdepAdd;
-
-
-	/**
-	 * Create the Spring context
-	 * 
-	 * <p>
-	 * Load the definition of the data source as a Spring context, then adds the transaction
-	 * management component.
-	 * 
-	 * @return the Spring application context
-	 */
-	private ClassPathXmlApplicationContext createContext( )
-	{
-		FileSystemXmlApplicationContext ctx = new FileSystemXmlApplicationContext( new String[] {
-			this.getDataSource( )
-		} );
-		ctx.refresh( );
-
-		return new ClassPathXmlApplicationContext( new String[] {
-			"configuration/transactions.xml"
-		} , true , ctx );
-	}
-
-
-	/**
-	 * Create database access templates
-	 * 
-	 * <p>
-	 * Initialise the transaction template and the stored procedure wrappers.
-	 * 
-	 * @param ctx
-	 *            the Spring application context
-	 */
-	private void createTemplates( ApplicationContext ctx )
-	{
-		DataSource dSource = ctx.getBean( DataSource.class );
-		PlatformTransactionManager tManager = ctx.getBean( PlatformTransactionManager.class );
-
-		this.fUocTechnology = new StoredProc( dSource , "defs" , "uoc_technology" )
-				.addParameter( "_name" , java.sql.Types.VARCHAR ).addParameter( "_category" , java.sql.Types.VARCHAR )
-				.addParameter( "_discovery" , java.sql.Types.VARCHAR )
-				.addParameter( "_description" , java.sql.Types.VARCHAR )
-				.addParameter( "_price" , java.sql.Types.BIGINT ).addParameter( "_points" , java.sql.Types.BIGINT )
-				.addOutput( "_result" , java.sql.Types.OTHER );
-
-		this.fTechdepClear = new StoredProc( dSource , "defs" , "techdep_clear" ).addParameter( "_tech" ,
-				java.sql.Types.VARCHAR );
-
-		this.fTechdepAdd = new StoredProc( dSource , "defs" , "techdep_add" )
-				.addParameter( "_dependent" , java.sql.Types.VARCHAR )
-				.addParameter( "_dependency" , java.sql.Types.VARCHAR ).addOutput( "_result" , java.sql.Types.OTHER );
-
-		this.tTemplate = new TransactionTemplate( tManager );
-	}
-
-
-	/**
-	 * Import all technology definitions
-	 * 
-	 * <p>
-	 * Import all technology definitions from the top-level {@link Technologies}, creating a map of
-	 * dependencies. Once all definitions have been imported, add all dependencies.
-	 * 
-	 * @param data
-	 *            the top level {@link Technologies} data instance
-	 * 
-	 * @throws DataImportException
-	 *             when some technology definition or dependency cannot be imported
-	 */
-	private void importTechnologies( Technologies data )
-			throws DataImportException
-	{
-		Map< String , List< String > > dependencies = new HashMap< String , List< String > >( );
-		for ( Technology technology : data ) {
-			this.importTechnologyDefinition( technology );
-			dependencies.put( technology.getName( ) , technology.getDependencies( ) );
-		}
-
-		for ( Map.Entry< String , List< String > > techDeps : dependencies.entrySet( ) ) {
-			for ( String dependency : techDeps.getValue( ) ) {
-				this.importDependency( techDeps.getKey( ) , dependency );
-			}
-		}
-	}
-
-
-	/**
-	 * Import a technology definition
-	 * 
-	 * <p>
-	 * Import the definition, and if there was already a definition by that name, clear its
-	 * dependencies.
-	 * 
-	 * @param technology
-	 *            the definition to import
-	 * @throws DataImportException
-	 *             when the update or creation stored procedure returns anything other than
-	 *             <code>CREATED</code> or <code>UPDATED</code>
-	 */
-	private void importTechnologyDefinition( Technology technology )
-			throws DataImportException
-	{
-		this.logger.info( "Importing technology '" + technology.getName( ) + "'" );
-
-		TechnologyDefinitionResult result = this.getResultOf( this.fUocTechnology.execute( technology.getName( ) ,
-				technology.getCategory( ) , technology.getDiscovery( ) , technology.getDescription( ) ,
-				technology.getCost( ) , technology.getPoints( ) ) );
-		if ( result == TechnologyDefinitionResult.UPDATED ) {
-			this.fTechdepClear.execute( technology.getName( ) );
-		} else if ( result != TechnologyDefinitionResult.CREATED ) {
-			throw new DataImportException( "Error while importing technology '" + technology.getName( ) + "': "
-					+ result );
-		}
-	}
-
-
-	/**
-	 * Import a dependency between two technologies
-	 * 
-	 * <p>
-	 * Attempt to add a dependency from a technology to another.
-	 * 
-	 * @param dependent
-	 *            the dependent technology
-	 * @param dependency
-	 *            the technology to depend on
-	 * 
-	 * @throws DataImportException
-	 *             if dependency creation fails
-	 */
-	private void importDependency( String dependent , String dependency )
-			throws DataImportException
-	{
-		this.logger.info( "Importing dependency from " + dependent + " to " + dependency );
-
-		TechnologyDefinitionResult result = this.getResultOf( this.fTechdepAdd.execute( dependent , dependency ) );
-		switch ( result ) {
-			case CREATED:
-				return;
-			case REDUNDANT:
-				throw new DataImportException( "( " + dependent + " -> " + dependency + " ) is redundant" );
-			case BAD_STRINGS:
-				throw new DataImportException( "( " + dependent + " -> " + dependency + " ): undefined technology" );
-			case CYCLE:
-				throw new DataImportException( "( " + dependent + " -> " + dependency + " ) would create a cycle" );
-			default:
-				throw new DataImportException( "( " + dependent + " -> " + dependency + " ): unexpected error code "
-						+ result );
-		}
-	}
-
-
-	/**
-	 * Helper method for stored procedure results
-	 * 
-	 * <p>
-	 * This method converts the map returned by one of the definition stored procedures into a
-	 * {@link TechnologyDefinitionResult} value.
-	 * 
-	 * @param spResult
-	 *            the return value of {@link StoredProc#execute(Object...)}
-	 * 
-	 * @return the converted value of the _result field
-	 */
-	private TechnologyDefinitionResult getResultOf( Map< String , Object > spResult )
-	{
-		return TechnologyDefinitionResult.valueOf( ( (PGobject) spResult.get( "_result" ) ).getValue( ) );
-	}
-
-
-	/**
-	 * Run the technology definitions import tool
-	 * 
-	 * <p>
-	 * Loads the data file, the connects to the database and creates or updates all definitions.
-	 */
-	@Override
-	public void run( )
-	{
-		Technologies data;
-		try {
-			data = new TechnologyLoader( this.file ).load( );
-		} catch ( DataImportException e ) {
-			this.logger.error( "Error while loading technology definitions" , e );
-			return;
-		}
-
-		AbstractApplicationContext ctx = this.createContext( );
-		this.createTemplates( ctx );
-		this.executeImportTransaction( data );
-		ToolBase.destroyContext( ctx );
-	}
-
-
-	/**
-	 * Execute the technology definitions importation transaction
-	 * 
-	 * <p>
-	 * Run a transaction and execute the importation code inside it. Roll back if anything goes
-	 * wrong.
-	 * 
-	 * @param data
-	 *            the {@link Technologies} definitions instance
-	 */
-	private void executeImportTransaction( final Technologies data )
-	{
-		boolean rv = this.tTemplate.execute( new TransactionCallback< Boolean >( ) {
-			@Override
-			public Boolean doInTransaction( TransactionStatus status )
-			{
-				boolean rv = ImportTechGraph.this.doTransaction( data );
-				if ( !rv ) {
-					status.setRollbackOnly( );
-				}
-				return rv;
-			}
-		} );
-		if ( rv ) {
-			this.logger.info( "Technology import successful" );
-		}
-	}
-
-
-	/**
-	 * Import transaction body
-	 * 
-	 * <p>
-	 * Import all definitions and handle exceptions.
-	 * 
-	 * @param data
-	 *            the {@link Technologies} definitions instance
-	 * @return
-	 */
-	private boolean doTransaction( Technologies data )
-	{
-		try {
-			this.importTechnologies( data );
-			return true;
-		} catch ( RuntimeException e ) {
-			this.logger.error( "Caught runtime exception" , e );
-		} catch ( DataImportException e ) {
-			this.logger.error( e.getMessage( ) );
-		}
-		return false;
-	}
-
-
-	/**
-	 * Obtain the name of the definitions file
-	 * 
-	 * <p>
-	 * Check the command line options, setting the definitions file accordingly.
-	 */
-	@Override
-	public boolean setOptions( String... options )
-	{
-		if ( options.length != 1 ) {
-			return false;
-		}
-		this.file = new File( options[ 0 ] );
-		if ( ! ( this.file.isFile( ) && this.file.canRead( ) ) ) {
-			return false;
-		}
-		return true;
-	}
-}
diff --git a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/ImportText.java b/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/ImportText.java
deleted file mode 100644
index 3dcf4ef..0000000
--- a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/ImportText.java
+++ /dev/null
@@ -1,249 +0,0 @@
-package com.deepclone.lw.cli;
-
-
-import java.io.File;
-
-import javax.sql.DataSource;
-
-import org.apache.log4j.Logger;
-import org.springframework.context.ApplicationContext;
-import org.springframework.context.support.AbstractApplicationContext;
-import org.springframework.context.support.ClassPathXmlApplicationContext;
-import org.springframework.context.support.FileSystemXmlApplicationContext;
-import org.springframework.transaction.PlatformTransactionManager;
-import org.springframework.transaction.TransactionStatus;
-import org.springframework.transaction.support.TransactionCallback;
-import org.springframework.transaction.support.TransactionTemplate;
-
-import com.deepclone.lw.cli.xmlimport.I18NLoader;
-import com.deepclone.lw.cli.xmlimport.data.DataImportException;
-import com.deepclone.lw.cli.xmlimport.data.i18n.I18NText;
-import com.deepclone.lw.cli.xmlimport.data.i18n.LanguageDefinition;
-import com.deepclone.lw.cli.xmlimport.data.i18n.StringDefinition;
-import com.deepclone.lw.utils.StoredProc;
-
-
-
-/**
- * I18N text import tool
- * 
- * <p>
- * This class defines the body of the I18N text import tool. It loads the data file specified on the
- * command line, validates it, then proceeds to loading the languages and strings to the database.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- * 
- */
-public class ImportText
-		extends CLITool
-{
-
-	/** Logging system */
-	private final Logger logger = Logger.getLogger( ImportText.class );
-
-	/** File to read the definitions from */
-	private File file;
-
-	/** Spring transaction template */
-	private TransactionTemplate tTemplate;
-
-	/** Language creation or update stored procedure */
-	private StoredProc uocLanguage;
-	/** Translation creation or update stored procedure */
-	private StoredProc uocTranslation;
-
-
-	/**
-	 * Create the Spring context
-	 * 
-	 * <p>
-	 * Load the definition of the data source as a Spring context, then adds the transaction
-	 * management component.
-	 * 
-	 * @return the Spring application context
-	 */
-	private ClassPathXmlApplicationContext createContext( )
-	{
-		FileSystemXmlApplicationContext ctx = new FileSystemXmlApplicationContext( new String[] {
-			this.getDataSource( )
-		} );
-		ctx.refresh( );
-
-		return new ClassPathXmlApplicationContext( new String[] {
-			"configuration/transactions.xml"
-		} , true , ctx );
-	}
-
-
-	/**
-	 * Create database access templates
-	 * 
-	 * <p>
-	 * Initialise the transaction template as well as both stored procedure definitions.
-	 * 
-	 * @param ctx
-	 *            the Spring application context
-	 */
-	private void createTemplates( ApplicationContext ctx )
-	{
-		DataSource dSource = ctx.getBean( DataSource.class );
-		PlatformTransactionManager tManager = ctx.getBean( PlatformTransactionManager.class );
-
-		this.uocLanguage = new StoredProc( dSource , "defs" , "uoc_language" ).addParameter( "lid" ,
-				java.sql.Types.VARCHAR ).addParameter( "lname" , java.sql.Types.VARCHAR );
-
-		this.uocTranslation = new StoredProc( dSource , "defs" , "uoc_translation" )
-				.addParameter( "lid" , java.sql.Types.VARCHAR ).addParameter( "sid" , java.sql.Types.VARCHAR )
-				.addParameter( "trans" , java.sql.Types.VARCHAR );
-
-		this.tTemplate = new TransactionTemplate( tManager );
-	}
-
-
-	/**
-	 * Import all languages and strings
-	 * 
-	 * <p>
-	 * Import all language and string definitions from the top-level I18N data instance.
-	 * 
-	 * @param data
-	 *            the top-level I18N data instance
-	 * 
-	 * @throws DataImportException
-	 *             when some external string definition fails to load
-	 */
-	private void importText( I18NText data )
-			throws DataImportException
-	{
-		for ( LanguageDefinition ld : data ) {
-			this.importLanguage( ld );
-		}
-	}
-
-
-	/**
-	 * Import a language definition and the translations it contains
-	 * 
-	 * <p>
-	 * Import the language's definition, then iterate over all string definitions and import them as
-	 * well.
-	 * 
-	 * @param ld
-	 *            the language's definition data
-	 * 
-	 * @throws DataImportException
-	 *             when some external string definition fails to load
-	 */
-	private void importLanguage( LanguageDefinition ld )
-			throws DataImportException
-	{
-		// Try creating or updating the language
-		this.uocLanguage.execute( ld.getId( ) , ld.getName( ) );
-
-		// Import translations
-		for ( StringDefinition sd : ld ) {
-			this.uocTranslation.execute( ld.getId( ) , sd.getId( ) , sd.getString( ) );
-		}
-	}
-
-
-	/**
-	 * Run the I18N definitions import tool
-	 * 
-	 * <p>
-	 * Load the data file, then connects to the database and create or update all definitions.
-	 */
-	@Override
-	public void run( )
-	{
-		I18NText data;
-		try {
-			data = new I18NLoader( this.file ).load( );
-		} catch ( DataImportException e ) {
-			System.err.println( "Error while loading '" + this.file + "': " + e.getMessage( ) );
-			this.logger.error( "Error while loading I18N data" , e );
-			return;
-		}
-
-		AbstractApplicationContext ctx = this.createContext( );
-		this.createTemplates( ctx );
-		this.executeImportTransaction( data );
-		ToolBase.destroyContext( ctx );
-	}
-
-
-	/**
-	 * Execute the I18N definitions importation transaction
-	 * 
-	 * <p>
-	 * Run a transaction and execute the importation code inside it. Roll back if anything goes
-	 * awry.
-	 * 
-	 * @param data
-	 *            the I18N definitions instance
-	 */
-	private void executeImportTransaction( final I18NText data )
-	{
-		boolean rv = this.tTemplate.execute( new TransactionCallback< Boolean >( ) {
-
-			@Override
-			public Boolean doInTransaction( TransactionStatus status )
-			{
-				boolean rv = ImportText.this.doTransaction( data );
-				if ( !rv ) {
-					status.setRollbackOnly( );
-				}
-				return rv;
-			}
-
-		} );
-		if ( rv ) {
-			this.logger.info( "Text import successful" );
-		}
-	}
-
-
-	/**
-	 * Import transaction body
-	 * 
-	 * <p>
-	 * Import all definitions and handle exceptions.
-	 * 
-	 * @param data
-	 *            the I18N definitions instance
-	 * 
-	 * @return <code>true</code> on success, <code>false</code> otherwise
-	 */
-	private boolean doTransaction( I18NText data )
-	{
-		try {
-			this.importText( data );
-			return true;
-		} catch ( RuntimeException e ) {
-			this.logger.error( "Caught runtime exception" , e );
-		} catch ( DataImportException e ) {
-			this.logger.error( "Error while importing external strings" , e );
-		}
-		return false;
-	}
-
-
-	/**
-	 * Obtain the name of the definitions file
-	 * 
-	 * <p>
-	 * Check the command line options, setting the definitions file accordingly.
-	 */
-	@Override
-	public boolean setOptions( String... options )
-	{
-		if ( options.length != 1 ) {
-			return false;
-		}
-		this.file = new File( options[ 0 ] );
-		if ( ! ( this.file.isFile( ) && this.file.canRead( ) ) ) {
-			return false;
-		}
-		return true;
-	}
-}
diff --git a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/EventDefinitionLoader.java b/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/EventDefinitionLoader.java
deleted file mode 100644
index 69ff4d7..0000000
--- a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/EventDefinitionLoader.java
+++ /dev/null
@@ -1,123 +0,0 @@
-package com.deepclone.lw.cli.xmlimport;
-
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-
-import com.deepclone.lw.cli.xmlimport.data.DataImportException;
-import com.deepclone.lw.cli.xmlimport.data.evdef.*;
-import com.thoughtworks.xstream.XStream;
-import com.thoughtworks.xstream.XStreamException;
-
-
-
-/**
- * Event definitions loader
- * 
- * <p>
- * This class implements loading event definitions from XML files. The definitions will be extracted
- * and verified.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-public class EventDefinitionLoader
-{
-	/** The file to read the XML from */
-	private final File file;
-
-
-	/**
-	 * Initialise the loader
-	 * 
-	 * @param file
-	 *            the XML file that contains the definitions
-	 */
-	public EventDefinitionLoader( File file )
-	{
-		this.file = file.getAbsoluteFile( );
-	}
-
-
-	/**
-	 * Initialise the necessary XStream instance
-	 * 
-	 * <p>
-	 * Initialise the XStream instance by processing annotations in all event definition importable
-	 * data classes.
-	 * 
-	 * @return the XStream instance to use when loading the data
-	 */
-	private XStream initXStream( )
-	{
-		XStream xstream = new XStream( );
-		xstream.processAnnotations( EventDefinitions.class );
-		xstream.processAnnotations( BooleanEventField.class );
-		xstream.processAnnotations( IntegerEventField.class );
-		xstream.processAnnotations( RealEventField.class );
-		xstream.processAnnotations( TextEventField.class );
-		xstream.processAnnotations( I18NEventField.class );
-		xstream.processAnnotations( EntityEventField.class );
-		return xstream;
-	}
-
-
-	/**
-	 * Load the event definitions
-	 * 
-	 * <p>
-	 * Load the XML file and process the definitions file using XStream.
-	 * 
-	 * @return the top-level importable data instance
-	 * 
-	 * @throws DataImportException
-	 *             if reading from the file or parsing its contents fail
-	 */
-	private EventDefinitions loadXMLFile( )
-			throws DataImportException
-	{
-		FileInputStream fis;
-		try {
-			fis = new FileInputStream( this.file );
-		} catch ( FileNotFoundException e ) {
-			throw new DataImportException( "Unable to load event definitions" , e );
-		}
-
-		try {
-			try {
-				XStream xstream = this.initXStream( );
-				return (EventDefinitions) xstream.fromXML( fis );
-			} finally {
-				fis.close( );
-			}
-		} catch ( IOException e ) {
-			throw new DataImportException( "Input error while loading event definitions" , e );
-		} catch ( XStreamException e ) {
-			throw new DataImportException( "XML error while loading event definitions" , e );
-		}
-	}
-
-
-	/**
-	 * Load and process I18N definition
-	 * 
-	 * <p>
-	 * Attempt to load all I18N definitions, make sure they are valid, then set the original file's
-	 * path.
-	 * 
-	 * @return the top-level importable data instance
-	 * 
-	 * @throws DataImportException
-	 *             if loading or verifying the data fails
-	 */
-	public EventDefinitions load( )
-			throws DataImportException
-	{
-		EventDefinitions events = this.loadXMLFile( );
-		events.verifyData( );
-		events.setReadFrom( this.file );
-		return events;
-	}
-
-}
diff --git a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/I18NLoader.java b/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/I18NLoader.java
deleted file mode 100644
index 2932549..0000000
--- a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/I18NLoader.java
+++ /dev/null
@@ -1,121 +0,0 @@
-package com.deepclone.lw.cli.xmlimport;
-
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-
-import com.deepclone.lw.cli.xmlimport.data.DataImportException;
-import com.deepclone.lw.cli.xmlimport.data.i18n.FileString;
-import com.deepclone.lw.cli.xmlimport.data.i18n.I18NText;
-import com.deepclone.lw.cli.xmlimport.data.i18n.InlineString;
-import com.thoughtworks.xstream.XStream;
-import com.thoughtworks.xstream.XStreamException;
-
-
-
-/**
- * I18N text definitions loader
- * 
- * <p>
- * This class can be used to load all I18N definitions. It will extract them from the XML file,
- * verify them and set their origin.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-public class I18NLoader
-{
-	/** The file to read the XML from */
-	private final File file;
-
-
-	/**
-	 * Initialise the loader
-	 * 
-	 * @param file
-	 *            the XML file that contains the definitions
-	 */
-	public I18NLoader( File file )
-	{
-		this.file = file.getAbsoluteFile( );
-	}
-
-
-	/**
-	 * Initialise the necessary XStream instance
-	 * 
-	 * <p>
-	 * Initialise the XStream instance by processing annotations in all I18N importable data
-	 * classes.
-	 * 
-	 * @return the XStream instance to use when loading the data
-	 */
-	private XStream initXStream( )
-	{
-		XStream xstream = new XStream( );
-		xstream.processAnnotations( I18NText.class );
-		xstream.processAnnotations( InlineString.class );
-		xstream.processAnnotations( FileString.class );
-		return xstream;
-	}
-
-
-	/**
-	 * Load the I18N definitions
-	 * 
-	 * <p>
-	 * Load the XML file and process the definitions file using XStream.
-	 * 
-	 * @return the top-level importable data instance
-	 * 
-	 * @throws DataImportException
-	 *             if reading from the file or parsing its contents fail
-	 */
-	private I18NText loadXMLFile( )
-			throws DataImportException
-	{
-		FileInputStream fis;
-		try {
-			fis = new FileInputStream( this.file );
-		} catch ( FileNotFoundException e ) {
-			throw new DataImportException( "Unable to load I18N definitions" , e );
-		}
-
-		try {
-			try {
-				XStream xstream = this.initXStream( );
-				return (I18NText) xstream.fromXML( fis );
-			} finally {
-				fis.close( );
-			}
-		} catch ( IOException e ) {
-			throw new DataImportException( "Input error while loading I18N definitions" , e );
-		} catch ( XStreamException e ) {
-			throw new DataImportException( "XML error while loading I18N definitions" , e );
-		}
-	}
-
-
-	/**
-	 * Load and process I18N definition
-	 * 
-	 * <p>
-	 * Attempt to load all I18N definitions, make sure they are valid, then set the original file's
-	 * path.
-	 * 
-	 * @return the top-level importable data instance
-	 * 
-	 * @throws DataImportException
-	 *             if loading or verifying the data fails
-	 */
-	public I18NText load( )
-			throws DataImportException
-	{
-		I18NText text = this.loadXMLFile( );
-		text.verifyData( );
-		text.setReadFrom( this.file );
-		return text;
-	}
-
-}
diff --git a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/ResourceLoader.java b/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/ResourceLoader.java
deleted file mode 100644
index 47656d8..0000000
--- a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/ResourceLoader.java
+++ /dev/null
@@ -1,118 +0,0 @@
-package com.deepclone.lw.cli.xmlimport;
-
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-
-import com.deepclone.lw.cli.xmlimport.data.DataImportException;
-import com.deepclone.lw.cli.xmlimport.data.resources.NaturalResource;
-import com.deepclone.lw.cli.xmlimport.data.resources.Resources;
-import com.thoughtworks.xstream.XStream;
-import com.thoughtworks.xstream.XStreamException;
-
-
-
-/**
- * Resource Loader
- * 
- * <p>
- * This class can be used to load all resource definitions. It extracts them from the XML file and
- * verifies them.
- * 
- * @author <a href="mailto:tim@mitheren.com">T. Rosser</a>
- */
-public class ResourceLoader
-{
-	/** The file to read the XML from */
-	private final File file;
-
-
-	/**
-	 * Initialise the loader
-	 * 
-	 * @param file
-	 *            the XML file that contains the definitions
-	 */
-	public ResourceLoader( File file )
-	{
-		this.file = file.getAbsoluteFile( );
-	}
-
-
-	/**
-	 * Initialise the necessary XStream instance
-	 * 
-	 * <p>
-	 * Initialise the XStream instance by processing the annotations of all the resource importable
-	 * data classes.
-	 * 
-	 * @return the XStream instance to use when loading the data
-	 */
-	private XStream initXStream( )
-	{
-		XStream xstream = new XStream( );
-		xstream.processAnnotations( Resources.class );
-		xstream.processAnnotations( NaturalResource.class );
-		return xstream;
-	}
-
-
-	/**
-	 * Load the resource definitions
-	 * 
-	 * <p>
-	 * Load the XML file and process the definitions using XStream.
-	 * 
-	 * @return the top-level importable data instance
-	 * 
-	 * @throws DataImportException
-	 *             if reading from the file or parsing its contents fail
-	 */
-	private Resources loadXMLFile( )
-			throws DataImportException
-	{
-		FileInputStream fis;
-		try {
-			fis = new FileInputStream( this.file );
-		} catch ( FileNotFoundException e ) {
-			throw new DataImportException( "Unable to load resource definitions" , e );
-		}
-
-		try {
-			try {
-				XStream xstream = this.initXStream( );
-				return (Resources) xstream.fromXML( fis );
-			} finally {
-				fis.close( );
-			}
-		} catch ( IOException e ) {
-			throw new DataImportException( "Input error while loading resource definitions" , e );
-		} catch ( XStreamException e ) {
-			throw new DataImportException( "XML error while loading resource definitions" , e );
-		}
-	}
-
-
-	/**
-	 * Load and process resource definitions
-	 * 
-	 * <p>
-	 * Attempt to load all resource definitions, ensure they are valid, then set the original file's
-	 * path.
-	 * 
-	 * @return the top-level importable data instance
-	 * 
-	 * @throws DataImportException
-	 *             if loading or verifying the data fails
-	 */
-	public Resources load( )
-			throws DataImportException
-	{
-		Resources resources = this.loadXMLFile( );
-		resources.verifyData( );
-		resources.setReadFrom( this.file );
-		return resources;
-	}
-}
diff --git a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/TechnologyLoader.java b/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/TechnologyLoader.java
deleted file mode 100644
index 275a7cf..0000000
--- a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/TechnologyLoader.java
+++ /dev/null
@@ -1,116 +0,0 @@
-package com.deepclone.lw.cli.xmlimport;
-
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-
-import com.deepclone.lw.cli.xmlimport.data.DataImportException;
-import com.deepclone.lw.cli.xmlimport.data.techs.Technologies;
-import com.thoughtworks.xstream.XStream;
-import com.thoughtworks.xstream.XStreamException;
-
-
-
-/**
- * Technology Loader
- * 
- * <p>
- * This class can be used to load all technology definitions. It extracts them from the XML file and
- * verifies them.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-public class TechnologyLoader
-{
-	/** The file to read the XML from */
-	private final File file;
-
-
-	/**
-	 * Initialise the loader
-	 * 
-	 * @param file
-	 *            the XML file that contains the definitions
-	 */
-	public TechnologyLoader( File file )
-	{
-		this.file = file.getAbsoluteFile( );
-	}
-
-
-	/**
-	 * Initialise the necessary XStream instance
-	 * 
-	 * <p>
-	 * Initialise the XStream instance by processing the annotations of all the technology
-	 * importable data classes.
-	 * 
-	 * @return the XStream instance to use when loading the data
-	 */
-	private XStream initXStream( )
-	{
-		XStream xstream = new XStream( );
-		xstream.processAnnotations( Technologies.class );
-		return xstream;
-	}
-
-
-	/**
-	 * Load the technology definitions
-	 * 
-	 * <p>
-	 * Load the XML file and process the definitions using XStream.
-	 * 
-	 * @return the top-level importable data instance
-	 * 
-	 * @throws DataImportException
-	 *             if reading from the file or parsing its contents fail
-	 */
-	private Technologies loadXMLFile( )
-			throws DataImportException
-	{
-		FileInputStream fis;
-		try {
-			fis = new FileInputStream( this.file );
-		} catch ( FileNotFoundException e ) {
-			throw new DataImportException( "Unable to load technology definitions" , e );
-		}
-
-		try {
-			try {
-				XStream xstream = this.initXStream( );
-				return (Technologies) xstream.fromXML( fis );
-			} finally {
-				fis.close( );
-			}
-		} catch ( IOException e ) {
-			throw new DataImportException( "Input error while loading technology definitions" , e );
-		} catch ( XStreamException e ) {
-			throw new DataImportException( "XML error while loading technology definitions" , e );
-		}
-	}
-
-
-	/**
-	 * Load and process technology definitions
-	 * 
-	 * <p>
-	 * Attempt to load all technology definitions, ensure they are valid, then set the original
-	 * file's path.
-	 * 
-	 * @return the top-level importable data instance
-	 * 
-	 * @throws DataImportException
-	 *             if loading or verifying the data fails
-	 */
-	public Technologies load( )
-			throws DataImportException
-	{
-		Technologies techs = this.loadXMLFile( );
-		techs.verifyData( );
-		techs.setReadFrom( this.file );
-		return techs;
-	}
-}
diff --git a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/data/DataImportException.java b/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/data/DataImportException.java
deleted file mode 100644
index 7c70c71..0000000
--- a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/data/DataImportException.java
+++ /dev/null
@@ -1,43 +0,0 @@
-package com.deepclone.lw.cli.xmlimport.data;
-
-
-/**
- * Data import exception
- * 
- * <p>
- * This exception is thrown by importable data classes when some error occurs while loading, or when
- * verification fails.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-@SuppressWarnings( "serial" )
-public class DataImportException
-		extends Exception
-{
-
-	/**
-	 * Initialise a data import exception using an error message
-	 * 
-	 * @param message
-	 *            the error message
-	 */
-	public DataImportException( String message )
-	{
-		super( message );
-	}
-
-
-	/**
-	 * Initialise a data import exception using an message and a cause
-	 * 
-	 * @param message
-	 *            the error message
-	 * @param cause
-	 *            the exception that caused this exception to be thrown
-	 */
-	public DataImportException( String message , Throwable cause )
-	{
-		super( message , cause );
-	}
-
-}
diff --git a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/data/ImportableData.java b/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/data/ImportableData.java
deleted file mode 100644
index fae56bd..0000000
--- a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/data/ImportableData.java
+++ /dev/null
@@ -1,66 +0,0 @@
-package com.deepclone.lw.cli.xmlimport.data;
-
-
-import java.io.File;
-import java.io.Serializable;
-
-
-
-/**
- * Base class for importable data
- * 
- * <p>
- * This abstract class serves as the base for all classes that represent data imported from XML
- * files during the database's initialisation.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-@SuppressWarnings( "serial" )
-public abstract class ImportableData
-		implements Serializable
-{
-
-	/** The file these data were read from */
-	private transient File readFrom;
-
-
-	/** @return the file these data were read from */
-	public final File getReadFrom( )
-	{
-		return this.readFrom;
-	}
-
-
-	/**
-	 * Validate the item
-	 * 
-	 * <p>
-	 * This method may be overridden to implement some form of validation of the loaded data.
-	 * 
-	 * @throws DataImportException
-	 *             if data validation failed
-	 */
-	public void verifyData( )
-			throws DataImportException
-	{
-		// EMPTY
-	}
-
-
-	/**
-	 * Set the source file
-	 * 
-	 * <p>
-	 * This method sets the file instance returned by {@link #getReadFrom()}. For classes that
-	 * represent collections of data, this method should be overridden in order to update all
-	 * contained items.
-	 * 
-	 * @param readFrom
-	 *            the file the data were read from
-	 */
-	public void setReadFrom( File readFrom )
-	{
-		this.readFrom = readFrom;
-	}
-
-}
diff --git a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/data/evdef/BooleanEventField.java b/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/data/evdef/BooleanEventField.java
deleted file mode 100644
index 24d134b..0000000
--- a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/data/evdef/BooleanEventField.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package com.deepclone.lw.cli.xmlimport.data.evdef;
-
-
-import com.thoughtworks.xstream.annotations.XStreamAlias;
-
-
-
-/**
- * A boolean field definition
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-@XStreamAlias( "boolean" )
-@SuppressWarnings( "serial" )
-public class BooleanEventField
-		extends EventFieldBase
-{
-
-	/** @return {@link EventFieldType#BOOLEAN} */
-	@Override
-	public EventFieldType getType( )
-	{
-		return EventFieldType.BOOLEAN;
-	}
-
-}
diff --git a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/data/evdef/EntityEventField.java b/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/data/evdef/EntityEventField.java
deleted file mode 100644
index 60fa881..0000000
--- a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/data/evdef/EntityEventField.java
+++ /dev/null
@@ -1,44 +0,0 @@
-package com.deepclone.lw.cli.xmlimport.data.evdef;
-
-
-import com.thoughtworks.xstream.annotations.XStreamAlias;
-import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
-
-
-
-/**
- * An entity reference field definition
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-@XStreamAlias( "entity" )
-@SuppressWarnings( "serial" )
-public class EntityEventField
-		extends EventFieldBase
-{
-
-	/** The type of entities this field references */
-	@XStreamAsAttribute
-	@XStreamAlias( "entity-type" )
-	private EventFieldEntityType entityType;
-
-
-	/**
-	 * Gets the type of entities this field references.
-	 * 
-	 * @return the type of entities this field references
-	 */
-	public EventFieldEntityType getEntityType( )
-	{
-		return this.entityType;
-	}
-
-
-	/** @return {@link EntityFieldType#ENTITY} */
-	@Override
-	public EventFieldType getType( )
-	{
-		return EventFieldType.ENTITY;
-	}
-
-}
diff --git a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/data/evdef/EventDefinition.java b/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/data/evdef/EventDefinition.java
deleted file mode 100644
index e68f1c2..0000000
--- a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/data/evdef/EventDefinition.java
+++ /dev/null
@@ -1,133 +0,0 @@
-package com.deepclone.lw.cli.xmlimport.data.evdef;
-
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.List;
-
-import com.deepclone.lw.cli.xmlimport.data.DataImportException;
-import com.deepclone.lw.cli.xmlimport.data.ImportableData;
-import com.thoughtworks.xstream.annotations.XStreamAlias;
-import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
-import com.thoughtworks.xstream.annotations.XStreamImplicit;
-
-
-
-/**
- * Event definition
- * 
- * <p>
- * This class represents an event definition entry from the data file. An event definition consists
- * in a few properties, and a potentially empty list of event field definitions.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- * 
- */
-@SuppressWarnings( "serial" )
-public class EventDefinition
-		extends ImportableData
-		implements Iterable< EventFieldBase >
-{
-
-	/** The event type's identifier */
-	@XStreamAsAttribute
-	@XStreamAlias( "id" )
-	private String identifier;
-
-	/** The default priority */
-	@XStreamAsAttribute
-	private Integer priority;
-
-	/** Whether users can override the events' priority */
-	@XStreamAsAttribute
-	private Boolean adjustable;
-
-	/** Prefix of the name and template strings */
-	@XStreamAsAttribute
-	@XStreamAlias( "i18n-strings" )
-	private String i18nStrings;
-
-	/** The list of fields */
-	@XStreamImplicit
-	private List< EventFieldBase > fields = new ArrayList< EventFieldBase >( );
-
-
-	/**
-	 * Gets the identifier.
-	 * 
-	 * @return the identifier
-	 */
-	public String getIdentifier( )
-	{
-		return this.identifier;
-	}
-
-
-	/**
-	 * Gets the priority.
-	 * 
-	 * @return the priority
-	 */
-	public int getPriority( )
-	{
-		return ( this.priority == null ) ? 2 : this.priority;
-	}
-
-
-	/**
-	 * Checks if the priority is adjustable.
-	 * 
-	 * @return <code>true</code> if the priority is adjustable
-	 */
-	public boolean isAdjustable( )
-	{
-		return ( this.adjustable == null ) ? true : this.adjustable;
-	}
-
-
-	/**
-	 * Gets the prefix of the name and template strings.
-	 * 
-	 * @return the prefix of the name and template strings.
-	 */
-	public String getI18NStrings( )
-	{
-		return this.i18nStrings;
-	}
-
-
-	/**
-	 * Allows iteration over the event definition's fields
-	 * 
-	 * @return an iterator on the event definition's fields
-	 */
-	@Override
-	public Iterator< EventFieldBase > iterator( )
-	{
-		return Collections.unmodifiableList( this.fields ).iterator( );
-	}
-
-
-	/**
-	 * Verify fields data
-	 * 
-	 * <p>
-	 * If no fields are defined, make sure the list is not <code>null</code>; otherwise iterate over
-	 * the fields to call their own data checks methods.
-	 */
-	@Override
-	public void verifyData( )
-			throws DataImportException
-	{
-		super.verifyData( );
-		if ( this.fields == null ) {
-			this.fields = new ArrayList< EventFieldBase >( );
-		} else {
-			for ( EventFieldBase f : this.fields ) {
-				f.verifyData( );
-			}
-		}
-	}
-
-}
diff --git a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/data/evdef/EventDefinitions.java b/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/data/evdef/EventDefinitions.java
deleted file mode 100644
index f5037e0..0000000
--- a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/data/evdef/EventDefinitions.java
+++ /dev/null
@@ -1,64 +0,0 @@
-package com.deepclone.lw.cli.xmlimport.data.evdef;
-
-
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-
-import com.deepclone.lw.cli.xmlimport.data.DataImportException;
-import com.deepclone.lw.cli.xmlimport.data.ImportableData;
-import com.thoughtworks.xstream.annotations.XStreamAlias;
-import com.thoughtworks.xstream.annotations.XStreamImplicit;
-
-
-
-/**
- * Event type definitions
- * 
- * <p>
- * This class represents the list of event type definitions as it is found in the appropriate data
- * file.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-@SuppressWarnings( "serial" )
-@XStreamAlias( "lw-event-definitions" )
-public class EventDefinitions
-		extends ImportableData
-		implements Iterable< EventDefinition >
-{
-
-	/** The list of event definitions */
-	@XStreamImplicit( itemFieldName = "evdef" )
-	private List< EventDefinition > definitions = new LinkedList< EventDefinition >( );
-
-
-	/** Iterate over event definitions */
-	@Override
-	public Iterator< EventDefinition > iterator( )
-	{
-		return Collections.unmodifiableList( this.definitions ).iterator( );
-	}
-
-
-	/**
-	 * Verify the list of definitions
-	 * 
-	 * <p>
-	 * Make sure the list of definitions is not empty, then call the definitions' data check method.
-	 */
-	@Override
-	public void verifyData( )
-			throws DataImportException
-	{
-		super.verifyData( );
-		if ( this.definitions == null ) {
-			throw new DataImportException( "No definitions in this file" );
-		}
-		for ( EventDefinition def : this.definitions ) {
-			def.verifyData( );
-		}
-	}
-
-}
diff --git a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/data/evdef/EventFieldBase.java b/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/data/evdef/EventFieldBase.java
deleted file mode 100644
index 3cec5f5..0000000
--- a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/data/evdef/EventFieldBase.java
+++ /dev/null
@@ -1,62 +0,0 @@
-package com.deepclone.lw.cli.xmlimport.data.evdef;
-
-
-import com.deepclone.lw.cli.xmlimport.data.ImportableData;
-import com.thoughtworks.xstream.annotations.XStreamAlias;
-import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
-
-
-
-/**
- * Common event field definition
- * 
- * <p>
- * This abstract class is used as the base for event field definitions.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-@SuppressWarnings( "serial" )
-public abstract class EventFieldBase
-		extends ImportableData
-{
-
-	/** The field's identifier */
-	@XStreamAsAttribute
-	@XStreamAlias( "id" )
-	private String identifier;
-
-	/** Whether the field is required or optional */
-	@XStreamAsAttribute
-	private Boolean required;
-
-
-	/**
-	 * Obtain the type of the field
-	 * 
-	 * @return the field's type.
-	 */
-	public abstract EventFieldType getType( );
-
-
-	/**
-	 * Gets the field's identifier.
-	 * 
-	 * @return the field's identifier
-	 */
-	public String getIdentifier( )
-	{
-		return this.identifier;
-	}
-
-
-	/**
-	 * Checks if the field is required or optional.
-	 * 
-	 * @return <code>true</code> if the field is required
-	 */
-	public boolean isRequired( )
-	{
-		return this.required == null ? true : this.required;
-	}
-
-}
diff --git a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/data/evdef/EventFieldEntityType.java b/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/data/evdef/EventFieldEntityType.java
deleted file mode 100644
index 52889af..0000000
--- a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/data/evdef/EventFieldEntityType.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package com.deepclone.lw.cli.xmlimport.data.evdef;
-
-
-/** Types of entities which can be referenced through entity fields
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-public enum EventFieldEntityType {
-
-	/** Empires */
-	EMP ,
-	/** Planets */
-	PLN ,
-	/** Fleets */
-	FLT ,
-	/** Alliances */
-	ALL ,
-	/** Battles */
-	BAT ,
-	/** Administrators */
-	ADM ,
-	/** Bug reports */
-	BUG
-}
diff --git a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/data/evdef/EventFieldType.java b/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/data/evdef/EventFieldType.java
deleted file mode 100644
index 1b33be3..0000000
--- a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/data/evdef/EventFieldType.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package com.deepclone.lw.cli.xmlimport.data.evdef;
-
-
-/** Types of event fields as they are stored in the definition file
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-public enum EventFieldType {
-
-	/** An integer field */
-	INTEGER ,
-
-	/** An double precision real number field */
-	REAL ,
-
-	/** A string field */
-	TEXT ,
-
-	/** A boolean field */
-	BOOLEAN ,
-
-	/** A field that references an internationalised string */
-	I18N ,
-
-	/** A field that references some game entity */
-	ENTITY
-
-}
diff --git a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/data/evdef/I18NEventField.java b/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/data/evdef/I18NEventField.java
deleted file mode 100644
index 689eb67..0000000
--- a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/data/evdef/I18NEventField.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package com.deepclone.lw.cli.xmlimport.data.evdef;
-
-
-import com.thoughtworks.xstream.annotations.XStreamAlias;
-
-
-
-/**
- * Definition of a field containing an I18N reference
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-@XStreamAlias( "i18n" )
-@SuppressWarnings( "serial" )
-public class I18NEventField
-		extends EventFieldBase
-{
-
-	/** @return {@link EventFieldType#I18N} */
-	@Override
-	public EventFieldType getType( )
-	{
-		return EventFieldType.I18N;
-	}
-
-}
diff --git a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/data/evdef/IntegerEventField.java b/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/data/evdef/IntegerEventField.java
deleted file mode 100644
index 1a8c1ec..0000000
--- a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/data/evdef/IntegerEventField.java
+++ /dev/null
@@ -1,57 +0,0 @@
-package com.deepclone.lw.cli.xmlimport.data.evdef;
-
-
-import com.thoughtworks.xstream.annotations.XStreamAlias;
-import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
-
-
-
-/**
- * An integer event field definition
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-@XStreamAlias( "integer" )
-@SuppressWarnings( "serial" )
-public class IntegerEventField
-		extends EventFieldBase
-{
-	/** Minimal value allowed for the field */
-	@XStreamAsAttribute
-	private Integer min;
-
-	/** Maximal value allowed for the field */
-	@XStreamAsAttribute
-	private Integer max;
-
-
-	/**
-	 * Gets the minimal value allowed for the field.
-	 * 
-	 * @return the minimal value allowed for the field
-	 */
-	public Integer getMin( )
-	{
-		return this.min;
-	}
-
-
-	/**
-	 * Gets the maximal value allowed for the field.
-	 * 
-	 * @return the maximal value allowed for the field
-	 */
-	public Integer getMax( )
-	{
-		return this.max;
-	}
-
-
-	/** @return {@link EventFieldType#INTEGER} */
-	@Override
-	public EventFieldType getType( )
-	{
-		return EventFieldType.INTEGER;
-	}
-
-}
diff --git a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/data/evdef/RealEventField.java b/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/data/evdef/RealEventField.java
deleted file mode 100644
index 2b68d23..0000000
--- a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/data/evdef/RealEventField.java
+++ /dev/null
@@ -1,58 +0,0 @@
-package com.deepclone.lw.cli.xmlimport.data.evdef;
-
-
-import com.thoughtworks.xstream.annotations.XStreamAlias;
-import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
-
-
-
-/**
- * A real field definition
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-@XStreamAlias( "real" )
-@SuppressWarnings( "serial" )
-public class RealEventField
-		extends EventFieldBase
-{
-
-	/** Minimal value for the field */
-	@XStreamAsAttribute
-	private Double min;
-
-	/** Maximal value for the field */
-	@XStreamAsAttribute
-	private Double max;
-
-
-	/**
-	 * Gets the minimal value for the field.
-	 * 
-	 * @return the minimal value for the field
-	 */
-	public Double getMin( )
-	{
-		return this.min;
-	}
-
-
-	/**
-	 * Gets the maximal value for the field.
-	 * 
-	 * @return the maximal value for the field
-	 */
-	public Double getMax( )
-	{
-		return this.max;
-	}
-
-
-	/** @return {@link EventFieldType#REAL} */
-	@Override
-	public EventFieldType getType( )
-	{
-		return EventFieldType.REAL;
-	}
-
-}
diff --git a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/data/evdef/TextEventField.java b/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/data/evdef/TextEventField.java
deleted file mode 100644
index 3e2ccd8..0000000
--- a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/data/evdef/TextEventField.java
+++ /dev/null
@@ -1,60 +0,0 @@
-package com.deepclone.lw.cli.xmlimport.data.evdef;
-
-
-import com.thoughtworks.xstream.annotations.XStreamAlias;
-import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
-
-
-
-/**
- * A text event field definition
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-@XStreamAlias( "text" )
-@SuppressWarnings( "serial" )
-public class TextEventField
-		extends EventFieldBase
-{
-
-	/** The field's minimum length */
-	@XStreamAsAttribute
-	@XStreamAlias( "min-length" )
-	private Integer minLength;
-
-	/** The field's maximum length */
-	@XStreamAsAttribute
-	@XStreamAlias( "max-length" )
-	private Integer maxLength;
-
-
-	/**
-	 * Gets the field's minimum length.
-	 * 
-	 * @return the field's minimum length
-	 */
-	public Integer getMinLength( )
-	{
-		return this.minLength;
-	}
-
-
-	/**
-	 * Gets the field's maximum length.
-	 * 
-	 * @return the field's maximum length
-	 */
-	public Integer getMaxLength( )
-	{
-		return this.maxLength;
-	}
-
-
-	/** @return {@link EventFieldType#TEXT} */
-	@Override
-	public EventFieldType getType( )
-	{
-		return EventFieldType.TEXT;
-	}
-
-}
diff --git a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/data/i18n/FileString.java b/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/data/i18n/FileString.java
deleted file mode 100644
index 4645170..0000000
--- a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/data/i18n/FileString.java
+++ /dev/null
@@ -1,104 +0,0 @@
-package com.deepclone.lw.cli.xmlimport.data.i18n;
-
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileReader;
-import java.io.IOException;
-
-import com.deepclone.lw.cli.xmlimport.data.DataImportException;
-import com.thoughtworks.xstream.annotations.XStreamAlias;
-import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
-
-
-
-/**
- * An external string definition
- * 
- * <p>
- * This class corresponds to I18N string definitions which use external files to store the actual
- * string.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-@SuppressWarnings( "serial" )
-@XStreamAlias( "from-file" )
-public class FileString
-		extends StringDefinition
-{
-	/** The name of the file which contains the string's text */
-	@XStreamAsAttribute
-	private String source;
-
-
-	/**
-	 * Verify an external string definition
-	 * 
-	 * <p>
-	 * Make sure that the definition actually includes the name of the file to load the string from.
-	 */
-	@Override
-	public void verifyData( )
-			throws DataImportException
-	{
-		super.verifyData( );
-		if ( this.source == null || "".equals( this.source.trim( ) ) ) {
-			throw new DataImportException( "Missing file name for string definition '" + this.getId( ) + "'" );
-		}
-	}
-
-
-	/**
-	 * Load the string
-	 * 
-	 * <p>
-	 * This implementation opens the file defined as the source of the string's text, reads it then
-	 * returns it.
-	 * 
-	 * @throws DataImportException
-	 *             if the file cannot be opened or read from
-	 */
-	@Override
-	public String getString( )
-			throws DataImportException
-	{
-		File source = getSourceFile( );
-
-		StringBuilder sBuilder = new StringBuilder( );
-		try {
-			BufferedReader in = new BufferedReader( new FileReader( source ) );
-			try {
-				String str;
-				while ( ( str = in.readLine( ) ) != null ) {
-					sBuilder.append( str );
-					sBuilder.append( "\n" );
-				}
-			} finally {
-				in.close( );
-			}
-		} catch ( IOException e ) {
-			throw new DataImportException( "Could not read from " + source.getPath( ) , e );
-		}
-
-		return sBuilder.toString( );
-	}
-
-
-	/**
-	 * Access the source file
-	 * 
-	 * <p>
-	 * Create the source file instance using the path to the data file the current instance was read
-	 * from as the base directory.
-	 * 
-	 * @return the source file
-	 */
-	private File getSourceFile( )
-	{
-		File parentDirectory = this.getReadFrom( ).getParentFile( );
-		if ( parentDirectory == null ) {
-			parentDirectory = new File( "." );
-		}
-		return new File( parentDirectory , this.source ).getAbsoluteFile( );
-	}
-}
diff --git a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/data/i18n/I18NText.java b/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/data/i18n/I18NText.java
deleted file mode 100644
index 13cf4da..0000000
--- a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/data/i18n/I18NText.java
+++ /dev/null
@@ -1,120 +0,0 @@
-package com.deepclone.lw.cli.xmlimport.data.i18n;
-
-
-import java.io.File;
-import java.io.Serializable;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-
-import com.deepclone.lw.cli.xmlimport.data.DataImportException;
-import com.deepclone.lw.cli.xmlimport.data.ImportableData;
-import com.thoughtworks.xstream.annotations.XStreamAlias;
-import com.thoughtworks.xstream.annotations.XStreamImplicit;
-
-
-
-/**
- * I18N text data
- * 
- * <p>
- * This class represents the contents of the I18N text definitions file. It contains a list of
- * language definitions.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-@SuppressWarnings( "serial" )
-@XStreamAlias( "lw-text-data" )
-public class I18NText
-		extends ImportableData
-		implements Serializable , Iterable< LanguageDefinition >
-{
-	/** All present language definitions */
-	@XStreamImplicit( itemFieldName = "language" )
-	private List< LanguageDefinition > languages = new LinkedList< LanguageDefinition >( );
-
-
-	/**
-	 * Set the source file
-	 * 
-	 * <p>
-	 * Update the definition's own source file, then update all language definitions.
-	 */
-	@Override
-	public void setReadFrom( File readFrom )
-	{
-		super.setReadFrom( readFrom );
-		for ( LanguageDefinition languageDefinition : this.languages ) {
-			languageDefinition.setReadFrom( readFrom );
-		}
-	}
-
-
-	/**
-	 * Verify I18N text data
-	 * 
-	 * <p>
-	 * Check each definition, then make sure both identifiers and language names are unique.
-	 */
-	@Override
-	public void verifyData( )
-			throws DataImportException
-	{
-		if ( this.languages == null || this.languages.isEmpty( ) ) {
-			throw new DataImportException( "No language definitions" );
-		}
-
-		HashSet< String > identifiers = new HashSet< String >( );
-		HashSet< String > names = new HashSet< String >( );
-		for ( LanguageDefinition definition : this.languages ) {
-			definition.verifyData( );
-			this.checkUniqueItem( "identifier" , identifiers , definition.getId( ) );
-			this.checkUniqueItem( "name" , names , definition.getName( ) );
-		}
-	}
-
-
-	/**
-	 * Check that some part of the definition is unique
-	 * 
-	 * <p>
-	 * This helper method is used by {@link #verifyData()} to make sure that names and identifiers
-	 * are unique.
-	 * 
-	 * @param exceptionText
-	 *            the name of the item
-	 * @param existing
-	 *            the set of existing items
-	 * @param value
-	 *            the item's value
-	 * 
-	 * @throws DataImportException
-	 *             if the item's value is already present in the set of existing items
-	 */
-	private void checkUniqueItem( String exceptionText , HashSet< String > existing , String value )
-			throws DataImportException
-	{
-		if ( existing.contains( value ) ) {
-			throw new DataImportException( "Duplicate language " + exceptionText + " '" + value + "'" );
-		}
-		existing.add( value );
-	}
-
-
-	/**
-	 * Language definition iterator
-	 * 
-	 * <p>
-	 * Grant access to the list of languages in read-only mode.
-	 * 
-	 * @return a read-only iterator on the list of languages.
-	 */
-	@Override
-	public Iterator< LanguageDefinition > iterator( )
-	{
-		return Collections.unmodifiableList( this.languages ).iterator( );
-	}
-
-}
diff --git a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/data/i18n/InlineString.java b/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/data/i18n/InlineString.java
deleted file mode 100644
index 01e497e..0000000
--- a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/data/i18n/InlineString.java
+++ /dev/null
@@ -1,55 +0,0 @@
-package com.deepclone.lw.cli.xmlimport.data.i18n;
-
-
-import com.deepclone.lw.cli.xmlimport.data.DataImportException;
-import com.thoughtworks.xstream.annotations.XStreamAlias;
-
-
-
-/**
- * An in-line string definition
- * 
- * <p>
- * This class corresponds to string definitions which are stored directly inside the XML data file.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-@SuppressWarnings( "serial" )
-@XStreamAlias( "inline-string" )
-public class InlineString
-		extends StringDefinition
-{
-
-	/** The string's text */
-	private String value;
-
-
-	/**
-	 * Verify the in-line string definition
-	 * 
-	 * <p>
-	 * Make sure that the definition actually contains a string.
-	 */
-	@Override
-	public void verifyData( )
-			throws DataImportException
-	{
-		super.verifyData( );
-
-		if ( this.value == null || "".equals( this.value.trim( ) ) ) {
-			throw new DataImportException( "Missing or empty in-line string definition '" + this.getId( ) + "'" );
-		}
-	}
-
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see StringDefinition#getString()
-	 */
-	@Override
-	public String getString( )
-	{
-		return this.value;
-	}
-}
\ No newline at end of file
diff --git a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/data/i18n/LanguageDefinition.java b/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/data/i18n/LanguageDefinition.java
deleted file mode 100644
index 77b17d1..0000000
--- a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/data/i18n/LanguageDefinition.java
+++ /dev/null
@@ -1,145 +0,0 @@
-package com.deepclone.lw.cli.xmlimport.data.i18n;
-
-
-import java.io.File;
-import java.io.Serializable;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-
-import com.deepclone.lw.cli.xmlimport.data.DataImportException;
-import com.deepclone.lw.cli.xmlimport.data.ImportableData;
-import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
-import com.thoughtworks.xstream.annotations.XStreamImplicit;
-
-
-
-/**
- * A language definition
- * 
- * <p>
- * Language definitions for the I18N text importer possess an identifier and a name. In addition,
- * they may contain any amount of string definitions.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-@SuppressWarnings( "serial" )
-public class LanguageDefinition
-		extends ImportableData
-		implements Serializable , Iterable< StringDefinition >
-{
-	/** The language's identifier */
-	@XStreamAsAttribute
-	private String id;
-
-	/** The language's name */
-	@XStreamAsAttribute
-	private String name;
-
-	/** All strings defined for this language */
-	@XStreamImplicit
-	private final List< StringDefinition > strings = new LinkedList< StringDefinition >( );
-
-
-	/**
-	 * Set the source file
-	 * 
-	 * <p>
-	 * Update the definition's own source file, then update all string definitions.
-	 */
-	@Override
-	public void setReadFrom( File readFrom )
-	{
-		super.setReadFrom( readFrom );
-		for ( StringDefinition definition : this.strings ) {
-			definition.setReadFrom( readFrom );
-		}
-	}
-
-
-	/**
-	 * Validate the language definition
-	 * 
-	 * <p>
-	 * Make sure that all definition characteristics are properly defined, then check all strings
-	 * and make sure they are unique.
-	 */
-	@Override
-	public void verifyData( )
-			throws DataImportException
-	{
-		if ( this.id == null || "".equals( this.id.trim( ) ) ) {
-			throw new DataImportException( "Missing language identifier" );
-		}
-		if ( this.name == null || "".equals( this.name.trim( ) ) ) {
-			throw new DataImportException( "Missing language name for identifier '" + this.id + "'" );
-		}
-		if ( this.strings == null || this.strings.isEmpty( ) ) {
-			throw new DataImportException( "No strings defined for language '" + this.id + "'" );
-		}
-
-		this.checkStringDefinitions( );
-	}
-
-
-	/**
-	 * Check all string definitions
-	 * 
-	 * <p>
-	 * Iterate over all included string definitions, validating them and making sure they all have
-	 * unique identifiers.
-	 * 
-	 * @throws DataImportException
-	 *             if a string definition is invalid or if string identifiers contain duplicates.
-	 */
-	private void checkStringDefinitions( )
-			throws DataImportException
-	{
-		HashSet< String > strings = new HashSet< String >( );
-		for ( StringDefinition definition : this.strings ) {
-			definition.verifyData( );
-
-			String stringId = definition.getId( );
-			if ( strings.contains( stringId ) ) {
-				throw new DataImportException( "In language '" + this.id + "': duplicate string '" + stringId + "'" );
-			}
-			strings.add( stringId );
-		}
-	}
-
-
-	/** @return the language's identifier */
-	public String getId( )
-	{
-		return this.id;
-	}
-
-
-	/** @return the language's name */
-	public String getName( )
-	{
-		return this.name;
-	}
-
-
-	/**
-	 * Iterate over all string definitions
-	 * 
-	 * <p>
-	 * This method grants access to the list of string definitions in read-only mode.
-	 * 
-	 * <p>
-	 * <strong>Warning:</strong> this method should not be called if {@link #containsStrings()}
-	 * returns <code>false</code>.
-	 * 
-	 * @return the read-only string definition iterator
-	 */
-	@Override
-	public Iterator< StringDefinition > iterator( )
-	{
-		return Collections.unmodifiableList( this.strings ).iterator( );
-	}
-
-}
diff --git a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/data/i18n/StringDefinition.java b/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/data/i18n/StringDefinition.java
deleted file mode 100644
index 1e2701a..0000000
--- a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/data/i18n/StringDefinition.java
+++ /dev/null
@@ -1,73 +0,0 @@
-package com.deepclone.lw.cli.xmlimport.data.i18n;
-
-
-import java.io.Serializable;
-import java.util.regex.Pattern;
-
-import com.deepclone.lw.cli.xmlimport.data.DataImportException;
-import com.deepclone.lw.cli.xmlimport.data.ImportableData;
-import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
-
-
-
-/**
- * A string definition
- * 
- * <p>
- * This class is the base for both types of string definitions used by the initial I18N text
- * importer. String definitions always contain an identifier, and it is always possible to obtain
- * the actual text they contain.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-@SuppressWarnings( "serial" )
-public abstract class StringDefinition
-		extends ImportableData
-		implements Serializable
-{
-	/** Pattern followed by string identifiers */
-	private static final Pattern identifierCheck = Pattern.compile( "^[a-z][a-z0-9]*([A-Z][a-z0-9]*)*$" );
-
-	/** The string's identifier */
-	@XStreamAsAttribute
-	private String id;
-
-
-	/**
-	 * Check a string definition's identifier
-	 * 
-	 * <p>
-	 * Make sure that a string definition's identifier is both present and valid.
-	 */
-	@Override
-	public void verifyData( )
-			throws DataImportException
-	{
-		if ( this.id == null ) {
-			throw new DataImportException( "Missing string identifier" );
-		} else if ( !identifierCheck.matcher( this.id ).find( ) ) {
-			throw new DataImportException( "Invalid string identifier '" + this.id + "'" );
-		}
-	}
-
-
-	/** @return the string's identifier */
-	public final String getId( )
-	{
-		return this.id;
-	}
-
-
-	/**
-	 * This method must be overridden to provide a way of reading the actual text of the string that
-	 * is being defined.
-	 * 
-	 * @return the string's text
-	 * 
-	 * @throws DataImportException
-	 *             if accessing the string's actual text fails
-	 */
-	public abstract String getString( )
-			throws DataImportException;
-
-}
diff --git a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/data/resources/BasicResource.java b/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/data/resources/BasicResource.java
deleted file mode 100644
index 86a8442..0000000
--- a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/data/resources/BasicResource.java
+++ /dev/null
@@ -1,105 +0,0 @@
-package com.deepclone.lw.cli.xmlimport.data.resources;
-
-
-import com.deepclone.lw.cli.xmlimport.data.DataImportException;
-import com.deepclone.lw.cli.xmlimport.data.ImportableData;
-import com.thoughtworks.xstream.annotations.XStreamAlias;
-import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
-
-
-
-/**
- * A Basic Resource
- * 
- * <p>
- * This class is the base for all resource classes providing a name, description, category and
- * weight. In certain cases the category can be null. It provides a method to verify that data has
- * been imported successfully.
- * 
- * @author <a href="mailto:tim@mitheren.com">T. Rosser</a>
- */
-@SuppressWarnings( "serial" )
-@XStreamAlias( "basic-resource" )
-public class BasicResource
-		extends ImportableData
-{
-	/** The resource's name */
-	@XStreamAsAttribute
-	private String name;
-
-	/** The resource's description */
-	@XStreamAsAttribute
-	private String description;
-
-	/**
-	 * The resource's category
-	 * 
-	 * <p>
-	 * Can be null for resources that do not belong to a category
-	 */
-	@XStreamAsAttribute
-	private String category;
-
-	/**
-	 * The resource's weight
-	 * 
-	 * <p>
-	 * Used when sorting resources and resource categories.
-	 */
-	@XStreamAsAttribute
-	private Integer weight; // Is int enough?
-
-
-	/**
-	 * Check a resource's data
-	 * 
-	 * <p>
-	 * Make sure that a resource's properties are both present and valid.
-	 */
-	@Override
-	public void verifyData( )
-			throws DataImportException
-	{
-		if ( this.name == null || "".equals( this.name.trim( ) ) ) {
-			throw new DataImportException( "Missing name string" );
-		}
-		if ( this.description == null || "".equals( this.description.trim( ) ) ) {
-			throw new DataImportException( "Missing description string" );
-		}
-		if ( this.category != null && "".equals( this.category.trim( ) ) ) {
-			throw new DataImportException( "Category invalid" );
-		}
-		if ( this.weight == null ) {
-			throw new DataImportException( "Missing weight" );
-		}
-	}
-
-
-	/** @return the resource's name */
-	public String getName( )
-	{
-		return this.name;
-	}
-
-
-	/** @return the resource's description */
-	public String getDescription( )
-	{
-		return this.description;
-	}
-
-
-	/** @return the resource's category */
-	public String getCategory( )
-	{
-		return this.category;
-	}
-
-
-	/** @return the resource's weight */
-	public Integer getWeight( )
-	{
-		return this.weight;
-	}
-
-}
diff --git a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/data/resources/NaturalResource.java b/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/data/resources/NaturalResource.java
deleted file mode 100644
index 7929d13..0000000
--- a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/data/resources/NaturalResource.java
+++ /dev/null
@@ -1,119 +0,0 @@
-package com.deepclone.lw.cli.xmlimport.data.resources;
-
-
-import com.deepclone.lw.cli.xmlimport.data.DataImportException;
-import com.thoughtworks.xstream.annotations.XStreamAlias;
-import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
-
-
-
-/**
- * A Natural Resource
- * 
- * <p>
- * This class represents naturally occurring resources. As well as extending {@link BasicResource}
- * it contains the presence-probability, quantity, difficulty and recovery of a resource and a
- * method to verify the data of these properties.
- * 
- * @author <a href="mailto:tim@mitheren.com">T. Rosser</a>
- */
-@SuppressWarnings( "serial" )
-@XStreamAlias( "natural-resource" )
-public class NaturalResource
-		extends BasicResource
-{
-	/**
-	 * The resource's presence-probability
-	 * 
-	 * <p>
-	 * Used by the universe generator to decide whether to add this type of resource to a particular
-	 * planet or not.
-	 */
-	@XStreamAlias( "presence-probability" )
-	@XStreamAsAttribute
-	private Double presenceProbability;
-
-	/** The resource's quantity */
-	@XStreamAlias( "quantity" )
-	private ResourceParameter quantity;
-
-	/**
-	 * The resource's difficulty
-	 * 
-	 * <p>
-	 * The difficulty of extracting the resource.
-	 */
-	@XStreamAlias( "difficulty" )
-	private ResourceParameter difficulty;
-
-	/**
-	 * The resource's recovery
-	 * 
-	 * <p>
-	 * The recovery rate of the resource.
-	 */
-	@XStreamAlias( "recovery" )
-	private ResourceParameter recovery;
-
-
-	/**
-	 * Check a resource's data
-	 * 
-	 * <p>
-	 * Make sure that a resource's properties are both present and valid. Calls the base class'
-	 * verifyData() method to check all of the data.
-	 */
-	@Override
-	public void verifyData( )
-			throws DataImportException
-	{
-		super.verifyData( );
-
-		if ( this.presenceProbability == null ) {
-			throw new DataImportException( "Missing presence-probability" );
-		}
-		if ( this.quantity == null ) {
-			throw new DataImportException( "Missing quantity" );
-		}
-		this.quantity.verifyData( "quantity" );
-
-		if ( this.difficulty == null ) {
-			throw new DataImportException( "Missing difficulty" );
-		}
-		this.difficulty.verifyData( "difficulty" );
-
-		if ( this.recovery == null ) {
-			throw new DataImportException( "Missing recovery" );
-		}
-		this.recovery.verifyData( "recovery" );
-
-	}
-
-
-	/** @return the resource's presence-probability */
-	public Double getPresenceProbability( )
-	{
-		return this.presenceProbability;
-	}
-
-
-	/** @return the resource's quantity */
-	public ResourceParameter getQuantity( )
-	{
-		return this.quantity;
-	}
-
-
-	/** @return the resource's difficulty */
-	public ResourceParameter getDifficulty( )
-	{
-		return this.difficulty;
-	}
-
-
-	/** @return the resource's recovery */
-	public ResourceParameter getRecovery( )
-	{
-		return this.recovery;
-	}
-}
diff --git a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/data/resources/ResourceParameter.java b/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/data/resources/ResourceParameter.java
deleted file mode 100644
index 6d7c6fe..0000000
--- a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/data/resources/ResourceParameter.java
+++ /dev/null
@@ -1,65 +0,0 @@
-package com.deepclone.lw.cli.xmlimport.data.resources;
-
-
-import com.deepclone.lw.cli.xmlimport.data.DataImportException;
-import com.deepclone.lw.cli.xmlimport.data.ImportableData;
-import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
-
-
-
-/**
- * Resource property parameter
- * 
- * <p>
- * This class represents the average and deviation of various properties of a resource.
- * 
- * @author <a href="mailto:tim@mitheren.com">T. Rosser</a>
- */
-@SuppressWarnings( "serial" )
-public class ResourceParameter
-		extends ImportableData
-{
-	/** The property's average */
-	@XStreamAsAttribute
-	private Double average;
-
-	/** The property's deviation */
-	@XStreamAsAttribute
-	private Double deviation;
-
-
-	/**
-	 * Check the property's data
-	 * 
-	 * <p>
-	 * Make sure that a average and deviation are present.
-	 * 
-	 * @param property
-	 *            the name of the property
-	 */
-	public void verifyData( String property )
-			throws DataImportException
-	{
-		if ( this.average == null ) {
-			throw new DataImportException( "Missing average for " + property );
-		}
-		if ( this.deviation == null ) {
-			throw new DataImportException( "Missing deviation for " + property );
-		}
-	}
-
-
-	/** @return the property's average */
-	public Double getAverage( )
-	{
-		return this.average;
-	}
-
-
-	/** @return the property's deviation */
-	public Double getDeviation( )
-	{
-		return this.deviation;
-	}
-
-}
diff --git a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/data/resources/Resources.java b/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/data/resources/Resources.java
deleted file mode 100644
index ad8b907..0000000
--- a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/data/resources/Resources.java
+++ /dev/null
@@ -1,96 +0,0 @@
-package com.deepclone.lw.cli.xmlimport.data.resources;
-
-
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-
-import com.deepclone.lw.cli.xmlimport.data.DataImportException;
-import com.deepclone.lw.cli.xmlimport.data.ImportableData;
-import com.thoughtworks.xstream.annotations.XStreamAlias;
-import com.thoughtworks.xstream.annotations.XStreamImplicit;
-
-
-
-/**
- * Resource Data
- * 
- * <p>
- * This class represents the contents of the resource text file. It contains a list of resource
- * definitions.
- * 
- * @author <a href="mailto:tim@mitheren.com">T. Rosser</a>
- */
-@SuppressWarnings( "serial" )
-@XStreamAlias( "lw-resources" )
-public class Resources
-		extends ImportableData
-		implements Iterable< BasicResource >
-{
-	/** All present resource definitions */
-	@XStreamImplicit
-	private final List< BasicResource > resources = new LinkedList< BasicResource >( );
-
-
-	/**
-	 * Checks the resource data
-	 * 
-	 * <p>
-	 * Checks each definition and ensures they are all unique.
-	 */
-	@Override
-	public void verifyData( )
-			throws DataImportException
-	{
-		if ( this.resources == null ) {
-			throw new DataImportException( "No resource definitions" );
-		}
-
-		HashSet< String > names = new HashSet< String >( );
-		for ( BasicResource resource : this.resources ) {
-			resource.verifyData( );
-			this.checkUniqueItem( names , resource.getName( ) );
-		}
-	}
-
-
-	/**
-	 * Checks that the name of the resource is unique
-	 * 
-	 * <p>
-	 * This helper method is used by {@link #verifyData()} to make sure resource names are unique.
-	 * 
-	 * @param existing
-	 *            the existing set of items
-	 * @param value
-	 *            the item's value
-	 * 
-	 * @throws DataImportException
-	 *             if the item's value is already present in the set of existing items
-	 */
-	public void checkUniqueItem( HashSet< String > existing , String value )
-			throws DataImportException
-	{
-		if ( existing.contains( value ) ) {
-			throw new DataImportException( "Duplicate resource name '" + value + "'" );
-		}
-		existing.add( value );
-	}
-
-
-	/**
-	 * Resource definition iterator
-	 * 
-	 * <p>
-	 * Grant access to the list of resources in read-only mode.
-	 * 
-	 * @return a read-only iterator on the list of resources.
-	 */
-	@Override
-	public Iterator< BasicResource > iterator( )
-	{
-		return Collections.unmodifiableList( this.resources ).iterator( );
-	}
-}
diff --git a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/data/resources/UOCResourceErrorCode.java b/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/data/resources/UOCResourceErrorCode.java
deleted file mode 100644
index 47dbed7..0000000
--- a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/data/resources/UOCResourceErrorCode.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package com.deepclone.lw.cli.xmlimport.data.resources;
-
-import com.deepclone.lw.cli.ImportResources;
-
-
-/**
- * Enum representing the error codes returned by the uoc_* stored procedures in
- * {@link ImportResources}
- * 
- * @author <a href="tim@mitheren.com">T. Rosser</a>
- * 
- */
-public enum UOCResourceErrorCode {
-	CREATED ,
-	UPDATED ,
-	BAD_TYPE ,
-	BAD_STRINGS ,
-	BAD_VALUE ,
-	DUP_DESCR;
-}
diff --git a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/data/techs/Technologies.java b/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/data/techs/Technologies.java
deleted file mode 100644
index 842f64c..0000000
--- a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/data/techs/Technologies.java
+++ /dev/null
@@ -1,98 +0,0 @@
-package com.deepclone.lw.cli.xmlimport.data.techs;
-
-
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-
-import com.deepclone.lw.cli.xmlimport.data.DataImportException;
-import com.deepclone.lw.cli.xmlimport.data.ImportableData;
-import com.thoughtworks.xstream.annotations.XStreamAlias;
-import com.thoughtworks.xstream.annotations.XStreamImplicit;
-
-
-
-/**
- * Technology definitions data
- * 
- * <p>
- * This class represents the contents of a technology definition XML file. It contains a list of
- * technology definitions.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-@SuppressWarnings( "serial" )
-@XStreamAlias( "lw-tech-graph" )
-public class Technologies
-		extends ImportableData
-		implements Iterable< Technology >
-{
-	/** All present technology definitions */
-	@XStreamImplicit( itemFieldName = "technology" )
-	private final List< Technology > technologies = new LinkedList< Technology >( );
-
-
-	/**
-	 * Check the technology data
-	 * 
-	 * <p>
-	 * Check whether there is a list of technologies, then check each definition to make sure that
-	 * it is valid and that its name is unique.
-	 */
-	@Override
-	public void verifyData( )
-			throws DataImportException
-	{
-		if ( this.technologies == null ) {
-			throw new DataImportException( "No technology definitions" );
-		}
-
-		HashSet< String > names = new HashSet< String >( );
-		for ( Technology tech : this.technologies ) {
-			tech.verifyData( );
-			this.checkUniqueItem( names , tech.getName( ) );
-		}
-	}
-
-
-	/**
-	 * Checks that the name of a technology is unique
-	 * 
-	 * <p>
-	 * This helper method is used by {@link #verifyData()} to make sure technology names are unique.
-	 * 
-	 * @param existing
-	 *            the existing set of names
-	 * @param value
-	 *            the name to check
-	 * 
-	 * @throws DataImportException
-	 *             if the name is already present in the set of existing names
-	 */
-	public void checkUniqueItem( HashSet< String > existing , String value )
-			throws DataImportException
-	{
-		if ( existing.contains( value ) ) {
-			throw new DataImportException( "Duplicate technology name '" + value + "'" );
-		}
-		existing.add( value );
-	}
-
-
-	/**
-	 * Technology definition iterator
-	 * 
-	 * <p>
-	 * Grant access to the list of technologies in read-only mode.
-	 * 
-	 * @return a read-only iterator on the list of technologies.
-	 */
-	@Override
-	public Iterator< Technology > iterator( )
-	{
-		return Collections.unmodifiableList( this.technologies ).iterator( );
-	}
-
-}
diff --git a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/data/techs/Technology.java b/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/data/techs/Technology.java
deleted file mode 100644
index 49b6368..0000000
--- a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/data/techs/Technology.java
+++ /dev/null
@@ -1,183 +0,0 @@
-package com.deepclone.lw.cli.xmlimport.data.techs;
-
-
-import java.util.Collections;
-import java.util.LinkedList;
-import java.util.List;
-
-import com.deepclone.lw.cli.xmlimport.data.DataImportException;
-import com.deepclone.lw.cli.xmlimport.data.ImportableData;
-import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
-import com.thoughtworks.xstream.annotations.XStreamImplicit;
-
-
-
-/**
- * A technology definition
- * 
- * <p>
- * This class represents a technology definition that can be imported from the data file. It
- * contains all required technology attributes, as well as a list of strings for the dependencies.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-@SuppressWarnings( "serial" )
-public class Technology
-		extends ImportableData
-{
-
-	/** Identifier of the name string */
-	@XStreamAsAttribute
-	private String name;
-
-	/** Identifier of the category string */
-	@XStreamAsAttribute
-	private String category;
-
-	/** Identifier of the description string */
-	@XStreamAsAttribute
-	private String description;
-
-	/** Identifier of the string to display on technology discovery */
-	@XStreamAsAttribute
-	private String discovery;
-
-	/** Monetary cost of the technology */
-	@XStreamAsAttribute
-	private Long cost;
-
-	/** Required amount of research points */
-	@XStreamAsAttribute
-	private Long points;
-
-	/** List of technology name string identifiers describing the dependencies */
-	@XStreamImplicit( itemFieldName = "depends-on" )
-	private final List< String > dependencies = new LinkedList< String >( );
-
-
-	/**
-	 * Technology definition verifier
-	 * 
-	 * <p>
-	 * Make sure that all technology definition fields are both present and valid. If dependencies
-	 * exist, also verify the names' validity.
-	 */
-	@Override
-	public void verifyData( )
-			throws DataImportException
-	{
-		if ( this.name == null || "".equals( this.name.trim( ) ) ) {
-			throw new DataImportException( "Missing name string" );
-		}
-		if ( this.category == null || "".equals( this.category.trim( ) ) ) {
-			throw new DataImportException( "Missing category string in " + this.name );
-		}
-		if ( this.description == null || "".equals( this.description.trim( ) ) ) {
-			throw new DataImportException( "Missing description string in " + this.name );
-		}
-		if ( this.discovery == null || "".equals( this.discovery.trim( ) ) ) {
-			throw new DataImportException( "Missing discovery string in " + this.name );
-		}
-
-		if ( this.points == null ) {
-			throw new DataImportException( "Missing research points in " + this.name );
-		} else if ( this.points <= 0 ) {
-			throw new DataImportException( "Invalid research points in " + this.name );
-		}
-
-		if ( this.cost == null ) {
-			throw new DataImportException( "Missing cost in " + this.name );
-		} else if ( this.cost <= 0 ) {
-			throw new DataImportException( "Invalid cost in " + this.name );
-		}
-
-		if ( this.dependencies != null ) {
-			for ( String dep : this.dependencies ) {
-				if ( dep == null || "".equals( dep.trim( ) ) ) {
-					throw new DataImportException( "Empty dependency name in " + this.name );
-				}
-			}
-		}
-	}
-
-
-	/**
-	 * Gets the identifier of the name string.
-	 * 
-	 * @return the identifier of the name string
-	 */
-	public String getName( )
-	{
-		return this.name;
-	}
-
-
-	/**
-	 * Gets the identifier of the category string.
-	 * 
-	 * @return the identifier of the category string
-	 */
-	public String getCategory( )
-	{
-		return this.category;
-	}
-
-
-	/**
-	 * Gets the identifier of the description string.
-	 * 
-	 * @return the identifier of the description string
-	 */
-	public String getDescription( )
-	{
-		return this.description;
-	}
-
-
-	/**
-	 * Gets the identifier of the string to display on technology discovery.
-	 * 
-	 * @return the identifier of the string to display on technology discovery
-	 */
-	public String getDiscovery( )
-	{
-		return this.discovery;
-	}
-
-
-	/**
-	 * Gets the monetary cost of the technology.
-	 * 
-	 * @return the monetary cost of the technology
-	 */
-	public Long getCost( )
-	{
-		return this.cost;
-	}
-
-
-	/**
-	 * Gets the required amount of research points.
-	 * 
-	 * @return the required amount of research points
-	 */
-	public Long getPoints( )
-	{
-		return this.points;
-	}
-
-
-	/**
-	 * Gets the list of technology name string identifiers describing the dependencies.
-	 * 
-	 * @return the list of technology name string identifiers describing the dependencies
-	 */
-	public List< String > getDependencies( )
-	{
-		if ( this.dependencies == null ) {
-			return Collections.emptyList( );
-		}
-		return Collections.unmodifiableList( this.dependencies );
-	}
-
-}
diff --git a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/data/techs/TechnologyDefinitionResult.java b/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/data/techs/TechnologyDefinitionResult.java
deleted file mode 100644
index e7491bb..0000000
--- a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/xmlimport/data/techs/TechnologyDefinitionResult.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package com.deepclone.lw.cli.xmlimport.data.techs;
-
-
-/**
- * Return codes for technology definition manipulation stored procedures
- * 
- * <p>
- * This enumeration represents the various values which can be returned by the stored procedures
- * which manipulate technology definitions and technology dependencies.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-public enum TechnologyDefinitionResult {
-
-	/** The technology definition or dependency was created */
-	CREATED ,
-
-	/** The technology definition was updated */
-	UPDATED ,
-
-	/** The dependency was deleted */
-	DELETED ,
-
-	/** The specified dependency does not exist */
-	MISSING ,
-
-	/** One (or more) of the numeric parameters is invalid */
-	BAD_VALUE ,
-
-	/**
-	 * The name, description, discovery or category string identifiers were not valid string
-	 * identifiers.
-	 */
-	BAD_STRINGS ,
-
-	/**
-	 * The specified description and/or discovery string was in use by another technology.
-	 */
-	DUP_STRING ,
-
-	/** The dependency would cause a cycle */
-	CYCLE ,
-
-	/** The dependency would be redundant */
-	REDUNDANT
-
-}
diff --git a/legacyworlds-server-main/src/main/resources/configuration/game.xml b/legacyworlds-server-main/src/main/resources/configuration/game.xml
deleted file mode 100644
index 65d25e6..0000000
--- a/legacyworlds-server-main/src/main/resources/configuration/game.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<beans xmlns="http://www.springframework.org/schema/beans"
-	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	xsi:schemaLocation="
-                        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
-
-	<!-- ========================================================== -->
-	<!-- Spring configuration loader for all "real" game components -->
-	<!-- ========================================================== -->
-	<import resource="game/events.xml" />
-	<import resource="game/resources.xml" />
-	<import resource="game/technologies.xml" />
-	<import resource="game/updates.xml" />
-
-</beans>
\ No newline at end of file
diff --git a/legacyworlds-server-main/src/main/resources/configuration/meta.xml b/legacyworlds-server-main/src/main/resources/configuration/meta.xml
deleted file mode 100644
index 69924f6..0000000
--- a/legacyworlds-server-main/src/main/resources/configuration/meta.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<beans xmlns="http://www.springframework.org/schema/beans"
-	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	xsi:schemaLocation="
-                        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
-
-	<!-- ================================================= -->
-	<!-- Spring configuration loader for "meta" components -->
-	<!-- ================================================= -->
-	<import resource="meta/accounts.xml" />
-	<import resource="meta/bt.xml" />
-	<import resource="meta/eventlog.xml" />
-	<import resource="meta/i18n.xml" />
-	<import resource="meta/mailer.xml" />
-	<import resource="meta/naming.xml" />
-	<import resource="meta/sessions.xml" />
-	<import resource="meta/system.xml" />
-
-</beans>
\ No newline at end of file
diff --git a/legacyworlds-server-main/src/main/resources/configuration/transactions.xml b/legacyworlds-server-main/src/main/resources/configuration/transactions.xml
deleted file mode 100644
index 3e20eb9..0000000
--- a/legacyworlds-server-main/src/main/resources/configuration/transactions.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<beans xmlns="http://www.springframework.org/schema/beans"
-	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx"
-	xsi:schemaLocation="
-                        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
-                        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd">
-
-	<bean id="transactionManager"
-		class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
-		<property name="dataSource" ref="dataSource" />
-	</bean>
-
-	<tx:annotation-driven transaction-manager="transactionManager" />
-
-</beans>
diff --git a/legacyworlds-server-main/src/main/resources/lw-server.xml b/legacyworlds-server-main/src/main/resources/lw-server.xml
deleted file mode 100644
index 07a0a74..0000000
--- a/legacyworlds-server-main/src/main/resources/lw-server.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<beans xmlns="http://www.springframework.org/schema/beans"
-	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
-	xsi:schemaLocation="
-                        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
-                        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">
-
-	<!-- ================================================== -->
-	<!-- Legacy Worlds server - Spring configuration loader -->
-	<!-- ================================================== -->
-
-	<!-- Use annotations to determine component wiring -->
-	<context:annotation-config />
-
-	<!-- Transaction manager -->
-	<import resource="configuration/transactions.xml" />
-
-	<!-- Server terminator -->
-	<bean id="terminator" class="com.deepclone.lw.srv.ServerTerminatorBean" />
-
-	<!-- "Meta" components -->
-	<import resource="configuration/meta.xml" />
-
-	<!-- Session types and command handlers -->
-	<import resource="configuration/session-types.xml" />
-
-	<!-- Load both the "final" game file and the "simple" implementation from 
-		B6M1. -->
-	<import resource="configuration/game.xml" />
-	<import resource="configuration/simple.xml" />
-
-</beans>
diff --git a/legacyworlds-server-main/src/test/java/.empty b/legacyworlds-server-main/src/test/java/.empty
deleted file mode 100644
index e69de29..0000000
diff --git a/legacyworlds-server-main/src/test/resources/.empty b/legacyworlds-server-main/src/test/resources/.empty
deleted file mode 100644
index e69de29..0000000
diff --git a/legacyworlds-server-tests/TestFiles/i18n-external-file/test.txt b/legacyworlds-server-tests/TestFiles/i18n-external-file/test.txt
deleted file mode 100644
index 273c1a9..0000000
--- a/legacyworlds-server-tests/TestFiles/i18n-external-file/test.txt
+++ /dev/null
@@ -1 +0,0 @@
-This is a test.
\ No newline at end of file
diff --git a/legacyworlds-server-tests/TestFiles/i18n-loader/bad-contents.xml b/legacyworlds-server-tests/TestFiles/i18n-loader/bad-contents.xml
deleted file mode 100644
index f33b821..0000000
--- a/legacyworlds-server-tests/TestFiles/i18n-loader/bad-contents.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<lw-text-data>
-
-	<does-not-exist />
-
-</lw-text-data>
\ No newline at end of file
diff --git a/legacyworlds-server-tests/TestFiles/i18n-loader/bad-data.xml b/legacyworlds-server-tests/TestFiles/i18n-loader/bad-data.xml
deleted file mode 100644
index aec5ebc..0000000
--- a/legacyworlds-server-tests/TestFiles/i18n-loader/bad-data.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<lw-text-data xmlns="http://www.deepclone.com/lw/b6/m1/i18n-text"
-	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	xsi:schemaLocation="http://www.deepclone.com/lw/b6/m1/i18n-text ../../../legacyworlds-server-main/data/i18n-text.xsd">
-
-	<language name="test" id="test">
-		<inline-string id="test">
-			<value />
-		</inline-string>
-	</language>
-
-</lw-text-data>
\ No newline at end of file
diff --git a/legacyworlds-server-tests/TestFiles/i18n-loader/bad-xml.xml b/legacyworlds-server-tests/TestFiles/i18n-loader/bad-xml.xml
deleted file mode 100644
index ee1d0ed..0000000
--- a/legacyworlds-server-tests/TestFiles/i18n-loader/bad-xml.xml
+++ /dev/null
@@ -1,2 +0,0 @@
-This is not an XML file, obviously.
-We'll make that even more confusing: <<<<<< & >>!!!
\ No newline at end of file
diff --git a/legacyworlds-server-tests/TestFiles/i18n-loader/good.xml b/legacyworlds-server-tests/TestFiles/i18n-loader/good.xml
deleted file mode 100644
index f1ca627..0000000
--- a/legacyworlds-server-tests/TestFiles/i18n-loader/good.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<lw-text-data xmlns="http://www.deepclone.com/lw/b6/m1/i18n-text"
-	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	xsi:schemaLocation="http://www.deepclone.com/lw/b6/m1/i18n-text ../../../legacyworlds-server-main/data/i18n-text.xsd">
-
-	<language name="test" id="test">
-	
-		<from-file id="test" source="test.txt" />
-
-	</language>
-
-</lw-text-data>
\ No newline at end of file
diff --git a/legacyworlds-server-tests/TestFiles/i18n-loader/test.txt b/legacyworlds-server-tests/TestFiles/i18n-loader/test.txt
deleted file mode 100644
index 30d74d2..0000000
--- a/legacyworlds-server-tests/TestFiles/i18n-loader/test.txt
+++ /dev/null
@@ -1 +0,0 @@
-test
\ No newline at end of file
diff --git a/legacyworlds-server-tests/TestFiles/resource-loader/bad-contents.xml b/legacyworlds-server-tests/TestFiles/resource-loader/bad-contents.xml
deleted file mode 100644
index 262c241..0000000
--- a/legacyworlds-server-tests/TestFiles/resource-loader/bad-contents.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<lw-resources>
-
-	<does-not-exist />
-
-</lw-resources>
\ No newline at end of file
diff --git a/legacyworlds-server-tests/TestFiles/resource-loader/bad-data.xml b/legacyworlds-server-tests/TestFiles/resource-loader/bad-data.xml
deleted file mode 100644
index 2209c73..0000000
--- a/legacyworlds-server-tests/TestFiles/resource-loader/bad-data.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<lw-resources xmlns="http://www.deepclone.com/lw/b6/m2/resources"
-		xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-		xsi:schemaLocation="http://www.deepclone.com/lw/b6/m2/resources
-resources.xsd">
-
-	<basic-resource /> 
-</lw-resources>
diff --git a/legacyworlds-server-tests/TestFiles/resource-loader/bad-xml.xml b/legacyworlds-server-tests/TestFiles/resource-loader/bad-xml.xml
deleted file mode 100644
index ee1d0ed..0000000
--- a/legacyworlds-server-tests/TestFiles/resource-loader/bad-xml.xml
+++ /dev/null
@@ -1,2 +0,0 @@
-This is not an XML file, obviously.
-We'll make that even more confusing: <<<<<< & >>!!!
\ No newline at end of file
diff --git a/legacyworlds-server-tests/TestFiles/resource-loader/good-data.xml b/legacyworlds-server-tests/TestFiles/resource-loader/good-data.xml
deleted file mode 100644
index 77a3e62..0000000
--- a/legacyworlds-server-tests/TestFiles/resource-loader/good-data.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<lw-resources xmlns="http://www.deepclone.com/lw/b6/m2/resources"
-	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	xsi:schemaLocation="http://www.deepclone.com/lw/b6/m2/resources
-resources.xsd">
-
-	<basic-resource name="money" description="moneyDescription"
-		weight="0" /> <!-- This could have a category="" as well -->
-
-	<natural-resource name="titanium" description="titaniumDescription"
-		category="minerals" weight="1" presence-probability="0.8">
-		<quantity average="5000" deviation="1500" />
-		<difficulty average="0.1" deviation="0.05" />
-		<recovery average="0.4" deviation="0.05" />
-	</natural-resource>
-
-</lw-resources>
\ No newline at end of file
diff --git a/legacyworlds-server-tests/TestFiles/technology-loader/bad-contents.xml b/legacyworlds-server-tests/TestFiles/technology-loader/bad-contents.xml
deleted file mode 100644
index 272dba0..0000000
--- a/legacyworlds-server-tests/TestFiles/technology-loader/bad-contents.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<lw-tech-graph>
-
-	<does-not-exist />
-
-</lw-tech-graph>
\ No newline at end of file
diff --git a/legacyworlds-server-tests/TestFiles/technology-loader/bad-data.xml b/legacyworlds-server-tests/TestFiles/technology-loader/bad-data.xml
deleted file mode 100644
index 584e660..0000000
--- a/legacyworlds-server-tests/TestFiles/technology-loader/bad-data.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<lw-tech-graph xmlns="http://www.deepclone.com/lw/b6/m2/tech-graph"
-	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	xsi:schemaLocation="http://www.deepclone.com/lw/b6/m2/tech-graph tech-graph.xsd">
-
-	<technology />
-
-</lw-tech-graph>
\ No newline at end of file
diff --git a/legacyworlds-server-tests/TestFiles/technology-loader/bad-xml.xml b/legacyworlds-server-tests/TestFiles/technology-loader/bad-xml.xml
deleted file mode 100644
index ee1d0ed..0000000
--- a/legacyworlds-server-tests/TestFiles/technology-loader/bad-xml.xml
+++ /dev/null
@@ -1,2 +0,0 @@
-This is not an XML file, obviously.
-We'll make that even more confusing: <<<<<< & >>!!!
\ No newline at end of file
diff --git a/legacyworlds-server-tests/TestFiles/technology-loader/good-data.xml b/legacyworlds-server-tests/TestFiles/technology-loader/good-data.xml
deleted file mode 100644
index 0cf7e8e..0000000
--- a/legacyworlds-server-tests/TestFiles/technology-loader/good-data.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<lw-tech-graph xmlns="http://www.deepclone.com/lw/b6/m2/tech-graph"
-	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	xsi:schemaLocation="http://www.deepclone.com/lw/b6/m2/tech-graph tech-graph.xsd">
-
-	<technology name="test" category="test" discovery="test"
-		description="test" cost="12" points="34" />
-
-</lw-tech-graph>
\ No newline at end of file
diff --git a/legacyworlds-server-tests/src/main/java/.empty b/legacyworlds-server-tests/src/main/java/.empty
deleted file mode 100644
index e69de29..0000000
diff --git a/legacyworlds-server-tests/src/main/resources/.empty b/legacyworlds-server-tests/src/main/resources/.empty
deleted file mode 100644
index e69de29..0000000
diff --git a/legacyworlds-server-tests/src/test/java/.empty b/legacyworlds-server-tests/src/test/java/.empty
deleted file mode 100644
index e69de29..0000000
diff --git a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/bt/es/TestBuildingsInformationMapper.java b/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/bt/es/TestBuildingsInformationMapper.java
deleted file mode 100644
index cb5209a..0000000
--- a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/bt/es/TestBuildingsInformationMapper.java
+++ /dev/null
@@ -1,83 +0,0 @@
-package com.deepclone.lw.beans.bt.es;
-
-
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.util.HashMap;
-
-import static org.junit.Assert.*;
-import org.junit.Before;
-import org.junit.Test;
-
-import com.deepclone.lw.beans.bt.es.data.BuildingsInformation;
-import com.deepclone.lw.testing.MockResultSet;
-
-
-
-/**
- * Tests for the {@link BuildingsInformationMapper} class.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-public class TestBuildingsInformationMapper
-{
-
-	/** Planet identifier found in the "result" */
-	private static final int PLANET_ID = 1;
-
-	/** Building identifier found in the "result" */
-	private static final int BUILDING_ID = 2;
-
-	/** Name found in the "result" */
-	private static final String BUILDING_NAME = "Test";
-
-	/** Quantity of buildings found in the "result" */
-	private static final int QUANTITY = 3;
-
-	/** Damage value found in the "result" */
-	private static final double DAMAGE = 4.0;
-
-	/** The fake result set used in the tests */
-	private ResultSet resultSet;
-
-	/** The mapper used in the tests */
-	private BuildingsInformationMapper mapper;
-
-
-	/**
-	 * Create the contents of the fake result set
-	 */
-	@Before
-	@SuppressWarnings( "unchecked" )
-	public void setUp( )
-	{
-		HashMap< String , Object > row = new HashMap< String , Object >( );
-		row.put( "planet_id" , PLANET_ID );
-		row.put( "building_id" , BUILDING_ID );
-		row.put( "building_name" , BUILDING_NAME );
-		row.put( "amount" , QUANTITY );
-		row.put( "damage" , DAMAGE );
-		this.resultSet = MockResultSet.create( new HashMap[] {
-			row
-		} );
-		this.mapper = new BuildingsInformationMapper( );
-	}
-
-
-	/**
-	 * The row mapper returns an instance that contains the necessary data.
-	 */
-	@Test
-	public void testRowMapper( )
-			throws SQLException
-	{
-		this.resultSet.absolute( 1 );
-		BuildingsInformation info = this.mapper.mapRow( this.resultSet , 0 );
-		assertNotNull( info );
-		assertEquals( PLANET_ID , info.getPlanetId( ) );
-		assertEquals( BUILDING_ID , info.getId( ) );
-		assertEquals( BUILDING_NAME , info.getName( ) );
-		assertEquals( QUANTITY , info.getAmount( ) );
-		assertEquals( DAMAGE , info.getDamage( ) , 0 );
-	}
-}
diff --git a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/bt/es/TestEmpireResourceInformationMapper.java b/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/bt/es/TestEmpireResourceInformationMapper.java
deleted file mode 100644
index b8bb7fc..0000000
--- a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/bt/es/TestEmpireResourceInformationMapper.java
+++ /dev/null
@@ -1,106 +0,0 @@
-package com.deepclone.lw.beans.bt.es;
-
-
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.util.HashMap;
-
-import static org.junit.Assert.*;
-
-import org.junit.Before;
-import org.junit.Test;
-
-import com.deepclone.lw.beans.bt.es.data.EmpireResourceInformation;
-import com.deepclone.lw.testing.MockResultSet;
-
-
-
-/**
- * Tests for the {@link EmpireResourceInformationMapper} class.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-public class TestEmpireResourceInformationMapper
-{
-
-	/** Resource identifier used in tests */
-	private static final String[] TEST_ID = {
-			"Test1" , "Test2"
-	};
-
-	/** "Owed" value used in tests */
-	private static final Double[] TEST_OWED = {
-			1.0 , 2.0
-	};
-
-	/** "Possessed" value used in tests */
-	private static final Double[] TEST_POSSESSED = {
-			3.0 , 4.0
-	};
-
-	/** Mining priority used in tests */
-	private static final Integer TEST_PRIORITY = 5;
-
-	/** The fake result set used in the tests */
-	private ResultSet resultSet;
-
-	/** The mapper used in the tests */
-	private EmpireResourceInformationMapper mapper;
-
-
-	/** Create the mapper and the contents of the fake result set */
-	@Before
-	@SuppressWarnings( "unchecked" )
-	public void setUp( )
-	{
-		this.mapper = new EmpireResourceInformationMapper( );
-
-		HashMap< String , Object > rows[] = new HashMap[ 2 ];
-		for ( int i = 0 ; i < 2 ; i++ ) {
-			HashMap< String , Object > row = new HashMap< String , Object >( );
-			row.put( "resource_name" , TEST_ID[ i ] );
-			row.put( "empres_possessed" , TEST_POSSESSED[ i ] );
-			row.put( "empres_owed" , TEST_OWED[ i ] );
-			if ( i == 1 ) {
-				row.put( "mining_priority" , TEST_PRIORITY );
-			}
-			rows[ i ] = row;
-		}
-
-		this.resultSet = MockResultSet.create( rows );
-	}
-
-
-	/** Mapping a row without mining priority */
-	@Test
-	public void testMapRow( )
-			throws SQLException
-	{
-		EmpireResourceInformation empRes;
-
-		this.resultSet.absolute( 1 );
-		empRes = this.mapper.mapRow( this.resultSet , 1 );
-
-		assertEquals( TEST_ID[ 0 ] , empRes.getResource( ) );
-		assertEquals( TEST_POSSESSED[ 0 ] , empRes.getPossessed( ) );
-		assertEquals( TEST_OWED[ 0 ] , empRes.getOwed( ) );
-		assertNull( empRes.getMiningPriority( ) );
-	}
-
-
-	/** Mapping a row with mining priority */
-	@Test
-	public void testMapRowWithPriority( )
-			throws SQLException
-	{
-		EmpireResourceInformation empRes;
-
-		this.resultSet.absolute( 2 );
-		empRes = this.mapper.mapRow( this.resultSet , 2 );
-
-		assertEquals( TEST_ID[ 1 ] , empRes.getResource( ) );
-		assertEquals( TEST_POSSESSED[ 1 ] , empRes.getPossessed( ) );
-		assertEquals( TEST_OWED[ 1 ] , empRes.getOwed( ) );
-		assertEquals( TEST_PRIORITY , empRes.getMiningPriority( ) );
-	}
-}
diff --git a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/bt/es/TestPlanetResourceRow.java b/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/bt/es/TestPlanetResourceRow.java
deleted file mode 100644
index f02a3a9..0000000
--- a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/bt/es/TestPlanetResourceRow.java
+++ /dev/null
@@ -1,102 +0,0 @@
-package com.deepclone.lw.beans.bt.es;
-
-
-import static org.junit.Assert.*;
-import org.junit.Before;
-import org.junit.Test;
-
-import com.deepclone.lw.beans.bt.es.data.ResourceProviderInformation;
-
-
-
-/**
- * Tests for the {@link PlanetResourceRow} class
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-public class TestPlanetResourceRow
-{
-
-	/** Identifier of the planet in the test object */
-	private static final int TEST_IDENTIFIER = 42;
-
-	/** Resource name used in the tests */
-	private static final String TEST_NAME = "Test";
-
-	/** The planet resource row instance used in tests */
-	private PlanetResourceRow prr;
-
-
-	/**
-	 * Create a planet resource row instance with the planet identifier specified by
-	 * {@link #TEST_IDENTIFIER}.
-	 */
-	@Before
-	public void setUp( )
-	{
-		this.prr = new PlanetResourceRow( TEST_IDENTIFIER );
-	}
-
-
-	/**
-	 * Planet identifier has been initialised correctly.
-	 */
-	@Test
-	public void testPlanetIdentifier( )
-	{
-		assertEquals( TEST_IDENTIFIER , this.prr.getPlanetId( ) );
-	}
-
-
-	/**
-	 * By default, the resource delta exists, the provider doesn't.
-	 */
-	@Test
-	public void testDefaultValues( )
-	{
-		assertNotNull( this.prr.getDelta( ) );
-		assertNull( this.prr.getProvider( ) );
-	}
-
-
-	/**
-	 * Setting and reading the resource provider record.
-	 */
-	@Test
-	public void testSetProvider( )
-	{
-		ResourceProviderInformation rpi = new ResourceProviderInformation( );
-		rpi.setResource( TEST_NAME );
-		this.prr.setProvider( rpi );
-		assertNotNull( this.prr.getProvider( ) );
-		assertEquals( TEST_NAME , this.prr.getProvider( ).getResource( ) );
-	}
-
-
-	/**
-	 * Setting the resource name when there is no resource provider record.
-	 */
-	@Test
-	public void testSetNameDeltaOnly( )
-	{
-		this.prr.setResource( TEST_NAME );
-		assertEquals( TEST_NAME , this.prr.getDelta( ).getResource( ) );
-		assertNull( this.prr.getProvider( ) );
-	}
-
-
-	/**
-	 * Setting the resource name when there are both a resource delta record and a resource provider
-	 * record.
-	 */
-	@Test
-	public void testSetNameFull( )
-	{
-		this.prr.setProvider( new ResourceProviderInformation( ) );
-		this.prr.setResource( TEST_NAME );
-		assertEquals( TEST_NAME , this.prr.getDelta( ).getResource( ) );
-		assertNotNull( this.prr.getProvider( ) );
-		assertEquals( TEST_NAME , this.prr.getProvider( ).getResource( ) );
-	}
-
-}
diff --git a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/bt/es/TestResourceRowMapper.java b/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/bt/es/TestResourceRowMapper.java
deleted file mode 100644
index 142e2b4..0000000
--- a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/bt/es/TestResourceRowMapper.java
+++ /dev/null
@@ -1,168 +0,0 @@
-package com.deepclone.lw.beans.bt.es;
-
-
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.util.HashMap;
-
-import static org.junit.Assert.*;
-import org.junit.Before;
-import org.junit.Test;
-
-import com.deepclone.lw.testing.MockResultSet;
-
-
-
-/**
- * Tests for the {@link ResourceRowMapper} class.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-public class TestResourceRowMapper
-{
-	/** Planet identifiers found in the "results" */
-	private static final int[] PLANET_IDS = new int[] {
-			1 , 2 , 3
-	};
-
-	/** Resource names found in the three "results", respectively */
-	private static final String[] RESOURCE_NAMES = new String[] {
-			"Test1" , "Test2" , "Test3"
-	};
-
-	/** Income values found in the three results */
-	private static final double[] INCOME_VALUES = new double[] {
-			4.0 , 5.0 , 6.0
-	};
-
-	/** Upkeep values found in the three results */
-	private static final double[] UPKEEP_VALUES = new double[] {
-			7.0 , 8.0 , 9.0
-	};
-
-	/** Resource provider quantity for the second and third rows */
-	private static final double[] RP_QUANTITY = {
-			10.0 , 11.0
-	};
-
-	/** Resource provider capacity for the second and third rows */
-	private static final double[] RP_CAPACITY = {
-			12.0 , 13.0
-	};
-
-	/** Resource provider extraction difficulty for the second and third rows */
-	private static final double[] RP_DIFFICULTY = {
-			14.0 , 15.0
-	};
-
-	/** Resource provider recovery rate for the second and third rows */
-	private static final double[] RP_RECOVERY = {
-			16.0 , 17.0
-	};
-
-	/** Mining priority value used for the third row */
-	private static final Integer MINING_PRIORITY = 18;
-
-	/** The fake result set used in the tests */
-	private ResultSet resultSet;
-
-	/** The mapper used in the tests */
-	private ResourceRowMapper mapper;
-
-
-	/** Create the mapper and the contents of the fake result set */
-	@Before
-	public void setUp( )
-	{
-		this.mapper = new ResourceRowMapper( );
-
-		@SuppressWarnings( "unchecked" )
-		HashMap< String , Object > rows[] = new HashMap[ 3 ];
-		for ( int i = 0 ; i < 3 ; i++ ) {
-			HashMap< String , Object > row = new HashMap< String , Object >( );
-			row.put( "planet_id" , PLANET_IDS[ i ] );
-			row.put( "resource_name" , RESOURCE_NAMES[ i ] );
-			row.put( "pres_income" , INCOME_VALUES[ i ] );
-			row.put( "pres_upkeep" , UPKEEP_VALUES[ i ] );
-			if ( i > 0 ) {
-				row.put( "resprov_quantity_max" , RP_CAPACITY[ i - 1 ] );
-				row.put( "resprov_quantity" , RP_QUANTITY[ i - 1 ] );
-				row.put( "resprov_difficulty" , RP_DIFFICULTY[ i - 1 ] );
-				row.put( "resprov_recovery" , RP_RECOVERY[ i - 1 ] );
-				if ( i > 1 ) {
-					row.put( "mining_priority" , MINING_PRIORITY );
-				}
-			}
-			rows[ i ] = row;
-		}
-
-		this.resultSet = MockResultSet.create( rows );
-	}
-
-
-	/**
-	 * Mapping a row with no provider information
-	 */
-	@Test
-	public void testMapNoProvider( )
-			throws SQLException
-	{
-		this.resultSet.absolute( 1 );
-
-		PlanetResourceRow row = this.mapper.mapRow( this.resultSet , 0 );
-		assertNotNull( row );
-		assertEquals( PLANET_IDS[ 0 ] , row.getPlanetId( ) );
-		assertEquals( RESOURCE_NAMES[ 0 ] , row.getDelta( ).getResource( ) );
-		assertEquals( INCOME_VALUES[ 0 ] , row.getDelta( ).getIncome( ) , 0 );
-		assertEquals( UPKEEP_VALUES[ 0 ] , row.getDelta( ).getUpkeep( ) , 0 );
-		assertNull( row.getProvider( ) );
-	}
-
-
-	/**
-	 * Mapping a row with a provider information record but no mining priority
-	 */
-	@Test
-	public void testMapWithProvider( )
-			throws SQLException
-	{
-		this.resultSet.absolute( 2 );
-
-		PlanetResourceRow row = this.mapper.mapRow( this.resultSet , 0 );
-		assertNotNull( row );
-		assertEquals( PLANET_IDS[ 1 ] , row.getPlanetId( ) );
-		assertEquals( RESOURCE_NAMES[ 1 ] , row.getDelta( ).getResource( ) );
-		assertEquals( INCOME_VALUES[ 1 ] , row.getDelta( ).getIncome( ) , 0 );
-		assertEquals( UPKEEP_VALUES[ 1 ] , row.getDelta( ).getUpkeep( ) , 0 );
-		assertNotNull( row.getProvider( ) );
-		assertEquals( RP_CAPACITY[ 0 ] , row.getProvider( ).getMaximalQuantity( ) , 0 );
-		assertEquals( RP_QUANTITY[ 0 ] , row.getProvider( ).getCurrentQuantity( ) , 0 );
-		assertEquals( RP_DIFFICULTY[ 0 ] , row.getProvider( ).getDifficulty( ) , 0 );
-		assertEquals( RP_RECOVERY[ 0 ] , row.getProvider( ).getRecovery( ) , 0 );
-		assertNull( row.getProvider( ).getMiningPriority( ) );
-	}
-
-
-	/**
-	 * Mapping a row with a provider information record and a mining priority
-	 */
-	@Test
-	public void testMapWithPriority( )
-			throws SQLException
-	{
-		this.resultSet.absolute( 3 );
-
-		PlanetResourceRow row = this.mapper.mapRow( this.resultSet , 0 );
-		assertNotNull( row );
-		assertEquals( PLANET_IDS[ 2 ] , row.getPlanetId( ) );
-		assertEquals( RESOURCE_NAMES[ 2 ] , row.getDelta( ).getResource( ) );
-		assertEquals( INCOME_VALUES[ 2 ] , row.getDelta( ).getIncome( ) , 0 );
-		assertEquals( UPKEEP_VALUES[ 2 ] , row.getDelta( ).getUpkeep( ) , 0 );
-		assertNotNull( row.getProvider( ) );
-		assertEquals( RP_CAPACITY[ 1 ] , row.getProvider( ).getMaximalQuantity( ) , 0 );
-		assertEquals( RP_QUANTITY[ 1 ] , row.getProvider( ).getCurrentQuantity( ) , 0 );
-		assertEquals( RP_DIFFICULTY[ 1 ] , row.getProvider( ).getDifficulty( ) , 0 );
-		assertEquals( RP_RECOVERY[ 1 ] , row.getProvider( ).getRecovery( ) , 0 );
-		assertEquals( MINING_PRIORITY , row.getProvider( ).getMiningPriority( ) );
-	}
-}
diff --git a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/bt/es/data/TestEmpireResourceInformation.java b/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/bt/es/data/TestEmpireResourceInformation.java
deleted file mode 100644
index 093a0e3..0000000
--- a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/bt/es/data/TestEmpireResourceInformation.java
+++ /dev/null
@@ -1,194 +0,0 @@
-package com.deepclone.lw.beans.bt.es.data;
-
-
-import static org.junit.Assert.*;
-
-import org.junit.Before;
-import org.junit.Test;
-
-import com.thoughtworks.xstream.XStream;
-
-
-
-/**
- * Tests for the {@link EmpireResourceInformation} class.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-public class TestEmpireResourceInformation
-{
-
-	/** Resource identifier used in tests */
-	private static final String TEST_ID = "Test";
-
-	/** "Owed" value used in tests */
-	private static final Double TEST_OWED = 1.0;
-
-	/** "Possessed" value used in tests */
-	private static final Double TEST_POSSESSED = 2.0;
-
-	/** Mining priority value used in tests */
-	private static final Integer TEST_PRIORITY = 3;
-
-	/** Empire resource information instance used in tests */
-	private EmpireResourceInformation empRes;
-
-
-	/** Create the instance to be used in actual tests */
-	@Before
-	public void setUp( )
-	{
-		this.empRes = new EmpireResourceInformation( );
-	}
-
-
-	/** Default values are <code>null</code> */
-	@Test
-	public void testDefaultValues( )
-	{
-		assertNull( this.empRes.getResource( ) );
-		assertNull( this.empRes.getOwed( ) );
-		assertNull( this.empRes.getPossessed( ) );
-		assertNull( this.empRes.getMiningPriority( ) );
-	}
-
-
-	/** Setting and reading the resource type */
-	@Test
-	public void testResource( )
-	{
-		this.empRes.setResource( TEST_ID );
-		assertEquals( TEST_ID , this.empRes.getResource( ) );
-	}
-
-
-	/** Setting the resource type to <code>null</code> */
-	@Test
-	public void testNullResource( )
-	{
-		try {
-			this.empRes.setResource( null );
-			fail( "InvalidDumpContentsException expected" );
-		} catch ( InvalidDumpContentsException exception ) {
-			assertEquals( EmpireResourceInformation.class , exception.getRecordType( ) );
-			assertEquals( "resource" , exception.getField( ) );
-		}
-	}
-
-
-	/** Setting and reading the amount of resources possessed */
-	@Test
-	public void testPossessed( )
-	{
-		this.empRes.setPossessed( TEST_POSSESSED );
-		assertEquals( TEST_POSSESSED , this.empRes.getPossessed( ) );
-	}
-
-
-	/** Setting and reading the amount of resources owed */
-	@Test
-	public void testOwed( )
-	{
-		this.empRes.setOwed( TEST_OWED );
-		assertEquals( TEST_OWED , this.empRes.getOwed( ) );
-	}
-
-
-	/** Setting and reading the mining priority */
-	@Test
-	public void testMiningPriority( )
-	{
-		this.empRes.setMiningPriority( TEST_PRIORITY );
-		assertEquals( TEST_PRIORITY , this.empRes.getMiningPriority( ) );
-	}
-
-
-	/** Serialising the instance to XML - no mining priority */
-	@Test
-	public void testXMLSerialisation( )
-	{
-		this.empRes.setResource( TEST_ID );
-		this.empRes.setOwed( TEST_OWED );
-		this.empRes.setPossessed( TEST_POSSESSED );
-
-		String serialised = this.createXStreamInstance( ).toXML( this.empRes );
-		assertNotNull( serialised );
-		assertTrue( serialised.startsWith( "<resource " ) );
-		assertTrue( serialised.endsWith( "/>" ) );
-		assertTrue( serialised.contains( " id=\"" + TEST_ID + "\"" ) );
-		assertTrue( serialised.contains( " owed=\"" + TEST_OWED + "\"" ) );
-		assertTrue( serialised.contains( " possessed=\"" + TEST_POSSESSED + "\"" ) );
-		assertFalse( serialised.contains( "mining-priority=\"" ) );
-	}
-
-
-	/** Serialising the instance to XML - including mining priority */
-	@Test
-	public void testXMLSerialisationWithPriority( )
-	{
-		this.empRes.setResource( TEST_ID );
-		this.empRes.setOwed( TEST_OWED );
-		this.empRes.setPossessed( TEST_POSSESSED );
-		this.empRes.setMiningPriority( TEST_PRIORITY );
-
-		String serialised = this.createXStreamInstance( ).toXML( this.empRes );
-		assertNotNull( serialised );
-		assertTrue( serialised.startsWith( "<resource " ) );
-		assertTrue( serialised.endsWith( "/>" ) );
-		assertTrue( serialised.contains( " id=\"" + TEST_ID + "\"" ) );
-		assertTrue( serialised.contains( " owed=\"" + TEST_OWED + "\"" ) );
-		assertTrue( serialised.contains( " possessed=\"" + TEST_POSSESSED + "\"" ) );
-		assertTrue( serialised.contains( " mining-priority=\"" + TEST_PRIORITY + "\"" ) );
-	}
-
-
-	/** Deserialising an instance from XML - no mining priority */
-	@Test
-	public void testXMLDeserialisation( )
-	{
-		String xml = "<resource id=\"" + TEST_ID + "\" owed=\"" + TEST_OWED.toString( ) + "\" possessed=\""
-				+ TEST_POSSESSED.toString( ) + "\" />";
-		Object deserialised = this.createXStreamInstance( ).fromXML( xml );
-
-		assertNotNull( deserialised );
-		assertEquals( EmpireResourceInformation.class , deserialised.getClass( ) );
-		this.empRes = (EmpireResourceInformation) deserialised;
-
-		assertEquals( TEST_ID , this.empRes.getResource( ) );
-		assertEquals( TEST_POSSESSED , this.empRes.getPossessed( ) );
-		assertEquals( TEST_OWED , this.empRes.getOwed( ) );
-		assertNull( this.empRes.getMiningPriority( ) );
-	}
-
-
-	/** Deserialising an instance from XML - including mining priority */
-	@Test
-	public void testXMLDeserialisationWithPriority( )
-	{
-		String xml = "<resource id=\"" + TEST_ID + "\" owed=\"" + TEST_OWED.toString( ) + "\" possessed=\""
-				+ TEST_POSSESSED.toString( ) + "\" mining-priority=\"" + TEST_PRIORITY.toString( ) + "\" />";
-		Object deserialised = this.createXStreamInstance( ).fromXML( xml );
-
-		assertNotNull( deserialised );
-		assertEquals( EmpireResourceInformation.class , deserialised.getClass( ) );
-		this.empRes = (EmpireResourceInformation) deserialised;
-
-		assertEquals( TEST_ID , this.empRes.getResource( ) );
-		assertEquals( TEST_POSSESSED , this.empRes.getPossessed( ) );
-		assertEquals( TEST_OWED , this.empRes.getOwed( ) );
-		assertEquals( TEST_PRIORITY , this.empRes.getMiningPriority( ) );
-	}
-
-
-	/**
-	 * Create and set up the {@link XStream} instance used in the serialisation tests
-	 * 
-	 * @return the {@link XStream} instance to use
-	 */
-	private XStream createXStreamInstance( )
-	{
-		XStream xstream = new XStream( );
-		xstream.processAnnotations( EmpireResourceInformation.class );
-		return xstream;
-	}
-}
diff --git a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/bt/es/data/TestInvalidDumpContentsException.java b/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/bt/es/data/TestInvalidDumpContentsException.java
deleted file mode 100644
index a88992d..0000000
--- a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/bt/es/data/TestInvalidDumpContentsException.java
+++ /dev/null
@@ -1,85 +0,0 @@
-package com.deepclone.lw.beans.bt.es.data;
-
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-
-import java.io.Serializable;
-
-import org.junit.Before;
-import org.junit.Test;
-
-import com.deepclone.lw.beans.bt.es.data.InvalidDumpContentsException;
-
-
-
-/**
- * Tests for the {@link InvalidDumpContentsException} class
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-public class TestInvalidDumpContentsException
-{
-
-	/**
-	 * A dummy class used to test the {@link InvalidDumpContentsException} class.
-	 * 
-	 * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
-	 */
-	@SuppressWarnings( "serial" )
-	private static final class TestRecord
-			implements Serializable
-	{
-		// EMPTY
-	}
-
-	/** Test string used as the "field" parameter */
-	private static final String TEST_STRING = "Test";
-
-	/** Exception instance used to run tests */
-	private InvalidDumpContentsException exception;
-
-
-	/**
-	 * Set up the test by creating an exception instance using {@link TestRecord} as the target
-	 * class and {@link #TEST_STRING} as the field name.
-	 */
-	@Before
-	public void setUp( )
-	{
-		this.exception = new InvalidDumpContentsException( TestRecord.class , TEST_STRING );
-	}
-
-
-	/**
-	 * The constructor must set the record's class and field name.
-	 */
-	@Test
-	public void testExceptionData( )
-	{
-		assertEquals( TestRecord.class , this.exception.getRecordType( ) );
-		assertEquals( TEST_STRING , this.exception.getField( ) );
-		assertNotNull( this.exception.getMessage( ) );
-	}
-
-
-	/**
-	 * The exception's message must end with the name of the class.
-	 */
-	@Test
-	public void testClassNameInMessage( )
-	{
-		assertTrue( this.exception.getMessage( ).endsWith( " " + TestRecord.class.getSimpleName( ) ) );
-	}
-
-
-	/**
-	 * The exception's message must contain the name of the field.
-	 */
-	@Test
-	public void testFieldNameInMessage( )
-	{
-		assertTrue( this.exception.getMessage( ).contains( " " + TEST_STRING + " " ) );
-	}
-}
diff --git a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/bt/es/data/TestResourceDeltaInformation.java b/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/bt/es/data/TestResourceDeltaInformation.java
deleted file mode 100644
index 2d899f6..0000000
--- a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/bt/es/data/TestResourceDeltaInformation.java
+++ /dev/null
@@ -1,174 +0,0 @@
-package com.deepclone.lw.beans.bt.es.data;
-
-
-import static org.junit.Assert.*;
-
-import org.junit.Before;
-import org.junit.Test;
-
-import com.thoughtworks.xstream.XStream;
-
-
-
-/**
- * Tests for the {@link ResourceDeltaInformation} XML dump storage class
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-public class TestResourceDeltaInformation
-{
-
-	/** A string used in tests */
-	private static final String TEST_STRING = "This is a test";
-
-	/** A real number used in tests */
-	private static final Double TEST_DOUBLE = 4.2;
-
-	/** A record used in the tests */
-	private ResourceDeltaInformation rdi;
-
-
-	/**
-	 * Set up the test by creating a new resource delta information record.
-	 */
-	@Before
-	public void setUp( )
-	{
-		this.rdi = new ResourceDeltaInformation( );
-	}
-
-
-	/**
-	 * All fields are set to <code>null</code> by default
-	 */
-	@Test
-	public void testDefaultValues( )
-	{
-		assertNull( this.rdi.getResource( ) );
-		assertNull( this.rdi.getIncome( ) );
-		assertNull( this.rdi.getUpkeep( ) );
-	}
-
-
-	/**
-	 * Setting and reading the resource's name
-	 */
-	@Test
-	public void testResourceName( )
-	{
-		this.rdi.setResource( TEST_STRING );
-		assertEquals( TEST_STRING , this.rdi.getResource( ) );
-	}
-
-
-	/**
-	 * Setting the resource name to <code>null</code> throws {@link InvalidDumpContentsException}
-	 */
-	@Test
-	public void testNullResourceName( )
-	{
-		try {
-			this.rdi.setResource( null );
-			fail( "No InvalidDumpContentsException thrown" );
-		} catch ( InvalidDumpContentsException exception ) {
-			assertEquals( ResourceDeltaInformation.class , exception.getRecordType( ) );
-			assertEquals( "resource" , exception.getField( ) );
-		}
-	}
-
-
-	/**
-	 * Setting and reading the income
-	 */
-	@Test
-	public void testIncome( )
-	{
-		this.rdi.setIncome( TEST_DOUBLE );
-		assertEquals( TEST_DOUBLE , this.rdi.getIncome( ) );
-	}
-
-
-	/**
-	 * Setting and reading the upkeep
-	 */
-	@Test
-	public void testUpkeep( )
-	{
-		this.rdi.setUpkeep( TEST_DOUBLE );
-		assertEquals( TEST_DOUBLE , this.rdi.getUpkeep( ) );
-	}
-
-
-	/**
-	 * Serialising the instance to XML
-	 */
-	@Test
-	public void testXMLSerialisation( )
-	{
-		this.rdi.setResource( TEST_STRING );
-		this.rdi.setIncome( 0.1 );
-		this.rdi.setUpkeep( 0.2 );
-
-		XStream xstream = this.createXStreamInstance( );
-		String serialised = xstream.toXML( this.rdi );
-		assertNotNull( serialised );
-		assertTrue( serialised.startsWith( "<resource-delta " ) );
-		assertTrue( serialised.endsWith( "/>" ) );
-		assertTrue( serialised.contains( " id=\"" + TEST_STRING + "\"" ) );
-		assertTrue( serialised.contains( " income=\"0.1\"" ) );
-		assertTrue( serialised.contains( " upkeep=\"0.2\"" ) );
-	}
-
-
-	/**
-	 * Deserialising an instance that contains data
-	 */
-	@Test
-	public void testXMLDeserialisation( )
-	{
-		String xml = "<resource-delta id=\"Test\" income=\"0.1\" upkeep=\"0.2\" />";
-		XStream xstream = this.createXStreamInstance( );
-		Object deserialised = xstream.fromXML( xml );
-
-		assertNotNull( deserialised );
-		assertEquals( ResourceDeltaInformation.class , deserialised.getClass( ) );
-		this.rdi = (ResourceDeltaInformation) deserialised;
-
-		assertEquals( "Test" , this.rdi.getResource( ) );
-		assertEquals( (Double) 0.1 , this.rdi.getIncome( ) );
-		assertEquals( (Double) 0.2 , this.rdi.getUpkeep( ) );
-	}
-
-
-	/**
-	 * Deserialising an instance that contains no data
-	 */
-	@Test
-	public void testXMLDeserialisationNoData( )
-	{
-		String xml = "<resource-delta />";
-		XStream xstream = this.createXStreamInstance( );
-		Object deserialised = xstream.fromXML( xml );
-
-		assertNotNull( deserialised );
-		assertEquals( ResourceDeltaInformation.class , deserialised.getClass( ) );
-		this.rdi = (ResourceDeltaInformation) deserialised;
-
-		assertNull( this.rdi.getResource( ) );
-		assertNull( this.rdi.getIncome( ) );
-		assertNull( this.rdi.getUpkeep( ) );
-	}
-
-
-	/**
-	 * Create and set up the {@link XStream} instance used in the serialisation tests
-	 * 
-	 * @return the {@link XStream} instance to use
-	 */
-	private XStream createXStreamInstance( )
-	{
-		XStream xstream = new XStream( );
-		xstream.processAnnotations( ResourceDeltaInformation.class );
-		return xstream;
-	}
-}
diff --git a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/bt/es/data/TestResourceProviderInformation.java b/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/bt/es/data/TestResourceProviderInformation.java
deleted file mode 100644
index c912562..0000000
--- a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/bt/es/data/TestResourceProviderInformation.java
+++ /dev/null
@@ -1,256 +0,0 @@
-package com.deepclone.lw.beans.bt.es.data;
-
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import org.junit.Before;
-import org.junit.Test;
-
-import com.thoughtworks.xstream.XStream;
-
-
-
-/**
- * Tests for the {@link ResourceProviderInformation} XML dump storage class
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-public class TestResourceProviderInformation
-{
-	/** A string used in tests */
-	private static final String TEST_STRING = "This is a test";
-
-	/** A real number used in tests */
-	private static final Double TEST_DOUBLE = 4.2;
-
-	/** Mining priority value used in tests */
-	private static final Integer TEST_PRIORITY = 3;
-
-	/** A resource provider information record */
-	private ResourceProviderInformation rpi;
-
-
-	@Before
-	public void setUp( )
-	{
-		this.rpi = new ResourceProviderInformation( );
-	}
-
-
-	/**
-	 * A new record's fields are all set to <code>null</code>.
-	 */
-	@Test
-	public void testDefaultValues( )
-	{
-		assertNull( this.rpi.getResource( ) );
-		assertNull( this.rpi.getCurrentQuantity( ) );
-		assertNull( this.rpi.getMaximalQuantity( ) );
-		assertNull( this.rpi.getDifficulty( ) );
-		assertNull( this.rpi.getRecovery( ) );
-		assertNull( this.rpi.getMiningPriority( ) );
-	}
-
-
-	/**
-	 * Setting and reading the resource's name
-	 */
-	@Test
-	public void testResourceName( )
-	{
-		this.rpi.setResource( TEST_STRING );
-		assertEquals( TEST_STRING , this.rpi.getResource( ) );
-	}
-
-
-	/**
-	 * Setting the resource name to <code>null</code> throws {@link InvalidDumpContentsException}
-	 */
-	@Test
-	public void testNullResourceName( )
-	{
-		try {
-			this.rpi.setResource( null );
-			fail( "No InvalidDumpContentsException thrown" );
-		} catch ( InvalidDumpContentsException exception ) {
-			assertEquals( ResourceProviderInformation.class , exception.getRecordType( ) );
-			assertEquals( "resource" , exception.getField( ) );
-		}
-	}
-
-
-	/**
-	 * Setting and reading the current quantity
-	 */
-	@Test
-	public void testCurrentQuantity( )
-	{
-		this.rpi.setCurrentQuantity( TEST_DOUBLE );
-		assertEquals( TEST_DOUBLE , this.rpi.getCurrentQuantity( ) );
-	}
-
-
-	/**
-	 * Setting and reading the maximal quantity
-	 */
-	@Test
-	public void testMaximalQuantity( )
-	{
-		this.rpi.setMaximalQuantity( TEST_DOUBLE );
-		assertEquals( TEST_DOUBLE , this.rpi.getMaximalQuantity( ) );
-	}
-
-
-	/**
-	 * Setting and reading the extraction difficulty
-	 */
-	@Test
-	public void testDifficulty( )
-	{
-		this.rpi.setDifficulty( TEST_DOUBLE );
-		assertEquals( TEST_DOUBLE , this.rpi.getDifficulty( ) );
-	}
-
-
-	/**
-	 * Setting and reading the recovery rate
-	 */
-	@Test
-	public void testRecovery( )
-	{
-		this.rpi.setRecovery( TEST_DOUBLE );
-		assertEquals( TEST_DOUBLE , this.rpi.getRecovery( ) );
-	}
-
-
-	/**
-	 * Setting and reading the mining priority
-	 */
-	@Test
-	public void testMiningPriority( )
-	{
-		this.rpi.setMiningPriority( TEST_PRIORITY );
-		assertEquals( TEST_PRIORITY , this.rpi.getMiningPriority( ) );
-	}
-
-
-	/**
-	 * Serialising the instance to XML, without mining priority
-	 */
-	@Test
-	public void testXMLSerialisation( )
-	{
-		this.rpi.setResource( TEST_STRING );
-		this.rpi.setCurrentQuantity( 0.1 );
-		this.rpi.setMaximalQuantity( 0.2 );
-		this.rpi.setDifficulty( 0.3 );
-		this.rpi.setRecovery( 0.4 );
-
-		XStream xstream = this.createXStreamInstance( );
-		String serialised = xstream.toXML( this.rpi );
-		assertNotNull( serialised );
-		assertTrue( serialised.startsWith( "<resource-provider " ) );
-		assertTrue( serialised.endsWith( "/>" ) );
-		assertTrue( serialised.contains( " resource=\"" + TEST_STRING + "\"" ) );
-		assertTrue( serialised.contains( " current=\"0.1\"" ) );
-		assertTrue( serialised.contains( " max=\"0.2\"" ) );
-		assertTrue( serialised.contains( " difficulty=\"0.3\"" ) );
-		assertTrue( serialised.contains( " recovery=\"0.4\"" ) );
-		assertFalse( serialised.contains( "mining-priority=" ) );
-	}
-
-
-	/**
-	 * Serialising the instance to XML, with a mining priority
-	 */
-	@Test
-	public void testXMLSerialisationWithPriority( )
-	{
-		this.rpi.setResource( TEST_STRING );
-		this.rpi.setCurrentQuantity( 0.1 );
-		this.rpi.setMaximalQuantity( 0.2 );
-		this.rpi.setDifficulty( 0.3 );
-		this.rpi.setRecovery( 0.4 );
-		this.rpi.setMiningPriority( TEST_PRIORITY );
-
-		XStream xstream = this.createXStreamInstance( );
-		String serialised = xstream.toXML( this.rpi );
-		assertNotNull( serialised );
-		assertTrue( serialised.startsWith( "<resource-provider " ) );
-		assertTrue( serialised.endsWith( "/>" ) );
-		assertTrue( serialised.contains( " resource=\"" + TEST_STRING + "\"" ) );
-		assertTrue( serialised.contains( " current=\"0.1\"" ) );
-		assertTrue( serialised.contains( " max=\"0.2\"" ) );
-		assertTrue( serialised.contains( " difficulty=\"0.3\"" ) );
-		assertTrue( serialised.contains( " recovery=\"0.4\"" ) );
-		assertTrue( serialised.contains( " mining-priority=\"" + TEST_PRIORITY.toString( ) + "\"" ) );
-	}
-
-
-	/**
-	 * Deserialising an instance - no mining priority
-	 */
-	@Test
-	public void testXMLDeserialisation( )
-	{
-		String xml = "<resource-provider resource=\"Test\" current=\"0.1\" max=\"0.2\" difficulty=\"0.3\" recovery=\"0.4\" />";
-		XStream xstream = this.createXStreamInstance( );
-		Object deserialised = xstream.fromXML( xml );
-
-		assertNotNull( deserialised );
-		assertEquals( ResourceProviderInformation.class , deserialised.getClass( ) );
-		this.rpi = (ResourceProviderInformation) deserialised;
-
-		assertEquals( "Test" , this.rpi.getResource( ) );
-		assertEquals( (Double) 0.1 , this.rpi.getCurrentQuantity( ) );
-		assertEquals( (Double) 0.2 , this.rpi.getMaximalQuantity( ) );
-		assertEquals( (Double) 0.3 , this.rpi.getDifficulty( ) );
-		assertEquals( (Double) 0.4 , this.rpi.getRecovery( ) );
-		assertNull( this.rpi.getMiningPriority( ) );
-	}
-
-
-	/**
-	 * Deserialising an instance with mining priority
-	 */
-	@Test
-	public void testXMLDeserialisationWithPriority( )
-	{
-		String xml = "<resource-provider resource=\"" + TEST_STRING
-				+ "\" current=\"0.1\" max=\"0.2\" difficulty=\"0.3\" recovery=\"0.4\" mining-priority=\""
-				+ TEST_PRIORITY.toString( ) + "\" />";
-		XStream xstream = this.createXStreamInstance( );
-		Object deserialised = xstream.fromXML( xml );
-
-		assertNotNull( deserialised );
-		assertEquals( ResourceProviderInformation.class , deserialised.getClass( ) );
-		this.rpi = (ResourceProviderInformation) deserialised;
-
-		assertEquals( TEST_STRING , this.rpi.getResource( ) );
-		assertEquals( (Double) 0.1 , this.rpi.getCurrentQuantity( ) );
-		assertEquals( (Double) 0.2 , this.rpi.getMaximalQuantity( ) );
-		assertEquals( (Double) 0.3 , this.rpi.getDifficulty( ) );
-		assertEquals( (Double) 0.4 , this.rpi.getRecovery( ) );
-		assertEquals( TEST_PRIORITY , this.rpi.getMiningPriority( ) );
-
-	}
-
-
-	/**
-	 * Create and set up the {@link XStream} instance used in the serialisation tests
-	 * 
-	 * @return the {@link XStream} instance to use
-	 */
-	private XStream createXStreamInstance( )
-	{
-		XStream xstream = new XStream( );
-		xstream.processAnnotations( ResourceProviderInformation.class );
-		xstream.alias( "resource-provider" , ResourceProviderInformation.class );
-		return xstream;
-	}
-}
diff --git a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/game/resources/MockMiningSettingsDAO.java b/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/game/resources/MockMiningSettingsDAO.java
deleted file mode 100644
index 330c0f2..0000000
--- a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/game/resources/MockMiningSettingsDAO.java
+++ /dev/null
@@ -1,174 +0,0 @@
-package com.deepclone.lw.beans.game.resources;
-
-
-import com.deepclone.lw.interfaces.game.resources.MiningSettingsDAO;
-
-
-
-/**
- * Mock mining settings DAO which can be used to simulate failures and trace which methods were
- * called.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- * 
- */
-public class MockMiningSettingsDAO
-		implements MiningSettingsDAO
-{
-	/**
-	 * The empire identifier with which {@link #startUpdate(int)} or {@link #togglePlanet(int, int)}
-	 * was called
-	 */
-	private Integer empire = null;
-
-	/** The planet identifier with which {@link #togglePlanet(int, int)} was called */
-	private Integer planet = null;
-
-	/** The amount of calls to {@link #setNewPriority(String, int)} */
-	private int callsToSet = 0;
-
-	/** Whether {@link #startUpdate(int)} was called */
-	private boolean startUpdateCalled = false;
-
-	/** Whether {@link #applyUpdate()} was called */
-	private boolean applyCalled = false;
-
-	/** Whether {@link #togglePlanet(int, int)} was called */
-	private boolean togglePlanetCalled = false;
-
-	/** Whether {@link #startUpdate(int)} will succeed or fail */
-	private boolean startUpdateSucceeds = true;
-
-	/** Whether applyUpdate will succeed */
-	private boolean applyUpdateSucceeds = true;
-
-	/**
-	 * Amount of calls to {@link #setNewPriority(String, int)} that will succeed, or
-	 * <code>null</code> if they will all succeed.
-	 */
-	private Integer maxSetCalls = null;
-
-
-	/** @return the empire identifier */
-	public Integer getEmpire( )
-	{
-		return this.empire;
-	}
-
-
-	/** @return the planet identifier */
-	public Integer getPlanet( )
-	{
-		return this.planet;
-	}
-
-
-	/** @return <code>true</code> if {@link #startUpdate(int)()} was called */
-	public boolean wasStartUpdateCalled( )
-	{
-		return this.startUpdateCalled;
-	}
-
-
-	/** @return the amount of calls to {@link #setNewPriority(String, int)} */
-	public int getCallsToSet( )
-	{
-		return this.callsToSet;
-	}
-
-
-	/** @return <code>true</code> if {@link #applyUpdate()} was called */
-	public boolean wasApplyCalled( )
-	{
-		return this.applyCalled;
-	}
-
-
-	/** @return <code>true</code> if {@link #togglePlanet(int, int)} was called */
-	public boolean wasTogllePlanetCalled( )
-	{
-		return this.togglePlanetCalled;
-	}
-
-
-	/**
-	 * Determine whether calls to {@link #startUpdate(int)} will succeed
-	 * 
-	 * @param startUpdateSucceeds
-	 *            <code>true</code> if the call is to succeed, <code>false</code> if it is to fail
-	 */
-	public void setStartUpdateSucceeds( boolean startUpdateSucceeds )
-	{
-		this.startUpdateSucceeds = startUpdateSucceeds;
-	}
-
-
-	/**
-	 * Determine whether calls to {@link #applyUpdate()} will succeed
-	 * 
-	 * @param applyUpdateSucceeds
-	 *            <code>true</code> if the call is to succeed, <code>false</code> if it is to fail
-	 */
-	public void setApplyUpdateSucceeds( boolean applyUpdateSucceeds )
-	{
-		this.applyUpdateSucceeds = applyUpdateSucceeds;
-	}
-
-
-	/**
-	 * Set the amount of calls to {@link #setNewPriority(String, int)} that will succeed
-	 * 
-	 * @param maxSetCalls
-	 *            the amount of calls that will succeed, or <code>null</code> if the method must
-	 *            always succeed
-	 */
-	public void setMaxSetCalls( Integer maxSetCalls )
-	{
-		this.maxSetCalls = maxSetCalls;
-	}
-
-
-	@Override
-	public boolean startUpdate( int empireId )
-	{
-		this.startUpdateCalled = true;
-		this.empire = empireId;
-		return this.startUpdateSucceeds;
-	}
-
-
-	@Override
-	public boolean startUpdate( int empire , int planet )
-	{
-		this.startUpdateCalled = true;
-		this.empire = empire;
-		this.planet = planet;
-		return this.startUpdateSucceeds;
-	}
-
-
-	@Override
-	public boolean setNewPriority( String resource , int priority )
-	{
-		this.callsToSet++;
-		return ( this.maxSetCalls == null || this.maxSetCalls > this.callsToSet - 1 );
-	}
-
-
-	@Override
-	public boolean applyUpdate( )
-	{
-		this.applyCalled = true;
-		return this.applyUpdateSucceeds;
-	}
-
-
-	@Override
-	public void togglePlanet( int empire , int planet )
-	{
-		this.togglePlanetCalled = true;
-		this.empire = empire;
-		this.planet = planet;
-	}
-
-}
diff --git a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/game/resources/TestAbstractResourceMapper.java b/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/game/resources/TestAbstractResourceMapper.java
deleted file mode 100644
index 4a0cd03..0000000
--- a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/game/resources/TestAbstractResourceMapper.java
+++ /dev/null
@@ -1,126 +0,0 @@
-package com.deepclone.lw.beans.game.resources;
-
-
-import static org.junit.Assert.*;
-
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.util.HashMap;
-
-import org.junit.Before;
-import org.junit.Test;
-
-import com.deepclone.lw.cmd.player.gdata.AbstractResourceRecord;
-import com.deepclone.lw.testing.MockResultSet;
-
-
-
-/**
- * Tests of the {@link AbstractResourceMapper} class
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-public class TestAbstractResourceMapper
-{
-	/** Strings used for the various fields */
-	private static final String TEST_STRINGS[] = {
-			"1" , "2" , "3" , "4"
-	};
-
-	/**
-	 * An empty resource record used to test the {@link AbstractResourceMapper}
-	 * 
-	 * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
-	 */
-	@SuppressWarnings( "serial" )
-	private static class EmptyResourceRecord
-			extends AbstractResourceRecord
-	{
-		// EMPTY
-	}
-
-	/**
-	 * Resource row mapper that calls
-	 * {@link AbstractResourceMapper#getResourceDescription(AbstractResourceRecord, ResultSet)}
-	 * 
-	 * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
-	 * 
-	 */
-	private static class EmptyResourceMapper
-			extends AbstractResourceMapper< EmptyResourceRecord >
-	{
-
-		@Override
-		public EmptyResourceRecord mapRow( ResultSet rs , int rowNum )
-				throws SQLException
-		{
-			EmptyResourceRecord record = new EmptyResourceRecord( );
-			this.getResourceDescription( record , rs );
-			return record;
-		}
-
-	}
-
-	/** The result set fed to the resource row mapper */
-	private ResultSet resultSet;
-
-	/** The mapper used in the tests */
-	private EmptyResourceMapper mapper;
-
-
-	/**
-	 * Create the test mapper and a fake result set with two results: one that includes a category,
-	 * and another without category.
-	 */
-	@Before
-	public void setUp( )
-	{
-		this.mapper = new EmptyResourceMapper( );
-
-		@SuppressWarnings( "unchecked" )
-		HashMap< String , Object > rows[] = new HashMap[ 2 ];
-		for ( int i = 0 ; i < 2 ; i++ ) {
-			HashMap< String , Object > row = new HashMap< String , Object >( );
-			row.put( "resource_identifier" , TEST_STRINGS[ 0 ] );
-			row.put( "resource_name" , TEST_STRINGS[ 1 ] );
-			row.put( "resource_description" , TEST_STRINGS[ 2 ] );
-			if ( i == 1 ) {
-				row.put( "resource_category" , TEST_STRINGS[ 3 ] );
-			}
-			rows[ i ] = row;
-		}
-
-		this.resultSet = MockResultSet.create( rows );
-	}
-
-
-	/** Test mapping a row with a NULL category */
-	@Test
-	public void testMapRowWithoutCategory( )
-			throws SQLException
-	{
-		this.resultSet.absolute( 1 );
-		EmptyResourceRecord record = this.mapper.mapRow( this.resultSet , 1 );
-
-		assertEquals( TEST_STRINGS[ 0 ] , record.getIdentifier( ) );
-		assertEquals( TEST_STRINGS[ 1 ] , record.getTitle( ) );
-		assertEquals( TEST_STRINGS[ 2 ] , record.getDescription( ) );
-		assertNull( record.getCategory( ) );
-	}
-
-
-	/** Test mapping a row with a non-NULL category */
-	@Test
-	public void testMapRowWithCategory( )
-			throws SQLException
-	{
-		this.resultSet.absolute( 2 );
-		EmptyResourceRecord record = this.mapper.mapRow( this.resultSet , 1 );
-
-		assertEquals( TEST_STRINGS[ 0 ] , record.getIdentifier( ) );
-		assertEquals( TEST_STRINGS[ 1 ] , record.getTitle( ) );
-		assertEquals( TEST_STRINGS[ 2 ] , record.getDescription( ) );
-		assertEquals( TEST_STRINGS[ 3 ] , record.getCategory( ) );
-	}
-
-}
diff --git a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/game/resources/TestEmpireResourceMapper.java b/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/game/resources/TestEmpireResourceMapper.java
deleted file mode 100644
index f9966ab..0000000
--- a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/game/resources/TestEmpireResourceMapper.java
+++ /dev/null
@@ -1,104 +0,0 @@
-package com.deepclone.lw.beans.game.resources;
-
-
-import static org.junit.Assert.*;
-
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.util.HashMap;
-
-import org.junit.Before;
-import org.junit.Test;
-
-import com.deepclone.lw.cmd.player.gdata.empire.EmpireResourceRecord;
-import com.deepclone.lw.testing.MockResultSet;
-
-
-
-/**
- * Tests of the {@link EmpireResourceMapper} class.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-public class TestEmpireResourceMapper
-{
-	private static final String TEST_STRING = "Test";
-
-	private static final long POSSESSED_VALUE = 2L;
-
-	private static final long P_INCOME_VALUE = 3L;
-
-	private static final long P_UPKEEP_VALUE = 4L;
-
-	private static final long F_UPKEEP_VALUE = 5L;
-
-	private static final Integer PRIORITY_VALUE = 6;
-
-	/** The fake result set fed to the mapper */
-	private ResultSet resultSet;
-
-	/** The mapper being tested */
-	private EmpireResourceMapper mapper;
-
-
-	@Before
-	public void setUp( )
-	{
-		this.mapper = new EmpireResourceMapper( );
-
-		@SuppressWarnings( "unchecked" )
-		HashMap< String , Object > rows[] = new HashMap[ 2 ];
-		for ( int i = 0 ; i < 2 ; i++ ) {
-			HashMap< String , Object > row = new HashMap< String , Object >( );
-
-			row.put( "resource_identifier" , TEST_STRING );
-
-			row.put( "empres_possessed" , POSSESSED_VALUE + i );
-			row.put( "planets_income" , P_INCOME_VALUE + i );
-			row.put( "planets_upkeep" , P_UPKEEP_VALUE + i );
-			row.put( "fleets_upkeep" , F_UPKEEP_VALUE + i );
-			if ( i == 1 ) {
-				row.put( "empmset_weight" , PRIORITY_VALUE + i );
-			}
-
-			rows[ i ] = row;
-		}
-		this.resultSet = MockResultSet.create( rows );
-	}
-
-
-	/** Test mapping a row that does not include a mining priority */
-	@Test
-	public void testMapWithoutPriority( )
-			throws SQLException
-	{
-		this.resultSet.absolute( 1 );
-		EmpireResourceRecord record = this.mapper.mapRow( this.resultSet , 1 );
-
-		assertEquals( TEST_STRING , record.getIdentifier( ) );
-		assertEquals( POSSESSED_VALUE , record.getStockpiled( ) );
-		assertEquals( P_INCOME_VALUE , record.getIncome( ) );
-		assertEquals( P_UPKEEP_VALUE , record.getPlanetUpkeep( ) );
-		assertEquals( F_UPKEEP_VALUE , record.getFleetUpkeep( ) );
-		assertNull( record.getMiningPriority( ) );
-	}
-
-
-	/** Test mapping a row that includes a mining priority */
-	@Test
-	public void testMapWithPriority( )
-			throws SQLException
-	{
-		this.resultSet.absolute( 2 );
-		EmpireResourceRecord record = this.mapper.mapRow( this.resultSet , 1 );
-
-		assertEquals( TEST_STRING , record.getIdentifier( ) );
-		assertEquals( 1 + POSSESSED_VALUE , record.getStockpiled( ) );
-		assertEquals( 1 + P_INCOME_VALUE , record.getIncome( ) );
-		assertEquals( 1 + P_UPKEEP_VALUE , record.getPlanetUpkeep( ) );
-		assertEquals( 1 + F_UPKEEP_VALUE , record.getFleetUpkeep( ) );
-		assertNotNull( record.getMiningPriority( ) );
-		assertEquals( 1 + PRIORITY_VALUE , (int) record.getMiningPriority( ) );
-	}
-
-}
diff --git a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/game/resources/TestPlanetListResourceRecordMapper.java b/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/game/resources/TestPlanetListResourceRecordMapper.java
deleted file mode 100644
index 3839e80..0000000
--- a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/game/resources/TestPlanetListResourceRecordMapper.java
+++ /dev/null
@@ -1,91 +0,0 @@
-package com.deepclone.lw.beans.game.resources;
-
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.util.HashMap;
-
-import org.junit.Before;
-import org.junit.Test;
-
-import com.deepclone.lw.cmd.player.gdata.PlanetListResourceRecord;
-import com.deepclone.lw.testing.MockResultSet;
-
-
-
-/**
- * Tests for the {@link PlanetListResourceRecordMapper}
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-public class TestPlanetListResourceRecordMapper
-{
-
-	/** Planet identifier value */
-	private static final int TEST_PLANET_ID = 1;
-
-	/** Income value */
-	private static final long TEST_INCOME = 2L;
-
-	/** Upkeep value */
-	private static final long TEST_UPKEEP = 3L;
-
-	/** Civilian investment value */
-	private static final long TEST_CIV_INVESTMENT = 4L;
-
-	/** Military investment value */
-	private static final long TEST_MIL_INVESTMENT = 5L;
-
-	/** Fake result set used as the data source */
-	private ResultSet data;
-
-	/** Row mapper to test */
-	private PlanetListResourceRecordMapper mapper;
-
-
-	/**
-	 * Initialise the row mapper as well as the fake result set
-	 */
-	@Before
-	@SuppressWarnings( "unchecked" )
-	public void setUp( )
-	{
-		HashMap< String , Object > row = new HashMap< String , Object >( );
-		row.put( "planet_id" , TEST_PLANET_ID );
-		row.put( "pres_income" , TEST_INCOME );
-		row.put( "pres_upkeep" , TEST_UPKEEP );
-		row.put( "civ_investment" , TEST_CIV_INVESTMENT );
-		row.put( "mil_investment" , TEST_MIL_INVESTMENT );
-
-		this.data = MockResultSet.create( new HashMap[] {
-			row
-		} );
-
-		this.mapper = new PlanetListResourceRecordMapper( );
-	}
-
-
-	/**
-	 * Try mapping a row
-	 */
-	@Test
-	public void testMapRow( )
-			throws SQLException
-	{
-		this.data.absolute( 1 );
-
-		FullPlanetListRecord fullRecord = this.mapper.mapRow( this.data , 1 );
-		assertEquals( TEST_PLANET_ID , fullRecord.getPlanetId( ) );
-
-		PlanetListResourceRecord record = fullRecord.getRecord( );
-		assertNotNull( record );
-		assertEquals( TEST_INCOME , record.getIncome( ) );
-		assertEquals( TEST_UPKEEP , record.getUpkeep( ) );
-		assertEquals( TEST_CIV_INVESTMENT , record.getCivInvestment( ) );
-		assertEquals( TEST_MIL_INVESTMENT , record.getMilInvestment( ) );
-	}
-
-}
diff --git a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/game/resources/TestPlanetResourceMapper.java b/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/game/resources/TestPlanetResourceMapper.java
deleted file mode 100644
index 5f2990f..0000000
--- a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/game/resources/TestPlanetResourceMapper.java
+++ /dev/null
@@ -1,131 +0,0 @@
-package com.deepclone.lw.beans.game.resources;
-
-
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.util.HashMap;
-
-import static org.junit.Assert.*;
-import org.junit.Before;
-import org.junit.Test;
-
-import com.deepclone.lw.cmd.player.gdata.planets.PlanetResourceRecord;
-import com.deepclone.lw.cmd.player.gdata.planets.ResourceProviderRecord;
-import com.deepclone.lw.testing.MockResultSet;
-
-
-
-/**
- * Tests for {@link PlanetResourceMapper}
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-public class TestPlanetResourceMapper
-{
-
-	/** Value used as the resource identifier */
-	private static final Object RID_VALUE = "resource id";
-
-	/** Value used as the income */
-	private static final long P_INCOME_VALUE = 1;
-
-	/** Value used as the upkeep */
-	private static final long P_UPKEEP_VALUE = 2;
-
-	/** Value used as the investment */
-	private static final long P_INVEST_VALUE = 3;
-
-	/** Value used as the resource provider's capacity */
-	private static final long RP_CAPACITY_VALUE = 5L;
-
-	/** Value used as the resource provider's current quantity */
-	private static final long RP_QUANTITY_VALUE = 6L;
-
-	/** Value used as the resource provider's difficulty */
-	private static final int RP_DIFF_VALUE = 7;
-
-	/** Value used as the mining setting */
-	private static final int MS_WEIGHT_VALUE = 8;
-
-	/** The mapper under test */
-	private PlanetResourceMapper mapper;
-
-	/** The fake result set fed to the mapper */
-	private ResultSet resultSet;
-
-
-	/**
-	 * Create the mapper and a result set to test it with.
-	 */
-	@Before
-	public void setUp( )
-	{
-		this.mapper = new PlanetResourceMapper( );
-
-		@SuppressWarnings( "unchecked" )
-		HashMap< String , Object > rows[] = new HashMap[ 2 ];
-		for ( int i = 0 ; i < 2 ; i++ ) {
-			HashMap< String , Object > row = new HashMap< String , Object >( );
-
-			row.put( "resource_identifier" , RID_VALUE );
-
-			row.put( "pres_income" , P_INCOME_VALUE + i );
-			row.put( "pres_upkeep" , P_UPKEEP_VALUE + i );
-			row.put( "pres_invested" , P_INVEST_VALUE + i );
-			if ( i == 1 ) {
-				row.put( "resprov_capacity" , RP_CAPACITY_VALUE );
-				row.put( "resprov_quantity" , RP_QUANTITY_VALUE );
-				row.put( "resprov_difficulty" , RP_DIFF_VALUE );
-				row.put( "mset_weight" , MS_WEIGHT_VALUE );
-			}
-
-			rows[ i ] = row;
-		}
-		this.resultSet = MockResultSet.create( rows );
-	}
-
-
-	/**
-	 * Planet resource row with no resource provider
-	 */
-	@Test
-	public void testRowWithoutResourceProvider( )
-			throws SQLException
-	{
-		this.resultSet.absolute( 1 );
-		PlanetResourceRecord row = this.mapper.mapRow( this.resultSet , 1 );
-
-		assertEquals( RID_VALUE , row.getIdentifier( ) );
-
-		assertEquals( P_INCOME_VALUE , row.getIncome( ) );
-		assertEquals( P_UPKEEP_VALUE , row.getUpkeep( ) );
-		assertEquals( P_INVEST_VALUE , row.getInvested( ) );
-
-		assertNull( row.getResourceProvider( ) );
-	}
-
-
-	/**
-	 * Planet resource row with a resource provider
-	 */
-	@Test
-	public void testRowWithResourceProvider( )
-			throws SQLException
-	{
-		this.resultSet.absolute( 2 );
-		PlanetResourceRecord row = this.mapper.mapRow( this.resultSet , 2 );
-
-		assertEquals( RID_VALUE , row.getIdentifier( ) );
-
-		assertEquals( P_INCOME_VALUE + 1 , row.getIncome( ) );
-		assertEquals( P_UPKEEP_VALUE + 1 , row.getUpkeep( ) );
-		assertEquals( P_INVEST_VALUE + 1 , row.getInvested( ) );
-
-		ResourceProviderRecord rp = row.getResourceProvider( );
-		assertNotNull( rp );
-		assertEquals( RP_CAPACITY_VALUE , rp.getCapacity( ) );
-		assertEquals( RP_QUANTITY_VALUE , rp.getQuantity( ) );
-		assertEquals( RP_DIFF_VALUE , rp.getDifficulty( ) );
-		assertEquals( MS_WEIGHT_VALUE , rp.getPriority( ) );
-	}
-}
diff --git a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/game/resources/TestResourcesControllerBean.java b/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/game/resources/TestResourcesControllerBean.java
deleted file mode 100644
index 393b577..0000000
--- a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/game/resources/TestResourcesControllerBean.java
+++ /dev/null
@@ -1,157 +0,0 @@
-package com.deepclone.lw.beans.game.resources;
-
-
-import static org.junit.Assert.*;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.junit.Before;
-import org.junit.Test;
-
-import com.deepclone.lw.interfaces.game.resources.MiningSettingsDAO;
-
-
-
-/**
- * Tests for {@link ResourcesControllerBean}
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- * 
- */
-public class TestResourcesControllerBean
-{
-
-	/** Empire identifier used in the tests */
-	private static final Integer EMPIRE_ID = 42;
-
-	/** Planet identifier used in the tests */
-	private static final Integer PLANET_ID = 43;
-
-	/** Mining settings used in the tests */
-	private static final Map< String , Integer > MINING_SETTINGS;
-
-	/**
-	 * Initialise the mining settings map
-	 */
-	static {
-		HashMap< String , Integer > tempMap = new HashMap< String , Integer >( );
-		tempMap.put( "test 1" , 1 );
-		tempMap.put( "test 2" , 2 );
-		tempMap.put( "test 3" , 3 );
-		tempMap.put( "test 4" , 4 );
-		MINING_SETTINGS = Collections.unmodifiableMap( tempMap );
-	}
-
-	/** The mock database access object */
-	private MockMiningSettingsDAO miningSettingsDAO;
-
-	/** The instance to test on */
-	private ResourcesControllerBean ctrl;
-
-
-	/**
-	 * Create the resource controller that will be used in the tests and its various (usually fake)
-	 * dependencies
-	 */
-	@Before
-	public void setUp( )
-	{
-		this.miningSettingsDAO = new MockMiningSettingsDAO( );
-		this.ctrl = new ResourcesControllerBean( );
-		this.ctrl.setMiningSettingsDAO( this.miningSettingsDAO );
-	}
-
-
-	/**
-	 * When calling {@link MiningSettingsDAO#startUpdate(int)} fails, the empire settings update is
-	 * interrupted.
-	 */
-	@Test
-	public void testEmpireStartUpdateFails( )
-	{
-		this.miningSettingsDAO.setStartUpdateSucceeds( false );
-		this.ctrl.updateEmpireSettings( EMPIRE_ID , MINING_SETTINGS );
-		assertTrue( this.miningSettingsDAO.wasStartUpdateCalled( ) );
-		assertEquals( EMPIRE_ID , this.miningSettingsDAO.getEmpire( ) );
-		assertEquals( 0 , this.miningSettingsDAO.getCallsToSet( ) );
-		assertFalse( this.miningSettingsDAO.wasApplyCalled( ) );
-	}
-
-
-	/**
-	 * When calling {@link MiningSettingsDAO#startUpdate(int,int)} fails, the planet settings update
-	 * is interrupted.
-	 */
-	@Test
-	public void testPlanetStartUpdateFails( )
-	{
-		this.miningSettingsDAO.setStartUpdateSucceeds( false );
-		this.ctrl.updatePlanetSettings( EMPIRE_ID , PLANET_ID , MINING_SETTINGS );
-		assertTrue( this.miningSettingsDAO.wasStartUpdateCalled( ) );
-		assertEquals( EMPIRE_ID , this.miningSettingsDAO.getEmpire( ) );
-		assertEquals( PLANET_ID , this.miningSettingsDAO.getPlanet( ) );
-		assertEquals( 0 , this.miningSettingsDAO.getCallsToSet( ) );
-		assertFalse( this.miningSettingsDAO.wasApplyCalled( ) );
-	}
-
-
-	/**
-	 * When calling {@link MiningSettingsDAO#startUpdate(int)} succeeds but one of the calls to
-	 * {@link MiningSettingsDAO#setNewPriority(String, int)} fails, the update is interrupted.
-	 */
-	@Test
-	public void testSetMiningPriorityFails( )
-	{
-		this.miningSettingsDAO.setMaxSetCalls( 2 );
-		this.ctrl.updateEmpireSettings( EMPIRE_ID , MINING_SETTINGS );
-		assertTrue( this.miningSettingsDAO.wasStartUpdateCalled( ) );
-		assertEquals( EMPIRE_ID , this.miningSettingsDAO.getEmpire( ) );
-		assertEquals( 3 , this.miningSettingsDAO.getCallsToSet( ) );
-		assertFalse( this.miningSettingsDAO.wasApplyCalled( ) );
-	}
-
-
-	/**
-	 * If both {@link MiningSettingsDAO#startUpdate(int)} and
-	 * {@link MiningSettingsDAO#setNewPriority(String, int)} succeed,
-	 * {@link MiningSettingsDAO#applyUpdate()} is called.
-	 */
-	@Test
-	public void testSettingsSuccess( )
-	{
-		this.ctrl.updateEmpireSettings( EMPIRE_ID , MINING_SETTINGS );
-		assertTrue( this.miningSettingsDAO.wasStartUpdateCalled( ) );
-		assertEquals( EMPIRE_ID , this.miningSettingsDAO.getEmpire( ) );
-		assertEquals( 4 , this.miningSettingsDAO.getCallsToSet( ) );
-		assertTrue( this.miningSettingsDAO.wasApplyCalled( ) );
-	}
-
-
-	/**
-	 * A failure of {@link MiningSettingsDAO#applyUpdate()} has no influence on the call.
-	 */
-	@Test
-	public void testSettingsApplyFail( )
-	{
-		this.miningSettingsDAO.setApplyUpdateSucceeds( false );
-		this.ctrl.updateEmpireSettings( EMPIRE_ID , MINING_SETTINGS );
-		assertTrue( this.miningSettingsDAO.wasStartUpdateCalled( ) );
-		assertEquals( EMPIRE_ID , this.miningSettingsDAO.getEmpire( ) );
-		assertEquals( 4 , this.miningSettingsDAO.getCallsToSet( ) );
-		assertTrue( this.miningSettingsDAO.wasApplyCalled( ) );
-	}
-
-	/**
-	 * "Toggle planet source" calls {@link MiningSettingsDAO#togglePlanet(int, int)}
-	 */
-	@Test
-	public void tesTogglePlanet()
-	{
-		this.ctrl.togglePlanet( EMPIRE_ID , PLANET_ID );
-		assertTrue( this.miningSettingsDAO.wasTogllePlanetCalled( ) );
-		assertEquals( EMPIRE_ID , this.miningSettingsDAO.getEmpire( ) );
-		assertEquals( PLANET_ID , this.miningSettingsDAO.getPlanet( ) );
-	}
-}
diff --git a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/naming/TestObjectNameValidatorBean.java b/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/naming/TestObjectNameValidatorBean.java
deleted file mode 100644
index 1e9d197..0000000
--- a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/naming/TestObjectNameValidatorBean.java
+++ /dev/null
@@ -1,249 +0,0 @@
-package com.deepclone.lw.beans.naming;
-
-
-import static org.junit.Assert.*;
-
-import org.junit.Before;
-import org.junit.Test;
-
-import com.deepclone.lw.cmd.ObjectNameError;
-
-
-
-/**
- * Tests for {@link ObjectNameValidatorBean}
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- * 
- */
-public class TestObjectNameValidatorBean
-{
-
-	/** Object name validator being tested */
-	private ObjectNameValidatorBean validator;
-
-
-	/**
-	 * Create the validator to run tests on
-	 */
-	@Before
-	public void setUp( )
-	{
-		this.validator = new ObjectNameValidatorBean( );
-	}
-
-
-	/**
-	 * A string shorter than the default minimal length will cause validation to fail with the
-	 * {@link ObjectNameError#INVALID} error on an unmodified validator.
-	 */
-	@Test
-	public void testDefaultMinimalLength( )
-	{
-		String test = "";
-		for ( int i = 0 ; i < ObjectNameValidatorBean.MIN_LENGTH - 1 ; i++ ) {
-			test += "x";
-		}
-
-		ObjectNameError error = this.validator.validate( test );
-		assertNotNull( error );
-		assertEquals( ObjectNameError.INVALID , error );
-	}
-
-
-	/**
-	 * A string longer than the default maximal length will cause validation to fail with the
-	 * {@link ObjectNameError#INVALID} error on an unmodified validator.
-	 */
-	@Test
-	public void testDefaultMaximalLength( )
-	{
-		String test = "";
-		for ( int i = 0 ; i < ObjectNameValidatorBean.MAX_LENGTH + 1 ; i++ ) {
-			test += "x";
-		}
-
-		ObjectNameError error = this.validator.validate( test );
-		assertNotNull( error );
-		assertEquals( ObjectNameError.INVALID , error );
-	}
-
-
-	/**
-	 * A string shorter than a modified minimal length will cause validation to fail with the
-	 * {@link ObjectNameError#INVALID} error.
-	 */
-	@Test
-	public void testMinimalLength( )
-	{
-		String test = "";
-		for ( int i = 0 ; i < 3 ; i++ ) {
-			test += "x";
-		}
-
-		this.validator.setMinLength( 4 );
-		this.validator.setMaxLength( 10 );
-		ObjectNameError error = this.validator.validate( test );
-		assertNotNull( error );
-		assertEquals( ObjectNameError.INVALID , error );
-	}
-
-
-	/**
-	 * A string longer than a modified maximal length will cause validation to fail with the
-	 * {@link ObjectNameError#INVALID} error on an unmodified validator.
-	 */
-	@Test
-	public void testMaximalLength( )
-	{
-		String test = "";
-		for ( int i = 0 ; i < 11 ; i++ ) {
-			test += "x";
-		}
-
-		this.validator.setMinLength( 4 );
-		this.validator.setMaxLength( 10 );
-		ObjectNameError error = this.validator.validate( test );
-		assertNotNull( error );
-		assertEquals( ObjectNameError.INVALID , error );
-	}
-
-
-	/**
-	 * A string that's empty will cause an {@link ObjectNameError#EMPTY} error.
-	 */
-	@Test
-	public void testEmptyString( )
-	{
-		String test = "";
-		ObjectNameError error = this.validator.validate( test );
-		assertNotNull( error );
-		assertEquals( ObjectNameError.EMPTY , error );
-	}
-
-
-	/**
-	 * A string that's full of spaces will cause an {@link ObjectNameError#EMPTY} error.
-	 */
-	@Test
-	public void testSpacesOnlyString( )
-	{
-		String test = "       ";
-		ObjectNameError error = this.validator.validate( test );
-		assertNotNull( error );
-		assertEquals( ObjectNameError.EMPTY , error );
-	}
-
-
-	/**
-	 * An otherwise valid string that starts with spaces will cause an
-	 * {@link ObjectNameError#INVALID} error.
-	 */
-	@Test
-	public void testStringStartsWithSpace( )
-	{
-		String test = " abcde";
-		this.validator.setMinLength( 1 );
-		this.validator.setMaxLength( 10 );
-		ObjectNameError error = this.validator.validate( test );
-		assertNotNull( error );
-		assertEquals( ObjectNameError.INVALID , error );
-	}
-
-
-	/**
-	 * An otherwise valid string that ends with spaces will cause an {@link ObjectNameError#INVALID}
-	 * error.
-	 */
-	@Test
-	public void testStringEndsWithSpace( )
-	{
-		String test = "abcde ";
-		this.validator.setMinLength( 1 );
-		this.validator.setMaxLength( 10 );
-		ObjectNameError error = this.validator.validate( test );
-		assertNotNull( error );
-		assertEquals( ObjectNameError.INVALID , error );
-	}
-
-
-	/**
-	 * An otherwise valid string that contains a sequence of two spaces will cause an
-	 * {@link ObjectNameError#INVALID} error.
-	 */
-	@Test
-	public void testStringSpaceSequence( )
-	{
-		String test = "ab  cde";
-		this.validator.setMinLength( 1 );
-		this.validator.setMaxLength( 10 );
-		ObjectNameError error = this.validator.validate( test );
-		assertNotNull( error );
-		assertEquals( ObjectNameError.INVALID , error );
-	}
-
-
-	/**
-	 * A string that contains an unsupported character will cause an {@link ObjectNameError#INVALID}
-	 * error.
-	 */
-	@Test
-	public void testStringInvalidCharacter( )
-	{
-		String test = "abcdœ";
-		this.validator.setMinLength( 1 );
-		this.validator.setMaxLength( 10 );
-		ObjectNameError error = this.validator.validate( test );
-		assertNotNull( error );
-		assertEquals( ObjectNameError.INVALID , error );
-	}
-
-
-	/**
-	 * A string that does not contain any letter (but is otherwise valid) will cause an
-	 * {@link ObjectNameError#INVALID} error.
-	 */
-	@Test
-	public void testStringNoLetters( )
-	{
-		String test = "@_@12";
-		this.validator.setMinLength( 1 );
-		this.validator.setMaxLength( 10 );
-		ObjectNameError error = this.validator.validate( test );
-		assertNotNull( error );
-		assertEquals( ObjectNameError.INVALID , error );
-	}
-
-
-	/**
-	 * Test validation on a "good" string
-	 */
-	@Test
-	public void testValidString( )
-	{
-		this.validator.setMinLength( 1 );
-		this.validator.setMaxLength( 5 );
-
-		ObjectNameError error = this.validator.validate( "ab12@" );
-		assertNull( error );
-	}
-
-
-
-	/**
-	 * Test validation with call-specific length constraints
-	 */
-	@Test
-	public void testLengthConstraints( )
-	{
-		this.validator.setMinLength( 5 );
-		this.validator.setMaxLength( 6 );
-
-		ObjectNameError error = this.validator.validate( "ab" , 2 , 10 );
-		assertNull( error );
-
-		error = this.validator.validate( "a012345678" , 2 , 10 );
-		assertNull( error );
-	}
-
-}
diff --git a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/updates/DummyBatchProcessor.java b/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/updates/DummyBatchProcessor.java
deleted file mode 100644
index bc5c718..0000000
--- a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/updates/DummyBatchProcessor.java
+++ /dev/null
@@ -1,62 +0,0 @@
-package com.deepclone.lw.beans.updates;
-
-
-import java.util.Collection;
-import java.util.HashSet;
-
-import com.deepclone.lw.interfaces.game.updates.UpdateBatchProcessor;
-
-
-
-/**
- * A dummy batch processor used in game update tests
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-class DummyBatchProcessor
-		implements UpdateBatchProcessor
-{
-	/** The name that will be returned by {@link #getUpdateType()} */
-	private final String updateType;
-
-	/** Ticks for which the {@link #processBatch(long)} was called */
-	private final HashSet< Long > ticks = new HashSet< Long >( );
-
-
-	/**
-	 * Set the update type
-	 * 
-	 * @param updateType
-	 *            the update type
-	 */
-	public DummyBatchProcessor( String updateType )
-	{
-		this.updateType = updateType;
-	}
-
-
-	/**
-	 * @return whatever type name was set when the instance was created
-	 */
-	@Override
-	public String getUpdateType( )
-	{
-		return this.updateType;
-	}
-
-
-	/** Adds the specified tick identifier to the set of ticks */
-	@Override
-	public void processBatch( long tickId )
-	{
-		this.ticks.add( tickId );
-	}
-
-
-	/** @return the set of ticks for which {@link #processBatch(long)} was called */
-	Collection< Long > getTicks( )
-	{
-		return this.ticks;
-	}
-
-}
diff --git a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/updates/MockGameUpdateProcessor.java b/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/updates/MockGameUpdateProcessor.java
deleted file mode 100644
index d719661..0000000
--- a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/updates/MockGameUpdateProcessor.java
+++ /dev/null
@@ -1,91 +0,0 @@
-package com.deepclone.lw.beans.updates;
-
-
-import com.deepclone.lw.interfaces.game.updates.GameUpdateProcessor;
-
-
-
-/**
- * A mock game update processor
- * 
- * <p>
- * This mock component keeps track of which of its methods have been called. It can also simulate
- * runtime errors during tick processing.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- * 
- */
-public class MockGameUpdateProcessor
-		implements GameUpdateProcessor
-{
-	private boolean tryLockCalled = false;
-	private boolean unlockCalled = false;
-	private boolean endCycleCalled = false;
-	private boolean executeCalled = false;
-
-	private boolean failExecute = false;
-
-
-	public boolean wasTryLockCalled( )
-	{
-		return this.tryLockCalled;
-	}
-
-
-	public boolean wasUnlockCalled( )
-	{
-		return this.unlockCalled;
-	}
-
-
-	public boolean wasEndCycleCalled( )
-	{
-		return this.endCycleCalled;
-	}
-
-
-	public boolean wasExecuteCalled( )
-	{
-		return this.executeCalled;
-	}
-
-
-	public void setFailExecute( boolean failExecute )
-	{
-		this.failExecute = failExecute;
-	}
-
-
-	@Override
-	public boolean tryLock( )
-	{
-		this.tryLockCalled = true;
-		return true;
-	}
-
-
-	@Override
-	public void unlock( )
-	{
-		this.unlockCalled = true;
-	}
-
-
-	@Override
-	public boolean endPreviousCycle( )
-	{
-		this.endCycleCalled = true;
-		return false;
-	}
-
-
-	@Override
-	public void executeUpdateCycle( )
-	{
-		this.executeCalled = true;
-		if ( this.failExecute ) {
-			throw new RuntimeException( "fail" );
-		}
-	}
-
-}
diff --git a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/updates/MockRegistry.java b/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/updates/MockRegistry.java
deleted file mode 100644
index 60ac8fc..0000000
--- a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/updates/MockRegistry.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package com.deepclone.lw.beans.updates;
-
-
-import java.util.HashMap;
-
-import com.deepclone.lw.interfaces.game.updates.UpdateBatchProcessor;
-
-
-
-/**
- * A mock processor registry
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-class MockRegistry
-		implements ServerProcessorRegistry
-{
-
-	/** The map of "processors" to return */
-	private final HashMap< String , UpdateBatchProcessor > processors = new HashMap< String , UpdateBatchProcessor >( );
-
-
-	/**
-	 * Add a processor to the registry
-	 * 
-	 * @param processor
-	 *            the processor to add
-	 */
-	public void put( UpdateBatchProcessor processor )
-	{
-		this.processors.put( processor.getUpdateType( ) , processor );
-	}
-
-
-	@Override
-	public UpdateBatchProcessor getProcessorFor( String type )
-	{
-		return this.processors.get( type );
-	}
-
-}
diff --git a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/updates/MockUpdatesDAO.java b/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/updates/MockUpdatesDAO.java
deleted file mode 100644
index 5cf16d6..0000000
--- a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/updates/MockUpdatesDAO.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package com.deepclone.lw.beans.updates;
-
-
-import com.deepclone.lw.interfaces.game.updates.UpdatesDAO;
-import com.deepclone.lw.sqld.sys.GameUpdateResult;
-
-
-
-/**
- * Mock updates DAO used in tests
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-class MockUpdatesDAO
-		implements UpdatesDAO
-{
-	/** The index to read at the next call to {@link #processUpdates(long)} */
-	public int index = 0;
-
-	/** The values to return as the update type to process */
-	public String[] values = new String[] { };
-
-
-	@Override
-	public GameUpdateResult processUpdates( long tickId )
-	{
-		if ( this.index >= this.values.length ) {
-			return new GameUpdateResult( );
-		}
-		return new GameUpdateResult( this.values[ this.index++ ] );
-	}
-}
diff --git a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/updates/TestGameUpdateProcessorBean.java b/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/updates/TestGameUpdateProcessorBean.java
deleted file mode 100644
index d6ff2da..0000000
--- a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/updates/TestGameUpdateProcessorBean.java
+++ /dev/null
@@ -1,240 +0,0 @@
-package com.deepclone.lw.beans.updates;
-
-
-import static org.junit.Assert.*;
-
-import java.sql.Timestamp;
-import java.util.Date;
-
-import org.junit.Before;
-import org.junit.Test;
-
-import com.deepclone.lw.interfaces.game.updates.UpdateBatchProcessor;
-import com.deepclone.lw.interfaces.sys.MaintenanceData;
-import com.deepclone.lw.testing.MockLogger;
-import com.deepclone.lw.testing.MockSystemStatus;
-import com.deepclone.lw.testing.MockTransactionManager;
-
-
-
-/**
- * Tests for {@link GameUpdateProcessorBean}
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-public class TestGameUpdateProcessorBean
-{
-
-	/** The mock logger */
-	private MockLogger logger;
-
-	/** Mock updates access interface */
-	private MockUpdatesDAO updatesDAO;
-
-	/** Mock processor registry */
-	private MockRegistry registry;
-
-	/** Mock system status component */
-	private MockSystemStatus system;
-
-	/** The instance under test */
-	private GameUpdateProcessorBean gup;
-
-	/**
-	 * A fake batch processor which actually enables maintenance mode.
-	 * 
-	 * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
-	 */
-	private static class MaintenanceEnabler
-			implements UpdateBatchProcessor
-	{
-
-		/** Mock system status component */
-		private MockSystemStatus system;
-
-
-		/**
-		 * Set the mock system status component
-		 * 
-		 * @param system
-		 *            the mock system status component
-		 */
-		MaintenanceEnabler( MockSystemStatus system )
-		{
-			this.system = system;
-		}
-
-
-		@Override
-		public String getUpdateType( )
-		{
-			return "maintenance";
-		}
-
-
-		@Override
-		public void processBatch( long tickId )
-		{
-			this.system.setMaintenance( new MaintenanceData( new Timestamp( new Date( ).getTime( ) ) , new Timestamp(
-					new Date( ).getTime( ) ) , "no reason" ) );
-		}
-
-	}
-
-
-	@Before
-	public void setUp( )
-	{
-		this.logger = new MockLogger( );
-		this.updatesDAO = new MockUpdatesDAO( );
-		this.updatesDAO.values = new String[] {
-			null
-		};
-		this.system = new MockSystemStatus( );
-		this.registry = new MockRegistry( );
-		this.registry.put( new MaintenanceEnabler( this.system ) );
-
-		this.gup = new GameUpdateProcessorBean( );
-		this.gup.setLogger( this.logger );
-		this.gup.setUpdatesDAO( this.updatesDAO );
-		this.gup.setRegistry( this.registry );
-		this.gup.setTransactionManager( new MockTransactionManager( ) );
-		this.gup.setSystemStatus( this.system );
-	}
-
-
-	/**
-	 * Try locking the processor
-	 */
-	@Test
-	public void testLocking( )
-	{
-		assertTrue( this.gup.tryLock( ) );
-		assertFalse( this.gup.tryLock( ) );
-	}
-
-
-	/** Try unlocking the processor */
-	@Test
-	public void testUnlocking( )
-	{
-		this.gup.tryLock( );
-		this.gup.unlock( );
-		assertTrue( this.gup.tryLock( ) );
-	}
-
-
-	/** Try unlocking the processor when it's not locked */
-	@Test( expected = IllegalStateException.class )
-	public void testUnlockingWithNoLock( )
-	{
-		this.gup.unlock( );
-	}
-
-
-	/**
-	 * {@link GameUpdateProcessorBean#endPreviousCycle()} returns <code>false</code> when there is
-	 * no "stuck" tick
-	 */
-	@Test
-	public void testEndCycleNoStuckTick( )
-	{
-		assertFalse( this.gup.endPreviousCycle( ) );
-	}
-
-
-	/**
-	 * {@link GameUpdateProcessorBean#endPreviousCycle()} returns <code>true</code> when maintenance
-	 * mode is enabled, but the update is not processed
-	 */
-	@Test
-	public void testEndCycleMaintenance( )
-	{
-		this.system.setCSTBehaviour( -2 );
-		assertTrue( this.gup.endPreviousCycle( ) );
-		assertEquals( 0 , this.updatesDAO.index );
-	}
-
-
-	/**
-	 * {@link GameUpdateProcessorBean#endPreviousCycle()} returns <code>true</code> when there is a
-	 * stuck tick, and the update is processed
-	 */
-	@Test
-	public void testEndCycle( )
-	{
-		this.system.setCSTBehaviour( 0 );
-		assertTrue( this.gup.endPreviousCycle( ) );
-		assertEquals( 1 , this.updatesDAO.index );
-	}
-
-
-	/**
-	 * {@link GameUpdateProcessorBean#executeUpdateCycle()} does not start a tick if there was a
-	 * stuck tick, but the previous tick is processed.
-	 */
-	@Test
-	public void testProcessWithStuckTick( )
-	{
-		this.system.setCSTBehaviour( 0 );
-		this.gup.executeUpdateCycle( );
-		assertFalse( this.system.wasStartTickCalled( ) );
-		assertEquals( 1 , this.updatesDAO.index );
-	}
-
-
-	/**
-	 * {@link GameUpdateProcessorBean#executeUpdateCycle()} does not start a tick if maintenance
-	 * mode was enabled from the start
-	 */
-	@Test
-	public void testProcessWithStuckTickAndMaintenance( )
-	{
-		this.system.setCSTBehaviour( -2 );
-		this.gup.executeUpdateCycle( );
-		assertFalse( this.system.wasStartTickCalled( ) );
-		assertEquals( 0 , this.updatesDAO.index );
-	}
-
-
-	/**
-	 * {@link GameUpdateProcessorBean#executeUpdateCycle()} does not start a tick if maintenance
-	 * mode is enabled between the check for stuck ticks and the new tick's start.
-	 */
-	@Test
-	public void testProcessWithMaintenance( )
-	{
-		this.system.setSTBehaviour( -2 );
-		this.gup.executeUpdateCycle( );
-		assertTrue( this.system.wasStartTickCalled( ) );
-		assertEquals( 0 , this.updatesDAO.index );
-	}
-
-
-	/**
-	 * {@link GameUpdateProcessorBean#executeUpdateCycle()} throws a runtime exception if there
-	 * seems to be a tick running when the new tick is supposed to start.
-	 */
-	@Test( expected = RuntimeException.class )
-	public void testProcessWithBadState( )
-	{
-		this.system.setSTBehaviour( -1 );
-		this.gup.executeUpdateCycle( );
-	}
-
-
-	/**
-	 * {@link GameUpdateProcessorBean#executeUpdateCycle()} stops processing mid-way if maintenance
-	 * mode becomes enabled
-	 */
-	@Test
-	public void testProcessWithMaintenanceEnabledMidWay( )
-	{
-		this.updatesDAO.values = new String[] {
-				null , "maintenance" , null
-		};
-		this.gup.executeUpdateCycle( );
-		assertTrue( this.system.wasStartTickCalled( ) );
-		assertEquals( 2 , this.updatesDAO.index );
-	}
-}
diff --git a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/updates/TestGameUpdateTaskBean.java b/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/updates/TestGameUpdateTaskBean.java
deleted file mode 100644
index 1f97148..0000000
--- a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/updates/TestGameUpdateTaskBean.java
+++ /dev/null
@@ -1,93 +0,0 @@
-package com.deepclone.lw.beans.updates;
-
-
-import static org.junit.Assert.*;
-
-import org.junit.Before;
-import org.junit.Test;
-
-import com.deepclone.lw.interfaces.sys.Ticker.Frequency;
-import com.deepclone.lw.testing.MockTicker;
-
-
-
-/**
- * Tests for {@link GameUpdateTaskBean}
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-public class TestGameUpdateTaskBean
-{
-	/** The mock ticker */
-	private MockTicker ticker;
-
-	/** The mock game update processor */
-	private MockGameUpdateProcessor processor;
-
-	/** The game update task */
-	private GameUpdateTaskBean gut;
-
-
-	/**
-	 * Initialise the mock components and the game update task instance
-	 */
-	@Before
-	public void setUp( )
-	{
-		this.ticker = new MockTicker( Frequency.MINUTE , "Game update" , GameUpdateTaskBean.class );
-		this.processor = new MockGameUpdateProcessor( );
-
-		this.gut = new GameUpdateTaskBean( );
-		this.gut.setTicker( this.ticker );
-		this.gut.setGameUpdateProcessor( this.processor );
-	}
-
-
-	/**
-	 * Check the component's initialisation
-	 */
-	@Test
-	public void testInitialisation( )
-	{
-		this.gut.afterPropertiesSet( );
-		assertTrue( this.processor.wasTryLockCalled( ) );
-		assertTrue( this.processor.wasUnlockCalled( ) );
-		assertTrue( this.processor.wasEndCycleCalled( ) );
-		assertFalse( this.processor.wasExecuteCalled( ) );
-	}
-
-
-	/**
-	 * Check the component's run() method
-	 */
-	@Test
-	public void testNormalRun( )
-	{
-		this.gut.run( );
-		assertTrue( this.processor.wasTryLockCalled( ) );
-		assertTrue( this.processor.wasUnlockCalled( ) );
-		assertFalse( this.processor.wasEndCycleCalled( ) );
-		assertTrue( this.processor.wasExecuteCalled( ) );
-	}
-
-
-	/**
-	 * Make sure the component is unlocked even if the execution fails
-	 */
-	@Test
-	public void testFailedRun( )
-	{
-		this.processor.setFailExecute( true );
-		try {
-			this.gut.run( );
-			fail( "Mock processor failed to fail" );
-		} catch ( RuntimeException e ) {
-			// EMPTY
-		}
-		assertTrue( this.processor.wasTryLockCalled( ) );
-		assertTrue( this.processor.wasUnlockCalled( ) );
-		assertFalse( this.processor.wasEndCycleCalled( ) );
-		assertTrue( this.processor.wasExecuteCalled( ) );
-	}
-
-}
diff --git a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/updates/TestGameUpdateTransaction.java b/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/updates/TestGameUpdateTransaction.java
deleted file mode 100644
index 2484435..0000000
--- a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/updates/TestGameUpdateTransaction.java
+++ /dev/null
@@ -1,86 +0,0 @@
-package com.deepclone.lw.beans.updates;
-
-
-import static org.junit.Assert.*;
-import org.junit.Before;
-import org.junit.Test;
-
-
-
-/**
- * Tests for {@link GameUpdateTransaction}
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-public class TestGameUpdateTransaction
-{
-
-	/** The mock updates DAO */
-	private MockUpdatesDAO updatesDAO;
-
-	/** The dummy batch processor used in the tests */
-	private DummyBatchProcessor processor;
-
-	/** The mock processor registry */
-	private MockRegistry registry;
-
-	/** The game update transaction used as a "guinea pig" */
-	private GameUpdateTransaction transaction;
-
-
-	/** Set up the mock objects and the guinea pig transaction instance */
-	@Before
-	public void setUp( )
-	{
-		this.updatesDAO = new MockUpdatesDAO( );
-		this.registry = new MockRegistry( );
-		this.registry.put( this.processor = new DummyBatchProcessor( "test" ) );
-		this.transaction = new GameUpdateTransaction( this.updatesDAO , this.registry , 1 );
-	}
-
-
-	/** Test return value when the stored procedure says that no more updates are to be processed */
-	@Test
-	public void testWhenFinished( )
-	{
-		assertTrue( this.transaction.doInTransaction( null ) );
-	}
-
-
-	/** Test return value when the stored procedure says that more updates are to be processed */
-	@Test
-	public void testWhenHasMore( )
-	{
-		this.updatesDAO.values = new String[] {
-			null
-		};
-		assertFalse( this.transaction.doInTransaction( null ) );
-	}
-
-
-	/** Test what happens when the stored procedure indicates the need for local processing */
-	@Test
-	public void testLocalProcessing( )
-	{
-		this.updatesDAO.values = new String[] {
-			"test"
-		};
-		assertFalse( this.transaction.doInTransaction( null ) );
-		assertEquals( 1 , this.processor.getTicks( ).size( ) );
-		assertTrue( this.processor.getTicks( ).contains( 1L ) );
-	}
-
-
-	/**
-	 * Test what happens when the stored procedure indicates the need for local processing but the
-	 * specified processor does not exist
-	 */
-	@Test( expected = UnsupportedUpdateException.class )
-	public void testMissingProcessor( )
-	{
-		this.updatesDAO.values = new String[] {
-			"missing processor"
-		};
-		this.transaction.doInTransaction( null );
-	}
-}
diff --git a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/updates/TestServerProcessorRegistryBean.java b/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/updates/TestServerProcessorRegistryBean.java
deleted file mode 100644
index 65fca67..0000000
--- a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/updates/TestServerProcessorRegistryBean.java
+++ /dev/null
@@ -1,62 +0,0 @@
-package com.deepclone.lw.beans.updates;
-
-
-import static org.junit.Assert.*;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.springframework.beans.factory.BeanInitializationException;
-
-
-
-/**
- * Tests for {@link ServerProcessorRegistryBean}
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-public class TestServerProcessorRegistryBean
-{
-	/** The "guinea pig" instance */
-	private ServerProcessorRegistryBean registry;
-
-
-	@Before
-	public void setUp( )
-	{
-		this.registry = new ServerProcessorRegistryBean( );
-		this.registry.postProcessAfterInitialization( new DummyBatchProcessor( "test" ) , "test" );
-	}
-
-
-	/** The registry returns <code>null</code> when the type has no processor */
-	@Test
-	public void testMissingReturnsNull( )
-	{
-		assertNull( this.registry.getProcessorFor( "does not exist" ) );
-	}
-
-
-	/** The registry returns the processor when there is one */
-	@Test
-	public void testExistingReturnsProcessor( )
-	{
-		assertNotNull( this.registry.getProcessorFor( "test" ) );
-	}
-
-
-	/** The registry ignores objects which are not batch processors */
-	@Test
-	public void testIgnoresOtherObjects( )
-	{
-		this.registry.postProcessAfterInitialization( "test" , "test" );
-	}
-
-
-	/** The registry crashes when two batch processors are defined for the same type */
-	@Test( expected = BeanInitializationException.class )
-	public void testFailsIfDuplicate( )
-	{
-		this.registry.postProcessAfterInitialization( new DummyBatchProcessor( "test" ) , "test" );
-	}
-
-}
diff --git a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/cli/xmlimport/TestI18NLoader.java b/legacyworlds-server-tests/src/test/java/com/deepclone/lw/cli/xmlimport/TestI18NLoader.java
deleted file mode 100644
index a44feed..0000000
--- a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/cli/xmlimport/TestI18NLoader.java
+++ /dev/null
@@ -1,141 +0,0 @@
-package com.deepclone.lw.cli.xmlimport;
-
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import java.io.File;
-import java.io.IOException;
-
-import org.junit.Test;
-
-import com.deepclone.lw.cli.xmlimport.data.DataImportException;
-import com.deepclone.lw.cli.xmlimport.data.i18n.I18NText;
-import com.deepclone.lw.cli.xmlimport.data.i18n.LanguageDefinition;
-import com.thoughtworks.xstream.converters.ConversionException;
-import com.thoughtworks.xstream.io.StreamException;
-
-
-
-/**
- * Unit tests for the {@link I18NLoader} class.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- * 
- */
-public class TestI18NLoader
-{
-
-	/**
-	 * Try initialising the loader with a <code>null</code> file instance.
-	 * 
-	 * @throws NullPointerException
-	 *             when the constructor is executed
-	 */
-	@Test( expected = NullPointerException.class )
-	public void testNullFile( )
-			throws NullPointerException
-	{
-		new I18NLoader( null );
-	}
-
-
-	/**
-	 * Try loading a file that does not exist
-	 */
-	@Test
-	public void testMissingFile( )
-	{
-		I18NLoader loader = new I18NLoader( new File( "does-not-exist" ) );
-		try {
-			loader.load( );
-		} catch ( DataImportException e ) {
-			assertTrue( "cause is a " + e.getCause( ).getClass( ).getName( ) , e.getCause( ) instanceof IOException );
-			return;
-		}
-		fail( "no exception after trying to load a missing file" );
-	}
-
-
-	/**
-	 * Try loading a file that contains something that definitely isn't XML.
-	 */
-	@Test
-	public void testBadXML( )
-	{
-		I18NLoader loader = new I18NLoader( new File( "TestFiles/i18n-loader/bad-xml.xml" ) );
-		try {
-			loader.load( );
-		} catch ( DataImportException e ) {
-			assertTrue( "cause is a " + e.getCause( ).getClass( ).getName( ) , e.getCause( ) instanceof StreamException );
-			return;
-		}
-		fail( "no exception after loading stuff that isn't XML" );
-	}
-
-
-	/**
-	 * Try loading a file that contains XML but which cannot be desertialised to an {@link I18NText}
-	 * instance.
-	 */
-	@Test
-	public void testBadContents( )
-	{
-		I18NLoader loader = new I18NLoader( new File( "TestFiles/i18n-loader/bad-contents.xml" ) );
-		try {
-			loader.load( );
-		} catch ( DataImportException e ) {
-			assertTrue( "cause is a " + e.getCause( ).getClass( ).getName( ) ,
-					e.getCause( ) instanceof ConversionException );
-			return;
-		}
-		fail( "no exception after loading bad XML" );
-	}
-
-
-	/**
-	 * Try loading a file that contains valid XML for an {@link I18NText} instance with semantic
-	 * errors.
-	 */
-	@Test
-	public void testBadData( )
-	{
-		I18NLoader loader = new I18NLoader( new File( "TestFiles/i18n-loader/bad-data.xml" ) );
-		try {
-			loader.load( );
-		} catch ( DataImportException e ) {
-			assertNull( e.getCause( ) );
-			return;
-		}
-		fail( "no exception after loading bad data" );
-	}
-
-
-	/**
-	 * Try loading valid data, make sure that it contains exactly what is expected, and that it
-	 * loads external strings from the appropriate directory.
-	 */
-	@Test
-	public void testGoodData( )
-	{
-		I18NLoader loader = new I18NLoader( new File( "TestFiles/i18n-loader/good.xml" ) );
-		I18NText text;
-		try {
-			text = loader.load( );
-		} catch ( DataImportException e ) {
-			fail( "could not load valid file" );
-			return;
-		}
-		assertNotNull( text );
-
-		int lCount = 0;
-		for ( @SuppressWarnings( "unused" )
-		LanguageDefinition ld : text ) {
-			lCount++;
-		}
-		assertEquals( 1 , lCount );
-	}
-}
diff --git a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/cli/xmlimport/TestResourceLoader.java b/legacyworlds-server-tests/src/test/java/com/deepclone/lw/cli/xmlimport/TestResourceLoader.java
deleted file mode 100644
index def4308..0000000
--- a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/cli/xmlimport/TestResourceLoader.java
+++ /dev/null
@@ -1,135 +0,0 @@
-package com.deepclone.lw.cli.xmlimport;
-
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import java.io.File;
-import java.io.IOException;
-
-import org.junit.Test;
-
-import com.deepclone.lw.cli.xmlimport.data.DataImportException;
-import com.deepclone.lw.cli.xmlimport.data.resources.BasicResource;
-import com.deepclone.lw.cli.xmlimport.data.resources.Resources;
-import com.thoughtworks.xstream.converters.ConversionException;
-import com.thoughtworks.xstream.io.StreamException;
-
-
-
-/**
- * Unit tests for the {@link ResourceLoader} class.
- * 
- * @author <a href="mailto:tim@mitheren.com">T. Rosser</a>
- * 
- */
-public class TestResourceLoader
-{
-	/**
-	 * Try initialising the loader with a <code>null</code> file instance.
-	 * 
-	 * @throws NullPointerException
-	 *             when the constructor is executed
-	 */
-	@Test( expected = NullPointerException.class )
-	public void testNullFile( )
-			throws NullPointerException
-	{
-		new ResourceLoader( null );
-	}
-
-
-	/** Try loading a file that does not exist */
-	@Test
-	public void testMissingFile( )
-	{
-		ResourceLoader loader = new ResourceLoader( new File( "does-not-exist" ) );
-		try {
-			loader.load( );
-		} catch ( DataImportException e ) {
-			assertTrue( "cause is a" + e.getCause( ).getClass( ).getName( ) , e.getCause( ) instanceof IOException );
-			return;
-		}
-		fail( "no exception after trying to load a missing file" );
-	}
-
-
-	/** Try loading a file that contains something that is not XML. */
-	@Test
-	public void testBadXML( )
-	{
-		ResourceLoader loader = new ResourceLoader( new File( "TestFiles/resource-loader/bad-xml.xml" ) );
-		try {
-			loader.load( );
-		} catch ( DataImportException e ) {
-			assertTrue( "cause is a " + e.getCause( ).getClass( ).getName( ) , e.getCause( ) instanceof StreamException );
-			return;
-		}
-		fail( "no exception after loading stuff that isn't XML" );
-	}
-
-
-	/**
-	 * Test loading a file that contains XML but which cannot be deserialised to an
-	 * {@link Resources} instance.
-	 */
-	@Test
-	public void testBadContents( )
-	{
-		ResourceLoader loader = new ResourceLoader( new File( "TestFiles/resource-loader/bad-contents.xml" ) );
-		try {
-			loader.load( );
-		} catch ( DataImportException e ) {
-			assertTrue( "cause is a " + e.getCause( ).getClass( ).getName( ) ,
-					e.getCause( ) instanceof ConversionException );
-			return;
-		}
-		fail( "no exception after loading bad XML" );
-	}
-
-
-	/**
-	 * Try loading a file that contains valid XML for a {@link ResourceLoader} instance with
-	 * semantic errors.
-	 */
-	@Test
-	public void testBadData( )
-	{
-		ResourceLoader loader = new ResourceLoader( new File( "TestFiles/resource-loader/bad-data.xml" ) );
-		try {
-			loader.load( );
-		} catch ( DataImportException e ) {
-			assertNull( e.getCause( ) );
-			return;
-		}
-		fail( "no exception after loading bad data" );
-	}
-
-
-	/** Try loading valid data, make sure that it contains exactly what is expected */
-	@Test
-	public void testGoodData( )
-	{
-		ResourceLoader loader = new ResourceLoader( new File( "TestFiles/resource-loader/good-data.xml" ) );
-		Resources resources;
-		try {
-			resources = loader.load( );
-		} catch ( DataImportException e ) {
-			fail( "could not load valid file" );
-			return;
-		}
-		assertNotNull( resources );
-
-		// Not sure if this is the best way to code for the two different resource types...
-		int rCount = 0;
-
-		for ( @SuppressWarnings( "unused" )
-		BasicResource br : resources ) {
-			rCount++;
-		}
-		assertEquals( 2 , rCount );
-	}
-}
diff --git a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/cli/xmlimport/TestTechnologyLoader.java b/legacyworlds-server-tests/src/test/java/com/deepclone/lw/cli/xmlimport/TestTechnologyLoader.java
deleted file mode 100644
index ee24fc4..0000000
--- a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/cli/xmlimport/TestTechnologyLoader.java
+++ /dev/null
@@ -1,132 +0,0 @@
-package com.deepclone.lw.cli.xmlimport;
-
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import java.io.File;
-import java.io.IOException;
-
-import org.junit.Test;
-
-import com.deepclone.lw.cli.xmlimport.data.DataImportException;
-import com.deepclone.lw.cli.xmlimport.data.techs.Technologies;
-import com.deepclone.lw.cli.xmlimport.data.techs.Technology;
-import com.thoughtworks.xstream.converters.ConversionException;
-import com.thoughtworks.xstream.io.StreamException;
-
-
-
-/**
- * Unit tests for the {@link TechnologyLoader} class.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-public class TestTechnologyLoader
-{
-	/**
-	 * Try initialising the loader with a <code>null</code> file instance.
-	 * 
-	 * @throws NullPointerException
-	 *             when the constructor is executed
-	 */
-	@Test( expected = NullPointerException.class )
-	public void testNullFile( )
-			throws NullPointerException
-	{
-		new TechnologyLoader( null );
-	}
-
-
-	/** Try loading a file that does not exist */
-	@Test
-	public void testMissingFile( )
-	{
-		TechnologyLoader loader = new TechnologyLoader( new File( "does-not-exist" ) );
-		try {
-			loader.load( );
-		} catch ( DataImportException e ) {
-			assertTrue( "cause is a" + e.getCause( ).getClass( ).getName( ) , e.getCause( ) instanceof IOException );
-			return;
-		}
-		fail( "no exception after trying to load a missing file" );
-	}
-
-
-	/** Try loading a file that contains something that is not XML. */
-	@Test
-	public void testBadXML( )
-	{
-		TechnologyLoader loader = new TechnologyLoader( new File( "TestFiles/technology-loader/bad-xml.xml" ) );
-		try {
-			loader.load( );
-		} catch ( DataImportException e ) {
-			assertTrue( "cause is a " + e.getCause( ).getClass( ).getName( ) , e.getCause( ) instanceof StreamException );
-			return;
-		}
-		fail( "no exception after loading stuff that isn't XML" );
-	}
-
-
-	/**
-	 * Test loading a file that contains XML but which cannot be deserialised to a
-	 * {@link Technologies} instance.
-	 */
-	@Test
-	public void testBadContents( )
-	{
-		TechnologyLoader loader = new TechnologyLoader( new File( "TestFiles/technology-loader/bad-contents.xml" ) );
-		try {
-			loader.load( );
-		} catch ( DataImportException e ) {
-			assertTrue( "cause is a " + e.getCause( ).getClass( ).getName( ) ,
-					e.getCause( ) instanceof ConversionException );
-			return;
-		}
-		fail( "no exception after loading bad XML" );
-	}
-
-
-	/**
-	 * Try loading a file that contains valid XML for a {@link Technologies} instance with semantic
-	 * errors.
-	 */
-	@Test
-	public void testBadData( )
-	{
-		TechnologyLoader loader = new TechnologyLoader( new File( "TestFiles/technology-loader/bad-data.xml" ) );
-		try {
-			loader.load( );
-		} catch ( DataImportException e ) {
-			assertNull( e.getCause( ) );
-			return;
-		}
-		fail( "no exception after loading bad data" );
-	}
-
-
-	/** Try loading valid data, make sure that it contains one record */
-	@Test
-	public void testGoodData( )
-	{
-		TechnologyLoader loader = new TechnologyLoader( new File( "TestFiles/technology-loader/good-data.xml" ) );
-		Technologies technologies;
-		try {
-			technologies = loader.load( );
-		} catch ( DataImportException e ) {
-			fail( "could not load valid file" );
-			return;
-		}
-		assertNotNull( technologies );
-
-		int rCount = 0;
-		for ( @SuppressWarnings( "unused" )
-		Technology tech : technologies ) {
-			rCount++;
-		}
-		assertEquals( 1 , rCount );
-	}
-}
diff --git a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/cli/xmlimport/data/TestImportableData.java b/legacyworlds-server-tests/src/test/java/com/deepclone/lw/cli/xmlimport/data/TestImportableData.java
deleted file mode 100644
index f8f5880..0000000
--- a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/cli/xmlimport/data/TestImportableData.java
+++ /dev/null
@@ -1,73 +0,0 @@
-package com.deepclone.lw.cli.xmlimport.data;
-
-
-import java.io.File;
-
-import org.junit.Test;
-
-import static org.junit.Assert.*;
-
-
-
-/**
- * Unit tests for the {@link ImportableData} class
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-public class TestImportableData
-{
-
-	/**
-	 * Dummy importable data
-	 * 
-	 * <p>
-	 * This class is used in the test to have access to an importable data instance that corresponds
-	 * exactly to the base class.
-	 * 
-	 * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
-	 */
-	@SuppressWarnings( "serial" )
-	private static class DummyData
-			extends ImportableData
-	{
-		// EMPTY
-	}
-
-
-	/** Make sure that {@link ImportableData#getReadFrom()} returns <code>null</code> by default */
-	@Test
-	public void testUninitialisedReadFrom( )
-	{
-		DummyData data = new DummyData( );
-		assertNull( data.getReadFrom( ) );
-	}
-
-
-	/** Checks the default implementation of {@link ImportableData#setReadFrom(File)} */
-	@Test
-	public void testSetReadFrom( )
-	{
-		DummyData data = new DummyData( );
-		File file = new File( "test" );
-
-		data.setReadFrom( file );
-		assertNotNull( data.getReadFrom( ) );
-		assertEquals( "test" , data.getReadFrom( ).getPath( ) );
-	}
-
-
-	/**
-	 * Make sure that the default implementation of {@link ImportableData#verifyData()} always
-	 * succeeds
-	 * 
-	 * @throws DataImportException
-	 *             if the default implementation fails somehow
-	 */
-	@Test
-	public void testDefaultVerify( )
-			throws DataImportException
-	{
-		DummyData data = new DummyData( );
-		data.verifyData( );
-	}
-}
diff --git a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/cli/xmlimport/data/i18n/BaseTest.java b/legacyworlds-server-tests/src/test/java/com/deepclone/lw/cli/xmlimport/data/i18n/BaseTest.java
deleted file mode 100644
index 1daeca8..0000000
--- a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/cli/xmlimport/data/i18n/BaseTest.java
+++ /dev/null
@@ -1,205 +0,0 @@
-package com.deepclone.lw.cli.xmlimport.data.i18n;
-
-
-import com.deepclone.lw.cli.xmlimport.I18NLoader;
-import com.deepclone.lw.cli.xmlimport.data.ImportableData;
-import com.thoughtworks.xstream.XStream;
-import com.thoughtworks.xstream.XStreamException;
-
-
-
-/**
- * Base class for I18N import structures
- * 
- * <p>
- * This class is used as a parent by tests of the I18N import structures. It includes the code
- * required to actually create such resources, as this can normally only be done through XStream.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- * 
- */
-abstract class BaseTest
-{
-
-	/**
-	 * Escape &amp;, &lt; and &gt; in XML strings
-	 * 
-	 * @param string
-	 *            the string to escape
-	 * 
-	 * @return the escaped string
-	 */
-	private String xmlString( String string )
-	{
-		return string.replace( "&" , "&amp;" ).replace( "<" , "&lt;" ).replace( ">" , "&gt;" );
-	}
-
-
-	/**
-	 * Escape &amp;, &lt; and &gt;, ' and " in XML strings
-	 * 
-	 * @param string
-	 *            the string to escape
-	 * 
-	 * @return the escaped string
-	 */
-	private String quoteString( String string )
-	{
-		return "\"" + this.xmlString( string ).replace( "\"" , "&quot;" ).replace( "'" , "&apos;" ) + "\"";
-	}
-
-
-	/**
-	 * Create an in-line string definition
-	 * 
-	 * <p>
-	 * Generate the XML code that corresponds to an in-line string definition.
-	 * 
-	 * @param identifier
-	 *            the string's identifier, or <code>null</code> to omit the identifier
-	 * @param contents
-	 *            the string's contents, or <code>null</code> to omit the contents.
-	 * 
-	 * @return the XML code corresponding to the string definition
-	 */
-	protected String createInlineStringDefinition( String identifier , String contents )
-	{
-		StringBuilder str = new StringBuilder( );
-		str.append( "<inline-string" );
-		if ( identifier != null ) {
-			str.append( " id=" ).append( this.quoteString( identifier ) );
-		}
-		str.append( '>' );
-		if ( contents != null ) {
-			str.append( "<value>" ).append( this.xmlString( contents ) ).append( "</value>" );
-		}
-		str.append( "</inline-string>" );
-		return str.toString( );
-	}
-
-
-	/**
-	 * Create an external string definition
-	 * 
-	 * <p>
-	 * Generate the XML code that corresponds to an external string definition.
-	 * 
-	 * @param identifier
-	 *            the string's identifier, or <code>null</code> to omit the identifier
-	 * @param source
-	 *            the string's source file, or <code>null</code> to omit the source.
-	 * 
-	 * @return the XML code corresponding to the string definition
-	 */
-	protected String createExternalStringDefinition( String identifier , String source )
-	{
-		StringBuilder str = new StringBuilder( );
-		str.append( "<from-file" );
-		if ( identifier != null ) {
-			str.append( " id=" ).append( this.quoteString( identifier ) );
-		}
-		if ( source != null ) {
-			str.append( " source=" ).append( this.quoteString( source ) );
-		}
-		str.append( " />" );
-		return str.toString( );
-	}
-
-
-	/**
-	 * Create a language definition
-	 * 
-	 * @param identifier
-	 *            the language's identifier, or <code>null</code> if the identifier is to be omitted
-	 * @param name
-	 *            the language's name, or <code>null</code> if the name is to be omitted
-	 * @param stringDefinitions
-	 *            XML definitions returned by {@link #createInlineStringDefinition(String, String)}
-	 *            or {@link #createExternalStringDefinition(String, String)}
-	 * 
-	 * @return the XML code corresponding to the language definition
-	 */
-	protected String createLanguageDefinition( String identifier , String name , String... stringDefinitions )
-	{
-		StringBuilder str = new StringBuilder( );
-
-		str.append( "<language" );
-		if ( identifier != null ) {
-			str.append( " id=" ).append( this.quoteString( identifier ) );
-		}
-		if ( name != null ) {
-			str.append( " name=" ).append( this.quoteString( name ) );
-		}
-		str.append( ">" );
-		for ( String definition : stringDefinitions ) {
-			str.append( definition );
-		}
-		str.append( "</language>" );
-
-		return str.toString( );
-	}
-
-
-	/**
-	 * Create the XML code for a top-level I18N definition element
-	 * 
-	 * @param languages
-	 *            XML definitions of languages, as returned by
-	 *            {@link #createLanguageDefinition(String, String, String...)}
-	 * 
-	 * @return the top-level element's XML code
-	 */
-	protected String createTopLevel( String... languages )
-	{
-		StringBuilder str = new StringBuilder( );
-		str.append( "<lw-text-data>" );
-		for ( String language : languages ) {
-			str.append( language );
-		}
-		str.append( "</lw-text-data>" );
-		return str.toString( );
-	}
-
-
-	/**
-	 * Create the necessary XStream instance
-	 * 
-	 * <p>
-	 * Initialise an XStream instance and set it up so it can process I18N data definitions. Unlike
-	 * the XStream instance generated by {@link I18NLoader}, this version also registers the alias
-	 * for language definitions.
-	 * 
-	 * @return the initialised XStream instance.
-	 */
-	private XStream createXStreamInstance( )
-	{
-		XStream xstream = new XStream( );
-		xstream.processAnnotations( I18NText.class );
-		xstream.processAnnotations( InlineString.class );
-		xstream.processAnnotations( FileString.class );
-		xstream.alias( "language" , LanguageDefinition.class );
-		return xstream;
-	}
-
-
-	/**
-	 * Create an I18N definition object from its XML code
-	 * 
-	 * @param xml
-	 *            the XML code
-	 * @param cls
-	 *            the class of the object
-	 * 
-	 * @return the object that was created from the code
-	 * 
-	 * @throws ClassCastException
-	 *             if the code corresponds to some other type of object
-	 * @throws XStreamException
-	 *             if some error occurred while unserialising the object
-	 */
-	protected < T extends ImportableData > T createObject( String xml , Class< T > cls )
-			throws ClassCastException , XStreamException
-	{
-		return cls.cast( this.createXStreamInstance( ).fromXML( xml ) );
-	}
-}
diff --git a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/cli/xmlimport/data/i18n/TestExternalString.java b/legacyworlds-server-tests/src/test/java/com/deepclone/lw/cli/xmlimport/data/i18n/TestExternalString.java
deleted file mode 100644
index 6970672..0000000
--- a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/cli/xmlimport/data/i18n/TestExternalString.java
+++ /dev/null
@@ -1,307 +0,0 @@
-package com.deepclone.lw.cli.xmlimport.data.i18n;
-
-
-import static org.junit.Assert.*;
-
-import java.io.File;
-
-import org.junit.Test;
-
-import com.deepclone.lw.cli.xmlimport.data.DataImportException;
-
-
-
-/**
- * Unit tests for the {@link FileString} class
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-public class TestExternalString
-		extends BaseTest
-{
-
-	/**
-	 * Test loading a valid external string record and the corresponding contents
-	 * 
-	 * @throws DataImportException
-	 *             if a failure occurs while reading the source file.
-	 */
-	@Test
-	public void testLoadStringOK( )
-			throws DataImportException
-	{
-		String definition = this.createExternalStringDefinition( "test" , "test.txt" );
-		FileString instance = this.createObject( definition , FileString.class );
-		instance.setReadFrom( new File( "TestFiles/i18n-external-file/file" ) );
-		assertEquals( "test" , instance.getId( ) );
-		assertEquals( "This is a test." , instance.getString( ).trim( ) );
-	}
-
-
-	/**
-	 * Test loading an external string record with no identifier
-	 * 
-	 * @throws DataImportException
-	 *             if a failure occurs while reading the source file.
-	 */
-	@Test
-	public void testLoadStringNullIdentifier( )
-			throws DataImportException
-	{
-		String definition = this.createExternalStringDefinition( null , "test.txt" );
-		FileString instance = this.createObject( definition , FileString.class );
-		instance.setReadFrom( new File( "TestFiles/i18n-external-file/file" ) );
-		assertNull( instance.getId( ) );
-		assertEquals( "This is a test." , instance.getString( ).trim( ) );
-	}
-
-
-	/**
-	 * Test loading an external string record with no source file
-	 * 
-	 * @throws DataImportException
-	 *             if a failure occurs while reading the source file
-	 * @throws NullPointerException
-	 *             when {@link FileString#getString()} is called while its source is
-	 *             <code>null</code>
-	 */
-	@Test( expected = NullPointerException.class )
-	public void testLoadStringNullSource( )
-			throws DataImportException , NullPointerException
-	{
-		String definition = this.createExternalStringDefinition( "test" , null );
-		FileString instance = this.createObject( definition , FileString.class );
-		instance.setReadFrom( new File( "TestFiles/i18n-external-file/file" ) );
-		assertEquals( "test" , instance.getId( ) );
-		instance.getString( );
-	}
-
-
-	/**
-	 * Test loading a valid external string record and obtaining the contents without setting the
-	 * path to the data file first.
-	 * 
-	 * @throws DataImportException
-	 *             if a failure occurs while reading the source file.
-	 * @throws NullPointerException
-	 *             when {@link FileString#getString()} is called while its original path is
-	 *             <code>null</code>
-	 */
-	@Test( expected = NullPointerException.class )
-	public void testLoadStringNoPath( )
-			throws DataImportException , NullPointerException
-	{
-		String definition = this.createExternalStringDefinition( "test" , "test.txt" );
-		FileString instance = this.createObject( definition , FileString.class );
-		instance.getString( );
-	}
-
-
-	/**
-	 * Test loading a valid external string record and obtaining the contents when the source file
-	 * does not exist.
-	 * 
-	 * @throws DataImportException
-	 *             when a failure occurs while reading the source file.
-	 */
-	@Test( expected = DataImportException.class )
-	public void testLoadStringBadSource( )
-			throws DataImportException , NullPointerException
-	{
-		String definition = this.createExternalStringDefinition( "test" , "does-not-exist.txt" );
-		FileString instance = this.createObject( definition , FileString.class );
-		instance.setReadFrom( new File( "TestFiles/i18n-external-file/file" ) );
-		instance.getString( );
-	}
-
-
-	/**
-	 * Test loading a valid external string record and obtaining the contents when the source file
-	 * is a directory.
-	 * 
-	 * @throws DataImportException
-	 *             when a failure occurs while reading the source file.
-	 */
-	@Test( expected = DataImportException.class )
-	public void testLoadStringSourceIsDirectory( )
-			throws DataImportException , NullPointerException
-	{
-		String definition = this.createExternalStringDefinition( "test" , "." );
-		FileString instance = this.createObject( definition , FileString.class );
-		instance.setReadFrom( new File( "TestFiles/i18n-external-file/file" ) );
-		instance.getString( );
-	}
-
-
-	/**
-	 * Test loading a valid external string record and obtaining the contents when the original
-	 * file's path is incorrect.
-	 * 
-	 * @throws DataImportException
-	 *             when a failure occurs while reading the source file.
-	 */
-	@Test( expected = DataImportException.class )
-	public void testLoadStringBadParent( )
-			throws DataImportException , NullPointerException
-	{
-		String definition = this.createExternalStringDefinition( "test" , "test.txt" );
-		FileString instance = this.createObject( definition , FileString.class );
-		instance.setReadFrom( new File( "does-not-exist/does-not-exist" ) );
-		instance.getString( );
-	}
-
-
-	/**
-	 * Test loading a valid external string record and obtaining the contents when the original
-	 * file's path is a single file name.
-	 * 
-	 * @throws DataImportException
-	 *             if a failure occurs while reading the source file.
-	 */
-	@Test
-	public void testLoadStringParentIsCurrentDirectory( )
-			throws DataImportException , NullPointerException
-	{
-		String definition = this.createExternalStringDefinition( "test" , "TestFiles/i18n-external-file/test.txt" );
-		FileString instance = this.createObject( definition , FileString.class );
-		instance.setReadFrom( new File( "does-not-exist" ) );
-		instance.getString( );
-	}
-
-
-
-	/** Test validating a file string record with a short identifier and a source */
-	@Test
-	public void testValidateSimple( )
-			throws DataImportException
-	{
-		String definition = this.createExternalStringDefinition( "test" , "test.txt" );
-		FileString instance = this.createObject( definition , FileString.class );
-		instance.verifyData( );
-	}
-
-
-	/** Test validating an external string record with a camel case identifier and a source */
-	@Test
-	public void testValidateCamelCaseIdentifier( )
-			throws DataImportException
-	{
-		String definition = this.createExternalStringDefinition( "testCamelCase" , "test.txt" );
-		FileString instance = this.createObject( definition , FileString.class );
-		instance.verifyData( );
-	}
-
-
-	/**
-	 * Test validating an external string record with an identifier that includes a sequence of
-	 * upper-case letters and a source
-	 */
-	@Test
-	public void testValidateCapsIdentifier( )
-			throws DataImportException
-	{
-		String definition = this.createExternalStringDefinition( "testCAPSIdentifier" , "test.txt" );
-		FileString instance = this.createObject( definition , FileString.class );
-		instance.verifyData( );
-	}
-
-
-	/**
-	 * Test validating an external string record with an identifier that includes numbers and some
-	 * contents
-	 */
-	@Test
-	public void testValidateNumbersIdentifier( )
-			throws DataImportException
-	{
-		String definition = this.createExternalStringDefinition( "test123Numbers123" , "test.txt" );
-		FileString instance = this.createObject( definition , FileString.class );
-		instance.verifyData( );
-	}
-
-
-	/**
-	 * Test rejecting an external string record with a <code>null</code> identifier and a source
-	 */
-	@Test( expected = DataImportException.class )
-	public void testValidateNullIdentifier( )
-			throws DataImportException
-	{
-		String definition = this.createExternalStringDefinition( null , "test.txt" );
-		FileString instance = this.createObject( definition , FileString.class );
-		instance.verifyData( );
-	}
-
-
-	/** Test rejecting an external string record with an identifier that starts with a bad character */
-	@Test( expected = DataImportException.class )
-	public void testValidateBadFirstCharacterIdentifier( )
-			throws DataImportException
-	{
-		String definition = this.createExternalStringDefinition( " test" , "test.txt" );
-		FileString instance = this.createObject( definition , FileString.class );
-		instance.verifyData( );
-	}
-
-
-	/**
-	 * Test rejecting an external string record with an identifier that starts with an upper-case
-	 * letter
-	 */
-	@Test( expected = DataImportException.class )
-	public void testValidateFirstCharacterWrongCaseIdentifier( )
-			throws DataImportException
-	{
-		String definition = this.createExternalStringDefinition( "Test" , "test.txt" );
-		FileString instance = this.createObject( definition , FileString.class );
-		instance.verifyData( );
-	}
-
-
-	/** Test rejecting an external string record with an identifier that includes "bad" characters */
-	@Test( expected = DataImportException.class )
-	public void testValidateBadMiddleCharacterIdentifier( )
-			throws DataImportException
-	{
-		String definition = this.createExternalStringDefinition( "test Test" , "test.txt" );
-		FileString instance = this.createObject( definition , FileString.class );
-		instance.verifyData( );
-	}
-
-
-	/** Test rejecting an external record with <code>null</code> contents */
-	@Test( expected = DataImportException.class )
-	public void testValidateNullSource( )
-			throws DataImportException
-	{
-		String definition = this.createExternalStringDefinition( "test" , null );
-		FileString instance = this.createObject( definition , FileString.class );
-		instance.verifyData( );
-	}
-
-
-	/** Test rejecting an external record with empty contents */
-	@Test( expected = DataImportException.class )
-	public void testValidateEmptySource( )
-			throws DataImportException
-	{
-		String definition = this.createExternalStringDefinition( "test" , "" );
-		FileString instance = this.createObject( definition , FileString.class );
-		instance.verifyData( );
-	}
-
-
-	/**
-	 * Test rejecting an external record with contents the include only white space (spaces, tabs,
-	 * new line, line feed)
-	 */
-	@Test( expected = DataImportException.class )
-	public void testValidateSpacesOnlySource( )
-			throws DataImportException
-	{
-		String definition = this.createExternalStringDefinition( "test" , " \t\r\n" );
-		FileString instance = this.createObject( definition , FileString.class );
-		instance.verifyData( );
-	}
-
-}
diff --git a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/cli/xmlimport/data/i18n/TestI18NText.java b/legacyworlds-server-tests/src/test/java/com/deepclone/lw/cli/xmlimport/data/i18n/TestI18NText.java
deleted file mode 100644
index f158d91..0000000
--- a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/cli/xmlimport/data/i18n/TestI18NText.java
+++ /dev/null
@@ -1,134 +0,0 @@
-package com.deepclone.lw.cli.xmlimport.data.i18n;
-
-
-import static org.junit.Assert.*;
-
-import org.junit.Before;
-import org.junit.Test;
-
-import com.deepclone.lw.cli.xmlimport.data.DataImportException;
-
-
-
-/**
- * Unit tests for the {@link I18NText} class
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-public class TestI18NText
-		extends BaseTest
-{
-	/** The language definition that will be used in most tests */
-	private String languageDefinition;
-
-
-	/** Initialise a language definition to use while testing */
-	@Before
-	public void setUp( )
-	{
-		String xml = this.createInlineStringDefinition( "test" , "test" );
-		this.languageDefinition = this.createLanguageDefinition( "test" , "test" , xml );
-	}
-
-
-	/**
-	 * Try loading a valid top-level I18N definition and make sure its contents are correct
-	 * 
-	 * @throws DataImportException
-	 *             if the language definition check fails for some unknown reason
-	 */
-	@Test
-	public void testLoadValidDefinitions( )
-			throws DataImportException
-	{
-		String xml = this.createTopLevel( this.languageDefinition );
-		I18NText text = this.createObject( xml , I18NText.class );
-
-		int count = 0;
-		for ( LanguageDefinition definition : text ) {
-			definition.verifyData( );
-			count++;
-		}
-		assertEquals( 1 , count );
-	}
-
-
-	/**
-	 * Try loading an empty top-level element
-	 * 
-	 * @throws NullPointerException
-	 *             when the iterator is accessed
-	 */
-	@Test( expected = NullPointerException.class )
-	public void testLoadEmpty( )
-			throws NullPointerException
-	{
-		String xml = this.createTopLevel( );
-		I18NText text = this.createObject( xml , I18NText.class );
-		text.iterator( );
-	}
-
-
-	/**
-	 * Try validating a correct top-level element
-	 * 
-	 * @throws DataImportException
-	 *             if the check fails
-	 */
-	@Test
-	public void testValidateOK( )
-			throws DataImportException
-	{
-		String xml = this.createTopLevel( this.languageDefinition );
-		I18NText text = this.createObject( xml , I18NText.class );
-		text.verifyData( );
-	}
-
-
-	/**
-	 * Try rejecting a top-level element that does not contain any language definition
-	 * 
-	 * @throws DataImportException
-	 *             when the check fails
-	 */
-	@Test( expected = DataImportException.class )
-	public void testValidateEmpty( )
-			throws DataImportException
-	{
-		String xml = this.createTopLevel( );
-		I18NText text = this.createObject( xml , I18NText.class );
-		text.verifyData( );
-	}
-
-
-	/**
-	 * Try rejecting a top-level element that contains an invalid language definition
-	 * 
-	 * @throws DataImportException
-	 *             when the check fails
-	 */
-	@Test( expected = DataImportException.class )
-	public void testValidateBadDefinition( )
-			throws DataImportException
-	{
-		String xml = this.createTopLevel( this.createLanguageDefinition( null , null ) );
-		I18NText text = this.createObject( xml , I18NText.class );
-		text.verifyData( );
-	}
-
-
-	/**
-	 * Try rejecting a top-level element that contains two valid but duplicate language definitions
-	 * 
-	 * @throws DataImportException
-	 *             when the check fails
-	 */
-	@Test( expected = DataImportException.class )
-	public void testValidateDuplicateDefinition( )
-			throws DataImportException
-	{
-		String xml = this.createTopLevel( this.languageDefinition , this.languageDefinition );
-		I18NText text = this.createObject( xml , I18NText.class );
-		text.verifyData( );
-	}
-}
diff --git a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/cli/xmlimport/data/i18n/TestInlineString.java b/legacyworlds-server-tests/src/test/java/com/deepclone/lw/cli/xmlimport/data/i18n/TestInlineString.java
deleted file mode 100644
index 501ce92..0000000
--- a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/cli/xmlimport/data/i18n/TestInlineString.java
+++ /dev/null
@@ -1,210 +0,0 @@
-package com.deepclone.lw.cli.xmlimport.data.i18n;
-
-
-import java.io.File;
-import java.lang.reflect.Method;
-
-import org.junit.Test;
-
-import com.deepclone.lw.cli.xmlimport.data.DataImportException;
-import com.deepclone.lw.cli.xmlimport.data.ImportableData;
-
-import static org.junit.Assert.*;
-
-
-
-/**
- * Tests for the {@link InlineString} class
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-public class TestInlineString
-		extends BaseTest
-{
-
-	/** Test loading a valid in-line string record */
-	@Test
-	public void testLoadStringOK( )
-	{
-		String definition = this.createInlineStringDefinition( "test" , "Test" );
-		InlineString instance = this.createObject( definition , InlineString.class );
-		assertEquals( "test" , instance.getId( ) );
-		assertEquals( "Test" , instance.getString( ) );
-	}
-
-
-	/** Test loading an in-line string record without identifier */
-	@Test
-	public void testLoadStringNoIdentifier( )
-	{
-		String definition = this.createInlineStringDefinition( null , "Test" );
-		InlineString instance = this.createObject( definition , InlineString.class );
-		assertNull( instance.getId( ) );
-		assertEquals( "Test" , instance.getString( ) );
-	}
-
-
-	/** Test loading an in-line string record without contents */
-	@Test
-	public void testLoadStringNoContents( )
-	{
-		String definition = this.createInlineStringDefinition( "test" , null );
-		InlineString instance = this.createObject( definition , InlineString.class );
-		assertEquals( "test" , instance.getId( ) );
-		assertNull( instance.getString( ) );
-	}
-
-
-	/** Test validating an in-line string record with a short identifier and some contents */
-	@Test
-	public void testValidateSimple( )
-			throws DataImportException
-	{
-		String definition = this.createInlineStringDefinition( "test" , "Test" );
-		InlineString instance = this.createObject( definition , InlineString.class );
-		instance.verifyData( );
-	}
-
-
-	/** Test validating an in-line string record with a camel case identifier and some contents */
-	@Test
-	public void testValidateCamelCaseIdentifier( )
-			throws DataImportException
-	{
-		String definition = this.createInlineStringDefinition( "testCamelCase" , "Test" );
-		InlineString instance = this.createObject( definition , InlineString.class );
-		instance.verifyData( );
-	}
-
-
-	/**
-	 * Test validating an in-line string record with an identifier that includes a sequence of
-	 * upper-case letters and some contents
-	 */
-	@Test
-	public void testValidateCapsIdentifier( )
-			throws DataImportException
-	{
-		String definition = this.createInlineStringDefinition( "testCAPSIdentifier" , "Test" );
-		InlineString instance = this.createObject( definition , InlineString.class );
-		instance.verifyData( );
-	}
-
-
-	/**
-	 * Test validating an in-line string record with an identifier that includes numbers and some
-	 * contents
-	 */
-	@Test
-	public void testValidateNumbersIdentifier( )
-			throws DataImportException
-	{
-		String definition = this.createInlineStringDefinition( "test123Numbers123" , "Test" );
-		InlineString instance = this.createObject( definition , InlineString.class );
-		instance.verifyData( );
-	}
-
-
-	/**
-	 * Test rejecting an in-line string record with a <code>null</code> identifier and some contents
-	 */
-	@Test( expected = DataImportException.class )
-	public void testValidateNullIdentifier( )
-			throws DataImportException
-	{
-		String definition = this.createInlineStringDefinition( null , "Test" );
-		InlineString instance = this.createObject( definition , InlineString.class );
-		instance.verifyData( );
-	}
-
-
-	/** Test rejecting an in-line string record with an identifier that starts with a bad character */
-	@Test( expected = DataImportException.class )
-	public void testValidateBadFirstCharacterIdentifier( )
-			throws DataImportException
-	{
-		String definition = this.createInlineStringDefinition( " test" , "Test" );
-		InlineString instance = this.createObject( definition , InlineString.class );
-		instance.verifyData( );
-	}
-
-
-	/**
-	 * Test rejecting an in-line string record with an identifier that starts with an upper-case
-	 * letter
-	 */
-	@Test( expected = DataImportException.class )
-	public void testValidateFirstCharacterWrongCaseIdentifier( )
-			throws DataImportException
-	{
-		String definition = this.createInlineStringDefinition( "Test" , "Test" );
-		InlineString instance = this.createObject( definition , InlineString.class );
-		instance.verifyData( );
-	}
-
-
-	/** Test rejecting an in-line string record with an identifier that includes "bad" characters */
-	@Test( expected = DataImportException.class )
-	public void testValidateBadMiddleCharacterIdentifier( )
-			throws DataImportException
-	{
-		String definition = this.createInlineStringDefinition( "test Test" , "Test" );
-		InlineString instance = this.createObject( definition , InlineString.class );
-		instance.verifyData( );
-	}
-
-
-	/** Test rejecting an in-line record with <code>null</code> contents */
-	@Test( expected = DataImportException.class )
-	public void testValidateNullContents( )
-			throws DataImportException
-	{
-		String definition = this.createInlineStringDefinition( "test" , null );
-		InlineString instance = this.createObject( definition , InlineString.class );
-		instance.verifyData( );
-	}
-
-
-	/** Test rejecting an in-line record with empty contents */
-	@Test( expected = DataImportException.class )
-	public void testValidateEmptyContents( )
-			throws DataImportException
-	{
-		String definition = this.createInlineStringDefinition( "test" , "" );
-		InlineString instance = this.createObject( definition , InlineString.class );
-		instance.verifyData( );
-	}
-
-
-	/**
-	 * Test rejecting an in-line record with contents the include only white space (spaces, tabs,
-	 * new line, line feed)
-	 */
-	@Test( expected = DataImportException.class )
-	public void testValidateSpacesOnlyContents( )
-			throws DataImportException
-	{
-		String definition = this.createInlineStringDefinition( "test" , " \t\r\n" );
-		InlineString instance = this.createObject( definition , InlineString.class );
-		instance.verifyData( );
-	}
-
-
-	/**
-	 * Make sure the class does not override {@link ImportableData#setReadFrom(java.io.File)}; if it
-	 * does, new tests <strong>must</strong> be written.
-	 * 
-	 * @throws NoSuchMethodException
-	 *             if the method has been deleted
-	 * @throws SecurityException
-	 *             if the JVM set-up is getting in the wayy
-	 */
-	@Test
-	public void testNoSetReadFromOverride( )
-			throws SecurityException , NoSuchMethodException
-	{
-		Class< InlineString > cls = InlineString.class;
-		Method method = cls.getMethod( "setReadFrom" , File.class );
-		assertEquals( ImportableData.class , method.getDeclaringClass( ) );
-	}
-}
diff --git a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/cli/xmlimport/data/i18n/TestLanguageDefinition.java b/legacyworlds-server-tests/src/test/java/com/deepclone/lw/cli/xmlimport/data/i18n/TestLanguageDefinition.java
deleted file mode 100644
index d9b18ef..0000000
--- a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/cli/xmlimport/data/i18n/TestLanguageDefinition.java
+++ /dev/null
@@ -1,264 +0,0 @@
-package com.deepclone.lw.cli.xmlimport.data.i18n;
-
-
-import static org.junit.Assert.*;
-
-import org.junit.Before;
-import org.junit.Test;
-
-import com.deepclone.lw.cli.xmlimport.data.DataImportException;
-
-
-
-/**
- * Unit tests for the {@link LanguageDefinition} class
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-public class TestLanguageDefinition
-		extends BaseTest
-{
-
-	/** The in-line string definition that will be used in most tests */
-	private String inlineDefinition;
-
-
-	/**
-	 * Create a valid in-line string definition to be appended to language definitions.
-	 */
-	@Before
-	public void setUp( )
-	{
-		this.inlineDefinition = this.createInlineStringDefinition( "test" , "test" );
-	}
-
-
-	/**
-	 * Test loading a valid language definition and make sure that all fields were set
-	 * appropriately.
-	 * 
-	 * @throws DataImportException
-	 *             if accessing the test string fails.
-	 */
-	@Test
-	public void testLoadValidDefinition( )
-			throws DataImportException
-	{
-		String xml = this.createLanguageDefinition( "t" , "Test" , this.inlineDefinition );
-		LanguageDefinition language = this.createObject( xml , LanguageDefinition.class );
-		assertEquals( "t" , language.getId( ) );
-		assertEquals( "Test" , language.getName( ) );
-
-		int count = 0;
-		for ( StringDefinition stringDefinition : language ) {
-			assertEquals( InlineString.class , stringDefinition.getClass( ) );
-			assertEquals( "test" , stringDefinition.getId( ) );
-			assertEquals( "test" , stringDefinition.getString( ) );
-			count++;
-		}
-		assertEquals( 1 , count );
-	}
-
-
-	/**
-	 * Test loading a language definition that has no identifier.
-	 */
-	@Test
-	public void testLoadNullIdentifier( )
-	{
-		String xml = this.createLanguageDefinition( null , "Test" , this.inlineDefinition );
-		LanguageDefinition language = this.createObject( xml , LanguageDefinition.class );
-		assertNull( language.getId( ) );
-	}
-
-
-	/**
-	 * Test loading a language definition that has no name
-	 */
-	@Test
-	public void testLoadNullName( )
-	{
-		String xml = this.createLanguageDefinition( "test" , null , this.inlineDefinition );
-		LanguageDefinition language = this.createObject( xml , LanguageDefinition.class );
-		assertNull( language.getName( ) );
-	}
-
-
-	/**
-	 * Test loading a language definition that has no contents
-	 * 
-	 * @throws NullPointerException
-	 *             when the language definition's iterator is accessed, as its contents will be
-	 *             <code>null</code>
-	 */
-	@Test( expected = NullPointerException.class )
-	public void testLoadNullContents( )
-			throws NullPointerException
-	{
-		String xml = this.createLanguageDefinition( "test" , "test" );
-		LanguageDefinition language = this.createObject( xml , LanguageDefinition.class );
-		language.iterator( );
-	}
-
-
-	/**
-	 * Test validating a correct language definition.
-	 * 
-	 * @throws DataImportException
-	 *             if validating the definition fails
-	 */
-	@Test
-	public void testValidateOK( )
-			throws DataImportException
-	{
-		String xml = this.createLanguageDefinition( "t" , "Test" , this.inlineDefinition );
-		LanguageDefinition language = this.createObject( xml , LanguageDefinition.class );
-		language.verifyData( );
-	}
-
-
-	/**
-	 * Test validating a language definition with a <code>null</code> identifier.
-	 * 
-	 * @throws DataImportException
-	 *             when validation fails
-	 */
-	@Test( expected = DataImportException.class )
-	public void testValidateNullIdentifier( )
-			throws DataImportException
-	{
-		String xml = this.createLanguageDefinition( null , "Test" , this.inlineDefinition );
-		LanguageDefinition language = this.createObject( xml , LanguageDefinition.class );
-		language.verifyData( );
-	}
-
-
-	/**
-	 * Test validating a language definition with an empty identifier.
-	 * 
-	 * @throws DataImportException
-	 *             when validation fails
-	 */
-	@Test( expected = DataImportException.class )
-	public void testValidateEmptyIdentifier( )
-			throws DataImportException
-	{
-		String xml = this.createLanguageDefinition( "" , "Test" , this.inlineDefinition );
-		LanguageDefinition language = this.createObject( xml , LanguageDefinition.class );
-		language.verifyData( );
-	}
-
-
-	/**
-	 * Test validating a language definition with an identifier that contains white space only.
-	 * 
-	 * @throws DataImportException
-	 *             when validation fails
-	 */
-	@Test( expected = DataImportException.class )
-	public void testValidateWhiteSpaceIdentifier( )
-			throws DataImportException
-	{
-		String xml = this.createLanguageDefinition( " \t\n\r" , "Test" , this.inlineDefinition );
-		LanguageDefinition language = this.createObject( xml , LanguageDefinition.class );
-		language.verifyData( );
-	}
-
-
-	/**
-	 * Test validating a language definition with a <code>null</code> name.
-	 * 
-	 * @throws DataImportException
-	 *             when validation fails
-	 */
-	@Test( expected = DataImportException.class )
-	public void testValidateNullName( )
-			throws DataImportException
-	{
-		String xml = this.createLanguageDefinition( "t" , null , this.inlineDefinition );
-		LanguageDefinition language = this.createObject( xml , LanguageDefinition.class );
-		language.verifyData( );
-	}
-
-
-	/**
-	 * Test validating a language definition with an empty name.
-	 * 
-	 * @throws DataImportException
-	 *             when validation fails
-	 */
-	@Test( expected = DataImportException.class )
-	public void testValidateEmptyName( )
-			throws DataImportException
-	{
-		String xml = this.createLanguageDefinition( "t" , "" , this.inlineDefinition );
-		LanguageDefinition language = this.createObject( xml , LanguageDefinition.class );
-		language.verifyData( );
-	}
-
-
-	/**
-	 * Test validating a language definition with a name that contains white space only.
-	 * 
-	 * @throws DataImportException
-	 *             when validation fails
-	 */
-	@Test( expected = DataImportException.class )
-	public void testValidateWhiteSpaceName( )
-			throws DataImportException
-	{
-		String xml = this.createLanguageDefinition( "t" , " \t\n\r" , this.inlineDefinition );
-		LanguageDefinition language = this.createObject( xml , LanguageDefinition.class );
-		language.verifyData( );
-	}
-
-
-	/**
-	 * Test validating a language definition with no contents.
-	 * 
-	 * @throws DataImportException
-	 *             when validation fails
-	 */
-	@Test( expected = DataImportException.class )
-	public void testValidateNoContents( )
-			throws DataImportException
-	{
-		String xml = this.createLanguageDefinition( "t" , "Test" );
-		LanguageDefinition language = this.createObject( xml , LanguageDefinition.class );
-		language.verifyData( );
-	}
-
-
-	/**
-	 * Test validating a language definition with invalid contents.
-	 * 
-	 * @throws DataImportException
-	 *             when validation fails
-	 */
-	@Test( expected = DataImportException.class )
-	public void testValidateBadContents( )
-			throws DataImportException
-	{
-		String strXML = this.createInlineStringDefinition( null , "test" );
-		String xml = this.createLanguageDefinition( "t" , "Test" , strXML );
-		LanguageDefinition language = this.createObject( xml , LanguageDefinition.class );
-		language.verifyData( );
-	}
-
-
-	/**
-	 * Test validating a language definition with duplicate contents.
-	 * 
-	 * @throws DataImportException
-	 *             when validation fails
-	 */
-	@Test( expected = DataImportException.class )
-	public void testValidateDuplicateContents( )
-			throws DataImportException
-	{
-		String xml = this.createLanguageDefinition( "t" , "Test" , this.inlineDefinition , this.inlineDefinition );
-		LanguageDefinition language = this.createObject( xml , LanguageDefinition.class );
-		language.verifyData( );
-	}
-
-}
diff --git a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/cli/xmlimport/data/resources/BaseTest.java b/legacyworlds-server-tests/src/test/java/com/deepclone/lw/cli/xmlimport/data/resources/BaseTest.java
deleted file mode 100644
index 9f2eb11..0000000
--- a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/cli/xmlimport/data/resources/BaseTest.java
+++ /dev/null
@@ -1,267 +0,0 @@
-package com.deepclone.lw.cli.xmlimport.data.resources;
-
-
-import com.deepclone.lw.cli.xmlimport.data.ImportableData;
-import com.deepclone.lw.cli.xmlimport.data.resources.BasicResource;
-import com.deepclone.lw.cli.xmlimport.data.resources.NaturalResource;
-import com.deepclone.lw.cli.xmlimport.data.resources.ResourceParameter;
-import com.deepclone.lw.cli.xmlimport.data.resources.Resources;
-import com.thoughtworks.xstream.XStream;
-import com.thoughtworks.xstream.XStreamException;
-
-
-
-/**
- * Base class for testing resource importation
- * 
- * <p>
- * This class is used as a parent for tests of the resource import structures. It includes the code
- * used to actually create these resources, as this can normally only be done through XStream.
- * 
- * @author <a href="mailto:tim@mitheren.com">T. Rosser</a>
- * 
- */
-
-abstract class BaseTest
-{
-	/**
-	 * Escape &amp;, &lt; and &gt; in XML strings
-	 * 
-	 * @param string
-	 *            the string to escape
-	 * 
-	 * @return the escaped string
-	 */
-	private String xmlString( String string )
-	{
-		return string.replace( "&" , "&amp;" ).replace( "<" , "&lt;" ).replace( ">" , "&gt;" );
-	}
-
-
-	/**
-	 * Escape &amp;, &lt; and &gt;, ' and " in XML strings
-	 * 
-	 * @param string
-	 *            the string to escape
-	 * 
-	 * @return the escaped string
-	 */
-	private String quoteString( String string )
-	{
-		return "\"" + this.xmlString( string ).replace( "\"" , "&quot;" ).replace( "'" , "&apos;" ) + "\"";
-	}
-
-
-	/**
-	 * Create a {@link BasicResource} definition.
-	 * 
-	 * <p>
-	 * Generate the XML code that corresponds to a basic resource definition.
-	 * 
-	 * @param name
-	 *            The resources name, or <code>null</code> to omit the name.
-	 * @param description
-	 *            The resources description, or <code>null</code> to omit the description.
-	 * @param weight
-	 *            The resources weight, or <code>null</code> to omit the weight.
-	 * @param category
-	 *            The resources category, or <code>null</code> to omit the category.
-	 * 
-	 * @return the XML code corresponding to the resource definition.
-	 */
-	protected String createBasicResourceDefinition( String name , String description , String weight , String category )
-	{
-		StringBuilder str = new StringBuilder( );
-
-		str.append( "<basic-resource" );
-
-		if ( name != null ) {
-			str.append( " name=" ).append( this.quoteString( name ) );
-		}
-		if ( description != null ) {
-			str.append( " description=" ).append( this.quoteString( description ) );
-		}
-		if ( weight != null ) {
-			str.append( " weight=" ).append( this.quoteString( weight ) );
-		}
-		if ( category != null ) {
-			str.append( " category=" ).append( this.quoteString( category ) );
-		}
-
-		str.append( " />" );
-
-		return str.toString( );
-	}
-
-
-	/**
-	 * Create the a {@link NaturalResource} definition.
-	 * 
-	 * <p>
-	 * Create the XML code that corresponds to a natural resource definition.
-	 * 
-	 * @param name
-	 *            The resources name, or <code>null</code> to omit the name.
-	 * @param description
-	 *            The resources description, or <code>null</code> to omit the description.
-	 * @param weight
-	 *            The resources weight, or <code>null</code> to omit the weight.
-	 * @param category
-	 *            The resources category, or <code>null</code> to omit the category.
-	 * @param probability
-	 *            The resources presence-probability, or <code>null</code> to omit the probability.
-	 * @param quantity
-	 *            The XML code representing the {@link ResourceParameter} giving the resources
-	 *            quantity average and deviation or <code>null</code> to omit the quantity.
-	 * @param difficulty
-	 *            The XML code representing the {@link ResourceParameter} giving the resources
-	 *            difficulty average and deviation or <code>null</code> to omit the difficulty.
-	 * @param recovery
-	 *            The XML code representing the {@link ResourceParameter} giving the resources
-	 *            recovery average and deviation or <code>null</code> to omit the recovery.
-	 * 
-	 * @return the XML code corresponding to the natural resource definition
-	 */
-	protected String createNaturalResourceDefinition( String name , String description , String weight ,
-			String category , String probability , String quantity , String difficulty , String recovery )
-	{
-		StringBuilder str = new StringBuilder( );
-
-		str.append( "<natural-resource" );
-
-		if ( name != null ) {
-			str.append( " name=" ).append( this.quoteString( name ) );
-		}
-		if ( description != null ) {
-			str.append( " description=" ).append( this.quoteString( description ) );
-		}
-		if ( weight != null ) {
-			str.append( " weight=" ).append( this.quoteString( weight ) );
-		}
-		if ( category != null ) {
-			str.append( " category=" ).append( this.quoteString( category ) );
-		}
-		if ( probability != null ) {
-			str.append( " presence-probability=" ).append( this.quoteString( probability ) );
-		}
-
-		str.append( ">" );
-
-		if ( quantity != null ) {
-			str.append( quantity );
-		}
-		if ( difficulty != null ) {
-			str.append( difficulty );
-		}
-		if ( recovery != null ) {
-			str.append( recovery );
-		}
-
-		str.append( "</natural-resource>" );
-
-		return str.toString( );
-	}
-
-
-	/**
-	 * Create a {@link ResourceParameter} definition
-	 * 
-	 * <p>
-	 * Generates the XML code the corresponds to a resource parameter definition.
-	 * 
-	 * @param type
-	 *            Gives the type of resource parameter to create (quantity/difficulty/recovery)
-	 * @param average
-	 *            The parameters average.
-	 * @param deviation
-	 *            The parameters deviation.
-	 * 
-	 * @return the XML code corresponding to the resource parameter definition
-	 */
-	protected String createResourceParameterDefinition( String type , String average , String deviation )
-	{
-		StringBuilder str = new StringBuilder( );
-
-		str.append( "<" );
-
-		if ( type != null ) {
-			str.append( type );
-		}
-		if ( average != null ) {
-			str.append( " average=" ).append( this.quoteString( average ) );
-		}
-		if ( deviation != null ) {
-			str.append( " deviation=" ).append( this.quoteString( deviation ) );
-		}
-
-		str.append( " />" );
-
-		return str.toString( );
-	}
-
-
-	/**
-	 * Creates the XML code for a top-level resource definition element
-	 * 
-	 * @param resources
-	 *            XML definitions of resources
-	 * 
-	 * @return the top-level elements XML code
-	 */
-	protected String createTopLevel( String... resources )
-	{
-		StringBuilder str = new StringBuilder( );
-		str.append( "<lw-resources>" );
-		for ( String resource : resources ) {
-			str.append( resource );
-		}
-		str.append( "</lw-resources>" );
-		return str.toString( );
-	}
-
-
-	/**
-	 * Create the necessary XStream instance
-	 * 
-	 * <p>
-	 * Initialise an XStream instance and set it up so it can process resource data definitions.
-	 * Unlike {@link ResourceLoader}, this version also registers multiple aliases for
-	 * ResourceParameter. This is because ResourceParameter is usually only used inside a
-	 * NaturalResource, but when testing may need to be created independently.
-	 */
-	private XStream createXStreamInstance( )
-	{
-		XStream xstream = new XStream( );
-		xstream.processAnnotations( Resources.class );
-		xstream.processAnnotations( NaturalResource.class );
-		xstream.alias( "quantity" , ResourceParameter.class );
-		xstream.alias( "difficulty" , ResourceParameter.class );
-		xstream.alias( "recovery" , ResourceParameter.class );
-		xstream.alias( "test" , ResourceParameter.class ); // Just for unit tests
-		xstream.alias( "lw-resources" , Resources.class );
-
-		return xstream;
-	}
-
-
-	/**
-	 * Create a resource object from its XML code
-	 * 
-	 * @param xml
-	 *            the XML code
-	 * @param cls
-	 *            the class of the object
-	 * 
-	 * @return the object that was created from the code
-	 * 
-	 * @throws ClassCastException
-	 *             if the code corresponds to some other type of object
-	 * @throws XStreamException
-	 *             if some error occurred while deserialising the object
-	 */
-	protected < T extends ImportableData > T createObject( String xml , Class< T > cls )
-			throws ClassCastException , XStreamException
-	{
-		return cls.cast( this.createXStreamInstance( ).fromXML( xml ) );
-	}
-}
diff --git a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/cli/xmlimport/data/resources/TestBasicResource.java b/legacyworlds-server-tests/src/test/java/com/deepclone/lw/cli/xmlimport/data/resources/TestBasicResource.java
deleted file mode 100644
index fd5f8cf..0000000
--- a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/cli/xmlimport/data/resources/TestBasicResource.java
+++ /dev/null
@@ -1,203 +0,0 @@
-package com.deepclone.lw.cli.xmlimport.data.resources;
-
-
-import static org.junit.Assert.assertEquals;
-
-import org.junit.Test;
-
-import com.deepclone.lw.cli.xmlimport.data.DataImportException;
-import com.deepclone.lw.cli.xmlimport.data.resources.BasicResource;
-import com.thoughtworks.xstream.converters.ConversionException;
-
-
-
-/**
- * Unit tests for {@link BasicResource}.
- * 
- * @author <a href="mailto:tim@mitheren.com>T. Rosser</a>
- * 
- */
-public class TestBasicResource
-		extends BaseTest
-{
-	/** Test loading a valid basic resource */
-	@Test
-	public void testLoadBasicResourceOK( )
-	{
-		String resource = this.createBasicResourceDefinition( "test" , "test" , "0" , "test" );
-		BasicResource instance = this.createObject( resource , BasicResource.class );
-		assertEquals( "test" , instance.getName( ) );
-		assertEquals( "test" , instance.getDescription( ) );
-		assertEquals( new Integer( 0 ) , instance.getWeight( ) );
-		assertEquals( "test" , instance.getCategory( ) );
-	}
-
-
-	/** Test loading a basic resource without name */
-	@Test
-	public void testLoadResourceNoName( )
-	{
-		String resource = this.createBasicResourceDefinition( null , "test" , "0" , "test" );
-		BasicResource instance = this.createObject( resource , BasicResource.class );
-		assertEquals( null , instance.getName( ) );
-		assertEquals( "test" , instance.getDescription( ) );
-		assertEquals( new Integer( 0 ) , instance.getWeight( ) );
-		assertEquals( "test" , instance.getCategory( ) );
-	}
-
-
-	/** Test loading a basic resource without description */
-	@Test
-	public void testLoadResourceNoDescription( )
-	{
-		String resource = this.createBasicResourceDefinition( "test" , null , "0" , "test" );
-		BasicResource instance = this.createObject( resource , BasicResource.class );
-		assertEquals( "test" , instance.getName( ) );
-		assertEquals( null , instance.getDescription( ) );
-		assertEquals( new Integer( 0 ) , instance.getWeight( ) );
-		assertEquals( "test" , instance.getCategory( ) );
-	}
-
-
-	/** Test loading a basic resource without weight */
-	@Test
-	public void testLoadBasicResourceNoWeight( )
-	{
-		String resource = this.createBasicResourceDefinition( "test" , "test" , null , "test" );
-		BasicResource instance = this.createObject( resource , BasicResource.class );
-		assertEquals( "test" , instance.getName( ) );
-		assertEquals( "test" , instance.getDescription( ) );
-		assertEquals( null , instance.getWeight( ) );
-		assertEquals( "test" , instance.getCategory( ) );
-	}
-
-
-	/** Test loading a basic resource without category */
-	@Test
-	public void testLoadBasicResourceNoCategory( )
-	{
-		String resource = this.createBasicResourceDefinition( "test" , "test" , "0" , null );
-		BasicResource instance = this.createObject( resource , BasicResource.class );
-		assertEquals( "test" , instance.getName( ) );
-		assertEquals( "test" , instance.getDescription( ) );
-		assertEquals( new Integer( 0 ) , instance.getWeight( ) );
-		assertEquals( null , instance.getCategory( ) );
-	}
-
-
-	/**
-	 * Test validating a valid basic resource
-	 * 
-	 * @throws DataImportException
-	 *             if the data is not valid
-	 */
-	@Test
-	public void testValidateBasicResourceOK( )
-			throws DataImportException
-	{
-		String resource = this.createBasicResourceDefinition( "test" , "test" , "0" , "test" );
-		BasicResource instance = this.createObject( resource , BasicResource.class );
-		instance.verifyData( );
-	}
-
-
-	/**
-	 * Test validating a basic resource without name
-	 * 
-	 * @throws DataImportException
-	 *             if the data is not valid
-	 */
-	@Test( expected = DataImportException.class )
-	public void testValidateResourceNoName( )
-			throws DataImportException
-	{
-		String resource = this.createBasicResourceDefinition( null , "test" , "0" , "test" );
-		BasicResource instance = this.createObject( resource , BasicResource.class );
-		instance.verifyData( );
-	}
-
-
-	/**
-	 * Test validating a basic resource without description
-	 * 
-	 * @throws DataImportException
-	 *             if the data is not valid
-	 */
-	@Test( expected = DataImportException.class )
-	public void testValidateResourceNoDescription( )
-			throws DataImportException
-	{
-		String resource = this.createBasicResourceDefinition( "test" , null , "0" , "test" );
-		BasicResource instance = this.createObject( resource , BasicResource.class );
-		instance.verifyData( );
-	}
-
-
-	/**
-	 * Test validating a basic resource without weight
-	 * 
-	 * @throws DataImportException
-	 *             if the data is not valid
-	 */
-	@Test( expected = DataImportException.class )
-	public void testValidateBasicResourceNoWeight( )
-			throws DataImportException
-	{
-		String resource = this.createBasicResourceDefinition( "test" , "test" , null , "test" );
-		BasicResource instance = this.createObject( resource , BasicResource.class );
-		instance.verifyData( );
-	}
-
-
-	/**
-	 * Test validating a basic resource without category
-	 * 
-	 * @throws DataImportException
-	 *             if the data is not valid
-	 */
-	@Test
-	public void testValidateBasicResourceNoCategory( )
-			throws DataImportException
-	{
-		String resource = this.createBasicResourceDefinition( "test" , "test" , "0" , null );
-		BasicResource instance = this.createObject( resource , BasicResource.class );
-		instance.verifyData( );
-	}
-
-
-	/**
-	 * Test validating a basic resource with a non-numeric string weight
-	 * 
-	 * @throws DataImportException
-	 *             if the data is not valid
-	 * @throws ConversionException
-	 *             if XStream cannot convert the text to an object
-	 */
-	@Test( expected = ConversionException.class )
-	public void testValidateBasicResourceStringWeight( )
-			throws DataImportException , ConversionException
-	{
-		String resource = this.createBasicResourceDefinition( "test" , "test" , "test" , "test" );
-		BasicResource instance = this.createObject( resource , BasicResource.class );
-		instance.verifyData( );
-	}
-
-
-	/**
-	 * Test validating a basic resource with a non-integer weight
-	 * 
-	 * @throws DataImportException
-	 *             if the data is not valid
-	 * @throws ConversionException
-	 *             if XStream cannot convert the text to an object
-	 */
-	@Test( expected = ConversionException.class )
-	public void testValidateBasicResourceStringFloat( )
-			throws DataImportException , ConversionException
-	{
-		String resource = this.createBasicResourceDefinition( "test" , "test" , "1.2" , null );
-		BasicResource instance = this.createObject( resource , BasicResource.class );
-		instance.verifyData( );
-	}
-
-}
diff --git a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/cli/xmlimport/data/resources/TestNaturalResource.java b/legacyworlds-server-tests/src/test/java/com/deepclone/lw/cli/xmlimport/data/resources/TestNaturalResource.java
deleted file mode 100644
index 63a55ae..0000000
--- a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/cli/xmlimport/data/resources/TestNaturalResource.java
+++ /dev/null
@@ -1,329 +0,0 @@
-package com.deepclone.lw.cli.xmlimport.data.resources;
-
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
-
-import org.junit.Before;
-import org.junit.Test;
-
-import com.deepclone.lw.cli.xmlimport.data.DataImportException;
-import com.deepclone.lw.cli.xmlimport.data.resources.NaturalResource;
-import com.deepclone.lw.cli.xmlimport.data.resources.ResourceParameter;
-import com.thoughtworks.xstream.converters.ConversionException;
-
-
-
-/**
- * Unit tests for {@link NaturalResource}.
- * 
- * @author <a href="mailto:tim@mitheren.com>T. Rosser</a>
- * 
- */
-public class TestNaturalResource
-		extends BaseTest
-{
-	/** The XML definition for a {@link ResourceParameter} representing a resources quantity */
-	private String quantity;
-
-	/** The XML definition for a {@link ResourceParameter} representing a resources quantity */
-	private String difficulty;
-
-	/** The XML definition for a {@link ResourceParameter} representing a resources quantity */
-	private String recovery;
-
-
-	/**
-	 * Create valid definitions for the ResourceParameters to be used in the NaturalResource tests
-	 */
-	@Before
-	public void setup( )
-	{
-		this.quantity = this.createResourceParameterDefinition( "quantity" , "0" , "0" );
-		this.difficulty = this.createResourceParameterDefinition( "difficulty" , "0" , "0" );
-		this.recovery = this.createResourceParameterDefinition( "recovery" , "0" , "0" );
-	}
-
-
-	/** Test loading a valid natural resource */
-	@Test
-	public void testLoadNaturalResourceOK( )
-	{
-		String resource = this.createNaturalResourceDefinition( "test" , "test" , "0" , "test" , "0" , this.quantity ,
-				this.difficulty , this.recovery );
-		NaturalResource instance = this.createObject( resource , NaturalResource.class );
-		assertEquals( new Double( 0 ) , instance.getPresenceProbability( ) );
-		if ( instance.getQuantity( ) != null ) {
-			assertEquals( new Double( 0 ) , instance.getQuantity( ).getAverage( ) );
-			assertEquals( new Double( 0 ) , instance.getQuantity( ).getDeviation( ) );
-		} else {
-			fail( "Quantity is null" );
-		}
-		if ( instance.getDifficulty( ) != null ) {
-			assertEquals( new Double( 0 ) , instance.getDifficulty( ).getAverage( ) );
-			assertEquals( new Double( 0 ) , instance.getDifficulty( ).getDeviation( ) );
-		} else {
-			fail( "Difficulty is null" );
-		}
-		if ( instance.getRecovery( ) != null ) {
-			assertEquals( new Double( 0 ) , instance.getRecovery( ).getAverage( ) );
-			assertEquals( new Double( 0 ) , instance.getRecovery( ).getDeviation( ) );
-		} else {
-			fail( "Recovery is null" );
-		}
-
-	}
-
-
-	/** Test loading a valid natural resource with presence-probability giving a Double value */
-	@Test
-	public void testLoadNaturalResourceWithDoubleOK( )
-	{
-		String resource = this.createNaturalResourceDefinition( "test" , "test" , "0" , "test" , "1.2" , this.quantity ,
-				this.difficulty , this.recovery );
-		NaturalResource instance = this.createObject( resource , NaturalResource.class );
-		assertEquals( new Double( 1.2 ) , instance.getPresenceProbability( ) );
-		if ( instance.getQuantity( ) != null ) {
-			assertEquals( new Double( 0 ) , instance.getQuantity( ).getAverage( ) );
-			assertEquals( new Double( 0 ) , instance.getQuantity( ).getDeviation( ) );
-		} else {
-			fail( "Quantity is null" );
-		}
-		if ( instance.getDifficulty( ) != null ) {
-			assertEquals( new Double( 0 ) , instance.getDifficulty( ).getAverage( ) );
-			assertEquals( new Double( 0 ) , instance.getDifficulty( ).getDeviation( ) );
-		} else {
-			fail( "Difficulty is null" );
-		}
-		if ( instance.getRecovery( ) != null ) {
-			assertEquals( new Double( 0 ) , instance.getRecovery( ).getAverage( ) );
-			assertEquals( new Double( 0 ) , instance.getRecovery( ).getDeviation( ) );
-		} else {
-			fail( "Recovery is null" );
-		}
-	}
-
-
-	/** Test loading a natural resource with no presence-probability */
-	@Test
-	public void testLoadNaturalResourceNoProbability( )
-	{
-		String resource = this.createNaturalResourceDefinition( "test" , "test" , "0" , "test" , null , this.quantity ,
-				this.difficulty , this.recovery );
-		NaturalResource instance = this.createObject( resource , NaturalResource.class );
-		assertEquals( null , instance.getPresenceProbability( ) );
-		if ( instance.getQuantity( ) != null ) {
-			assertEquals( new Double( 0 ) , instance.getQuantity( ).getAverage( ) );
-			assertEquals( new Double( 0 ) , instance.getQuantity( ).getDeviation( ) );
-		} else {
-			fail( "Quantity is null" );
-		}
-		if ( instance.getDifficulty( ) != null ) {
-			assertEquals( new Double( 0 ) , instance.getDifficulty( ).getAverage( ) );
-			assertEquals( new Double( 0 ) , instance.getDifficulty( ).getDeviation( ) );
-		} else {
-			fail( "Difficulty is null" );
-		}
-		if ( instance.getRecovery( ) != null ) {
-			assertEquals( new Double( 0 ) , instance.getRecovery( ).getAverage( ) );
-			assertEquals( new Double( 0 ) , instance.getRecovery( ).getDeviation( ) );
-		} else {
-			fail( "Recovery is null" );
-		}
-	}
-
-
-	/** Test loading a natural resource with no quantity */
-	@Test
-	public void testLoadNaturalResourceNoQuantity( )
-	{
-		String resource = this.createNaturalResourceDefinition( "test" , "test" , "0" , "test" , "0" , null ,
-				this.difficulty , this.recovery );
-		NaturalResource instance = this.createObject( resource , NaturalResource.class );
-		assertEquals( new Double( 0 ) , instance.getPresenceProbability( ) );
-		assertEquals( null , instance.getQuantity( ) );
-		if ( instance.getDifficulty( ) != null ) {
-			assertEquals( new Double( 0 ) , instance.getDifficulty( ).getAverage( ) );
-			assertEquals( new Double( 0 ) , instance.getDifficulty( ).getDeviation( ) );
-		} else {
-			fail( "Difficulty is null" );
-		}
-		if ( instance.getRecovery( ) != null ) {
-			assertEquals( new Double( 0 ) , instance.getRecovery( ).getAverage( ) );
-			assertEquals( new Double( 0 ) , instance.getRecovery( ).getDeviation( ) );
-		} else {
-			fail( "Recovery is null" );
-		}
-	}
-
-
-	/** Test loading a natural resource with no difficulty */
-	@Test
-	public void testLoadNaturalResourceNoDifficulty( )
-	{
-		String resource = this.createNaturalResourceDefinition( "test" , "test" , "0" , "test" , "0" , this.quantity ,
-				null , this.recovery );
-		NaturalResource instance = this.createObject( resource , NaturalResource.class );
-		assertEquals( new Double( 0 ) , instance.getPresenceProbability( ) );
-
-		if ( instance.getQuantity( ) != null ) {
-			assertEquals( new Double( 0 ) , instance.getQuantity( ).getAverage( ) );
-			assertEquals( new Double( 0 ) , instance.getQuantity( ).getDeviation( ) );
-		} else {
-			fail( "Quantity is null" );
-		}
-		assertEquals( null , instance.getDifficulty( ) );
-		if ( instance.getRecovery( ) != null ) {
-			assertEquals( new Double( 0 ) , instance.getRecovery( ).getAverage( ) );
-			assertEquals( new Double( 0 ) , instance.getRecovery( ).getDeviation( ) );
-		} else {
-			fail( "Recovery is null" );
-		}
-	}
-
-
-	/** Test loading a natural resource with no recovery */
-	@Test
-	public void testLoadNaturalResourceNoRecovery( )
-	{
-		String resource = this.createNaturalResourceDefinition( "test" , "test" , "0" , "test" , "0" , this.quantity ,
-				this.difficulty , null );
-		NaturalResource instance = this.createObject( resource , NaturalResource.class );
-		assertEquals( new Double( 0 ) , instance.getPresenceProbability( ) );
-		if ( instance.getQuantity( ) != null ) {
-			assertEquals( new Double( 0 ) , instance.getQuantity( ).getAverage( ) );
-			assertEquals( new Double( 0 ) , instance.getQuantity( ).getDeviation( ) );
-		} else {
-			fail( "Quantity is null" );
-		}
-		if ( instance.getDifficulty( ) != null ) {
-			assertEquals( new Double( 0 ) , instance.getDifficulty( ).getAverage( ) );
-			assertEquals( new Double( 0 ) , instance.getDifficulty( ).getDeviation( ) );
-		} else {
-			fail( "Difficulty is null" );
-		}
-		assertEquals( null , instance.getRecovery( ) );
-	}
-
-
-	/**
-	 * Test validating a valid natural resource
-	 * 
-	 * @throws DataImportException
-	 *             if the data is not valid
-	 */
-	@Test
-	public void testValidateNaturalResourceOK( )
-			throws DataImportException
-	{
-		String resource = this.createNaturalResourceDefinition( "test" , "test" , "0" , "test" , "0" , this.quantity ,
-				this.difficulty , this.recovery );
-		NaturalResource instance = this.createObject( resource , NaturalResource.class );
-		instance.verifyData( );
-	}
-
-
-	/**
-	 * Test validating a valid natural resource with presence-probability containing a Double value
-	 * 
-	 * @throws DataImportException
-	 *             if the data is not valid
-	 */
-	@Test
-	public void testValidateNaturalResourceWithDoubleOK( )
-			throws DataImportException
-	{
-		String resource = this.createNaturalResourceDefinition( "test" , "test" , "0" , "test" , "1.2" , this.quantity ,
-				this.difficulty , this.recovery );
-		NaturalResource instance = this.createObject( resource , NaturalResource.class );
-		instance.verifyData( );
-	}
-
-
-	/**
-	 * Test validating a natural resource with no presence-probability
-	 * 
-	 * @throws DataImportException
-	 *             if the data is not valid
-	 */
-	@Test( expected = DataImportException.class )
-	public void testValidateNaturalResourceNoProbability( )
-			throws DataImportException
-	{
-		String resource = this.createNaturalResourceDefinition( "test" , "test" , "0" , "test" , null , this.quantity ,
-				this.difficulty , this.recovery );
-		NaturalResource instance = this.createObject( resource , NaturalResource.class );
-		instance.verifyData( );
-	}
-
-
-	/**
-	 * Test validating a natural resource with no quantity
-	 * 
-	 * @throws DataImportException
-	 *             if the data is not valid
-	 */
-	@Test( expected = DataImportException.class )
-	public void testValidateNaturalResourceNoQuantity( )
-			throws DataImportException
-	{
-		String resource = this.createNaturalResourceDefinition( "test" , "test" , "0" , "test" , "0" , null ,
-				this.difficulty , this.recovery );
-		NaturalResource instance = this.createObject( resource , NaturalResource.class );
-		instance.verifyData( );
-	}
-
-
-	/**
-	 * Test validating a natural resource with no difficulty
-	 * 
-	 * @throws DataImportException
-	 *             if the data is not valid
-	 */
-	@Test( expected = DataImportException.class )
-	public void testValidateNaturalResourceNoDifficulty( )
-			throws DataImportException
-	{
-		String resource = this.createNaturalResourceDefinition( "test" , "test" , "0" , "test" , "0" , this.quantity ,
-				null , this.recovery );
-		NaturalResource instance = this.createObject( resource , NaturalResource.class );
-		instance.verifyData( );
-	}
-
-
-	/**
-	 * Test validating a natural resource with no recovery
-	 * 
-	 * @throws DataImportException
-	 *             if the data is not valid
-	 */
-	@Test( expected = DataImportException.class )
-	public void testValidateNaturalResourceNoRecovery( )
-			throws DataImportException
-	{
-		String resource = this.createNaturalResourceDefinition( "test" , "test" , "0" , "test" , "0" , this.quantity ,
-				this.difficulty , null );
-		NaturalResource instance = this.createObject( resource , NaturalResource.class );
-		instance.verifyData( );
-	}
-
-
-	/**
-	 * Test validating a natural resource with a non-numerical string as presence-probability
-	 * 
-	 * @throws DataImportException
-	 *             if the data is not valid
-	 * @throws ConversionException
-	 *             if XStream cannot convert the text into an object
-	 */
-	@Test( expected = ConversionException.class )
-	public void testValidateNaturalResourceStringProbability( )
-			throws DataImportException , ConversionException
-	{
-		String resource = this.createNaturalResourceDefinition( "test" , "test" , "0" , "test" , "test" ,
-				this.quantity , this.difficulty , this.recovery );
-		NaturalResource instance = this.createObject( resource , NaturalResource.class );
-		instance.verifyData( );
-	}
-
-}
diff --git a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/cli/xmlimport/data/resources/TestResourceParameter.java b/legacyworlds-server-tests/src/test/java/com/deepclone/lw/cli/xmlimport/data/resources/TestResourceParameter.java
deleted file mode 100644
index dd82eee..0000000
--- a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/cli/xmlimport/data/resources/TestResourceParameter.java
+++ /dev/null
@@ -1,192 +0,0 @@
-package com.deepclone.lw.cli.xmlimport.data.resources;
-
-
-import static org.junit.Assert.assertEquals;
-
-import org.junit.Test;
-
-import com.deepclone.lw.cli.xmlimport.data.DataImportException;
-import com.deepclone.lw.cli.xmlimport.data.resources.ResourceParameter;
-import com.thoughtworks.xstream.converters.ConversionException;
-
-
-
-/**
- * Unit tests for {@link ResourceParameter}.
- * 
- * @author <a href="mailto:tim@mitheren.com>T. Rosser</a>
- * 
- */
-public class TestResourceParameter
-		extends BaseTest
-{
-	/** Test loading a valid resource parameter */
-	@Test
-	public void testLoadResourceParameterOK( )
-	{
-		String rp = this.createResourceParameterDefinition( "test" , "0" , "0" );
-		ResourceParameter instance = this.createObject( rp , ResourceParameter.class );
-		assertEquals( new Double( 0 ) , instance.getAverage( ) );
-		assertEquals( new Double( 0 ) , instance.getDeviation( ) );
-	}
-
-
-	/** Test loading a valid resource parameter with average containing a Double value */
-	@Test
-	public void testLoadResourceParameterDoubleAverageOK( )
-	{
-		String rp = this.createResourceParameterDefinition( "test" , "1.2" , "0" );
-		ResourceParameter instance = this.createObject( rp , ResourceParameter.class );
-		assertEquals( new Double( 1.2 ) , instance.getAverage( ) );
-		assertEquals( new Double( 0 ) , instance.getDeviation( ) );
-	}
-
-
-	/** Test loading a valid resource parameter with deviation containing a Double value */
-	@Test
-	public void testLoadResourceParameterDoubleDeviationOK( )
-	{
-		String rp = this.createResourceParameterDefinition( "test" , "0" , "1.2" );
-		ResourceParameter instance = this.createObject( rp , ResourceParameter.class );
-		assertEquals( new Double( 0 ) , instance.getAverage( ) );
-		assertEquals( new Double( 1.2 ) , instance.getDeviation( ) );
-	}
-
-
-	/** Test loading a valid resource parameter with no average */
-	@Test
-	public void testLoadResourceParameterNoAverage( )
-	{
-		String rp = this.createResourceParameterDefinition( "test" , null , "0" );
-		ResourceParameter instance = this.createObject( rp , ResourceParameter.class );
-		assertEquals( null , instance.getAverage( ) );
-		assertEquals( new Double( 0 ) , instance.getDeviation( ) );
-	}
-
-
-	/** Test loading a valid resource parameter with no deviation */
-	@Test
-	public void testLoadResourceParameterNoDeviation( )
-	{
-		String rp = this.createResourceParameterDefinition( "test" , "0" , null );
-		ResourceParameter instance = this.createObject( rp , ResourceParameter.class );
-		assertEquals( new Double( 0 ) , instance.getAverage( ) );
-		assertEquals( null , instance.getDeviation( ) );
-	}
-
-
-	/**
-	 * Test validating a valid resource parameter
-	 * 
-	 * @throws DataImportException
-	 *             if the data is not valid
-	 */
-	@Test
-	public void testValidateResourceParameterOK( )
-			throws DataImportException
-	{
-		String rp = this.createResourceParameterDefinition( "test" , "0" , "0" );
-		ResourceParameter instance = this.createObject( rp , ResourceParameter.class );
-		instance.verifyData( "test" );
-	}
-
-
-	/**
-	 * Test validating a valid resource parameter with average containing a Double value
-	 * 
-	 * @throws DataImportException
-	 *             if the data is not valid
-	 */
-	@Test
-	public void testValidateResourceParameterDoubleAverageOK( )
-			throws DataImportException
-	{
-		String rp = this.createResourceParameterDefinition( "test" , "1.2" , "0" );
-		ResourceParameter instance = this.createObject( rp , ResourceParameter.class );
-		instance.verifyData( "test" );
-	}
-
-
-	/**
-	 * Test validating a valid resource parameter with deviation containing a Double value
-	 * 
-	 * @throws DataImportException
-	 *             if the data is not valid
-	 */
-	@Test
-	public void testValidateResourceParameterDoubleDeviationOK( )
-			throws DataImportException
-	{
-		String rp = this.createResourceParameterDefinition( "test" , "0" , "1.2" );
-		ResourceParameter instance = this.createObject( rp , ResourceParameter.class );
-		instance.verifyData( "test" );
-	}
-
-
-	/**
-	 * Test validating a resource parameter with no average
-	 * 
-	 * @throws DataImportException
-	 *             if the data is not valid
-	 */
-	@Test( expected = DataImportException.class )
-	public void testValidateResourceParameterNoAverage( )
-			throws DataImportException
-	{
-		String rp = this.createResourceParameterDefinition( "test" , null , "0" );
-		ResourceParameter instance = this.createObject( rp , ResourceParameter.class );
-		instance.verifyData( "test" );
-	}
-
-
-	/**
-	 * Test validating a resource parameter with no deviation
-	 * 
-	 * @throws DataImportException
-	 *             if the data is not valid
-	 */
-	@Test( expected = DataImportException.class )
-	public void testValidateResourceParameterNoDeviation( )
-			throws DataImportException
-	{
-		String rp = this.createResourceParameterDefinition( "test" , "0" , null );
-		ResourceParameter instance = this.createObject( rp , ResourceParameter.class );
-		instance.verifyData( "test" );
-	}
-
-
-	/**
-	 * Test validating a resource parameter with a non-numerical string average
-	 * 
-	 * @throws DataImportException
-	 *             if the data is not valid
-	 * @throws ConversionException
-	 *             if XStream cannot convert the text into an object
-	 */
-	@Test( expected = ConversionException.class )
-	public void testValidateResourceParameterStringAverage( )
-			throws DataImportException , ConversionException
-	{
-		String rp = this.createResourceParameterDefinition( "test" , "test" , "0" );
-		ResourceParameter instance = this.createObject( rp , ResourceParameter.class );
-		instance.verifyData( "test" );
-	}
-
-
-	/**
-	 * Test validating a resource parameter with a non-numerical string deviation
-	 * 
-	 * @throws DataImportException
-	 *             if the data is not valid
-	 * @throws ConversionException
-	 *             if XStream cannot convert the text into an object
-	 */
-	@Test( expected = ConversionException.class )
-	public void testValidateResourceParameterStringDeviation( )
-			throws DataImportException , ConversionException
-	{
-		String rp = this.createResourceParameterDefinition( "test" , "0" , "test" );
-		ResourceParameter instance = this.createObject( rp , ResourceParameter.class );
-		instance.verifyData( "test" );
-	}
-}
diff --git a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/cli/xmlimport/data/resources/TestResources.java b/legacyworlds-server-tests/src/test/java/com/deepclone/lw/cli/xmlimport/data/resources/TestResources.java
deleted file mode 100644
index dc730a4..0000000
--- a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/cli/xmlimport/data/resources/TestResources.java
+++ /dev/null
@@ -1,137 +0,0 @@
-package com.deepclone.lw.cli.xmlimport.data.resources;
-
-
-import static org.junit.Assert.assertEquals;
-
-import org.junit.Before;
-import org.junit.Test;
-
-import com.deepclone.lw.cli.xmlimport.data.DataImportException;
-import com.deepclone.lw.cli.xmlimport.data.resources.BasicResource;
-import com.deepclone.lw.cli.xmlimport.data.resources.Resources;
-
-
-
-/**
- * Unit tests for {@link Resources}.
- * 
- * @author <a href="mailto:tim@mitheren.com>T. Rosser</a>
- * 
- */
-public class TestResources
-		extends BaseTest
-{
-	/** The basic resource definition used in most tests */
-	private String basicResourceDefinition;
-
-
-	/** Initialise the basic resource definition used in tests */
-	@Before
-	public void setUp( )
-	{
-		this.basicResourceDefinition = this.createBasicResourceDefinition( "test" , "test" , "0" , "test" );
-	}
-
-
-	/**
-	 * Try loading a valid top-level resource definition and make sure it's contents are correct
-	 * 
-	 * @throws DataImportException
-	 *             if the resource definition check fails
-	 */
-	@Test
-	public void testLoadValidResources( )
-			throws DataImportException
-	{
-		String xml = this.createTopLevel( this.basicResourceDefinition );
-		Resources resources = this.createObject( xml , Resources.class );
-
-		int count = 0;
-		for ( BasicResource resource : resources ) {
-			resource.verifyData( );
-			count++;
-		}
-		assertEquals( 1 , count );
-	}
-
-
-	/**
-	 * Try loading an empty top-level element
-	 * 
-	 * @throws NullPointerException
-	 *             if the resource definition check fails
-	 */
-	@Test( expected = NullPointerException.class )
-	public void testLoadEmpty( )
-			throws NullPointerException
-	{
-		String xml = this.createTopLevel( );
-		Resources resources = this.createObject( xml , Resources.class );
-		resources.iterator( );
-	}
-
-
-	/**
-	 * Test validating a valid top-level resource definition
-	 * 
-	 * @throws DataImportException
-	 *             if the resource definition check fails
-	 */
-	@Test
-	public void testValidateOK( )
-			throws DataImportException
-	{
-		String xml = this.createTopLevel( this.basicResourceDefinition );
-		Resources resources = this.createObject( xml , Resources.class );
-		resources.verifyData( );
-	}
-
-
-	/**
-	 * Try rejecting a top-level element that does not contain any resource definitions
-	 * 
-	 * @throws DataImportException
-	 *             if the resource definition check fails
-	 */
-	@Test( expected = DataImportException.class )
-	public void testValidateEmpty( )
-			throws DataImportException
-	{
-		String xml = this.createTopLevel( );
-		Resources resources = this.createObject( xml , Resources.class );
-		resources.verifyData( );
-	}
-
-
-	/**
-	 * Try rejecting a top-level element that contains an invalid resource definition
-	 * 
-	 * @throws DataImportException
-	 *             if the resource definition check fails
-	 */
-	@Test( expected = DataImportException.class )
-	public void testValidateBadDefinition( )
-			throws DataImportException
-	{
-		String xml = this.createTopLevel( this.createBasicResourceDefinition( null , null , null , null ) );
-		Resources resources = this.createObject( xml , Resources.class );
-		resources.verifyData( );
-	}
-
-
-	/**
-	 * Try rejecting a top-level element that contains two valid but duplicate resource definitions
-	 * 
-	 * @throws DataImportException
-	 *             if the resource definition check fails
-	 */
-	@Test( expected = DataImportException.class )
-	public void testValidateDuplicateDefinition( )
-			throws DataImportException
-	{
-		String xml = this.createTopLevel( this.basicResourceDefinition , this.basicResourceDefinition );
-		Resources resources = this.createObject( xml , Resources.class );
-		resources.verifyData( );
-	}
-
-}
\ No newline at end of file
diff --git a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/cli/xmlimport/data/techs/BaseTest.java b/legacyworlds-server-tests/src/test/java/com/deepclone/lw/cli/xmlimport/data/techs/BaseTest.java
deleted file mode 100644
index 2d70331..0000000
--- a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/cli/xmlimport/data/techs/BaseTest.java
+++ /dev/null
@@ -1,175 +0,0 @@
-package com.deepclone.lw.cli.xmlimport.data.techs;
-
-
-import com.deepclone.lw.cli.xmlimport.data.ImportableData;
-import com.thoughtworks.xstream.XStream;
-import com.thoughtworks.xstream.XStreamException;
-
-
-
-/**
- * Base class for testing technology importation
- * 
- * <p>
- * This class is used as a parent for tests of the technology import structures. It includes the
- * code used to actually create these technology definitions, as this can normally only be done
- * through XStream.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- * 
- */
-
-abstract class BaseTest
-{
-	/**
-	 * Escape &amp;, &lt; and &gt; in XML strings
-	 * 
-	 * @param string
-	 *            the string to escape
-	 * 
-	 * @return the escaped string
-	 */
-	private String xmlString( String string )
-	{
-		return string.replace( "&" , "&amp;" ).replace( "<" , "&lt;" ).replace( ">" , "&gt;" );
-	}
-
-
-	/**
-	 * Escape &amp;, &lt; and &gt;, ' and " in XML strings
-	 * 
-	 * @param string
-	 *            the string to escape
-	 * 
-	 * @return the escaped string
-	 */
-	private String quoteString( String string )
-	{
-		return "\"" + this.xmlString( string ).replace( "\"" , "&quot;" ).replace( "'" , "&apos;" ) + "\"";
-	}
-
-
-	/**
-	 * Create the XML code for a technology definition
-	 * 
-	 * <p>
-	 * This method generates the XML code for a technology definition, which can then be imported
-	 * using XStream into a {@link Technology} instance. It is capable of generating instances with
-	 * various fields set to <code>null</code>.
-	 * 
-	 * @param name
-	 *            identifier of the technology's name string
-	 * @param category
-	 *            identifier of the technology's category string
-	 * @param discovery
-	 *            identifier of the technology's discovery string
-	 * @param description
-	 *            identifier of the technology's description string
-	 * @param cost
-	 *            monetary cost of implementing the technology
-	 * @param points
-	 *            amount of research points required
-	 * @param dependencies
-	 *            dependencies as an array of strings
-	 * @return
-	 */
-	protected String createTechnology( String name , String category , String discovery , String description ,
-			Long cost , Long points , String... dependencies )
-	{
-		StringBuilder builder = new StringBuilder( "<technology" );
-
-		if ( name != null ) {
-			builder.append( " name=" ).append( this.quoteString( name ) );
-		}
-		if ( category != null ) {
-			builder.append( " category=" ).append( this.quoteString( category ) );
-		}
-		if ( discovery != null ) {
-			builder.append( " discovery=" ).append( this.quoteString( discovery ) );
-		}
-		if ( description != null ) {
-			builder.append( " description=" ).append( this.quoteString( description ) );
-		}
-		if ( cost != null ) {
-			builder.append( " cost=\"" ).append( cost ).append( "\"" );
-		}
-		if ( points != null ) {
-			builder.append( " points=\"" ).append( points ).append( "\"" );
-		}
-
-		if ( dependencies.length == 0 ) {
-			builder.append( " />" );
-		} else {
-			builder.append( ">" );
-			for ( String dep : dependencies ) {
-				builder.append( "<depends-on>" );
-				if ( dep != null ) {
-					builder.append( this.xmlString( dep ) );
-				}
-				builder.append( "</depends-on>" );
-			}
-			builder.append( "</technology>" );
-		}
-
-		return builder.toString( );
-	}
-
-
-	/**
-	 * Creates the XML code for a top-level technology definition element
-	 * 
-	 * @param resources
-	 *            XML definitions of technologies
-	 * 
-	 * @return the top-level element's XML code
-	 */
-	protected String createTopLevel( String... technologies )
-	{
-		StringBuilder str = new StringBuilder( );
-		str.append( "<lw-tech-graph>" );
-		for ( String technology : technologies ) {
-			str.append( technology );
-		}
-		str.append( "</lw-tech-graph>" );
-		return str.toString( );
-	}
-
-
-	/**
-	 * Create the necessary XStream instance
-	 * 
-	 * <p>
-	 * Initialise an XStream instance and set it up so it can process technology data definitions.
-	 * This includes annotation processing, of course, but also generating an alias allowing the
-	 * &lt;technology&gt; tag to be recognised on its own.
-	 */
-	private XStream createXStreamInstance( )
-	{
-		XStream xstream = new XStream( );
-		xstream.processAnnotations( Technologies.class );
-		xstream.alias( "technology" , Technology.class );
-		return xstream;
-	}
-
-
-	/**
-	 * Create a resource object from its XML code
-	 * 
-	 * @param xml
-	 *            the XML code
-	 * @param cls
-	 *            the class of the object
-	 * 
-	 * @return the object that was created from the code
-	 * 
-	 * @throws ClassCastException
-	 *             if the code corresponds to some other type of object
-	 * @throws XStreamException
-	 *             if some error occurred while deserialising the object
-	 */
-	protected < T extends ImportableData > T createObject( String xml , Class< T > cls )
-			throws ClassCastException , XStreamException
-	{
-		return cls.cast( this.createXStreamInstance( ).fromXML( xml ) );
-	}
-}
diff --git a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/cli/xmlimport/data/techs/TestTechnologies.java b/legacyworlds-server-tests/src/test/java/com/deepclone/lw/cli/xmlimport/data/techs/TestTechnologies.java
deleted file mode 100644
index bd5c6ac..0000000
--- a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/cli/xmlimport/data/techs/TestTechnologies.java
+++ /dev/null
@@ -1,96 +0,0 @@
-package com.deepclone.lw.cli.xmlimport.data.techs;
-
-
-import static org.junit.Assert.*;
-
-import org.junit.Test;
-
-import com.deepclone.lw.cli.xmlimport.data.DataImportException;
-
-
-
-/**
- * Unit tests for the {@link Technologies} class
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-public class TestTechnologies
-		extends BaseTest
-{
-
-	/**
-	 * Test loading an empty list of technologies
-	 * 
-	 * <p>
-	 * {@link Technologies#iterator()} will throw {@link NullPointerException} when there are no
-	 * definitions. Use that to determine if it is empty.
-	 */
-	@Test( expected = NullPointerException.class )
-	public void testEmpty( )
-	{
-		String defs = this.createTopLevel( );
-		Technologies techs = this.createObject( defs , Technologies.class );
-		techs.iterator( );
-	}
-
-
-	/**
-	 * Test loading a list of technologies
-	 */
-	@Test
-	public void testTechs( )
-	{
-		String tDef = this.createTechnology( "name" , "category" , "discovery" , "description" , 12L , 34L );
-		String defs = this.createTopLevel( tDef );
-		Technologies techs = this.createObject( defs , Technologies.class );
-
-		int i = 0;
-		for ( Technology technology : techs ) {
-			assertNotNull( technology );
-			assertEquals( 0 , i );
-			i++;
-		}
-	}
-
-
-	/**
-	 * Test verifying an empty list of technologies
-	 */
-	@Test( expected = DataImportException.class )
-	public void testVerifyEmpty( )
-			throws DataImportException
-	{
-		String defs = this.createTopLevel( );
-		Technologies techs = this.createObject( defs , Technologies.class );
-		techs.verifyData( );
-	}
-
-
-	/**
-	 * Test verifying a list of technologies with an invalid technology in it
-	 */
-	@Test( expected = DataImportException.class )
-	public void testVerifyInvalid( )
-			throws DataImportException
-	{
-		String tDef = this.createTechnology( null , "category" , "discovery" , "description" , 12L , 34L );
-		String defs = this.createTopLevel( tDef );
-		Technologies techs = this.createObject( defs , Technologies.class );
-		techs.verifyData( );
-	}
-
-
-	/**
-	 * Test verifying a valid list of technologies
-	 */
-	@Test
-	public void testVerifyOk( )
-			throws DataImportException
-	{
-		String tDef = this.createTechnology( "name" , "category" , "discovery" , "description" , 12L , 34L );
-		String defs = this.createTopLevel( tDef );
-		Technologies techs = this.createObject( defs , Technologies.class );
-		techs.verifyData( );
-	}
-
-}
diff --git a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/cli/xmlimport/data/techs/TestTechnology.java b/legacyworlds-server-tests/src/test/java/com/deepclone/lw/cli/xmlimport/data/techs/TestTechnology.java
deleted file mode 100644
index 4b76abc..0000000
--- a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/cli/xmlimport/data/techs/TestTechnology.java
+++ /dev/null
@@ -1,329 +0,0 @@
-package com.deepclone.lw.cli.xmlimport.data.techs;
-
-
-import static org.junit.Assert.*;
-
-import org.junit.Test;
-
-import com.deepclone.lw.cli.xmlimport.data.DataImportException;
-
-
-
-/**
- * Test the {@link Technology} class
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-public class TestTechnology
-		extends BaseTest
-{
-
-	/**
-	 * Test loading a definition with no dependencies
-	 */
-	@Test
-	public void testLoadNoDeps( )
-	{
-		String definition = this.createTechnology( "name" , "category" , "discovery" , "description" , 12L , 34L );
-		Technology technology = this.createObject( definition , Technology.class );
-
-		assertNotNull( technology );
-		assertEquals( "name" , technology.getName( ) );
-		assertEquals( "category" , technology.getCategory( ) );
-		assertEquals( "discovery" , technology.getDiscovery( ) );
-		assertEquals( "description" , technology.getDescription( ) );
-		assertEquals( new Long( 12 ) , technology.getCost( ) );
-		assertEquals( new Long( 34 ) , technology.getPoints( ) );
-
-		assertNotNull( technology.getDependencies( ) );
-		assertTrue( technology.getDependencies( ).isEmpty( ) );
-	}
-
-
-	/**
-	 * Test loading a definition with dependencies
-	 */
-	@Test
-	public void testLoadDeps( )
-	{
-		String definition = this.createTechnology( "name" , "category" , "discovery" , "description" , 12L , 34L ,
-				"dep1" , "dep2" );
-		Technology technology = this.createObject( definition , Technology.class );
-
-		assertNotNull( technology );
-		assertEquals( "name" , technology.getName( ) );
-		assertEquals( "category" , technology.getCategory( ) );
-		assertEquals( "discovery" , technology.getDiscovery( ) );
-		assertEquals( "description" , technology.getDescription( ) );
-		assertEquals( new Long( 12 ) , technology.getCost( ) );
-		assertEquals( new Long( 34 ) , technology.getPoints( ) );
-
-		assertNotNull( technology.getDependencies( ) );
-		assertEquals( 2 , technology.getDependencies( ).size( ) );
-		assertEquals( "dep1" , technology.getDependencies( ).get( 0 ) );
-		assertEquals( "dep2" , technology.getDependencies( ).get( 1 ) );
-	}
-
-
-	/**
-	 * Test {@link Technology#verifyData()} when the name is null
-	 */
-	@Test( expected = DataImportException.class )
-	public void testVerifyNameNull( )
-			throws DataImportException
-	{
-		String definition = this.createTechnology( null , "category" , "discovery" , "description" , 12L , 34L );
-		Technology technology = this.createObject( definition , Technology.class );
-		technology.verifyData( );
-	}
-
-
-	/**
-	 * Test {@link Technology#verifyData()} when the name is empty
-	 */
-	@Test( expected = DataImportException.class )
-	public void testVerifyNameEmpty( )
-			throws DataImportException
-	{
-		String definition = this.createTechnology( "" , "category" , "discovery" , "description" , 12L , 34L );
-		Technology technology = this.createObject( definition , Technology.class );
-		technology.verifyData( );
-	}
-
-
-	/**
-	 * Test {@link Technology#verifyData()} when the name consists of spaces only
-	 */
-	@Test( expected = DataImportException.class )
-	public void testVerifyNameSpaces( )
-			throws DataImportException
-	{
-		String definition = this.createTechnology( "    " , "category" , "discovery" , "description" , 12L , 34L );
-		Technology technology = this.createObject( definition , Technology.class );
-		technology.verifyData( );
-	}
-
-
-	/**
-	 * Test {@link Technology#verifyData()} when the category is null
-	 */
-	@Test( expected = DataImportException.class )
-	public void testVerifyCategoryNull( )
-			throws DataImportException
-	{
-		String definition = this.createTechnology( "name" , null , "discovery" , "description" , 12L , 34L );
-		Technology technology = this.createObject( definition , Technology.class );
-		technology.verifyData( );
-	}
-
-
-	/**
-	 * Test {@link Technology#verifyData()} when the category is empty
-	 */
-	@Test( expected = DataImportException.class )
-	public void testVerifyCategoryEmpty( )
-			throws DataImportException
-	{
-		String definition = this.createTechnology( "name" , "" , "discovery" , "description" , 12L , 34L );
-		Technology technology = this.createObject( definition , Technology.class );
-		technology.verifyData( );
-	}
-
-
-	/**
-	 * Test {@link Technology#verifyData()} when the category consists of spaces only
-	 */
-	@Test( expected = DataImportException.class )
-	public void testVerifyCategorySpaces( )
-			throws DataImportException
-	{
-		String definition = this.createTechnology( "name" , "    " , "discovery" , "description" , 12L , 34L );
-		Technology technology = this.createObject( definition , Technology.class );
-		technology.verifyData( );
-	}
-
-
-	/**
-	 * Test {@link Technology#verifyData()} when the discovery string is null
-	 */
-	@Test( expected = DataImportException.class )
-	public void testVerifyDiscoveryNull( )
-			throws DataImportException
-	{
-		String definition = this.createTechnology( "name" , "category" , null , "description" , 12L , 34L );
-		Technology technology = this.createObject( definition , Technology.class );
-		technology.verifyData( );
-	}
-
-
-	/**
-	 * Test {@link Technology#verifyData()} when the discovery string is empty
-	 */
-	@Test( expected = DataImportException.class )
-	public void testVerifyDiscoveryEmpty( )
-			throws DataImportException
-	{
-		String definition = this.createTechnology( "name" , "category" , "" , "description" , 12L , 34L );
-		Technology technology = this.createObject( definition , Technology.class );
-		technology.verifyData( );
-	}
-
-
-	/**
-	 * Test {@link Technology#verifyData()} when the discovery string consists of spaces only
-	 */
-	@Test( expected = DataImportException.class )
-	public void testVerifyDiscoverySpaces( )
-			throws DataImportException
-	{
-		String definition = this.createTechnology( "name" , "category" , "    " , "description" , 12L , 34L );
-		Technology technology = this.createObject( definition , Technology.class );
-		technology.verifyData( );
-	}
-
-
-	/**
-	 * Test {@link Technology#verifyData()} when the description is null
-	 */
-	@Test( expected = DataImportException.class )
-	public void testVerifyDescriptionNull( )
-			throws DataImportException
-	{
-		String definition = this.createTechnology( "name" , "category" , "discovery" , null , 12L , 34L );
-		Technology technology = this.createObject( definition , Technology.class );
-		technology.verifyData( );
-	}
-
-
-	/**
-	 * Test {@link Technology#verifyData()} when the description is empty
-	 */
-	@Test( expected = DataImportException.class )
-	public void testVerifyDescriptionEmpty( )
-			throws DataImportException
-	{
-		String definition = this.createTechnology( "name" , "category" , "discovery" , "" , 12L , 34L );
-		Technology technology = this.createObject( definition , Technology.class );
-		technology.verifyData( );
-	}
-
-
-	/**
-	 * Test {@link Technology#verifyData()} when the description consists of spaces only
-	 */
-	@Test( expected = DataImportException.class )
-	public void testVerifyDescriptionSpaces( )
-			throws DataImportException
-	{
-		String definition = this.createTechnology( "name" , "category" , "discovery" , "  " , 12L , 34L );
-		Technology technology = this.createObject( definition , Technology.class );
-		technology.verifyData( );
-	}
-
-
-	/**
-	 * Test {@link Technology#verifyData()} when the cost is null
-	 */
-	@Test( expected = DataImportException.class )
-	public void testVerifyCostNull( )
-			throws DataImportException
-	{
-		String definition = this.createTechnology( "name" , "category" , "discovery" , "description" , null , 34L );
-		Technology technology = this.createObject( definition , Technology.class );
-		technology.verifyData( );
-	}
-
-
-	/**
-	 * Test {@link Technology#verifyData()} when the cost is 0
-	 */
-	@Test( expected = DataImportException.class )
-	public void testVerifyCostZero( )
-			throws DataImportException
-	{
-		String definition = this.createTechnology( "name" , "category" , "discovery" , "description" , 0L , 34L );
-		Technology technology = this.createObject( definition , Technology.class );
-		technology.verifyData( );
-	}
-
-
-	/**
-	 * Test {@link Technology#verifyData()} when the amount of points is null
-	 */
-	@Test( expected = DataImportException.class )
-	public void testVerifyPointsNull( )
-			throws DataImportException
-	{
-		String definition = this.createTechnology( "name" , "category" , "discovery" , "description" , 12L , null );
-		Technology technology = this.createObject( definition , Technology.class );
-		technology.verifyData( );
-	}
-
-
-	/**
-	 * Test {@link Technology#verifyData()} when the amount of points is 0
-	 */
-	@Test( expected = DataImportException.class )
-	public void testVerifyPointsZero( )
-			throws DataImportException
-	{
-		String definition = this.createTechnology( "name" , "category" , "discovery" , "description" , 12L , 0L );
-		Technology technology = this.createObject( definition , Technology.class );
-		technology.verifyData( );
-	}
-
-
-	/**
-	 * Test {@link Technology#verifyData()} on a valid definition with no dependencies
-	 */
-	@Test
-	public void testVerifyValidNoDeps( )
-			throws DataImportException
-	{
-		String definition = this.createTechnology( "name" , "category" , "discovery" , "description" , 12L , 34L );
-		Technology technology = this.createObject( definition , Technology.class );
-		technology.verifyData( );
-	}
-
-
-	/**
-	 * Test {@link Technology#verifyData()} when a dependency is empty
-	 */
-	@Test( expected = DataImportException.class )
-	public void testVerifyDepsEmpty( )
-			throws DataImportException
-	{
-		String definition = this.createTechnology( "name" , "category" , "discovery" , "description" , 12L , 34L , "" );
-		Technology technology = this.createObject( definition , Technology.class );
-		technology.verifyData( );
-	}
-
-
-	/**
-	 * Test {@link Technology#verifyData()} when a dependency consists of spaces only
-	 */
-	@Test( expected = DataImportException.class )
-	public void testVerifyDepsSpaces( )
-			throws DataImportException
-	{
-		String definition = this.createTechnology( "name" , "category" , "discovery" , "description" , 12L , 34L ,
-				"   " );
-		Technology technology = this.createObject( definition , Technology.class );
-		technology.verifyData( );
-	}
-
-
-	/**
-	 * Test {@link Technology#verifyData()} on a valid definition with dependencies
-	 */
-	@Test
-	public void testVerifyValidDeps( )
-			throws DataImportException
-	{
-		String definition = this.createTechnology( "name" , "category" , "discovery" , "description" , 12L , 34L ,
-				"dep1" , "dep2" );
-		Technology technology = this.createObject( definition , Technology.class );
-		technology.verifyData( );
-	}
-
-}
diff --git a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/testing/MockLogger.java b/legacyworlds-server-tests/src/test/java/com/deepclone/lw/testing/MockLogger.java
deleted file mode 100644
index a047453..0000000
--- a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/testing/MockLogger.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package com.deepclone.lw.testing;
-
-
-import java.util.HashMap;
-
-import com.deepclone.lw.interfaces.eventlog.Logger;
-import com.deepclone.lw.interfaces.eventlog.SystemLogger;
-
-
-
-/**
- * A mock Logger component
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- * 
- */
-public class MockLogger
-		implements Logger
-{
-	/** Map of existing system loggers */
-	private final HashMap< String , MockSystemLogger > loggers = new HashMap< String , MockSystemLogger >( );
-
-
-	@Override
-	public SystemLogger getSystemLogger( String component )
-	{
-		MockSystemLogger logger = this.loggers.get( component );
-		if ( logger == null ) {
-			this.loggers.put( component , logger = new MockSystemLogger( ) );
-		}
-		return logger;
-	}
-
-}
diff --git a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/testing/MockResultSet.java b/legacyworlds-server-tests/src/test/java/com/deepclone/lw/testing/MockResultSet.java
deleted file mode 100644
index fc92bed..0000000
--- a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/testing/MockResultSet.java
+++ /dev/null
@@ -1,271 +0,0 @@
-package com.deepclone.lw.testing;
-
-
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-import java.lang.reflect.Proxy;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.util.HashMap;
-
-
-
-/**
- * Mock result set
- * 
- * <p>
- * This class uses a proxy to mock a {@link ResultSet} instance. It can be used in unit tests to
- * fake SQL operation results.
- * 
- * <p>
- * FIXME: for now, this class is mostly empty. It will be filled as necessary when writing tests.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-public class MockResultSet
-		implements InvocationHandler
-{
-	/** The rows in this result set */
-	private final HashMap< String , Object >[] rows;
-
-	/** The current row's index */
-	private int index = -1;
-
-	/** Last read column was <code>null</code>? */
-	private boolean nullFound = false;
-
-
-	/**
-	 * Initialise the result set's rows.
-	 * 
-	 * @param rows
-	 *            an array of hash tables that will be returned when trying to access the result set
-	 */
-	private MockResultSet( HashMap< String , Object >[] rows )
-	{
-		this.rows = rows;
-	}
-
-
-	@Override
-	public Object invoke( Object proxy , Method method , Object[] args )
-			throws Throwable
-	{
-		Method m = MockResultSet.class.getMethod( method.getName( ) , method.getParameterTypes( ) );
-		if ( m == null ) {
-			throw new SQLException( "Unsupported method " + method.getName( ) );
-		}
-
-		return m.invoke( this , args );
-	}
-
-
-	/**
-	 * Create a mock result set
-	 * 
-	 * @param rows
-	 *            the values that will be returned by the result set
-	 * 
-	 * @return a mock result set
-	 */
-	public static ResultSet create( HashMap< String , Object >[] rows )
-	{
-		return (ResultSet) Proxy.newProxyInstance( ResultSet.class.getClassLoader( ) , new Class[] {
-			ResultSet.class
-		} , new MockResultSet( rows ) );
-	}
-
-
-	/**
-	 * Move the cursor to some row
-	 * 
-	 * @param row
-	 *            the row to select
-	 * 
-	 * @return <code>true</code> if the cursor is inside the fake result, <code>false</code> if it
-	 *         isn't.
-	 */
-	public boolean absolute( int row )
-	{
-		if ( row < 0 ) {
-			row = this.rows.length + row;
-		} else {
-			row--;
-		}
-
-		if ( row < 0 ) {
-			this.index = -1;
-			return false;
-		}
-
-		if ( row >= this.rows.length ) {
-			this.index = this.rows.length - 1;
-			return false;
-		}
-
-		this.index = row;
-		return true;
-	}
-
-
-	/**
-	 * Access the next "row"
-	 * 
-	 * <p>
-	 * If there are more "rows" available, move to the next one.
-	 * 
-	 * @return <code>true</code> if there are more rows, <code>false</code> if there aren't.
-	 */
-	public boolean next( )
-	{
-		if ( this.index < this.rows.length ) {
-			this.index++;
-		}
-		return this.index < this.rows.length;
-	}
-
-
-	/**
-	 * Check if the last value accessed contained NULL
-	 * 
-	 * @return <code>true</code> if it did, <code>false</code> if it didn't
-	 */
-	public boolean wasNull( )
-	{
-		return this.nullFound;
-	}
-
-
-	/**
-	 * Return the object in some column of the current "row"
-	 * 
-	 * @param columnName
-	 *            the column's name
-	 * 
-	 * @return the object from the fake results
-	 * 
-	 * @throws SQLException
-	 *             if no row is selected
-	 */
-	public Object getObject( String columnName )
-			throws SQLException
-	{
-		if ( this.index < 0 || this.index >= this.rows.length ) {
-			throw new SQLException( "Current row is out of bounds" );
-		}
-		Object object = this.rows[ this.index ].get( columnName );
-		this.nullFound = ( object == null );
-		return object;
-	}
-
-
-	/**
-	 * Return the object in some column of the current "row" as a string
-	 * 
-	 * @param columnName
-	 *            the column's name
-	 * 
-	 * @return the object from the fake results, as a string
-	 * 
-	 * @throws SQLException
-	 *             if no row is selected
-	 */
-	public String getString( String columnName )
-			throws SQLException
-	{
-		Object object = this.getObject( columnName );
-		if ( object != null ) {
-			return object.toString( );
-		}
-		return null;
-	}
-
-
-	/**
-	 * Return the object in some column of the current "row" as a boolean
-	 * 
-	 * @param columnName
-	 *            the column's name
-	 * 
-	 * @return the object from the fake results, as a boolean
-	 * 
-	 * @throws SQLException
-	 *             if no row is selected
-	 */
-	public boolean getBoolean( String columnName )
-			throws SQLException
-	{
-		Object object = this.getObject( columnName );
-		if ( object != null ) {
-			return (Boolean) object;
-		}
-		return false;
-	}
-
-
-	/**
-	 * Return the object in some column of the current "row" as an integer
-	 * 
-	 * @param columnName
-	 *            the column's name
-	 * 
-	 * @return the object from the fake results, as an integer
-	 * 
-	 * @throws SQLException
-	 *             if no row is selected
-	 */
-	public int getInt( String columnName )
-			throws SQLException
-	{
-		Object object = this.getObject( columnName );
-		if ( object != null ) {
-			return (Integer) object;
-		}
-		return 0;
-	}
-
-
-	/**
-	 * Return the object in some column of the current "row" as a long integer
-	 * 
-	 * @param columnName
-	 *            the column's name
-	 * 
-	 * @return the object from the fake results, as a long integer
-	 * 
-	 * @throws SQLException
-	 *             if no row is selected
-	 */
-	public long getLong( String columnName )
-			throws SQLException
-	{
-		Object object = this.getObject( columnName );
-		if ( object != null ) {
-			return (Long) object;
-		}
-		return 0;
-	}
-
-
-	/**
-	 * Return the object in some column of the current "row" as a double
-	 * 
-	 * @param columnName
-	 *            the column's name
-	 * 
-	 * @return the object from the fake results, as a double
-	 * 
-	 * @throws SQLException
-	 *             if no row is selected
-	 */
-	public double getDouble( String columnName )
-			throws SQLException
-	{
-		Object object = this.getObject( columnName );
-		if ( object != null ) {
-			return (Double) object;
-		}
-		return 0;
-	}
-
-}
diff --git a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/testing/MockSystemLogger.java b/legacyworlds-server-tests/src/test/java/com/deepclone/lw/testing/MockSystemLogger.java
deleted file mode 100644
index 5d15c20..0000000
--- a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/testing/MockSystemLogger.java
+++ /dev/null
@@ -1,62 +0,0 @@
-package com.deepclone.lw.testing;
-
-
-import com.deepclone.lw.cmd.admin.logs.LogLevel;
-import com.deepclone.lw.interfaces.eventlog.SystemLogger;
-
-
-
-/**
- * A mock logger for components
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-public class MockSystemLogger
-		implements SystemLogger
-{
-	/** How many messages were logged */
-	private int counter = 0;
-
-
-	/** @return the amount of messages that were logged */
-	public int getCounter( )
-	{
-		return counter;
-	}
-
-
-	/**
-	 * Set the message counter
-	 * 
-	 * @param counter
-	 *            the counter's new value
-	 */
-	public void setCounter( int counter )
-	{
-		this.counter = counter;
-	}
-
-
-	@Override
-	public SystemLogger log( LogLevel level , String message )
-	{
-		this.counter++;
-		return this;
-	}
-
-
-	@Override
-	public SystemLogger log( LogLevel level , String message , Throwable exception )
-	{
-		this.counter++;
-		return this;
-	}
-
-
-	@Override
-	public SystemLogger flush( )
-	{
-		return this;
-	}
-
-}
diff --git a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/testing/MockSystemStatus.java b/legacyworlds-server-tests/src/test/java/com/deepclone/lw/testing/MockSystemStatus.java
deleted file mode 100644
index 52bb8f8..0000000
--- a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/testing/MockSystemStatus.java
+++ /dev/null
@@ -1,148 +0,0 @@
-package com.deepclone.lw.testing;
-
-
-import com.deepclone.lw.interfaces.sys.MaintenanceData;
-import com.deepclone.lw.interfaces.sys.MaintenanceStatusException;
-import com.deepclone.lw.interfaces.sys.SystemStatus;
-import com.deepclone.lw.interfaces.sys.TickStatusException;
-
-
-
-/**
- * A mock system status component
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-public class MockSystemStatus
-		implements SystemStatus
-{
-	/** Maintenance data to return when {@link #checkMaintenance()} is called */
-	private MaintenanceData maintenance = null;
-
-	/** Value that determines the behaviour of {@link #startTick()} */
-	private long stValue = 0;
-
-	/** Value that determines the behaviour of {@link #checkStuckTick()} */
-	private long cstValue = -1;
-
-	/** Was {@link #startTick()} called? */
-	private boolean startTickCalled = false;
-
-
-	/**
-	 * Set the maintenance data to return when {@link #checkMaintenance()} is called
-	 * 
-	 * @param maintenance
-	 *            the data to return from {@link #checkMaintenance()}
-	 */
-	public void setMaintenance( MaintenanceData maintenance )
-	{
-		this.maintenance = maintenance;
-	}
-
-
-	/**
-	 * Set the value that determines the behaviour of {@link #checkStuckTick()}
-	 * 
-	 * <ul>
-	 * <li>-2 will cause a {@link MaintenanceStatusException},
-	 * <li>-1 will cause it to return <code>null</code>,
-	 * <li>any other value will be returned.
-	 * </ul>
-	 * 
-	 * @param cstValue
-	 *            the value
-	 */
-	public void setCSTBehaviour( long cstValue )
-	{
-		this.cstValue = cstValue;
-	}
-
-
-	/**
-	 * Set the value that determines the behaviour of {@link #startTick()}
-	 * 
-	 * <ul>
-	 * <li>-2 will cause a {@link MaintenanceStatusException},
-	 * <li>-1 will cause a {@link TickStatusException},
-	 * <li>any other value will be returned.
-	 * </ul>
-	 * 
-	 * @param cstValue
-	 *            the value
-	 */
-	public void setSTBehaviour( long stValue )
-	{
-		this.stValue = stValue;
-	}
-
-
-	/**
-	 * @return <code>true</code> if {@link #startTick()} was called.
-	 */
-	public boolean wasStartTickCalled( )
-	{
-		return startTickCalled;
-	}
-
-
-	@Override
-	public MaintenanceData checkMaintenance( )
-	{
-		return this.maintenance;
-	}
-
-
-	@Override
-	public void startMaintenance( int adminId , String reason , int duration )
-			throws MaintenanceStatusException
-	{
-		// EMPTY - ignored
-	}
-
-
-	@Override
-	public void updateMaintenance( int adminId , int durationFromNow )
-			throws MaintenanceStatusException
-	{
-		// EMPTY - ignored
-	}
-
-
-	@Override
-	public void endMaintenance( int adminId )
-			throws MaintenanceStatusException
-	{
-		// EMPTY - ignored
-	}
-
-
-	@Override
-	public long startTick( )
-			throws TickStatusException , MaintenanceStatusException
-	{
-		this.startTickCalled = true;
-		if ( this.stValue == -1 ) {
-			throw new TickStatusException( );
-		}
-		if ( this.stValue == -2 ) {
-			throw new MaintenanceStatusException( );
-		}
-		return this.stValue;
-	}
-
-
-	@Override
-	public Long checkStuckTick( )
-			throws MaintenanceStatusException
-	{
-		if ( this.cstValue == -1 ) {
-			return null;
-		}
-		if ( this.cstValue == -2 ) {
-			throw new MaintenanceStatusException( );
-		}
-		return this.cstValue;
-	}
-
-}
diff --git a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/testing/MockTicker.java b/legacyworlds-server-tests/src/test/java/com/deepclone/lw/testing/MockTicker.java
deleted file mode 100644
index 6dc8fe9..0000000
--- a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/testing/MockTicker.java
+++ /dev/null
@@ -1,82 +0,0 @@
-package com.deepclone.lw.testing;
-
-
-import com.deepclone.lw.interfaces.sys.Ticker;
-
-import static org.junit.Assert.*;
-
-
-
-/**
- * A mock ticker component
- * 
- * <p>
- * This mock component can be used to make sure that another component registers some task as
- * expected.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- * 
- */
-public class MockTicker
-		implements Ticker
-{
-	/** The task's expected frequency */
-	private final Frequency expectedFrequency;
-
-	/** The task's expected name */
-	private final String expectedName;
-
-	/** The task's expected type */
-	private final Class< ? > expectedType;
-
-
-	/**
-	 * Initialise the mock ticker's expectations
-	 * 
-	 * @param expectedFrequency
-	 *            the task's expected frequency
-	 * @param expectedName
-	 *            the task's expected name
-	 * @param expectedType
-	 *            the task's expected type
-	 */
-	public MockTicker( Frequency expectedFrequency , String expectedName , Class< ? > expectedType )
-	{
-		this.expectedFrequency = expectedFrequency;
-		this.expectedName = expectedName;
-		this.expectedType = expectedType;
-	}
-
-
-	@Override
-	public void registerTask( Frequency frequency , String name , Runnable task )
-	{
-		assertEquals( this.expectedFrequency , frequency );
-		assertEquals( this.expectedName , name );
-		assertTrue( this.expectedType.isInstance( task ) );
-	}
-
-
-	@Override
-	public void pause( )
-			throws IllegalStateException
-	{
-		// EMPTY - ignored
-	}
-
-
-	@Override
-	public void unpause( )
-			throws IllegalStateException
-	{
-		// EMPTY - ignored
-	}
-
-
-	@Override
-	public boolean isActive( )
-	{
-		return true;
-	}
-
-}
diff --git a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/testing/MockTransactionManager.java b/legacyworlds-server-tests/src/test/java/com/deepclone/lw/testing/MockTransactionManager.java
deleted file mode 100644
index 3b68085..0000000
--- a/legacyworlds-server-tests/src/test/java/com/deepclone/lw/testing/MockTransactionManager.java
+++ /dev/null
@@ -1,43 +0,0 @@
-package com.deepclone.lw.testing;
-
-
-import org.springframework.transaction.PlatformTransactionManager;
-import org.springframework.transaction.TransactionDefinition;
-import org.springframework.transaction.TransactionException;
-import org.springframework.transaction.TransactionStatus;
-
-
-
-/**
- * A mock transaction manager
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-public class MockTransactionManager
-		implements PlatformTransactionManager
-{
-
-	@Override
-	public TransactionStatus getTransaction( TransactionDefinition definition )
-			throws TransactionException
-	{
-		return null;
-	}
-
-
-	@Override
-	public void commit( TransactionStatus status )
-			throws TransactionException
-	{
-		// EMPTY
-	}
-
-
-	@Override
-	public void rollback( TransactionStatus status )
-			throws TransactionException
-	{
-		// EMPTY
-	}
-
-}
diff --git a/legacyworlds-server-tests/src/test/resources/.empty b/legacyworlds-server-tests/src/test/resources/.empty
deleted file mode 100644
index e69de29..0000000
diff --git a/legacyworlds-server-utils/src/main/resources/.empty b/legacyworlds-server-utils/src/main/resources/.empty
deleted file mode 100644
index e69de29..0000000
diff --git a/legacyworlds-server-utils/src/test/java/.empty b/legacyworlds-server-utils/src/test/java/.empty
deleted file mode 100644
index e69de29..0000000
diff --git a/legacyworlds-server-utils/src/test/resources/.empty b/legacyworlds-server-utils/src/test/resources/.empty
deleted file mode 100644
index e69de29..0000000
diff --git a/legacyworlds-server/.project b/legacyworlds-server/.project
new file mode 100644
index 0000000..5ff6ca3
--- /dev/null
+++ b/legacyworlds-server/.project
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>legacyworlds-server</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.maven.ide.eclipse.maven2Builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.maven.ide.eclipse.maven2Nature</nature>
+	</natures>
+</projectDescription>
diff --git a/legacyworlds-server/legacyworlds-server-beans/.project b/legacyworlds-server/legacyworlds-server-beans/.project
new file mode 100644
index 0000000..7f3bd93
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/.project
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>legacyworlds-server-beans</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.maven.ide.eclipse.maven2Builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.maven.ide.eclipse.maven2Nature</nature>
+	</natures>
+</projectDescription>
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/.classpath b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/.classpath
new file mode 100644
index 0000000..7c3d14f
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/.classpath
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" output="target/classes" path="src/main/java"/>
+	<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources"/>
+	<classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
+	<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+	<classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER"/>
+	<classpathentry kind="output" path="target/classes"/>
+</classpath>
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/.project b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/.project
new file mode 100644
index 0000000..a5031a0
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/.project
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>legacyworlds-server-beans-accounts</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.maven.ide.eclipse.maven2Builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.maven.ide.eclipse.maven2Nature</nature>
+	</natures>
+</projectDescription>
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/.settings/org.eclipse.jdt.core.prefs b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..cb25da1
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,6 @@
+#Fri Apr 09 10:19:20 CEST 2010
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.6
diff --git a/legacyworlds-server-beans-accounts/pom.xml b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/pom.xml
similarity index 67%
rename from legacyworlds-server-beans-accounts/pom.xml
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/pom.xml
index a150eda..67b65e7 100644
--- a/legacyworlds-server-beans-accounts/pom.xml
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/pom.xml
@@ -4,12 +4,12 @@
 	<parent>
 		<artifactId>legacyworlds-server-beans</artifactId>
 		<groupId>com.deepclone.lw</groupId>
-		<version>1.0.0</version>
-		<relativePath>../legacyworlds-server-beans/pom.xml</relativePath>
+		<version>5.99.2</version>
 	</parent>
 
+	<groupId>com.deepclone.lw</groupId>
 	<artifactId>legacyworlds-server-beans-accounts</artifactId>
-	<name>Legacy Worlds - Server - Components - Accounts</name>
-	<version>${legacyworlds.version.main}.${legacyworlds.version.release}-${legacyworlds.version.build}</version>
+	<name>Legacy Worlds account management</name>
+	<version>5.99.2</version>
 	<description>This package contains the beans responsible for managing accounts, including registration, inactivity checks, bans and authentication.</description>
-</project>
+</project>
\ No newline at end of file
diff --git a/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/acm/AccountCleanupBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/acm/AccountCleanupBean.java
similarity index 100%
rename from legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/acm/AccountCleanupBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/acm/AccountCleanupBean.java
diff --git a/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/acm/AccountCleanupTask.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/acm/AccountCleanupTask.java
similarity index 100%
rename from legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/acm/AccountCleanupTask.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/acm/AccountCleanupTask.java
diff --git a/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/acm/AccountManagementBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/acm/AccountManagementBean.java
similarity index 100%
rename from legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/acm/AccountManagementBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/acm/AccountManagementBean.java
diff --git a/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/acm/QuitProcessorBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/acm/QuitProcessorBean.java
similarity index 100%
rename from legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/acm/QuitProcessorBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/acm/QuitProcessorBean.java
diff --git a/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/acm/QuitProcessorTask.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/acm/QuitProcessorTask.java
similarity index 100%
rename from legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/acm/QuitProcessorTask.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/acm/QuitProcessorTask.java
diff --git a/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/acm/RequestsExpirationBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/acm/RequestsExpirationBean.java
similarity index 100%
rename from legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/acm/RequestsExpirationBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/acm/RequestsExpirationBean.java
diff --git a/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/acm/RequestsExpirationTask.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/acm/RequestsExpirationTask.java
similarity index 100%
rename from legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/acm/RequestsExpirationTask.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/acm/RequestsExpirationTask.java
diff --git a/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/acm/UserSessionDAOBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/acm/UserSessionDAOBean.java
similarity index 93%
rename from legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/acm/UserSessionDAOBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/acm/UserSessionDAOBean.java
index c6cb78a..cdb5fb0 100644
--- a/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/acm/UserSessionDAOBean.java
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/acm/UserSessionDAOBean.java
@@ -11,8 +11,8 @@ import javax.sql.DataSource;
 import org.springframework.beans.factory.InitializingBean;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.dao.EmptyResultDataAccessException;
-import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.jdbc.core.RowMapper;
+import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
 
 import com.deepclone.lw.cmd.admin.users.SessionTerminationType;
 import com.deepclone.lw.cmd.admin.users.UserSession;
@@ -25,7 +25,7 @@ public class UserSessionDAOBean
 		implements UserSessionDAO , InitializingBean
 {
 
-	private JdbcTemplate dTemplate;
+	private SimpleJdbcTemplate dTemplate;
 
 	private final RowMapper< UserSession > mSession;
 
@@ -66,7 +66,7 @@ public class UserSessionDAOBean
 	@Autowired( required = true )
 	public void setDataSource( DataSource dataSource )
 	{
-		this.dTemplate = new JdbcTemplate( dataSource );
+		this.dTemplate = new SimpleJdbcTemplate( dataSource );
 
 		this.fSessionStart = new StoredProc( dataSource , "users" , "sessions_login" );
 		this.fSessionStart.addParameter( "credentials_id" , Types.INTEGER );
@@ -84,7 +84,7 @@ public class UserSessionDAOBean
 	@Override
 	public void afterPropertiesSet( )
 	{
-		this.dTemplate.execute( "SELECT users.sessions_server_restart()" );
+		this.dTemplate.getJdbcOperations( ).execute( "SELECT users.sessions_server_restart()" );
 	}
 
 
diff --git a/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/acm/UsersDAOBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/acm/UsersDAOBean.java
similarity index 97%
rename from legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/acm/UsersDAOBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/acm/UsersDAOBean.java
index 730a946..7e5d421 100644
--- a/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/acm/UsersDAOBean.java
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/acm/UsersDAOBean.java
@@ -11,8 +11,8 @@ import javax.sql.DataSource;
 
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.dao.EmptyResultDataAccessException;
-import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.jdbc.core.RowMapper;
+import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
 
 import com.deepclone.lw.cmd.admin.users.AccountBanEntry;
 import com.deepclone.lw.cmd.admin.users.AccountListEntry;
@@ -55,7 +55,7 @@ public class UsersDAOBean
 	private final AccountListMapper< AccountListEntry > mAccountList;
 	private final AccountListMapper< AccountViewEntry > mAccountView;
 
-	private JdbcTemplate dTemplate;
+	private SimpleJdbcTemplate dTemplate;
 
 	private StoredProc fCreateAccount;
 	private StoredProc fMailFailure;
@@ -181,7 +181,7 @@ public class UsersDAOBean
 	@Autowired( required = true )
 	public void setDataSource( DataSource dataSource )
 	{
-		this.dTemplate = new JdbcTemplate( dataSource );
+		this.dTemplate = new SimpleJdbcTemplate( dataSource );
 
 		this.fCreateAccount = new StoredProc( dataSource , "users" , "create_credentials" );
 		this.fCreateAccount.addParameter( "address" , Types.VARCHAR );
@@ -426,7 +426,7 @@ public class UsersDAOBean
 	@Override
 	public void expireRequests( )
 	{
-		this.dTemplate.execute( "SELECT users.expire_requests( )" );
+		this.dTemplate.getJdbcOperations( ).execute( "SELECT users.expire_requests( )" );
 	}
 
 
@@ -469,7 +469,7 @@ public class UsersDAOBean
 	@Override
 	public void processVacations( )
 	{
-		this.dTemplate.execute( "SELECT users.process_vacations( )" );
+		this.dTemplate.getJdbcOperations( ).execute( "SELECT users.process_vacations( )" );
 	}
 
 
@@ -529,7 +529,7 @@ public class UsersDAOBean
 	@Override
 	public void deleteOldAccounts( )
 	{
-		this.dTemplate.execute( "SELECT users.delete_old_accounts( )" );
+		this.dTemplate.getJdbcOperations( ).execute( "SELECT users.delete_old_accounts( )" );
 	}
 
 
diff --git a/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/acm/VacationProcessorBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/acm/VacationProcessorBean.java
similarity index 100%
rename from legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/acm/VacationProcessorBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/acm/VacationProcessorBean.java
diff --git a/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/acm/VacationProcessorTask.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/acm/VacationProcessorTask.java
similarity index 100%
rename from legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/acm/VacationProcessorTask.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/acm/VacationProcessorTask.java
diff --git a/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/admin/AdminDAOBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/admin/AdminDAOBean.java
similarity index 97%
rename from legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/admin/AdminDAOBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/admin/AdminDAOBean.java
index 12f4b06..84a3a7a 100644
--- a/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/admin/AdminDAOBean.java
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/admin/AdminDAOBean.java
@@ -13,8 +13,8 @@ import javax.sql.DataSource;
 
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.dao.EmptyResultDataAccessException;
-import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.jdbc.core.RowMapper;
+import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
 
 import com.deepclone.lw.cmd.admin.adata.AdminOverview;
 import com.deepclone.lw.interfaces.admin.AdminDAO;
@@ -34,7 +34,7 @@ public class AdminDAOBean
 	private static final String sGetAdminByName = "SELECT * FROM admin.admins_view WHERE lower( name ) = ?";
 	private static final String sListAdministrators = "SELECT * FROM admin.admins_view ORDER BY active DESC , name";
 
-	private JdbcTemplate dTemplate;
+	private SimpleJdbcTemplate dTemplate;
 
 	private final RowMapper< AdminRecord > mAdminRecord;
 	private final RowMapper< AdminOverview > mAdminOverview;
@@ -89,7 +89,7 @@ public class AdminDAOBean
 	@Autowired( required = true )
 	public void setDataSource( DataSource dataSource )
 	{
-		this.dTemplate = new JdbcTemplate( dataSource );
+		this.dTemplate = new SimpleJdbcTemplate( dataSource );
 
 		this.fCreateAdmin = new StoredProc( dataSource , "admin" , "create_admin" );
 		this.fCreateAdmin.addParameter( "address" , Types.VARCHAR );
diff --git a/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/admin/AdminRecapBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/admin/AdminRecapBean.java
similarity index 100%
rename from legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/admin/AdminRecapBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/admin/AdminRecapBean.java
diff --git a/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/admin/AdminRecapTask.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/admin/AdminRecapTask.java
similarity index 100%
rename from legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/admin/AdminRecapTask.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/admin/AdminRecapTask.java
diff --git a/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/admin/AdministrationBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/admin/AdministrationBean.java
similarity index 100%
rename from legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/admin/AdministrationBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/admin/AdministrationBean.java
diff --git a/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/admin/BansDAOBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/admin/BansDAOBean.java
similarity index 96%
rename from legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/admin/BansDAOBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/admin/BansDAOBean.java
index 52b6653..ec5f1a9 100644
--- a/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/admin/BansDAOBean.java
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/admin/BansDAOBean.java
@@ -12,8 +12,8 @@ import javax.sql.DataSource;
 
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.dao.EmptyResultDataAccessException;
-import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.jdbc.core.RowMapper;
+import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
 
 import com.deepclone.lw.cmd.admin.bans.ArchivedBanRequest;
 import com.deepclone.lw.cmd.admin.bans.BanRequest;
@@ -51,7 +51,7 @@ public class BansDAOBean
 		}
 	}
 
-	private JdbcTemplate dTemplate;
+	private SimpleJdbcTemplate dTemplate;
 
 	private final BanRequestMapper< BanRequest > mPending;
 	private final BanRequestMapper< BanRequest > mArchived;
@@ -122,7 +122,7 @@ public class BansDAOBean
 	@Autowired( required = true )
 	public void setDataSource( DataSource dataSource )
 	{
-		this.dTemplate = new JdbcTemplate( dataSource );
+		this.dTemplate = new SimpleJdbcTemplate( dataSource );
 
 		this.fRequestBanAddress = new StoredProc( dataSource , "admin" , "request_ban_on_address" );
 		this.fRequestBanAddress.addParameter( "admin_id" , Types.INTEGER );
@@ -251,14 +251,14 @@ public class BansDAOBean
 	@Override
 	public void expireBanRequests( )
 	{
-		this.dTemplate.execute( "SELECT admin.expire_ban_requests( )" );
+		this.dTemplate.getJdbcOperations( ).execute( "SELECT admin.expire_ban_requests( )" );
 	}
 
 
 	@Override
 	public void expireWarnings( )
 	{
-		this.dTemplate.execute( "SELECT admin.expire_warnings( )" );
+		this.dTemplate.getJdbcOperations( ).execute( "SELECT admin.expire_warnings( )" );
 	}
 
 
diff --git a/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/admin/BansProcessorBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/admin/BansProcessorBean.java
similarity index 100%
rename from legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/admin/BansProcessorBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/admin/BansProcessorBean.java
diff --git a/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/admin/BansProcessorTask.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/admin/BansProcessorTask.java
similarity index 100%
rename from legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/admin/BansProcessorTask.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/admin/BansProcessorTask.java
diff --git a/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/admin/IpBanBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/admin/IpBanBean.java
similarity index 100%
rename from legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/admin/IpBanBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/admin/IpBanBean.java
diff --git a/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/prefs/BoolPreferenceType.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/prefs/BoolPreferenceType.java
similarity index 100%
rename from legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/prefs/BoolPreferenceType.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/prefs/BoolPreferenceType.java
diff --git a/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/prefs/DefaultPreferencesBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/prefs/DefaultPreferencesBean.java
similarity index 100%
rename from legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/prefs/DefaultPreferencesBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/prefs/DefaultPreferencesBean.java
diff --git a/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/prefs/EnumPreferenceType.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/prefs/EnumPreferenceType.java
similarity index 100%
rename from legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/prefs/EnumPreferenceType.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/prefs/EnumPreferenceType.java
diff --git a/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/prefs/IntPreferenceType.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/prefs/IntPreferenceType.java
similarity index 100%
rename from legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/prefs/IntPreferenceType.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/prefs/IntPreferenceType.java
diff --git a/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/prefs/PreferenceDefinitionsBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/prefs/PreferenceDefinitionsBean.java
similarity index 98%
rename from legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/prefs/PreferenceDefinitionsBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/prefs/PreferenceDefinitionsBean.java
index ba69780..05a1603 100644
--- a/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/prefs/PreferenceDefinitionsBean.java
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/prefs/PreferenceDefinitionsBean.java
@@ -12,8 +12,8 @@ import javax.sql.DataSource;
 
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.dao.EmptyResultDataAccessException;
-import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.jdbc.core.RowMapper;
+import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
 import org.springframework.transaction.PlatformTransactionManager;
 import org.springframework.transaction.TransactionStatus;
 import org.springframework.transaction.annotation.Transactional;
@@ -70,7 +70,7 @@ public class PreferenceDefinitionsBean
 	private SystemLogger logger;
 	private Translator translator;
 
-	private JdbcTemplate dTemplate;
+	private SimpleJdbcTemplate dTemplate;
 
 	private StoredProc uocGroup;
 	private StoredProc uocDef;
@@ -95,7 +95,7 @@ public class PreferenceDefinitionsBean
 	@Autowired( required = true )
 	public void setDataSource( DataSource dataSource )
 	{
-		this.dTemplate = new JdbcTemplate( dataSource );
+		this.dTemplate = new SimpleJdbcTemplate( dataSource );
 
 		this.uocGroup = new StoredProc( dataSource , "defs" , "uoc_preference_group" );
 		this.uocGroup.addParameter( "name" , Types.VARCHAR );
diff --git a/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/prefs/PreferenceTypeImpl.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/prefs/PreferenceTypeImpl.java
similarity index 100%
rename from legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/prefs/PreferenceTypeImpl.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/prefs/PreferenceTypeImpl.java
diff --git a/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/prefs/PreferenceTypesRegistryBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/prefs/PreferenceTypesRegistryBean.java
similarity index 100%
rename from legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/prefs/PreferenceTypesRegistryBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/prefs/PreferenceTypesRegistryBean.java
diff --git a/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/prefs/PreferencesDAOBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/prefs/PreferencesDAOBean.java
similarity index 96%
rename from legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/prefs/PreferencesDAOBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/prefs/PreferencesDAOBean.java
index b955ffa..6387587 100644
--- a/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/prefs/PreferencesDAOBean.java
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/prefs/PreferencesDAOBean.java
@@ -12,8 +12,8 @@ import java.util.Map;
 import javax.sql.DataSource;
 
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.jdbc.core.RowMapper;
+import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
 
 import com.deepclone.lw.interfaces.prefs.AccountPreferences;
 import com.deepclone.lw.interfaces.prefs.Preference;
@@ -30,7 +30,7 @@ public class PreferencesDAOBean
 		implements PreferencesDAO
 {
 
-	private JdbcTemplate dTemplate;
+	private SimpleJdbcTemplate dTemplate;
 	private PreferenceTypesRegistry registry;
 	private StoredProc fReset;
 	private StoredProc fSetPref;
@@ -39,7 +39,7 @@ public class PreferencesDAOBean
 	@Autowired( required = true )
 	public void setDataSource( DataSource dataSource )
 	{
-		this.dTemplate = new JdbcTemplate( dataSource );
+		this.dTemplate = new SimpleJdbcTemplate( dataSource );
 
 		this.fReset = new StoredProc( dataSource , "users" , "reset_preferences" );
 		this.fReset.addParameter( "a_id" , Types.INTEGER );
diff --git a/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/prefs/StringPreferenceType.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/prefs/StringPreferenceType.java
similarity index 100%
rename from legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/prefs/StringPreferenceType.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/java/com/deepclone/lw/beans/prefs/StringPreferenceType.java
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/resources/configuration/accounts-beans.xml b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/resources/configuration/accounts-beans.xml
new file mode 100644
index 0000000..bd7ec9b
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/resources/configuration/accounts-beans.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="
+                        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
+
+	<import resource="accounts/account-cleanup-bean.xml" />
+	<import resource="accounts/account-management-bean.xml" />
+	<import resource="accounts/admin-dao-bean.xml" />
+	<import resource="accounts/admin-recap-bean.xml" />
+	<import resource="accounts/administration-bean.xml" />
+	<import resource="accounts/bans-dao-bean.xml" />
+	<import resource="accounts/bans-processor-bean.xml" />
+	<import resource="accounts/default-preferences-bean.xml" />
+	<import resource="accounts/ip-ban-bean.xml" />
+	<import resource="accounts/preference-definitions-bean.xml" />
+	<import resource="accounts/preferences-dao-bean.xml" />
+	<import resource="accounts/quit-processor-bean.xml" />
+	<import resource="accounts/requests-expiration-bean.xml" />
+	<import resource="accounts/user-session-dao-bean.xml" />
+	<import resource="accounts/users-dao-bean.xml" />
+	<import resource="accounts/vacation-processor-bean.xml" />
+
+</beans>
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/resources/configuration/accounts/account-cleanup-bean.xml b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/resources/configuration/accounts/account-cleanup-bean.xml
new file mode 100644
index 0000000..e1c6a61
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/resources/configuration/accounts/account-cleanup-bean.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="
+                        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
+
+	<bean id="accountCleanup" class="com.deepclone.lw.beans.acm.AccountCleanupBean" />
+
+</beans>
diff --git a/legacyworlds-server-beans-user/src/main/resources/configuration/session-types.xml b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/resources/configuration/accounts/account-management-bean.xml
similarity index 65%
rename from legacyworlds-server-beans-user/src/main/resources/configuration/session-types.xml
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/resources/configuration/accounts/account-management-bean.xml
index e52899d..6062c6a 100644
--- a/legacyworlds-server-beans-user/src/main/resources/configuration/session-types.xml
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/resources/configuration/accounts/account-management-bean.xml
@@ -4,8 +4,6 @@
 	xsi:schemaLocation="
                         http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
 
-	<import resource="session-types/administration.xml" />
-	<import resource="session-types/external.xml" />
-	<import resource="session-types/player.xml" />
+	<bean id="accountManagement" class="com.deepclone.lw.beans.acm.AccountManagementBean" />
 
-</beans>
\ No newline at end of file
+</beans>
diff --git a/legacyworlds-server-beans-events/src/main/resources/configuration/game/events.xml b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/resources/configuration/accounts/admin-dao-bean.xml
similarity index 60%
rename from legacyworlds-server-beans-events/src/main/resources/configuration/game/events.xml
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/resources/configuration/accounts/admin-dao-bean.xml
index bf70490..8640f69 100644
--- a/legacyworlds-server-beans-events/src/main/resources/configuration/game/events.xml
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/resources/configuration/accounts/admin-dao-bean.xml
@@ -2,8 +2,8 @@
 <beans xmlns="http://www.springframework.org/schema/beans"
 	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 	xsi:schemaLocation="
-                        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
+                        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
 
-	<bean id="eventProcessor" class="com.deepclone.lw.beans.events.EventProcessorBean" />
+	<bean id="adminDao" class="com.deepclone.lw.beans.admin.AdminDAOBean" />
 
-</beans>
\ No newline at end of file
+</beans>
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/resources/configuration/accounts/admin-recap-bean.xml b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/resources/configuration/accounts/admin-recap-bean.xml
new file mode 100644
index 0000000..4d609ab
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/resources/configuration/accounts/admin-recap-bean.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="
+                        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
+
+	<bean id="adminRecap" class="com.deepclone.lw.beans.admin.AdminRecapBean" />
+
+</beans>
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/resources/configuration/accounts/administration-bean.xml b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/resources/configuration/accounts/administration-bean.xml
new file mode 100644
index 0000000..1039d63
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/resources/configuration/accounts/administration-bean.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="
+                        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
+
+	<bean id="administration" class="com.deepclone.lw.beans.admin.AdministrationBean" />
+
+</beans>
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/resources/configuration/accounts/bans-dao-bean.xml b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/resources/configuration/accounts/bans-dao-bean.xml
new file mode 100644
index 0000000..f654c86
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/resources/configuration/accounts/bans-dao-bean.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="
+                        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
+
+	<bean id="bansDao" class="com.deepclone.lw.beans.admin.BansDAOBean" />
+
+</beans>
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/resources/configuration/accounts/bans-processor-bean.xml b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/resources/configuration/accounts/bans-processor-bean.xml
new file mode 100644
index 0000000..4167e63
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/resources/configuration/accounts/bans-processor-bean.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="
+                        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
+
+	<bean id="bansProcessor" class="com.deepclone.lw.beans.admin.BansProcessorBean" />
+
+</beans>
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/resources/configuration/accounts/default-preferences-bean.xml b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/resources/configuration/accounts/default-preferences-bean.xml
new file mode 100644
index 0000000..e7bca93
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/resources/configuration/accounts/default-preferences-bean.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="
+                        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
+
+	<bean id="defaultPreferences" class="com.deepclone.lw.beans.prefs.DefaultPreferencesBean" />
+
+</beans>
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/resources/configuration/accounts/ip-ban-bean.xml b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/resources/configuration/accounts/ip-ban-bean.xml
new file mode 100644
index 0000000..2c70cf8
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/resources/configuration/accounts/ip-ban-bean.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="
+                        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
+
+	<bean id="ipBan" class="com.deepclone.lw.beans.admin.IpBanBean" />
+
+</beans>
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/resources/configuration/accounts/preference-definitions-bean.xml b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/resources/configuration/accounts/preference-definitions-bean.xml
new file mode 100644
index 0000000..73dfc57
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/resources/configuration/accounts/preference-definitions-bean.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="
+                        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
+
+	<bean id="preferenceDefinitions" class="com.deepclone.lw.beans.prefs.PreferenceDefinitionsBean" />
+	<bean id="preferenceTypesRegistry" class="com.deepclone.lw.beans.prefs.PreferenceTypesRegistryBean" />
+
+</beans>
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/resources/configuration/accounts/preferences-dao-bean.xml b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/resources/configuration/accounts/preferences-dao-bean.xml
new file mode 100644
index 0000000..42926c3
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/resources/configuration/accounts/preferences-dao-bean.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="
+                        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
+
+	<bean id="preferencesDAO" class="com.deepclone.lw.beans.prefs.PreferencesDAOBean" />
+
+</beans>
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/resources/configuration/accounts/quit-processor-bean.xml b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/resources/configuration/accounts/quit-processor-bean.xml
new file mode 100644
index 0000000..a571d09
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/resources/configuration/accounts/quit-processor-bean.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="
+                        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
+
+	<bean id="quitProcessor" class="com.deepclone.lw.beans.acm.QuitProcessorBean" />
+
+</beans>
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/resources/configuration/accounts/requests-expiration-bean.xml b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/resources/configuration/accounts/requests-expiration-bean.xml
new file mode 100644
index 0000000..f4525e4
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/resources/configuration/accounts/requests-expiration-bean.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="
+                        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
+
+	<bean id="requestsExpiration" class="com.deepclone.lw.beans.acm.RequestsExpirationBean" />
+
+</beans>
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/resources/configuration/accounts/user-session-dao-bean.xml b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/resources/configuration/accounts/user-session-dao-bean.xml
new file mode 100644
index 0000000..0c7e785
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/resources/configuration/accounts/user-session-dao-bean.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="
+                        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
+
+	<bean id="userSessionDao" class="com.deepclone.lw.beans.acm.UserSessionDAOBean" />
+
+</beans>
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/resources/configuration/accounts/users-dao-bean.xml b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/resources/configuration/accounts/users-dao-bean.xml
new file mode 100644
index 0000000..817940f
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/resources/configuration/accounts/users-dao-bean.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="
+                        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
+
+	<bean id="usersDAO" class="com.deepclone.lw.beans.acm.UsersDAOBean" />
+
+</beans>
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/resources/configuration/accounts/vacation-processor-bean.xml b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/resources/configuration/accounts/vacation-processor-bean.xml
new file mode 100644
index 0000000..2c67fea
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-accounts/src/main/resources/configuration/accounts/vacation-processor-bean.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="
+                        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
+
+	<bean id="vacationProcessor" class="com.deepclone.lw.beans.acm.VacationProcessorBean" />
+
+</beans>
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-bt/.classpath b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-bt/.classpath
new file mode 100644
index 0000000..7c3d14f
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-bt/.classpath
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" output="target/classes" path="src/main/java"/>
+	<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources"/>
+	<classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
+	<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+	<classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER"/>
+	<classpathentry kind="output" path="target/classes"/>
+</classpath>
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-bt/.project b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-bt/.project
new file mode 100644
index 0000000..6701380
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-bt/.project
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>legacyworlds-server-beans-bt</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.maven.ide.eclipse.maven2Builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.maven.ide.eclipse.maven2Nature</nature>
+	</natures>
+</projectDescription>
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-bt/.settings/org.eclipse.jdt.core.prefs b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-bt/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..1e525bc
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-bt/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,6 @@
+#Tue Apr 13 08:30:06 CEST 2010
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.6
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-bt/.settings/org.maven.ide.eclipse.prefs b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-bt/.settings/org.maven.ide.eclipse.prefs
new file mode 100644
index 0000000..12bb0a0
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-bt/.settings/org.maven.ide.eclipse.prefs
@@ -0,0 +1,9 @@
+#Tue Apr 13 08:30:04 CEST 2010
+activeProfiles=
+eclipse.preferences.version=1
+fullBuildGoals=process-test-resources
+includeModules=false
+resolveWorkspaceProjects=true
+resourceFilterGoals=process-resources resources\:testResources
+skipCompilerPlugin=true
+version=1
diff --git a/legacyworlds-server-beans-bt/pom.xml b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-bt/pom.xml
similarity index 58%
rename from legacyworlds-server-beans-bt/pom.xml
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-bt/pom.xml
index 152da94..80a4b6e 100644
--- a/legacyworlds-server-beans-bt/pom.xml
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-bt/pom.xml
@@ -4,8 +4,7 @@
 	<parent>
 		<artifactId>legacyworlds-server-beans</artifactId>
 		<groupId>com.deepclone.lw</groupId>
-		<version>1.0.0</version>
-		<relativePath>../legacyworlds-server-beans/pom.xml</relativePath>
+		<version>5.99.2</version>
 	</parent>
 
 	<dependencies>
@@ -13,16 +12,14 @@
 		<dependency>
 			<groupId>com.thoughtworks.xstream</groupId>
 			<artifactId>xstream</artifactId>
-		</dependency>
-
-		<dependency>
-			<groupId>postgresql</groupId>
-			<artifactId>postgresql</artifactId>
+			<version>${com.thoughtworks.xstream.version}</version>
+			<type>jar</type>
 		</dependency>
 
 	</dependencies>
 
+	<groupId>com.deepclone.lw</groupId>
 	<artifactId>legacyworlds-server-beans-bt</artifactId>
-	<name>Legacy Worlds - Server - Components - Bug tracking system</name>
-	<version>${legacyworlds.version.main}.${legacyworlds.version.release}-${legacyworlds.version.build}</version>
-</project>
+	<version>5.99.2</version>
+	<name>Legacy Worlds bug tracking system</name>
+</project>
\ No newline at end of file
diff --git a/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/AdminBugsBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/AdminBugsBean.java
similarity index 100%
rename from legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/AdminBugsBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/AdminBugsBean.java
diff --git a/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/BugsDAOBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/BugsDAOBean.java
similarity index 98%
rename from legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/BugsDAOBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/BugsDAOBean.java
index 6483a57..8f5c37e 100644
--- a/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/BugsDAOBean.java
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/BugsDAOBean.java
@@ -11,8 +11,9 @@ import javax.sql.DataSource;
 
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.dao.EmptyResultDataAccessException;
-import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.jdbc.core.RowMapper;
+import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
+
 import com.deepclone.lw.cmd.admin.adata.Administrator;
 import com.deepclone.lw.cmd.bt.data.*;
 import com.deepclone.lw.interfaces.bt.BugsDAO;
@@ -24,7 +25,7 @@ public class BugsDAOBean
 		implements BugsDAO
 {
 
-	private JdbcTemplate dTemplate;
+	private SimpleJdbcTemplate dTemplate;
 
 	private final RowMapper< BugReport > mBugReport;
 	private final RowMapper< BugEvent > mBugEvent;
@@ -128,7 +129,7 @@ public class BugsDAOBean
 	@Autowired( required = true )
 	public void setDataSource( DataSource dataSource )
 	{
-		this.dTemplate = new JdbcTemplate( dataSource );
+		this.dTemplate = new SimpleJdbcTemplate( dataSource );
 
 		this.fPostUserReport = new StoredProc( dataSource , "bugs" , "post_player_report" );
 		this.fPostUserReport.addParameter( "empire_id" , Types.INTEGER );
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/EmpireSummaryBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/EmpireSummaryBean.java
new file mode 100644
index 0000000..a6823f7
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/EmpireSummaryBean.java
@@ -0,0 +1,253 @@
+package com.deepclone.lw.beans.bt;
+
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.sql.DataSource;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.jdbc.core.RowMapper;
+import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
+
+import com.deepclone.lw.beans.bt.esdata.*;
+import com.deepclone.lw.interfaces.bt.EmpireSummary;
+import com.thoughtworks.xstream.XStream;
+
+
+
+public class EmpireSummaryBean
+		implements EmpireSummary
+{
+
+	private SimpleJdbcTemplate dTemplate;
+
+	private final XStream xStream;
+
+	private final RowMapper< DebugInformation > mMainInfo;
+	private final RowMapper< ResearchInformation > mResearch;
+	private final RowMapper< TechnologyInformation > mTechnology;
+	private final RowMapper< PlanetInformation > mPlanet;
+	private final RowMapper< QueueItemInformation > mQueueItem;
+	private final RowMapper< BuildingsInformation > mBuildings;
+	private final RowMapper< FleetInformation > mFleet;
+	private final RowMapper< ShipsInformation > mShips;
+
+
+	public EmpireSummaryBean( )
+	{
+		this.xStream = new XStream( );
+		this.xStream.processAnnotations( new Class< ? >[] {
+				AccountInformation.class , AllianceInformation.class , BuildingsInformation.class ,
+				DebugInformation.class , EmpireInformation.class , FleetInformation.class , MovementInformation.class ,
+				PlanetInformation.class , QueueInformation.class , QueueItemInformation.class ,
+				ResearchInformation.class , TechnologyInformation.class , ShipsInformation.class ,
+				SystemInformation.class
+		} );
+
+		this.mMainInfo = new RowMapper< DebugInformation >( ) {
+			@Override
+			public DebugInformation mapRow( ResultSet rs , int rowNum )
+					throws SQLException
+			{
+				DebugInformation di = new DebugInformation( );
+
+				di.getSystem( ).setNextTick( rs.getLong( "next_tick" ) );
+				di.getSystem( ).setCurrentTick( (Long) rs.getObject( "current_tick" ) );
+
+				di.getAccount( ).setId( rs.getInt( "account_id" ) );
+				di.getAccount( ).setAddress( rs.getString( "account_address" ) );
+				di.getAccount( ).setGameCredits( rs.getInt( "game_credits" ) );
+				di.getAccount( ).setStatus( rs.getString( "account_status" ) );
+				di.getAccount( ).setLanguage( rs.getString( "account_language" ) );
+
+				di.getEmpire( ).setId( rs.getInt( "empire_id" ) );
+				di.getEmpire( ).setName( rs.getString( "empire_name" ) );
+				di.getEmpire( ).setCash( rs.getDouble( "cash" ) );
+
+				String allianceTag = rs.getString( "alliance_tag" );
+				if ( allianceTag != null ) {
+					AllianceInformation alliance = new AllianceInformation( );
+					alliance.setId( rs.getInt( "alliance_id" ) );
+					alliance.setTag( allianceTag );
+					alliance.setPending( rs.getBoolean( "alliance_pending" ) );
+					di.getEmpire( ).setAlliance( alliance );
+				}
+
+				return di;
+			}
+		};
+		this.mResearch = new RowMapper< ResearchInformation >( ) {
+			@Override
+			public ResearchInformation mapRow( ResultSet rs , int rowNum )
+					throws SQLException
+			{
+				ResearchInformation ri = new ResearchInformation( );
+				ri.setName( rs.getString( "name" ) );
+				ri.setAccumulated( rs.getDouble( "accumulated" ) );
+				ri.setPriority( rs.getInt( "priority" ) );
+				return ri;
+			}
+		};
+		this.mTechnology = new RowMapper< TechnologyInformation >( ) {
+			@Override
+			public TechnologyInformation mapRow( ResultSet rs , int rowNum )
+					throws SQLException
+			{
+				TechnologyInformation ti = new TechnologyInformation( );
+				ti.setName( rs.getString( "name" ) );
+				ti.setImplemented( rs.getBoolean( "implemented" ) );
+				return ti;
+			}
+		};
+		this.mPlanet = new RowMapper< PlanetInformation >( ) {
+			@Override
+			public PlanetInformation mapRow( ResultSet rs , int rowNum )
+					throws SQLException
+			{
+				PlanetInformation pi = new PlanetInformation( );
+				pi.setId( rs.getInt( "planet_id" ) );
+				pi.setPopulation( rs.getDouble( "population" ) );
+				pi.setCurrentHappiness( rs.getDouble( "current_happiness" ) );
+				pi.setTargetHappiness( rs.getDouble( "target_happiness" ) );
+				pi.getCivilianQueue( ).setAccMoney( rs.getDouble( "civ_money" ) );
+				pi.getCivilianQueue( ).setAccWork( rs.getDouble( "civ_work" ) );
+				pi.getMilitaryQueue( ).setAccMoney( rs.getDouble( "mil_money" ) );
+				pi.getMilitaryQueue( ).setAccWork( rs.getDouble( "mil_work" ) );
+				return pi;
+			}
+		};
+		this.mQueueItem = new RowMapper< QueueItemInformation >( ) {
+			@Override
+			public QueueItemInformation mapRow( ResultSet rs , int rowNum )
+					throws SQLException
+			{
+				QueueItemInformation qii = new QueueItemInformation( );
+				qii.setPlanetId( rs.getInt( "planet_id" ) );
+				qii.setMilitary( rs.getBoolean( "military" ) );
+				qii.setId( rs.getInt( "item_id" ) );
+				qii.setName( rs.getString( "item_name" ) );
+				qii.setDestroy( rs.getBoolean( "destroy" ) );
+				qii.setAmount( rs.getInt( "amount" ) );
+				return qii;
+			}
+		};
+		this.mBuildings = new RowMapper< BuildingsInformation >( ) {
+			@Override
+			public BuildingsInformation mapRow( ResultSet rs , int rowNum )
+					throws SQLException
+			{
+				BuildingsInformation bi = new BuildingsInformation( );
+				bi.setPlanetId( rs.getInt( "planet_id" ) );
+				bi.setId( rs.getInt( "building_id" ) );
+				bi.setName( rs.getString( "building_name" ) );
+				bi.setAmount( rs.getInt( "amount" ) );
+				bi.setDamage( rs.getDouble( "damage" ) );
+				return bi;
+			}
+		};
+		this.mFleet = new RowMapper< FleetInformation >( ) {
+			@Override
+			public FleetInformation mapRow( ResultSet rs , int rowNum )
+					throws SQLException
+			{
+				FleetInformation fi = new FleetInformation( );
+				fi.setId( rs.getLong( "fleet_id" ) );
+				fi.setName( rs.getString( "fleet_name" ) );
+				fi.setStatus( rs.getString( "status" ) );
+				fi.setAttacking( rs.getBoolean( "attacking" ) );
+				fi.setLocationId( rs.getInt( "location_id" ) );
+				fi.setLocationName( rs.getString( "location_name" ) );
+
+				Integer sourceId = (Integer) rs.getObject( "source_id" );
+				if ( sourceId != null ) {
+					MovementInformation mi = new MovementInformation( );
+					mi.setSourceId( sourceId );
+					mi.setSourceName( rs.getString( "source_name" ) );
+					mi.setTimeLeft( rs.getInt( "time_left" ) );
+					mi.setStateTimeLeft( rs.getInt( "state_time_left" ) );
+					mi.setNearId( (Integer) rs.getObject( "ref_point_id" ) );
+					mi.setNearName( rs.getString( "ref_point_name" ) );
+					mi.setOutwards( (Boolean) rs.getObject( "outwards" ) );
+					mi.setPastRefPoint( (Boolean) rs.getObject( "past_ref_point" ) );
+					mi.setStartX( (Float) rs.getObject( "start_x" ) );
+					mi.setStartY( (Float) rs.getObject( "start_y" ) );
+					fi.setMovement( mi );
+				}
+
+				return fi;
+			}
+		};
+		this.mShips = new RowMapper< ShipsInformation >( ) {
+			@Override
+			public ShipsInformation mapRow( ResultSet rs , int rowNum )
+					throws SQLException
+			{
+				ShipsInformation si = new ShipsInformation( );
+				si.setFleetId( rs.getLong( "fleet_id" ) );
+				si.setId( rs.getInt( "ship_id" ) );
+				si.setName( rs.getString( "ship_name" ) );
+				si.setAmount( rs.getInt( "amount" ) );
+				si.setDamage( rs.getDouble( "damage" ) );
+				return si;
+			}
+		};
+	}
+
+
+	@Autowired( required = true )
+	public void setDataSource( DataSource dataSource )
+	{
+		this.dTemplate = new SimpleJdbcTemplate( dataSource );
+	}
+
+
+	@Override
+	public String getSummary( int empireId )
+	{
+		String sql = "SELECT * FROM bugs.dump_main_view WHERE empire_id = ?";
+		DebugInformation di = this.dTemplate.queryForObject( sql , this.mMainInfo , empireId );
+
+		sql = "SELECT * FROM bugs.dump_research_view WHERE empire_id = ?";
+		di.getResearch( ).addAll( this.dTemplate.query( sql , this.mResearch , empireId ) );
+
+		sql = "SELECT * FROM bugs.dump_technologies_view WHERE empire_id = ?";
+		di.getTechnologies( ).addAll( this.dTemplate.query( sql , this.mTechnology , empireId ) );
+
+		sql = "SELECT * FROM bugs.dump_planets_view WHERE empire_id = ?";
+		Map< Integer , PlanetInformation > planets = new HashMap< Integer , PlanetInformation >( );
+		for ( PlanetInformation pi : this.dTemplate.query( sql , this.mPlanet , empireId ) ) {
+			di.getPlanets( ).add( pi );
+			planets.put( pi.getId( ) , pi );
+		}
+
+		sql = "SELECT * FROM bugs.dump_queues_view WHERE empire_id = ? ORDER BY queue_order";
+		for ( QueueItemInformation qii : this.dTemplate.query( sql , this.mQueueItem , empireId ) ) {
+			PlanetInformation pi = planets.get( qii.getPlanetId( ) );
+			QueueInformation qi = ( qii.isMilitary( ) ? pi.getMilitaryQueue( ) : pi.getCivilianQueue( ) );
+			qi.getItems( ).add( qii );
+		}
+
+		sql = "SELECT * FROM bugs.dump_buildings_view WHERE empire_id = ?";
+		for ( BuildingsInformation bi : this.dTemplate.query( sql , this.mBuildings , empireId ) ) {
+			planets.get( bi.getPlanetId( ) ).getBuildings( ).add( bi );
+		}
+
+		sql = "SELECT * FROM bugs.dump_fleets_view WHERE empire_id = ?";
+		Map< Long , FleetInformation > fleets = new HashMap< Long , FleetInformation >( );
+		for ( FleetInformation fi : this.dTemplate.query( sql , this.mFleet , empireId ) ) {
+			di.getFleets( ).add( fi );
+			fleets.put( fi.getId( ) , fi );
+		}
+
+		sql = "SELECT * FROM bugs.dump_ships_view WHERE empire_id = ?";
+		for ( ShipsInformation si : this.dTemplate.query( sql , this.mShips , empireId ) ) {
+			fleets.get( si.getFleetId( ) ).getShips( ).add( si );
+		}
+
+		return this.xStream.toXML( di );
+	}
+
+}
diff --git a/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/PlayerBugsBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/PlayerBugsBean.java
similarity index 100%
rename from legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/PlayerBugsBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/PlayerBugsBean.java
diff --git a/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/data/AccountInformation.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/esdata/AccountInformation.java
similarity index 96%
rename from legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/data/AccountInformation.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/esdata/AccountInformation.java
index 0fae3b3..d6496e8 100644
--- a/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/data/AccountInformation.java
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/esdata/AccountInformation.java
@@ -1,4 +1,4 @@
-package com.deepclone.lw.beans.bt.es.data;
+package com.deepclone.lw.beans.bt.esdata;
 
 
 import java.io.Serializable;
diff --git a/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/data/AllianceInformation.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/esdata/AllianceInformation.java
similarity index 95%
rename from legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/data/AllianceInformation.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/esdata/AllianceInformation.java
index 56368fb..e156b4b 100644
--- a/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/data/AllianceInformation.java
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/esdata/AllianceInformation.java
@@ -1,4 +1,4 @@
-package com.deepclone.lw.beans.bt.es.data;
+package com.deepclone.lw.beans.bt.esdata;
 
 
 import java.io.Serializable;
diff --git a/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/data/BuildingsInformation.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/esdata/BuildingsInformation.java
similarity index 96%
rename from legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/data/BuildingsInformation.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/esdata/BuildingsInformation.java
index 75416fc..61a9415 100644
--- a/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/data/BuildingsInformation.java
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/esdata/BuildingsInformation.java
@@ -1,4 +1,4 @@
-package com.deepclone.lw.beans.bt.es.data;
+package com.deepclone.lw.beans.bt.esdata;
 
 
 import java.io.Serializable;
diff --git a/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/data/DebugInformation.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/esdata/DebugInformation.java
similarity index 50%
rename from legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/data/DebugInformation.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/esdata/DebugInformation.java
index ab6c15f..2a676e0 100644
--- a/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/data/DebugInformation.java
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/esdata/DebugInformation.java
@@ -1,8 +1,8 @@
-package com.deepclone.lw.beans.bt.es.data;
+package com.deepclone.lw.beans.bt.esdata;
 
 
 import java.io.Serializable;
-import java.util.ArrayList;
+import java.util.LinkedList;
 import java.util.List;
 
 import com.thoughtworks.xstream.annotations.XStreamAlias;
@@ -15,26 +15,29 @@ public class DebugInformation
 		implements Serializable
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = 2L;
 
 	@XStreamAsAttribute
 	@XStreamAlias( "dump-version" )
-	private int version = 2;
+	private final int version = 2;
 
-	private SystemInformation system = new SystemInformation( );
+	private final SystemInformation system = new SystemInformation( );
 
-	private AccountInformation account = new AccountInformation( );
+	private final AccountInformation account = new AccountInformation( );
 
-	private EmpireInformation empire = new EmpireInformation( );
+	private final EmpireInformation empire = new EmpireInformation( );
 
 	@XStreamAlias( "research" )
-	private List< ResearchInformation > research = new ArrayList< ResearchInformation >( );
+	private final List< ResearchInformation > research = new LinkedList< ResearchInformation >( );
+
+	@XStreamAlias( "technologies" )
+	private final List< TechnologyInformation > technologies = new LinkedList< TechnologyInformation >( );
 
 	@XStreamAlias( "planets" )
-	private List< PlanetInformation > planets = new ArrayList< PlanetInformation >( );
+	private final List< PlanetInformation > planets = new LinkedList< PlanetInformation >( );
 
 	@XStreamAlias( "fleets" )
-	private List< FleetInformation > fleets = new ArrayList< FleetInformation >( );
+	private final List< FleetInformation > fleets = new LinkedList< FleetInformation >( );
 
 
 	public int getVersion( )
@@ -67,6 +70,12 @@ public class DebugInformation
 	}
 
 
+	public List< TechnologyInformation > getTechnologies( )
+	{
+		return technologies;
+	}
+
+
 	public List< PlanetInformation > getPlanets( )
 	{
 		return planets;
@@ -78,4 +87,4 @@ public class DebugInformation
 		return fleets;
 	}
 
-}
+}
\ No newline at end of file
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/esdata/EmpireInformation.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/esdata/EmpireInformation.java
new file mode 100644
index 0000000..94825fe
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/esdata/EmpireInformation.java
@@ -0,0 +1,80 @@
+package com.deepclone.lw.beans.bt.esdata;
+
+
+import java.io.Serializable;
+
+import com.thoughtworks.xstream.annotations.XStreamAlias;
+import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
+
+
+
+@XStreamAlias( "empire" )
+public class EmpireInformation
+		implements Serializable
+{
+
+	private static final long serialVersionUID = 1L;
+
+	@XStreamAsAttribute
+	@XStreamAlias( "id" )
+	private int id;
+
+	@XStreamAsAttribute
+	@XStreamAlias( "name" )
+	private String name;
+
+	@XStreamAsAttribute
+	@XStreamAlias( "cash" )
+	private double cash;
+
+	private AllianceInformation alliance;
+
+
+	public int getId( )
+	{
+		return id;
+	}
+
+
+	public void setId( int id )
+	{
+		this.id = id;
+	}
+
+
+	public String getName( )
+	{
+		return name;
+	}
+
+
+	public void setName( String name )
+	{
+		this.name = name;
+	}
+
+
+	public double getCash( )
+	{
+		return cash;
+	}
+
+
+	public void setCash( double cash )
+	{
+		this.cash = cash;
+	}
+
+
+	public AllianceInformation getAlliance( )
+	{
+		return alliance;
+	}
+
+
+	public void setAlliance( AllianceInformation alliance )
+	{
+		this.alliance = alliance;
+	}
+
+}
diff --git a/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/data/FleetInformation.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/esdata/FleetInformation.java
similarity index 97%
rename from legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/data/FleetInformation.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/esdata/FleetInformation.java
index 3030e5a..d049007 100644
--- a/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/data/FleetInformation.java
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/esdata/FleetInformation.java
@@ -1,4 +1,4 @@
-package com.deepclone.lw.beans.bt.es.data;
+package com.deepclone.lw.beans.bt.esdata;
 
 
 import java.io.Serializable;
diff --git a/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/data/MovementInformation.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/esdata/MovementInformation.java
similarity index 97%
rename from legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/data/MovementInformation.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/esdata/MovementInformation.java
index 36e9f69..b3f20a0 100644
--- a/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/data/MovementInformation.java
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/esdata/MovementInformation.java
@@ -1,4 +1,4 @@
-package com.deepclone.lw.beans.bt.es.data;
+package com.deepclone.lw.beans.bt.esdata;
 
 
 import java.io.Serializable;
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/esdata/PlanetInformation.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/esdata/PlanetInformation.java
new file mode 100644
index 0000000..e2c10a9
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/esdata/PlanetInformation.java
@@ -0,0 +1,124 @@
+package com.deepclone.lw.beans.bt.esdata;
+
+
+import java.io.Serializable;
+import java.util.LinkedList;
+import java.util.List;
+
+import com.thoughtworks.xstream.annotations.XStreamAlias;
+import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
+
+
+
+@XStreamAlias( "planet" )
+public class PlanetInformation
+		implements Serializable
+{
+
+	private static final long serialVersionUID = 1L;
+
+	@XStreamAsAttribute
+	@XStreamAlias( "id" )
+	private int id;
+
+	@XStreamAsAttribute
+	@XStreamAlias( "id" )
+	private String name;
+
+	@XStreamAlias( "population" )
+	private double population;
+
+	@XStreamAlias( "current-happiness" )
+	private double currentHappiness;
+
+	@XStreamAlias( "target-happiness" )
+	private double targetHappiness;
+
+	@XStreamAlias( "buildings" )
+	private List< BuildingsInformation > buildings = new LinkedList< BuildingsInformation >( );
+
+	@XStreamAlias( "civ-queue" )
+	private QueueInformation civilianQueue = new QueueInformation( );
+
+	@XStreamAlias( "mil-queue" )
+	private QueueInformation militaryQueue = new QueueInformation( );
+
+
+	public int getId( )
+	{
+		return id;
+	}
+
+
+	public void setId( int id )
+	{
+		this.id = id;
+	}
+
+
+	public String getName( )
+	{
+		return name;
+	}
+
+
+	public void setName( String name )
+	{
+		this.name = name;
+	}
+
+
+	public double getPopulation( )
+	{
+		return population;
+	}
+
+
+	public void setPopulation( double population )
+	{
+		this.population = population;
+	}
+
+
+	public double getCurrentHappiness( )
+	{
+		return currentHappiness;
+	}
+
+
+	public void setCurrentHappiness( double currentHappiness )
+	{
+		this.currentHappiness = currentHappiness;
+	}
+
+
+	public double getTargetHappiness( )
+	{
+		return targetHappiness;
+	}
+
+
+	public void setTargetHappiness( double targetHappiness )
+	{
+		this.targetHappiness = targetHappiness;
+	}
+
+
+	public List< BuildingsInformation > getBuildings( )
+	{
+		return buildings;
+	}
+
+
+	public QueueInformation getCivilianQueue( )
+	{
+		return civilianQueue;
+	}
+
+
+	public QueueInformation getMilitaryQueue( )
+	{
+		return militaryQueue;
+	}
+
+}
diff --git a/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/data/QueueInformation.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/esdata/QueueInformation.java
similarity index 95%
rename from legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/data/QueueInformation.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/esdata/QueueInformation.java
index a4e7401..3aacd7a 100644
--- a/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/data/QueueInformation.java
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/esdata/QueueInformation.java
@@ -1,4 +1,4 @@
-package com.deepclone.lw.beans.bt.es.data;
+package com.deepclone.lw.beans.bt.esdata;
 
 
 import java.io.Serializable;
diff --git a/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/data/QueueItemInformation.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/esdata/QueueItemInformation.java
similarity index 96%
rename from legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/data/QueueItemInformation.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/esdata/QueueItemInformation.java
index 9e432e8..a96a3d2 100644
--- a/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/data/QueueItemInformation.java
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/esdata/QueueItemInformation.java
@@ -1,4 +1,4 @@
-package com.deepclone.lw.beans.bt.es.data;
+package com.deepclone.lw.beans.bt.esdata;
 
 
 import java.io.Serializable;
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/esdata/ResearchInformation.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/esdata/ResearchInformation.java
new file mode 100644
index 0000000..ec90c4a
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/esdata/ResearchInformation.java
@@ -0,0 +1,65 @@
+package com.deepclone.lw.beans.bt.esdata;
+
+
+import java.io.Serializable;
+
+import com.thoughtworks.xstream.annotations.XStreamAlias;
+import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
+
+
+
+@XStreamAlias( "research-topic" )
+public class ResearchInformation
+		implements Serializable
+
+{
+
+	private static final long serialVersionUID = 2L;
+
+	@XStreamAsAttribute
+	private String name;
+
+	@XStreamAsAttribute
+	@XStreamAlias( "accumulated-points" )
+	private double accumulated;
+
+	@XStreamAsAttribute
+	private int priority;
+
+
+	public String getName( )
+	{
+		return name;
+	}
+
+
+	public void setName( String name )
+	{
+		this.name = name;
+	}
+
+
+	public double getAccumulated( )
+	{
+		return accumulated;
+	}
+
+
+	public void setAccumulated( double accumulated )
+	{
+		this.accumulated = accumulated;
+	}
+
+
+	public int getPriority( )
+	{
+		return priority;
+	}
+
+
+	public void setPriority( int priority )
+	{
+		this.priority = priority;
+	}
+
+}
diff --git a/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/data/ShipsInformation.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/esdata/ShipsInformation.java
similarity index 96%
rename from legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/data/ShipsInformation.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/esdata/ShipsInformation.java
index 8a7229c..047ddfd 100644
--- a/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/data/ShipsInformation.java
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/esdata/ShipsInformation.java
@@ -1,4 +1,4 @@
-package com.deepclone.lw.beans.bt.es.data;
+package com.deepclone.lw.beans.bt.esdata;
 
 
 import java.io.Serializable;
diff --git a/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/data/SystemInformation.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/esdata/SystemInformation.java
similarity index 94%
rename from legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/data/SystemInformation.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/esdata/SystemInformation.java
index 4a98a10..1d51bca 100644
--- a/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/es/data/SystemInformation.java
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/esdata/SystemInformation.java
@@ -1,4 +1,4 @@
-package com.deepclone.lw.beans.bt.es.data;
+package com.deepclone.lw.beans.bt.esdata;
 
 
 import java.io.Serializable;
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/esdata/TechnologyInformation.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/esdata/TechnologyInformation.java
new file mode 100644
index 0000000..0839378
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-bt/src/main/java/com/deepclone/lw/beans/bt/esdata/TechnologyInformation.java
@@ -0,0 +1,48 @@
+package com.deepclone.lw.beans.bt.esdata;
+
+
+import java.io.Serializable;
+
+import com.thoughtworks.xstream.annotations.XStreamAlias;
+import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
+
+
+
+@XStreamAlias( "technology" )
+public class TechnologyInformation
+		implements Serializable
+{
+
+	private static final long serialVersionUID = 1L;
+
+	@XStreamAsAttribute
+	private String name;
+
+	@XStreamAsAttribute
+	private boolean implemented;
+
+
+	public String getName( )
+	{
+		return name;
+	}
+
+
+	public void setName( String name )
+	{
+		this.name = name;
+	}
+
+
+	public boolean isImplemented( )
+	{
+		return implemented;
+	}
+
+
+	public void setImplemented( boolean implemented )
+	{
+		this.implemented = implemented;
+	}
+
+}
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-bt/src/main/resources/configuration/bt-beans.xml b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-bt/src/main/resources/configuration/bt-beans.xml
new file mode 100644
index 0000000..2673721
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-bt/src/main/resources/configuration/bt-beans.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="
+                        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
+
+	<import resource="bt/admin-bugs-bean.xml" />
+	<import resource="bt/bugs-dao-bean.xml" />
+	<import resource="bt/empire-summary-bean.xml" />
+	<import resource="bt/player-bugs-bean.xml" />
+
+</beans>
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-bt/src/main/resources/configuration/bt/admin-bugs-bean.xml b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-bt/src/main/resources/configuration/bt/admin-bugs-bean.xml
new file mode 100644
index 0000000..5ddaaca
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-bt/src/main/resources/configuration/bt/admin-bugs-bean.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="
+                        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
+
+	<bean id="adminBugs" class="com.deepclone.lw.beans.bt.AdminBugsBean" />
+
+</beans>
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-bt/src/main/resources/configuration/bt/bugs-dao-bean.xml b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-bt/src/main/resources/configuration/bt/bugs-dao-bean.xml
new file mode 100644
index 0000000..3850ac1
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-bt/src/main/resources/configuration/bt/bugs-dao-bean.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="
+                        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
+
+	<bean id="bugsDAO" class="com.deepclone.lw.beans.bt.BugsDAOBean" />
+
+</beans>
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-bt/src/main/resources/configuration/bt/empire-summary-bean.xml b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-bt/src/main/resources/configuration/bt/empire-summary-bean.xml
new file mode 100644
index 0000000..bb9f28c
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-bt/src/main/resources/configuration/bt/empire-summary-bean.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="
+                        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
+
+	<bean id="empireSummary" class="com.deepclone.lw.beans.bt.EmpireSummaryBean" />
+
+</beans>
diff --git a/legacyworlds-server-beans-bt/src/main/resources/configuration/meta/bt.xml b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-bt/src/main/resources/configuration/bt/player-bugs-bean.xml
similarity index 52%
rename from legacyworlds-server-beans-bt/src/main/resources/configuration/meta/bt.xml
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-bt/src/main/resources/configuration/bt/player-bugs-bean.xml
index d96389c..47c377f 100644
--- a/legacyworlds-server-beans-bt/src/main/resources/configuration/meta/bt.xml
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-bt/src/main/resources/configuration/bt/player-bugs-bean.xml
@@ -2,11 +2,8 @@
 <beans xmlns="http://www.springframework.org/schema/beans"
 	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 	xsi:schemaLocation="
-                        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
+                        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
 
-	<bean id="adminBugs" class="com.deepclone.lw.beans.bt.AdminBugsBean" />
-	<bean id="bugsDAO" class="com.deepclone.lw.beans.bt.BugsDAOBean" />
-	<bean id="empireSummary" class="com.deepclone.lw.beans.bt.es.EmpireSummaryBean" />
 	<bean id="playerBugs" class="com.deepclone.lw.beans.bt.PlayerBugsBean" />
 
-</beans>
\ No newline at end of file
+</beans>
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-eventlog/.classpath b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-eventlog/.classpath
new file mode 100644
index 0000000..7c3d14f
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-eventlog/.classpath
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" output="target/classes" path="src/main/java"/>
+	<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources"/>
+	<classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
+	<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+	<classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER"/>
+	<classpathentry kind="output" path="target/classes"/>
+</classpath>
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-eventlog/.project b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-eventlog/.project
new file mode 100644
index 0000000..e52eaf0
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-eventlog/.project
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>legacyworlds-server-beans-eventlog</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.maven.ide.eclipse.maven2Builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.maven.ide.eclipse.maven2Nature</nature>
+	</natures>
+</projectDescription>
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-eventlog/.settings/org.eclipse.jdt.core.prefs b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-eventlog/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..82cc298
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-eventlog/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,6 @@
+#Fri Apr 09 10:19:28 CEST 2010
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.6
diff --git a/legacyworlds-server-beans-eventlog/pom.xml b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-eventlog/pom.xml
similarity index 68%
rename from legacyworlds-server-beans-eventlog/pom.xml
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-eventlog/pom.xml
index 2c15149..939d46e 100644
--- a/legacyworlds-server-beans-eventlog/pom.xml
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-eventlog/pom.xml
@@ -4,12 +4,12 @@
 	<parent>
 		<artifactId>legacyworlds-server-beans</artifactId>
 		<groupId>com.deepclone.lw</groupId>
-		<version>1.0.0</version>
-		<relativePath>../legacyworlds-server-beans/pom.xml</relativePath>
+		<version>5.99.2</version>
 	</parent>
 
+	<groupId>com.deepclone.lw</groupId>
 	<artifactId>legacyworlds-server-beans-eventlog</artifactId>
-	<name>Legacy Worlds - Server - Components - Logging</name>
+	<version>5.99.2</version>
+	<name>Legacy Worlds event log</name>
 	<description>This package is responsible for all logging in Legacy Worlds through three different beans (system event logger, admin event logger and user event logger).</description>
-	<version>${legacyworlds.version.main}.${legacyworlds.version.release}-${legacyworlds.version.build}</version>
-</project>
+</project>
\ No newline at end of file
diff --git a/legacyworlds-server-beans-eventlog/src/main/java/com/deepclone/lw/beans/eventlog/AdminErrorMailBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-eventlog/src/main/java/com/deepclone/lw/beans/eventlog/AdminErrorMailBean.java
similarity index 100%
rename from legacyworlds-server-beans-eventlog/src/main/java/com/deepclone/lw/beans/eventlog/AdminErrorMailBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-eventlog/src/main/java/com/deepclone/lw/beans/eventlog/AdminErrorMailBean.java
diff --git a/legacyworlds-server-beans-eventlog/src/main/java/com/deepclone/lw/beans/eventlog/AdminErrorMailTask.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-eventlog/src/main/java/com/deepclone/lw/beans/eventlog/AdminErrorMailTask.java
similarity index 100%
rename from legacyworlds-server-beans-eventlog/src/main/java/com/deepclone/lw/beans/eventlog/AdminErrorMailTask.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-eventlog/src/main/java/com/deepclone/lw/beans/eventlog/AdminErrorMailTask.java
diff --git a/legacyworlds-server-beans-eventlog/src/main/java/com/deepclone/lw/beans/eventlog/EntryQueueItem.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-eventlog/src/main/java/com/deepclone/lw/beans/eventlog/EntryQueueItem.java
similarity index 100%
rename from legacyworlds-server-beans-eventlog/src/main/java/com/deepclone/lw/beans/eventlog/EntryQueueItem.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-eventlog/src/main/java/com/deepclone/lw/beans/eventlog/EntryQueueItem.java
diff --git a/legacyworlds-server-beans-eventlog/src/main/java/com/deepclone/lw/beans/eventlog/LogCleanerBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-eventlog/src/main/java/com/deepclone/lw/beans/eventlog/LogCleanerBean.java
similarity index 100%
rename from legacyworlds-server-beans-eventlog/src/main/java/com/deepclone/lw/beans/eventlog/LogCleanerBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-eventlog/src/main/java/com/deepclone/lw/beans/eventlog/LogCleanerBean.java
diff --git a/legacyworlds-server-beans-eventlog/src/main/java/com/deepclone/lw/beans/eventlog/LogCleanerTask.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-eventlog/src/main/java/com/deepclone/lw/beans/eventlog/LogCleanerTask.java
similarity index 100%
rename from legacyworlds-server-beans-eventlog/src/main/java/com/deepclone/lw/beans/eventlog/LogCleanerTask.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-eventlog/src/main/java/com/deepclone/lw/beans/eventlog/LogCleanerTask.java
diff --git a/legacyworlds-server-beans-eventlog/src/main/java/com/deepclone/lw/beans/eventlog/LogReaderBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-eventlog/src/main/java/com/deepclone/lw/beans/eventlog/LogReaderBean.java
similarity index 98%
rename from legacyworlds-server-beans-eventlog/src/main/java/com/deepclone/lw/beans/eventlog/LogReaderBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-eventlog/src/main/java/com/deepclone/lw/beans/eventlog/LogReaderBean.java
index e274a02..1476bab 100644
--- a/legacyworlds-server-beans-eventlog/src/main/java/com/deepclone/lw/beans/eventlog/LogReaderBean.java
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-eventlog/src/main/java/com/deepclone/lw/beans/eventlog/LogReaderBean.java
@@ -13,8 +13,8 @@ import javax.sql.DataSource;
 
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.dao.EmptyResultDataAccessException;
-import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.jdbc.core.RowMapper;
+import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
 import org.springframework.transaction.PlatformTransactionManager;
 import org.springframework.transaction.TransactionStatus;
 import org.springframework.transaction.support.TransactionCallback;
@@ -39,7 +39,7 @@ public class LogReaderBean
 		implements LogReader
 {
 
-	private JdbcTemplate dTemplate;
+	private SimpleJdbcTemplate dTemplate;
 	private TransactionTemplate tTemplate;
 
 	private final RowMapper< LogEntry > mLogEntry;
@@ -88,7 +88,7 @@ public class LogReaderBean
 	@Autowired( required = true )
 	public void setDataSource( DataSource dataSource )
 	{
-		this.dTemplate = new JdbcTemplate( dataSource );
+		this.dTemplate = new SimpleJdbcTemplate( dataSource );
 	}
 
 
diff --git a/legacyworlds-server-beans-eventlog/src/main/java/com/deepclone/lw/beans/eventlog/LogWriterBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-eventlog/src/main/java/com/deepclone/lw/beans/eventlog/LogWriterBean.java
similarity index 100%
rename from legacyworlds-server-beans-eventlog/src/main/java/com/deepclone/lw/beans/eventlog/LogWriterBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-eventlog/src/main/java/com/deepclone/lw/beans/eventlog/LogWriterBean.java
diff --git a/legacyworlds-server-beans-eventlog/src/main/java/com/deepclone/lw/beans/eventlog/LogWriterTask.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-eventlog/src/main/java/com/deepclone/lw/beans/eventlog/LogWriterTask.java
similarity index 100%
rename from legacyworlds-server-beans-eventlog/src/main/java/com/deepclone/lw/beans/eventlog/LogWriterTask.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-eventlog/src/main/java/com/deepclone/lw/beans/eventlog/LogWriterTask.java
diff --git a/legacyworlds-server-beans-eventlog/src/main/java/com/deepclone/lw/beans/eventlog/LoggerBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-eventlog/src/main/java/com/deepclone/lw/beans/eventlog/LoggerBean.java
similarity index 100%
rename from legacyworlds-server-beans-eventlog/src/main/java/com/deepclone/lw/beans/eventlog/LoggerBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-eventlog/src/main/java/com/deepclone/lw/beans/eventlog/LoggerBean.java
diff --git a/legacyworlds-server-beans-eventlog/src/main/java/com/deepclone/lw/beans/eventlog/SystemLoggerImpl.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-eventlog/src/main/java/com/deepclone/lw/beans/eventlog/SystemLoggerImpl.java
similarity index 100%
rename from legacyworlds-server-beans-eventlog/src/main/java/com/deepclone/lw/beans/eventlog/SystemLoggerImpl.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-eventlog/src/main/java/com/deepclone/lw/beans/eventlog/SystemLoggerImpl.java
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-eventlog/src/main/resources/configuration/eventlog-beans.xml b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-eventlog/src/main/resources/configuration/eventlog-beans.xml
new file mode 100644
index 0000000..934a2d8
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-eventlog/src/main/resources/configuration/eventlog-beans.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="
+                        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
+
+	<import resource="eventlog/admin-error-mail-bean.xml" />
+	<import resource="eventlog/log-cleaner-bean.xml" />
+	<import resource="eventlog/log-reader-bean.xml" />
+	<import resource="eventlog/log-writer-bean.xml" />
+	<import resource="eventlog/logger-bean.xml" />
+
+</beans>
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-eventlog/src/main/resources/configuration/eventlog/admin-error-mail-bean.xml b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-eventlog/src/main/resources/configuration/eventlog/admin-error-mail-bean.xml
new file mode 100644
index 0000000..f0e6a6e
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-eventlog/src/main/resources/configuration/eventlog/admin-error-mail-bean.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="
+                        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
+
+	<bean id="adminErrorMail" class="com.deepclone.lw.beans.eventlog.AdminErrorMailBean" />
+
+</beans>
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-eventlog/src/main/resources/configuration/eventlog/log-cleaner-bean.xml b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-eventlog/src/main/resources/configuration/eventlog/log-cleaner-bean.xml
new file mode 100644
index 0000000..7773c57
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-eventlog/src/main/resources/configuration/eventlog/log-cleaner-bean.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="
+                        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
+
+	<bean id="logCleaner" class="com.deepclone.lw.beans.eventlog.LogCleanerBean" />
+
+</beans>
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-eventlog/src/main/resources/configuration/eventlog/log-reader-bean.xml b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-eventlog/src/main/resources/configuration/eventlog/log-reader-bean.xml
new file mode 100644
index 0000000..1e56da0
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-eventlog/src/main/resources/configuration/eventlog/log-reader-bean.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="
+                        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
+
+	<bean id="logReader" class="com.deepclone.lw.beans.eventlog.LogReaderBean" />
+
+</beans>
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-eventlog/src/main/resources/configuration/eventlog/log-writer-bean.xml b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-eventlog/src/main/resources/configuration/eventlog/log-writer-bean.xml
new file mode 100644
index 0000000..21fc777
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-eventlog/src/main/resources/configuration/eventlog/log-writer-bean.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="
+                        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
+
+	<bean id="logWriter" class="com.deepclone.lw.beans.eventlog.LogWriterBean" />
+
+</beans>
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-eventlog/src/main/resources/configuration/eventlog/logger-bean.xml b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-eventlog/src/main/resources/configuration/eventlog/logger-bean.xml
new file mode 100644
index 0000000..22b1347
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-eventlog/src/main/resources/configuration/eventlog/logger-bean.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="
+                        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
+
+	<bean id="logger" class="com.deepclone.lw.beans.eventlog.LoggerBean" />
+
+</beans>
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-events/.classpath b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-events/.classpath
new file mode 100644
index 0000000..7c3d14f
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-events/.classpath
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" output="target/classes" path="src/main/java"/>
+	<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources"/>
+	<classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
+	<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+	<classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER"/>
+	<classpathentry kind="output" path="target/classes"/>
+</classpath>
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-events/.project b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-events/.project
new file mode 100644
index 0000000..99714d6
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-events/.project
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>legacyworlds-server-beans-events</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.maven.ide.eclipse.maven2Builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.maven.ide.eclipse.maven2Nature</nature>
+	</natures>
+</projectDescription>
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-events/.settings/org.eclipse.jdt.core.prefs b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-events/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..6839360
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-events/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,6 @@
+#Sun Apr 03 09:36:59 CEST 2011
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.6
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-events/.settings/org.maven.ide.eclipse.prefs b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-events/.settings/org.maven.ide.eclipse.prefs
new file mode 100644
index 0000000..abbef3f
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-events/.settings/org.maven.ide.eclipse.prefs
@@ -0,0 +1,9 @@
+#Sun Apr 03 09:36:59 CEST 2011
+activeProfiles=
+eclipse.preferences.version=1
+fullBuildGoals=process-test-resources
+includeModules=false
+resolveWorkspaceProjects=true
+resourceFilterGoals=process-resources resources\:testResources
+skipCompilerPlugin=true
+version=1
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-events/pom.xml b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-events/pom.xml
new file mode 100644
index 0000000..143c198
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-events/pom.xml
@@ -0,0 +1,13 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <artifactId>legacyworlds-server-beans</artifactId>
+    <groupId>com.deepclone.lw</groupId>
+    <version>5.99.2</version>
+  </parent>
+  <groupId>com.deepclone.lw</groupId>
+  <artifactId>legacyworlds-server-beans-events</artifactId>
+  <version>5.99.2</version>
+  <name>Game events</name>
+  <description>This module contains components which manage game events.</description>
+</project>
\ No newline at end of file
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-i18n/.classpath b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-i18n/.classpath
new file mode 100644
index 0000000..7c3d14f
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-i18n/.classpath
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" output="target/classes" path="src/main/java"/>
+	<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources"/>
+	<classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
+	<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+	<classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER"/>
+	<classpathentry kind="output" path="target/classes"/>
+</classpath>
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-i18n/.project b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-i18n/.project
new file mode 100644
index 0000000..dffe14c
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-i18n/.project
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>legacyworlds-server-beans-i18n</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.maven.ide.eclipse.maven2Builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.maven.ide.eclipse.maven2Nature</nature>
+	</natures>
+</projectDescription>
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-i18n/.settings/org.eclipse.jdt.core.prefs b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-i18n/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..9640d22
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-i18n/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,6 @@
+#Fri Apr 09 10:19:36 CEST 2010
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.6
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-i18n/pom.xml b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-i18n/pom.xml
new file mode 100644
index 0000000..a3f0ce7
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-i18n/pom.xml
@@ -0,0 +1,16 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+	<parent>
+		<artifactId>legacyworlds-server-beans</artifactId>
+		<groupId>com.deepclone.lw</groupId>
+		<version>5.99.2</version>
+	</parent>
+
+	<groupId>com.deepclone.lw</groupId>
+	<artifactId>legacyworlds-server-beans-i18n</artifactId>
+	<name>Legacy Worlds internationalisation</name>
+	<version>5.99.2</version>
+	<description>This package defines the two beans which control server-side internationalised text management.</description>
+
+</project>
\ No newline at end of file
diff --git a/legacyworlds-server-beans-i18n/src/main/java/com/deepclone/lw/beans/i18n/I18NAdministrationImpl.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-i18n/src/main/java/com/deepclone/lw/beans/i18n/I18NAdministrationImpl.java
similarity index 100%
rename from legacyworlds-server-beans-i18n/src/main/java/com/deepclone/lw/beans/i18n/I18NAdministrationImpl.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-i18n/src/main/java/com/deepclone/lw/beans/i18n/I18NAdministrationImpl.java
diff --git a/legacyworlds-server-beans-i18n/src/main/java/com/deepclone/lw/beans/i18n/I18NData.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-i18n/src/main/java/com/deepclone/lw/beans/i18n/I18NData.java
similarity index 95%
rename from legacyworlds-server-beans-i18n/src/main/java/com/deepclone/lw/beans/i18n/I18NData.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-i18n/src/main/java/com/deepclone/lw/beans/i18n/I18NData.java
index 3ebac74..c48b5f6 100644
--- a/legacyworlds-server-beans-i18n/src/main/java/com/deepclone/lw/beans/i18n/I18NData.java
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-i18n/src/main/java/com/deepclone/lw/beans/i18n/I18NData.java
@@ -12,7 +12,7 @@ import java.util.concurrent.locks.ReentrantReadWriteLock;
 
 import javax.sql.DataSource;
 
-import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
 import org.springframework.transaction.TransactionStatus;
 import org.springframework.transaction.support.TransactionCallbackWithoutResult;
 import org.springframework.transaction.support.TransactionTemplate;
@@ -35,7 +35,7 @@ class I18NData
 	private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock( );
 
 	/** Database interface */
-	private final JdbcTemplate dTemplate;
+	private final SimpleJdbcTemplate dTemplate;
 
 	/** Transaction manager interface */
 	private final TransactionTemplate tTemplate;
@@ -53,7 +53,7 @@ class I18NData
 	/** Copies the required references then loads all data */
 	I18NData( DataSource dataSource , TransactionTemplate tTemplate )
 	{
-		this.dTemplate = new JdbcTemplate( dataSource );
+		this.dTemplate = new SimpleJdbcTemplate( dataSource );
 		this.tTemplate = tTemplate;
 
 		this.fUocLanguage = new StoredProc( dataSource , "defs" , "uoc_language" );
@@ -239,20 +239,6 @@ class I18NData
 	}
 
 
-	/**
-	 * Access the store for some language
-	 * 
-	 * @param language
-	 *            the language to access
-	 * 
-	 * @return the language store, or <code>null</code> if the language is not defined.
-	 */
-	LanguageStore getStore( String language )
-	{
-		return this.languages.get( language );
-	}
-
-
 	/**
 	 * Sets or creates the translation for a given language/string identifier pair.
 	 * 
@@ -271,8 +257,7 @@ class I18NData
 	 * @throws IllegalArgumentException
 	 *             if the string does not exist
 	 */
-	String setTranslation( final int administrator , final String language , final String string ,
-			final String translation )
+	String setTranslation( final int administrator , final String language , final String string , final String translation )
 	{
 		// Get existing translation
 		LanguageStore store = this.languages.get( language );
diff --git a/legacyworlds-server-beans-i18n/src/main/java/com/deepclone/lw/beans/i18n/I18NManagerBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-i18n/src/main/java/com/deepclone/lw/beans/i18n/I18NManagerBean.java
similarity index 100%
rename from legacyworlds-server-beans-i18n/src/main/java/com/deepclone/lw/beans/i18n/I18NManagerBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-i18n/src/main/java/com/deepclone/lw/beans/i18n/I18NManagerBean.java
diff --git a/legacyworlds-server-beans-i18n/src/main/java/com/deepclone/lw/beans/i18n/LanguageStore.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-i18n/src/main/java/com/deepclone/lw/beans/i18n/LanguageStore.java
similarity index 100%
rename from legacyworlds-server-beans-i18n/src/main/java/com/deepclone/lw/beans/i18n/LanguageStore.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-i18n/src/main/java/com/deepclone/lw/beans/i18n/LanguageStore.java
diff --git a/legacyworlds-server-beans-i18n/src/main/java/com/deepclone/lw/beans/i18n/LoaderTransaction.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-i18n/src/main/java/com/deepclone/lw/beans/i18n/LoaderTransaction.java
similarity index 92%
rename from legacyworlds-server-beans-i18n/src/main/java/com/deepclone/lw/beans/i18n/LoaderTransaction.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-i18n/src/main/java/com/deepclone/lw/beans/i18n/LoaderTransaction.java
index 7df47fa..ffedd04 100644
--- a/legacyworlds-server-beans-i18n/src/main/java/com/deepclone/lw/beans/i18n/LoaderTransaction.java
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-i18n/src/main/java/com/deepclone/lw/beans/i18n/LoaderTransaction.java
@@ -6,8 +6,8 @@ import java.sql.SQLException;
 import java.util.HashMap;
 import java.util.HashSet;
 
-import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.jdbc.core.RowMapper;
+import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
 import org.springframework.transaction.TransactionStatus;
 import org.springframework.transaction.support.TransactionCallbackWithoutResult;
 
@@ -27,7 +27,7 @@ class LoaderTransaction
 {
 
 	/** Database interface */
-	private final JdbcTemplate dTemplate;
+	private final SimpleJdbcTemplate dTemplate;
 
 	/** String definition map being initialised */
 	private final HashSet< String > strings;
@@ -37,7 +37,7 @@ class LoaderTransaction
 
 
 	/** Copies the required references */
-	LoaderTransaction( JdbcTemplate dTemplate , HashSet< String > strings ,
+	LoaderTransaction( SimpleJdbcTemplate dTemplate , HashSet< String > strings ,
 			HashMap< String , LanguageStore > languages )
 	{
 		this.dTemplate = dTemplate;
diff --git a/legacyworlds-server-beans-i18n/src/main/java/com/deepclone/lw/beans/i18n/TranslatorBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-i18n/src/main/java/com/deepclone/lw/beans/i18n/TranslatorBean.java
similarity index 65%
rename from legacyworlds-server-beans-i18n/src/main/java/com/deepclone/lw/beans/i18n/TranslatorBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-i18n/src/main/java/com/deepclone/lw/beans/i18n/TranslatorBean.java
index 4e97fbf..7ef4255 100644
--- a/legacyworlds-server-beans-i18n/src/main/java/com/deepclone/lw/beans/i18n/TranslatorBean.java
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-i18n/src/main/java/com/deepclone/lw/beans/i18n/TranslatorBean.java
@@ -1,14 +1,12 @@
 package com.deepclone.lw.beans.i18n;
 
 
-import java.util.Collection;
-import java.util.HashMap;
 import java.util.HashSet;
-import java.util.Map;
 import java.util.Set;
 
 import org.springframework.beans.factory.annotation.Autowired;
 
+import com.deepclone.lw.interfaces.i18n.LanguageTranslator;
 import com.deepclone.lw.interfaces.i18n.Translator;
 import com.deepclone.lw.interfaces.i18n.UnknownLanguageException;
 import com.deepclone.lw.interfaces.i18n.UnknownStringException;
@@ -16,17 +14,75 @@ import com.deepclone.lw.interfaces.i18n.UnknownStringException;
 
 
 /**
- * Translation component
- * 
- * <p>
  * The translator bean's implementation uses the contents of the {@link I18NData} instance, which it
  * only accesses in read-only mode.
  * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
+ * @author tseeker
  */
 public class TranslatorBean
 		implements Translator
 {
+
+	/**
+	 * Implementation of a language-specific translator.
+	 */
+	private static class LanguageTranslatorImpl
+			implements LanguageTranslator
+	{
+		/** Language used by the translator */
+		private final String language;
+
+		/** Translations store */
+		private final I18NData data;
+
+
+		LanguageTranslatorImpl( String language , TranslatorBean translator )
+		{
+			this.language = language;
+			this.data = translator.data;
+		}
+
+
+		/* Documentation in LanguageTranslator interface */
+		@Override
+		public String getLanguage( )
+		{
+			return this.language;
+		}
+
+
+		/* Documentation in LanguageTranslator interface */
+		@Override
+		public String getLanguageName( )
+		{
+			this.data.readLock( ).lock( );
+			try {
+				return this.data.getLanguageName( language );
+			} finally {
+				this.data.readLock( ).unlock( );
+			}
+		}
+
+
+		/* Documentation in LanguageTranslator interface */
+		@Override
+		public String translate( String string )
+				throws UnknownStringException
+		{
+			this.data.readLock( ).lock( );
+			try {
+				if ( !this.data.hasString( string ) ) {
+					throw new UnknownStringException( string );
+				}
+				return this.data.getTranslation( language , string );
+			} finally {
+				this.data.readLock( ).unlock( );
+			}
+		}
+
+	}
+
+	/** Translations store */
 	private I18NData data;
 
 
@@ -89,23 +145,6 @@ public class TranslatorBean
 	}
 
 
-	/* Documentation in Translator interface */
-	@Override
-	public String getLanguageName( String language )
-			throws UnknownLanguageException
-	{
-		this.data.readLock( ).lock( );
-		try {
-			if ( !this.data.isLanguageComplete( language ) ) {
-				throw new UnknownLanguageException( language );
-			}
-			return this.data.getLanguageName( language );
-		} finally {
-			this.data.readLock( ).unlock( );
-		}
-	}
-
-
 	/* Documentation in Translator interface */
 	@Override
 	public String translate( String language , String string )
@@ -126,30 +165,34 @@ public class TranslatorBean
 	}
 
 
-	/**
-	 * Access the store for the specified language then extract translations
-	 */
+	/* Documentation in Translator interface */
 	@Override
-	public Map< String , String > translate( String language , Collection< String > strings )
-			throws UnknownStringException , UnknownLanguageException
+	public String getLanguageName( String language )
+			throws UnknownLanguageException
 	{
 		this.data.readLock( ).lock( );
 		try {
 			if ( !this.data.isLanguageComplete( language ) ) {
 				throw new UnknownLanguageException( language );
 			}
-			
-			LanguageStore store = this.data.getStore( language );
-			HashMap< String , String > result = new HashMap< String , String >( );
-			for ( String identifier : strings ) {
-				String value = store.getTranslation( identifier );
-				if ( value == null ) {
-					throw new UnknownStringException( identifier );
-				}
-				result.put( identifier , value );
-			}
+			return this.data.getLanguageName( language );
+		} finally {
+			this.data.readLock( ).unlock( );
+		}
+	}
 
-			return result;
+
+	/* Documentation in Translator interface */
+	@Override
+	public LanguageTranslator getLanguageTranslator( String language )
+			throws UnknownLanguageException
+	{
+		this.data.readLock( ).lock( );
+		try {
+			if ( !this.data.isLanguageComplete( language ) ) {
+				throw new UnknownLanguageException( language );
+			}
+			return new LanguageTranslatorImpl( language , this );
 		} finally {
 			this.data.readLock( ).unlock( );
 		}
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-i18n/src/main/resources/configuration/i18n-beans.xml b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-i18n/src/main/resources/configuration/i18n-beans.xml
new file mode 100644
index 0000000..bfaaebb
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-i18n/src/main/resources/configuration/i18n-beans.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="
+                        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
+
+	<import resource="i18n/i18n-manager-bean.xml" />
+	<import resource="i18n/i18n-translator-bean.xml" />
+
+</beans>
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-i18n/src/main/resources/configuration/i18n/i18n-manager-bean.xml b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-i18n/src/main/resources/configuration/i18n/i18n-manager-bean.xml
new file mode 100644
index 0000000..a683f48
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-i18n/src/main/resources/configuration/i18n/i18n-manager-bean.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+                xsi:schemaLocation="
+                        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
+
+	<bean id="i18nManager" class="com.deepclone.lw.beans.i18n.I18NManagerBean" />
+
+</beans>
diff --git a/legacyworlds-server-beans-i18n/src/main/resources/configuration/meta/i18n.xml b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-i18n/src/main/resources/configuration/i18n/i18n-translator-bean.xml
similarity index 52%
rename from legacyworlds-server-beans-i18n/src/main/resources/configuration/meta/i18n.xml
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-i18n/src/main/resources/configuration/i18n/i18n-translator-bean.xml
index dc21c5b..9118332 100644
--- a/legacyworlds-server-beans-i18n/src/main/resources/configuration/meta/i18n.xml
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-i18n/src/main/resources/configuration/i18n/i18n-translator-bean.xml
@@ -1,10 +1,9 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <beans xmlns="http://www.springframework.org/schema/beans"
-	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	xsi:schemaLocation="
-                        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
-
-	<bean id="i18nManager" class="com.deepclone.lw.beans.i18n.I18NManagerBean" />
+                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+                xsi:schemaLocation="
+                        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
+                        
 	<bean id="i18nTranslator" class="com.deepclone.lw.beans.i18n.TranslatorBean" />
 
-</beans>
\ No newline at end of file
+</beans>
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-mailer/.classpath b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-mailer/.classpath
new file mode 100644
index 0000000..7c3d14f
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-mailer/.classpath
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" output="target/classes" path="src/main/java"/>
+	<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources"/>
+	<classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
+	<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+	<classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER"/>
+	<classpathentry kind="output" path="target/classes"/>
+</classpath>
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-mailer/.project b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-mailer/.project
new file mode 100644
index 0000000..1c8b8cf
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-mailer/.project
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>legacyworlds-server-beans-mailer</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.maven.ide.eclipse.maven2Builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.maven.ide.eclipse.maven2Nature</nature>
+	</natures>
+</projectDescription>
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-mailer/.settings/org.eclipse.jdt.core.prefs b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-mailer/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..0a8422b
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-mailer/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,6 @@
+#Fri Apr 09 10:19:43 CEST 2010
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.6
diff --git a/legacyworlds-server-beans-mailer/pom.xml b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-mailer/pom.xml
similarity index 59%
rename from legacyworlds-server-beans-mailer/pom.xml
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-mailer/pom.xml
index a69cc12..4bdff1a 100644
--- a/legacyworlds-server-beans-mailer/pom.xml
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-mailer/pom.xml
@@ -4,26 +4,31 @@
 	<parent>
 		<artifactId>legacyworlds-server-beans</artifactId>
 		<groupId>com.deepclone.lw</groupId>
-		<version>1.0.0</version>
-		<relativePath>../legacyworlds-server-beans/pom.xml</relativePath>
+		<version>5.99.2</version>
 	</parent>
 
+	<groupId>com.deepclone.lw</groupId>
 	<artifactId>legacyworlds-server-beans-mailer</artifactId>
-	<name>Legacy Worlds - Server - Components - Mailer</name>
-	<version>${legacyworlds.version.main}.${legacyworlds.version.release}-${legacyworlds.version.build}</version>
-	<description>This package contains the mailer component, which uses LW's i18n system and Spring's mail sending interfaces.
-It is capable of sending mails synchronously or asynchronously.</description>
+	<version>5.99.2</version>
+	<name>Legacy Worlds mailer</name>
+	<description>
+		This package contains the mailer component, which uses LW's i18n system and Spring's mail sending interfaces.
+It is capable of sending mails synchronously or asynchronously.
+	</description>
 
 	<dependencies>
 		<dependency>
 			<groupId>org.springframework</groupId>
 			<artifactId>spring-context-support</artifactId>
+			<version>${org.springframework.version}</version>
 			<type>jar</type>
 		</dependency>
 
 		<dependency>
 			<groupId>javax.mail</groupId>
 			<artifactId>mail</artifactId>
+			<version>${javax.mail.version}</version>
+			<scope>runtime</scope>
 		</dependency>
 	</dependencies>
 
diff --git a/legacyworlds-server-beans-mailer/src/main/java/com/deepclone/lw/beans/mailer/MailDataImpl.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-mailer/src/main/java/com/deepclone/lw/beans/mailer/MailDataImpl.java
similarity index 100%
rename from legacyworlds-server-beans-mailer/src/main/java/com/deepclone/lw/beans/mailer/MailDataImpl.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-mailer/src/main/java/com/deepclone/lw/beans/mailer/MailDataImpl.java
diff --git a/legacyworlds-server-beans-mailer/src/main/java/com/deepclone/lw/beans/mailer/MailQueueHandler.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-mailer/src/main/java/com/deepclone/lw/beans/mailer/MailQueueHandler.java
similarity index 100%
rename from legacyworlds-server-beans-mailer/src/main/java/com/deepclone/lw/beans/mailer/MailQueueHandler.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-mailer/src/main/java/com/deepclone/lw/beans/mailer/MailQueueHandler.java
diff --git a/legacyworlds-server-beans-mailer/src/main/java/com/deepclone/lw/beans/mailer/MailQueueItem.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-mailer/src/main/java/com/deepclone/lw/beans/mailer/MailQueueItem.java
similarity index 100%
rename from legacyworlds-server-beans-mailer/src/main/java/com/deepclone/lw/beans/mailer/MailQueueItem.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-mailer/src/main/java/com/deepclone/lw/beans/mailer/MailQueueItem.java
diff --git a/legacyworlds-server-beans-mailer/src/main/java/com/deepclone/lw/beans/mailer/MailQueueTask.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-mailer/src/main/java/com/deepclone/lw/beans/mailer/MailQueueTask.java
similarity index 100%
rename from legacyworlds-server-beans-mailer/src/main/java/com/deepclone/lw/beans/mailer/MailQueueTask.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-mailer/src/main/java/com/deepclone/lw/beans/mailer/MailQueueTask.java
diff --git a/legacyworlds-server-beans-mailer/src/main/java/com/deepclone/lw/beans/mailer/MailQueueTerminator.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-mailer/src/main/java/com/deepclone/lw/beans/mailer/MailQueueTerminator.java
similarity index 100%
rename from legacyworlds-server-beans-mailer/src/main/java/com/deepclone/lw/beans/mailer/MailQueueTerminator.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-mailer/src/main/java/com/deepclone/lw/beans/mailer/MailQueueTerminator.java
diff --git a/legacyworlds-server-beans-mailer/src/main/java/com/deepclone/lw/beans/mailer/MailerBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-mailer/src/main/java/com/deepclone/lw/beans/mailer/MailerBean.java
similarity index 100%
rename from legacyworlds-server-beans-mailer/src/main/java/com/deepclone/lw/beans/mailer/MailerBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-mailer/src/main/java/com/deepclone/lw/beans/mailer/MailerBean.java
diff --git a/legacyworlds-server-beans-mailer/src/main/java/com/deepclone/lw/beans/mailer/QueuedMail.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-mailer/src/main/java/com/deepclone/lw/beans/mailer/QueuedMail.java
similarity index 100%
rename from legacyworlds-server-beans-mailer/src/main/java/com/deepclone/lw/beans/mailer/QueuedMail.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-mailer/src/main/java/com/deepclone/lw/beans/mailer/QueuedMail.java
diff --git a/legacyworlds-server-beans-mailer/src/main/resources/configuration/meta/mailer.xml b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-mailer/src/main/resources/configuration/mailer-beans.xml
similarity index 74%
rename from legacyworlds-server-beans-mailer/src/main/resources/configuration/meta/mailer.xml
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-mailer/src/main/resources/configuration/mailer-beans.xml
index cceb640..e5e284f 100644
--- a/legacyworlds-server-beans-mailer/src/main/resources/configuration/meta/mailer.xml
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-mailer/src/main/resources/configuration/mailer-beans.xml
@@ -2,9 +2,9 @@
 <beans xmlns="http://www.springframework.org/schema/beans"
 	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 	xsi:schemaLocation="
-                        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
+                        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
 
-	<bean id="mailer" class="com.deepclone.lw.beans.mailer.MailerBean" />
+	<import resource="mailer/mailer-bean.xml" />
 	<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
 		<property name="host" value="127.0.0.1" />
 	</bean>
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-mailer/src/main/resources/configuration/mailer/mailer-bean.xml b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-mailer/src/main/resources/configuration/mailer/mailer-bean.xml
new file mode 100644
index 0000000..a430dd0
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-mailer/src/main/resources/configuration/mailer/mailer-bean.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+                xsi:schemaLocation="
+                        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
+
+	<!-- Mailer bean - all properties autowired or defaulted -->
+	<bean id="mailer" class="com.deepclone.lw.beans.mailer.MailerBean" />
+
+</beans>
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-naming/.classpath b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-naming/.classpath
new file mode 100644
index 0000000..7c3d14f
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-naming/.classpath
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" output="target/classes" path="src/main/java"/>
+	<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources"/>
+	<classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
+	<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+	<classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER"/>
+	<classpathentry kind="output" path="target/classes"/>
+</classpath>
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-naming/.project b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-naming/.project
new file mode 100644
index 0000000..f7bc35d
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-naming/.project
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>legacyworlds-server-beans-naming</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.maven.ide.eclipse.maven2Builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.maven.ide.eclipse.maven2Nature</nature>
+	</natures>
+</projectDescription>
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-naming/.settings/org.eclipse.jdt.core.prefs b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-naming/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..d627e17
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-naming/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,6 @@
+#Thu Feb 25 09:52:02 CET 2010
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.6
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-naming/.settings/org.maven.ide.eclipse.prefs b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-naming/.settings/org.maven.ide.eclipse.prefs
new file mode 100644
index 0000000..8e6c298
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-naming/.settings/org.maven.ide.eclipse.prefs
@@ -0,0 +1,9 @@
+#Thu Feb 25 09:52:02 CET 2010
+activeProfiles=
+eclipse.preferences.version=1
+fullBuildGoals=process-test-resources
+includeModules=false
+resolveWorkspaceProjects=true
+resourceFilterGoals=process-resources resources\:testResources
+skipCompilerPlugin=true
+version=1
diff --git a/legacyworlds-server-beans-naming/pom.xml b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-naming/pom.xml
similarity index 66%
rename from legacyworlds-server-beans-naming/pom.xml
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-naming/pom.xml
index 864cec9..59a113f 100644
--- a/legacyworlds-server-beans-naming/pom.xml
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-naming/pom.xml
@@ -4,12 +4,12 @@
 	<parent>
 		<artifactId>legacyworlds-server-beans</artifactId>
 		<groupId>com.deepclone.lw</groupId>
-		<version>1.0.0</version>
-		<relativePath>../legacyworlds-server-beans/pom.xml</relativePath>
+		<version>5.99.2</version>
 	</parent>
 
+	<groupId>com.deepclone.lw</groupId>
 	<artifactId>legacyworlds-server-beans-naming</artifactId>
-	<name>Legacy Worlds - Server - Components - Naming system</name>
-	<version>${legacyworlds.version.main}.${legacyworlds.version.release}-${legacyworlds.version.build}</version>
+	<version>5.99.2</version>
+	<name>Legacy Worlds object naming system</name>
 	<description>This module contains the beans responsible for managing the names of the various objects (players and planets).</description>
-</project>
+</project>
\ No newline at end of file
diff --git a/legacyworlds-server-beans-naming/src/main/java/com/deepclone/lw/beans/naming/NamesManagerBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-naming/src/main/java/com/deepclone/lw/beans/naming/NamesManagerBean.java
similarity index 100%
rename from legacyworlds-server-beans-naming/src/main/java/com/deepclone/lw/beans/naming/NamesManagerBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-naming/src/main/java/com/deepclone/lw/beans/naming/NamesManagerBean.java
diff --git a/legacyworlds-server-beans-naming/src/main/java/com/deepclone/lw/beans/naming/NamingDAOBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-naming/src/main/java/com/deepclone/lw/beans/naming/NamingDAOBean.java
similarity index 97%
rename from legacyworlds-server-beans-naming/src/main/java/com/deepclone/lw/beans/naming/NamingDAOBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-naming/src/main/java/com/deepclone/lw/beans/naming/NamingDAOBean.java
index a672d84..2c2be52 100644
--- a/legacyworlds-server-beans-naming/src/main/java/com/deepclone/lw/beans/naming/NamingDAOBean.java
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-naming/src/main/java/com/deepclone/lw/beans/naming/NamingDAOBean.java
@@ -11,8 +11,8 @@ import java.util.Map;
 import javax.sql.DataSource;
 
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.jdbc.core.RowMapper;
+import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
 
 import com.deepclone.lw.cmd.admin.naming.Name;
 import com.deepclone.lw.cmd.admin.naming.NameType;
@@ -33,7 +33,7 @@ public class NamingDAOBean
 		long count;
 	}
 
-	private JdbcTemplate dTemplate;
+	private SimpleJdbcTemplate dTemplate;
 
 	private StoredProc fGetEmpire;
 	private StoredProc fRenamePlanet;
@@ -75,7 +75,7 @@ public class NamingDAOBean
 	@Autowired( required = true )
 	public void setDataSource( DataSource dataSource )
 	{
-		this.dTemplate = new JdbcTemplate( dataSource );
+		this.dTemplate = new SimpleJdbcTemplate( dataSource );
 
 		this.fGetEmpire = new StoredProc( dataSource , "emp" , "get_current" );
 		this.fGetEmpire.addParameter( "account_id" , Types.INTEGER );
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-naming/src/main/resources/configuration/naming-beans.xml b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-naming/src/main/resources/configuration/naming-beans.xml
new file mode 100644
index 0000000..f4ab8cc
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-naming/src/main/resources/configuration/naming-beans.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="
+                        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
+
+	<import resource="naming/names-manager-bean.xml" />
+	<import resource="naming/naming-dao-bean.xml" />
+
+</beans>
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-naming/src/main/resources/configuration/naming/names-manager-bean.xml b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-naming/src/main/resources/configuration/naming/names-manager-bean.xml
new file mode 100644
index 0000000..060f506
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-naming/src/main/resources/configuration/naming/names-manager-bean.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="
+                        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
+
+	<bean id="namesManager" class="com.deepclone.lw.beans.naming.NamesManagerBean" />
+
+</beans>
diff --git a/legacyworlds-server-beans-naming/src/main/resources/configuration/meta/naming.xml b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-naming/src/main/resources/configuration/naming/naming-dao-bean.xml
similarity index 57%
rename from legacyworlds-server-beans-naming/src/main/resources/configuration/meta/naming.xml
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-naming/src/main/resources/configuration/naming/naming-dao-bean.xml
index 4750147..0a3dfe5 100644
--- a/legacyworlds-server-beans-naming/src/main/resources/configuration/meta/naming.xml
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-naming/src/main/resources/configuration/naming/naming-dao-bean.xml
@@ -2,10 +2,8 @@
 <beans xmlns="http://www.springframework.org/schema/beans"
 	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 	xsi:schemaLocation="
-                        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
+                        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
 
-	<bean id="objectNameValidator" class="com.deepclone.lw.beans.naming.ObjectNameValidatorBean" />
-	<bean id="namesManager" class="com.deepclone.lw.beans.naming.NamesManagerBean" />
 	<bean id="namingDAO" class="com.deepclone.lw.beans.naming.NamingDAOBean" />
 
 </beans>
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/.classpath b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/.classpath
new file mode 100644
index 0000000..7c3d14f
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/.classpath
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" output="target/classes" path="src/main/java"/>
+	<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources"/>
+	<classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
+	<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+	<classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER"/>
+	<classpathentry kind="output" path="target/classes"/>
+</classpath>
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/.project b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/.project
new file mode 100644
index 0000000..e30c96f
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/.project
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>legacyworlds-server-beans-simple</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.maven.ide.eclipse.maven2Builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.maven.ide.eclipse.maven2Nature</nature>
+	</natures>
+</projectDescription>
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/.settings/org.eclipse.jdt.core.prefs b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..a82c1db
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,6 @@
+#Thu Apr 22 11:23:34 CEST 2010
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.6
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/.settings/org.maven.ide.eclipse.prefs b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/.settings/org.maven.ide.eclipse.prefs
new file mode 100644
index 0000000..fa121cb
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/.settings/org.maven.ide.eclipse.prefs
@@ -0,0 +1,9 @@
+#Thu Apr 22 11:23:34 CEST 2010
+activeProfiles=
+eclipse.preferences.version=1
+fullBuildGoals=process-test-resources
+includeModules=false
+resolveWorkspaceProjects=true
+resourceFilterGoals=process-resources resources\:testResources
+skipCompilerPlugin=true
+version=1
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/pom.xml b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/pom.xml
new file mode 100644
index 0000000..ea2e695
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/pom.xml
@@ -0,0 +1,13 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <artifactId>legacyworlds-server-beans</artifactId>
+    <groupId>com.deepclone.lw</groupId>
+    <version>5.99.2</version>
+  </parent>
+  <groupId>com.deepclone.lw</groupId>
+  <artifactId>legacyworlds-server-beans-simple</artifactId>
+  <version>5.99.2</version>
+  <name>Legacy Worlds simple game</name>
+  <description>This module contains code that corresponds to a simple "placeholder" game. This code should become obsolete over time, as it is being replaced with actual LWB6 code, until the module can finally be removed.</description>
+</project>
\ No newline at end of file
diff --git a/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/empire/AllianceDAOBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/empire/AllianceDAOBean.java
similarity index 98%
rename from legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/empire/AllianceDAOBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/empire/AllianceDAOBean.java
index 8fc70b5..df2d7cc 100644
--- a/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/empire/AllianceDAOBean.java
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/empire/AllianceDAOBean.java
@@ -10,8 +10,8 @@ import javax.sql.DataSource;
 
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.dao.EmptyResultDataAccessException;
-import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.jdbc.core.RowMapper;
+import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
 
 import com.deepclone.lw.cmd.player.gdata.NameIdPair;
 import com.deepclone.lw.cmd.player.gdata.alliance.AllianceLeaderData;
@@ -28,7 +28,7 @@ public class AllianceDAOBean
 		implements AllianceDAO
 {
 
-	private JdbcTemplate dTemplate;
+	private SimpleJdbcTemplate dTemplate;
 	private StoredProc fCreateAlliance;
 	private StoredProc fJoinAlliance;
 	private StoredProc fCancelJoin;
@@ -42,7 +42,7 @@ public class AllianceDAOBean
 	@Autowired( required = true )
 	public void setDataSource( DataSource dataSource )
 	{
-		this.dTemplate = new JdbcTemplate( dataSource );
+		this.dTemplate = new SimpleJdbcTemplate( dataSource );
 
 		this.fCreateAlliance = new StoredProc( dataSource , "emp" , "create_alliance" );
 		this.fCreateAlliance.addParameter( "empire_id" , Types.INTEGER );
diff --git a/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/empire/AllianceManagementBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/empire/AllianceManagementBean.java
similarity index 100%
rename from legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/empire/AllianceManagementBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/empire/AllianceManagementBean.java
diff --git a/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/empire/EmpireDAOBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/empire/EmpireDAOBean.java
similarity index 86%
rename from legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/empire/EmpireDAOBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/empire/EmpireDAOBean.java
index 9d15e1e..5e30025 100644
--- a/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/empire/EmpireDAOBean.java
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/empire/EmpireDAOBean.java
@@ -10,8 +10,8 @@ import javax.sql.DataSource;
 
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.dao.EmptyResultDataAccessException;
-import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.jdbc.core.RowMapper;
+import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
 
 import com.deepclone.lw.cmd.ObjectNameError;
 import com.deepclone.lw.cmd.player.gdata.NameIdPair;
@@ -26,7 +26,7 @@ import com.deepclone.lw.utils.StoredProc;
 public class EmpireDAOBean
 		implements EmpireDAO
 {
-	private JdbcTemplate dTemplate;
+	private SimpleJdbcTemplate dTemplate;
 	private StoredProc fAddEmpEnemy;
 	private StoredProc fAddAllEnemy;
 	private StoredProc fRemoveEmpEnemy;
@@ -35,11 +35,35 @@ public class EmpireDAOBean
 
 	private final PlanetListMapper mPlanetList = new PlanetListMapper( );
 
+	private final RowMapper< GeneralInformation > mEmpireInfo;
+
+
+	public EmpireDAOBean( )
+	{
+		this.mEmpireInfo = new RowMapper< GeneralInformation >( ) {
+			@Override
+			public GeneralInformation mapRow( ResultSet rs , int rowNum )
+					throws SQLException
+			{
+				String st = rs.getString( "status" );
+				Character status = ( st == null ) ? null : st.charAt( 0 );
+				String name = rs.getString( "name" );
+				String tag = rs.getString( "alliance" );
+				String language = rs.getString( "language" );
+				long cash = rs.getLong( "cash" );
+				long nextTick = rs.getLong( "game_time" );
+				int accountId = rs.getInt( "account_id" );
+				return new GeneralInformation( status , name , tag , language , cash , nextTick , accountId );
+			}
+		};
+
+	}
+
 
 	@Autowired( required = true )
 	public void setDataSource( DataSource dataSource )
 	{
-		this.dTemplate = new JdbcTemplate( dataSource );
+		this.dTemplate = new SimpleJdbcTemplate( dataSource );
 
 		this.fAddEmpEnemy = new StoredProc( dataSource , "emp" , "add_enemy_empire" );
 		this.fAddEmpEnemy.addParameter( "empire_id" , Types.INTEGER );
@@ -71,7 +95,7 @@ public class EmpireDAOBean
 	{
 		String sql = "SELECT * FROM emp.general_information WHERE id = ?";
 		try {
-			return this.dTemplate.queryForObject( sql , new GeneralInformationRowMapper( ) , empireId );
+			return this.dTemplate.queryForObject( sql , this.mEmpireInfo , empireId );
 		} catch ( EmptyResultDataAccessException e ) {
 			return null;
 		}
diff --git a/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/empire/EmpireManagementBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/empire/EmpireManagementBean.java
similarity index 83%
rename from legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/empire/EmpireManagementBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/empire/EmpireManagementBean.java
index 2e3838b..0fc3d79 100644
--- a/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/empire/EmpireManagementBean.java
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/empire/EmpireManagementBean.java
@@ -1,10 +1,8 @@
 package com.deepclone.lw.beans.empire;
 
 
-import java.util.ArrayList;
 import java.util.LinkedList;
 import java.util.List;
-import java.util.Map;
 
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.transaction.annotation.Transactional;
@@ -18,7 +16,6 @@ import com.deepclone.lw.cmd.player.elist.EnemyListResponse;
 import com.deepclone.lw.cmd.player.gdata.GamePageData;
 import com.deepclone.lw.cmd.player.gdata.NameIdPair;
 import com.deepclone.lw.cmd.player.gdata.PlanetListData;
-import com.deepclone.lw.cmd.player.gdata.PlanetListResourceRecord;
 import com.deepclone.lw.cmd.player.gdata.battles.BattleListEntry;
 import com.deepclone.lw.cmd.player.gdata.empire.OverviewData;
 import com.deepclone.lw.interfaces.acm.UsersDAO;
@@ -26,7 +23,9 @@ import com.deepclone.lw.interfaces.game.BattlesCache;
 import com.deepclone.lw.interfaces.game.BattlesDAO;
 import com.deepclone.lw.interfaces.game.EmpireDAO;
 import com.deepclone.lw.interfaces.game.EmpireManagement;
-import com.deepclone.lw.interfaces.game.resources.ResourcesInformationDAO;
+import com.deepclone.lw.interfaces.i18n.LanguageTranslator;
+import com.deepclone.lw.interfaces.i18n.Translator;
+import com.deepclone.lw.interfaces.i18n.UnknownLanguageException;
 import com.deepclone.lw.interfaces.naming.NamingDAO;
 import com.deepclone.lw.interfaces.prefs.AccountPreferences;
 import com.deepclone.lw.interfaces.prefs.PreferencesDAO;
@@ -46,7 +45,7 @@ public class EmpireManagementBean
 	private EmpireDAO empireDao;
 	private PreferencesDAO prefsDao;
 	private BattlesDAO battlesDao;
-	private ResourcesInformationDAO resourcesInformationDao;
+	private Translator translator;
 
 
 	@Autowired( required = true )
@@ -85,9 +84,9 @@ public class EmpireManagementBean
 
 
 	@Autowired( required = true )
-	public void setResourcesInformationDao( ResourcesInformationDAO resourcesInformationDao )
+	public void setI18NManager( Translator translator )
 	{
-		this.resourcesInformationDao = resourcesInformationDao;
+		this.translator = translator;
 	}
 
 
@@ -111,9 +110,20 @@ public class EmpireManagementBean
 		AccountPreferences prefs = this.prefsDao.getPreferences( generalInformation.getAccountId( ) );
 		boolean rlTime = prefs.getPreference( "useRLTime" , Boolean.class );
 
-		return new GamePageData( generalInformation.getName( ) , generalInformation.getStatus( ) ,
-				generalInformation.getTag( ) , generalInformation.getCash( ) , generalInformation.getNextTick( ) ,
-				planets , rlTime, generalInformation.getLanguage( ) );
+		return new GamePageData( generalInformation.getName( ) , generalInformation.getStatus( ) , generalInformation
+				.getTag( ) , generalInformation.getCash( ) , generalInformation.getNextTick( ) , planets , rlTime );
+	}
+
+
+	@Override
+	public LanguageTranslator getTranslator( int empireId )
+	{
+		GeneralInformation generalInformation = this.empireDao.getInformation( empireId );
+		try {
+			return this.translator.getLanguageTranslator( generalInformation.getLanguage( ) );
+		} catch ( UnknownLanguageException e ) {
+			throw new RuntimeException( "account for empire " + empireId + " is using an unsupported language" , e );
+		}
 	}
 
 
@@ -140,8 +150,6 @@ public class EmpireManagementBean
 			battles.add( entry );
 		}
 
-		overview.setEconomy( this.resourcesInformationDao.getEmpireInformation( empireId ) );
-
 		return new EmpireResponse( this.getGeneralInformation( empireId ) , overview , battles );
 	}
 
@@ -149,19 +157,9 @@ public class EmpireManagementBean
 	@Override
 	public ListPlanetsResponse getPlanetList( int empireId )
 	{
+		GamePageData page = this.getGeneralInformation( empireId );
 		List< PlanetListData > planets = this.empireDao.getPlanetList( empireId );
-
-		Map< Integer , List< PlanetListResourceRecord >> resources;
-		resources = this.resourcesInformationDao.getPlanetListData( empireId );
-		for ( PlanetListData planet : planets ) {
-			List< PlanetListResourceRecord > planetResources = resources.get( planet.getId( ) );
-			if ( planetResources == null ) {
-				planetResources = new ArrayList< PlanetListResourceRecord >( );
-			}
-			planet.setResources( planetResources );
-		}
-
-		return new ListPlanetsResponse( this.getGeneralInformation( empireId ) , planets );
+		return new ListPlanetsResponse( page , planets );
 	}
 
 
diff --git a/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/empire/PlanetListMapper.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/empire/PlanetListMapper.java
similarity index 100%
rename from legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/empire/PlanetListMapper.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/empire/PlanetListMapper.java
diff --git a/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/fleets/BattleViewerBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/fleets/BattleViewerBean.java
similarity index 100%
rename from legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/fleets/BattleViewerBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/fleets/BattleViewerBean.java
diff --git a/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/fleets/BattlesCacheBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/fleets/BattlesCacheBean.java
similarity index 100%
rename from legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/fleets/BattlesCacheBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/fleets/BattlesCacheBean.java
diff --git a/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/fleets/BattlesDAOBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/fleets/BattlesDAOBean.java
similarity index 98%
rename from legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/fleets/BattlesDAOBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/fleets/BattlesDAOBean.java
index 1b87bbe..f7ce1a4 100644
--- a/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/fleets/BattlesDAOBean.java
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/fleets/BattlesDAOBean.java
@@ -12,8 +12,9 @@ import javax.sql.DataSource;
 
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.dao.EmptyResultDataAccessException;
-import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.jdbc.core.RowMapper;
+import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
+
 import com.deepclone.lw.interfaces.game.BattlesDAO;
 import com.deepclone.lw.sqld.game.battle.*;
 
@@ -33,7 +34,7 @@ public class BattlesDAOBean
 	private static final String sGetAllBattles = "SELECT * FROM battles.battles_list WHERE empire = ? ORDER BY last_tick DESC NULLS FIRST , first_tick DESC , x , y , orbit";
 	private static final String sGetNewBattles = "SELECT * FROM battles.battles_list WHERE empire = ? AND ( last_update > ? OR NOT finished ) ORDER BY last_tick DESC NULLS FIRST , first_tick DESC , x , y , orbit";
 
-	private JdbcTemplate dTemplate;
+	private SimpleJdbcTemplate dTemplate;
 
 	private final RowMapper< EmpireBattleRecord > mGetBattleRecord;
 	private final RowMapper< PresenceRecord > mGetPresenceList;
@@ -172,7 +173,7 @@ public class BattlesDAOBean
 	@Autowired( required = true )
 	public void setDataSource( DataSource dataSource )
 	{
-		this.dTemplate = new JdbcTemplate( dataSource );
+		this.dTemplate = new SimpleJdbcTemplate( dataSource );
 	}
 
 
diff --git a/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/fleets/FleetManagementBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/fleets/FleetManagementBean.java
similarity index 100%
rename from legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/fleets/FleetManagementBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/fleets/FleetManagementBean.java
diff --git a/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/fleets/FleetsDAOBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/fleets/FleetsDAOBean.java
similarity index 99%
rename from legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/fleets/FleetsDAOBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/fleets/FleetsDAOBean.java
index 6be2ef2..3fdbb24 100644
--- a/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/fleets/FleetsDAOBean.java
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/fleets/FleetsDAOBean.java
@@ -13,8 +13,8 @@ import javax.sql.DataSource;
 
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.dao.EmptyResultDataAccessException;
-import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.jdbc.core.RowMapper;
+import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
 
 import com.deepclone.lw.cmd.player.gdata.NameIdPair;
 import com.deepclone.lw.cmd.player.gdata.PlanetRelationType;
@@ -42,7 +42,7 @@ public class FleetsDAOBean
 	private static String sqlSingleMoving = "SELECT * FROM fleets.moving_fleets WHERE empire = ? AND id = ?";
 	private static String sqlFleetShips = "SELECT * FROM fleets.ships_view WHERE empire = ? AND id = ?";
 
-	private JdbcTemplate dTemplate;
+	private SimpleJdbcTemplate dTemplate;
 
 	private RowMapper< FleetLocation > mLocations;
 	private RowMapper< RawFleetOwner > mOwners;
@@ -209,7 +209,7 @@ public class FleetsDAOBean
 	@Autowired( required = true )
 	public void setDataSource( DataSource dataSource )
 	{
-		this.dTemplate = new JdbcTemplate( dataSource );
+		this.dTemplate = new SimpleJdbcTemplate( dataSource );
 
 		this.fMoveFleets = new StoredProc( dataSource , "fleets" , "move_fleets" );
 		this.fMoveFleets.addParameter( "empire_id" , Types.INTEGER );
diff --git a/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/map/MapViewerBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/map/MapViewerBean.java
similarity index 100%
rename from legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/map/MapViewerBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/map/MapViewerBean.java
diff --git a/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/map/PlanetDAOBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/map/PlanetDAOBean.java
similarity index 98%
rename from legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/map/PlanetDAOBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/map/PlanetDAOBean.java
index e9a1cf9..8fe710b 100644
--- a/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/map/PlanetDAOBean.java
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/map/PlanetDAOBean.java
@@ -9,8 +9,9 @@ import java.util.List;
 import javax.sql.DataSource;
 
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.jdbc.core.RowMapper;
+import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
+
 import com.deepclone.lw.cmd.player.gdata.planets.BuildableBuildingData;
 import com.deepclone.lw.cmd.player.gdata.planets.BuildableShipData;
 import com.deepclone.lw.cmd.player.gdata.planets.BuildingData;
@@ -29,7 +30,7 @@ public class PlanetDAOBean
 		implements PlanetDAO
 {
 
-	private JdbcTemplate dTemplate;
+	private SimpleJdbcTemplate dTemplate;
 
 	private RowMapper< Basic > mPlanetBasics;
 	private RowMapper< Orbital > mPlanetOrbital;
@@ -101,7 +102,6 @@ public class PlanetDAOBean
 				info.setRenamePossible( rs.getBoolean( "can_rename" ) );
 				info.setAbandonPossible( rs.getBoolean( "can_abandon" ) );
 				info.setAbandonTime( rs.getInt( "abandon_time" ) );
-				info.setOwnSettings( rs.getBoolean( "specific_mining_settings" ) );
 				return info;
 			}
 		};
@@ -195,7 +195,7 @@ public class PlanetDAOBean
 	@Autowired( required = true )
 	public void setDataSource( DataSource dataSource )
 	{
-		this.dTemplate = new JdbcTemplate( dataSource );
+		this.dTemplate = new SimpleJdbcTemplate( dataSource );
 
 		this.fFlushBuildQueue = new StoredProc( dataSource , "verse" , "flush_build_queue" );
 		this.fFlushBuildQueue.addParameter( "planet_id" , Types.INTEGER );
diff --git a/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/map/PlanetsManagementBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/map/PlanetsManagementBean.java
similarity index 95%
rename from legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/map/PlanetsManagementBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/map/PlanetsManagementBean.java
index 8d5bf13..709fe4b 100644
--- a/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/map/PlanetsManagementBean.java
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/map/PlanetsManagementBean.java
@@ -19,7 +19,6 @@ import com.deepclone.lw.cmd.player.planets.ViewPlanetResponse;
 import com.deepclone.lw.interfaces.game.EmpireManagement;
 import com.deepclone.lw.interfaces.game.PlanetDAO;
 import com.deepclone.lw.interfaces.game.PlanetsManagement;
-import com.deepclone.lw.interfaces.game.resources.ResourcesInformationDAO;
 import com.deepclone.lw.interfaces.naming.NamingDAO;
 import com.deepclone.lw.sqld.game.PlanetData;
 import com.deepclone.lw.sqld.game.PlanetData.AccessType;
@@ -37,7 +36,6 @@ public class PlanetsManagementBean
 	private EmpireManagement empireManagement;
 	private PlanetDAO planetDao;
 	private NamingDAO namingDao;
-	private ResourcesInformationDAO resourcesInformationDao;
 
 
 	@Autowired( required = true )
@@ -61,13 +59,6 @@ public class PlanetsManagementBean
 	}
 
 
-	@Autowired( required = true )
-	public void setResourcesInformationDao( ResourcesInformationDAO resourcesInformationDao )
-	{
-		this.resourcesInformationDao = resourcesInformationDao;
-	}
-
-
 	private PlanetOrbitalView getOrbitalView( int empireId , int planetId , AccessType access )
 	{
 		if ( access == AccessType.BASIC ) {
@@ -109,7 +100,6 @@ public class PlanetsManagementBean
 		view.sethChange( data.gethChange( ) );
 		view.setIncome( data.getIncome( ) );
 		view.setUpkeep( data.getUpkeep( ) );
-		view.setOwnMiningSettings( data.isOwnSettings( ) );
 
 		view.setCivQueue( this.planetDao.getConstructionQueue( planetId ) );
 		view.setMilQueue( this.planetDao.getMilitaryQueue( planetId ) );
@@ -117,8 +107,6 @@ public class PlanetsManagementBean
 		view.setbBuildings( this.planetDao.getAvailableBuildings( planetId ) );
 		view.setbShips( this.planetDao.getAvailableShips( planetId ) );
 
-		view.setResources( this.resourcesInformationDao.getPlanetInformation( planetId ) );
-
 		return view;
 	}
 
@@ -211,8 +199,8 @@ public class PlanetsManagementBean
 		if ( one == null ) {
 			return new ViewPlanetResponse( planetId , page , this.getBasicView( basic ) , orbital , owner );
 		}
-		return new RenamePlanetResponse( planetId , page , this.getBasicView( basic ) , orbital , owner , name ,
-				one.toString( ) );
+		return new RenamePlanetResponse( planetId , page , this.getBasicView( basic ) , orbital , owner , name , one
+				.toString( ) );
 	}
 
 
diff --git a/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/map/UniverseDAOBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/map/UniverseDAOBean.java
similarity index 85%
rename from legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/map/UniverseDAOBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/map/UniverseDAOBean.java
index b8e0c9b..b7dfe92 100644
--- a/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/map/UniverseDAOBean.java
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/map/UniverseDAOBean.java
@@ -8,8 +8,8 @@ import java.util.List;
 import javax.sql.DataSource;
 
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.jdbc.core.RowMapper;
+import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
 
 import com.deepclone.lw.interfaces.game.UniverseDAO;
 import com.deepclone.lw.sqld.game.MapData;
@@ -19,20 +19,20 @@ import com.deepclone.lw.sqld.game.MapData;
 public class UniverseDAOBean
 		implements UniverseDAO
 {
-	private JdbcTemplate dTemplate;
+	private SimpleJdbcTemplate dTemplate;
 
 
 	@Autowired( required = true )
 	public void setDataSource( DataSource dataSource )
 	{
-		this.dTemplate = new JdbcTemplate( dataSource );
+		this.dTemplate = new SimpleJdbcTemplate( dataSource );
 	}
 
 
 	@Override
 	public void generate( )
 	{
-		this.dTemplate.execute( "SELECT verse.generate( )" );
+		this.dTemplate.getJdbcOperations( ).execute( "SELECT verse.generate( )" );
 	}
 
 
diff --git a/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/map/UniverseGeneratorBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/map/UniverseGeneratorBean.java
similarity index 100%
rename from legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/map/UniverseGeneratorBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/map/UniverseGeneratorBean.java
diff --git a/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/map/UniverseGeneratorTask.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/map/UniverseGeneratorTask.java
similarity index 100%
rename from legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/map/UniverseGeneratorTask.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/map/UniverseGeneratorTask.java
diff --git a/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/AdminMessagesBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/AdminMessagesBean.java
similarity index 100%
rename from legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/AdminMessagesBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/AdminMessagesBean.java
diff --git a/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/EmpireMessagesBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/EmpireMessagesBean.java
similarity index 100%
rename from legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/EmpireMessagesBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/EmpireMessagesBean.java
diff --git a/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/MailTaskBase.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/MailTaskBase.java
similarity index 100%
rename from legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/MailTaskBase.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/MailTaskBase.java
diff --git a/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/MessageBoxDAOBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/MessageBoxDAOBean.java
similarity index 98%
rename from legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/MessageBoxDAOBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/MessageBoxDAOBean.java
index 462f40c..3933d8d 100644
--- a/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/MessageBoxDAOBean.java
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/MessageBoxDAOBean.java
@@ -13,8 +13,8 @@ import java.util.Map;
 import javax.sql.DataSource;
 
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.jdbc.core.RowMapper;
+import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
 
 import com.deepclone.lw.cmd.msgdata.MessageType;
 import com.deepclone.lw.cmd.player.msgs.MessageBoxAction;
@@ -87,7 +87,7 @@ public class MessageBoxDAOBean
 
 	private final Map< CacheKey , CacheData > cache = new HashMap< CacheKey , CacheData >( );
 
-	private JdbcTemplate dTemplate;
+	private SimpleJdbcTemplate dTemplate;
 	private final RowMapper< InboxRecord > listMapper;
 
 	private StoredProc fSendSpam;
@@ -135,7 +135,7 @@ public class MessageBoxDAOBean
 	@Autowired( required = true )
 	public void setDataSource( DataSource dataSource )
 	{
-		this.dTemplate = new JdbcTemplate( dataSource );
+		this.dTemplate = new SimpleJdbcTemplate( dataSource );
 
 		this.fSendSpam = new StoredProc( dataSource , "msgs" , "deliver_admin_spam" );
 		this.fSendSpam.addParameter( "admin_id" , Types.INTEGER );
diff --git a/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/MessageCleanerBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/MessageCleanerBean.java
similarity index 100%
rename from legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/MessageCleanerBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/MessageCleanerBean.java
diff --git a/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/MessageContentCacheBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/MessageContentCacheBean.java
similarity index 100%
rename from legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/MessageContentCacheBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/MessageContentCacheBean.java
diff --git a/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/MessageFormatRegistryBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/MessageFormatRegistryBean.java
similarity index 100%
rename from legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/MessageFormatRegistryBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/MessageFormatRegistryBean.java
diff --git a/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/MessageFormatWiringBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/MessageFormatWiringBean.java
similarity index 100%
rename from legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/MessageFormatWiringBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/MessageFormatWiringBean.java
diff --git a/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/MessageRecordsDAOBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/MessageRecordsDAOBean.java
similarity index 98%
rename from legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/MessageRecordsDAOBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/MessageRecordsDAOBean.java
index 92cfc6d..261d44a 100644
--- a/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/MessageRecordsDAOBean.java
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/MessageRecordsDAOBean.java
@@ -10,8 +10,8 @@ import java.util.Map;
 import javax.sql.DataSource;
 
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.jdbc.core.RowMapper;
+import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
 
 import com.deepclone.lw.interfaces.msg.MessageRecordsDAO;
 import com.deepclone.lw.sqld.msgs.*;
@@ -43,7 +43,7 @@ public class MessageRecordsDAOBean
 	private static final String sGetQueueLocations = "SELECT * FROM events.queue_locations_view WHERE event_id = ANY( ? ::BIGINT[] )";
 	private static final String sGetEventFleets = "SELECT * FROM events.fleet_lists WHERE event_id = ANY( ? ::BIGINT[] )";
 
-	private JdbcTemplate dTemplate;
+	private SimpleJdbcTemplate dTemplate;
 
 	private final RowMapper< TextMessageRecord > mTextMessage;
 	private final RowMapper< EventTypeRecord > mEventTypes;
@@ -219,7 +219,7 @@ public class MessageRecordsDAOBean
 	@Autowired( required = true )
 	public void setDataSource( DataSource dataSource )
 	{
-		this.dTemplate = new JdbcTemplate( dataSource );
+		this.dTemplate = new SimpleJdbcTemplate( dataSource );
 	}
 
 
diff --git a/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/MessageTasksBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/MessageTasksBean.java
similarity index 100%
rename from legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/MessageTasksBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/MessageTasksBean.java
diff --git a/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/NotificationsDAOBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/NotificationsDAOBean.java
similarity index 95%
rename from legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/NotificationsDAOBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/NotificationsDAOBean.java
index 777b143..9665362 100644
--- a/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/NotificationsDAOBean.java
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/NotificationsDAOBean.java
@@ -10,8 +10,8 @@ import java.util.List;
 import javax.sql.DataSource;
 
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.jdbc.core.RowMapper;
+import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
 
 import com.deepclone.lw.interfaces.msg.NotificationsDAO;
 import com.deepclone.lw.sqld.msgs.InboxRecord;
@@ -26,7 +26,7 @@ public class NotificationsDAOBean
 	private static final String sGetInstantNotifications = "SELECT * FROM msgs.get_mail_data() WHERE last_unmailed IS NOT NULL";
 	private static final String sGetRecapNotifications = "SELECT * FROM msgs.get_mail_data() WHERE last_unrecaped IS NOT NULL";
 
-	private JdbcTemplate dTemplate;
+	private SimpleJdbcTemplate dTemplate;
 
 	private final RowMapper< NotificationsRecord > mNotifications;
 	private RowMapper< InboxRecord > mList;
@@ -81,7 +81,7 @@ public class NotificationsDAOBean
 	@Autowired( required = true )
 	public void setDataSource( DataSource dataSource )
 	{
-		this.dTemplate = new JdbcTemplate( dataSource );
+		this.dTemplate = new SimpleJdbcTemplate( dataSource );
 
 		this.fMarkInstantMessages = new StoredProc( dataSource , "msgs" , "mark_instant_notifications" );
 		this.fMarkInstantMessages.addParameter( "empire_id" , Types.INTEGER );
@@ -163,6 +163,6 @@ public class NotificationsDAOBean
 	@Override
 	public void cleanupMessages( )
 	{
-		this.dTemplate.execute( "SELECT msgs.cleanup( )" );
+		this.dTemplate.getJdbcOperations( ).execute( "SELECT msgs.cleanup( )" );
 	}
 }
diff --git a/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/NotificationsTask.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/NotificationsTask.java
similarity index 100%
rename from legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/NotificationsTask.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/NotificationsTask.java
diff --git a/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/RecapitulationTask.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/RecapitulationTask.java
similarity index 100%
rename from legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/RecapitulationTask.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/RecapitulationTask.java
diff --git a/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/fmt/AbandonMessageFormatterBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/fmt/AbandonMessageFormatterBean.java
similarity index 100%
rename from legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/fmt/AbandonMessageFormatterBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/fmt/AbandonMessageFormatterBean.java
diff --git a/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/fmt/AdminMessageExtractor.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/fmt/AdminMessageExtractor.java
similarity index 100%
rename from legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/fmt/AdminMessageExtractor.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/fmt/AdminMessageExtractor.java
diff --git a/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/fmt/AdminMessageFormatterBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/fmt/AdminMessageFormatterBean.java
similarity index 100%
rename from legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/fmt/AdminMessageFormatterBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/fmt/AdminMessageFormatterBean.java
diff --git a/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/fmt/AllianceDisbandedMessageFormatterBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/fmt/AllianceDisbandedMessageFormatterBean.java
similarity index 100%
rename from legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/fmt/AllianceDisbandedMessageFormatterBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/fmt/AllianceDisbandedMessageFormatterBean.java
diff --git a/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/fmt/AllianceMessageExtractor.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/fmt/AllianceMessageExtractor.java
similarity index 100%
rename from legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/fmt/AllianceMessageExtractor.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/fmt/AllianceMessageExtractor.java
diff --git a/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/fmt/BattleMessageFormatterBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/fmt/BattleMessageFormatterBean.java
similarity index 100%
rename from legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/fmt/BattleMessageFormatterBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/fmt/BattleMessageFormatterBean.java
diff --git a/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/fmt/BugMessageFormatterBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/fmt/BugMessageFormatterBean.java
similarity index 100%
rename from legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/fmt/BugMessageFormatterBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/fmt/BugMessageFormatterBean.java
diff --git a/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/fmt/DebtMessageFormatterBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/fmt/DebtMessageFormatterBean.java
similarity index 100%
rename from legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/fmt/DebtMessageFormatterBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/fmt/DebtMessageFormatterBean.java
diff --git a/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/fmt/ExternalMessageFormatBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/fmt/ExternalMessageFormatBean.java
similarity index 100%
rename from legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/fmt/ExternalMessageFormatBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/fmt/ExternalMessageFormatBean.java
diff --git a/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/fmt/FleetMessageExtractor.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/fmt/FleetMessageExtractor.java
similarity index 100%
rename from legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/fmt/FleetMessageExtractor.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/fmt/FleetMessageExtractor.java
diff --git a/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/fmt/FleetMessageFormatterBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/fmt/FleetMessageFormatterBean.java
similarity index 100%
rename from legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/fmt/FleetMessageFormatterBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/fmt/FleetMessageFormatterBean.java
diff --git a/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/fmt/KickedMessageFormatterBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/fmt/KickedMessageFormatterBean.java
similarity index 100%
rename from legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/fmt/KickedMessageFormatterBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/fmt/KickedMessageFormatterBean.java
diff --git a/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/fmt/LeadershipMessageFormatterBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/fmt/LeadershipMessageFormatterBean.java
similarity index 100%
rename from legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/fmt/LeadershipMessageFormatterBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/fmt/LeadershipMessageFormatterBean.java
diff --git a/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/fmt/LeftAllianceMessageFormatterBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/fmt/LeftAllianceMessageFormatterBean.java
similarity index 100%
rename from legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/fmt/LeftAllianceMessageFormatterBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/fmt/LeftAllianceMessageFormatterBean.java
diff --git a/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/fmt/LostPlanetMessageFormatterBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/fmt/LostPlanetMessageFormatterBean.java
similarity index 100%
rename from legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/fmt/LostPlanetMessageFormatterBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/fmt/LostPlanetMessageFormatterBean.java
diff --git a/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/fmt/PendingRequestMessageFormatterBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/fmt/PendingRequestMessageFormatterBean.java
similarity index 100%
rename from legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/fmt/PendingRequestMessageFormatterBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/fmt/PendingRequestMessageFormatterBean.java
diff --git a/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/fmt/PlanetMessageExtractor.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/fmt/PlanetMessageExtractor.java
similarity index 100%
rename from legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/fmt/PlanetMessageExtractor.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/fmt/PlanetMessageExtractor.java
diff --git a/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/fmt/QueueMessageFormatterBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/fmt/QueueMessageFormatterBean.java
similarity index 100%
rename from legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/fmt/QueueMessageFormatterBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/fmt/QueueMessageFormatterBean.java
diff --git a/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/fmt/RequestResultMessageFormatterBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/fmt/RequestResultMessageFormatterBean.java
similarity index 100%
rename from legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/fmt/RequestResultMessageFormatterBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/fmt/RequestResultMessageFormatterBean.java
diff --git a/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/fmt/StrikeMessageFormatterBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/fmt/StrikeMessageFormatterBean.java
similarity index 100%
rename from legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/fmt/StrikeMessageFormatterBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/fmt/StrikeMessageFormatterBean.java
diff --git a/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/fmt/TakenPlanetMessageFormatterBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/fmt/TakenPlanetMessageFormatterBean.java
similarity index 100%
rename from legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/fmt/TakenPlanetMessageFormatterBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/fmt/TakenPlanetMessageFormatterBean.java
diff --git a/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/fmt/TechMessageFormatterBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/fmt/TechMessageFormatterBean.java
similarity index 100%
rename from legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/fmt/TechMessageFormatterBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/msgs/fmt/TechMessageFormatterBean.java
diff --git a/legacyworlds-server-beans-simple/src/main/resources/configuration/simple.xml b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/resources/configuration/simple-beans.xml
similarity index 100%
rename from legacyworlds-server-beans-simple/src/main/resources/configuration/simple.xml
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/resources/configuration/simple-beans.xml
diff --git a/legacyworlds-server-beans-simple/src/main/resources/configuration/simple/alliance-dao-bean.xml b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/resources/configuration/simple/alliance-dao-bean.xml
similarity index 100%
rename from legacyworlds-server-beans-simple/src/main/resources/configuration/simple/alliance-dao-bean.xml
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/resources/configuration/simple/alliance-dao-bean.xml
diff --git a/legacyworlds-server-beans-simple/src/main/resources/configuration/simple/alliance-management-bean.xml b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/resources/configuration/simple/alliance-management-bean.xml
similarity index 100%
rename from legacyworlds-server-beans-simple/src/main/resources/configuration/simple/alliance-management-bean.xml
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/resources/configuration/simple/alliance-management-bean.xml
diff --git a/legacyworlds-server-beans-simple/src/main/resources/configuration/simple/battle-data-beans.xml b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/resources/configuration/simple/battle-data-beans.xml
similarity index 100%
rename from legacyworlds-server-beans-simple/src/main/resources/configuration/simple/battle-data-beans.xml
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/resources/configuration/simple/battle-data-beans.xml
diff --git a/legacyworlds-server-beans-simple/src/main/resources/configuration/simple/empire-dao-bean.xml b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/resources/configuration/simple/empire-dao-bean.xml
similarity index 100%
rename from legacyworlds-server-beans-simple/src/main/resources/configuration/simple/empire-dao-bean.xml
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/resources/configuration/simple/empire-dao-bean.xml
diff --git a/legacyworlds-server-beans-simple/src/main/resources/configuration/simple/empire-management-bean.xml b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/resources/configuration/simple/empire-management-bean.xml
similarity index 100%
rename from legacyworlds-server-beans-simple/src/main/resources/configuration/simple/empire-management-bean.xml
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/resources/configuration/simple/empire-management-bean.xml
diff --git a/legacyworlds-server-beans-simple/src/main/resources/configuration/simple/fleet-management-bean.xml b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/resources/configuration/simple/fleet-management-bean.xml
similarity index 100%
rename from legacyworlds-server-beans-simple/src/main/resources/configuration/simple/fleet-management-bean.xml
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/resources/configuration/simple/fleet-management-bean.xml
diff --git a/legacyworlds-server-beans-simple/src/main/resources/configuration/simple/fleets-dao-bean.xml b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/resources/configuration/simple/fleets-dao-bean.xml
similarity index 100%
rename from legacyworlds-server-beans-simple/src/main/resources/configuration/simple/fleets-dao-bean.xml
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/resources/configuration/simple/fleets-dao-bean.xml
diff --git a/legacyworlds-server-beans-simple/src/main/resources/configuration/simple/map-viewer-bean.xml b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/resources/configuration/simple/map-viewer-bean.xml
similarity index 100%
rename from legacyworlds-server-beans-simple/src/main/resources/configuration/simple/map-viewer-bean.xml
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/resources/configuration/simple/map-viewer-bean.xml
diff --git a/legacyworlds-server-beans-simple/src/main/resources/configuration/simple/message-beans.xml b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/resources/configuration/simple/message-beans.xml
similarity index 100%
rename from legacyworlds-server-beans-simple/src/main/resources/configuration/simple/message-beans.xml
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/resources/configuration/simple/message-beans.xml
diff --git a/legacyworlds-server-beans-simple/src/main/resources/configuration/simple/planet-dao-bean.xml b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/resources/configuration/simple/planet-dao-bean.xml
similarity index 100%
rename from legacyworlds-server-beans-simple/src/main/resources/configuration/simple/planet-dao-bean.xml
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/resources/configuration/simple/planet-dao-bean.xml
diff --git a/legacyworlds-server-beans-simple/src/main/resources/configuration/simple/planets-management-bean.xml b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/resources/configuration/simple/planets-management-bean.xml
similarity index 100%
rename from legacyworlds-server-beans-simple/src/main/resources/configuration/simple/planets-management-bean.xml
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/resources/configuration/simple/planets-management-bean.xml
diff --git a/legacyworlds-server-beans-simple/src/main/resources/configuration/simple/universe-dao-bean.xml b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/resources/configuration/simple/universe-dao-bean.xml
similarity index 100%
rename from legacyworlds-server-beans-simple/src/main/resources/configuration/simple/universe-dao-bean.xml
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/resources/configuration/simple/universe-dao-bean.xml
diff --git a/legacyworlds-server-beans-simple/src/main/resources/configuration/simple/universe-generator-bean.xml b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/resources/configuration/simple/universe-generator-bean.xml
similarity index 100%
rename from legacyworlds-server-beans-simple/src/main/resources/configuration/simple/universe-generator-bean.xml
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-simple/src/main/resources/configuration/simple/universe-generator-bean.xml
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-system/.classpath b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-system/.classpath
new file mode 100644
index 0000000..7c3d14f
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-system/.classpath
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" output="target/classes" path="src/main/java"/>
+	<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources"/>
+	<classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
+	<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+	<classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER"/>
+	<classpathentry kind="output" path="target/classes"/>
+</classpath>
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-system/.project b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-system/.project
new file mode 100644
index 0000000..8351fb8
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-system/.project
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>legacyworlds-server-beans-system</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.maven.ide.eclipse.maven2Builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.maven.ide.eclipse.maven2Nature</nature>
+	</natures>
+</projectDescription>
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-system/.settings/org.eclipse.jdt.core.prefs b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-system/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..35c2ee3
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-system/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,6 @@
+#Tue Feb 23 12:51:19 CET 2010
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.6
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-system/.settings/org.maven.ide.eclipse.prefs b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-system/.settings/org.maven.ide.eclipse.prefs
new file mode 100644
index 0000000..b7fd985
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-system/.settings/org.maven.ide.eclipse.prefs
@@ -0,0 +1,9 @@
+#Tue Feb 23 12:51:19 CET 2010
+activeProfiles=
+eclipse.preferences.version=1
+fullBuildGoals=process-test-resources
+includeModules=false
+resolveWorkspaceProjects=true
+resourceFilterGoals=process-resources resources\:testResources
+skipCompilerPlugin=true
+version=1
diff --git a/legacyworlds-server-beans-system/pom.xml b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-system/pom.xml
similarity index 51%
rename from legacyworlds-server-beans-system/pom.xml
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-system/pom.xml
index e367674..593f8fb 100644
--- a/legacyworlds-server-beans-system/pom.xml
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-system/pom.xml
@@ -4,12 +4,12 @@
 	<parent>
 		<artifactId>legacyworlds-server-beans</artifactId>
 		<groupId>com.deepclone.lw</groupId>
-		<version>1.0.0</version>
-		<relativePath>../legacyworlds-server-beans/pom.xml</relativePath>
+		<version>5.99.2</version>
 	</parent>
 
+	<groupId>com.deepclone.lw</groupId>
 	<artifactId>legacyworlds-server-beans-system</artifactId>
-	<version>${legacyworlds.version.main}.${legacyworlds.version.release}-${legacyworlds.version.build}</version>
-	<name>Legacy Worlds - Server - Components - System</name>
-	<description>This module regroups system management components such as the constants manager.</description>
-</project>
+	<version>5.99.2</version>
+	<name>Legacy Worlds system management</name>
+	<description>This module regroups system management beans such as the constants manager.</description>
+</project>
\ No newline at end of file
diff --git a/legacyworlds-server-beans-system/src/main/java/com/deepclone/lw/beans/sys/ConstantsAdministrationImpl.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-system/src/main/java/com/deepclone/lw/beans/sys/ConstantsAdministrationImpl.java
similarity index 100%
rename from legacyworlds-server-beans-system/src/main/java/com/deepclone/lw/beans/sys/ConstantsAdministrationImpl.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-system/src/main/java/com/deepclone/lw/beans/sys/ConstantsAdministrationImpl.java
diff --git a/legacyworlds-server-beans-system/src/main/java/com/deepclone/lw/beans/sys/ConstantsData.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-system/src/main/java/com/deepclone/lw/beans/sys/ConstantsData.java
similarity index 97%
rename from legacyworlds-server-beans-system/src/main/java/com/deepclone/lw/beans/sys/ConstantsData.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-system/src/main/java/com/deepclone/lw/beans/sys/ConstantsData.java
index e63a517..2712a22 100644
--- a/legacyworlds-server-beans-system/src/main/java/com/deepclone/lw/beans/sys/ConstantsData.java
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-system/src/main/java/com/deepclone/lw/beans/sys/ConstantsData.java
@@ -14,10 +14,10 @@ import java.util.Set;
 
 import javax.sql.DataSource;
 
-import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.jdbc.core.RowMapper;
 import org.springframework.jdbc.core.SqlParameter;
 import org.springframework.jdbc.core.simple.SimpleJdbcCall;
+import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
 import org.springframework.transaction.TransactionStatus;
 import org.springframework.transaction.support.TransactionCallbackWithoutResult;
 import org.springframework.transaction.support.TransactionTemplate;
@@ -43,7 +43,7 @@ import com.deepclone.lw.utils.StoredProc;
 class ConstantsData
 {
 	/** Database interface */
-	private JdbcTemplate dTemplate;
+	private SimpleJdbcTemplate dTemplate;
 
 	/** Transaction manager interface */
 	private TransactionTemplate tTemplate;
@@ -85,7 +85,7 @@ class ConstantsData
 	 */
 	ConstantsData( DataSource dataSource , TransactionTemplate tTemplate , Logger logger )
 	{
-		this.dTemplate = new JdbcTemplate( dataSource );
+		this.dTemplate = new SimpleJdbcTemplate( dataSource );
 
 		this.uocConstantNoBounds = new SimpleJdbcCall( dataSource );
 		this.uocConstantNoBounds.withCatalogName( "sys" ).withFunctionName( "uoc_constant" );
@@ -93,7 +93,7 @@ class ConstantsData
 		this.uocConstantNoBounds.addDeclaredParameter( new SqlParameter( "cname" , Types.VARCHAR ) );
 		this.uocConstantNoBounds.addDeclaredParameter( new SqlParameter( "cdesc" , Types.VARCHAR ) );
 		this.uocConstantNoBounds.addDeclaredParameter( new SqlParameter( "catname" , Types.VARCHAR ) );
-		this.uocConstantNoBounds.addDeclaredParameter( new SqlParameter( "value" , Types.REAL ) );
+		this.uocConstantNoBounds.addDeclaredParameter( new SqlParameter( "value" , Types.DOUBLE ) );
 
 		this.uocConstantSingleBound = new SimpleJdbcCall( dataSource );
 		this.uocConstantSingleBound.withCatalogName( "sys" ).withFunctionName( "uoc_constant" );
@@ -101,8 +101,8 @@ class ConstantsData
 		this.uocConstantSingleBound.addDeclaredParameter( new SqlParameter( "cname" , Types.VARCHAR ) );
 		this.uocConstantSingleBound.addDeclaredParameter( new SqlParameter( "cdesc" , Types.VARCHAR ) );
 		this.uocConstantSingleBound.addDeclaredParameter( new SqlParameter( "catname" , Types.VARCHAR ) );
-		this.uocConstantSingleBound.addDeclaredParameter( new SqlParameter( "value" , Types.REAL ) );
-		this.uocConstantSingleBound.addDeclaredParameter( new SqlParameter( "boundary" , Types.REAL ) );
+		this.uocConstantSingleBound.addDeclaredParameter( new SqlParameter( "value" , Types.DOUBLE ) );
+		this.uocConstantSingleBound.addDeclaredParameter( new SqlParameter( "boundary" , Types.DOUBLE ) );
 		this.uocConstantSingleBound.addDeclaredParameter( new SqlParameter( "is_min" , Types.BOOLEAN ) );
 
 		this.uocConstantTwoBounds = new SimpleJdbcCall( dataSource );
@@ -111,13 +111,13 @@ class ConstantsData
 		this.uocConstantTwoBounds.addDeclaredParameter( new SqlParameter( "cname" , Types.VARCHAR ) );
 		this.uocConstantTwoBounds.addDeclaredParameter( new SqlParameter( "cdesc" , Types.VARCHAR ) );
 		this.uocConstantTwoBounds.addDeclaredParameter( new SqlParameter( "catname" , Types.VARCHAR ) );
-		this.uocConstantTwoBounds.addDeclaredParameter( new SqlParameter( "value" , Types.REAL ) );
-		this.uocConstantTwoBounds.addDeclaredParameter( new SqlParameter( "min" , Types.REAL ) );
-		this.uocConstantTwoBounds.addDeclaredParameter( new SqlParameter( "max" , Types.REAL ) );
+		this.uocConstantTwoBounds.addDeclaredParameter( new SqlParameter( "value" , Types.DOUBLE ) );
+		this.uocConstantTwoBounds.addDeclaredParameter( new SqlParameter( "min" , Types.DOUBLE ) );
+		this.uocConstantTwoBounds.addDeclaredParameter( new SqlParameter( "max" , Types.DOUBLE ) );
 
 		this.fSetConstant = new StoredProc( dataSource , "sys" , "set_constant" );
 		this.fSetConstant.addParameter( "cname" , Types.VARCHAR );
-		this.fSetConstant.addParameter( "value" , Types.REAL );
+		this.fSetConstant.addParameter( "value" , Types.DOUBLE );
 		this.fSetConstant.addParameter( "admin" , Types.INTEGER );
 
 		this.tTemplate = tTemplate;
@@ -149,8 +149,8 @@ class ConstantsData
 				c.setName( rs.getString( "name" ) );
 				c.setDescription( rs.getString( "description" ) );
 				c.setValue( rs.getDouble( "value" ) );
-				c.setMinValue( (Float) rs.getObject( "min" ) );
-				c.setMaxValue( (Float) rs.getObject( "max" ) );
+				c.setMinValue( (Double) rs.getObject( "min" ) );
+				c.setMaxValue( (Double) rs.getObject( "max" ) );
 				return c;
 			}
 
@@ -609,7 +609,7 @@ class ConstantsData
 				@Override
 				protected void doInTransactionWithoutResult( TransactionStatus status )
 				{
-					fSetConstant.execute( name , value.floatValue( ) , admin );
+					fSetConstant.execute( name , value , admin );
 				}
 
 			} );
diff --git a/legacyworlds-server-beans-system/src/main/java/com/deepclone/lw/beans/sys/ConstantsManagerBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-system/src/main/java/com/deepclone/lw/beans/sys/ConstantsManagerBean.java
similarity index 91%
rename from legacyworlds-server-beans-system/src/main/java/com/deepclone/lw/beans/sys/ConstantsManagerBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-system/src/main/java/com/deepclone/lw/beans/sys/ConstantsManagerBean.java
index 04064d3..6a73a8c 100644
--- a/legacyworlds-server-beans-system/src/main/java/com/deepclone/lw/beans/sys/ConstantsManagerBean.java
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-system/src/main/java/com/deepclone/lw/beans/sys/ConstantsManagerBean.java
@@ -1,8 +1,9 @@
 package com.deepclone.lw.beans.sys;
 
 
+import java.util.Arrays;
 import java.util.Collection;
-import java.util.Set;
+import java.util.HashSet;
 
 import javax.sql.DataSource;
 
@@ -92,9 +93,10 @@ public class ConstantsManagerBean
 
 	/* Documented in ConstantsManager interface */
 	@Override
-	public void registerUser( ConstantsUser user , Set< String > constants )
+	public void registerUser( ConstantsUser user , String... constants )
 	{
-		this.data.registerUser( user , constants );
+		HashSet< String > cSet = new HashSet< String >( Arrays.asList( constants ) );
+		this.data.registerUser( user , cSet );
 	}
 
 
@@ -112,4 +114,5 @@ public class ConstantsManagerBean
 	{
 		return new ConstantsAdministrationImpl( this.data , admin );
 	}
+
 }
diff --git a/legacyworlds-server-beans-system/src/main/java/com/deepclone/lw/beans/sys/ConstantsRegistrarBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-system/src/main/java/com/deepclone/lw/beans/sys/ConstantsRegistrarBean.java
similarity index 81%
rename from legacyworlds-server-beans-system/src/main/java/com/deepclone/lw/beans/sys/ConstantsRegistrarBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-system/src/main/java/com/deepclone/lw/beans/sys/ConstantsRegistrarBean.java
index 414ba46..cd8379e 100644
--- a/legacyworlds-server-beans-system/src/main/java/com/deepclone/lw/beans/sys/ConstantsRegistrarBean.java
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-system/src/main/java/com/deepclone/lw/beans/sys/ConstantsRegistrarBean.java
@@ -32,8 +32,6 @@ public class ConstantsRegistrarBean
 		// Misc. game-related values
 		cDesc = "Game updates - batch size.";
 		defs.add( new ConstantDefinition( "game.batchSize" , "Game (misc)" , cDesc , 20.0 , 1.0 , true ) );
-		cDesc = "Event processing - batch size.";
-		defs.add( new ConstantDefinition( "game.events.batchSize" , "Game (misc)" , cDesc , 100.0 , 1.0 , true ) );
 		cDesc = "Population growth factor.";
 		defs.add( new ConstantDefinition( "game.growthFactor" , "Game (misc)" , cDesc , 50.0 , 1.0 , true ) );
 		cDesc = "Increase to the population growth factor caused by reanimation centres.";
@@ -56,20 +54,6 @@ public class ConstantsRegistrarBean
 		cDesc = "Initial universe size (offset relative to the centre).";
 		defs.add( new ConstantDefinition( "game.universe.initialSize" , "Universe" , cDesc , 1.0 , 1.0 , true ) );
 
-		// Natural resources
-		cDesc = "Global recovery rate multiplier for natural resources. This should be kept close to 0.";
-		defs.add( new ConstantDefinition( "game.resources.recovery" , "Natural resources" , cDesc , 0.01 , 0.00001 ,
-				1.0 ) );
-		cDesc = "Resource recovery dampener. Lower means less dampening";
-		defs.add( new ConstantDefinition( "game.resources.recoveryDampening" , "Natural resources" , cDesc , 1.5 , 1.0 ,
-				true ) );
-		cDesc = "Resource weight base value. This value is taken to the Xth power to compute the actual "
-				+ "weight when determining how mining work is distributed amongst a planet's resource providers.";
-		defs.add( new ConstantDefinition( "game.resources.weightBase" , "Natural resources" , cDesc , 10.0 , 1.1 ,
-				100.0 ) );
-		cDesc = "Resources extracted per work unit, per (real) day, from a full provider with minimal difficulty.";
-		defs.add( new ConstantDefinition( "game.resources.extraction" , "Natural resources" , cDesc , 10.0 , 1.0 , true ) );
-
 		// Happiness
 		String[] hcNames = {
 				"noEmployment" , "employmentLimit" , "noDefence" , "defenceLimit" , "popPerDefencePoint" ,
@@ -96,7 +80,7 @@ public class ConstantsRegistrarBean
 		cDesc = "Empire size limit (relative to the ideal size) beyond which things get tough.";
 		defs.add( new ConstantDefinition( hcNames[ 7 ] , cat , cDesc , 2.0 , 1.1 , true ) );
 		cDesc = "Happiness level below which strikes begin.";
-		defs.add( new ConstantDefinition( hcNames[ 8 ] , cat , cDesc , 0.5 , 0.0 , 1.0 ) );
+		defs.add( new ConstantDefinition( hcNames[ 8 ] , cat , cDesc , 0.25 , 0.0 , 1.0 ) );
 		cDesc = "Happiness change at each update, relative to the size of the population.";
 		defs.add( new ConstantDefinition( hcNames[ 9 ] , cat , cDesc , 0.001 , 0.00001 , 0.99999 ) );
 		cDesc = "Maximal population units for which happiness will change.";
@@ -126,27 +110,6 @@ public class ConstantsRegistrarBean
 		cDesc = "Proportion of queue investments that is recovered when flushing the queue.";
 		defs.add( new ConstantDefinition( wcNames[ 6 ] , cat , cDesc , 0.1 , 0.01 , 1.0 ) );
 
-		// Research
-		String[] rcNames = {
-				"basePoints" , "visibility.points" , "visibility.ratio" , "weightBase" , "vacation"
-		};
-		for ( int i = 0 ; i < rcNames.length ; i++ ) {
-			rcNames[ i ] = "game.research." + rcNames[ i ];
-		}
-		cat = "Research & technologies";
-		cDesc = "Research points per population unit.";
-		defs.add( new ConstantDefinition( rcNames[ 0 ] , cat , cDesc , 0.50 , 0.01 , true ) );
-		cDesc = "Points above which a technology becomes visible.";
-		defs.add( new ConstantDefinition( rcNames[ 1 ] , cat , cDesc , 2500.0 , 0.01 , true ) );
-		cDesc = "Completion ratio above which a technology becomes visible.";
-		defs.add( new ConstantDefinition( rcNames[ 2 ] , cat , cDesc , 0.10 , 0.01 , 0.99 ) );
-		cDesc = "Technology weight base value. This value is taken to the Xth power (where X is a priority) "
-				+ "to compute the actual weight when determining how research points are distributed between "
-				+ "an empire's in-progress research.";
-		defs.add( new ConstantDefinition( rcNames[ 3 ] , cat , cDesc , 10.0 , 1.0 , true ) );
-		cDesc = "Research points multiplier used when the player is on vacation.";
-		defs.add( new ConstantDefinition( rcNames[ 4 ] , cat , cDesc , 0.1 , 0.01 , 0.99 ) );
-
 		// Vacation mode
 		cDesc = "Initial vacation credits.";
 		defs.add( new ConstantDefinition( "vacation.initial" , "Vacation mode" , cDesc , 4320.0 , 0.0 , true ) );
@@ -158,6 +121,8 @@ public class ConstantsRegistrarBean
 		defs.add( new ConstantDefinition( "vacation.cost" , "Vacation mode" , cDesc , 3.0 , 2.0 , 20.0 ) );
 		cDesc = "Income/upkeep divider used when vacation mode is active.";
 		defs.add( new ConstantDefinition( "vacation.cashDivider" , "Vacation mode" , cDesc , 3.0 , 1.1 , 10.0 ) );
+		cDesc = "Research points divider used when vacation mode is active.";
+		defs.add( new ConstantDefinition( "vacation.researchDivider" , "Vacation mode" , cDesc , 10.0 , 1.1 , 50.0 ) );
 
 		// Map names
 		cDesc = "Minimal delay between map object renaming.";
@@ -232,9 +197,13 @@ public class ConstantsRegistrarBean
 		cDesc = "Amount of credits granted for low priority bug reports.";
 		defs.add( new ConstantDefinition( "bugtracker.lowCredits" , "Bug tracking system" , cDesc , 1.0 , 1.0 , true ) );
 		cDesc = "Amount of credits granted for normal bug reports.";
-		defs.add( new ConstantDefinition( "bugtracker.mediumCredits" , "Bug tracking system" , cDesc , 2.0 , 1.0 , true ) );
+		defs
+				.add( new ConstantDefinition( "bugtracker.mediumCredits" , "Bug tracking system" , cDesc , 2.0 , 1.0 ,
+						true ) );
 		cDesc = "Amount of credits granted for critical bug reports.";
-		defs.add( new ConstantDefinition( "bugtracker.highCredits" , "Bug tracking system" , cDesc , 3.0 , 1.0 , true ) );
+		defs
+				.add( new ConstantDefinition( "bugtracker.highCredits" , "Bug tracking system" , cDesc , 3.0 , 1.0 ,
+						true ) );
 
 		cm.registerConstants( defs );
 	}
diff --git a/legacyworlds-server-beans-system/src/main/java/com/deepclone/lw/beans/sys/ServerSessionData.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-system/src/main/java/com/deepclone/lw/beans/sys/ServerSessionData.java
similarity index 100%
rename from legacyworlds-server-beans-system/src/main/java/com/deepclone/lw/beans/sys/ServerSessionData.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-system/src/main/java/com/deepclone/lw/beans/sys/ServerSessionData.java
diff --git a/legacyworlds-server-beans-system/src/main/java/com/deepclone/lw/beans/sys/SessionManagerBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-system/src/main/java/com/deepclone/lw/beans/sys/SessionManagerBean.java
similarity index 100%
rename from legacyworlds-server-beans-system/src/main/java/com/deepclone/lw/beans/sys/SessionManagerBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-system/src/main/java/com/deepclone/lw/beans/sys/SessionManagerBean.java
diff --git a/legacyworlds-server-beans-system/src/main/java/com/deepclone/lw/beans/sys/SystemStatusBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-system/src/main/java/com/deepclone/lw/beans/sys/SystemStatusBean.java
similarity index 85%
rename from legacyworlds-server-beans-system/src/main/java/com/deepclone/lw/beans/sys/SystemStatusBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-system/src/main/java/com/deepclone/lw/beans/sys/SystemStatusBean.java
index f3ddd7d..3d0631d 100644
--- a/legacyworlds-server-beans-system/src/main/java/com/deepclone/lw/beans/sys/SystemStatusBean.java
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-system/src/main/java/com/deepclone/lw/beans/sys/SystemStatusBean.java
@@ -9,10 +9,8 @@ import java.util.Map;
 import javax.sql.DataSource;
 
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.jdbc.core.RowMapper;
-import org.springframework.jdbc.core.SqlOutParameter;
-import org.springframework.jdbc.core.simple.SimpleJdbcCall;
+import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
 import org.springframework.transaction.PlatformTransactionManager;
 import org.springframework.transaction.TransactionStatus;
 import org.springframework.transaction.support.TransactionCallback;
@@ -33,7 +31,7 @@ public class SystemStatusBean
 {
 
 	/** Database interface */
-	private JdbcTemplate dTemplate;
+	private SimpleJdbcTemplate dTemplate;
 
 	/** Transaction template */
 	private TransactionTemplate tTemplate;
@@ -44,18 +42,19 @@ public class SystemStatusBean
 	/** Current maintenance mode record */
 	private MaintenanceData maintenance = null;
 
-	private SimpleJdbcCall doStartTick;
-	private SimpleJdbcCall doCheckTick;
-
 	private StoredProc fEnterMaintenanceMode;
 	private StoredProc fExtendMaintenanceMode;
 	private StoredProc fExitMaintenanceMode;
 
+	private StoredProc fCheckTick;
+	private StoredProc fStartTick;
+	private StoredProc fEndTick;
+
 
 	@Autowired( required = true )
 	public void setDataSource( DataSource dataSource )
 	{
-		this.dTemplate = new JdbcTemplate( dataSource );
+		this.dTemplate = new SimpleJdbcTemplate( dataSource );
 
 		this.fEnterMaintenanceMode = new StoredProc( dataSource , "sys" , "enter_maintenance_mode" );
 		this.fEnterMaintenanceMode.addParameter( "admin_id" , Types.INTEGER );
@@ -72,16 +71,14 @@ public class SystemStatusBean
 		this.fExitMaintenanceMode.addParameter( "admin_id" , Types.INTEGER );
 		this.fExitMaintenanceMode.addOutput( "success" , Types.BOOLEAN );
 
-		this.doStartTick = new SimpleJdbcCall( dataSource );
-		this.doStartTick.withCatalogName( "sys" ).withFunctionName( "start_tick" );
-		this.doStartTick.withoutProcedureColumnMetaDataAccess( );
-		this.doStartTick.addDeclaredParameter( new SqlOutParameter( "tick_id" , Types.BIGINT ) );
+		this.fCheckTick = new StoredProc( dataSource , "sys" , "check_stuck_tick" );
+		this.fCheckTick.addOutput( "tick_id" , Types.BIGINT );
 
-		this.doCheckTick = new SimpleJdbcCall( dataSource );
-		this.doCheckTick.withCatalogName( "sys" ).withFunctionName( "check_stuck_tick" );
-		this.doCheckTick.withoutProcedureColumnMetaDataAccess( );
-		this.doCheckTick.addDeclaredParameter( new SqlOutParameter( "tick_id" , Types.BIGINT ) );
+		this.fStartTick = new StoredProc( dataSource , "sys" , "start_tick" );
+		this.fStartTick.addOutput( "tick_id" , Types.BIGINT );
 
+		this.fEndTick = new StoredProc( dataSource , "sys" , "end_tick" );
+		this.fEndTick.addParameter( "tick_id" , Types.BIGINT );
 	}
 
 
@@ -246,6 +243,31 @@ public class SystemStatusBean
 	}
 
 
+	/* Documented in interface */
+	@Override
+	public Long checkStuckTick( )
+			throws MaintenanceStatusException
+	{
+		Long tid = this.tTemplate.execute( new TransactionCallback< Long >( ) {
+
+			@Override
+			public Long doInTransaction( TransactionStatus status )
+			{
+				Map< String , Object > m = fCheckTick.execute( );
+				loadStatus( );
+				return (Long) m.get( "tick_id" );
+			}
+
+		} );
+
+		if ( tid == null && this.maintenance != null ) {
+			throw new MaintenanceStatusException( this.maintenance );
+		}
+
+		return tid;
+	}
+
+
 	/* Documented in interface */
 	@Override
 	synchronized public long startTick( )
@@ -256,7 +278,7 @@ public class SystemStatusBean
 			@Override
 			public Long doInTransaction( TransactionStatus status )
 			{
-				Map< String , Object > m = doStartTick.execute( );
+				Map< String , Object > m = fStartTick.execute( );
 				loadStatus( );
 				return (Long) m.get( "tick_id" );
 			}
@@ -277,26 +299,28 @@ public class SystemStatusBean
 
 	/* Documented in interface */
 	@Override
-	public Long checkStuckTick( )
-			throws MaintenanceStatusException
+	public void endTick( )
+			throws TickStatusException , MaintenanceStatusException
 	{
-		Long tid = this.tTemplate.execute( new TransactionCallback< Long >( ) {
-
-			@Override
-			public Long doInTransaction( TransactionStatus status )
-			{
-				Map< String , Object > m = doCheckTick.execute( );
-				loadStatus( );
-				return (Long) m.get( "tick_id" );
-			}
-
-		} );
-
-		if ( tid == null && this.maintenance != null ) {
+		if ( this.maintenance != null ) {
 			throw new MaintenanceStatusException( this.maintenance );
 		}
 
-		return tid;
+		final Long tid = this.status.getCurrentTick( );
+		if ( tid == null ) {
+			throw new TickStatusException( );
+		}
+
+		this.tTemplate.execute( new TransactionCallbackWithoutResult( ) {
+
+			@Override
+			protected void doInTransactionWithoutResult( TransactionStatus status )
+			{
+				fEndTick.execute( tid );
+				loadStatus( );
+			}
+
+		} );
 	}
 
 }
diff --git a/legacyworlds-server-beans-system/src/main/java/com/deepclone/lw/beans/sys/TickerBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-system/src/main/java/com/deepclone/lw/beans/sys/TickerBean.java
similarity index 95%
rename from legacyworlds-server-beans-system/src/main/java/com/deepclone/lw/beans/sys/TickerBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-system/src/main/java/com/deepclone/lw/beans/sys/TickerBean.java
index b39d795..57d810d 100644
--- a/legacyworlds-server-beans-system/src/main/java/com/deepclone/lw/beans/sys/TickerBean.java
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-system/src/main/java/com/deepclone/lw/beans/sys/TickerBean.java
@@ -1,9 +1,6 @@
 package com.deepclone.lw.beans.sys;
 
 
-import java.util.HashSet;
-import java.util.Set;
-
 import org.springframework.beans.factory.DisposableBean;
 import org.springframework.beans.factory.InitializingBean;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -101,9 +98,7 @@ public class TickerBean
 		this.mainThread = new TickerThread( this.logger , this.tickerManager );
 
 		// Register thread as a constants user
-		Set< String > use = new HashSet< String >( );
-		use.add( "ticker.interval" );
-		this.constantsManager.registerUser( this.mainThread , use );
+		this.constantsManager.registerUser( this.mainThread , "ticker.interval" );
 	}
 
 
diff --git a/legacyworlds-server-beans-system/src/main/java/com/deepclone/lw/beans/sys/TickerManagerBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-system/src/main/java/com/deepclone/lw/beans/sys/TickerManagerBean.java
similarity index 97%
rename from legacyworlds-server-beans-system/src/main/java/com/deepclone/lw/beans/sys/TickerManagerBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-system/src/main/java/com/deepclone/lw/beans/sys/TickerManagerBean.java
index 54c7756..87a93ca 100644
--- a/legacyworlds-server-beans-system/src/main/java/com/deepclone/lw/beans/sys/TickerManagerBean.java
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-system/src/main/java/com/deepclone/lw/beans/sys/TickerManagerBean.java
@@ -17,8 +17,8 @@ import javax.sql.DataSource;
 
 import org.springframework.beans.factory.InitializingBean;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.jdbc.core.RowMapper;
+import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
 import org.springframework.transaction.PlatformTransactionManager;
 import org.springframework.transaction.TransactionStatus;
 import org.springframework.transaction.support.TransactionCallback;
@@ -42,7 +42,7 @@ public class TickerManagerBean
 	private final Set< Integer > registered = new HashSet< Integer >( );
 
 	private TransactionTemplate tTemplate;
-	private JdbcTemplate dTemplate;
+	private SimpleJdbcTemplate dTemplate;
 
 	private final RowMapper< TickerTaskRecord > mTask;
 
@@ -80,7 +80,7 @@ public class TickerManagerBean
 	@Autowired( required = true )
 	public void setDataSource( DataSource dataSource )
 	{
-		this.dTemplate = new JdbcTemplate( dataSource );
+		this.dTemplate = new SimpleJdbcTemplate( dataSource );
 
 		this.fRegisterTask = new StoredProc( dataSource , "sys" , "register_ticker_task" );
 		this.fRegisterTask.addParameter( "task_name" , Types.VARCHAR );
diff --git a/legacyworlds-server-beans-system/src/main/java/com/deepclone/lw/beans/sys/TickerTask.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-system/src/main/java/com/deepclone/lw/beans/sys/TickerTask.java
similarity index 100%
rename from legacyworlds-server-beans-system/src/main/java/com/deepclone/lw/beans/sys/TickerTask.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-system/src/main/java/com/deepclone/lw/beans/sys/TickerTask.java
diff --git a/legacyworlds-server-beans-system/src/main/java/com/deepclone/lw/beans/sys/TickerTaskStatusHandler.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-system/src/main/java/com/deepclone/lw/beans/sys/TickerTaskStatusHandler.java
similarity index 100%
rename from legacyworlds-server-beans-system/src/main/java/com/deepclone/lw/beans/sys/TickerTaskStatusHandler.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-system/src/main/java/com/deepclone/lw/beans/sys/TickerTaskStatusHandler.java
diff --git a/legacyworlds-server-beans-system/src/main/java/com/deepclone/lw/beans/sys/TickerThread.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-system/src/main/java/com/deepclone/lw/beans/sys/TickerThread.java
similarity index 100%
rename from legacyworlds-server-beans-system/src/main/java/com/deepclone/lw/beans/sys/TickerThread.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-system/src/main/java/com/deepclone/lw/beans/sys/TickerThread.java
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-system/src/main/resources/configuration/system-beans.xml b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-system/src/main/resources/configuration/system-beans.xml
new file mode 100644
index 0000000..7d0a16e
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-system/src/main/resources/configuration/system-beans.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="
+                        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
+
+	<import resource="system/constants-manager-bean.xml" />
+	<import resource="system/constants-registrar-bean.xml" />
+	<import resource="system/ticker-bean.xml" />
+	<import resource="system/session-manager-bean.xml" />
+	<import resource="system/system-status-bean.xml" />
+
+</beans>
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-system/src/main/resources/configuration/system/constants-manager-bean.xml b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-system/src/main/resources/configuration/system/constants-manager-bean.xml
new file mode 100644
index 0000000..3603ae6
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-system/src/main/resources/configuration/system/constants-manager-bean.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="
+                        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
+
+	<bean id="constantsManager" class="com.deepclone.lw.beans.sys.ConstantsManagerBean" />
+
+</beans>
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-system/src/main/resources/configuration/system/constants-registrar-bean.xml b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-system/src/main/resources/configuration/system/constants-registrar-bean.xml
new file mode 100644
index 0000000..3fa577d
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-system/src/main/resources/configuration/system/constants-registrar-bean.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="
+                        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
+
+	<bean id="constantsRegistrar" class="com.deepclone.lw.beans.sys.ConstantsRegistrarBean" />
+
+</beans>
diff --git a/legacyworlds-server-beans-system/src/main/resources/configuration/meta/system.xml b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-system/src/main/resources/configuration/system/session-manager-bean.xml
similarity index 54%
rename from legacyworlds-server-beans-system/src/main/resources/configuration/meta/system.xml
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-system/src/main/resources/configuration/system/session-manager-bean.xml
index 7728e8d..dcddd03 100644
--- a/legacyworlds-server-beans-system/src/main/resources/configuration/meta/system.xml
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-system/src/main/resources/configuration/system/session-manager-bean.xml
@@ -7,23 +7,15 @@
 	<bean id="authChallengeGenerator" class="com.deepclone.lw.utils.RandomStringGenerator">
 		<qualifier value="authChallenges" />
 		<property name="length" value="100" />
-		<property name="characterSet"
-			value="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" />
+		<property name="characterSet" value="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" />
 	</bean>
 
-	<bean id="constantsManager" class="com.deepclone.lw.beans.sys.ConstantsManagerBean" />
-	<bean id="constantsRegistrar" class="com.deepclone.lw.beans.sys.ConstantsRegistrarBean" />
-
 	<bean id="sessionIDGenerator" class="com.deepclone.lw.utils.RandomStringGenerator">
 		<qualifier value="sessionIdentifiers" />
 		<property name="length" value="50" />
-		<property name="characterSet"
-			value="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" />
+		<property name="characterSet" value="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" />
 	</bean>
 
 	<bean id="sessionManager" class="com.deepclone.lw.beans.sys.SessionManagerBean" />
-	<bean id="systemStatus" class="com.deepclone.lw.beans.sys.SystemStatusBean" />
-	<bean id="ticker" class="com.deepclone.lw.beans.sys.TickerBean" />
-	<bean id="tickerManager" class="com.deepclone.lw.beans.sys.TickerManagerBean" />
 
-</beans>
\ No newline at end of file
+</beans>
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-system/src/main/resources/configuration/system/system-status-bean.xml b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-system/src/main/resources/configuration/system/system-status-bean.xml
new file mode 100644
index 0000000..f8b97f4
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-system/src/main/resources/configuration/system/system-status-bean.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="
+                        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
+
+	<bean id="systemStatus" class="com.deepclone.lw.beans.sys.SystemStatusBean" />
+
+</beans>
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-system/src/main/resources/configuration/system/ticker-bean.xml b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-system/src/main/resources/configuration/system/ticker-bean.xml
new file mode 100644
index 0000000..894c846
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-system/src/main/resources/configuration/system/ticker-bean.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="
+                        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
+
+	<bean id="tickerManager" class="com.deepclone.lw.beans.sys.TickerManagerBean" />
+	<bean id="ticker" class="com.deepclone.lw.beans.sys.TickerBean" />
+
+</beans>
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-techs/.classpath b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-techs/.classpath
new file mode 100644
index 0000000..7c3d14f
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-techs/.classpath
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" output="target/classes" path="src/main/java"/>
+	<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources"/>
+	<classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
+	<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+	<classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER"/>
+	<classpathentry kind="output" path="target/classes"/>
+</classpath>
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-techs/.project b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-techs/.project
new file mode 100644
index 0000000..cc4857f
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-techs/.project
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>legacyworlds-server-beans-techs</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.maven.ide.eclipse.maven2Builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.maven.ide.eclipse.maven2Nature</nature>
+	</natures>
+</projectDescription>
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-techs/.settings/org.eclipse.jdt.core.prefs b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-techs/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..c2127c6
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-techs/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,6 @@
+#Mon Mar 28 09:14:01 CEST 2011
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.6
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-techs/.settings/org.maven.ide.eclipse.prefs b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-techs/.settings/org.maven.ide.eclipse.prefs
new file mode 100644
index 0000000..cdf9a81
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-techs/.settings/org.maven.ide.eclipse.prefs
@@ -0,0 +1,9 @@
+#Mon Mar 28 09:13:56 CEST 2011
+activeProfiles=
+eclipse.preferences.version=1
+fullBuildGoals=process-test-resources
+includeModules=false
+resolveWorkspaceProjects=true
+resourceFilterGoals=process-resources resources\:testResources
+skipCompilerPlugin=true
+version=1
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-techs/pom.xml b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-techs/pom.xml
new file mode 100644
index 0000000..12861da
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-techs/pom.xml
@@ -0,0 +1,15 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+	<parent>
+		<artifactId>legacyworlds-server-beans</artifactId>
+		<groupId>com.deepclone.lw</groupId>
+		<version>5.99.2</version>
+	</parent>
+
+	<groupId>com.deepclone.lw</groupId>
+	<artifactId>legacyworlds-server-beans-techs</artifactId>
+	<version>5.99.2</version>
+	<name>Legacy Worlds technology management</name>
+	<description>This package contains components which are used to manage technologies in LW games.</description>
+</project>
\ No newline at end of file
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-techs/src/main/java/com/deepclone/lw/beans/techs/EmpireTechnologyDAOBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-techs/src/main/java/com/deepclone/lw/beans/techs/EmpireTechnologyDAOBean.java
new file mode 100644
index 0000000..924142c
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-techs/src/main/java/com/deepclone/lw/beans/techs/EmpireTechnologyDAOBean.java
@@ -0,0 +1,160 @@
+package com.deepclone.lw.beans.techs;
+
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Types;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import javax.sql.DataSource;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.jdbc.core.RowMapper;
+import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
+
+import com.deepclone.lw.interfaces.game.techs.EmpireTechnologyDAO;
+import com.deepclone.lw.sqld.game.techs.EmpireTechnology;
+import com.deepclone.lw.utils.StoredProc;
+
+
+
+/**
+ * Implementation the empire technology and research data access component.
+ * 
+ * @author tseeker
+ */
+public class EmpireTechnologyDAOBean
+		implements EmpireTechnologyDAO
+{
+	/** SQL query that reads the list of an empire's technologies */
+	private static final String qGetTechnologies = "SELECT * FROM emp.technologies_view WHERE empire = ?";
+
+	/** SQL query that executes the priorities update preparation function */
+	private static final String qStartPrioritiesUpdate = "SELECT emp.prepare_research_priorities_update( )";
+
+	/** SQL query that inserts research priority changes into the temporary table */
+	private static final String qUploadPriorities = "INSERT INTO research_priorities_updates ( technology , priority ) "
+			+ "VALUES ( ? , ? )";
+
+	/** Data source access component */
+	private SimpleJdbcTemplate dTemplate;
+
+	/** Row mapper for empire technologies */
+	private RowMapper< EmpireTechnology > mEmpireTechnology;
+
+	/** Wrapper for the stored procedure that implements technologies */
+	private StoredProc fImplementTech;
+
+	/** Wrapper for the stored procedure to apply research priority updates */
+	private StoredProc fApplyResearchPriorities;
+
+
+	/** Initialise the row mapper */
+	public EmpireTechnologyDAOBean( )
+	{
+		this.mEmpireTechnology = new RowMapper< EmpireTechnology >( ) {
+
+			@Override
+			public EmpireTechnology mapRow( ResultSet rs , int rowNum )
+					throws SQLException
+			{
+				int techId = rs.getInt( "technology_id" );
+				String techName = rs.getString( "technology" );
+				boolean detailed = rs.getBoolean( "detailed" );
+				Integer completion = (Integer) rs.getObject( "completion" );
+				Integer cost = (Integer) rs.getObject( "cost" );
+				Integer priority = (Integer) rs.getObject( "priority" );
+
+				EmpireTechnology result;
+				if ( !detailed ) {
+					result = new EmpireTechnology( techId * rs.getInt( "empire" ) , techName , completion , priority );
+				} else if ( completion != null ) {
+					result = new EmpireTechnology( techName , completion , priority );
+				} else if ( cost != null ) {
+					result = new EmpireTechnology( techName , cost );
+				} else {
+					result = new EmpireTechnology( techName );
+				}
+				return result;
+			}
+
+		};
+	}
+
+
+	/**
+	 * Dependency injector that initialises the database access component and stored procedure
+	 * wrappers.
+	 * 
+	 * @param dataSource
+	 *            the data source
+	 */
+	@Autowired( required = true )
+	public void setDataSource( DataSource dataSource )
+	{
+		this.dTemplate = new SimpleJdbcTemplate( dataSource );
+
+		// Stored procedure for technology implementation
+		this.fImplementTech = new StoredProc( dataSource , "emp" , "implement_tech" );
+		this.fImplementTech.addParameter( "empire_id" , Types.INTEGER );
+		this.fImplementTech.addParameter( "technology" , Types.VARCHAR );
+		this.fImplementTech.addOutput( "error_code" , Types.INTEGER );
+
+		// Stored procedure to apply research priority updates
+		this.fApplyResearchPriorities = new StoredProc( dataSource , "emp" , "apply_research_priorities" );
+		this.fApplyResearchPriorities.addParameter( "empire_id" , Types.INTEGER );
+		this.fApplyResearchPriorities.addOutput( "error_code" , Types.INTEGER );
+	}
+
+
+	/* Documentation in EmpireTechnologyDAO interface */
+	@Override
+	public List< EmpireTechnology > getTechnologies( int empireId )
+	{
+		return this.dTemplate.query( qGetTechnologies , this.mEmpireTechnology , empireId );
+	}
+
+
+	/* Documentation in EmpireTechnologyDAO interface */
+	@Override
+	public int implementTechnology( int empireId , String technology )
+	{
+		return (Integer) this.fImplementTech.execute( empireId , technology ).get( "error_code" );
+	}
+
+
+	/* Documentation in EmpireTechnologyDAO interface */
+	@Override
+	public void startPrioritiesUpdate( )
+	{
+		this.dTemplate.queryForList( qStartPrioritiesUpdate );
+	}
+
+
+	/* Documentation in EmpireTechnologyDAO interface */
+	@Override
+	public void uploadPriorities( Map< String , Integer > priorities )
+	{
+		List< Object[] > batch = new ArrayList< Object[] >( priorities.size( ) );
+		int counter = 0;
+		for ( Entry< String , Integer > entry : priorities.entrySet( ) ) {
+			Object[] values = new Object[] {
+					entry.getKey( ) , entry.getValue( )
+			};
+			batch.add( counter++ , values );
+		}
+		this.dTemplate.batchUpdate( qUploadPriorities , batch );
+	}
+
+
+	/* Documentation in EmpireTechnologyDAO interface */
+	@Override
+	public int finishPrioritiesUpdate( int empireId )
+	{
+		return (Integer) this.fApplyResearchPriorities.execute( empireId ).get( "error_code" );
+	}
+
+}
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-techs/src/main/java/com/deepclone/lw/beans/techs/EmpireTechnologyManagerBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-techs/src/main/java/com/deepclone/lw/beans/techs/EmpireTechnologyManagerBean.java
new file mode 100644
index 0000000..ab85d96
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-techs/src/main/java/com/deepclone/lw/beans/techs/EmpireTechnologyManagerBean.java
@@ -0,0 +1,181 @@
+package com.deepclone.lw.beans.techs;
+
+
+import java.util.Arrays;
+import java.util.Map;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+
+import com.deepclone.lw.cmd.player.research.ResearchOperationResponse;
+import com.deepclone.lw.cmd.player.research.ViewResearchResponse;
+import com.deepclone.lw.interfaces.game.EmpireManagement;
+import com.deepclone.lw.interfaces.game.techs.EmpireTechnologyDAO;
+import com.deepclone.lw.interfaces.game.techs.EmpireTechnologyManager;
+import com.deepclone.lw.interfaces.game.techs.TechnologyGraphManager;
+import com.deepclone.lw.interfaces.sys.ConstantDefinition;
+import com.deepclone.lw.interfaces.sys.ConstantsManager;
+
+
+
+/**
+ * Implementation of the empire technology and research management component.
+ * 
+ * @author tseeker
+ */
+@Transactional
+public class EmpireTechnologyManagerBean
+		implements EmpireTechnologyManager
+{
+	/** Empire management component */
+	private EmpireManagement empireManager;
+
+	/** Data access component for empire technologies and research */
+	private EmpireTechnologyDAO empireTechnologyDAO;
+
+	/** Technology graph management component */
+	private TechnologyGraphManager techGraphManager;
+
+
+	/**
+	 * Dependency injector for the empire management component.
+	 * 
+	 * @param empireManager
+	 *            the empire management component
+	 */
+	@Autowired( required = true )
+	public void setEmpireManager( EmpireManagement empireManager )
+	{
+		this.empireManager = empireManager;
+	}
+
+
+	/**
+	 * Dependency injector for the data access component for empire technologies and research
+	 * 
+	 * @param empireTechnologyDAO
+	 *            data access component for empire technologies and research
+	 */
+	@Autowired( required = true )
+	public void setEmpireTechnologyDAO( EmpireTechnologyDAO empireTechnologyDAO )
+	{
+		this.empireTechnologyDAO = empireTechnologyDAO;
+	}
+
+
+	/**
+	 * Dependency injector for the technology graph management component.
+	 * 
+	 * @param techGraphManager
+	 *            the technology graph management component
+	 */
+	@Autowired( required = true )
+	public void setTechnologyGraphManager( TechnologyGraphManager techGraphManager )
+	{
+		this.techGraphManager = techGraphManager;
+	}
+
+
+	/**
+	 * Dependency injector which registers research-related constants into the constants manager.
+	 * 
+	 * @param constantsManager
+	 *            the constants manager component
+	 */
+	@Autowired( required = true )
+	public void setConstantsManager( ConstantsManager constantsManager )
+	{
+		ConstantDefinition[] definitions = new ConstantDefinition[] {
+				new ConstantDefinition( "game.research.minPoints" , "Research" ,
+						"Minimal research points before a technology being researched is identified" , 50000.0 , 1.0 ,
+						true ) ,
+				new ConstantDefinition( "game.research.minRatio" , "Research" ,
+						"Minimal ratio before a technology being researched is identified" , 0.75 , 0.01 , 0.99 ) ,
+				new ConstantDefinition( "game.research.perPopUnit" , "Research" ,
+						"Research points per population unit." , 0.50 , 0.01 , true )
+		};
+		constantsManager.registerConstants( Arrays.asList( definitions ) );
+	}
+
+
+	/* Documentation in EmpireTechnologyManager interface */
+	@Override
+	public ViewResearchResponse getResearchData( int empireId )
+	{
+		return new ResearchResponseBuilder( empireId , this.empireManager , this.empireTechnologyDAO ,
+				this.techGraphManager ).getResponse( );
+	}
+
+
+	/* Documentation in EmpireTechnologyManager interface */
+	@Override
+	public ResearchOperationResponse implementTechnology( int empireId , String technology )
+	{
+		int result = this.empireTechnologyDAO.implementTechnology( empireId , technology );
+		ResearchOperationResponse response;
+
+		if ( result == 0 ) {
+			response = new ResearchOperationResponse( );
+		} else {
+			ResearchResponseBuilder builder = new ResearchResponseBuilder( empireId , this.empireManager ,
+					this.empireTechnologyDAO , this.techGraphManager );
+			switch ( result ) {
+
+				case 1:
+					response = builder.getResponse( ResearchOperationResponse.Result.ERR_RESOURCES );
+					break;
+
+				case 2:
+					response = builder.getResponse( ResearchOperationResponse.Result.ERR_STATE_CHANGED );
+					break;
+
+				default:
+					throw new RuntimeException( "unsupported return value " + result );
+
+			}
+		}
+
+		return response;
+	}
+
+
+	/* Documentation in EmpireTechnologyManager interface */
+	@Override
+	public ResearchOperationResponse setResearchPriorities( int empireId , Map< String , Integer > priorities )
+	{
+		int result;
+		if ( priorities.size( ) < 2 ) {
+			result = 2;
+		} else {
+			this.empireTechnologyDAO.startPrioritiesUpdate( );
+			this.empireTechnologyDAO.uploadPriorities( priorities );
+			result = this.empireTechnologyDAO.finishPrioritiesUpdate( empireId );
+		}
+
+		ResearchOperationResponse response;
+		if ( result == 0 ) {
+			response = new ResearchOperationResponse( );
+		} else {
+			ResearchResponseBuilder builder = new ResearchResponseBuilder( empireId , this.empireManager ,
+					this.empireTechnologyDAO , this.techGraphManager );
+
+			switch ( result ) {
+
+				case 1:
+					response = builder.getResponse( ResearchOperationResponse.Result.ERR_STATE_CHANGED );
+					break;
+
+				case 2:
+					response = builder.getResponse( ResearchOperationResponse.Result.ERR_INVALID );
+					break;
+
+				default:
+					throw new RuntimeException( "unsupported return value " + result );
+
+			}
+		}
+
+		return response;
+	}
+
+}
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-techs/src/main/java/com/deepclone/lw/beans/techs/EmpireUpdate.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-techs/src/main/java/com/deepclone/lw/beans/techs/EmpireUpdate.java
new file mode 100644
index 0000000..c32ebba
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-techs/src/main/java/com/deepclone/lw/beans/techs/EmpireUpdate.java
@@ -0,0 +1,293 @@
+package com.deepclone.lw.beans.techs;
+
+
+import java.util.Collection;
+import java.util.EnumMap;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import com.deepclone.lw.cmd.admin.logs.LogLevel;
+import com.deepclone.lw.interfaces.eventlog.SystemLogger;
+import com.deepclone.lw.sqld.game.techs.ResearchStatus;
+import com.deepclone.lw.sqld.game.techs.ResearchUpdateInput;
+import com.deepclone.lw.sqld.game.techs.ResearchUpdateOutput;
+import com.deepclone.lw.sqld.game.techs.TechGraph;
+import com.deepclone.lw.sqld.game.techs.TechGraphException;
+import com.deepclone.lw.sqld.game.techs.Technology;
+
+
+
+/**
+ * Research update implementation for a single empire.
+ * 
+ * @author tseeker
+ */
+class EmpireUpdate
+{
+	/** Empire identifier */
+	private final int id;
+
+	/** Research points produced */
+	private double production;
+
+	/** All technologies (known or being researched) */
+	private final Map< String , ResearchUpdateInput > byName;
+
+	/** Technology names by status */
+	private final Map< ResearchStatus , Set< String >> byStatus;
+
+	/** Output records by name */
+	private final Map< String , ResearchUpdateOutput > output;
+
+	/** Sum of the current research priorities */
+	private double totalPriority;
+
+	/** Amount of active research topics */
+	private int activeTopics;
+
+	/** Parent component's logging interface */
+	private SystemLogger logger;
+
+
+	/**
+	 * Initialise the empire updater using the global lists of production points and research
+	 * statuses.
+	 * 
+	 * @param logger
+	 *            the component's logging system
+	 * @param empireId
+	 *            the empire for whom the research update is to be computed
+	 * @param production
+	 *            the map of production points for all empires in the batch
+	 * @param status
+	 *            the list of statuses for all empires in the batch
+	 */
+	EmpireUpdate( SystemLogger logger , int empireId , Map< Integer , Double > production ,
+			HashMap< Integer , List< ResearchUpdateInput >> status )
+	{
+		this.id = empireId;
+		this.production = production.get( this.id );
+		this.logger = logger;
+
+		this.byName = new HashMap< String , ResearchUpdateInput >( );
+		this.output = new HashMap< String , ResearchUpdateOutput >( );
+
+		this.byStatus = new EnumMap< ResearchStatus , Set< String > >( ResearchStatus.class );
+		this.byStatus.put( ResearchStatus.IN_PROGRESS , new HashSet< String >( ) );
+		this.byStatus.put( ResearchStatus.RESEARCHED , new HashSet< String >( ) );
+		this.byStatus.put( ResearchStatus.IMPLEMENTED , new HashSet< String >( ) );
+
+		// Initialise sets and maps
+		List< ResearchUpdateInput > empStatus = status.get( this.id );
+		if ( empStatus != null ) {
+			for ( ResearchUpdateInput entry : status.get( this.id ) ) {
+				this.byName.put( entry.getTechnology( ) , entry );
+				this.byStatus.get( entry.getStatus( ) ).add( entry.getTechnology( ) );
+			}
+			this.logger.flush( );
+		}
+	}
+
+
+	/**
+	 * Perform the research update, filling the {@link #output} map.
+	 * 
+	 * @param techGraph
+	 *            the technology graph
+	 * @throws TechGraphException
+	 *             indicates an internal error
+	 */
+	void compute( TechGraph techGraph )
+			throws TechGraphException
+	{
+		if ( this.production == 0 ) {
+			return;
+		}
+		this.prepareOutput( );
+
+		List< Technology > newResearch = this.findNewTechnologies( techGraph );
+		if ( !newResearch.isEmpty( ) ) {
+			this.addResearch( newResearch );
+		}
+		if ( this.output.isEmpty( ) ) {
+			return;
+		}
+
+		List< String > inProgress = new LinkedList< String >( this.output.keySet( ) );
+		for ( String resName : inProgress ) {
+			this.researchProgress( techGraph.getTechnology( resName ) , resName );
+		}
+
+		this.updatePriorities( );
+	}
+
+
+	/**
+	 * Copy information from the list of research to the output map.
+	 */
+	private void prepareOutput( )
+	{
+		this.totalPriority = 0;
+		for ( ResearchUpdateInput entry : this.byName.values( ) ) {
+			if ( entry.getStatus( ) != ResearchStatus.IN_PROGRESS ) {
+				continue;
+			}
+			this.output.put( entry.getTechnology( ) , new ResearchUpdateOutput( this.id , entry.getTechnology( ) ,
+					false , entry.getPoints( ) , entry.getPriority( ) ) );
+			this.totalPriority += entry.getPriority( );
+		}
+		this.activeTopics = this.byStatus.get( ResearchStatus.IN_PROGRESS ).size( );
+	}
+
+
+	/**
+	 * Find new technologies to research
+	 * 
+	 * XXX: we shouldn't be doing that at every update; it's only required if the techs were added
+	 * or deleted, if dependencies were changed or if the empire implemented a technology.
+	 * 
+	 * @param techGraph
+	 *            the technology graph
+	 * @return the list of technologies on which research can start
+	 * @throws TechGraphException
+	 *             indicates an internal error
+	 */
+	private List< Technology > findNewTechnologies( TechGraph techGraph )
+			throws TechGraphException
+	{
+		LinkedList< Technology > newResearch = new LinkedList< Technology >( );
+		Set< String > implemented = this.byStatus.get( ResearchStatus.IMPLEMENTED );
+		if ( implemented == null ) {
+			throw new RuntimeException( "wtf?!" );
+		}
+		for ( String catName : techGraph.getCategories( ) ) {
+			for ( String techName : techGraph.getCategory( catName ).getTechnologies( ) ) {
+				// Check if the empire "knows" of the tech
+				if ( this.byName.containsKey( techName ) ) {
+					continue;
+				}
+
+				// Check dependencies
+				Technology tech = techGraph.getTechnology( techName );
+				boolean mayStart = true;
+				for ( String depName : tech.getDependencies( ) ) {
+					if ( !implemented.contains( depName ) ) {
+						mayStart = false;
+						break;
+					}
+				}
+
+				if ( mayStart ) {
+					newResearch.add( tech );
+				}
+			}
+		}
+		return newResearch;
+	}
+
+
+	/**
+	 * Add new entries to the list of current research topics and updates the total priority
+	 * accordingly.
+	 * 
+	 * @param newResearch
+	 *            the list of research topics to add
+	 */
+	private void addResearch( List< Technology > newResearch )
+	{
+		int increment;
+		if ( this.totalPriority == 0 ) {
+			increment = 1;
+		} else {
+			increment = (int) Math.ceil( this.totalPriority / this.activeTopics );
+		}
+
+		for ( Technology tech : newResearch ) {
+			this.output.put( tech.getName( ) , new ResearchUpdateOutput( this.id , tech.getName( ) , true , 0 ,
+					increment ) );
+			this.totalPriority += increment;
+		}
+		this.activeTopics += newResearch.size( );
+	}
+
+
+	/**
+	 * Update the progress on a research topic.
+	 * 
+	 * @param technology
+	 *            the technology's definition
+	 * @param name
+	 *            the name of the research topic
+	 */
+	private void researchProgress( Technology technology , String name )
+	{
+		ResearchUpdateOutput entry = this.output.get( name );
+		if ( entry.getPriority( ) == 0 ) {
+			return;
+		}
+
+		double points = this.production * entry.getPriority( ) / this.totalPriority;
+		double total = points + entry.getPoints( );
+
+		if ( total >= technology.getPoints( ) ) {
+			this.totalPriority -= entry.getPriority( );
+			this.production = this.production + total - entry.getPoints( );
+			this.output.put( name , new ResearchUpdateOutput( this.id , name ) );
+			this.activeTopics--;
+		} else {
+			entry.addPoints( points );
+		}
+	}
+
+
+	/**
+	 * Update priorities of active research topics in the output map.
+	 */
+	private void updatePriorities( )
+	{
+		if ( this.activeTopics == 0 || this.totalPriority == 100 ) {
+			return;
+		}
+
+		List< ResearchUpdateOutput > progress = new LinkedList< ResearchUpdateOutput >( );
+		int newTotal = 0;
+		for ( ResearchUpdateOutput update : this.output.values( ) ) {
+			Integer prio = update.getPriority( );
+			if ( prio == null ) {
+				continue;
+			}
+
+			int newValue = (int) Math.floor( 100.0 * prio / this.totalPriority );
+			progress.add( update );
+			update.setPriority( newValue );
+			newTotal += newValue;
+		}
+
+		// Distribute the rest of the points
+		while ( newTotal < 100 ) {
+			for ( ResearchUpdateOutput update : progress ) {
+				update.setPriority( update.getPriority( ) + 1 );
+				newTotal++;
+				if ( newTotal == 100 ) {
+					break;
+				}
+			}
+		}
+		this.logger.flush( );
+	}
+
+
+	/** @return the update output records */
+	Collection< ResearchUpdateOutput > getOutput( )
+	{
+		if ( !this.output.isEmpty( ) ) {
+			this.logger.log( LogLevel.TRACE , "Empire " + this.id + " - " + this.output.size( ) + " update(s)" )
+					.flush( );
+		}
+		return this.output.values( );
+	}
+}
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-techs/src/main/java/com/deepclone/lw/beans/techs/ResearchResponseBuilder.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-techs/src/main/java/com/deepclone/lw/beans/techs/ResearchResponseBuilder.java
new file mode 100644
index 0000000..1c24a1f
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-techs/src/main/java/com/deepclone/lw/beans/techs/ResearchResponseBuilder.java
@@ -0,0 +1,280 @@
+package com.deepclone.lw.beans.techs;
+
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import com.deepclone.lw.cmd.player.gdata.GamePageData;
+import com.deepclone.lw.cmd.player.gdata.empire.ResearchData;
+import com.deepclone.lw.cmd.player.gdata.empire.TechnologyCategoryData;
+import com.deepclone.lw.cmd.player.gdata.empire.TechnologyData;
+import com.deepclone.lw.cmd.player.research.ResearchOperationResponse;
+import com.deepclone.lw.cmd.player.research.ViewResearchResponse;
+import com.deepclone.lw.cmd.player.research.ResearchOperationResponse.Result;
+import com.deepclone.lw.interfaces.game.EmpireManagement;
+import com.deepclone.lw.interfaces.game.techs.EmpireTechnologyDAO;
+import com.deepclone.lw.interfaces.game.techs.TechnologyGraphManager;
+import com.deepclone.lw.interfaces.i18n.LanguageTranslator;
+import com.deepclone.lw.interfaces.i18n.UnknownStringException;
+import com.deepclone.lw.sqld.game.techs.Category;
+import com.deepclone.lw.sqld.game.techs.EmpireTechnology;
+import com.deepclone.lw.sqld.game.techs.ResearchStatus;
+import com.deepclone.lw.sqld.game.techs.TechGraph;
+import com.deepclone.lw.sqld.game.techs.TechGraphException;
+import com.deepclone.lw.sqld.game.techs.Technology;
+
+
+
+/**
+ * Class that builds {@link ViewResearchResponse} or {@link ResearchOperationResponse} instances.
+ * 
+ * @author tseeker
+ */
+class ResearchResponseBuilder
+{
+
+	/** Empire identifier */
+	private final int empireId;
+
+	/** Empire management component */
+	private final EmpireManagement empireManager;
+
+	/** Technology and research data access component */
+	private final EmpireTechnologyDAO empireTechnologyDAO;
+
+	/** Technology graph management component */
+	private final TechnologyGraphManager techGraphManager;
+
+	/** Game page data */
+	private GamePageData pageData;
+
+	/** List of current research topics */
+	private List< ResearchData > research;
+
+	/** Lists of implemented technologies by category */
+	private Map< String , List< TechnologyData > > implementedMap;
+
+	/** Final list of implemented technologies */
+	private List< TechnologyCategoryData > implementedLists;
+
+	/** All implemented technologies by identifier */
+	private Map< String , TechnologyData > implementedById;
+
+
+	/**
+	 * Initialise the response builder by setting the empire identifier and the various components
+	 * that may be required to generate the response.
+	 * 
+	 * @param empireId
+	 *            the empire identifier
+	 * @param empireManager
+	 *            the empire management component
+	 * @param empireTechnologyDAO
+	 *            the technology and research data access component
+	 * @param techGraphManager
+	 *            the technology graph management component
+	 */
+	ResearchResponseBuilder( int empireId , EmpireManagement empireManager , EmpireTechnologyDAO empireTechnologyDAO ,
+			TechnologyGraphManager techGraphManager )
+	{
+		this.empireId = empireId;
+		this.empireManager = empireManager;
+		this.empireTechnologyDAO = empireTechnologyDAO;
+		this.techGraphManager = techGraphManager;
+	}
+
+
+	/**
+	 * Build a basic research view response.
+	 * 
+	 * @return the research view response.
+	 */
+	ViewResearchResponse getResponse( )
+	{
+		try {
+			this.buildResponseContents( );
+		} catch ( Exception e ) {
+			throw new RuntimeException( "internal error while processing research data" , e );
+		}
+		return new ViewResearchResponse( this.pageData , this.research , this.implementedLists );
+	}
+
+
+	/**
+	 * Build a research operation response.
+	 * 
+	 * @param errorCode
+	 *            the operation's error code (should not be
+	 *            {@link ResearchOperationResponse.Result#OK}).
+	 * @return the research operation response.
+	 */
+	ResearchOperationResponse getResponse( Result errorCode )
+	{
+		try {
+			this.buildResponseContents( );
+		} catch ( Exception e ) {
+			throw new RuntimeException( "internal error while processing research data" , e );
+		}
+		return new ResearchOperationResponse( this.pageData , this.research , this.implementedLists , errorCode );
+	}
+
+
+	/**
+	 * Build the lists and records required by research view or operation responses. This includes
+	 * the list of current research topics as well as the list of implemented technologies.
+	 * 
+	 * @throws UnknownStringException
+	 *             if there is an incoherence between the tech graph and the translations database.
+	 * @throws TechGraphException
+	 *             if there is an incoherence between the empire research records and the tech
+	 *             graph.
+	 */
+	private void buildResponseContents( )
+			throws UnknownStringException , TechGraphException
+	{
+		LanguageTranslator translator = this.empireManager.getTranslator( this.empireId );
+		TechGraph techGraph = this.techGraphManager.getGraph( );
+
+		this.research = new LinkedList< ResearchData >( );
+		this.implementedMap = new HashMap< String , List< TechnologyData > >( );
+		this.implementedById = new HashMap< String , TechnologyData >( );
+
+		for ( EmpireTechnology record : this.empireTechnologyDAO.getTechnologies( this.empireId ) ) {
+			if ( record.getStatus( ) == ResearchStatus.IMPLEMENTED ) {
+				this.addImplemented( record , translator , techGraph );
+			} else {
+				this.addResearchData( record , translator , techGraph );
+			}
+		}
+
+		this.pageData = this.empireManager.getGeneralInformation( this.empireId );
+		Collections.sort( this.research );
+		this.postProcessImplemented( translator , techGraph );
+	}
+
+
+	/**
+	 * Add an implemented technology record.
+	 * 
+	 * @param record
+	 *            the original record as returned by the {@link EmpireTechnologyDAO}.
+	 * @param translator
+	 *            the translator for the empire's language
+	 * @param techGraph
+	 *            the technology graph
+	 * 
+	 * @throws TechGraphException
+	 *             if there is an incoherence between the empire research records and the tech
+	 *             graph.
+	 * @throws UnknownStringException
+	 *             if there is an incoherence between the tech graph and the translations database.
+	 */
+	private void addImplemented( EmpireTechnology record , LanguageTranslator translator , TechGraph techGraph )
+			throws TechGraphException , UnknownStringException
+	{
+		String techId = record.getIdentifier( );
+		Technology tech = techGraph.getTechnology( techId );
+		Category category = tech.getCategory( );
+
+		List< TechnologyData > catTechs = this.implementedMap.get( category.getName( ) );
+		if ( catTechs == null ) {
+			catTechs = new LinkedList< TechnologyData >( );
+			this.implementedMap.put( category.getName( ) , catTechs );
+		}
+
+		TechnologyData tData;
+		String name = translator.translate( techId );
+		String description = translator.translate( tech.getDescription( ) );
+		tData = new TechnologyData( techId , name , description , tech.getDependencies( ) , new LinkedList< String >( ) );
+
+		catTechs.add( tData );
+		this.implementedById.put( techId , tData );
+	}
+
+
+	/**
+	 * Add a research topic record.
+	 * 
+	 * @param record
+	 *            the original record as returned by the {@link EmpireTechnologyDAO}.
+	 * @param translator
+	 *            the translator for the empire's language
+	 * @param techGraph
+	 *            the technology graph
+	 * 
+	 * @throws TechGraphException
+	 *             if there is an incoherence between the empire research records and the tech
+	 *             graph.
+	 * @throws UnknownStringException
+	 *             if there is an incoherence between the tech graph and the translations database.
+	 */
+	private void addResearchData( EmpireTechnology record , LanguageTranslator translator , TechGraph techGraph )
+			throws TechGraphException , UnknownStringException
+	{
+		String techId = record.getIdentifier( );
+		Technology tech = techGraph.getTechnology( techId );
+		String category = translator.translate( tech.getCategory( ).getName( ) );
+
+		ResearchData rData;
+
+		if ( !record.isDetailed( ) ) {
+			rData = new ResearchData( record.getNumericId( ) , category , record.getPercentage( ) , record
+					.getPriority( ) );
+		} else {
+			String name = translator.translate( techId );
+			String description = translator.translate( tech.getDescription( ) );
+			String[] dependencies = tech.getDependencies( ).toArray( new String[] { } );
+			if ( record.getStatus( ) == ResearchStatus.RESEARCHED ) {
+				rData = new ResearchData( techId , category , name , description , dependencies , (int) tech.getCost( ) );
+			} else {
+				rData = new ResearchData( techId , category , name , description , dependencies , record
+						.getPercentage( ) , record.getPriority( ) );
+			}
+		}
+
+		this.research.add( rData );
+	}
+
+
+	/**
+	 * Post-process implemented technologies by adding reverse dependencies, sorting each list, and
+	 * generating the sorted list of technology categories.
+	 * 
+	 * @param translator
+	 *            the translator for the empire's language
+	 * @param techGraph
+	 *            the technology graph
+	 * 
+	 * @throws TechGraphException
+	 *             if there is an incoherence between the empire research records and the tech
+	 *             graph.
+	 * @throws UnknownStringException
+	 *             if there is an incoherence between the tech graph and the translations database.
+	 */
+	private void postProcessImplemented( LanguageTranslator translator , TechGraph techGraph )
+			throws UnknownStringException , TechGraphException
+	{
+		this.implementedLists = new LinkedList< TechnologyCategoryData >( );
+		for ( String catId : this.implementedMap.keySet( ) ) {
+
+			List< TechnologyData > techs = this.implementedMap.get( catId );
+			for ( TechnologyData tData : techs ) {
+				for ( String dependency : tData.getDependsOn( ) ) {
+					TechnologyData depData = this.implementedById.get( dependency );
+					if ( depData != null ) {
+						depData.getDependencyOf( ).add( tData.getIdentifier( ) );
+					}
+				}
+			}
+			Collections.sort( techs );
+
+			String catName = translator.translate( catId );
+			String catDesc = translator.translate( techGraph.getCategory( catId ).getDescription( ) );
+			this.implementedLists.add( new TechnologyCategoryData( catName , catDesc , techs ) );
+		}
+		Collections.sort( this.implementedLists );
+	}
+}
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-techs/src/main/java/com/deepclone/lw/beans/techs/ResearchUpdateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-techs/src/main/java/com/deepclone/lw/beans/techs/ResearchUpdateBean.java
new file mode 100644
index 0000000..f499a3a
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-techs/src/main/java/com/deepclone/lw/beans/techs/ResearchUpdateBean.java
@@ -0,0 +1,180 @@
+package com.deepclone.lw.beans.techs;
+
+
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import org.springframework.beans.factory.annotation.Autowired;
+
+import com.deepclone.lw.interfaces.eventlog.Logger;
+import com.deepclone.lw.interfaces.eventlog.SystemLogger;
+import com.deepclone.lw.interfaces.game.techs.ResearchUpdateDAO;
+import com.deepclone.lw.interfaces.game.techs.TechnologyGraphManager;
+import com.deepclone.lw.interfaces.game.updates.GameUpdate;
+import com.deepclone.lw.interfaces.game.updates.GameUpdatePhase;
+import com.deepclone.lw.interfaces.game.updates.GameUpdatePhaseHandler;
+import com.deepclone.lw.interfaces.game.updates.UpdatesDAO;
+import com.deepclone.lw.sqld.game.techs.ResearchUpdateInput;
+import com.deepclone.lw.sqld.game.techs.ResearchUpdateOutput;
+import com.deepclone.lw.sqld.game.techs.TechGraph;
+import com.deepclone.lw.sqld.game.techs.TechGraphException;
+
+
+
+/**
+ * Component responsible for updating empires' research status.
+ * 
+ * @author tseeker
+ */
+public class ResearchUpdateBean
+		implements GameUpdatePhaseHandler
+{
+	/** The component's logging interface */
+	private SystemLogger logger;
+
+	/** The technology graph management component */
+	private TechnologyGraphManager techGraphManager;
+
+	/** The current technology graph */
+	private TechGraph techGraph;
+
+	/** The main game update data access component */
+	private UpdatesDAO updatesDAO;
+
+	/** The research updates data access component */
+	private ResearchUpdateDAO researchUpdateDAO;
+
+
+	/**
+	 * Dependency injector that initialises the component's logging interface.
+	 * 
+	 * @param logger
+	 *            the system logger
+	 */
+	@Autowired( required = true )
+	public void setLogger( Logger logger )
+	{
+		this.logger = logger.getSystemLogger( "ResearchUpdate" );
+	}
+
+
+	/**
+	 * Dependency injector for the technology graph management component.
+	 * 
+	 * @param techGraphManager
+	 *            the technology graph management component
+	 */
+	@Autowired( required = true )
+	public void setTechGraphManager( TechnologyGraphManager techGraphManager )
+	{
+		this.techGraphManager = techGraphManager;
+	}
+
+
+	/**
+	 * Dependency injector that sets the main game update data access component.
+	 * 
+	 * @param updatesDAO
+	 *            the main game update data access component
+	 */
+	@Autowired( required = true )
+	public void setUpdatesDAO( UpdatesDAO updatesDAO )
+	{
+		this.updatesDAO = updatesDAO;
+	}
+
+
+	/**
+	 * Dependency injector that sets the research updates data access component
+	 * 
+	 * @param researchUpdateDAO
+	 *            the research updates data access component
+	 */
+	@Autowired( required = true )
+	public void setResearchUpdateDAO( ResearchUpdateDAO researchUpdateDAO )
+	{
+		this.researchUpdateDAO = researchUpdateDAO;
+	}
+
+
+	/**
+	 * Dependency injector that registers the handler with the main game update manager
+	 * 
+	 * @param updateManager
+	 *            the game update manager
+	 */
+	@Autowired( required = true )
+	public void setUpdateManager( GameUpdate updateManager )
+	{
+		updateManager.registerHandler( this );
+	}
+
+
+	/* Documentation in GameUpdatePhaseHandler interface */
+	@Override
+	public GameUpdatePhase getPhase( )
+	{
+		return GameUpdatePhase.EMPIRE_RESEARCH;
+	}
+
+
+	/**
+	 * Get a copy of the technology graph when the update phase starts.
+	 */
+	@Override
+	public void onPhaseStart( long updateId )
+	{
+		this.techGraph = this.techGraphManager.getGraph( );
+	}
+
+
+	/**
+	 * If there are research updates left to process, lock the records, then obtain all relevant
+	 * data, process each empire using {@link EmpireUpdate}, and send the updates to the database.
+	 */
+	@Override
+	public boolean updateGame( long updateId )
+	{
+		// Look for records to update
+		if ( !this.updatesDAO.prepareUpdates( updateId , this.getPhase( ) ) ) {
+			return false;
+		}
+
+		Map< Integer , Double > production;
+		HashMap< Integer , List< ResearchUpdateInput >> status;
+		status = new HashMap< Integer , List< ResearchUpdateInput > >( );
+
+		// Prepare update and load input
+		this.researchUpdateDAO.prepareUpdate( updateId );
+		production = this.researchUpdateDAO.getResearchPoints( updateId );
+		for ( ResearchUpdateInput input : this.researchUpdateDAO.getUpdateData( updateId ) ) {
+			List< ResearchUpdateInput > eStatus = status.get( input.getEmpireId( ) );
+			if ( eStatus == null ) {
+				eStatus = new LinkedList< ResearchUpdateInput >( );
+				status.put( input.getEmpireId( ) , eStatus );
+			}
+			eStatus.add( input );
+		}
+
+		// Handle the update for each empire
+		List< ResearchUpdateOutput > output = new LinkedList< ResearchUpdateOutput >( );
+		for ( int empireId : production.keySet( ) ) {
+			EmpireUpdate update = new EmpireUpdate( this.logger , empireId , production , status );
+			try {
+				update.compute( this.techGraph );
+			} catch ( TechGraphException e ) {
+				throw new RuntimeException( "incoherent technology graph" , e );
+			}
+			output.addAll( update.getOutput( ) );
+		}
+
+		// Send and validate updates
+		this.researchUpdateDAO.submitUpdateData( output );
+		this.updatesDAO.validateUpdatedRecords( updateId , GameUpdatePhase.EMPIRE_RESEARCH );
+
+		return true;
+	}
+
+}
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-techs/src/main/java/com/deepclone/lw/beans/techs/ResearchUpdateDAOBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-techs/src/main/java/com/deepclone/lw/beans/techs/ResearchUpdateDAOBean.java
new file mode 100644
index 0000000..b50d807
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-techs/src/main/java/com/deepclone/lw/beans/techs/ResearchUpdateDAOBean.java
@@ -0,0 +1,138 @@
+package com.deepclone.lw.beans.techs;
+
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Types;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.sql.DataSource;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.jdbc.core.RowMapper;
+import org.springframework.jdbc.core.namedparam.SqlParameterSource;
+import org.springframework.jdbc.core.namedparam.SqlParameterSourceUtils;
+import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
+
+import com.deepclone.lw.interfaces.game.techs.ResearchUpdateDAO;
+import com.deepclone.lw.sqld.game.techs.ResearchUpdateInput;
+import com.deepclone.lw.sqld.game.techs.ResearchUpdateOutput;
+import com.deepclone.lw.utils.StoredProc;
+
+
+
+public class ResearchUpdateDAOBean
+		implements ResearchUpdateDAO
+{
+	/** Query that reads research update input */
+	private static final String qGetInput = "SELECT * FROM emp.research_update_input_view WHERE update_id = ?";
+
+	/** Query that reads empire research points production */
+	private static final String qGetPoints = "SELECT * FROM emp.research_points_production WHERE update_id = ?";
+
+	/** Query that adds a record to the output */
+	private static final String qAddOutput = "INSERT INTO research_update_output "
+			+ "(empire_id , technology , creation , points , priority) "
+			+ "VALUES ( :empireId , :technology , :creation , :points , :priority )";
+
+	/** Query that submits the update */
+	private static final String qSubmitUpdate = "SELECT emp.submit_research_update( )";
+
+	/** Data source access */
+	private SimpleJdbcTemplate dTemplate;
+
+	/** Wrapper for the stored procedure that prepares the database for update */
+	private StoredProc fPrepareUpdate;
+
+	/** Row mapper for research update input */
+	RowMapper< ResearchUpdateInput > ruiMapper;
+
+
+	/**
+	 * Initialise the component's row mapper.
+	 */
+	public ResearchUpdateDAOBean( )
+	{
+		this.ruiMapper = new RowMapper< ResearchUpdateInput >( ) {
+			@Override
+			public ResearchUpdateInput mapRow( ResultSet rs , int rowNum )
+					throws SQLException
+			{
+				int empireId = rs.getInt( "empire_id" );
+				String technology = rs.getString( "technology" );
+
+				Boolean implemented = (Boolean) rs.getObject( "implemented" );
+				if ( implemented == null ) {
+					double points = rs.getDouble( "points" );
+					int priority = rs.getInt( "priority" );
+					return new ResearchUpdateInput( empireId , technology , points , priority );
+				}
+
+				return new ResearchUpdateInput( empireId , technology , implemented );
+			}
+		};
+	}
+
+
+	/**
+	 * Dependency injector that initialises the component's database access and stored procedure
+	 * wrappers.
+	 * 
+	 * @param dataSource
+	 *            the data source
+	 */
+	@Autowired( required = true )
+	public void setDataSource( DataSource dataSource )
+	{
+		this.dTemplate = new SimpleJdbcTemplate( dataSource );
+
+		// Stored procedure that prepares the database for update
+		this.fPrepareUpdate = new StoredProc( dataSource , "emp" , "prepare_research_update" );
+		this.fPrepareUpdate.addParameter( "update_id" , Types.BIGINT );
+	}
+
+
+	/* Documented in ResearchUpdateDAO interface */
+	@Override
+	public void prepareUpdate( long updateId )
+	{
+		this.fPrepareUpdate.execute( updateId );
+	}
+
+
+	/* Documented in ResearchUpdateDAO interface */
+	@Override
+	public List< ResearchUpdateInput > getUpdateData( long updateId )
+	{
+		return this.dTemplate.query( qGetInput , this.ruiMapper , updateId );
+	}
+
+
+	/* Documented in ResearchUpdateDAO interface */
+	@Override
+	public Map< Integer , Double > getResearchPoints( long updateId )
+	{
+		Map< Integer , Double > result = new HashMap< Integer , Double >( );
+
+		for ( Map< String , Object > row : this.dTemplate.queryForList( qGetPoints , updateId ) ) {
+			result.put( (Integer) row.get( "empire_id" ) , (Double) row.get( "points" ) );
+		}
+
+		return result;
+	}
+
+
+	/* Documented in ResearchUpdateDAO interface */
+	@Override
+	public void submitUpdateData( List< ResearchUpdateOutput > output )
+	{
+		if ( !output.isEmpty( ) ) {
+			SqlParameterSource[] batch = SqlParameterSourceUtils.createBatch( output.toArray( ) );
+			this.dTemplate.batchUpdate( qAddOutput , batch );
+		}
+		this.dTemplate.queryForList( qSubmitUpdate );
+	}
+
+}
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-techs/src/main/java/com/deepclone/lw/beans/techs/TechnologyGraphDAOBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-techs/src/main/java/com/deepclone/lw/beans/techs/TechnologyGraphDAOBean.java
new file mode 100644
index 0000000..f716b5a
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-techs/src/main/java/com/deepclone/lw/beans/techs/TechnologyGraphDAOBean.java
@@ -0,0 +1,134 @@
+package com.deepclone.lw.beans.techs;
+
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+import javax.sql.DataSource;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.core.RowCallbackHandler;
+
+import com.deepclone.lw.interfaces.game.techs.TechnologyGraphDAO;
+import com.deepclone.lw.sqld.game.techs.TechGraph;
+import com.deepclone.lw.sqld.game.techs.TechGraphException;
+
+
+
+public class TechnologyGraphDAOBean
+		implements TechnologyGraphDAO
+{
+	private static final String qGetCategories = "SELECT name , description FROM tech.categories_view";
+	private static final String qGetTechnologies = "SELECT category , name , description , points , cost FROM tech.technologies_view";
+	private static final String qGetDependencies = "SELECT technology , dependency FROM tech.dependencies_view";
+
+	private static abstract class TechGraphDBHandler
+			implements RowCallbackHandler
+	{
+		TechGraph graph;
+		TechGraphException error;
+
+
+		public TechGraphDBHandler( )
+		{
+			// EMPTY
+		}
+
+
+		public final void setGraph( TechGraph graph )
+		{
+			this.graph = graph;
+		}
+
+
+		@Override
+		public final void processRow( ResultSet rs )
+				throws SQLException
+		{
+			if ( this.error != null ) {
+				return;
+			}
+
+			try {
+				this.extractData( rs );
+			} catch ( TechGraphException e ) {
+				this.error = e;
+			}
+		}
+
+
+		protected abstract void extractData( ResultSet rs )
+				throws TechGraphException , SQLException;
+
+	}
+
+	private static class CategoryExtractor
+			extends TechGraphDBHandler
+	{
+		@Override
+		protected void extractData( ResultSet rs )
+				throws TechGraphException , SQLException
+		{
+			this.graph.addCategory( rs.getString( "name" ) , rs.getString( "description" ) );
+		}
+
+	}
+
+	private static class TechnologyExtractor
+			extends TechGraphDBHandler
+	{
+		@Override
+		protected void extractData( ResultSet rs )
+				throws TechGraphException , SQLException
+		{
+			this.graph.addTechnology( rs.getString( "category" ) , rs.getString( "name" ) , rs
+					.getString( "description" ) , rs.getInt( "points" ) , rs.getInt( "cost" ) );
+		}
+	}
+
+	private static class DependencyExtractor
+			extends TechGraphDBHandler
+	{
+		@Override
+		protected void extractData( ResultSet rs )
+				throws TechGraphException , SQLException
+		{
+			this.graph.addDependency( rs.getString( "technology" ) , rs.getString( "dependency" ) );
+		}
+
+	}
+
+	private JdbcTemplate dTemplate;
+
+
+	@Autowired( required = true )
+	public void setDataSource( DataSource dataSource )
+	{
+		this.dTemplate = new JdbcTemplate( dataSource );
+	}
+
+
+	@Override
+	public TechGraph loadGraph( )
+			throws TechGraphException
+	{
+		TechGraph result = new TechGraph( );
+		this.extractGraphData( result , new CategoryExtractor( ) , qGetCategories );
+		this.extractGraphData( result , new TechnologyExtractor( ) , qGetTechnologies );
+		this.extractGraphData( result , new DependencyExtractor( ) , qGetDependencies );
+		return result;
+	}
+
+
+	private void extractGraphData( TechGraph graph , TechGraphDBHandler extractor , String query )
+			throws TechGraphException
+	{
+		extractor.setGraph( graph );
+		this.dTemplate.query( query , extractor );
+		if ( extractor.error != null ) {
+			throw extractor.error;
+		}
+	}
+
+}
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-techs/src/main/java/com/deepclone/lw/beans/techs/TechnologyGraphManagerBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-techs/src/main/java/com/deepclone/lw/beans/techs/TechnologyGraphManagerBean.java
new file mode 100644
index 0000000..2699fdb
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-techs/src/main/java/com/deepclone/lw/beans/techs/TechnologyGraphManagerBean.java
@@ -0,0 +1,74 @@
+package com.deepclone.lw.beans.techs;
+
+
+import java.util.LinkedList;
+import java.util.List;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+
+import com.deepclone.lw.cmd.admin.techs.TechCategory;
+import com.deepclone.lw.interfaces.game.techs.TechnologyGraphDAO;
+import com.deepclone.lw.interfaces.game.techs.TechnologyGraphManager;
+import com.deepclone.lw.sqld.game.techs.Category;
+import com.deepclone.lw.sqld.game.techs.TechGraph;
+import com.deepclone.lw.sqld.game.techs.TechGraphException;
+
+
+
+@Transactional
+public class TechnologyGraphManagerBean
+		implements TechnologyGraphManager
+{
+	private TechGraph graph;
+	private TechnologyGraphDAO technologyGraphDAO;
+
+
+	@Autowired( required = true )
+	public void setTechGraphDAO( TechnologyGraphDAO technologyGraphDAO )
+	{
+		this.technologyGraphDAO = technologyGraphDAO;
+	}
+
+
+	private void loadGraph( )
+			throws TechGraphException
+	{
+		if ( this.graph == null ) {
+			this.graph = this.technologyGraphDAO.loadGraph( );
+		}
+	}
+
+
+	/* Documented in TechnologyGraphManager interface */
+	@Override
+	public TechGraph getGraph( )
+	{
+		try {
+			this.loadGraph( );
+		} catch ( TechGraphException e ) {
+			throw new RuntimeException( e );
+		}
+		return new TechGraph( this.graph );
+	}
+
+
+	/* Documented in TechnologyGraphManager interface */
+	@Override
+	public List< TechCategory > listCategories( )
+	{
+		try {
+			this.loadGraph( );
+
+			List< TechCategory > result = new LinkedList< TechCategory >( );
+			for ( String catName : this.graph.getCategories( ) ) {
+				Category cat = this.graph.getCategory( catName );
+				result.add( new TechCategory( catName , cat.getDescription( ) , cat.getTechnologies( ) ) );
+			}
+
+			return result;
+		} catch ( TechGraphException e ) {
+			throw new RuntimeException( e );
+		}
+	}
+}
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-techs/src/main/resources/configuration/techs-beans.xml b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-techs/src/main/resources/configuration/techs-beans.xml
new file mode 100644
index 0000000..df082ba
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-techs/src/main/resources/configuration/techs-beans.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="
+                        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
+
+	<import resource="techs/empire-technology-dao-bean.xml" />
+	<import resource="techs/empire-technology-manager-bean.xml" />
+	<import resource="techs/research-update-bean.xml" />
+	<import resource="techs/research-update-dao-bean.xml" />
+	<import resource="techs/technology-graph-dao-bean.xml" />
+	<import resource="techs/technology-graph-manager-bean.xml" />
+
+</beans>
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-techs/src/main/resources/configuration/techs/empire-technology-dao-bean.xml b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-techs/src/main/resources/configuration/techs/empire-technology-dao-bean.xml
new file mode 100644
index 0000000..2edfe89
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-techs/src/main/resources/configuration/techs/empire-technology-dao-bean.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="
+                        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
+
+	<bean id="empireTechnologyDAO" class="com.deepclone.lw.beans.techs.EmpireTechnologyDAOBean" />
+
+</beans>
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-techs/src/main/resources/configuration/techs/empire-technology-manager-bean.xml b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-techs/src/main/resources/configuration/techs/empire-technology-manager-bean.xml
new file mode 100644
index 0000000..20b8065
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-techs/src/main/resources/configuration/techs/empire-technology-manager-bean.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="
+                        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
+
+	<bean id="empireTechnologyManager" class="com.deepclone.lw.beans.techs.EmpireTechnologyManagerBean" />
+
+</beans>
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-techs/src/main/resources/configuration/techs/research-update-bean.xml b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-techs/src/main/resources/configuration/techs/research-update-bean.xml
new file mode 100644
index 0000000..2bf00a9
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-techs/src/main/resources/configuration/techs/research-update-bean.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="
+                        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
+
+	<bean id="researchUpdate" class="com.deepclone.lw.beans.techs.ResearchUpdateBean" />
+
+</beans>
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-techs/src/main/resources/configuration/techs/research-update-dao-bean.xml b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-techs/src/main/resources/configuration/techs/research-update-dao-bean.xml
new file mode 100644
index 0000000..1e29667
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-techs/src/main/resources/configuration/techs/research-update-dao-bean.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="
+                        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
+
+	<bean id="researchUpdateDAO" class="com.deepclone.lw.beans.techs.ResearchUpdateDAOBean" />
+
+</beans>
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-techs/src/main/resources/configuration/techs/technology-graph-dao-bean.xml b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-techs/src/main/resources/configuration/techs/technology-graph-dao-bean.xml
new file mode 100644
index 0000000..5a77f1c
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-techs/src/main/resources/configuration/techs/technology-graph-dao-bean.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="
+                        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
+
+	<bean id="technologyGraphDAO" class="com.deepclone.lw.beans.techs.TechnologyGraphDAOBean" />
+
+</beans>
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-techs/src/main/resources/configuration/techs/technology-graph-manager-bean.xml b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-techs/src/main/resources/configuration/techs/technology-graph-manager-bean.xml
new file mode 100644
index 0000000..511a02b
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-techs/src/main/resources/configuration/techs/technology-graph-manager-bean.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="
+                        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
+
+	<bean id="technologyGraphManager" class="com.deepclone.lw.beans.techs.TechnologyGraphManagerBean" />
+
+</beans>
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-updates/.classpath b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-updates/.classpath
new file mode 100644
index 0000000..7c3d14f
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-updates/.classpath
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" output="target/classes" path="src/main/java"/>
+	<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources"/>
+	<classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
+	<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+	<classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER"/>
+	<classpathentry kind="output" path="target/classes"/>
+</classpath>
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-updates/.project b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-updates/.project
new file mode 100644
index 0000000..b085973
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-updates/.project
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>legacyworlds-server-beans-updates</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.maven.ide.eclipse.maven2Builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.maven.ide.eclipse.maven2Nature</nature>
+	</natures>
+</projectDescription>
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-updates/.settings/org.eclipse.jdt.core.prefs b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-updates/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..e13ce5e
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-updates/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,6 @@
+#Tue Mar 29 13:49:47 CEST 2011
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.6
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-updates/.settings/org.maven.ide.eclipse.prefs b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-updates/.settings/org.maven.ide.eclipse.prefs
new file mode 100644
index 0000000..052be69
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-updates/.settings/org.maven.ide.eclipse.prefs
@@ -0,0 +1,9 @@
+#Tue Mar 29 13:49:47 CEST 2011
+activeProfiles=
+eclipse.preferences.version=1
+fullBuildGoals=process-test-resources
+includeModules=false
+resolveWorkspaceProjects=true
+resourceFilterGoals=process-resources resources\:testResources
+skipCompilerPlugin=true
+version=1
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-updates/pom.xml b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-updates/pom.xml
new file mode 100644
index 0000000..bc4f4e5
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-updates/pom.xml
@@ -0,0 +1,13 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <artifactId>legacyworlds-server-beans</artifactId>
+    <groupId>com.deepclone.lw</groupId>
+    <version>5.99.2</version>
+  </parent>
+  <groupId>com.deepclone.lw</groupId>
+  <artifactId>legacyworlds-server-beans-updates</artifactId>
+  <version>5.99.2</version>
+  <name>Legacy Worlds updates and pre-computation management</name>
+  <description>This Maven module contains the components which implement both the game's "standard", per-minute update system as well as the pre-computation manager.</description>
+</project>
\ No newline at end of file
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-updates/src/main/java/com/deepclone/lw/beans/updates/GameUpdateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-updates/src/main/java/com/deepclone/lw/beans/updates/GameUpdateBean.java
new file mode 100644
index 0000000..2a1b0ae
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-updates/src/main/java/com/deepclone/lw/beans/updates/GameUpdateBean.java
@@ -0,0 +1,367 @@
+package com.deepclone.lw.beans.updates;
+
+
+import java.util.ArrayList;
+import java.util.EnumMap;
+import java.util.List;
+
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.transaction.PlatformTransactionManager;
+import org.springframework.transaction.TransactionStatus;
+import org.springframework.transaction.support.TransactionCallback;
+import org.springframework.transaction.support.TransactionTemplate;
+
+import com.deepclone.lw.cmd.admin.logs.LogLevel;
+import com.deepclone.lw.interfaces.eventlog.Logger;
+import com.deepclone.lw.interfaces.eventlog.SystemLogger;
+import com.deepclone.lw.interfaces.game.updates.DuplicateUpdateHandler;
+import com.deepclone.lw.interfaces.game.updates.GameUpdate;
+import com.deepclone.lw.interfaces.game.updates.GameUpdatePhase;
+import com.deepclone.lw.interfaces.game.updates.GameUpdatePhaseHandler;
+import com.deepclone.lw.interfaces.game.updates.UpdatesDAO;
+import com.deepclone.lw.interfaces.sys.ConstantDefinition;
+import com.deepclone.lw.interfaces.sys.ConstantsManager;
+import com.deepclone.lw.interfaces.sys.MaintenanceStatusException;
+import com.deepclone.lw.interfaces.sys.SystemStatus;
+import com.deepclone.lw.interfaces.sys.TickStatusException;
+import com.deepclone.lw.interfaces.sys.Ticker;
+import com.deepclone.lw.interfaces.sys.Ticker.Frequency;
+
+
+
+/**
+ * Implementation of the game update management component.
+ * 
+ * @author tseeker
+ */
+public class GameUpdateBean
+		implements GameUpdate , InitializingBean , Runnable , ApplicationContextAware
+{
+	/** The event scheduling component */
+	private Ticker ticker;
+
+	/** The system status access and update component */
+	private SystemStatus systemStatus;
+
+	/** The game update component's logger */
+	private SystemLogger logger;
+
+	/** Transaction template */
+	private TransactionTemplate tTemplate;
+
+	/** Game updates data access component */
+	private UpdatesDAO updatesDao;
+
+	/** Amount of registered, non-default handlers */
+	private int nRegisteredHandlers = 0;
+
+	/** Amount of handler components */
+	private int nHandlerComponents = -1;
+
+	/** Registered game update phase handlers */
+	private final EnumMap< GameUpdatePhase , GameUpdatePhaseHandler > handlers;
+
+
+	public GameUpdateBean( )
+	{
+		this.handlers = new EnumMap< GameUpdatePhase , GameUpdatePhaseHandler >( GameUpdatePhase.class );
+	}
+
+
+	/**
+	 * Dependency injector for the event scheduling component
+	 * 
+	 * @param ticker
+	 *            the event scheduling component
+	 */
+	@Autowired( required = true )
+	public void setTicker( Ticker ticker )
+	{
+		this.ticker = ticker;
+	}
+
+
+	/**
+	 * Dependency injector for the system status access component
+	 * 
+	 * @param systemStatus
+	 *            the system status access component
+	 */
+	@Autowired( required = true )
+	public void setSystemStatus( SystemStatus systemStatus )
+	{
+		this.systemStatus = systemStatus;
+	}
+
+
+	/**
+	 * Dependency injector that initialises the game update component's logger.
+	 * 
+	 * @param logger
+	 *            the system logging component
+	 */
+	@Autowired( required = true )
+	public void setLogger( Logger logger )
+	{
+		this.logger = logger.getSystemLogger( "GameUpdate" );
+	}
+
+
+	/**
+	 * Dependency injector that initialises the transaction template.
+	 * 
+	 * @param transactionManager
+	 *            the application's transaction manager
+	 */
+	@Autowired( required = true )
+	public void setTransactionManager( PlatformTransactionManager transactionManager )
+	{
+		this.tTemplate = new TransactionTemplate( transactionManager );
+	}
+
+
+	/**
+	 * Dependency injector for the game updates data access component
+	 * 
+	 * @param updatesDao
+	 *            the game updates data access component
+	 */
+	@Autowired( required = true )
+	public void setUpdatesDAO( UpdatesDAO updatesDao )
+	{
+		this.updatesDao = updatesDao;
+	}
+
+
+	/**
+	 * Dependency injector which registers the game.updatesPerDay constant.
+	 * 
+	 * @param constantsManager
+	 *            the constants manager
+	 */
+	@Autowired( required = true )
+	public void setConstantsManager( ConstantsManager constantsManager )
+	{
+		List< ConstantDefinition > definitions;
+		ConstantDefinition constant;
+		definitions = new ArrayList< ConstantDefinition >( 1 );
+		constant = new ConstantDefinition(
+				"game.updatesPerDay" ,
+				"Game (misc)" ,
+				"Game updates per day from the computations's point of view. "
+						+ "This does not affect the actual amount of updates, but changes the computations. "
+						+ "Can be used to speed things up or slow them down without actually changing ticker.interval." ,
+				1440.0 , 0.05 , 5760.0 );
+		definitions.add( 0 , constant );
+		constantsManager.registerConstants( definitions );
+	}
+
+
+	/**
+	 * Read the amount of update phase handlers from the application context.
+	 * 
+	 * @param context
+	 *            the application context
+	 */
+	@Override
+	public void setApplicationContext( ApplicationContext context )
+			throws BeansException
+	{
+		this.nHandlerComponents = context.getBeansOfType( GameUpdatePhaseHandler.class ).size( );
+		if ( this.nRegisteredHandlers == this.nHandlerComponents ) {
+			this.initialise( );
+		}
+	}
+
+
+	/* Documentation in GameUpdate interface */
+	@Override
+	public void registerHandler( GameUpdatePhaseHandler handler )
+			throws DuplicateUpdateHandler
+	{
+		GameUpdatePhase phase = handler.getPhase( );
+		synchronized ( this.handlers ) {
+			if ( this.handlers.containsKey( phase ) ) {
+				throw new DuplicateUpdateHandler( phase );
+			}
+			this.handlers.put( phase , handler );
+		}
+		this.logger.log( LogLevel.DEBUG , "Registered game update handler for phase " + phase.toString( ) ).flush( );
+
+		this.nRegisteredHandlers++;
+		if ( this.nRegisteredHandlers == this.nHandlerComponents ) {
+			this.initialise( );
+		}
+	}
+
+
+	/**
+	 * Initialise the component if it is ready.
+	 */
+	@Override
+	public void afterPropertiesSet( )
+	{
+		if ( this.nRegisteredHandlers == this.nHandlerComponents ) {
+			this.initialise( );
+		}
+	}
+
+
+	/**
+	 * Finish any pending computations (unless maintenance mode is active), then register the game
+	 * update task into the {@link #ticker}.
+	 */
+	private void initialise( )
+	{
+		// Finish previous tick if possible
+		try {
+			this.endPreviousTick( );
+		} catch ( MaintenanceStatusException e ) {
+			// EMPTY
+		}
+
+		// Register ticker task
+		this.ticker.registerTask( Frequency.MINUTE , "Game update" , this );
+
+		// Make sure initialisation only occurs once
+		this.nHandlerComponents = -1;
+	}
+
+
+	/**
+	 * When the game update event is triggered by the system's scheduling component, attempt to run
+	 * a game update.
+	 * 
+	 * First, check if there is already a game update in progress, and attempt to finish running it
+	 * if necessary. Otherwise start a new update though the system status manager, and execute it.
+	 */
+	@Override
+	public void run( )
+	{
+		// Attempt to end the previous tick, if e.g. maintenance mode was initiated while it was
+		// being processed
+		try {
+			if ( this.endPreviousTick( ) ) {
+				return;
+			}
+		} catch ( MaintenanceStatusException e ) {
+			return;
+		}
+
+		// Initiate next tick
+		long tickId;
+		try {
+			tickId = this.systemStatus.startTick( );
+		} catch ( TickStatusException e ) {
+			throw new RuntimeException( "tick initiated while previous tick still being processed" , e );
+		} catch ( MaintenanceStatusException e ) {
+			return;
+		}
+
+		// Execute tick
+		this.logger.log( LogLevel.DEBUG , "Tick " + tickId + " started" ).flush( );
+		this.executeUpdate( tickId );
+	}
+
+
+	/**
+	 * Check if a game update was in progress and finish running it if necessary.
+	 * 
+	 * @return <code>true</code> if a game update was already being executed, <code>false</code>
+	 *         otherwise.
+	 * 
+	 * @throws MaintenanceStatusException
+	 *             if the game is under maintenance.
+	 */
+	private boolean endPreviousTick( )
+			throws MaintenanceStatusException
+	{
+		Long currentTick = this.systemStatus.checkStuckTick( );
+		if ( currentTick == null ) {
+			return false;
+		}
+
+		this.logger.log( LogLevel.WARNING , "Tick " + currentTick + " restarted" ).flush( );
+		this.executeUpdate( currentTick.longValue( ) );
+
+		return true;
+	}
+
+
+	/**
+	 * Execute all phase handlers for a game update, then mark the update as completed.
+	 * 
+	 * @param updateId
+	 *            the identifier of the current update
+	 */
+	private void executeUpdate( long updateId )
+	{
+		for ( GameUpdatePhase phase : GameUpdatePhase.values( ) ) {
+			this.executeUpdatePhase( updateId , phase );
+		}
+
+		try {
+			this.systemStatus.endTick( );
+		} catch ( TickStatusException e ) {
+			throw new RuntimeException( "Game update completed but status error reported" , e );
+		} catch ( MaintenanceStatusException e ) {
+			return;
+		}
+
+		this.logger.log( LogLevel.TRACE , "Tick " + updateId + " completed" ).flush( );
+	}
+
+
+	/**
+	 * Execute a phase of the game update.
+	 * 
+	 * @param updateId
+	 *            the identifier of the current update
+	 * @param phase
+	 *            the phase of the update to execute
+	 */
+	private void executeUpdatePhase( final long updateId , GameUpdatePhase phase )
+	{
+		final GameUpdatePhaseHandler handler = this.getHandlerForPhase( phase );
+		handler.onPhaseStart( updateId );
+
+		boolean hasMore;
+		do {
+			hasMore = this.tTemplate.execute( new TransactionCallback< Boolean >( ) {
+				@Override
+				public Boolean doInTransaction( TransactionStatus status )
+				{
+					return handler.updateGame( updateId );
+				}
+			} );
+		} while ( hasMore );
+	}
+
+
+	/**
+	 * Access the handler for an update phase. If no handler has been registered, create a default
+	 * {@link ProceduralGameUpdate} handler.
+	 * 
+	 * @param phase
+	 *            the update phase whose handler is to be retrieved
+	 * @return the game update handler
+	 */
+	private GameUpdatePhaseHandler getHandlerForPhase( GameUpdatePhase phase )
+	{
+		GameUpdatePhaseHandler handler;
+		synchronized ( this.handlers ) {
+			handler = this.handlers.get( phase );
+			if ( handler == null ) {
+				this.logger.log( LogLevel.DEBUG , "Creating default handler for phase " + phase.toString( ) ).flush( );
+				handler = new ProceduralGameUpdate( this.updatesDao , phase );
+				this.handlers.put( phase , handler );
+			}
+		}
+		return handler;
+	}
+
+}
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-updates/src/main/java/com/deepclone/lw/beans/updates/ProceduralGameUpdate.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-updates/src/main/java/com/deepclone/lw/beans/updates/ProceduralGameUpdate.java
new file mode 100644
index 0000000..73480ed
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-updates/src/main/java/com/deepclone/lw/beans/updates/ProceduralGameUpdate.java
@@ -0,0 +1,52 @@
+package com.deepclone.lw.beans.updates;
+
+
+import com.deepclone.lw.interfaces.game.updates.GameUpdatePhase;
+import com.deepclone.lw.interfaces.game.updates.GameUpdatePhaseHandler;
+import com.deepclone.lw.interfaces.game.updates.UpdatesDAO;
+
+
+
+class ProceduralGameUpdate
+		implements GameUpdatePhaseHandler
+{
+
+	private final GameUpdatePhase phase;
+	private final UpdatesDAO updatesDao;
+
+
+	ProceduralGameUpdate( UpdatesDAO updatesDao , GameUpdatePhase phase )
+	{
+		this.updatesDao = updatesDao;
+		this.phase = phase;
+	}
+
+
+	@Override
+	public GameUpdatePhase getPhase( )
+	{
+		return this.phase;
+	}
+
+
+	@Override
+	public boolean updateGame( long updateId )
+	{
+		if ( !this.updatesDao.prepareUpdates( updateId , this.phase ) ) {
+			return false;
+		}
+
+		this.updatesDao.executeProceduralUpdate( updateId , this.phase );
+		this.updatesDao.validateUpdatedRecords( updateId , this.phase );
+
+		return true;
+	}
+
+
+	@Override
+	public void onPhaseStart( long updateId )
+	{
+		// EMPTY
+	}
+
+}
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-updates/src/main/java/com/deepclone/lw/beans/updates/UpdatesDAOBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-updates/src/main/java/com/deepclone/lw/beans/updates/UpdatesDAOBean.java
new file mode 100644
index 0000000..69a3af3
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-updates/src/main/java/com/deepclone/lw/beans/updates/UpdatesDAOBean.java
@@ -0,0 +1,85 @@
+package com.deepclone.lw.beans.updates;
+
+
+import java.sql.Types;
+
+import javax.sql.DataSource;
+
+import org.springframework.beans.factory.annotation.Autowired;
+
+import com.deepclone.lw.interfaces.game.updates.GameUpdatePhase;
+import com.deepclone.lw.interfaces.game.updates.UpdatesDAO;
+import com.deepclone.lw.utils.StoredProc;
+
+
+
+/**
+ * Implementation of the game update data access component.
+ * 
+ * @author tseeker
+ */
+public class UpdatesDAOBean
+		implements UpdatesDAO
+{
+
+	/** Wrapper for the stored procedure that prepares updates */
+	private StoredProc fPrepareUpdates;
+
+	/** Wrapper for the stored procedure that executes a procedural game update */
+	private StoredProc fExecuteProcedural;
+
+	/** Wrapper for the stored procedure that marks update records as processed */
+	private StoredProc fUpdatesProcessed;
+
+
+	/**
+	 * Dependency injector that initialises stored procedure call handlers.
+	 * 
+	 * @param dataSource
+	 *            the data source
+	 */
+	@Autowired( required = true )
+	public void setDataSource( DataSource dataSource )
+	{
+		// Stored procedure that prepares updates
+		this.fPrepareUpdates = new StoredProc( dataSource , "sys" , "prepare_updates" );
+		this.fPrepareUpdates.addParameter( "u_id" , Types.BIGINT );
+		this.fPrepareUpdates.addParameter( "u_type" , "update_type" );
+		this.fPrepareUpdates.addOutput( "has_more" , Types.BOOLEAN );
+
+		// Stored procedure that executes a procedural game update
+		this.fExecuteProcedural = new StoredProc( dataSource , "sys" , "exec_update_proc" );
+		this.fExecuteProcedural.addParameter( "u_id" , Types.BIGINT );
+		this.fExecuteProcedural.addParameter( "u_type" , "update_type" );
+
+		// Stored procedure that marks update records as processed
+		this.fUpdatesProcessed = new StoredProc( dataSource , "sys" , "updates_processed" );
+		this.fUpdatesProcessed.addParameter( "u_id" , Types.BIGINT );
+		this.fUpdatesProcessed.addParameter( "u_type" , "update_type" );
+	}
+
+
+	/* Documentation in UpdatesDAO interface */
+	@Override
+	public boolean prepareUpdates( long updateId , GameUpdatePhase phase )
+	{
+		return (Boolean) this.fPrepareUpdates.execute( updateId , phase.toString( ) ).get( "has_more" );
+	}
+
+
+	/* Documentation in UpdatesDAO interface */
+	@Override
+	public void executeProceduralUpdate( long updateId , GameUpdatePhase phase )
+	{
+		this.fExecuteProcedural.execute( updateId , phase.toString( ) );
+	}
+
+
+	/* Documentation in UpdatesDAO interface */
+	@Override
+	public void validateUpdatedRecords( long updateId , GameUpdatePhase phase )
+	{
+		this.fUpdatesProcessed.execute( updateId , phase );
+	}
+
+}
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-updates/src/main/resources/configuration/updates-beans.xml b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-updates/src/main/resources/configuration/updates-beans.xml
new file mode 100644
index 0000000..7387fce
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-updates/src/main/resources/configuration/updates-beans.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="
+                        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
+
+	<import resource="updates/game-update-bean.xml" />
+	<import resource="updates/updates-dao-bean.xml" />
+
+</beans>
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-updates/src/main/resources/configuration/updates/game-update-bean.xml b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-updates/src/main/resources/configuration/updates/game-update-bean.xml
new file mode 100644
index 0000000..54534ff
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-updates/src/main/resources/configuration/updates/game-update-bean.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="
+                        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
+
+	<!-- Game update bean -->
+	<bean id="gameUpdate" class="com.deepclone.lw.beans.updates.GameUpdateBean" />
+
+</beans>
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-updates/src/main/resources/configuration/updates/updates-dao-bean.xml b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-updates/src/main/resources/configuration/updates/updates-dao-bean.xml
new file mode 100644
index 0000000..eb24044
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-updates/src/main/resources/configuration/updates/updates-dao-bean.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="
+                        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
+
+	<bean id="updatesDAO" class="com.deepclone.lw.beans.updates.UpdatesDAOBean" />
+
+</beans>
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/.classpath b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/.classpath
new file mode 100644
index 0000000..7c3d14f
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/.classpath
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" output="target/classes" path="src/main/java"/>
+	<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources"/>
+	<classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
+	<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+	<classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER"/>
+	<classpathentry kind="output" path="target/classes"/>
+</classpath>
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/.project b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/.project
new file mode 100644
index 0000000..b2adbb1
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/.project
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>legacyworlds-server-beans-user</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.maven.ide.eclipse.maven2Builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.maven.ide.eclipse.maven2Nature</nature>
+	</natures>
+</projectDescription>
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/.settings/org.eclipse.jdt.core.prefs b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..ce751ed
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,6 @@
+#Wed Apr 14 12:43:45 CEST 2010
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.6
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/.settings/org.maven.ide.eclipse.prefs b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/.settings/org.maven.ide.eclipse.prefs
new file mode 100644
index 0000000..6b7d8f9
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/.settings/org.maven.ide.eclipse.prefs
@@ -0,0 +1,9 @@
+#Wed Apr 14 12:43:44 CEST 2010
+activeProfiles=
+eclipse.preferences.version=1
+fullBuildGoals=process-test-resources
+includeModules=false
+resolveWorkspaceProjects=true
+resourceFilterGoals=process-resources resources\:testResources
+skipCompilerPlugin=true
+version=1
diff --git a/legacyworlds-server-beans-user/pom.xml b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/pom.xml
similarity index 63%
rename from legacyworlds-server-beans-user/pom.xml
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/pom.xml
index e506d66..f1969df 100644
--- a/legacyworlds-server-beans-user/pom.xml
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/pom.xml
@@ -4,12 +4,12 @@
 	<parent>
 		<artifactId>legacyworlds-server-beans</artifactId>
 		<groupId>com.deepclone.lw</groupId>
-		<version>1.0.0</version>
-		<relativePath>../legacyworlds-server-beans/pom.xml</relativePath>
+		<version>5.99.2</version>
 	</parent>
 
+	<groupId>com.deepclone.lw</groupId>
 	<artifactId>legacyworlds-server-beans-user</artifactId>
-	<version>${legacyworlds.version.main}.${legacyworlds.version.release}-${legacyworlds.version.build}</version>
-	<name>Legacy Worlds - Server - Components - User actions</name>
+	<version>5.99.2</version>
+	<name>Legacy Worlds server - user actions</name>
 	<description>This module defines beans and classes that handle user actions.</description>
-</project>
+</project>
\ No newline at end of file
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/ObjectNameValidatorBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/ObjectNameValidatorBean.java
new file mode 100644
index 0000000..cd3bcff
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/ObjectNameValidatorBean.java
@@ -0,0 +1,77 @@
+package com.deepclone.lw.beans.user;
+
+
+import java.util.regex.Pattern;
+
+import com.deepclone.lw.cmd.ObjectNameError;
+
+
+
+public class ObjectNameValidatorBean
+{
+
+	private int minLength = 2;
+	private int maxLength = 20;
+
+	private static Pattern fail[] = {
+			Pattern.compile( "\\s\\s+" ) ,
+			Pattern.compile( "[^A-Za-z0-9 _\\'\\!\\:\\,\\-\\.\\*@\\[\\]\\{\\}]" )
+	};
+
+	private static Pattern needed[] = {
+		Pattern.compile( "[A-Za-z]" )
+	};
+
+
+	public void setMinLength( Integer v )
+	{
+		this.minLength = v;
+	}
+
+
+	public void setMaxLength( Integer v )
+	{
+		this.maxLength = v;
+	}
+
+
+	public ObjectNameError validate( String name )
+	{
+		return this.customValidate( name , this.minLength , this.maxLength );
+	}
+
+
+	public ObjectNameError customValidate( String name , int minLength , int maxLength )
+	{
+		if ( "".equals( name.trim( ) ) ) {
+			return ObjectNameError.EMPTY;
+		}
+
+		// No leading or trailing spaces
+		if ( !name.equals( name.trim( ) ) ) {
+			return ObjectNameError.INVALID;
+		}
+
+		// Check length
+		int length = name.length( );
+		if ( length < minLength || length > maxLength ) {
+			return ObjectNameError.INVALID;
+		}
+
+		// Check bad patterns
+		for ( Pattern p : ObjectNameValidatorBean.fail ) {
+			if ( p.matcher( name ).find( ) ) {
+				return ObjectNameError.INVALID;
+			}
+		}
+
+		// Check good patterns
+		for ( Pattern p : ObjectNameValidatorBean.needed ) {
+			if ( !p.matcher( name ).find( ) ) {
+				return ObjectNameError.INVALID;
+			}
+		}
+
+		return null;
+	}
+}
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/abst/AutowiredCommandDelegate.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/abst/AutowiredCommandDelegate.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/abst/AutowiredCommandDelegate.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/abst/AutowiredCommandDelegate.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/abst/AutowiredSubTypeDelegate.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/abst/AutowiredSubTypeDelegate.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/abst/AutowiredSubTypeDelegate.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/abst/AutowiredSubTypeDelegate.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/abst/SessionCommandDelegate.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/abst/SessionCommandDelegate.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/abst/SessionCommandDelegate.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/abst/SessionCommandDelegate.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/abst/SessionCommandHandler.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/abst/SessionCommandHandler.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/abst/SessionCommandHandler.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/abst/SessionCommandHandler.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/abst/SessionCommandWiringBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/abst/SessionCommandWiringBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/abst/SessionCommandWiringBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/abst/SessionCommandWiringBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/abst/SessionSubTypeDelegate.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/abst/SessionSubTypeDelegate.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/abst/SessionSubTypeDelegate.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/abst/SessionSubTypeDelegate.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/abst/SessionSubTypeWiringBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/abst/SessionSubTypeWiringBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/abst/SessionSubTypeWiringBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/abst/SessionSubTypeWiringBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/abst/StatefulSessionTypeDefiner.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/abst/StatefulSessionTypeDefiner.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/abst/StatefulSessionTypeDefiner.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/abst/StatefulSessionTypeDefiner.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/AdminSessionDefinerBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/AdminSessionDefinerBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/AdminSessionDefinerBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/AdminSessionDefinerBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/AdminSessionSubType.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/AdminSessionSubType.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/AdminSessionSubType.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/AdminSessionSubType.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/common/AdminOperation.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/common/AdminOperation.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/common/AdminOperation.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/common/AdminOperation.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/common/CommonCommandsBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/common/CommonCommandsBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/common/CommonCommandsBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/common/CommonCommandsBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/common/CreateAuthChallengeCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/common/CreateAuthChallengeCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/common/CreateAuthChallengeCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/common/CreateAuthChallengeCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/common/NoOperationCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/common/NoOperationCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/common/NoOperationCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/common/NoOperationCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/common/SetPasswordCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/common/SetPasswordCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/common/SetPasswordCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/common/SetPasswordCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/AdminCommandsBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/AdminCommandsBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/AdminCommandsBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/AdminCommandsBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/AdminOverviewCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/AdminOverviewCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/AdminOverviewCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/AdminOverviewCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/bans/BansSummaryCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/bans/BansSummaryCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/bans/BansSummaryCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/bans/BansSummaryCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/bans/ConfirmBanCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/bans/ConfirmBanCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/bans/ConfirmBanCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/bans/ConfirmBanCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/bans/LiftBanCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/bans/LiftBanCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/bans/LiftBanCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/bans/LiftBanCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/bans/ListBansCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/bans/ListBansCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/bans/ListBansCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/bans/ListBansCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/bans/RejectBanCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/bans/RejectBanCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/bans/RejectBanCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/bans/RejectBanCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/bans/RequestBanCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/bans/RequestBanCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/bans/RequestBanCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/bans/RequestBanCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/bt/BugsSummaryCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/bt/BugsSummaryCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/bt/BugsSummaryCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/bt/BugsSummaryCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/bt/GetSnapshotCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/bt/GetSnapshotCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/bt/GetSnapshotCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/bt/GetSnapshotCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/bt/ListBugsCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/bt/ListBugsCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/bt/ListBugsCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/bt/ListBugsCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/bt/MergeReportsCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/bt/MergeReportsCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/bt/MergeReportsCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/bt/MergeReportsCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/bt/ModerateCommentCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/bt/ModerateCommentCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/bt/ModerateCommentCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/bt/ModerateCommentCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/bt/PostCommentCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/bt/PostCommentCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/bt/PostCommentCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/bt/PostCommentCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/bt/ReportBugCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/bt/ReportBugCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/bt/ReportBugCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/bt/ReportBugCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/bt/ReportStatusCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/bt/ReportStatusCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/bt/ReportStatusCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/bt/ReportStatusCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/bt/ReportVisibilityCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/bt/ReportVisibilityCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/bt/ReportVisibilityCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/bt/ReportVisibilityCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/bt/ValidateReportCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/bt/ValidateReportCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/bt/ValidateReportCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/bt/ValidateReportCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/bt/ViewBugCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/bt/ViewBugCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/bt/ViewBugCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/bt/ViewBugCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/cnst/GetConstantsCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/cnst/GetConstantsCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/cnst/GetConstantsCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/cnst/GetConstantsCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/cnst/SetConstantCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/cnst/SetConstantCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/cnst/SetConstantCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/cnst/SetConstantCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/i18n/ChangeLanguageCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/i18n/ChangeLanguageCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/i18n/ChangeLanguageCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/i18n/ChangeLanguageCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/i18n/GetLanguageCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/i18n/GetLanguageCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/i18n/GetLanguageCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/i18n/GetLanguageCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/i18n/SetStringCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/i18n/SetStringCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/i18n/SetStringCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/i18n/SetStringCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/i18n/ViewLanguagesCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/i18n/ViewLanguagesCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/i18n/ViewLanguagesCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/i18n/ViewLanguagesCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/logs/GetEntryCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/logs/GetEntryCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/logs/GetEntryCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/logs/GetEntryCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/logs/ViewLogsCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/logs/ViewLogsCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/logs/ViewLogsCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/logs/ViewLogsCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/mntm/EnableMaintenanceCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/mntm/EnableMaintenanceCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/mntm/EnableMaintenanceCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/mntm/EnableMaintenanceCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/mntm/EndMaintenanceCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/mntm/EndMaintenanceCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/mntm/EndMaintenanceCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/mntm/EndMaintenanceCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/mntm/ExtendMaintenanceCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/mntm/ExtendMaintenanceCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/mntm/ExtendMaintenanceCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/mntm/ExtendMaintenanceCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/mntm/MaintenanceStatusCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/mntm/MaintenanceStatusCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/mntm/MaintenanceStatusCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/mntm/MaintenanceStatusCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/msgs/ComposeMessageCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/msgs/ComposeMessageCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/msgs/ComposeMessageCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/msgs/ComposeMessageCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/msgs/GetMessagesCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/msgs/GetMessagesCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/msgs/GetMessagesCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/msgs/GetMessagesCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/msgs/MessageBoxCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/msgs/MessageBoxCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/msgs/MessageBoxCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/msgs/MessageBoxCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/msgs/PrepareMessageCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/msgs/PrepareMessageCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/msgs/PrepareMessageCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/msgs/PrepareMessageCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/msgs/ReadMessageCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/msgs/ReadMessageCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/msgs/ReadMessageCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/msgs/ReadMessageCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/msgs/SendSpamCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/msgs/SendSpamCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/msgs/SendSpamCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/msgs/SendSpamCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/names/GetNamesCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/names/GetNamesCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/names/GetNamesCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/names/GetNamesCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/names/NamesActionCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/names/NamesActionCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/names/NamesActionCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/names/NamesActionCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/names/NamesSummaryCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/names/NamesSummaryCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/names/NamesSummaryCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/names/NamesSummaryCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/prefs/GetPrefDefaultsCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/prefs/GetPrefDefaultsCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/prefs/GetPrefDefaultsCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/prefs/GetPrefDefaultsCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/prefs/SetPrefDefaultCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/prefs/SetPrefDefaultCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/prefs/SetPrefDefaultCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/prefs/SetPrefDefaultCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/su/AddAdministratorCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/su/AddAdministratorCommandDelegateBean.java
similarity index 91%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/su/AddAdministratorCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/su/AddAdministratorCommandDelegateBean.java
index ee5aac1..8be8246 100644
--- a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/su/AddAdministratorCommandDelegateBean.java
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/su/AddAdministratorCommandDelegateBean.java
@@ -3,6 +3,7 @@ package com.deepclone.lw.beans.user.admin.main.su;
 
 import org.springframework.beans.factory.annotation.Autowired;
 
+import com.deepclone.lw.beans.user.ObjectNameValidatorBean;
 import com.deepclone.lw.cmd.ObjectNameError;
 import com.deepclone.lw.cmd.admin.adata.Administrator;
 import com.deepclone.lw.cmd.admin.adata.Privileges;
@@ -10,7 +11,6 @@ import com.deepclone.lw.cmd.admin.su.AddAdministratorCommand;
 import com.deepclone.lw.cmd.admin.su.AddAdministratorResponse;
 import com.deepclone.lw.cmd.admin.su.AddAdministratorResponse.AddressError;
 import com.deepclone.lw.interfaces.admin.Administration;
-import com.deepclone.lw.interfaces.naming.ObjectNameValidator;
 import com.deepclone.lw.session.Command;
 import com.deepclone.lw.session.CommandResponse;
 import com.deepclone.lw.utils.EmailAddress;
@@ -22,7 +22,7 @@ public class AddAdministratorCommandDelegateBean
 {
 
 	private Administration administration;
-	private ObjectNameValidator validator;
+	private ObjectNameValidatorBean validator;
 
 
 	@Autowired( required = true )
@@ -33,7 +33,7 @@ public class AddAdministratorCommandDelegateBean
 
 
 	@Autowired( required = true )
-	public void setValidator( ObjectNameValidator validator )
+	public void setValidator( ObjectNameValidatorBean validator )
 	{
 		this.validator = validator;
 	}
@@ -57,7 +57,7 @@ public class AddAdministratorCommandDelegateBean
 		if ( "".equals( name ) ) {
 			nameError = ObjectNameError.EMPTY;
 		} else {
-			nameError = this.validator.validate( name , 2 , 64 );
+			nameError = this.validator.customValidate( name , 2 , 64 );
 		}
 
 		// Check address
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/su/ListAdministratorsCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/su/ListAdministratorsCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/su/ListAdministratorsCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/su/ListAdministratorsCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/su/ResetAdminPasswordCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/su/ResetAdminPasswordCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/su/ResetAdminPasswordCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/su/ResetAdminPasswordCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/su/SUExistingOperation.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/su/SUExistingOperation.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/su/SUExistingOperation.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/su/SUExistingOperation.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/su/SetPrivilegesCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/su/SetPrivilegesCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/su/SetPrivilegesCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/su/SetPrivilegesCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/su/SuperUserOperation.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/su/SuperUserOperation.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/su/SuperUserOperation.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/su/SuperUserOperation.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/su/ViewAdministratorCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/su/ViewAdministratorCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/su/ViewAdministratorCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/su/ViewAdministratorCommandDelegateBean.java
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/techs/ListCategoriesCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/techs/ListCategoriesCommandDelegateBean.java
new file mode 100644
index 0000000..be5fc43
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/techs/ListCategoriesCommandDelegateBean.java
@@ -0,0 +1,59 @@
+package com.deepclone.lw.beans.user.admin.main.techs;
+
+
+import org.springframework.beans.factory.annotation.Autowired;
+
+import com.deepclone.lw.beans.user.abst.AutowiredCommandDelegate;
+import com.deepclone.lw.beans.user.abst.SessionCommandHandler;
+import com.deepclone.lw.beans.user.admin.common.AdminOperation;
+import com.deepclone.lw.beans.user.admin.main.AdminCommandsBean;
+import com.deepclone.lw.cmd.admin.adata.Administrator;
+import com.deepclone.lw.cmd.admin.adata.Privileges;
+import com.deepclone.lw.cmd.admin.techs.ListCategoriesCommand;
+import com.deepclone.lw.cmd.admin.techs.ListCategoriesResponse;
+import com.deepclone.lw.interfaces.game.techs.TechnologyGraphManager;
+import com.deepclone.lw.interfaces.session.ServerSession;
+import com.deepclone.lw.session.Command;
+import com.deepclone.lw.session.CommandResponse;
+
+
+
+public class ListCategoriesCommandDelegateBean
+		extends AdminOperation
+		implements AutowiredCommandDelegate
+{
+	private TechnologyGraphManager manager;
+
+
+	@Autowired( required = true )
+	public void setManager( TechnologyGraphManager manager )
+	{
+		this.manager = manager;
+	}
+
+
+	@Override
+	public Class< ? extends SessionCommandHandler > getCommandHandler( )
+	{
+		return AdminCommandsBean.class;
+	}
+
+
+	@Override
+	public Class< ? extends Command > getType( )
+	{
+		return ListCategoriesCommand.class;
+	}
+
+
+	@Override
+	public CommandResponse execute( ServerSession session , Command command )
+	{
+		Administrator admin = this.getAdministrator( session );
+		if ( !admin.hasPrivilege( Privileges.GDAT ) ) {
+			return new ListCategoriesResponse( admin );
+		}
+		return new ListCategoriesResponse( admin , this.manager.listCategories( ) );
+	}
+
+}
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/tick/SetTaskStatusCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/tick/SetTaskStatusCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/tick/SetTaskStatusCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/tick/SetTaskStatusCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/tick/TickerStatusCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/tick/TickerStatusCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/tick/TickerStatusCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/tick/TickerStatusCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/tick/ToggleTickerCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/tick/ToggleTickerCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/tick/ToggleTickerCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/tick/ToggleTickerCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/users/GiveCreditsCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/users/GiveCreditsCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/users/GiveCreditsCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/users/GiveCreditsCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/users/ListAccountsCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/users/ListAccountsCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/users/ListAccountsCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/users/ListAccountsCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/users/ListSessionsCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/users/ListSessionsCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/users/ListSessionsCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/users/ListSessionsCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/users/ViewAccountCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/users/ViewAccountCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/users/ViewAccountCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/admin/main/users/ViewAccountCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/ext/AccountCreationCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/ext/AccountCreationCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/ext/AccountCreationCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/ext/AccountCreationCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/ext/ConfPwdRecoveryCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/ext/ConfPwdRecoveryCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/ext/ConfPwdRecoveryCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/ext/ConfPwdRecoveryCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/ext/ExternalSessionDefinerBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/ext/ExternalSessionDefinerBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/ext/ExternalSessionDefinerBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/ext/ExternalSessionDefinerBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/ext/LanguageListRequired.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/ext/LanguageListRequired.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/ext/LanguageListRequired.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/ext/LanguageListRequired.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/ext/ListLanguagesCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/ext/ListLanguagesCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/ext/ListLanguagesCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/ext/ListLanguagesCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/ext/ReqPwdRecoveryCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/ext/ReqPwdRecoveryCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/ext/ReqPwdRecoveryCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/ext/ReqPwdRecoveryCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/BanDetailsCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/BanDetailsCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/BanDetailsCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/BanDetailsCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/BannedSubTypeBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/BannedSubTypeBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/BannedSubTypeBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/BannedSubTypeBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/DisabledSubTypeBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/DisabledSubTypeBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/DisabledSubTypeBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/DisabledSubTypeBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/GameSubTypeBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/GameSubTypeBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/GameSubTypeBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/GameSubTypeBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/GetLanguageCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/GetLanguageCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/GetLanguageCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/GetLanguageCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/PlayerCommonCommandsBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/PlayerCommonCommandsBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/PlayerCommonCommandsBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/PlayerCommonCommandsBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/PlayerSessionDefinerBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/PlayerSessionDefinerBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/PlayerSessionDefinerBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/PlayerSessionDefinerBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/PlayerSessionSubType.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/PlayerSessionSubType.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/PlayerSessionSubType.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/PlayerSessionSubType.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/ReactivateCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/ReactivateCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/ReactivateCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/ReactivateCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/ValidationCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/ValidationCommandDelegateBean.java
similarity index 95%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/ValidationCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/ValidationCommandDelegateBean.java
index 7235287..6633bb8 100644
--- a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/ValidationCommandDelegateBean.java
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/ValidationCommandDelegateBean.java
@@ -3,13 +3,13 @@ package com.deepclone.lw.beans.user.player;
 
 import org.springframework.beans.factory.annotation.Autowired;
 
+import com.deepclone.lw.beans.user.ObjectNameValidatorBean;
 import com.deepclone.lw.beans.user.abst.AutowiredCommandDelegate;
 import com.deepclone.lw.beans.user.abst.SessionCommandHandler;
 import com.deepclone.lw.cmd.ObjectNameError;
 import com.deepclone.lw.cmd.player.account.AccountValidationCommand;
 import com.deepclone.lw.cmd.player.account.AccountValidationResponse;
 import com.deepclone.lw.interfaces.acm.AccountManagement;
-import com.deepclone.lw.interfaces.naming.ObjectNameValidator;
 import com.deepclone.lw.interfaces.session.ServerSession;
 import com.deepclone.lw.session.Command;
 import com.deepclone.lw.session.CommandResponse;
@@ -23,7 +23,7 @@ public class ValidationCommandDelegateBean
 {
 
 	private AccountManagement manager;
-	private ObjectNameValidator validator;
+	private ObjectNameValidatorBean validator;
 
 
 	@Autowired( required = true )
@@ -34,7 +34,7 @@ public class ValidationCommandDelegateBean
 
 
 	@Autowired( required = true )
-	public void setObjectNameValidator( ObjectNameValidator validator )
+	public void setObjectNameValidator( ObjectNameValidatorBean validator )
 	{
 		this.validator = validator;
 	}
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/ValidationSubTypeBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/ValidationSubTypeBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/ValidationSubTypeBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/ValidationSubTypeBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/account/CancelQuitCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/account/CancelQuitCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/account/CancelQuitCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/account/CancelQuitCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/account/CreateAuthChallengeCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/account/CreateAuthChallengeCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/account/CreateAuthChallengeCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/account/CreateAuthChallengeCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/account/GetAccountCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/account/GetAccountCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/account/GetAccountCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/account/GetAccountCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/account/QuitGameCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/account/QuitGameCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/account/QuitGameCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/account/QuitGameCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/account/SetAddressCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/account/SetAddressCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/account/SetAddressCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/account/SetAddressCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/account/SetLanguageCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/account/SetLanguageCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/account/SetLanguageCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/account/SetLanguageCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/account/SetPasswordCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/account/SetPasswordCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/account/SetPasswordCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/account/SetPasswordCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/account/SetPreferencesCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/account/SetPreferencesCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/account/SetPreferencesCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/account/SetPreferencesCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/account/ToggleVacationCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/account/ToggleVacationCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/account/ToggleVacationCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/account/ToggleVacationCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/account/ValidateSetAddressCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/account/ValidateSetAddressCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/account/ValidateSetAddressCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/account/ValidateSetAddressCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/bt/ListBugsCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/bt/ListBugsCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/bt/ListBugsCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/bt/ListBugsCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/bt/PostCommentCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/bt/PostCommentCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/bt/PostCommentCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/bt/PostCommentCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/bt/ReportBugCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/bt/ReportBugCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/bt/ReportBugCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/bt/ReportBugCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/bt/ViewBugCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/bt/ViewBugCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/bt/ViewBugCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/bt/ViewBugCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/GetBattleCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/GetBattleCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/GetBattleCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/GetBattleCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/GetNewPlanetCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/GetNewPlanetCommandDelegateBean.java
similarity index 91%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/GetNewPlanetCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/GetNewPlanetCommandDelegateBean.java
index 9b0add8..e59bb96 100644
--- a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/GetNewPlanetCommandDelegateBean.java
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/GetNewPlanetCommandDelegateBean.java
@@ -3,6 +3,7 @@ package com.deepclone.lw.beans.user.player.game;
 
 import org.springframework.beans.factory.annotation.Autowired;
 
+import com.deepclone.lw.beans.user.ObjectNameValidatorBean;
 import com.deepclone.lw.beans.user.abst.AutowiredCommandDelegate;
 import com.deepclone.lw.beans.user.abst.SessionCommandHandler;
 import com.deepclone.lw.beans.user.player.GameSubTypeBean;
@@ -10,7 +11,6 @@ import com.deepclone.lw.cmd.ObjectNameError;
 import com.deepclone.lw.cmd.player.GetNewPlanetCommand;
 import com.deepclone.lw.cmd.player.GetNewPlanetResponse;
 import com.deepclone.lw.interfaces.game.EmpireManagement;
-import com.deepclone.lw.interfaces.naming.ObjectNameValidator;
 import com.deepclone.lw.interfaces.session.ServerSession;
 import com.deepclone.lw.session.Command;
 import com.deepclone.lw.session.CommandResponse;
@@ -23,7 +23,7 @@ public class GetNewPlanetCommandDelegateBean
 {
 
 	private EmpireManagement empireManagement;
-	private ObjectNameValidator validator;
+	private ObjectNameValidatorBean validator;
 
 
 	@Autowired( required = true )
@@ -34,7 +34,7 @@ public class GetNewPlanetCommandDelegateBean
 
 
 	@Autowired( required = true )
-	public void setObjectNameValidator( ObjectNameValidator validator )
+	public void setObjectNameValidator( ObjectNameValidatorBean validator )
 	{
 		this.validator = validator;
 	}
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/ListBattlesCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/ListBattlesCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/ListBattlesCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/ListBattlesCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/ListPlanetsCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/ListPlanetsCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/ListPlanetsCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/ListPlanetsCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/OverviewCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/OverviewCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/OverviewCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/OverviewCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/ViewMapCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/ViewMapCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/ViewMapCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/ViewMapCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/alliances/AllianceStatusCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/alliances/AllianceStatusCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/alliances/AllianceStatusCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/alliances/AllianceStatusCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/alliances/CancelJoinCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/alliances/CancelJoinCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/alliances/CancelJoinCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/alliances/CancelJoinCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/alliances/CreateAllianceCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/alliances/CreateAllianceCommandDelegateBean.java
similarity index 87%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/alliances/CreateAllianceCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/alliances/CreateAllianceCommandDelegateBean.java
index fbaa298..607054a 100644
--- a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/alliances/CreateAllianceCommandDelegateBean.java
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/alliances/CreateAllianceCommandDelegateBean.java
@@ -3,6 +3,7 @@ package com.deepclone.lw.beans.user.player.game.alliances;
 
 import org.springframework.beans.factory.annotation.Autowired;
 
+import com.deepclone.lw.beans.user.ObjectNameValidatorBean;
 import com.deepclone.lw.beans.user.abst.AutowiredCommandDelegate;
 import com.deepclone.lw.beans.user.abst.SessionCommandHandler;
 import com.deepclone.lw.beans.user.player.GameSubTypeBean;
@@ -12,7 +13,6 @@ import com.deepclone.lw.cmd.player.alliances.CreateAllianceCommand;
 import com.deepclone.lw.cmd.player.alliances.CreateAllianceResponse;
 import com.deepclone.lw.cmd.player.gdata.alliance.AllianceCreationStatus;
 import com.deepclone.lw.interfaces.game.AllianceManagement;
-import com.deepclone.lw.interfaces.naming.ObjectNameValidator;
 import com.deepclone.lw.interfaces.session.ServerSession;
 import com.deepclone.lw.session.Command;
 import com.deepclone.lw.session.CommandResponse;
@@ -24,7 +24,7 @@ public class CreateAllianceCommandDelegateBean
 {
 
 	private AllianceManagement allianceManagement;
-	private ObjectNameValidator validator;
+	private ObjectNameValidatorBean validator;
 
 
 	@Autowired( required = true )
@@ -35,7 +35,7 @@ public class CreateAllianceCommandDelegateBean
 
 
 	@Autowired( required = true )
-	public void setObjectNameValidator( ObjectNameValidator validator )
+	public void setObjectNameValidator( ObjectNameValidatorBean validator )
 	{
 		this.validator = validator;
 	}
@@ -65,10 +65,10 @@ public class CreateAllianceCommandDelegateBean
 		}
 
 		String tag = command.getTag( );
-		ObjectNameError tagError = this.validator.validate( tag , 2 , 5 );
+		ObjectNameError tagError = this.validator.customValidate( tag , 2 , 5 );
 
 		String name = command.getName( );
-		ObjectNameError nameError = this.validator.validate( name , 5 , 64 );
+		ObjectNameError nameError = this.validator.customValidate( name , 5 , 64 );
 
 		if ( tagError != null || nameError != null ) {
 			AllianceStatusResponse r = this.allianceManagement.getView( empireId );
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/alliances/JoinAllianceCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/alliances/JoinAllianceCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/alliances/JoinAllianceCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/alliances/JoinAllianceCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/alliances/KickMembersCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/alliances/KickMembersCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/alliances/KickMembersCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/alliances/KickMembersCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/alliances/LeaveAllianceCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/alliances/LeaveAllianceCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/alliances/LeaveAllianceCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/alliances/LeaveAllianceCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/alliances/ManageRequestsCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/alliances/ManageRequestsCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/alliances/ManageRequestsCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/alliances/ManageRequestsCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/alliances/TransferLeadershipCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/alliances/TransferLeadershipCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/alliances/TransferLeadershipCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/alliances/TransferLeadershipCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/alliances/ViewAllianceCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/alliances/ViewAllianceCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/alliances/ViewAllianceCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/alliances/ViewAllianceCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/elist/AddEnemyCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/elist/AddEnemyCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/elist/AddEnemyCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/elist/AddEnemyCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/elist/EnemyListCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/elist/EnemyListCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/elist/EnemyListCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/elist/EnemyListCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/elist/RemoveEnemiesCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/elist/RemoveEnemiesCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/elist/RemoveEnemiesCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/elist/RemoveEnemiesCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/fleets/DisbandFleetsCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/fleets/DisbandFleetsCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/fleets/DisbandFleetsCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/fleets/DisbandFleetsCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/fleets/MergeFleetsCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/fleets/MergeFleetsCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/fleets/MergeFleetsCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/fleets/MergeFleetsCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/fleets/MoveFleetsCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/fleets/MoveFleetsCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/fleets/MoveFleetsCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/fleets/MoveFleetsCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/fleets/RenameFleetsCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/fleets/RenameFleetsCommandDelegateBean.java
similarity index 88%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/fleets/RenameFleetsCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/fleets/RenameFleetsCommandDelegateBean.java
index 3f57dc8..240c345 100644
--- a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/fleets/RenameFleetsCommandDelegateBean.java
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/fleets/RenameFleetsCommandDelegateBean.java
@@ -3,13 +3,13 @@ package com.deepclone.lw.beans.user.player.game.fleets;
 
 import org.springframework.beans.factory.annotation.Autowired;
 
+import com.deepclone.lw.beans.user.ObjectNameValidatorBean;
 import com.deepclone.lw.beans.user.abst.AutowiredCommandDelegate;
 import com.deepclone.lw.beans.user.abst.SessionCommandHandler;
 import com.deepclone.lw.beans.user.player.GameSubTypeBean;
 import com.deepclone.lw.cmd.player.fleets.RenameFleetsCommand;
 import com.deepclone.lw.cmd.player.fleets.RenameFleetsResponse;
 import com.deepclone.lw.interfaces.game.FleetManagement;
-import com.deepclone.lw.interfaces.naming.ObjectNameValidator;
 import com.deepclone.lw.interfaces.session.ServerSession;
 import com.deepclone.lw.session.Command;
 import com.deepclone.lw.session.CommandResponse;
@@ -20,7 +20,7 @@ public class RenameFleetsCommandDelegateBean
 		implements AutowiredCommandDelegate
 {
 	private FleetManagement fleetManager;
-	private ObjectNameValidator validator;
+	private ObjectNameValidatorBean validator;
 
 
 	@Autowired( required = true )
@@ -31,7 +31,7 @@ public class RenameFleetsCommandDelegateBean
 
 
 	@Autowired( required = true )
-	public void setObjectNameValidator( ObjectNameValidator validator )
+	public void setObjectNameValidator( ObjectNameValidatorBean validator )
 	{
 		this.validator = validator;
 	}
@@ -64,7 +64,7 @@ public class RenameFleetsCommandDelegateBean
 		boolean error;
 		if ( command.isRename( ) ) {
 			name = command.getName( ).trim( );
-			if ( !"".equals( name ) && this.validator.validate( name , 1 , 40 ) != null ) {
+			if ( !"".equals( name ) && this.validator.customValidate( name , 1 , 40 ) != null ) {
 				error = true;
 				name = null;
 			} else {
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/fleets/SetFleetsModeCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/fleets/SetFleetsModeCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/fleets/SetFleetsModeCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/fleets/SetFleetsModeCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/fleets/SplitFleetCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/fleets/SplitFleetCommandDelegateBean.java
similarity index 88%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/fleets/SplitFleetCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/fleets/SplitFleetCommandDelegateBean.java
index 47e1a17..3d77684 100644
--- a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/fleets/SplitFleetCommandDelegateBean.java
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/fleets/SplitFleetCommandDelegateBean.java
@@ -3,13 +3,13 @@ package com.deepclone.lw.beans.user.player.game.fleets;
 
 import org.springframework.beans.factory.annotation.Autowired;
 
+import com.deepclone.lw.beans.user.ObjectNameValidatorBean;
 import com.deepclone.lw.beans.user.abst.AutowiredCommandDelegate;
 import com.deepclone.lw.beans.user.abst.SessionCommandHandler;
 import com.deepclone.lw.beans.user.player.GameSubTypeBean;
 import com.deepclone.lw.cmd.player.fleets.SplitFleetCommand;
 import com.deepclone.lw.cmd.player.fleets.SplitFleetResponse;
 import com.deepclone.lw.interfaces.game.FleetManagement;
-import com.deepclone.lw.interfaces.naming.ObjectNameValidator;
 import com.deepclone.lw.interfaces.session.ServerSession;
 import com.deepclone.lw.session.Command;
 import com.deepclone.lw.session.CommandResponse;
@@ -20,7 +20,7 @@ public class SplitFleetCommandDelegateBean
 		implements AutowiredCommandDelegate
 {
 	private FleetManagement fleetManager;
-	private ObjectNameValidator validator;
+	private ObjectNameValidatorBean validator;
 
 
 	@Autowired( required = true )
@@ -31,7 +31,7 @@ public class SplitFleetCommandDelegateBean
 
 
 	@Autowired( required = true )
-	public void setObjectNameValidator( ObjectNameValidator validator )
+	public void setObjectNameValidator( ObjectNameValidatorBean validator )
 	{
 		this.validator = validator;
 	}
@@ -64,7 +64,7 @@ public class SplitFleetCommandDelegateBean
 		boolean error;
 		if ( name != null ) {
 			name = command.getName( ).trim( );
-			if ( !"".equals( name ) && this.validator.validate( name , 1 , 40 ) != null ) {
+			if ( !"".equals( name ) && this.validator.customValidate( name , 1 , 40 ) != null ) {
 				error = true;
 				name = "";
 			} else {
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/fleets/ViewFleetsCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/fleets/ViewFleetsCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/fleets/ViewFleetsCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/fleets/ViewFleetsCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/planets/AbandonPlanetCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/planets/AbandonPlanetCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/planets/AbandonPlanetCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/planets/AbandonPlanetCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/planets/BuildingActionCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/planets/BuildingActionCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/planets/BuildingActionCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/planets/BuildingActionCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/planets/FlushQueueCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/planets/FlushQueueCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/planets/FlushQueueCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/planets/FlushQueueCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/planets/RenamePlanetCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/planets/RenamePlanetCommandDelegateBean.java
similarity index 92%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/planets/RenamePlanetCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/planets/RenamePlanetCommandDelegateBean.java
index 73b07c3..f006bee 100644
--- a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/planets/RenamePlanetCommandDelegateBean.java
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/planets/RenamePlanetCommandDelegateBean.java
@@ -3,6 +3,7 @@ package com.deepclone.lw.beans.user.player.game.planets;
 
 import org.springframework.beans.factory.annotation.Autowired;
 
+import com.deepclone.lw.beans.user.ObjectNameValidatorBean;
 import com.deepclone.lw.beans.user.abst.AutowiredCommandDelegate;
 import com.deepclone.lw.beans.user.abst.SessionCommandHandler;
 import com.deepclone.lw.beans.user.player.GameSubTypeBean;
@@ -11,7 +12,6 @@ import com.deepclone.lw.cmd.player.planets.RenamePlanetCommand;
 import com.deepclone.lw.cmd.player.planets.RenamePlanetResponse;
 import com.deepclone.lw.cmd.player.planets.ViewPlanetResponse;
 import com.deepclone.lw.interfaces.game.PlanetsManagement;
-import com.deepclone.lw.interfaces.naming.ObjectNameValidator;
 import com.deepclone.lw.interfaces.session.ServerSession;
 import com.deepclone.lw.session.Command;
 import com.deepclone.lw.session.CommandResponse;
@@ -24,7 +24,7 @@ public class RenamePlanetCommandDelegateBean
 {
 
 	private PlanetsManagement planetsManagement;
-	private ObjectNameValidator validator;
+	private ObjectNameValidatorBean validator;
 
 
 	@Autowired( required = true )
@@ -35,7 +35,7 @@ public class RenamePlanetCommandDelegateBean
 
 
 	@Autowired( required = true )
-	public void setObjectNameValidator( ObjectNameValidator validator )
+	public void setObjectNameValidator( ObjectNameValidatorBean validator )
 	{
 		this.validator = validator;
 	}
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/planets/ShipBuildingCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/planets/ShipBuildingCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/planets/ShipBuildingCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/planets/ShipBuildingCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/planets/ViewPlanetCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/planets/ViewPlanetCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/planets/ViewPlanetCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/planets/ViewPlanetCommandDelegateBean.java
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/techs/ImplementTechCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/techs/ImplementTechCommandDelegateBean.java
new file mode 100644
index 0000000..a0bc22a
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/techs/ImplementTechCommandDelegateBean.java
@@ -0,0 +1,57 @@
+package com.deepclone.lw.beans.user.player.game.techs;
+
+
+import org.springframework.beans.factory.annotation.Autowired;
+
+import com.deepclone.lw.beans.user.abst.AutowiredCommandDelegate;
+import com.deepclone.lw.beans.user.abst.SessionCommandHandler;
+import com.deepclone.lw.beans.user.player.GameSubTypeBean;
+import com.deepclone.lw.cmd.player.research.ImplementTechCommand;
+import com.deepclone.lw.cmd.player.research.ResearchOperationResponse;
+import com.deepclone.lw.interfaces.game.techs.EmpireTechnologyManager;
+import com.deepclone.lw.interfaces.session.ServerSession;
+import com.deepclone.lw.session.Command;
+import com.deepclone.lw.session.CommandResponse;
+
+
+
+public class ImplementTechCommandDelegateBean
+		implements AutowiredCommandDelegate
+
+{
+
+	private EmpireTechnologyManager techManagement;
+
+
+	@Autowired( required = true )
+	public void setEmpireManager( EmpireTechnologyManager manager )
+	{
+		this.techManagement = manager;
+	}
+
+
+	@Override
+	public Class< ? extends Command > getType( )
+	{
+		return ImplementTechCommand.class;
+	}
+
+
+	@Override
+	public Class< ? extends SessionCommandHandler > getCommandHandler( )
+	{
+		return GameSubTypeBean.class;
+	}
+
+
+	@Override
+	public CommandResponse execute( ServerSession session , Command cParam )
+	{
+		ImplementTechCommand command = (ImplementTechCommand) cParam;
+		int empireId = session.get( "empireId" , Integer.class );
+		if ( session.get( "vacation" , Boolean.class ) ) {
+			return new ResearchOperationResponse( );
+		}
+		return this.techManagement.implementTechnology( empireId , command.getTech( ) );
+	}
+}
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/techs/SetResearchPrioritiesCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/techs/SetResearchPrioritiesCommandDelegateBean.java
new file mode 100644
index 0000000..58923ad
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/techs/SetResearchPrioritiesCommandDelegateBean.java
@@ -0,0 +1,56 @@
+package com.deepclone.lw.beans.user.player.game.techs;
+
+
+import org.springframework.beans.factory.annotation.Autowired;
+
+import com.deepclone.lw.beans.user.abst.AutowiredCommandDelegate;
+import com.deepclone.lw.beans.user.abst.SessionCommandHandler;
+import com.deepclone.lw.beans.user.player.GameSubTypeBean;
+import com.deepclone.lw.cmd.player.research.ResearchOperationResponse;
+import com.deepclone.lw.cmd.player.research.SetResearchPrioritiesCommand;
+import com.deepclone.lw.interfaces.game.techs.EmpireTechnologyManager;
+import com.deepclone.lw.interfaces.session.ServerSession;
+import com.deepclone.lw.session.Command;
+import com.deepclone.lw.session.CommandResponse;
+
+
+
+public class SetResearchPrioritiesCommandDelegateBean
+		implements AutowiredCommandDelegate
+{
+
+	private EmpireTechnologyManager techManagement;
+
+
+	@Autowired( required = true )
+	public void setEmpireManager( EmpireTechnologyManager manager )
+	{
+		this.techManagement = manager;
+	}
+
+
+	@Override
+	public Class< ? extends Command > getType( )
+	{
+		return SetResearchPrioritiesCommand.class;
+	}
+
+
+	@Override
+	public Class< ? extends SessionCommandHandler > getCommandHandler( )
+	{
+		return GameSubTypeBean.class;
+	}
+
+
+	@Override
+	public CommandResponse execute( ServerSession session , Command cParam )
+	{
+		SetResearchPrioritiesCommand command = (SetResearchPrioritiesCommand) cParam;
+		int empireId = session.get( "empireId" , Integer.class );
+		if ( session.get( "vacation" , Boolean.class ) ) {
+			return new ResearchOperationResponse( );
+		}
+		return this.techManagement.setResearchPriorities( empireId , command.getPriorities( ) );
+	}
+}
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/techs/ViewResearchCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/techs/ViewResearchCommandDelegateBean.java
new file mode 100644
index 0000000..d54061b
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/game/techs/ViewResearchCommandDelegateBean.java
@@ -0,0 +1,52 @@
+package com.deepclone.lw.beans.user.player.game.techs;
+
+
+import org.springframework.beans.factory.annotation.Autowired;
+
+import com.deepclone.lw.beans.user.abst.AutowiredCommandDelegate;
+import com.deepclone.lw.beans.user.abst.SessionCommandHandler;
+import com.deepclone.lw.beans.user.player.GameSubTypeBean;
+import com.deepclone.lw.cmd.player.research.ViewResearchCommand;
+import com.deepclone.lw.interfaces.game.techs.EmpireTechnologyManager;
+import com.deepclone.lw.interfaces.session.ServerSession;
+import com.deepclone.lw.session.Command;
+import com.deepclone.lw.session.CommandResponse;
+
+
+
+public class ViewResearchCommandDelegateBean
+		implements AutowiredCommandDelegate
+{
+
+	private EmpireTechnologyManager techManagement;
+
+
+	@Autowired( required = true )
+	public void setEmpireManager( EmpireTechnologyManager manager )
+	{
+		this.techManagement = manager;
+	}
+
+
+	@Override
+	public Class< ? extends Command > getType( )
+	{
+		return ViewResearchCommand.class;
+	}
+
+
+	@Override
+	public Class< ? extends SessionCommandHandler > getCommandHandler( )
+	{
+		return GameSubTypeBean.class;
+	}
+
+
+	@Override
+	public CommandResponse execute( ServerSession session , Command cParam )
+	{
+		int empireId = session.get( "empireId" , Integer.class );
+		return this.techManagement.getResearchData( empireId );
+	}
+
+}
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/msgs/ComposeMessageCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/msgs/ComposeMessageCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/msgs/ComposeMessageCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/msgs/ComposeMessageCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/msgs/GetMessagesCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/msgs/GetMessagesCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/msgs/GetMessagesCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/msgs/GetMessagesCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/msgs/ListTargetsCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/msgs/ListTargetsCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/msgs/ListTargetsCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/msgs/ListTargetsCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/msgs/MessageBoxCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/msgs/MessageBoxCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/msgs/MessageBoxCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/msgs/MessageBoxCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/msgs/PrepareMessageCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/msgs/PrepareMessageCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/msgs/PrepareMessageCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/msgs/PrepareMessageCommandDelegateBean.java
diff --git a/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/msgs/ReadMessageCommandDelegateBean.java b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/msgs/ReadMessageCommandDelegateBean.java
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/msgs/ReadMessageCommandDelegateBean.java
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/java/com/deepclone/lw/beans/user/player/msgs/ReadMessageCommandDelegateBean.java
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/resources/configuration/user-beans.xml b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/resources/configuration/user-beans.xml
new file mode 100644
index 0000000..3c1c824
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/resources/configuration/user-beans.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="
+                        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
+
+	<import resource="user/admin-session-definer-bean.xml" />
+	<import resource="user/external-session-definer-bean.xml" />
+	<import resource="user/object-name-validator-bean.xml" />
+	<import resource="user/player-session-definer-bean.xml" />
+	<import resource="user/session-command-wiring-bean.xml" />
+	<import resource="user/session-subtype-wiring-bean.xml" />
+
+</beans>
diff --git a/legacyworlds-server-beans-user/src/main/resources/configuration/session-types/administration.xml b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/resources/configuration/user/admin-session-definer-bean.xml
similarity index 98%
rename from legacyworlds-server-beans-user/src/main/resources/configuration/session-types/administration.xml
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/resources/configuration/user/admin-session-definer-bean.xml
index deab9c8..9ee2df0 100644
--- a/legacyworlds-server-beans-user/src/main/resources/configuration/session-types/administration.xml
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/resources/configuration/user/admin-session-definer-bean.xml
@@ -93,5 +93,8 @@
 	<bean class="com.deepclone.lw.beans.user.admin.main.mntm.EnableMaintenanceCommandDelegateBean" />
 	<bean class="com.deepclone.lw.beans.user.admin.main.mntm.EndMaintenanceCommandDelegateBean" />
 	<bean class="com.deepclone.lw.beans.user.admin.main.mntm.ExtendMaintenanceCommandDelegateBean" />
+	
+	<!-- Technology graph -->
+	<bean class="com.deepclone.lw.beans.user.admin.main.techs.ListCategoriesCommandDelegateBean" />
 
 </beans>
diff --git a/legacyworlds-server-beans-user/src/main/resources/configuration/session-types/external.xml b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/resources/configuration/user/external-session-definer-bean.xml
similarity index 100%
rename from legacyworlds-server-beans-user/src/main/resources/configuration/session-types/external.xml
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/resources/configuration/user/external-session-definer-bean.xml
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/resources/configuration/user/object-name-validator-bean.xml b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/resources/configuration/user/object-name-validator-bean.xml
new file mode 100644
index 0000000..7d06f66
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/resources/configuration/user/object-name-validator-bean.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="
+                        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
+
+	<bean id="objectNameValidator" class="com.deepclone.lw.beans.user.ObjectNameValidatorBean" />
+
+</beans>
diff --git a/legacyworlds-server-beans-user/src/main/resources/configuration/session-types/player.xml b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/resources/configuration/user/player-session-definer-bean.xml
similarity index 91%
rename from legacyworlds-server-beans-user/src/main/resources/configuration/session-types/player.xml
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/resources/configuration/user/player-session-definer-bean.xml
index 8398256..16a23e9 100644
--- a/legacyworlds-server-beans-user/src/main/resources/configuration/session-types/player.xml
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/resources/configuration/user/player-session-definer-bean.xml
@@ -44,13 +44,12 @@
 
 	<!-- Game: empire -->
 	<bean class="com.deepclone.lw.beans.user.player.game.OverviewCommandDelegateBean" />
-	<bean class="com.deepclone.lw.beans.user.player.game.tech.ImplementTechCommandDelegateBean" />
-	<bean class="com.deepclone.lw.beans.user.player.game.UpdateEmpireMiningSettingsCommandDelegateBean" />
 	<bean class="com.deepclone.lw.beans.user.player.game.GetNewPlanetCommandDelegateBean" />
 	
-	<!-- Game: research -->
-	<bean class="com.deepclone.lw.beans.user.player.game.tech.GetResearchCommandDelegateBean" />
-	<bean class="com.deepclone.lw.beans.user.player.game.tech.UpdateResearchPrioritiesCommandDelegateBean" />
+	<!-- Game: technologies -->
+	<bean class="com.deepclone.lw.beans.user.player.game.techs.ViewResearchCommandDelegateBean" />
+	<bean class="com.deepclone.lw.beans.user.player.game.techs.ImplementTechCommandDelegateBean" />
+	<bean class="com.deepclone.lw.beans.user.player.game.techs.SetResearchPrioritiesCommandDelegateBean" />
 
 	<!-- Game: planet list -->
 	<bean class="com.deepclone.lw.beans.user.player.game.ListPlanetsCommandDelegateBean" />
@@ -65,8 +64,6 @@
 	<bean class="com.deepclone.lw.beans.user.player.game.planets.FlushQueueCommandDelegateBean" />
 	<bean class="com.deepclone.lw.beans.user.player.game.planets.RenamePlanetCommandDelegateBean" />
 	<bean class="com.deepclone.lw.beans.user.player.game.planets.AbandonPlanetCommandDelegateBean" />
-	<bean class="com.deepclone.lw.beans.user.player.game.planets.ToggleMiningSettingsCommandDelegateBean" />
-	<bean class="com.deepclone.lw.beans.user.player.game.planets.UpdatePlanetMiningSettingsCommandDelegateBean" />
 
 	<!-- Game: enemy list -->
 	<bean class="com.deepclone.lw.beans.user.player.game.elist.EnemyListCommandDelegateBean" />
diff --git a/legacyworlds-server-beans-user/src/main/resources/configuration/meta/sessions.xml b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/resources/configuration/user/session-command-wiring-bean.xml
similarity index 66%
rename from legacyworlds-server-beans-user/src/main/resources/configuration/meta/sessions.xml
rename to legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/resources/configuration/user/session-command-wiring-bean.xml
index b676198..da9ba6d 100644
--- a/legacyworlds-server-beans-user/src/main/resources/configuration/meta/sessions.xml
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/resources/configuration/user/session-command-wiring-bean.xml
@@ -2,9 +2,8 @@
 <beans xmlns="http://www.springframework.org/schema/beans"
 	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 	xsi:schemaLocation="
-                        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
+                        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
 
 	<bean id="sessionCommandWiring" class="com.deepclone.lw.beans.user.abst.SessionCommandWiringBean" />
-	<bean id="sessionSubTypeWiring" class="com.deepclone.lw.beans.user.abst.SessionSubTypeWiringBean" />
 
-</beans>
\ No newline at end of file
+</beans>
diff --git a/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/resources/configuration/user/session-subtype-wiring-bean.xml b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/resources/configuration/user/session-subtype-wiring-bean.xml
new file mode 100644
index 0000000..5713773
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/legacyworlds-server-beans-user/src/main/resources/configuration/user/session-subtype-wiring-bean.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="
+                        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
+
+	<bean id="sessionSubTypeWiring" class="com.deepclone.lw.beans.user.abst.SessionSubTypeWiringBean" />
+
+</beans>
diff --git a/legacyworlds-server/legacyworlds-server-beans/pom.xml b/legacyworlds-server/legacyworlds-server-beans/pom.xml
new file mode 100644
index 0000000..b93a25f
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-beans/pom.xml
@@ -0,0 +1,39 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+	<parent>
+		<artifactId>legacyworlds-server</artifactId>
+		<groupId>com.deepclone.lw</groupId>
+		<version>5.99.2</version>
+	</parent>
+
+	<groupId>com.deepclone.lw</groupId>
+	<artifactId>legacyworlds-server-beans</artifactId>
+	<name>Legacy Worlds server beans</name>
+	<version>5.99.2</version>
+	<packaging>pom</packaging>
+	<description>This metapackage regroups all packages which define beans for the Legacy Worlds server.</description>
+
+	<dependencies>
+		<dependency>
+			<groupId>com.deepclone.lw</groupId>
+			<artifactId>legacyworlds-server-interfaces</artifactId>
+			<version>${project.version}</version>
+		</dependency>
+	</dependencies>
+
+	<modules>
+		<module>legacyworlds-server-beans-i18n</module>
+		<module>legacyworlds-server-beans-eventlog</module>
+		<module>legacyworlds-server-beans-accounts</module>
+		<module>legacyworlds-server-beans-mailer</module>
+		<module>legacyworlds-server-beans-system</module>
+		<module>legacyworlds-server-beans-naming</module>
+		<module>legacyworlds-server-beans-bt</module>
+		<module>legacyworlds-server-beans-user</module>
+		<module>legacyworlds-server-beans-simple</module>
+		<module>legacyworlds-server-beans-techs</module>
+		<module>legacyworlds-server-beans-updates</module>
+		<module>legacyworlds-server-beans-events</module>
+	</modules>
+</project>
diff --git a/legacyworlds-server/legacyworlds-server-data/.classpath b/legacyworlds-server/legacyworlds-server-data/.classpath
new file mode 100644
index 0000000..7c3d14f
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-data/.classpath
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" output="target/classes" path="src/main/java"/>
+	<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources"/>
+	<classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
+	<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+	<classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER"/>
+	<classpathentry kind="output" path="target/classes"/>
+</classpath>
diff --git a/legacyworlds-server/legacyworlds-server-data/.project b/legacyworlds-server/legacyworlds-server-data/.project
new file mode 100644
index 0000000..e0c56e5
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-data/.project
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>legacyworlds-server-data</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.maven.ide.eclipse.maven2Builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.maven.ide.eclipse.maven2Nature</nature>
+	</natures>
+</projectDescription>
diff --git a/legacyworlds-server/legacyworlds-server-data/.settings/org.eclipse.jdt.core.prefs b/legacyworlds-server/legacyworlds-server-data/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..b66e1f0
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-data/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,6 @@
+#Fri Apr 09 10:19:59 CEST 2010
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.6
diff --git a/legacyworlds-server-data/db-structure/database.sql b/legacyworlds-server/legacyworlds-server-data/db-structure/database.sql
similarity index 70%
rename from legacyworlds-server-data/db-structure/database.sql
rename to legacyworlds-server/legacyworlds-server-data/db-structure/database.sql
index 9552e38..675eeb6 100644
--- a/legacyworlds-server-data/db-structure/database.sql
+++ b/legacyworlds-server/legacyworlds-server-data/db-structure/database.sql
@@ -1,29 +1,21 @@
 -- LegacyWorlds Beta 6
 -- PostgreSQL database scripts
 --
--- Main database loader script
+-- Main database script
 --
 -- Initialises the various roles and the database itself,
 -- then processes scripts from the "parts" directory.
 --
--- Copyright(C) 2004-2012, DeepClone Development
+-- Copyright(C) 2004-2010, DeepClone Development
 -- --------------------------------------------------------
 
 -- Read configuration from file
 \set pgadmin `grep ^admin= db-config.txt | sed -e s/.*=//`
 \set dbname `grep ^db= db-config.txt | sed -e s/.*=//`
-\set dbname_string '''':dbname''''
 \set dbuser `grep ^user= db-config.txt | sed -e s/.*=//`
-\set dbuser_string '''':dbuser''''
 \set dbupass ''''`grep ^password= db-config.txt | sed -e s/.*=// -e "s/'/''/g"`''''
 
 
-/* List all files in the "parts" directory and create a loader script from
- * that.
- */
-\! find parts -type f -name '*.sql' | sort | sed -e 's/^/\\i /' > loader.tmp
-
-
 -- Connect to the main system database
 \c postgres :pgadmin
 
@@ -42,10 +34,21 @@ GRANT CONNECT ON DATABASE :dbname TO :dbuser;
 -- Connect to the LW database with the PostgreSQL admin user
 \c :dbname :pgadmin
 
-/* Load everything from the loader script */
-BEGIN;
-\i loader.tmp
-COMMIT;
+-- Register PL/PgSQL
+CREATE TRUSTED PROCEDURAL LANGUAGE plpgsql;
 
-/* Delete loader script */
-\! rm loader.tmp
+BEGIN;
+
+-- Create database schemas
+\i parts/000-schemas.sql
+
+-- Process structure definition scripts
+\i parts/010-data.sql
+
+-- Process functions and views definition scripts
+\i parts/020-functions.sql
+
+-- Process game update functions
+\i parts/030-updates.sql
+
+COMMIT;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/db-config.sample.txt b/legacyworlds-server/legacyworlds-server-data/db-structure/db-config.txt
similarity index 100%
rename from legacyworlds-server-data/db-structure/db-config.sample.txt
rename to legacyworlds-server/legacyworlds-server-data/db-structure/db-config.txt
diff --git a/legacyworlds-server-data/db-structure/parts/010-schemas.sql b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/000-schemas.sql
similarity index 100%
rename from legacyworlds-server-data/db-structure/parts/010-schemas.sql
rename to legacyworlds-server/legacyworlds-server-data/db-structure/parts/000-schemas.sql
diff --git a/legacyworlds-server/legacyworlds-server-data/db-structure/parts/010-data.sql b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/010-data.sql
new file mode 100644
index 0000000..add939b
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/010-data.sql
@@ -0,0 +1,29 @@
+-- LegacyWorlds Beta 6
+-- PostgreSQL database scripts
+--
+-- Structures creation
+--
+-- Copyright(C) 2004-2010, DeepClone Development
+-- --------------------------------------------------------
+
+\i parts/data/000-typedefs.sql
+\i parts/data/010-i18n-data.sql
+\i parts/data/020-prefs-data.sql
+\i parts/data/030-users-data.sql
+\i parts/data/035-session-data.sql
+\i parts/data/040-admin-data.sql
+\i parts/data/050-accounts-data.sql
+\i parts/data/055-bugs-data.sql
+\i parts/data/060-naming-data.sql
+\i parts/data/070-constants-data.sql
+\i parts/data/080-techs-data.sql
+\i parts/data/090-buildables-data.sql
+\i parts/data/100-universe-data.sql
+\i parts/data/110-empires-data.sql
+\i parts/data/120-construction-data.sql
+\i parts/data/130-fleets-data.sql
+\i parts/data/140-status-data.sql
+\i parts/data/150-logs-data.sql
+\i parts/data/160-battle-data.sql
+\i parts/data/170-events-data.sql
+\i parts/data/180-messages-data.sql
\ No newline at end of file
diff --git a/legacyworlds-server/legacyworlds-server-data/db-structure/parts/020-functions.sql b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/020-functions.sql
new file mode 100644
index 0000000..3ef2d79
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/020-functions.sql
@@ -0,0 +1,37 @@
+-- LegacyWorlds Beta 6
+-- PostgreSQL database scripts
+--
+-- Functions and views
+--
+-- Copyright(C) 2004-2010, DeepClone Development
+-- --------------------------------------------------------
+
+\i parts/functions/000-defs-functions.sql
+\i parts/functions/002-sys-functions.sql
+\i parts/functions/005-logs-functions.sql
+\i parts/functions/010-constants-functions.sql
+\i parts/functions/020-naming-functions.sql
+\i parts/functions/030-tech-functions.sql
+\i parts/functions/035-users-view.sql
+\i parts/functions/040-empire-functions.sql
+\i parts/functions/045-research-functions.sql
+\i parts/functions/050-computation-functions.sql
+\i parts/functions/060-universe-functions.sql
+\i parts/functions/070-users-functions.sql
+\i parts/functions/075-session-functions.sql
+\i parts/functions/080-buildings-functions.sql
+\i parts/functions/100-status-functions.sql
+\i parts/functions/110-prefs-functions.sql
+\i parts/functions/120-map-functions.sql
+\i parts/functions/140-planets-functions.sql
+\i parts/functions/150-battle-functions.sql
+\i parts/functions/160-battle-views.sql
+\i parts/functions/163-alliance-functions.sql
+\i parts/functions/165-fleets-functions.sql
+\i parts/functions/167-planet-list.sql
+\i parts/functions/170-event-functions.sql
+\i parts/functions/180-messages-functions.sql
+\i parts/functions/190-admin-functions.sql
+\i parts/functions/200-bugs-functions.sql
+\i parts/functions/210-admin-overview.sql
+
diff --git a/legacyworlds-server/legacyworlds-server-data/db-structure/parts/030-updates.sql b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/030-updates.sql
new file mode 100644
index 0000000..47862f5
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/030-updates.sql
@@ -0,0 +1,22 @@
+-- LegacyWorlds Beta 6
+-- PostgreSQL database scripts
+--
+-- Game updates
+--
+-- Copyright(C) 2004-2010, DeepClone Development
+-- --------------------------------------------------------
+
+
+\i parts/updates/000-updates-ctrl.sql
+\i parts/updates/010-empire-money.sql
+\i parts/updates/020-empire-research.sql
+\i parts/updates/025-empire-debt.sql
+\i parts/updates/030-fleet-arrivals.sql
+\i parts/updates/040-fleet-movements.sql
+\i parts/updates/050-fleet-status.sql
+\i parts/updates/060-planet-battle.sql
+\i parts/updates/070-planet-abandon.sql
+\i parts/updates/080-planet-construction.sql
+\i parts/updates/090-planet-military.sql
+\i parts/updates/100-planet-population.sql
+\i parts/updates/110-planet-money.sql
diff --git a/legacyworlds-server-data/db-structure/parts/030-data/000-typedefs.sql b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/data/000-typedefs.sql
similarity index 50%
rename from legacyworlds-server-data/db-structure/parts/030-data/000-typedefs.sql
rename to legacyworlds-server/legacyworlds-server-data/db-structure/parts/data/000-typedefs.sql
index ae64132..4ba3baa 100644
--- a/legacyworlds-server-data/db-structure/parts/030-data/000-typedefs.sql
+++ b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/data/000-typedefs.sql
@@ -12,7 +12,7 @@ CREATE TYPE processing_status
 	
 -- Building output types
 CREATE TYPE building_output_type
-	AS ENUM ( 'CASH', 'POP', 'DEF', 'WORK' , 'MINE' );
+	AS ENUM ( 'CASH', 'POP', 'DEF', 'WORK' );
 
 -- Fleet status
 CREATE TYPE fleet_status
@@ -28,65 +28,20 @@ CREATE TYPE log_type
 
 -- Update types
 CREATE TYPE update_type	AS ENUM (
-
-	/* Empires' money is being updated using the previous update's results
-	 * 
-	 * FIXME: this update type should disappear, as everything it does will
-	 * be replaced by the resources update.
-	 */
 	'EMPIRE_MONEY' ,
-
-	/* Empires' resources are being updated using the previous update's
-	 * results.
-	 */
-	'EMPIRE_RESOURCES' ,
-
-	/* Empire research points are being attributed to technologies */
 	'EMPIRE_RESEARCH' ,
-	
-	/* The effects of empires' debts are being computed */ 
 	'EMPIRE_DEBT' ,
-	
-	/* Fleets which were 1 update away are arriving at their destination */
 	'PLANET_FLEET_ARRIVALS' ,
-	
-	/* Other fleets are moving */
 	'PLANET_FLEET_MOVEMENTS' ,
-	
-	/* Fleet states (e.g. "deploying", "unavailable", etc...) are being
-	 * updated.
-	 */
 	'PLANET_FLEET_STATUS' ,
-	
-	/* Start new battles where necessary */
 	'PLANET_BATTLE_START' ,
-	
-	/* Process all in-progress battles */
 	'PLANET_BATTLE_MAIN' ,
-	
-	/* Finalise battles that need to be ended */
 	'PLANET_BATTLE_END' ,
-	
-	/* Abandon planets */
 	'PLANET_ABANDON' ,
-	
-	/* Handle civilian build queues */
 	'PLANET_CONSTRUCTION' ,
-	
-	/* Handle military build queues */
 	'PLANET_MILITARY' ,
-	
-	/* Update planets' population */
 	'PLANET_POPULATION' ,
-	
-	/* Regenerate resources in resource providers */
-	'PLANET_RES_REGEN' ,
-
-	/* Compute income and upkeep of planets */
-	'PLANET_MONEY' ,
-	
-	/* Compute mining results for planets owned by empires */
-	'PLANET_MINING'
+	'PLANET_MONEY' 
 );
 
 -- Types of recapitulative e-mail messages
diff --git a/legacyworlds-server-data/db-structure/parts/030-data/010-i18n.sql b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/data/010-i18n-data.sql
similarity index 100%
rename from legacyworlds-server-data/db-structure/parts/030-data/010-i18n.sql
rename to legacyworlds-server/legacyworlds-server-data/db-structure/parts/data/010-i18n-data.sql
diff --git a/legacyworlds-server-data/db-structure/parts/030-data/020-prefs.sql b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/data/020-prefs-data.sql
similarity index 100%
rename from legacyworlds-server-data/db-structure/parts/030-data/020-prefs.sql
rename to legacyworlds-server/legacyworlds-server-data/db-structure/parts/data/020-prefs-data.sql
diff --git a/legacyworlds-server-data/db-structure/parts/030-data/030-users.sql b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/data/030-users-data.sql
similarity index 100%
rename from legacyworlds-server-data/db-structure/parts/030-data/030-users.sql
rename to legacyworlds-server/legacyworlds-server-data/db-structure/parts/data/030-users-data.sql
diff --git a/legacyworlds-server-data/db-structure/parts/030-data/035-session.sql b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/data/035-session-data.sql
similarity index 100%
rename from legacyworlds-server-data/db-structure/parts/030-data/035-session.sql
rename to legacyworlds-server/legacyworlds-server-data/db-structure/parts/data/035-session-data.sql
diff --git a/legacyworlds-server-data/db-structure/parts/030-data/040-admin.sql b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/data/040-admin-data.sql
similarity index 100%
rename from legacyworlds-server-data/db-structure/parts/030-data/040-admin.sql
rename to legacyworlds-server/legacyworlds-server-data/db-structure/parts/data/040-admin-data.sql
diff --git a/legacyworlds-server-data/db-structure/parts/030-data/050-accounts.sql b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/data/050-accounts-data.sql
similarity index 100%
rename from legacyworlds-server-data/db-structure/parts/030-data/050-accounts.sql
rename to legacyworlds-server/legacyworlds-server-data/db-structure/parts/data/050-accounts-data.sql
diff --git a/legacyworlds-server-data/db-structure/parts/030-data/055-bugs.sql b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/data/055-bugs-data.sql
similarity index 100%
rename from legacyworlds-server-data/db-structure/parts/030-data/055-bugs.sql
rename to legacyworlds-server/legacyworlds-server-data/db-structure/parts/data/055-bugs-data.sql
diff --git a/legacyworlds-server-data/db-structure/parts/030-data/060-naming.sql b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/data/060-naming-data.sql
similarity index 100%
rename from legacyworlds-server-data/db-structure/parts/030-data/060-naming.sql
rename to legacyworlds-server/legacyworlds-server-data/db-structure/parts/data/060-naming-data.sql
diff --git a/legacyworlds-server-data/db-structure/parts/030-data/070-constants.sql b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/data/070-constants-data.sql
similarity index 85%
rename from legacyworlds-server-data/db-structure/parts/030-data/070-constants.sql
rename to legacyworlds-server/legacyworlds-server-data/db-structure/parts/data/070-constants-data.sql
index 82bca01..6441785 100644
--- a/legacyworlds-server-data/db-structure/parts/030-data/070-constants.sql
+++ b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/data/070-constants-data.sql
@@ -25,9 +25,9 @@ CREATE TABLE sys.constant_definitions(
 	name			VARCHAR(64) NOT NULL PRIMARY KEY,
 	category_id		INT NOT NULL ,
 	description		TEXT NOT NULL ,
-	min_value		REAL ,
-	max_value		REAL ,
-	c_value			REAL NOT NULL ,
+	min_value		DOUBLE PRECISION ,
+	max_value		DOUBLE PRECISION ,
+	c_value			DOUBLE PRECISION NOT NULL ,
 	CHECK(
 		( min_value IS NULL OR (
 				min_value IS NOT NULL AND c_value >= min_value ) )
diff --git a/legacyworlds-server/legacyworlds-server-data/db-structure/parts/data/080-techs-data.sql b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/data/080-techs-data.sql
new file mode 100644
index 0000000..b46a85a
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/data/080-techs-data.sql
@@ -0,0 +1,72 @@
+-- LegacyWorlds Beta 6
+-- PostgreSQL database scripts
+--
+-- Technology definitions
+--
+-- Copyright(C) 2004-2010, DeepClone Development
+-- --------------------------------------------------------
+
+
+--
+-- Categories
+--
+CREATE TABLE tech.categories(
+	name_id			INT NOT NULL PRIMARY KEY ,
+	description_id	INT NOT NULL
+);
+
+CREATE INDEX idx_categories_description
+	ON tech.categories (description_id);
+
+ALTER TABLE tech.categories
+	ADD CONSTRAINT fk_categories_name
+		FOREIGN KEY (name_id) REFERENCES defs.strings ,
+	ADD CONSTRAINT fk_categories_description
+		FOREIGN KEY (description_id) REFERENCES defs.strings;
+
+
+--
+-- Technologies
+--
+
+CREATE TABLE tech.technologies(
+	name_id			INT NOT NULL PRIMARY KEY ,
+	description_id	INT NOT NULL ,
+	category_id		INT NOT NULL ,
+	points			INT NOT NULL CHECK( points > 0 ) ,
+	cost			INT NOT NULL CHECK( cost > 0 )
+);
+
+CREATE INDEX idx_technologies_description
+	ON tech.technologies (description_id);
+CREATE INDEX idx_technologies_category
+	ON tech.technologies (category_id);
+
+ALTER TABLE tech.technologies
+	ADD CONSTRAINT fk_technologies_category
+		FOREIGN KEY (category_id) REFERENCES tech.categories ,
+	ADD CONSTRAINT fk_technologies_name
+		FOREIGN KEY (name_id) REFERENCES defs.strings ,
+	ADD CONSTRAINT fk_technologies_description
+		FOREIGN KEY (description_id) REFERENCES defs.strings;
+
+
+
+--
+-- Dependencies
+--
+
+CREATE TABLE tech.dependencies(
+	technology_id	INT NOT NULL ,
+	depends_on		INT NOT NULL ,
+	PRIMARY KEY( technology_id , depends_on )
+);
+
+CREATE INDEX idx_dependencies_dependson
+	ON tech.dependencies (depends_on);
+
+ALTER TABLE tech.dependencies
+	ADD CONSTRAINT fk_dependencies_technology
+		FOREIGN KEY (technology_id) REFERENCES tech.technologies ,
+	ADD CONSTRAINT fk_dependencies_dependson
+		FOREIGN KEY (depends_on) REFERENCES tech.technologies;
diff --git a/legacyworlds-server-data/db-structure/parts/030-data/090-buildables.sql b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/data/090-buildables-data.sql
similarity index 56%
rename from legacyworlds-server-data/db-structure/parts/030-data/090-buildables.sql
rename to legacyworlds-server/legacyworlds-server-data/db-structure/parts/data/090-buildables-data.sql
index 9fd997d..5ab70ee 100644
--- a/legacyworlds-server-data/db-structure/parts/030-data/090-buildables.sql
+++ b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/data/090-buildables-data.sql
@@ -10,26 +10,40 @@
 -- "Buildables"
 --
 CREATE TABLE tech.buildables(
-	name_id				INT NOT NULL PRIMARY KEY ,
-	description_id		INT NOT NULL ,
-	technology_name_id	INT ,
-	cost				INT NOT NULL CHECK( cost > 0 ) ,
-	work				INT NOT NULL CHECK( work > 0 ) ,
-	upkeep				INT NOT NULL CHECK( upkeep >= 0 )
+	name_id			INT NOT NULL PRIMARY KEY ,
+	description_id	INT NOT NULL ,
+	cost			INT NOT NULL CHECK( cost > 0 ) ,
+	work			INT NOT NULL CHECK( work > 0 ) ,
+	upkeep			INT NOT NULL CHECK( upkeep >= 0 )
 );
 
 CREATE INDEX idx_buildables_description
 	ON tech.buildables (description_id);
-CREATE INDEX idx_buildables_technology
-	ON tech.buildables ( technology_name_id );
 
 ALTER TABLE tech.buildables
 	ADD CONSTRAINT fk_buildables_name
 		FOREIGN KEY (name_id) REFERENCES defs.strings ,
 	ADD CONSTRAINT fk_buildables_description
-		FOREIGN KEY (description_id) REFERENCES defs.strings ,
-	ADD CONSTRAINT fk_buildables_technology
-		FOREIGN KEY (technology_name_id) REFERENCES defs.technologies;
+		FOREIGN KEY (description_id) REFERENCES defs.strings;
+
+
+--
+-- Requirements
+--
+CREATE TABLE tech.buildable_requirements(
+	buildable_id	INT NOT NULL ,
+	technology_id	INT NOT NULL ,
+	PRIMARY KEY( buildable_id , technology_id )
+);
+
+CREATE INDEX idx_buildablereqs_technology
+	ON tech.buildable_requirements( technology_id );
+
+ALTER TABLE tech.buildable_requirements
+	ADD CONSTRAINT fk_buildablereqs_buildable
+		FOREIGN KEY (buildable_id) REFERENCES tech.buildables ,
+	ADD CONSTRAINT fk_buildablereqs_technology
+		FOREIGN KEY (technology_id) REFERENCES tech.technologies;
 
 
 --
diff --git a/legacyworlds-server/legacyworlds-server-data/db-structure/parts/data/100-universe-data.sql b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/data/100-universe-data.sql
new file mode 100644
index 0000000..a784220
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/data/100-universe-data.sql
@@ -0,0 +1,95 @@
+-- LegacyWorlds Beta 6
+-- PostgreSQL database scripts
+--
+-- Stellar systems and planets
+--
+-- Copyright(C) 2004-2010, DeepClone Development
+-- --------------------------------------------------------
+
+
+--
+-- Stellar systems
+--
+CREATE TABLE verse.systems(
+	id		SERIAL NOT NULL PRIMARY KEY ,
+	x		INT NOT NULL ,
+	y		INT NOT NULL
+);
+
+CREATE UNIQUE INDEX idx_systems_coordinates
+	ON verse.systems( x , y );
+
+--
+-- Planets
+--
+CREATE TABLE verse.planets(
+	name_id		INT NOT NULL PRIMARY KEY ,
+	system_id	INT NOT NULL ,
+	orbit		INT NOT NULL
+					CHECK( orbit BETWEEN 1 AND 5 ) ,
+	picture		INT NOT NULL ,
+	population	DOUBLE PRECISION NOT NULL
+					CHECK( population >= 0 )
+);
+
+CREATE UNIQUE INDEX idx_planets_coordinates
+	ON verse.planets( system_id , orbit );
+	
+ALTER TABLE verse.planets
+	ADD CONSTRAINT fk_planets_name
+		FOREIGN KEY (name_id) REFERENCES naming.map_names ,
+	ADD CONSTRAINT fk_planets_system
+		FOREIGN KEY (system_id) REFERENCES verse.systems;
+
+
+--
+-- Happiness
+--
+CREATE TABLE verse.planet_happiness(
+	planet_id	INT NOT NULL PRIMARY KEY ,
+	target		DOUBLE PRECISION NOT NULL
+					CHECK( target BETWEEN 0.0 AND 1.0 ) ,
+	current		DOUBLE PRECISION NOT NULL
+					CHECK( current > 0 )
+);
+
+ALTER TABLE verse.planet_happiness
+	ADD CONSTRAINT fk_planethappiness_planet
+		FOREIGN KEY (planet_id) REFERENCES verse.planets;
+
+
+--
+-- Money
+--
+CREATE TABLE verse.planet_money(
+	planet_id	INT NOT NULL PRIMARY KEY ,
+	income		DOUBLE PRECISION NOT NULL
+					CHECK( income >= 0 ) ,
+	upkeep		DOUBLE PRECISION NOT NULL
+					CHECK( upkeep >= 0 )
+);
+
+ALTER TABLE verse.planet_money
+	ADD CONSTRAINT fk_planetmoney_planet
+		FOREIGN KEY (planet_id) REFERENCES verse.planets;
+
+
+--
+-- Buildings
+--
+CREATE TABLE verse.planet_buildings(
+	planet_id		INT NOT NULL ,
+	building_id		INT NOT NULL ,
+	amount			INT NOT NULL CHECK( amount >= 0 ) ,
+	damage			DOUBLE PRECISION NOT NULL CHECK( damage >= 0 ) ,
+	PRIMARY KEY( planet_id , building_id )
+);
+
+CREATE INDEX idx_planetbuildings_building
+	ON verse.planet_buildings (building_id);
+
+ALTER TABLE verse.planet_buildings
+	ADD CONSTRAINT fk_planetbuildings_planet
+		FOREIGN KEY (planet_id) REFERENCES verse.planets ,
+	ADD CONSTRAINT fk_planetbuildings_building
+		FOREIGN KEY (building_id) REFERENCES tech.buildings;
diff --git a/legacyworlds-server/legacyworlds-server-data/db-structure/parts/data/110-empires-data.sql b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/data/110-empires-data.sql
new file mode 100644
index 0000000..0cf46be
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/data/110-empires-data.sql
@@ -0,0 +1,203 @@
+-- LegacyWorlds Beta 6
+-- PostgreSQL database scripts
+--
+-- Empires and alliances
+--
+-- Copyright(C) 2004-2010, DeepClone Development
+-- --------------------------------------------------------
+
+
+--
+-- Empires
+--
+
+CREATE TABLE emp.empires(
+	name_id		INT NOT NULL PRIMARY KEY ,
+	cash		DOUBLE PRECISION NOT NULL
+					CHECK( cash >= 0 ),
+	debt		DOUBLE PRECISION NOT NULL DEFAULT 0
+					CHECK( debt >= 0)
+);
+
+ALTER TABLE emp.empires
+	ADD CONSTRAINT fk_empires_name
+		FOREIGN KEY (name_id) REFERENCES naming.empire_names;
+
+
+--
+-- Research in progress
+--
+
+CREATE TABLE emp.research(
+	empire_id		INT NOT NULL ,
+	technology_id	INT	NOT NULL ,
+	accumulated		DOUBLE PRECISION NOT NULL DEFAULT 0
+						CHECK( accumulated >= 0 ) ,
+	priority		INT NOT NULL
+						CHECK( priority BETWEEN 0 AND 100 ) ,
+	PRIMARY KEY( empire_id , technology_id )
+);
+
+CREATE INDEX idx_research_technology
+	ON emp.research (technology_id);
+
+ALTER TABLE emp.research
+	ADD CONSTRAINT fk_research_empire
+		FOREIGN KEY (empire_id) REFERENCES emp.empires
+			ON DELETE CASCADE ,
+	ADD CONSTRAINT fk_research_technology
+		FOREIGN KEY (technology_id) REFERENCES tech.technologies
+			ON DELETE CASCADE;
+
+
+
+--
+-- Researched technologies (both implemented and pending implementation)
+--
+
+CREATE TABLE emp.researched_technologies(
+	empire_id		INT NOT NULL ,
+	technology_id	INT NOT NULL ,
+	implemented		BOOLEAN NOT NULL ,
+	PRIMARY KEY ( empire_id , technology_id )
+);
+
+CREATE INDEX idx_researched_technology
+	ON emp.researched_technologies ( technology_id );
+CREATE INDEX idx_researched_implemented
+	ON emp.researched_technologies ( empire_id , implemented );
+
+ALTER TABLE emp.researched_technologies
+	ADD CONSTRAINT fk_researched_empire
+		FOREIGN KEY ( empire_id ) REFERENCES emp.empires
+			ON DELETE CASCADE ,
+	ADD CONSTRAINT fk_researched_technology
+		FOREIGN KEY ( technology_id ) REFERENCES tech.technologies
+			ON DELETE CASCADE;
+
+
+--
+-- Empire planets
+-- 
+
+CREATE TABLE emp.planets(
+	planet_id		INT NOT NULL PRIMARY KEY ,
+	empire_id		INT NOT NULL
+);
+
+CREATE INDEX idx_planets_empire
+	ON emp.planets (empire_id);
+
+ALTER TABLE emp.planets
+	ADD CONSTRAINT fk_eplanets_planet
+		FOREIGN KEY (planet_id) REFERENCES verse.planets ,
+	ADD CONSTRAINT fk_eplanets_empire
+		FOREIGN KEY (empire_id) REFERENCES emp.empires
+			ON DELETE CASCADE;
+
+
+--
+-- Planets being abandonned
+--
+
+CREATE TABLE emp.abandon(
+	planet_id		INT NOT NULL PRIMARY KEY ,
+	time_left		INT NOT NULL CHECK ( time_left > 0 )
+);
+
+CREATE INDEX idx_abandon_ready
+	ON emp.abandon ( ( time_left = 1 ) );
+
+ALTER TABLE emp.abandon
+	ADD CONSTRAINT fk_abandon_planet
+		FOREIGN KEY (planet_id) REFERENCES emp.planets
+			ON DELETE CASCADE;
+
+
+--
+-- Alliances
+--
+
+CREATE TABLE emp.alliances(
+	id				SERIAL NOT NULL PRIMARY KEY ,
+	tag				VARCHAR(5) NOT NULL ,
+	name			VARCHAR(128) NOT NULL ,
+	leader_id		INT NOT NULL
+);
+
+CREATE UNIQUE INDEX idx_alliances_tag
+	ON emp.alliances ( lower(tag) );
+CREATE UNIQUE INDEX idx_alliances_leader
+	ON emp.alliances (leader_id);
+
+ALTER TABLE emp.alliances
+	ADD CONSTRAINT fk_alliances_leader
+		FOREIGN KEY (leader_id) REFERENCES emp.empires
+			ON DELETE CASCADE;
+
+
+--
+-- Alliance membership
+--
+
+CREATE TABLE emp.alliance_members(
+	empire_id		INT NOT NULL PRIMARY KEY ,
+	alliance_id		INT NOT NULL ,
+	is_pending		BOOLEAN NOT NULL
+						DEFAULT TRUE
+);
+
+CREATE INDEX idx_alliancemembers_alliance
+	ON emp.alliance_members( alliance_id );
+
+ALTER TABLE emp.alliance_members
+	ADD CONSTRAINT fk_alliancemembers_empire
+		FOREIGN KEY (empire_id) REFERENCES emp.empires
+			ON DELETE CASCADE ,
+	ADD CONSTRAINT fk_alliancemembers_alliance
+		FOREIGN KEY (alliance_id) REFERENCES emp.alliances
+			ON DELETE CASCADE;
+
+
+--
+-- Enemy lists, alliances
+--
+
+CREATE TABLE emp.enemy_alliances(
+	empire_id		INT NOT NULL ,
+	alliance_id		INT NOT NULL ,
+	PRIMARY KEY (empire_id,alliance_id)
+);
+
+CREATE INDEX idx_enemyalliances_alliance
+	ON emp.enemy_alliances (alliance_id);
+
+ALTER TABLE emp.enemy_alliances
+	ADD CONSTRAINT fk_enemyalliances_empire
+		FOREIGN KEY (empire_id) REFERENCES emp.empires
+			ON DELETE CASCADE ,
+	ADD CONSTRAINT fk_enemyalliances_alliance
+		FOREIGN KEY (alliance_id) REFERENCES emp.alliances
+			ON DELETE CASCADE;
+
+
+--
+-- Enemy lists, empires
+--
+
+CREATE TABLE emp.enemy_empires(
+	empire_id		INT NOT NULL ,
+	enemy_id		INT NOT NULL ,
+	PRIMARY KEY (empire_id,enemy_id)
+);
+
+CREATE INDEX idx_enemyempires_enemy
+	ON emp.enemy_empires (enemy_id);
+
+ALTER TABLE emp.enemy_empires
+	ADD CONSTRAINT fk_enemyempires_empire
+		FOREIGN KEY (empire_id) REFERENCES emp.empires
+			ON DELETE CASCADE ,
+	ADD CONSTRAINT fk_enemyempires_enemy
+		FOREIGN KEY (enemy_id) REFERENCES emp.empires
+			ON DELETE CASCADE;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/parts/030-data/120-construction.sql b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/data/120-construction-data.sql
similarity index 88%
rename from legacyworlds-server-data/db-structure/parts/030-data/120-construction.sql
rename to legacyworlds-server/legacyworlds-server-data/db-structure/parts/data/120-construction-data.sql
index 9ae9fcd..2e1a050 100644
--- a/legacyworlds-server-data/db-structure/parts/030-data/120-construction.sql
+++ b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/data/120-construction-data.sql
@@ -13,8 +13,8 @@
 
 CREATE TABLE verse.bld_queues(
 	planet_id		INT NOT NULL PRIMARY KEY ,
-	money			REAL NOT NULL CHECK( money >= 0 ),
-	work			REAL NOT NULL CHECK( work >= 0 )
+	money			DOUBLE PRECISION NOT NULL CHECK( money >= 0 ),
+	work			DOUBLE PRECISION NOT NULL CHECK( work >= 0 )
 );
 
 ALTER TABLE verse.bld_queues
@@ -51,8 +51,8 @@ ALTER TABLE verse.bld_items
 
 CREATE TABLE verse.mil_queues(
 	planet_id		INT NOT NULL PRIMARY KEY ,
-	money			REAL NOT NULL CHECK( money >= 0 ),
-	work			REAL NOT NULL CHECK( work >= 0 )
+	money			DOUBLE PRECISION NOT NULL CHECK( money >= 0 ),
+	work			DOUBLE PRECISION NOT NULL CHECK( work >= 0 )
 );
 
 ALTER TABLE verse.mil_queues
diff --git a/legacyworlds-server-data/db-structure/parts/030-data/130-fleets.sql b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/data/130-fleets-data.sql
similarity index 95%
rename from legacyworlds-server-data/db-structure/parts/030-data/130-fleets.sql
rename to legacyworlds-server/legacyworlds-server-data/db-structure/parts/data/130-fleets-data.sql
index 7d7bb0f..96cd979 100644
--- a/legacyworlds-server-data/db-structure/parts/030-data/130-fleets.sql
+++ b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/data/130-fleets-data.sql
@@ -46,7 +46,7 @@ CREATE TABLE fleets.ships(
 	fleet_id	BIGINT NOT NULL ,
 	ship_id		INT NOT NULL ,
 	amount		INT NOT NULL CHECK( amount >= 0 ) ,
-	damage		REAL NOT NULL ,
+	damage		DOUBLE PRECISION NOT NULL ,
 	PRIMARY KEY( fleet_id , ship_id )
 );
 
@@ -89,8 +89,8 @@ ALTER TABLE fleets.movements
 
 CREATE TABLE fleets.ms_space(
 	movement_id		BIGINT NOT NULL PRIMARY KEY ,
-	start_x			REAL NOT NULL ,
-	start_y			REAL NOT NULL
+	start_x			DOUBLE PRECISION NOT NULL ,
+	start_y			DOUBLE PRECISION NOT NULL
 );
 
 ALTER TABLE fleets.ms_space
diff --git a/legacyworlds-server/legacyworlds-server-data/db-structure/parts/data/140-status-data.sql b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/data/140-status-data.sql
new file mode 100644
index 0000000..a3c76bb
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/data/140-status-data.sql
@@ -0,0 +1,107 @@
+-- LegacyWorlds Beta 6
+-- PostgreSQL database scripts
+--
+-- System & game updates status
+--
+-- Copyright(C) 2004-2010, DeepClone Development
+-- --------------------------------------------------------
+
+--
+-- System status
+--
+CREATE TABLE sys.status(
+	next_tick			BIGINT NOT NULL
+							DEFAULT 0 ,
+	current_tick		BIGINT ,
+
+	last_msg_recap		TIMESTAMP WITHOUT TIME ZONE
+							NOT NULL
+							DEFAULT now( ) ,
+	last_admin_recap	TIMESTAMP WITHOUT TIME ZONE
+							NOT NULL
+							DEFAULT now( ) ,
+	last_error_recap	TIMESTAMP WITHOUT TIME ZONE
+							NOT NULL
+							DEFAULT now( ) ,
+
+	maintenance_start	TIMESTAMP WITHOUT TIME ZONE ,
+	maintenance_end		TIMESTAMP WITHOUT TIME ZONE ,
+	maintenance_text	TEXT
+);
+
+INSERT INTO sys.status DEFAULT VALUES;
+
+GRANT SELECT ON sys.status TO :dbuser;
+
+
+
+--
+-- Ticker status
+--
+
+CREATE TYPE ticker_task_status
+	AS ENUM( 'RUNNING' , 'STOPPED' , 'AUTO' );
+
+CREATE TABLE sys.ticker(
+	id				SERIAL PRIMARY KEY ,
+	task_name		VARCHAR(64) NOT NULL UNIQUE ,
+	status			ticker_task_status NOT NULL ,
+	auto_start		TIMESTAMP WITHOUT TIME ZONE
+);
+
+INSERT INTO sys.ticker( task_name , status )
+	VALUES ( 'Game update' , 'STOPPED' );
+
+GRANT SELECT ON sys.ticker TO :dbuser;
+
+
+
+--
+-- Updates
+--
+CREATE TABLE sys.updates(
+	id					BIGSERIAL NOT NULL PRIMARY KEY ,
+	gu_type				update_type NOT NULL ,
+	status				processing_status NOT NULL DEFAULT 'FUTURE' ,
+	last_tick			BIGINT NOT NULL DEFAULT -1
+);
+
+CREATE INDEX idx_updates_finder
+	ON sys.updates (gu_type, status, last_tick);
+
+
+--
+-- Planet updates
+--
+CREATE TABLE verse.updates(
+	update_id			BIGINT NOT NULL PRIMARY KEY ,
+	planet_id			INT NOT NULL
+);
+
+CREATE INDEX idx_planetupdates_planet
+	ON verse.updates (planet_id);
+
+ALTER TABLE verse.updates
+	ADD CONSTRAINT fk_planetupdates_update
+		FOREIGN KEY ( update_id ) REFERENCES sys.updates ,
+	ADD CONSTRAINT fk_planetupdates_planet
+		FOREIGN KEY ( planet_id ) REFERENCES verse.planets;
+
+
+--
+-- Empire updates
+--
+CREATE TABLE emp.updates(
+	update_id			BIGINT NOT NULL PRIMARY KEY ,
+	empire_id			INT NOT NULL
+);
+
+CREATE INDEX idx_empireupdates_empire
+	ON emp.updates( empire_id );
+
+ALTER TABLE emp.updates
+	ADD CONSTRAINT fk_empireupdates_update
+		FOREIGN KEY ( update_id ) REFERENCES sys.updates ,
+	ADD CONSTRAINT fk_empireupdates_empire
+		FOREIGN KEY ( empire_id ) REFERENCES emp.empires
+			ON DELETE CASCADE;
diff --git a/legacyworlds-server-data/db-structure/parts/030-data/150-logs.sql b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/data/150-logs-data.sql
similarity index 100%
rename from legacyworlds-server-data/db-structure/parts/030-data/150-logs.sql
rename to legacyworlds-server/legacyworlds-server-data/db-structure/parts/data/150-logs-data.sql
diff --git a/legacyworlds-server-data/db-structure/parts/030-data/160-battle.sql b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/data/160-battle-data.sql
similarity index 100%
rename from legacyworlds-server-data/db-structure/parts/030-data/160-battle.sql
rename to legacyworlds-server/legacyworlds-server-data/db-structure/parts/data/160-battle-data.sql
diff --git a/legacyworlds-server/legacyworlds-server-data/db-structure/parts/data/170-events-data.sql b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/data/170-events-data.sql
new file mode 100644
index 0000000..d1d72fd
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/data/170-events-data.sql
@@ -0,0 +1,464 @@
+-- LegacyWorlds Beta 6
+-- PostgreSQL database scripts
+--
+-- Storage of events (internal messages)
+--
+-- Copyright(C) 2004-2011, DeepClone Development
+-- --------------------------------------------------------
+
+
+--
+-- Event type definitionss
+--
+
+CREATE TABLE events.event_type_definitions(
+	etd_type			VARCHAR( 48 ) NOT NULL
+							PRIMARY KEY ,
+	etd_priority		INT NOT NULL
+							CHECK( etd_priority BETWEEN 1 AND 5 ) ,
+	etd_user_priority	BOOLEAN NOT NULL
+);
+
+
+--
+-- Types of field contents
+--
+--	INMB	integer
+--	RNMB	real number
+--	TEXT	text
+--	BOOL	boolean
+--	I18N	internationalised string
+--	EREF	game entity reference
+--
+
+CREATE TYPE events.field_content_type
+	AS ENUM ( 'INMB' , 'RNMB' , 'TEXT' , 'BOOL' , 'I18N' , 'EREF' );
+
+
+--
+-- Subtypes of reference field contents
+--
+--	EMP		empire
+--	MAP		map object
+--	FLT		fleet
+--	BAT		battle
+--	ADM		administrator
+--	MSG		message
+--	BUG		bug report
+--
+
+CREATE TYPE events.field_reference_type
+	AS ENUM ( 'EMP' , 'MAP' , 'FLT' , 'BAT' , 'ADM' , 'MSG' , 'BUG' );
+
+
+--
+-- Event field definitions
+--
+
+CREATE TABLE events.event_field_definitions(
+	etd_type			VARCHAR( 48 ) NOT NULL ,
+	efd_field			VARCHAR( 48 ) NOT NULL ,
+	efd_required		BOOLEAN NOT NULL ,
+	efd_type			events.field_content_type NOT NULL ,
+	efd_reference_type	events.field_reference_type ,
+	efd_low_boundary	DOUBLE PRECISION ,
+	efd_high_boundary	DOUBLE PRECISION ,
+	
+	PRIMARY KEY ( etd_type , efd_field ) ,
+
+	CHECK( efd_type = 'EREF' AND efd_reference_type IS NOT NULL
+			OR efd_type <> 'EREF' AND efd_reference_type IS NULL ) ,
+
+	CHECK ( efd_type IN ( 'INMB' , 'RNMB' , 'TEXT' )
+			OR  efd_type NOT IN ( 'INMB' , 'RNMB' , 'TEXT' )
+					AND efd_low_boundary IS NULL
+					AND efd_high_boundary IS NULL ) ,
+
+	CHECK ( efd_low_boundary IS NULL OR efd_high_boundary IS NULL
+			OR efd_low_boundary < efd_high_boundary )
+);
+
+ALTER TABLE events.event_field_definitions
+	ADD CONSTRAINT fk_efd_type
+		FOREIGN KEY ( etd_type ) REFERENCES events.event_type_definitions;
+
+
+
+--
+-- Event format definitions
+--
+
+CREATE TABLE events.event_format_definitions(
+	etd_type		VARCHAR( 48 ) NOT NULL ,
+	efmd_order		INT NOT NULL ,
+	efmd_template	INT NOT NULL ,
+
+	PRIMARY KEY ( etd_type , efmd_order )
+);
+
+CREATE INDEX idx_efmd_template
+	ON events.event_format_definitions ( efmd_template );
+
+ALTER TABLE events.event_format_definitions
+	ADD CONSTRAINT fk_efmd_type
+		FOREIGN KEY ( etd_type ) REFERENCES events.event_type_definitions ,
+	ADD CONSTRAINT fk_efmd_template
+		FOREIGN KEY ( efmd_template ) REFERENCES defs.strings;
+
+
+
+--
+-- Types of format conditions
+--
+--	EX		has value				all
+--	EQ		is equal to ...			all except EREF
+--	NE		is not equal to ...		all except EREF
+--	GT		> ...					INMB , RNMB
+--			length > ...			TEXT
+--	LT		< ...					INMB , RNMB
+--			shorter than ...		TEXT
+--	GE		>= ...					INMB , RNMB
+--			length >= ...			TEXT
+--	LE		<= ...					INMB , RNMB
+--			length <= ...			TEXT
+--	AV		available				EREF
+--
+
+CREATE TYPE events.format_condition_type
+	AS ENUM ( 'EX' , 'EQ' , 'NE' , 'GT' , 'LT' , 'GE' , 'LE' , 'AV' );
+
+
+--
+-- Conditions on format definitions
+--
+
+CREATE TABLE events.efmt_conditions(
+	etd_type		VARCHAR( 48 ) NOT NULL ,
+	efmd_order		INT NOT NULL ,
+	efd_field		VARCHAR( 48 ) NOT NULL ,
+	efc_type		events.format_condition_type NOT NULL ,
+	efc_boolean		BOOLEAN ,
+	efc_numeric		DOUBLE PRECISION ,
+	efc_string		TEXT ,
+	
+	PRIMARY KEY( etd_type , efmd_order , efd_field , efc_type )
+);
+
+CREATE INDEX idx_efmtc_field
+	ON events.efmt_conditions ( etd_type , efd_field );
+
+ALTER TABLE events.efmt_conditions
+	ADD CONSTRAINT fk_efmtc_format
+		FOREIGN KEY  ( etd_type , efmd_order ) REFERENCES events.event_format_definitions ,
+	ADD CONSTRAINT fk_efmtc_field
+		FOREIGN KEY  ( etd_type , efd_field ) REFERENCES events.event_field_definitions;
+
+
+
+
+-- --------------------------------------------------------
+-- OLD CODE BELOW
+--
+
+CREATE TYPE event_type
+	AS ENUM ( 'QUEUE' , 'EMPIRE' , 'FLEETS' , 'PLANET', 'ALLIANCE', 'ADMIN' , 'BUGS' );
+
+CREATE TYPE event_status
+	AS ENUM( 'TICK' , 'ACTION' , 'READY' , 'SENT' );
+
+
+
+--
+-- Events table
+--
+
+CREATE TABLE events.events(
+	event_id		BIGSERIAL PRIMARY KEY ,
+	empire_id		INT NOT NULL ,
+	tick			BIGINT NOT NULL ,
+	real_time		TIMESTAMP WITHOUT TIME ZONE
+						NOT NULL
+						DEFAULT now() ,
+	evt_type		event_type NOT NULL ,
+	evt_subtype		INT NOT NULL ,
+	status			event_status NOT NULL
+);
+
+CREATE INDEX idx_events_empire
+	ON events.events (empire_id);
+
+CREATE INDEX idx_events_time
+	ON events.events (real_time);
+
+CREATE INDEX idx_events_lookup
+	ON events.events( empire_id , tick , evt_type , evt_subtype , status )
+	WHERE status IN ( 'TICK' , 'ACTION' );
+
+ALTER TABLE events.events
+	ADD CONSTRAINT fk_events_empire
+		FOREIGN KEY ( empire_id ) REFERENCES emp.empires
+			ON DELETE CASCADE;
+
+GRANT SELECT ON events.events TO :dbuser;
+
+
+--
+-- Build queue events
+--
+
+CREATE TABLE events.queue_events (
+	event_id		BIGINT NOT NULL PRIMARY KEY
+);
+
+ALTER TABLE events.queue_events
+	ADD CONSTRAINT fk_bqevents_event
+		FOREIGN KEY (event_id) REFERENCES events.events
+			ON DELETE CASCADE;
+
+
+
+--
+-- Build queue event locations
+--
+
+CREATE TABLE events.bqe_locations(
+	event_id		BIGINT NOT NULL ,
+	location_id		INT NOT NULL ,
+	location_name	VARCHAR(20) NOT NULL ,
+	PRIMARY KEY( event_id , location_id )
+);
+
+ALTER TABLE events.bqe_locations
+	ADD CONSTRAINT fk_bqelocations_event
+		FOREIGN KEY (event_id) REFERENCES events.queue_events
+			ON DELETE CASCADE ,
+	ADD CONSTRAINT fk_bqelocations_location
+		FOREIGN KEY (location_id) REFERENCES verse.planets;
+
+
+
+--
+-- Empire events
+--
+
+CREATE TABLE events.empire_events(
+	event_id		BIGINT NOT NULL PRIMARY KEY ,
+	technology_id	INT NOT NULL
+);
+
+CREATE INDEX idx_empevents_tech
+	ON events.empire_events (technology_id);
+
+ALTER TABLE events.empire_events
+	ADD CONSTRAINT fk_empevents_event
+		FOREIGN KEY (event_id) REFERENCES events.events
+			ON DELETE CASCADE,
+	ADD CONSTRAINT fk_empevents_tech
+		FOREIGN KEY (technology_id) REFERENCES tech.technologies;
+
+
+
+--
+-- Fleet events
+--
+
+CREATE TABLE events.fleets_events(
+	event_id		BIGINT NOT NULL PRIMARY KEY ,
+	location_id		INT NOT NULL ,
+	location_name	VARCHAR(20) NOT NULL
+);
+
+CREATE INDEX idx_flevents_location
+	ON events.fleets_events( location_id );
+
+ALTER TABLE events.fleets_events
+	ADD CONSTRAINT fk_flevents_event
+		FOREIGN KEY (event_id) REFERENCES events.events
+			ON DELETE CASCADE ,
+	ADD CONSTRAINT fk_flevents_location
+		FOREIGN KEY (location_id) REFERENCES verse.planets;
+
+
+
+--
+-- Fleets for fleet events
+--
+
+CREATE TABLE events.fleet_lists(
+	id				BIGSERIAL PRIMARY KEY ,
+	event_id		BIGINT NOT NULL ,
+	owner_id		INT ,
+	owner_name		VARCHAR(20) NOT NULL ,
+	fleet_name		VARCHAR(64) ,
+	fleet_power		BIGINT NOT NULL CHECK( fleet_power > 0 ) ,
+	status			BOOLEAN ,
+	source_id		INT ,
+	source_name		VARCHAR(20) ,
+	CHECK( source_id IS NULL AND source_name IS NULL OR source_id IS NOT NULL AND source_name IS NOT NULL )
+);
+
+CREATE INDEX idx_flelists_event
+	ON events.fleet_lists( event_id );
+
+CREATE INDEX idx_flelists_owner
+	ON events.fleet_lists( owner_id )
+	WHERE owner_id IS NOT NULL;
+
+CREATE INDEX idx_flelists_source
+	ON events.fleet_lists( source_id )
+	WHERE source_id IS NOT NULL;
+
+ALTER TABLE events.fleet_lists
+	ADD CONSTRAINT fk_flelist_event
+		FOREIGN KEY ( event_id ) REFERENCES events.fleets_events
+			ON DELETE CASCADE ,
+	ADD CONSTRAINT fk_flelist_owner
+		FOREIGN KEY ( owner_id ) REFERENCES emp.empires
+			ON DELETE SET NULL ,
+	ADD CONSTRAINT fk_flelist_source
+		FOREIGN KEY ( source_id ) REFERENCES verse.planets;
+
+GRANT SELECT ON events.fleet_lists TO :dbuser;
+
+
+
+--
+-- Planet events
+--
+
+CREATE TABLE events.planet_events(
+	event_id		BIGINT PRIMARY KEY,
+	location_id		INT NOT NULL ,
+	location_name	VARCHAR(20) NOT NULL ,
+	empire_id		INT ,
+	empire_name		VARCHAR(20) ,
+	battle_id		BIGINT ,
+	CHECK( battle_id IS NULL AND empire_id IS NULL AND empire_name IS NULL
+		OR battle_id IS NOT NULL AND empire_id IS NULL AND empire_name IS NULL
+		OR battle_id IS NULL AND empire_name IS NOT NULL )
+);
+
+CREATE INDEX idx_pevents_event
+	ON events.planet_events ( event_id );
+
+CREATE INDEX idx_pevents_location
+	ON events.planet_events ( location_id );
+
+CREATE INDEX idx_pevents_empire
+	ON events.planet_events ( empire_id )
+	WHERE empire_id IS NOT NULL;
+
+CREATE INDEX idx_pevents_battle
+	ON events.planet_events ( battle_id )
+	WHERE battle_id IS NOT NULL;
+
+ALTER TABLE events.planet_events
+	ADD CONSTRAINT fk_pevents_event
+		FOREIGN KEY ( event_id ) REFERENCES events.events
+			ON DELETE CASCADE ,
+	ADD CONSTRAINT fk_pevents_location
+		FOREIGN KEY ( location_id ) REFERENCES verse.planets ,
+	ADD CONSTRAINT fk_pevents_empire
+		FOREIGN KEY ( empire_id ) REFERENCES emp.empires
+			ON DELETE SET NULL ,
+	ADD CONSTRAINT fk_pevents_battle
+		FOREIGN KEY ( battle_id ) REFERENCES battles.battles;
+
+
+
+--
+-- Alliance events
+--
+
+CREATE TABLE events.alliance_events(
+	event_id		BIGINT PRIMARY KEY ,
+	alliance_id		INT ,
+	alliance_tag	VARCHAR( 5 ) NOT NULL ,
+	empire_id		INT ,
+	empire_name		VARCHAR( 20 ) ,
+	req_result		BOOLEAN ,
+	CHECK( req_result IS NULL AND empire_id IS NULL AND empire_name IS NULL
+		OR req_result IS NOT NULL AND empire_id IS NULL AND empire_name IS NULL
+		OR req_result IS NULL AND empire_name IS NOT NULL )
+);
+
+CREATE INDEX idx_aevents_event
+	ON events.alliance_events ( event_id );
+
+CREATE INDEX idx_aevents_alliance
+	ON events.alliance_events ( alliance_id )
+	WHERE alliance_id IS NOT NULL;
+
+CREATE INDEX idx_aevents_empire
+	ON events.alliance_events ( empire_id )
+	WHERE empire_id IS NOT NULL;
+
+ALTER TABLE events.alliance_events
+	ADD CONSTRAINT fk_aevents_event
+		FOREIGN KEY ( event_id ) REFERENCES events.events
+			ON DELETE CASCADE ,
+	ADD CONSTRAINT fk_aevents_allliance
+		FOREIGN KEY ( alliance_id ) REFERENCES emp.alliances
+			ON DELETE SET NULL ,
+	ADD CONSTRAINT fk_aevents_empire
+		FOREIGN KEY ( empire_id ) REFERENCES emp.empires
+			ON DELETE SET NULL;
+
+
+
+--
+-- Admin events
+--
+
+CREATE TABLE events.admin_events(
+	event_id		BIGINT PRIMARY KEY ,
+	n_warnings		INT ,
+	location_id		INT ,
+	old_name		VARCHAR( 20 ) NOT NULL ,
+	new_name		VARCHAR( 20 )
+);
+
+CREATE INDEX idx_adevents_event
+	ON events.admin_events ( event_id );
+
+CREATE INDEX idx_adevents_location
+	ON events.admin_events ( location_id )
+	WHERE location_id IS NOT NULL;
+
+ALTER TABLE events.admin_events
+	ADD CONSTRAINT fk_adevents_event
+		FOREIGN KEY ( event_id ) REFERENCES events.events
+			ON DELETE CASCADE ,
+	ADD CONSTRAINT fk_adevents_location
+		FOREIGN KEY ( location_id ) REFERENCES verse.planets;
+
+
+
+--
+-- Bug tracking events
+--
+
+CREATE TABLE events.bug_events(
+	event_id		BIGINT PRIMARY KEY ,
+	bug_id			BIGINT NOT NULL ,
+	submitter_id	BIGINT NOT NULL
+);
+
+CREATE INDEX idx_btevents_event
+	ON events.bug_events ( event_id );
+
+CREATE INDEX idx_btevents_bug
+	ON events.bug_events ( bug_id );
+
+CREATE INDEX idx_btevents_submitter
+	ON events.bug_events ( submitter_id );
+
+
+ALTER TABLE events.bug_events
+	ADD CONSTRAINT fk_btevents_event
+		FOREIGN KEY ( event_id ) REFERENCES events.events
+			ON DELETE CASCADE ,
+	ADD CONSTRAINT fk_btevents_bug
+		FOREIGN KEY ( bug_id ) REFERENCES bugs.initial_report_events ,
+	ADD CONSTRAINT fk_btevents_submitter
+		FOREIGN KEY ( submitter_id ) REFERENCES bugs.submitters;
diff --git a/legacyworlds-server-data/db-structure/parts/030-data/180-messages.sql b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/data/180-messages-data.sql
similarity index 100%
rename from legacyworlds-server-data/db-structure/parts/030-data/180-messages.sql
rename to legacyworlds-server/legacyworlds-server-data/db-structure/parts/data/180-messages-data.sql
diff --git a/legacyworlds-server-data/db-structure/parts/040-functions/000-defs.sql b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/functions/000-defs-functions.sql
similarity index 100%
rename from legacyworlds-server-data/db-structure/parts/040-functions/000-defs.sql
rename to legacyworlds-server/legacyworlds-server-data/db-structure/parts/functions/000-defs-functions.sql
diff --git a/legacyworlds-server-data/db-structure/parts/040-functions/002-sys.sql b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/functions/002-sys-functions.sql
similarity index 97%
rename from legacyworlds-server-data/db-structure/parts/040-functions/002-sys.sql
rename to legacyworlds-server/legacyworlds-server-data/db-structure/parts/functions/002-sys-functions.sql
index 6f75303..79a3271 100644
--- a/legacyworlds-server-data/db-structure/parts/040-functions/002-sys.sql
+++ b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/functions/002-sys-functions.sql
@@ -61,7 +61,7 @@ BEGIN
 	THEN
 		UPDATE sys.ticker SET status = 'RUNNING' , auto_start = NULL
 			WHERE id = task_id;
-		PERFORM sys.write_sql_log( 'Ticker' , 'INFO'::log_level , 'Scheduled task ''' || t_name
+		PERFORM sys.write_log( 'Ticker' , 'INFO'::log_level , 'Scheduled task ''' || t_name
 			|| ''' has been enabled' );
 	END IF;
 END;
diff --git a/legacyworlds-server-data/db-structure/parts/040-functions/005-logs.sql b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/functions/005-logs-functions.sql
similarity index 86%
rename from legacyworlds-server-data/db-structure/parts/040-functions/005-logs.sql
rename to legacyworlds-server/legacyworlds-server-data/db-structure/parts/functions/005-logs-functions.sql
index 0579cda..f7a7c0c 100644
--- a/legacyworlds-server-data/db-structure/parts/040-functions/005-logs.sql
+++ b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/functions/005-logs-functions.sql
@@ -124,47 +124,6 @@ $$ LANGUAGE plpgsql;
 GRANT EXECUTE ON FUNCTION sys.write_log( TEXT , log_level , TEXT ) TO :dbuser;
 
 
-/*
- * Remotely append a system log entry
- *
- * This function is called from within transactions in order to write to the
- * system log. Unlike sys.write_log(), entries added through this function
- * will not be lost if the transaction is rolled back.
- *
- * Since the function is meant to be called from SQL code, it does not return
- * anything as the identifier of the new entry is not required.
- *
- * Parameters:
- *		_component		The component that is appending to the log
- *		_level			The log level
- *		_message		The message to write
- */
-
-CREATE OR REPLACE FUNCTION sys.write_sql_log( _component TEXT , _level log_level , _message TEXT )
-		RETURNS VOID
-		STRICT VOLATILE
-		SECURITY INVOKER
-	AS $write_sql_log$
-BEGIN
-	BEGIN
-		PERFORM dblink_connect( 'cn_logging' , 'srv_logging' );
-	EXCEPTION
-		WHEN duplicate_object THEN
-			-- Ignore the error, assume we're connected
-	END;
-
-	PERFORM * FROM dblink( 'cn_logging' ,
-		'SELECT * FROM sys.write_log( '
-			|| quote_literal( _component ) || ' , '''
-			|| _level::text || '''::log_level , '
-			|| quote_literal( _message ) || ' )'
-	) AS ( entry_id bigint );
-END;
-$write_sql_log$ LANGUAGE plpgsql;
-
-GRANT EXECUTE ON FUNCTION sys.write_sql_log( TEXT , log_level , TEXT ) TO :dbuser;
-
-
 
 --
 -- Append an exception log entry
diff --git a/legacyworlds-server-data/db-structure/parts/040-functions/010-constants.sql b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/functions/010-constants-functions.sql
similarity index 89%
rename from legacyworlds-server-data/db-structure/parts/040-functions/010-constants.sql
rename to legacyworlds-server/legacyworlds-server-data/db-structure/parts/functions/010-constants-functions.sql
index f0c78ed..c4cd55f 100644
--- a/legacyworlds-server-data/db-structure/parts/040-functions/010-constants.sql
+++ b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/functions/010-constants-functions.sql
@@ -57,8 +57,8 @@ $$ LANGUAGE plpgsql;
 --	the constant's actual value
 --
 
-CREATE OR REPLACE FUNCTION sys.uoc_constant( cnm TEXT , cdesc TEXT , ccnm TEXT , dval REAL )
-		RETURNS REAL
+CREATE OR REPLACE FUNCTION sys.uoc_constant( cnm TEXT , cdesc TEXT , ccnm TEXT , dval DOUBLE PRECISION )
+		RETURNS DOUBLE PRECISION
 		STRICT
 		VOLATILE
 		SECURITY DEFINER
@@ -66,7 +66,7 @@ CREATE OR REPLACE FUNCTION sys.uoc_constant( cnm TEXT , cdesc TEXT , ccnm TEXT ,
 DECLARE
 	ccid	INT;
 	occid	INT;
-	cval	REAL;
+	cval	DOUBLE PRECISION;
 BEGIN
 	ccid := sys.cog_constant_category( ccnm );
 
@@ -97,7 +97,7 @@ BEGIN
 END;
 $$ LANGUAGE plpgsql;
 
-GRANT EXECUTE ON FUNCTION sys.uoc_constant( TEXT , TEXT , TEXT , REAL ) TO :dbuser;
+GRANT EXECUTE ON FUNCTION sys.uoc_constant( TEXT , TEXT , TEXT , DOUBLE PRECISION ) TO :dbuser;
 
 
 
@@ -116,8 +116,8 @@ GRANT EXECUTE ON FUNCTION sys.uoc_constant( TEXT , TEXT , TEXT , REAL ) TO :dbus
 --	the constant's actual value
 --
 
-CREATE OR REPLACE FUNCTION sys.uoc_constant( cnm TEXT , cdesc TEXT , ccnm TEXT , dval REAL , bval REAL , ismin BOOLEAN )
-		RETURNS REAL
+CREATE OR REPLACE FUNCTION sys.uoc_constant( cnm TEXT , cdesc TEXT , ccnm TEXT , dval DOUBLE PRECISION , bval DOUBLE PRECISION , ismin BOOLEAN )
+		RETURNS DOUBLE PRECISION
 		STRICT
 		VOLATILE
 		SECURITY DEFINER
@@ -125,9 +125,9 @@ CREATE OR REPLACE FUNCTION sys.uoc_constant( cnm TEXT , cdesc TEXT , ccnm TEXT ,
 DECLARE
 	ccid	INT;
 	occid	INT;
-	cval	REAL;
-	mival	REAL;
-	maval	REAL;
+	cval	DOUBLE PRECISION;
+	mival	DOUBLE PRECISION;
+	maval	DOUBLE PRECISION;
 BEGIN
 	IF ismin THEN
 		mival := bval;
@@ -175,7 +175,7 @@ BEGIN
 END;
 $$ LANGUAGE plpgsql;
 
-GRANT EXECUTE ON FUNCTION sys.uoc_constant( TEXT , TEXT , TEXT , REAL , REAL , BOOLEAN ) TO :dbuser;
+GRANT EXECUTE ON FUNCTION sys.uoc_constant( TEXT , TEXT , TEXT , DOUBLE PRECISION , DOUBLE PRECISION , BOOLEAN ) TO :dbuser;
 
 
 
@@ -194,8 +194,8 @@ GRANT EXECUTE ON FUNCTION sys.uoc_constant( TEXT , TEXT , TEXT , REAL , REAL , B
 --	the constant's actual value
 --
 
-CREATE OR REPLACE FUNCTION sys.uoc_constant( cnm TEXT , cdesc TEXT , ccnm TEXT , dval REAL , mival REAL , maval REAL )
-		RETURNS REAL
+CREATE OR REPLACE FUNCTION sys.uoc_constant( cnm TEXT , cdesc TEXT , ccnm TEXT , dval DOUBLE PRECISION , mival DOUBLE PRECISION , maval DOUBLE PRECISION )
+		RETURNS DOUBLE PRECISION
 		STRICT
 		VOLATILE
 		SECURITY DEFINER
@@ -203,7 +203,7 @@ CREATE OR REPLACE FUNCTION sys.uoc_constant( cnm TEXT , cdesc TEXT , ccnm TEXT ,
 DECLARE
 	ccid	INT;
 	occid	INT;
-	cval	REAL;
+	cval	DOUBLE PRECISION;
 BEGIN
 	ccid := sys.cog_constant_category( ccnm );
 
@@ -243,7 +243,7 @@ BEGIN
 END;
 $$ LANGUAGE plpgsql;
 
-GRANT EXECUTE ON FUNCTION sys.uoc_constant( TEXT , TEXT , TEXT , REAL , REAL , REAL ) TO :dbuser;
+GRANT EXECUTE ON FUNCTION sys.uoc_constant( TEXT , TEXT , TEXT , DOUBLE PRECISION , DOUBLE PRECISION , DOUBLE PRECISION ) TO :dbuser;
 
 
 
@@ -259,7 +259,7 @@ GRANT EXECUTE ON FUNCTION sys.uoc_constant( TEXT , TEXT , TEXT , REAL , REAL , R
 --	TRUE on success, FALSE on failure
 --
 
-CREATE OR REPLACE FUNCTION sys.set_constant( cnm TEXT , nval REAL , aid INT )
+CREATE OR REPLACE FUNCTION sys.set_constant( cnm TEXT , nval DOUBLE PRECISION , aid INT )
 		RETURNS BOOLEAN
 		STRICT
 		VOLATILE
@@ -282,7 +282,7 @@ BEGIN
 END;
 $$ LANGUAGE plpgsql;
 
-GRANT EXECUTE ON FUNCTION sys.set_constant( TEXT , REAL , INT ) TO :dbuser;
+GRANT EXECUTE ON FUNCTION sys.set_constant( TEXT , DOUBLE PRECISION , INT ) TO :dbuser;
 
 
 
@@ -294,7 +294,7 @@ GRANT EXECUTE ON FUNCTION sys.set_constant( TEXT , REAL , INT ) TO :dbuser;
 --
 
 CREATE OR REPLACE FUNCTION sys.get_constant( cnm TEXT )
-	RETURNS REAL
+	RETURNS DOUBLE PRECISION
 	STRICT STABLE
 	SECURITY DEFINER
 AS $$
diff --git a/legacyworlds-server-data/db-structure/parts/040-functions/020-naming.sql b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/functions/020-naming-functions.sql
similarity index 100%
rename from legacyworlds-server-data/db-structure/parts/040-functions/020-naming.sql
rename to legacyworlds-server/legacyworlds-server-data/db-structure/parts/functions/020-naming-functions.sql
diff --git a/legacyworlds-server/legacyworlds-server-data/db-structure/parts/functions/030-tech-functions.sql b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/functions/030-tech-functions.sql
new file mode 100644
index 0000000..df70d4e
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/functions/030-tech-functions.sql
@@ -0,0 +1,507 @@
+-- LegacyWorlds Beta 6
+-- PostgreSQL database scripts
+--
+-- Functions and views for technologies and buildables
+--
+-- Copyright(C) 2004-2010, DeepClone Development
+-- --------------------------------------------------------
+
+
+--
+-- "Basic" buildables view (buildables that do not depend on any technology)
+--
+
+CREATE VIEW tech.basic_buildables
+	AS SELECT b.* FROM tech.buildables b
+			LEFT OUTER JOIN tech.buildable_requirements r
+				ON r.buildable_id = b.name_id
+		WHERE r.buildable_id IS NULL;
+
+
+--
+-- Buildings view
+--
+
+CREATE VIEW tech.buildings_view
+	AS SELECT b.name_id , b.description_id , b.cost , b.work , b.upkeep ,
+			bld.workers , bld.output_type , bld.output
+		FROM tech.buildables b
+			INNER JOIN tech.buildings bld
+				ON b.name_id = bld.buildable_id;
+
+
+--
+-- Ships view
+--
+
+CREATE VIEW tech.ships_view
+	AS SELECT b.name_id , b.description_id , b.cost , b.work , b.upkeep ,
+			s.flight_time , s.power
+		FROM tech.buildables b
+			INNER JOIN tech.ships s
+				ON b.name_id = s.buildable_id;
+				
+
+--
+-- Categories view
+--
+
+CREATE VIEW tech.categories_view
+	AS SELECT ns.name AS name , ds.name AS description
+		FROM tech.categories c
+			INNER JOIN defs.strings ns
+				ON ns.id = c.name_id
+			INNER JOIN defs.strings ds
+				ON ds.id = c.description_id;
+
+GRANT SELECT ON tech.categories_view TO :dbuser;
+				
+
+--
+-- Technologies view
+--
+
+CREATE VIEW tech.technologies_view
+	AS SELECT cs.name AS category , ns.name AS name ,
+			ds.name AS description , t.points , t.cost
+		FROM tech.technologies t
+			INNER JOIN defs.strings cs
+				ON cs.id = t.category_id
+			INNER JOIN defs.strings ns
+				ON ns.id = t.name_id
+			INNER JOIN defs.strings ds
+				ON ds.id = t.description_id;
+
+GRANT SELECT ON tech.technologies_view TO :dbuser;
+
+
+--
+-- Dependencies view
+--
+
+CREATE VIEW tech.dependencies_view
+	AS SELECT ts.name AS technology , ds.name AS dependency
+		FROM tech.dependencies d
+			INNER JOIN defs.strings ts
+				ON ts.id = d.technology_id
+			INNER JOIN defs.strings ds
+				ON ds.id = d.depends_on;
+
+GRANT SELECT ON tech.dependencies_view TO :dbuser;
+
+
+
+--
+-- Creates or updates a technology category
+--
+-- Parameters:
+--	cat_name	String identifier of the category's name
+--	cat_desc	String identifier of the category's description
+--
+-- Returns:
+--	0			No error
+--	1			Name string not found
+--	2			Description string not found
+--
+
+CREATE OR REPLACE FUNCTION tech.uoc_category( cat_name TEXT , cat_desc TEXT )
+		RETURNS INT
+		STRICT VOLATILE
+		SECURITY DEFINER
+	AS $$
+DECLARE
+	cn_id	INT;
+	cd_id	INT;
+BEGIN
+	-- Get name / description identifiers
+	SELECT INTO cn_id id FROM defs.strings WHERE name = cat_name;
+	IF NOT FOUND THEN
+			RETURN 1;
+	END IF;
+	SELECT INTO cd_id id FROM defs.strings WHERE name = cat_desc;
+	IF NOT FOUND THEN
+		RETURN 2;
+	END IF;
+	
+	-- Create or update the category
+	BEGIN
+		INSERT INTO tech.categories ( name_id , description_id )
+			VALUES ( cn_id , cd_id );
+	EXCEPTION
+		WHEN unique_violation THEN
+			UPDATE tech.categories SET description_id = cd_id
+				WHERE name_id = cn_id;
+	END;
+	RETURN 0;
+END;
+$$ LANGUAGE plpgsql;
+
+GRANT EXECUTE ON FUNCTION tech.uoc_category( TEXT , TEXT ) to :dbuser;
+
+
+--
+-- Creates or updates a technology. If there are dependencies, clear them.
+--
+-- Parameters:
+--	nt_name		Name string identifier
+--	nt_category	Category string identifier
+--	nt_desc		Description string identifier
+--	nt_points	Research points for the technology
+--	nt_cost		Cost of the technology
+--
+-- Returns:
+--	0			No error
+--	1			Name string not found
+--	2			Category not found
+--	3			Description string not found
+--	4			Invalid parameters (points or cost)
+--
+
+CREATE OR REPLACE FUNCTION tech.uoc_technology( nt_name TEXT , nt_category TEXT , nt_desc TEXT ,
+			nt_points INT , nt_cost INT )
+		RETURNS INT
+		STRICT VOLATILE
+		SECURITY DEFINER
+	AS $$
+DECLARE
+	n_id	INT;
+	c_id	INT;
+	d_id	INT;
+BEGIN
+	-- Get name, category and description identifiers
+	SELECT INTO n_id id FROM defs.strings WHERE name = nt_name;
+	IF NOT FOUND THEN
+			RETURN 1;
+	END IF;
+	SELECT INTO c_id c.name_id FROM tech.categories c
+		INNER JOIN defs.strings s
+			ON s.id = c.name_id AND s.name = nt_category;
+	IF NOT FOUND THEN
+		RETURN 2;
+	END IF;
+	SELECT INTO d_id id FROM defs.strings WHERE name = nt_desc;
+	IF NOT FOUND THEN
+		RETURN 3;
+	END IF;
+
+	-- Create or update the technology
+	BEGIN
+		BEGIN
+			INSERT INTO tech.technologies ( name_id , category_id , description_id , points , cost )
+				VALUES ( n_id , c_id , d_id , nt_points , nt_cost );
+		EXCEPTION
+			WHEN unique_violation THEN
+				UPDATE tech.technologies
+					SET category_id = c_id , description_id = cd_id ,
+						points = nt_points , cost = nt_cost
+					WHERE name_id = n_id;
+				DELETE FROM tech.dependencies
+					WHERE technology_id = n_id;
+		END;
+	EXCEPTION
+		WHEN check_violation THEN
+			RETURN 4;
+	END;
+	RETURN 0;
+END;
+$$ LANGUAGE plpgsql;		
+
+GRANT EXECUTE ON FUNCTION tech.uoc_technology( TEXT , TEXT , TEXT , INT , INT ) to :dbuser;
+
+
+--
+-- Adds a technology dependency
+--
+-- Parameters:
+--	nd_name		Name of the dependent technology
+--	nd_dep		Name of the dependency
+--
+-- Returns:
+--	0			No error
+--	1			Technology not found
+--	2			Dependency not found
+--	3			Duplicate dependency
+--
+CREATE OR REPLACE FUNCTION tech.add_dependency( nd_name TEXT , nd_dep TEXT )
+		RETURNS INT
+		STRICT VOLATILE
+		SECURITY DEFINER
+	AS $$
+DECLARE
+	t_id	INT;
+	d_id	INT;
+BEGIN
+	-- Get technology
+	SELECT INTO t_id t.name_id FROM tech.technologies t
+		INNER JOIN defs.strings s
+			ON s.id = t.name_id AND s.name = nd_name;
+	IF NOT FOUND THEN
+		RETURN 1;
+	END IF;
+
+	-- Get dependency
+	SELECT INTO d_id t.name_id FROM tech.technologies t
+		INNER JOIN defs.strings s
+			ON s.id = t.name_id AND s.name = nd_dep;
+	IF NOT FOUND THEN
+		RETURN 2;
+	END IF;
+	
+	-- Add dependency
+	BEGIN
+		INSERT INTO tech.dependencies ( technology_id , depends_on )
+			VALUES ( t_id , d_id );
+	EXCEPTION
+		WHEN unique_violation THEN
+			RETURN 3;
+	END;
+	RETURN 0;
+END;
+$$ LANGUAGE plpgsql;
+
+GRANT EXECUTE ON FUNCTION tech.add_dependency( TEXT, TEXT ) TO :dbuser;
+
+
+
+--
+-- Creates or updates a buildable definition
+--
+-- Parameters:
+--	bdn		Buildable name
+--	bdd		Buildable description
+--	bdc		Cost
+--	bdw		Work
+--	bdu		Upkeep
+--	bdtn	Dependency
+--
+-- Returns:
+--	the buildable's identifier
+--
+
+CREATE OR REPLACE FUNCTION tech.uoc_buildable( bdn TEXT , bdd TEXT , bdc INT , bdw INT , bdu INT , bdtn TEXT )
+		RETURNS INT
+		STRICT
+		VOLATILE
+		SECURITY INVOKER
+	AS $$
+DECLARE
+	nid		INT;
+	did		INT;
+	tdid	INT;
+BEGIN
+	-- Get the various translations
+	SELECT INTO nid id FROM defs.strings WHERE name = bdn;
+	SELECT INTO did id FROM defs.strings WHERE name = bdd;
+	IF bdtn <> '' THEN
+		SELECT INTO tdid tl.name_id FROM tech.technologies tl
+			INNER JOIN defs.strings s
+				ON s.id = tl.name_id
+			WHERE s.name = bdtn;
+	END IF;
+	
+	-- Create or update the definition
+	BEGIN
+		INSERT INTO tech.buildables ( name_id , description_id , cost , work , upkeep )
+			VALUES ( nid , did , bdc , bdw , bdu );
+	EXCEPTION
+		WHEN unique_violation THEN
+			UPDATE tech.buildables SET description_id = did , cost = bdc , work = bdw , upkeep = bdu
+				WHERE name_id = nid;
+	END;
+
+	-- Set dependencies
+	DELETE FROM tech.buildable_requirements WHERE buildable_id = nid;
+	IF bdtn <> '' THEN
+		INSERT INTO tech.buildable_requirements ( buildable_id , technology_id )
+			VALUES ( nid , tdid );
+	END IF;
+	
+	RETURN nid;
+END;
+$$ LANGUAGE plpgsql;
+
+
+
+--
+-- Update or create a building definition (no tech dependency)
+--
+-- Parameters:
+--	bdn		Buildable name
+--	bdd		Buildable description
+--	bdc		Cost
+--	bdw		Work
+--	bdu		Upkeep
+--	bdwk	Workers
+--	bdot	Output type
+--	bdo		Output
+--
+
+CREATE OR REPLACE FUNCTION tech.uoc_building( bdn TEXT , bdd TEXT , bdc INT , bdw INT ,
+											  bdu INT , bdwk INT , bdot building_output_type , bdo INT )
+		RETURNS VOID
+		STRICT
+		VOLATILE
+		SECURITY DEFINER
+	AS $$
+DECLARE
+	bdid	INT;
+BEGIN
+	bdid := tech.uoc_buildable( bdn , bdd , bdc , bdw , bdu , '' );
+	
+	PERFORM buildable_id FROM tech.ships WHERE buildable_id = bdid;
+	IF FOUND THEN
+		RAISE EXCEPTION 'Trying to transform a ship into a building';
+	END IF;
+
+	BEGIN
+		INSERT INTO tech.buildings (buildable_id, workers, output_type, output)
+			VALUES (bdid , bdwk , bdot , bdo);
+	EXCEPTION
+		WHEN unique_violation THEN
+			UPDATE tech.buildings SET workers = bdwk , output_type = bdot , output = bdo
+				WHERE buildable_id = bdid;
+	END;
+END;
+$$ LANGUAGE plpgsql;
+
+GRANT EXECUTE ON FUNCTION tech.uoc_building( TEXT , TEXT , INT , INT , INT , INT , building_output_type , INT ) TO :dbuser;
+
+
+
+--
+-- Update or create a building definition (with tech dependency)
+--
+-- Parameters:
+--	bdn		Buildable name
+--	bdd		Buildable description
+--	bdc		Cost
+--	bdw		Work
+--	bdu		Upkeep
+--	bdwk	Workers
+--	bdot	Output type
+--	bdo		Output
+--	bdtn	Dependency
+--
+
+CREATE OR REPLACE FUNCTION tech.uoc_building( bdn TEXT , bdd TEXT , bdc INT , bdw INT ,
+											  bdu INT , bdwk INT , bdot building_output_type , bdo INT ,
+											  bdtn TEXT )
+		RETURNS VOID
+		STRICT VOLATILE
+		SECURITY DEFINER
+	AS $$
+DECLARE
+	bdid	INT;
+BEGIN
+	bdid := tech.uoc_buildable( bdn , bdd , bdc , bdw , bdu , bdtn );
+	
+	PERFORM buildable_id FROM tech.ships WHERE buildable_id = bdid;
+	IF FOUND THEN
+		RAISE EXCEPTION 'Trying to transform a ship into a building';
+	END IF;
+
+	BEGIN
+		INSERT INTO tech.buildings (buildable_id, workers, output_type, output)
+			VALUES (bdid , bdwk , bdot , bdo);
+	EXCEPTION
+		WHEN unique_violation THEN
+			UPDATE tech.buildings SET workers = bdwk , output_type = bdot , output = bdo
+				WHERE buildable_id = bdid;
+	END;
+END;
+$$ LANGUAGE plpgsql;
+
+GRANT EXECUTE ON FUNCTION tech.uoc_building( TEXT , TEXT , INT , INT , INT , INT , building_output_type , INT , TEXT ) TO :dbuser;
+
+
+
+--
+-- Update or create a ship definition (no tech dependency)
+--
+-- Parameters:
+--	sn		Buildable name
+--	sd		Buildable description
+--	sc		Cost
+--	sw		Work
+--	su		Upkeep
+--	sp		Power
+--	sft		Orbital flight time
+--
+
+CREATE OR REPLACE FUNCTION tech.uoc_ship( sn TEXT , sd TEXT , sc INT , sw INT ,
+										  su INT , sp INT , sft INT )
+		RETURNS VOID
+		STRICT
+		VOLATILE
+		SECURITY DEFINER
+	AS $$
+DECLARE
+	bdid	INT;
+BEGIN
+	bdid := tech.uoc_buildable( sn , sd , sc , sw , su , '' );
+	
+	PERFORM buildable_id FROM tech.buildings WHERE buildable_id = bdid;
+	IF FOUND THEN
+		RAISE EXCEPTION 'Trying to transform a building into a ship';
+	END IF;
+
+	BEGIN
+		INSERT INTO tech.ships (buildable_id, flight_time, power)
+			VALUES (bdid , sft , sp);
+	EXCEPTION
+		WHEN unique_violation THEN
+			UPDATE tech.ships SET flight_time = sft , power = sp
+				WHERE buildable_id = bdid;
+	END;
+END;
+$$ LANGUAGE plpgsql;
+
+GRANT EXECUTE ON FUNCTION tech.uoc_ship( TEXT , TEXT , INT , INT , INT , INT , INT ) TO :dbuser;
+
+
+
+--
+-- Update or create a ship definition
+--
+-- Parameters:
+--	sn		Buildable name
+--	sd		Buildable description
+--	sc		Cost
+--	sw		Work
+--	su		Upkeep
+--	sp		Power
+--	sft		Orbital flight time
+--	stdn	Tech name
+--
+
+CREATE OR REPLACE FUNCTION tech.uoc_ship( sn TEXT , sd TEXT , sc INT , sw INT ,
+										  su INT , sp INT , sft INT , stdn TEXT )
+		RETURNS VOID
+		STRICT
+		VOLATILE
+		SECURITY DEFINER
+	AS $$
+DECLARE
+	bdid	INT;
+BEGIN
+	bdid := tech.uoc_buildable( sn , sd , sc , sw , su , stdn );
+	
+	PERFORM buildable_id FROM tech.buildings WHERE buildable_id = bdid;
+	IF FOUND THEN
+		RAISE EXCEPTION 'Trying to transform a building into a ship';
+	END IF;
+
+	BEGIN
+		INSERT INTO tech.ships (buildable_id, flight_time, power)
+			VALUES (bdid , sft , sp);
+	EXCEPTION
+		WHEN unique_violation THEN
+			UPDATE tech.ships SET flight_time = sft , power = sp
+				WHERE buildable_id = bdid;
+	END;
+END;
+$$ LANGUAGE plpgsql;
+
+GRANT EXECUTE ON FUNCTION tech.uoc_ship( TEXT , TEXT , INT , INT , INT , INT , INT , TEXT ) TO :dbuser;
+
+
diff --git a/legacyworlds-server-data/db-structure/parts/040-functions/035-users.sql b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/functions/035-users-view.sql
similarity index 100%
rename from legacyworlds-server-data/db-structure/parts/040-functions/035-users.sql
rename to legacyworlds-server/legacyworlds-server-data/db-structure/parts/functions/035-users-view.sql
diff --git a/legacyworlds-server-data/db-structure/parts/040-functions/040-empire.sql b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/functions/040-empire-functions.sql
similarity index 72%
rename from legacyworlds-server-data/db-structure/parts/040-functions/040-empire.sql
rename to legacyworlds-server/legacyworlds-server-data/db-structure/parts/functions/040-empire-functions.sql
index 28f3377..73109da 100644
--- a/legacyworlds-server-data/db-structure/parts/040-functions/040-empire.sql
+++ b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/functions/040-empire-functions.sql
@@ -3,70 +3,47 @@
 --
 -- Empire management functions and views
 --
--- Copyright(C) 2004-2012, DeepClone Development
+-- Copyright(C) 2004-2011, DeepClone Development
 -- --------------------------------------------------------
 
 
-/*
- * Empire creation
- * ----------------
- * 
- * This function inserts the rows that represent an empire and its settings.
- * It also initialises the empire's updates.
- *
- * Parameters:
- *		_name_id		Empire name identifier
- *		_planet_id		Planet identifier
- *		_initial_cash	Initial cash
- */
-DROP FUNCTION IF EXISTS emp.create_empire( INT , INT , REAL );
-CREATE FUNCTION emp.create_empire(
-			_name_id		INT ,
-			_planet_id		INT ,
-			_initial_cash	REAL )
+--
+-- Empire creation
+--
+-- Parameters:
+--	nid		Empire name identifier
+--	pid		Planet identifier
+--	icash	Initial cash
+--
+CREATE OR REPLACE FUNCTION emp.create_empire( nid INT , pid INT , icash DOUBLE PRECISION )
 		RETURNS VOID
-		STRICT VOLATILE
+		STRICT
+		VOLATILE
 		SECURITY INVOKER
 	AS $$
+DECLARE
+	uid		BIGINT;
+	utp		update_type;
 BEGIN
-
 	-- Add empire and give initial planet
 	INSERT INTO emp.empires ( name_id , cash )
-		VALUES ( _name_id , _initial_cash );
+		VALUES ( nid , icash );
 	INSERT INTO emp.planets ( planet_id , empire_id )
-		VALUES ( _planet_id , _name_id );
-
-	-- Add mining settings
-	INSERT INTO emp.mining_settings ( empire_id , resource_name_id )
-		SELECT _name_id , _resource.resource_name_id
-			FROM defs.natural_resources _resource;
-
-	-- Add empire resources
-	INSERT INTO emp.resources ( empire_id , resource_name_id )
-		SELECT _name_id , resource_name_id FROM defs.resources;
-
-	-- Insert technologies that have no dependencies as research in progress
-	INSERT INTO emp.technologies ( empire_id , technology_name_id )
-		SELECT _name_id , technology_name_id
-			FROM defs.technologies
-				LEFT OUTER JOIN defs.technology_dependencies
-					USING ( technology_name_id )
-			WHERE techdep_id IS NULL;
-
-	-- Update resource mining quantities
-	UPDATE verse.planet_resources
-		SET pres_income = emp.mining_compute_extraction( _update_row )
-		FROM emp.mining_get_input( _name_id ) _update_row
-		WHERE planet_id = _update_row.planet
-			AND resource_name_id = _update_row.resource;
+		VALUES ( pid , nid );
 
+	-- Add empire update records
+	FOR utp IN SELECT x FROM unnest( enum_range( NULL::update_type ) ) AS x
+					WHERE x::text LIKE 'EMPIRE_%'
+	LOOP
+		INSERT INTO sys.updates( gu_type )
+			VALUES ( utp )
+			RETURNING id INTO uid;
+		INSERT INTO emp.updates ( update_id , empire_id )
+			VALUES ( uid , nid );
+	END LOOP;
 END;
 $$ LANGUAGE plpgsql;
 
-REVOKE EXECUTE
-	ON FUNCTION emp.create_empire( INT , INT , REAL )
-	FROM PUBLIC;
-
 
 --
 -- Returns a planet owner's empire size
@@ -104,7 +81,6 @@ $$ LANGUAGE SQL;
 GRANT EXECUTE ON FUNCTION emp.get_current( INT ) TO :dbuser;
 
 
-
 --
 -- Add an enemy empire
 --
@@ -394,7 +370,7 @@ CREATE OR REPLACE FUNCTION emp.get_new_planet( e_id INT , p_name TEXT , OUT err_
 DECLARE
 	plid	INT;
 	accid	INT;
-	ccash	REAL;
+	ccash	DOUBLE PRECISION;
 	f_id	BIGINT;
 	fleets	BIGINT[];
 BEGIN
@@ -464,9 +440,8 @@ CREATE VIEW emp.enemies
 -- General information view
 --
 
-DROP VIEW IF EXISTS emp.general_information CASCADE;
 CREATE VIEW emp.general_information
-	AS SELECT e.name_id AS id , en.name AS name ,
+	AS SELECT e.name_id AS id , en.name AS name , av.language ,
 			  ( CASE
 			  		WHEN av.status = 'QUITTING' THEN 'q'
 			  		WHEN av.status = 'VACATION' THEN 'v'
@@ -475,17 +450,13 @@ CREATE VIEW emp.general_information
 			  END ) AS status ,
 			  e.cash AS cash , a.tag AS alliance ,
 			  st.next_tick AS game_time ,
-			  av.id AS account_id ,
-			  av.language AS language
+			  av.id AS account_id
 		FROM emp.empires e
-			INNER JOIN naming.empire_names en
-				ON en.id = e.name_id
-			INNER JOIN users.accounts_view av
-				ON av.id = en.owner_id
+			INNER JOIN naming.empire_names en ON en.id = e.name_id
+			INNER JOIN users.accounts_view av ON av.id = en.owner_id
 			LEFT OUTER JOIN emp.alliance_members am
 				ON am.empire_id = e.name_id AND NOT am.is_pending
-			LEFT OUTER JOIN emp.alliances a
-				ON a.id = am.alliance_id
+			LEFT OUTER JOIN emp.alliances a ON a.id = am.alliance_id
 			CROSS JOIN sys.status st;
 
 GRANT SELECT ON emp.general_information TO :dbuser;
@@ -601,112 +572,4 @@ CREATE VIEW emp.enemy_lists
 					INNER JOIN emp.alliances a ON a.id = el.alliance_id
 		) AS x;
 
-GRANT SELECT ON emp.enemy_lists TO :dbuser;
-
-
-/*
- * Planets income and upkeep totals
- * 
- * This view computes the totals of planets' incomes and upkeeps for each
- * empire and resource type.
- * 
- * FIXME: time-related factor is hardcoded
- * 
- * Fields:
- *		empire_id			The empire's identifier
- *		resource_name_id	The identifier of the resource type
- *		planets_income		The planets' income over 12h RT / 1 month GT,
- *								rounded down
- *		planets_upkeep		The planets' upkeep over 12h RT / 1 month GT,
- *								rounded up
- */
-DROP VIEW IF EXISTS emp.planet_resources_view CASCADE;
-CREATE VIEW emp.planet_resources_view
-	AS SELECT
-			empire_id , resource_name_id ,
-			FLOOR( SUM( pres_income ) * 720.0 )::BIGINT AS planets_income ,
-			CEIL( SUM( pres_upkeep ) * 720.0 )::BIGINT AS planets_upkeep
-		FROM emp.planets
-			LEFT OUTER JOIN verse.planet_resources
-				USING ( planet_id )
-		GROUP BY empire_id , resource_name_id;
-
-
-/*
- * Empire resources view
- * 
- * This view contains all resource-related information for each empire and
- * resource type.
- * 
- * FIXME: fleets upkeep is set to 0 at the moment.
- * 
- * Fields:
- *		empire_id				The empire's identifier
- *		resource_identifier		The text identifier of the resource
- *		resource_name			The internationalised name of the resource
- *		resource_description	The internationalised description of the
- *									resource
- *		resource_category		The internationalised category of the resource,
- *									or NULL if the resource is not in a
- *									category.
- *		empres_possessed		The empire's stockpile of this type of
- *									resource, rounded down
- *		empmset_weight			The empire-wide mining setting for the
- *									resource type, or NULL if this is a basic
- *									resource
- *		planets_income			The planets' total income
- *		planets_upkeep			The planets' total upkeep
- *		fleets_upkeep			The fleets' total upkeep
- */
-DROP VIEW IF EXISTS emp.resources_view CASCADE;
-CREATE VIEW emp.resources_view
-	AS SELECT
-			empire_id ,
-			_r_name_str.name AS resource_identifier ,
-			_r_name.translated_string AS resource_name ,
-			_r_desc.translated_string AS resource_description ,
-			_r_cat.translated_string AS resource_category ,
-			FLOOR( empres_possessed )::BIGINT AS empres_possessed ,
-			empmset_weight ,
-			( CASE
-				WHEN planets_income IS NULL THEN
-					0::BIGINT
-				ELSE
-					planets_income
-			END ) AS planets_income ,
-			( CASE
-				WHEN planets_upkeep IS NULL THEN
-					0::BIGINT
-				ELSE
-					planets_upkeep
-			END ) AS planets_upkeep ,
-			0::BIGINT AS fleets_upkeep
-
-		FROM defs.ordered_resources_view
-			INNER JOIN emp.resources
-				USING ( resource_name_id )
-			INNER JOIN naming.empire_names _name
-				ON _name.id = empire_id
-			INNER JOIN users.credentials _creds
-				ON _creds.address_id = _name.owner_id
-			INNER JOIN defs.strings _r_name_str
-				ON _r_name_str.id = resource_name_id
-			INNER JOIN defs.translations _r_name
-				ON _r_name.string_id = resource_name_id
-					AND _r_name.lang_id = _creds.language_id
-			INNER JOIN defs.translations _r_desc
-				ON _r_desc.string_id = resource_description_id
-					AND _r_desc.lang_id = _creds.language_id
-			LEFT OUTER JOIN defs.translations _r_cat
-				ON _r_cat.string_id = resource_category_id
-					AND _r_cat.lang_id = _creds.language_id
-			LEFT OUTER JOIN emp.mining_settings
-				USING ( empire_id , resource_name_id )
-			LEFT OUTER JOIN emp.planet_resources_view
-				USING ( empire_id , resource_name_id )
-
-		ORDER BY resource_ordering;
-		
-GRANT SELECT
-	ON emp.resources_view
-	TO :dbuser;
+GRANT SELECT ON emp.enemy_lists TO :dbuser;
\ No newline at end of file
diff --git a/legacyworlds-server/legacyworlds-server-data/db-structure/parts/functions/045-research-functions.sql b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/functions/045-research-functions.sql
new file mode 100644
index 0000000..4ee2133
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/functions/045-research-functions.sql
@@ -0,0 +1,227 @@
+-- LegacyWorlds Beta 6
+-- PostgreSQL database scripts
+--
+-- Research mananagement functions and views
+--
+-- Copyright(C) 2004-2011, DeepClone Development
+-- --------------------------------------------------------
+
+
+
+
+--
+-- Implement a technology
+--
+-- Parameters:
+--	e_id	Empire identifier
+--	t_name	Technology name
+--
+-- Returns:
+--	0		on success
+--	1		if the empire does not posses the necessary resources
+--	2		if the technology or empire were not found
+--
+
+CREATE OR REPLACE FUNCTION emp.implement_tech( e_id INT , t_name TEXT )
+		RETURNS INT
+		STRICT VOLATILE
+		SECURITY DEFINER
+	AS $$
+DECLARE
+	e_cash	DOUBLE PRECISION;
+	t_id	INT;
+	t_cost	DOUBLE PRECISION;
+BEGIN
+	SELECT INTO e_cash , t_id , t_cost e.cash , ns.id , td.cost
+		FROM defs.strings ns
+			INNER JOIN tech.technologies td
+				ON td.name_id = ns.id
+			INNER JOIN emp.researched_technologies rt
+				ON rt.technology_id = td.name_id
+			INNER JOIN emp.empires e
+				ON rt.empire_id = e.name_id
+		WHERE e.name_id = e_id AND ns.name = t_name
+		FOR UPDATE OF e , rt;
+	IF NOT FOUND THEN
+		RETURN 2;
+	END IF;
+	
+	IF e_cash < t_cost THEN
+		RETURN 1;
+	END IF;
+	
+	UPDATE emp.empires
+		SET cash = e_cash - t_cost
+		WHERE name_id = e_id;
+	UPDATE emp.researched_technologies
+		SET implemented = TRUE
+		WHERE empire_id = e_id AND technology_id = t_id;
+
+	RETURN 0;
+END;
+$$ LANGUAGE plpgsql;
+
+GRANT EXECUTE ON FUNCTION emp.implement_tech( INT , TEXT ) TO :dbuser;
+
+
+
+--
+-- Prepare for research priorities updates
+--
+
+CREATE OR REPLACE FUNCTION emp.prepare_research_priorities_update( )
+		RETURNS VOID
+		STRICT VOLATILE
+		SECURITY DEFINER
+	AS $$
+BEGIN
+	CREATE TEMPORARY TABLE research_priorities_updates(
+		technology		TEXT ,
+		priority		INT
+	);
+	CREATE INDEX rpu_technology ON research_priorities_updates ( technology );
+	IF session_user <> current_user THEN
+		EXECUTE 'GRANT INSERT ON research_priorities_updates TO ' || session_user;
+	END IF;
+END;
+$$ LANGUAGE plpgsql;
+
+GRANT EXECUTE ON FUNCTION emp.prepare_research_priorities_update( ) TO :dbuser;
+
+
+--
+-- Applies research priorities updates
+--
+-- Parameters:
+--	e_id		identifier of the empire the updates should be applied to
+--
+-- Returns:
+--	an error code:
+--		0		success
+--		1		list of updates does not match current research topics
+--		2		invalid priorities
+--
+
+CREATE OR REPLACE FUNCTION emp.apply_research_priorities( IN e_id INT )
+		RETURNS INT
+		STRICT VOLATILE
+		SECURITY DEFINER
+	AS $$
+DECLARE
+	rec		RECORD;
+	t		INT;
+	rval	INT;
+BEGIN
+	-- Lock empire and research info
+	PERFORM er.technology_id
+		FROM emp.empires e
+			INNER JOIN emp.research er ON er.empire_id = e.name_id
+		WHERE e.name_id = e_id
+		FOR UPDATE OF e , er;
+
+	-- Check values
+	t := 0;
+	rval := 0;
+	FOR rec IN SELECT rpu.priority , r.technology_id FROM research_priorities_updates rpu
+					LEFT OUTER JOIN emp.research_view r
+						ON ( r.detailed AND r.technology = rpu.technology )
+							OR ( NOT r.detailed AND ( 'unknown-' || ( r.technology_id * e_id )::TEXT ) = rpu.technology )
+					WHERE r.empire = e_id OR r.empire IS NULL
+				UNION SELECT rpu.priority , r.technology_id FROM research_priorities_updates rpu
+					RIGHT OUTER JOIN emp.research_view r
+						ON ( r.detailed AND r.technology = rpu.technology )
+							OR ( NOT r.detailed AND ( 'unknown-' || ( r.technology_id * e_id )::TEXT ) = rpu.technology )
+					WHERE r.empire = e_id
+	LOOP
+		IF rec.priority IS NULL OR rec.technology_id IS NULL THEN
+			rval := 1;
+			EXIT;
+		ELSIF rec.priority NOT BETWEEN 0 AND 100 THEN
+			rval := 2;
+			EXIT;
+		END IF;
+		t := t + rec.priority;
+	END LOOP;
+	IF rval = 0 AND t <> 100 THEN
+		rval := 2;
+	END IF;
+
+	-- Update research info
+	IF rval = 0 THEN
+		UPDATE emp.research er SET priority = rpu.priority
+			FROM research_priorities_updates rpu , emp.research_view rv
+			WHERE ( rpu.technology = CASE
+							WHEN rv.detailed THEN
+								rv.technology
+							ELSE
+								( 'unknown-' || ( rv.technology_id * e_id )::TEXT )
+						END )
+				AND rv.empire = e_id
+				AND er.empire_id = e_id
+				AND er.technology_id = rv.technology_id;
+	END IF;
+	DROP TABLE research_priorities_updates;
+	RETURN rval;
+END;
+$$ LANGUAGE plpgsql;
+
+GRANT EXECUTE ON FUNCTION emp.apply_research_priorities( INT ) TO :dbuser;
+
+
+
+
+--
+-- Base research view
+--
+
+CREATE VIEW emp.base_research_view
+	AS SELECT er.empire_id AS empire , er.technology_id , ns.name AS technology ,
+				td.points AS required , ( CASE
+					WHEN er.accumulated > td.points THEN
+						td.points - 1
+					ELSE
+						er.accumulated
+				END ) AS accumulated , er.priority
+			FROM emp.research er
+				INNER JOIN tech.technologies td ON td.name_id = er.technology_id
+				INNER JOIN defs.strings ns ON ns.id = er.technology_id;
+
+
+--
+-- Research view
+--
+
+CREATE VIEW emp.research_view
+	AS SELECT empire , technology , technology_id ,
+				FLOOR( 100 * accumulated / required )::INT AS completion ,
+				( accumulated >= sys.get_constant( 'game.research.minPoints' )
+					OR accumulated / required >= sys.get_constant( 'game.research.minRatio' ) ) AS detailed ,
+				priority
+			FROM emp.base_research_view;
+
+
+--
+-- Researched and implemented technologies view
+
+CREATE VIEW emp.known_techs_view
+	AS SELECT et.empire_id AS empire , et.technology_id , ns.name AS technology ,
+				( CASE WHEN et.implemented THEN NULL::INT ELSE td.cost END ) AS cost
+			FROM emp.researched_technologies et
+				INNER JOIN tech.technologies td ON td.name_id = et.technology_id
+				INNER JOIN defs.strings ns ON ns.id = et.technology_id;
+
+
+--
+-- Combined research and technologies view
+--
+
+CREATE VIEW emp.technologies_view
+	AS SELECT empire , technology_id , technology ,
+				detailed , completion , priority , NULL::INT AS cost
+			FROM emp.research_view
+	UNION ALL SELECT empire , technology_id , technology ,
+				TRUE AS detailed , NULL::INT AS completion , NULL::INT AS priority , cost
+			FROM emp.known_techs_view;
+
+GRANT SELECT ON emp.technologies_view TO :dbuser;
+
diff --git a/legacyworlds-server/legacyworlds-server-data/db-structure/parts/functions/050-computation-functions.sql b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/functions/050-computation-functions.sql
new file mode 100644
index 0000000..0f75a48
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/functions/050-computation-functions.sql
@@ -0,0 +1,232 @@
+-- LegacyWorlds Beta 6
+-- PostgreSQL database scripts
+--
+-- Various functions for in-game computations
+--
+-- Copyright(C) 2004-2010, DeepClone Development
+-- --------------------------------------------------------
+
+
+--
+-- sigma( x ) = exp( x ) / ( 1 + exp( x ) )
+--
+
+CREATE OR REPLACE FUNCTION verse.sigma( x DOUBLE PRECISION )
+	RETURNS DOUBLE PRECISION
+	STRICT IMMUTABLE SECURITY INVOKER
+AS $$
+	SELECT ( CASE
+		WHEN $1 < -100 THEN 0
+		WHEN $1 > 100 THEN 1
+		ELSE ( exp( $1 ) / ( 1 + exp( $1 ) ) )
+	END );
+$$ LANGUAGE SQL;
+
+
+
+--
+-- poly( x , a , b , c ) = ( a * x + b ) * x + c 
+--
+
+CREATE OR REPLACE FUNCTION verse.poly( x DOUBLE PRECISION , a DOUBLE PRECISION , b DOUBLE PRECISION , c DOUBLE PRECISION )
+	RETURNS DOUBLE PRECISION
+	STRICT IMMUTABLE SECURITY INVOKER
+AS $$
+	SELECT ( $2 * $1 + $3 ) * $1 + $4;
+$$ LANGUAGE SQL;
+
+
+
+--
+-- Happiness curve, K1 constant
+--
+
+CREATE OR REPLACE FUNCTION verse.hcc_const_k1( xmax DOUBLE PRECISION , ymax DOUBLE PRECISION , xlimit DOUBLE PRECISION , ylimit DOUBLE PRECISION )
+	RETURNS DOUBLE PRECISION
+	STRICT IMMUTABLE SECURITY INVOKER
+AS $$
+	SELECT ( ( $4 - $2 ) / ( ( $3 - $1 ) ^ 2 ) );
+$$ LANGUAGE SQL;
+
+
+
+--
+-- Happiness curve, K2 constant
+--
+
+CREATE OR REPLACE FUNCTION verse.hcc_const_k2( ylimit DOUBLE PRECISION , yasymptote DOUBLE PRECISION )
+	RETURNS DOUBLE PRECISION
+	STRICT IMMUTABLE SECURITY INVOKER
+AS $$
+	SELECT ( 2 * ( $1 - $2 ) );
+$$ LANGUAGE SQL;
+
+
+
+--
+-- Happiness curve, K3 constant
+--
+
+CREATE OR REPLACE FUNCTION verse.hcc_const_k3( xmax DOUBLE PRECISION , ymax DOUBLE PRECISION , xlimit DOUBLE PRECISION , ylimit DOUBLE PRECISION , yasymptote DOUBLE PRECISION )
+	RETURNS DOUBLE PRECISION
+	STRICT IMMUTABLE SECURITY INVOKER
+AS $$
+	SELECT ( verse.hcc_const_k1( $1 , $2 , $3 , $4 ) * 4 * ( $3 - $1 ) / ( $5 - $4 ) );
+$$ LANGUAGE SQL;
+
+
+
+--
+-- Happiness curve, first part
+--
+
+CREATE OR REPLACE FUNCTION verse.hcc_part_1( x DOUBLE PRECISION , ymin DOUBLE PRECISION , ymax DOUBLE PRECISION , xmax DOUBLE PRECISION )
+	RETURNS DOUBLE PRECISION
+	STRICT IMMUTABLE SECURITY INVOKER
+AS $$
+DECLARE
+	v	DOUBLE PRECISION;
+BEGIN
+	v := ( ymin - ymax ) / xmax;
+	RETURN verse.poly( x , v / xmax , -2 * v , ymin );
+END;
+$$ LANGUAGE plpgsql;
+
+
+
+--
+-- Happiness curve, second part
+--
+
+CREATE OR REPLACE FUNCTION verse.hcc_part_2( x DOUBLE PRECISION , xmax DOUBLE PRECISION , ymax DOUBLE PRECISION , xlimit DOUBLE PRECISION , ylimit DOUBLE PRECISION )
+	RETURNS DOUBLE PRECISION
+	STRICT IMMUTABLE SECURITY INVOKER
+AS $$
+DECLARE
+	k1	DOUBLE PRECISION;
+BEGIN
+	k1 := verse.hcc_const_k1( xmax , ymax , xlimit , ylimit );
+	RETURN verse.poly( x , k1 , -2 * xmax * k1 , ymax + k1 * xmax * xmax );
+END;
+$$ LANGUAGE plpgsql;
+
+
+
+--
+-- Happiness curve, third part
+--
+
+CREATE OR REPLACE FUNCTION verse.hcc_part_3( x DOUBLE PRECISION , xmax DOUBLE PRECISION , ymax DOUBLE PRECISION , xlimit DOUBLE PRECISION , ylimit DOUBLE PRECISION , yasymptote DOUBLE PRECISION )
+	RETURNS DOUBLE PRECISION
+	STRICT IMMUTABLE SECURITY INVOKER
+AS $$
+DECLARE
+	k2	DOUBLE PRECISION;
+	k3	DOUBLE PRECISION;
+BEGIN
+	k2 := verse.hcc_const_k2( ylimit , yasymptote );
+	k3 := verse.hcc_const_k3( xmax , ymax , xlimit , ylimit , yasymptote );
+	RETURN yasymptote + k2 * ( 1 - verse.sigma( ( k3 * ( x - xlimit ) ) ) );
+END;
+$$ LANGUAGE plpgsql;
+
+
+
+--
+-- Happiness curve
+--
+
+CREATE OR REPLACE FUNCTION verse.happiness_curve( x DOUBLE PRECISION , ymin DOUBLE PRECISION , xmax DOUBLE PRECISION , ymax DOUBLE PRECISION , xlimit DOUBLE PRECISION , ylimit DOUBLE PRECISION , yasymptote DOUBLE PRECISION )
+	RETURNS DOUBLE PRECISION
+	STRICT IMMUTABLE SECURITY INVOKER
+AS $$
+	SELECT (CASE
+		WHEN $1 < $3 THEN
+			verse.hcc_part_1( $1 , $2 , $4 , $3 )
+		WHEN $1 < $5 THEN
+			verse.hcc_part_2( $1 , $3 , $4 , $5 , $6 )
+		ELSE
+			verse.hcc_part_3( $1 , $3 , $4 , $5 , $6 , $7 )
+	END)
+$$ LANGUAGE SQL;
+
+
+
+--
+-- Happiness computation
+--
+
+CREATE OR REPLACE FUNCTION verse.compute_happiness( population DOUBLE PRECISION , workers DOUBLE PRECISION , defence DOUBLE PRECISION , empsize INT )
+		RETURNS DOUBLE PRECISION
+		STRICT STABLE SECURITY INVOKER
+	AS $$
+DECLARE
+	whappiness	DOUBLE PRECISION;
+	dhappiness	DOUBLE PRECISION;
+	shappiness	DOUBLE PRECISION;
+BEGIN
+	-- Work-related happiness
+	whappiness := verse.happiness_curve(
+		workers / population ,
+		sys.get_constant( 'game.happiness.noEmployment' ) , 1.0 , 1.0 , 
+		sys.get_constant( 'game.happiness.employmentLimit' ) , 0.5 , 0
+	);
+
+	-- Defence-related happiness
+	dhappiness := verse.happiness_curve(
+		sys.get_constant( 'game.happiness.popPerDefencePoint' ) * defence / population ,
+		sys.get_constant( 'game.happiness.noDefence' ) , 1.0 , 1.0 , 
+		sys.get_constant( 'game.happiness.defenceLimit' ) , 0.5 , 0
+	);
+	
+	-- Influence of empire size
+	shappiness := verse.happiness_curve(
+		empsize / sys.get_constant( 'game.happiness.idealEmpireSize' ) ,
+		sys.get_constant( 'game.happiness.smallEmpire' ) , 1.0 , 1.0 , 
+		sys.get_constant( 'game.happiness.eSizeLimit' ) , 0.5 , 0
+	);
+	
+	RETURN shappiness * ( whappiness + dhappiness ) / 2.0;
+END;
+$$ LANGUAGE plpgsql;
+
+
+
+--
+-- Production adjustment
+--
+CREATE OR REPLACE FUNCTION verse.adjust_production( prod DOUBLE PRECISION , happiness DOUBLE PRECISION )
+	RETURNS DOUBLE PRECISION
+	STRICT IMMUTABLE
+	SECURITY INVOKER
+AS $$
+	SELECT ( CASE
+		WHEN $2 < sys.get_constant( 'game.happiness.strike' ) THEN
+			$1 * ( 1 - ( $2 / sys.get_constant( 'game.happiness.strike' ) ) )
+		ELSE
+			$1
+	END );
+$$ LANGUAGE SQL;
+
+
+--
+-- Income computation
+--
+
+CREATE OR REPLACE FUNCTION verse.compute_income( population DOUBLE PRECISION , happiness DOUBLE PRECISION , cashprod DOUBLE PRECISION )
+		RETURNS DOUBLE PRECISION
+		STRICT STABLE
+		SECURITY INVOKER
+	AS $$
+DECLARE
+	base	DOUBLE PRECISION;
+	badj	DOUBLE PRECISION;
+	cprod	DOUBLE PRECISION;
+BEGIN
+	badj := ( 1 - verse.adjust_production( 1.0 , happiness ) ) * sys.get_constant( 'game.work.strikeEffect' );
+	base := floor( population ) * sys.get_constant( 'game.work.population' ) * ( 1 - badj );
+	cprod := verse.adjust_production( cashprod , happiness ) * sys.get_constant( 'game.work.factory' );
+	RETURN cprod + base;
+END;
+$$ LANGUAGE plpgsql;
+
diff --git a/legacyworlds-server-data/db-structure/parts/040-functions/060-universe.sql b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/functions/060-universe-functions.sql
similarity index 87%
rename from legacyworlds-server-data/db-structure/parts/040-functions/060-universe.sql
rename to legacyworlds-server/legacyworlds-server-data/db-structure/parts/functions/060-universe-functions.sql
index ca6718e..bfccac6 100644
--- a/legacyworlds-server-data/db-structure/parts/040-functions/060-universe.sql
+++ b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/functions/060-universe-functions.sql
@@ -19,14 +19,14 @@
 --
 
 CREATE OR REPLACE FUNCTION verse.get_raw_production( pid INT , pt building_output_type )
-		RETURNS REAL
+		RETURNS DOUBLE PRECISION
 		STRICT STABLE
 		SECURITY DEFINER
 	AS $$
 DECLARE
-	rv	REAL;
+	rv	DOUBLE PRECISION;
 BEGIN
-	SELECT INTO rv SUM( b.amount * d.output )::REAL
+	SELECT INTO rv SUM( b.amount * d.output )
 		FROM verse.planet_buildings b
 			INNER JOIN tech.buildings d
 				ON d.buildable_id = b.building_id AND d.output_type = pt
@@ -114,14 +114,14 @@ $$ LANGUAGE SQL;
 --
 
 CREATE OR REPLACE FUNCTION verse.get_planet_upkeep( pid INT )
-		RETURNS REAL
+		RETURNS DOUBLE PRECISION
 		STRICT STABLE
 		SECURITY INVOKER
 	AS $$
 DECLARE
-	rv	REAL;
+	rv	DOUBLE PRECISION;
 BEGIN
-	SELECT INTO rv SUM( b.amount * d.upkeep )::REAL
+	SELECT INTO rv SUM( b.amount * d.upkeep )
 		FROM verse.planet_buildings b
 			INNER JOIN tech.buildables d
 				ON d.name_id = b.building_id
@@ -145,7 +145,7 @@ $$ LANGUAGE plpgsql;
 --	npics	Amount of planet pictures
 --
 
-CREATE OR REPLACE FUNCTION verse.create_planet( sid INT , o INT , ipop REAL , npics INT )
+CREATE OR REPLACE FUNCTION verse.create_planet( sid INT , o INT , ipop DOUBLE PRECISION , npics INT )
 		RETURNS VOID
 		STRICT VOLATILE
 		SECURITY INVOKER
@@ -156,7 +156,7 @@ DECLARE
 	bpp			INT;
 	uid			BIGINT;
 	utp			update_type;
-	happiness	REAL;
+	happiness	DOUBLE PRECISION;
 BEGIN
 	-- Planet name and planet
 	pnid := naming.create_map_name( 'P' );
@@ -193,9 +193,16 @@ BEGIN
 					verse.get_raw_production( pnid , 'CASH'::building_output_type )
 				) , verse.get_planet_upkeep( pnid ) );
 
-	-- FIXME: for now, just stick data about resources in the appropriate table
-	INSERT INTO verse.planet_resources ( planet_id , resource_name_id )
-		SELECT pnid , resource_name_id FROM defs.resources;
+	-- Add planet update records
+	FOR utp IN SELECT x FROM unnest( enum_range( NULL::update_type ) ) AS x
+					WHERE x::text LIKE 'PLANET_%'
+	LOOP
+		INSERT INTO sys.updates( gu_type )
+			VALUES ( utp )
+			RETURNING id INTO uid;
+		INSERT INTO verse.updates ( update_id , planet_id )
+			VALUES ( uid , pnid );
+	END LOOP;
 END;
 $$ LANGUAGE plpgsql;
 
@@ -210,7 +217,7 @@ $$ LANGUAGE plpgsql;
 --	npics	Amount of planet pictures
 --
 
-CREATE OR REPLACE FUNCTION verse.create_system( sx INT , sy INT , ipop REAL , npics INT )
+CREATE OR REPLACE FUNCTION verse.create_system( sx INT , sy INT , ipop DOUBLE PRECISION , npics INT )
 		RETURNS VOID
 		STRICT VOLATILE
 		SECURITY INVOKER
@@ -238,12 +245,11 @@ $$ LANGUAGE plpgsql;
 -- Generate multiple systems at the specified coordinates
 --
 -- Parameters:
---	_area				Area to generate
+--	(x0,y0)-(x1,y1)		Area to generate
 --	ipop				Initial population
 --
 
-DROP FUNCTION IF EXISTS verse.create_systems( verse.generator_area_type , REAL );
-CREATE FUNCTION verse.create_systems( _area verse.generator_area_type , ipop REAL )
+CREATE OR REPLACE FUNCTION verse.create_systems( x0 INT , y0 INT , x1 INT , y1 INT , ipop DOUBLE PRECISION )
 		RETURNS VOID
 		STRICT VOLATILE
 		SECURITY INVOKER
@@ -253,27 +259,18 @@ DECLARE
 	y		INT;
 	npics	INT;
 BEGIN
-	PERFORM verse.collect_resprov_statistics( );
-
 	npics := floor( sys.get_constant( 'game.universe.pictures' ) );
-	FOR x IN _area.x0 .. _area.x1
+	FOR x IN x0 .. x1
 	LOOP
-		FOR y IN _area.y0 .. _area.y1
+		FOR y IN y0 .. y1
 		LOOP
 			PERFORM verse.create_system( x , y , ipop , npics );
 		END LOOP;
 	END LOOP;
-
-	PERFORM verse.create_resource_providers( _area );
 END;
 $$ LANGUAGE plpgsql;
 
 
-REVOKE EXECUTE
-	ON FUNCTION verse.create_systems( _area verse.generator_area_type , REAL )
-	FROM PUBLIC;
-
-
 
 --
 -- Generate the initial universe
@@ -286,12 +283,12 @@ CREATE OR REPLACE FUNCTION verse.generate_initial_universe( )
 	AS $$
 DECLARE
 	sz		INT;
-	pop 	REAL;
+	pop 	DOUBLE PRECISION;
 	npics	INT;
 BEGIN
 	sz := floor( sys.get_constant( 'game.universe.initialSize' ) );
 	pop := sys.get_constant( 'game.universe.initialPopulation' );
-	PERFORM verse.create_systems( ROW( -sz , -sz , sz , sz ) , pop );
+	PERFORM verse.create_systems( -sz , -sz , sz , sz , pop );
 END;
 $$ LANGUAGE plpgsql;
 
@@ -319,7 +316,7 @@ DECLARE
 	y0		INT;
 	x1		INT;
 	y1		INT;
-	pop		REAL;
+	pop		DOUBLE PRECISION;
 BEGIN
 	-- Get current bounds
 	SELECT INTO min_x , max_x , min_y , max_y
@@ -351,7 +348,7 @@ BEGIN
 
 	-- Get average population and generate new systems
 	SELECT INTO pop AVG( population ) FROM verse.planets;
-	PERFORM verse.create_systems( ROW( x0 , y0 , x1 , y1 ) , pop );
+	PERFORM verse.create_systems( x0 , y0 , x1 , y1 , pop );
 END;
 $$ LANGUAGE plpgsql;
 
@@ -371,7 +368,7 @@ CREATE OR REPLACE FUNCTION verse.generate( )
 	AS $$
 DECLARE
 	p_count	INT;
-	f_ratio	REAL;
+	f_ratio	DOUBLE PRECISION;
 BEGIN
 	-- Get total planet count
 	SELECT INTO p_count 5 * count(*)
@@ -384,7 +381,7 @@ BEGIN
 	END IF;
 
 	-- Get available planets ratio
-	SELECT INTO f_ratio count(*)::REAL / p_count::REAL
+	SELECT INTO f_ratio count(*)::DOUBLE PRECISION / p_count::DOUBLE PRECISION
 		FROM verse.available_planets;
 
 	-- Expand universe if required
@@ -394,4 +391,4 @@ BEGIN
 END;
 $$ LANGUAGE plpgsql;
 
-GRANT EXECUTE ON FUNCTION verse.generate() TO :dbuser;
+GRANT EXECUTE ON FUNCTION verse.generate() TO :dbuser;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/parts/040-functions/070-users.sql b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/functions/070-users-functions.sql
similarity index 99%
rename from legacyworlds-server-data/db-structure/parts/040-functions/070-users.sql
rename to legacyworlds-server/legacyworlds-server-data/db-structure/parts/functions/070-users-functions.sql
index 0e666db..46bb65f 100644
--- a/legacyworlds-server-data/db-structure/parts/040-functions/070-users.sql
+++ b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/functions/070-users-functions.sql
@@ -181,7 +181,7 @@ BEGIN
 	ELSE
 		RAISE EXCEPTION 'Invalid account status % (account #%)' , st , a_id;
 	END IF;
-	PERFORM sys.write_sql_log( 'AccountManagement' , 'ERROR'::log_level , 'Account re-activation mail could not be sent for account #' || a_id || ', deleting validation key' );
+	PERFORM sys.write_log( 'AccountManagement' , 'ERROR'::log_level , 'Account re-activation mail could not be sent for account #' || a_id || ', deleting validation key' );
 END;
 $$ LANGUAGE plpgsql;
 
@@ -470,7 +470,7 @@ BEGIN
 		WHERE a.address = addr
 		FOR UPDATE;
 	IF NOT FOUND THEN
-		PERFORM sys.write_sql_log( 'AccountManagement' , 'WARNING'::log_level , 'account for "'
+		PERFORM sys.write_log( 'AccountManagement' , 'WARNING'::log_level , 'account for "'
 			|| addr || '" not found' );
 		account_error := 1;
 		RETURN;
diff --git a/legacyworlds-server-data/db-structure/parts/040-functions/075-session.sql b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/functions/075-session-functions.sql
similarity index 100%
rename from legacyworlds-server-data/db-structure/parts/040-functions/075-session.sql
rename to legacyworlds-server/legacyworlds-server-data/db-structure/parts/functions/075-session-functions.sql
diff --git a/legacyworlds-server-data/db-structure/parts/040-functions/080-buildings.sql b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/functions/080-buildings-functions.sql
similarity index 100%
rename from legacyworlds-server-data/db-structure/parts/040-functions/080-buildings.sql
rename to legacyworlds-server/legacyworlds-server-data/db-structure/parts/functions/080-buildings-functions.sql
diff --git a/legacyworlds-server-data/db-structure/parts/040-functions/100-status.sql b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/functions/100-status-functions.sql
similarity index 100%
rename from legacyworlds-server-data/db-structure/parts/040-functions/100-status.sql
rename to legacyworlds-server/legacyworlds-server-data/db-structure/parts/functions/100-status-functions.sql
diff --git a/legacyworlds-server-data/db-structure/parts/040-functions/110-prefs.sql b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/functions/110-prefs-functions.sql
similarity index 100%
rename from legacyworlds-server-data/db-structure/parts/040-functions/110-prefs.sql
rename to legacyworlds-server/legacyworlds-server-data/db-structure/parts/functions/110-prefs-functions.sql
diff --git a/legacyworlds-server-data/db-structure/parts/040-functions/120-map.sql b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/functions/120-map-functions.sql
similarity index 100%
rename from legacyworlds-server-data/db-structure/parts/040-functions/120-map.sql
rename to legacyworlds-server/legacyworlds-server-data/db-structure/parts/functions/120-map-functions.sql
diff --git a/legacyworlds-server-data/db-structure/parts/040-functions/140-planets.sql b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/functions/140-planets-functions.sql
similarity index 88%
rename from legacyworlds-server-data/db-structure/parts/040-functions/140-planets.sql
rename to legacyworlds-server/legacyworlds-server-data/db-structure/parts/functions/140-planets-functions.sql
index 8c4955a..582e52a 100644
--- a/legacyworlds-server-data/db-structure/parts/040-functions/140-planets.sql
+++ b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/functions/140-planets-functions.sql
@@ -36,16 +36,14 @@ CREATE TYPE planet_orbital_data AS (
 
 
 -- Planet owner view
-DROP TYPE IF EXISTS emp.planet_owner_data;
-CREATE TYPE emp.planet_owner_data AS (
-	happiness					INT ,
-	h_change					INT ,
-	income						BIGINT ,
-	upkeep						BIGINT ,
-	specific_mining_settings	BOOLEAN ,
-	can_rename					BOOLEAN ,
-	can_abandon					BOOLEAN ,
-	abandon_time				INT
+CREATE TYPE planet_owner_data AS (
+	happiness		INT ,
+	h_change		INT ,
+	income			BIGINT ,
+	upkeep			BIGINT ,
+	can_rename		BOOLEAN ,
+	can_abandon		BOOLEAN ,
+	abandon_time	INT
 );
 
 
@@ -177,17 +175,17 @@ CREATE OR REPLACE FUNCTION verse.get_orbital_view( e_id INT , p_id INT )
 	AS $$
 DECLARE
 	rv		planet_orbital_data;
-	happ	REAL;
+	happ	DOUBLE PRECISION;
 	e_att	BOOLEAN;
 	rec		RECORD;
 BEGIN
 	-- Get the planet's population and defence
 	SELECT INTO rv.population , happ
-			floor( p.population )::BIGINT , ( ph.current / p.population )::REAL
+			floor( p.population )::BIGINT , ( ph.current / p.population )::DOUBLE PRECISION
 		FROM verse.planets p
 			INNER JOIN verse.planet_happiness ph ON ph.planet_id = p.name_id
 		WHERE p.name_id = p_id;
-	rv.defence := round( verse.adjust_production( verse.get_raw_production( p_id , 'DEF' ) , happ ) );
+	rv.defence := verse.adjust_production( verse.get_raw_production( p_id , 'DEF' ) , happ );
 
 	-- Get the empire's fleet mode
 	SELECT INTO e_att f.attacking
@@ -245,33 +243,26 @@ GRANT EXECUTE ON FUNCTION verse.get_orbital_view( INT , INT ) TO :dbuser;
 --	an owner planet view entry
 --
 
-DROP FUNCTION IF EXISTS verse.get_owner_view( INT , INT ) CASCADE;
 CREATE OR REPLACE FUNCTION verse.get_owner_view( e_id INT , p_id INT )
-		RETURNS emp.planet_owner_data
+		RETURNS planet_owner_data
 		STRICT STABLE
 		SECURITY DEFINER
 	AS $$
 DECLARE
-	rv		emp.planet_owner_data;
+	rv		planet_owner_data;
 	t_happ	INT;
 	h_chg	INT;
 	mdelay	BIGINT;
 	r_time	INTERVAL;
 BEGIN
 	-- Get income, upkeep, current and target happiness
-	SELECT INTO rv.income , rv.upkeep , rv.happiness , t_happ , rv.specific_mining_settings
+	SELECT INTO rv.income , rv.upkeep , rv.happiness , t_happ
 			floor( pm.income )::INT , floor( pm.upkeep )::INT ,
 			floor( 100 * ph.current / p.population )::INT ,
-			floor( 100 * ph.target )::INT ,
-			_count.settings_exist
+			floor( 100 * ph.target )::INT
 		FROM verse.planets p
 			INNER JOIN verse.planet_happiness ph ON ph.planet_id = p.name_id
 			INNER JOIN verse.planet_money pm ON pm.planet_id = p.name_id
-			CROSS JOIN (
-				SELECT ( COUNT( * ) > 0 ) AS settings_exist
-					FROM emp.planet_mining_settings
-					WHERE planet_id = p_id AND empire_id = e_id
-			) _count
 		WHERE p.name_id = p_id;
 
 	-- Compute happiness change indicator
@@ -315,12 +306,7 @@ BEGIN
 END;
 $$ LANGUAGE plpgsql;
 
-REVOKE EXECUTE
-	ON FUNCTION verse.get_owner_view( INT , INT )
-	FROM PUBLIC;
-GRANT EXECUTE
-	ON FUNCTION verse.get_owner_view( INT , INT )
-	TO :dbuser;
+GRANT EXECUTE ON FUNCTION verse.get_owner_view( INT , INT ) TO :dbuser;
 
 
 
@@ -346,8 +332,7 @@ AS $$
 				( bd.workers * b.amount )::INT AS jobs ,
 				( bd.upkeep * b.amount  )::BIGINT AS upkeep ,
 				bd.output_type AS p_type ,
-				floor( verse.adjust_production( ( bd.output * b.amount )::REAL ,
-						( ph.current / p.population )::REAL )
+				floor( verse.adjust_production( bd.output * b.amount , ph.current / p.population )
 				)::BIGINT AS p_value
 		FROM verse.planet_buildings b
 			INNER JOIN verse.planets p ON p.name_id = b.planet_id
@@ -387,9 +372,9 @@ AS $$
 				ELSE floor( qi.amount * bd.cost - ( CASE WHEN qi.queue_order = 0 THEN q.money ELSE 0 END ) )
 			END )::BIGINT AS investment ,
 			( CASE
-				WHEN ceil( verse.adjust_production( ( p.population * sys.get_constant( 'game.work.wuPerPopUnit' ) )::REAL , ( ph.current / p.population )::REAL ) ) = 0 THEN NULL
+				WHEN ceil( verse.adjust_production( p.population * sys.get_constant( 'game.work.wuPerPopUnit' ) , ph.current / p.population ) ) = 0 THEN NULL
 				ELSE ceil( ( qi.amount * bd.work * ( CASE WHEN qi.destroy THEN sys.get_constant( 'game.work.destructionWork' ) ELSE 1 END ) - ( CASE WHEN qi.queue_order = 0 THEN q.work ELSE 0 END ) )
-							/ verse.adjust_production( ( p.population * sys.get_constant( 'game.work.wuPerPopUnit' ) )::REAL , ( ph.current / p.population )::REAL ) )
+							/ verse.adjust_production( p.population * sys.get_constant( 'game.work.wuPerPopUnit' ) , ph.current / p.population ) )
 			END )::BIGINT AS time_left
 		FROM verse.planets p
 			INNER JOIN verse.planet_happiness ph ON ph.planet_id = p.name_id
@@ -428,9 +413,9 @@ AS $$
 			qi.amount AS amount , FALSE AS destroy ,
 			floor( qi.amount * bd.cost - ( CASE WHEN qi.queue_order = 0 THEN q.money ELSE 0 END ) )::BIGINT AS investment ,
 			( CASE
-				WHEN ceil( verse.adjust_production( verse.get_raw_production( $1 , 'WORK' ) , ( ph.current / p.population )::REAL ) ) = 0 THEN NULL
+				WHEN ceil( verse.adjust_production( verse.get_raw_production( $1 , 'WORK' ) , ph.current / p.population ) ) = 0 THEN NULL
 				ELSE ceil( ( qi.amount * bd.work - ( CASE WHEN qi.queue_order = 0 THEN q.work ELSE 0 END ) )
-							/ verse.adjust_production( verse.get_raw_production( $1 , 'WORK' ) , ( ph.current / p.population )::REAL ) )
+							/ verse.adjust_production( verse.get_raw_production( $1 , 'WORK' ) , ph.current / p.population ) )
 			END )::BIGINT AS time_left
 		FROM verse.planets p
 			INNER JOIN verse.planet_happiness ph ON ph.planet_id = p.name_id
@@ -468,8 +453,8 @@ AS $$
 	SELECT bv.name_id AS id , t1.translated_string AS name , t2.translated_string AS description ,
 			bv.cost AS cost ,
 			( CASE
-				WHEN ceil( pdat.p_work ) = 0 THEN NULL
-				ELSE ceil( bv.work / pdat.p_work )
+			    WHEN ceil( pdat.p_work ) = 0 THEN NULL
+			    ELSE ceil( bv.work / pdat.p_work )
 			END )::BIGINT AS time_to_build ,
 			bv.upkeep AS upkeep , bv.workers AS workers , bv.output_type AS p_type , bv.output AS p_value
 	    FROM (
@@ -478,12 +463,13 @@ AS $$
 					INNER JOIN tech.basic_buildables bb USING( name_id )
 			UNION SELECT bv.*
 			    FROM tech.buildings_view bv
+					INNER JOIN tech.buildable_requirements r ON r.buildable_id = bv.name_id
+					INNER JOIN tech.technologies l ON l.name_id = r.technology_id
 					INNER JOIN emp.planets ep ON ep.planet_id = $1
-					INNER JOIN emp.technologies _emptech
-						USING ( technology_name_id , empire_id )
-				WHERE emptech_state = 'KNOWN' 
+					INNER JOIN emp.researched_technologies t
+					    ON t.empire_id = ep.empire_id AND t.technology_id = l.name_id
 		    ) AS bv , (
-			SELECT verse.adjust_production( ( p.population * sys.get_constant( 'game.work.wuPerPopUnit' ) )::REAL , ( ph.current / p.population )::REAL ) AS p_work ,
+			SELECT verse.adjust_production( p.population * sys.get_constant( 'game.work.wuPerPopUnit' ) , ph.current / p.population ) AS p_work ,
 				c.language_id AS language
 			    FROM verse.planets p
 					INNER JOIN verse.planet_happiness ph ON ph.planet_id = p.name_id
@@ -529,12 +515,13 @@ AS $$
 					INNER JOIN tech.basic_buildables bb USING( name_id )
 			UNION SELECT bv.*
 			    FROM tech.ships_view bv
+					INNER JOIN tech.buildable_requirements r ON r.buildable_id = bv.name_id
+					INNER JOIN tech.technologies l ON l.name_id = r.technology_id
 					INNER JOIN emp.planets ep ON ep.planet_id = $1
-					INNER JOIN emp.technologies t
-						USING ( empire_id , technology_name_id )
-				WHERE emptech_state = 'KNOWN' 
+					INNER JOIN emp.researched_technologies t
+					    ON t.empire_id = ep.empire_id AND t.technology_id = l.name_id
 		    ) AS bv , (
-			SELECT verse.adjust_production( verse.get_raw_production( $1 , 'WORK' ) , ( ph.current / p.population )::REAL ) AS p_work ,
+			SELECT verse.adjust_production( verse.get_raw_production( $1 , 'WORK' ) , ph.current / p.population ) AS p_work ,
 				c.language_id AS language
 			    FROM verse.planets p
 					INNER JOIN verse.planet_happiness ph ON ph.planet_id = p.name_id
@@ -606,7 +593,7 @@ CREATE OR REPLACE FUNCTION verse.flush_build_queue( p_id INT )
 	AS $$
 DECLARE
 	e_id	INT;
-	q_cash	REAL;
+	q_cash	DOUBLE PRECISION;
 BEGIN
 	SELECT INTO e_id , q_cash e.name_id , q.money
 		FROM verse.planets p
@@ -645,7 +632,7 @@ CREATE OR REPLACE FUNCTION verse.flush_military_queue( p_id INT )
 	AS $$
 DECLARE
 	e_id	INT;
-	q_cash	REAL;
+	q_cash	DOUBLE PRECISION;
 BEGIN
 	SELECT INTO e_id , q_cash e.name_id , q.money
 		FROM verse.planets p
@@ -687,8 +674,8 @@ CREATE OR REPLACE FUNCTION verse.add_military_item( p_id INT , s_id INT , s_cnt
 DECLARE
 	e_id		INT;
 	qlen		INT;
-	_needed		INT;
-	_known		INT;
+	dep_level	INT;
+	has_level	INT;
 BEGIN
 	IF s_cnt < 1 THEN
 		RETURN;
@@ -707,16 +694,16 @@ BEGIN
 	END IF;
 
 	-- Check technologies
-	SELECT INTO _needed , _known
-			b.technology_name_id , t.technology_name_id
+	SELECT INTO dep_level , has_level l.level , t.level
 		FROM tech.ships s
-			INNER JOIN tech.buildables b
-				ON b.name_id = s.buildable_id
-			LEFT OUTER JOIN emp.technologies t
-				ON t.empire_id = e_id AND t.technology_name_id = b.technology_name_id
-					AND t.emptech_state = 'KNOWN'
+			LEFT OUTER JOIN tech.buildable_requirements r
+				ON r.buildable_id = s.buildable_id
+			LEFT OUTER JOIN tech.technologies l
+				ON l.name_id = r.technology_id
+			LEFT OUTER JOIN emp.researched_technologies t
+				ON t.empire_id = e_id AND t.technology_id = l.name_id
 		WHERE s.buildable_id = s_id;
-	IF NOT FOUND OR ( _known IS NULL AND _needed IS NOT NULL ) THEN
+	IF NOT FOUND OR ( has_level IS NULL AND dep_level IS NOT NULL ) THEN
 		RETURN;
 	END IF;
 
@@ -753,8 +740,8 @@ CREATE OR REPLACE FUNCTION verse.construct_buildings( p_id INT , b_id INT , b_cn
 DECLARE
 	e_id		INT;
 	qlen		INT;
-	_needed		INT;
-	_known		INT;
+	dep_level	INT;
+	has_level	INT;
 BEGIN
 	IF b_cnt < 1 THEN
 		RETURN;
@@ -773,16 +760,16 @@ BEGIN
 	END IF;
 
 	-- Check technologies
-	SELECT INTO _needed , _known
-			b.technology_name_id , t.technology_name_id
-		FROM tech.buildings s
-			INNER JOIN tech.buildables b
-				ON b.name_id = s.buildable_id
-			LEFT OUTER JOIN emp.technologies t
-				ON t.empire_id = e_id AND t.technology_name_id = b.technology_name_id
-					AND t.emptech_state = 'KNOWN'
-		WHERE s.buildable_id = b_id;
-	IF NOT FOUND OR ( _known IS NULL AND _needed IS NOT NULL ) THEN
+	SELECT INTO dep_level , has_level l.level , t.level
+		FROM tech.buildings b
+			LEFT OUTER JOIN tech.buildable_requirements r
+				ON r.buildable_id = b.buildable_id
+			LEFT OUTER JOIN tech.technologies l
+				ON l.name_id = r.technology_id
+			LEFT OUTER JOIN emp.researched_technologies t
+				ON t.empire_id = e_id AND t.technology_id = l.name_id
+		WHERE b.buildable_id = b_id;
+	IF NOT FOUND OR ( has_level IS NULL AND dep_level IS NOT NULL ) THEN
 		RETURN;
 	END IF;
 
@@ -991,7 +978,7 @@ $$ LANGUAGE plpgsql;
 --	tick		Current tick
 --
 
-CREATE OR REPLACE FUNCTION verse.inflict_battle_damage( p_id INT , t_power BIGINT , dmg REAL , b_id BIGINT , tick BIGINT )
+CREATE OR REPLACE FUNCTION verse.inflict_battle_damage( p_id INT , t_power BIGINT , dmg DOUBLE PRECISION , b_id BIGINT , tick BIGINT )
 		RETURNS VOID
 		STRICT VOLATILE
 		SECURITY INVOKER
@@ -999,10 +986,10 @@ CREATE OR REPLACE FUNCTION verse.inflict_battle_damage( p_id INT , t_power BIGIN
 DECLARE
 	rec		RECORD;
 	bp_id	BIGINT;
-	st_dmg	REAL;
+	st_dmg	DOUBLE PRECISION;
 	n_dest	INT;
 BEGIN
-	PERFORM sys.write_sql_log( 'BattleUpdate' , 'TRACE'::log_level , 'Inflicting ' || dmg
+	PERFORM sys.write_log( 'BattleUpdate' , 'TRACE'::log_level , 'Inflicting ' || dmg
 		|| ' damage to planet #' || p_id );
 
 	bp_id := NULL;
@@ -1020,7 +1007,7 @@ BEGIN
 			st_dmg := 0;
 		END IF;
 		
-		PERFORM sys.write_sql_log( 'BattleUpdate' , 'TRACE'::log_level , 'Building type #' || rec.building_id
+		PERFORM sys.write_log( 'BattleUpdate' , 'TRACE'::log_level , 'Building type #' || rec.building_id
 			|| ' - Damage ' || st_dmg || '; destruction: ' || n_dest );
 
 		-- Apply damage
@@ -1050,23 +1037,23 @@ $$ LANGUAGE plpgsql;
 --	d_ratio		Debt damage ratio
 --
 
-CREATE OR REPLACE FUNCTION verse.handle_debt( e_id INT , t_upkeep REAL , debt REAL , d_ratio REAL )
+CREATE OR REPLACE FUNCTION verse.handle_debt( e_id INT , t_upkeep DOUBLE PRECISION , debt DOUBLE PRECISION , d_ratio DOUBLE PRECISION )
 		RETURNS VOID
 		STRICT VOLATILE
 		SECURITY INVOKER
 	AS $$
 DECLARE
 	tick		BIGINT;
-	tot_damage	REAL;
+	tot_damage	DOUBLE PRECISION;
 	p_rec		RECORD;
 	b_rec		RECORD;
 	bp_id		BIGINT;
-	b_damage	REAL;
+	b_damage	DOUBLE PRECISION;
 	n_destroy	INT;
 BEGIN
 	tick := sys.get_tick( ) - 1;
 	tot_damage := t_upkeep * d_ratio / debt;
-	PERFORM sys.write_sql_log( 'EmpireDebt' , 'DEBUG'::log_level , 'Inflicting debt damage to buildings; total upkeep: '
+	PERFORM sys.write_log( 'EmpireDebt' , 'DEBUG'::log_level , 'Inflicting debt damage to buildings; total upkeep: '
 		|| t_upkeep || ', damage ratio: ' || d_ratio || ', total damage: ' || tot_damage );
 
 	FOR p_rec IN SELECT ep.planet_id AS planet , b.id AS battle
@@ -1078,7 +1065,7 @@ BEGIN
 		bp_id := NULL;
 		
 		FOR b_rec IN SELECT b.building_id AS building , b.amount AS amount ,
-							( b.amount * bb.upkeep )::REAL AS upkeep ,
+							b.amount * bb.upkeep AS upkeep ,
 							b.damage AS damage , ( bd.output_type = 'DEF' ) AS is_def
 						FROM verse.planet_buildings b
 							INNER JOIN tech.buildables bb ON bb.name_id = b.building_id
@@ -1111,4 +1098,4 @@ BEGIN
 		END LOOP;
 	END LOOP;
 END;
-$$ LANGUAGE plpgsql;
+$$ LANGUAGE plpgsql;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/parts/040-functions/150-battle.sql b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/functions/150-battle-functions.sql
similarity index 97%
rename from legacyworlds-server-data/db-structure/parts/040-functions/150-battle.sql
rename to legacyworlds-server/legacyworlds-server-data/db-structure/parts/functions/150-battle-functions.sql
index d6a4607..94827f0 100644
--- a/legacyworlds-server-data/db-structure/parts/040-functions/150-battle.sql
+++ b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/functions/150-battle-functions.sql
@@ -626,7 +626,7 @@ $$ LANGUAGE plpgsql;
 --	tick	Current tick identifier
 --
 
-CREATE OR REPLACE FUNCTION battles.inflict_damage( b_id BIGINT , dmg REAL , att BOOLEAN , tick BIGINT )
+CREATE OR REPLACE FUNCTION battles.inflict_damage( b_id BIGINT , dmg DOUBLE PRECISION , att BOOLEAN , tick BIGINT )
 		RETURNS VOID
 		STRICT VOLATILE
 		SECURITY INVOKER
@@ -653,10 +653,10 @@ BEGIN
 	IF NOT att THEN
 		st_power := battles.get_defence_power( b_id , tick );
 		tot_power := tot_power + st_power;
-		PERFORM sys.write_sql_log( 'BattleUpdate' , 'TRACE'::log_level , 'About to inflict planet damage; total power: ' || tot_power
-			|| '; planet power: ' || st_power || '; computed damage: ' || ( dmg * st_power / tot_power )::REAL );
+		PERFORM sys.write_log( 'BattleUpdate' , 'TRACE'::log_level , 'About to inflict planet damage; total power: ' || tot_power
+			|| '; planet power: ' || st_power || '; computed damage: ' || ( dmg * st_power / tot_power ) );
 		IF st_power <> 0 THEN
-			PERFORM verse.inflict_battle_damage( planet , st_power , ( dmg * st_power / tot_power )::REAL , b_id , tick );
+			PERFORM verse.inflict_battle_damage( planet , st_power , dmg * st_power / tot_power , b_id , tick );
 		END IF;
 	END IF;
 	
@@ -668,7 +668,7 @@ BEGIN
 					LEFT OUTER JOIN fleets.movements m ON m.fleet_id = f.id
 				WHERE b.id = b_id AND m.fleet_id IS NULL AND f.attacking = att
 	LOOP
-		PERFORM fleets.inflict_battle_damage( rec.id , ( dmg * rec.power / tot_power )::REAL , b_id , tick );
+		PERFORM fleets.inflict_battle_damage( rec.id , dmg * rec.power / tot_power , b_id , tick );
 	END LOOP;
 END;
 $$ LANGUAGE plpgsql;
diff --git a/legacyworlds-server-data/db-structure/parts/040-functions/160-battle-views.sql b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/functions/160-battle-views.sql
similarity index 99%
rename from legacyworlds-server-data/db-structure/parts/040-functions/160-battle-views.sql
rename to legacyworlds-server/legacyworlds-server-data/db-structure/parts/functions/160-battle-views.sql
index c649e10..4309c03 100644
--- a/legacyworlds-server-data/db-structure/parts/040-functions/160-battle-views.sql
+++ b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/functions/160-battle-views.sql
@@ -256,8 +256,8 @@ CREATE VIEW battles.buildings_history
 					WHEN rbp.raw_power = 0 THEN
 						rbh.raw_power
 					ELSE
-						rbh.raw_power::REAL * rbp.actual_power::REAL / rbp.raw_power::REAL
-				END )::REAL AS power
+						rbh.raw_power * rbp.actual_power / rbp.raw_power
+				END ) AS power
 			FROM battles.empire_list_view elv
 				INNER JOIN battles.raw_buildings_history rbh USING (battle)
 				INNER JOIN battles.raw_buildings_power rbp USING (battle,tick)
diff --git a/legacyworlds-server-data/db-structure/parts/040-functions/163-alliance.sql b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/functions/163-alliance-functions.sql
similarity index 100%
rename from legacyworlds-server-data/db-structure/parts/040-functions/163-alliance.sql
rename to legacyworlds-server/legacyworlds-server-data/db-structure/parts/functions/163-alliance-functions.sql
diff --git a/legacyworlds-server-data/db-structure/parts/040-functions/165-fleets.sql b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/functions/165-fleets-functions.sql
similarity index 95%
rename from legacyworlds-server-data/db-structure/parts/040-functions/165-fleets.sql
rename to legacyworlds-server/legacyworlds-server-data/db-structure/parts/functions/165-fleets-functions.sql
index 7bb87dd..4d2e02b 100644
--- a/legacyworlds-server-data/db-structure/parts/040-functions/165-fleets.sql
+++ b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/functions/165-fleets-functions.sql
@@ -55,7 +55,7 @@ $$ LANGUAGE plpgsql;
 --	the in-system movement's duration
 --
 
-CREATE OR REPLACE FUNCTION fleets.compute_insystem_duration( f_time INT , s_orbit REAL , d_orbit REAL )
+CREATE OR REPLACE FUNCTION fleets.compute_insystem_duration( f_time INT , s_orbit DOUBLE PRECISION , d_orbit DOUBLE PRECISION )
 		RETURNS INT
 		STRICT IMMUTABLE
 		SECURITY INVOKER
@@ -84,7 +84,7 @@ $$ LANGUAGE plpgsql;
 --	the outer space movement's duration
 --
 
-CREATE OR REPLACE FUNCTION fleets.compute_outerspace_duration( f_time INT , s_x REAL , s_y REAL , d_x REAL , d_y REAL )
+CREATE OR REPLACE FUNCTION fleets.compute_outerspace_duration( f_time INT , s_x DOUBLE PRECISION , s_y DOUBLE PRECISION , d_x DOUBLE PRECISION , d_y DOUBLE PRECISION )
 		RETURNS INT
 		STRICT IMMUTABLE
 		SECURITY INVOKER
@@ -115,16 +115,16 @@ $$ LANGUAGE plpgsql;
 
 CREATE OR REPLACE FUNCTION fleets.compute_current_orbit(
 			f_time INT , rp_orbit INT , outwards BOOLEAN , past_rp BOOLEAN , ft_left INT )
-		RETURNS REAL
+		RETURNS DOUBLE PRECISION
 		STRICT IMMUTABLE
 		SECURITY INVOKER
 	AS $$
 DECLARE
-	dist	REAL;
-	dir		REAL;
-	rloc	REAL;
+	dist	DOUBLE PRECISION;
+	dir		DOUBLE PRECISION;
+	rloc	DOUBLE PRECISION;
 BEGIN
-	dist := 1.0 - ft_left::REAL / f_time::REAL;
+	dist := 1.0 - ft_left::DOUBLE PRECISION / f_time::DOUBLE PRECISION;
 	dir := ( CASE WHEN outwards THEN 0.5 ELSE -0.5 END );
 	IF past_rp THEN
 		rloc := rp_orbit;
@@ -157,13 +157,14 @@ $$ LANGUAGE plpgsql;
 --
 
 CREATE OR REPLACE FUNCTION fleets.compute_current_location(
-			f_time INT , s_x REAL , s_y REAL , d_x REAL , d_y REAL , r_time INT ,
-			OUT c_x REAL , OUT c_y REAL )
+			f_time INT , s_x DOUBLE PRECISION , s_y DOUBLE PRECISION ,
+			d_x DOUBLE PRECISION , d_y DOUBLE PRECISION , r_time INT ,
+			OUT c_x DOUBLE PRECISION , OUT c_y DOUBLE PRECISION )
 		STRICT IMMUTABLE
 		SECURITY INVOKER
 	AS $$
 DECLARE
-	tot_time	REAL;
+	tot_time	DOUBLE PRECISION;
 BEGIN
 	tot_time := fleets.compute_outerspace_duration( f_time , s_x , s_y , d_x , d_y );
 	c_x := s_x + ( d_x - s_x ) * ( 1 - r_time / tot_time );
@@ -251,7 +252,7 @@ $$ LANGUAGE plpgsql;
 --
 
 CREATE OR REPLACE FUNCTION fleets.compute_insystem_redirect(
-			f_time INT , s_sys INT , s_orbit REAL , d_id INT ,
+			f_time INT , s_sys INT , s_orbit DOUBLE PRECISION , d_id INT ,
 			OUT duration INT , OUT direction BOOLEAN , OUT s_duration INT ,
 			OUT ref_point INT , OUT past_rp BOOLEAN )
 		STRICT IMMUTABLE
@@ -260,7 +261,7 @@ CREATE OR REPLACE FUNCTION fleets.compute_insystem_redirect(
 DECLARE
 	s_rec	RECORD;
 	d_rec	RECORD;
-	torb	REAL;
+	torb	DOUBLE PRECISION;
 	rporb	INT;
 BEGIN
 	-- Get destination planet coordinates, orbit and system ID
@@ -294,9 +295,9 @@ BEGIN
 		ELSE
 			torb := floor( torb );
 		END IF;
-		s_duration := fleets.compute_insystem_duration( f_time , s_orbit , ( torb / 2 )::REAL );
+		s_duration := fleets.compute_insystem_duration( f_time , s_orbit , torb / 2 );
 		rporb := round( s_orbit );
-		past_rp := ( CASE WHEN direction THEN ( rporb::REAL <= s_orbit ) ELSE ( rporb::REAL >= s_orbit ) END );
+		past_rp := ( CASE WHEN direction THEN ( rporb <= s_orbit ) ELSE ( rporb >= s_orbit ) END );
 	END IF;
 	SELECT INTO ref_point name_id FROM verse.planets p
 		WHERE p.system_id = s_sys AND orbit = rporb;
@@ -322,7 +323,7 @@ $$ LANGUAGE plpgsql;
 --
 
 CREATE OR REPLACE FUNCTION fleets.compute_outerspace_redirect(
-			f_time INT , s_x REAL , s_y REAL , d_id INT ,
+			f_time INT , s_x DOUBLE PRECISION , s_y DOUBLE PRECISION , d_id INT ,
 			OUT duration INT , OUT s_duration INT )
 		STRICT IMMUTABLE
 		SECURITY INVOKER
@@ -365,8 +366,8 @@ DECLARE
 	dir		BOOLEAN;
 	rpid	INT;
 	prp		BOOLEAN;
-	cx		REAL;
-	cy		REAL;
+	cx		DOUBLE PRECISION;
+	cy		DOUBLE PRECISION;
 BEGIN
 	-- Lock fleets and planets
 	PERFORM * FROM fleets.fleets f
@@ -415,17 +416,17 @@ BEGIN
 			-- Fleet redirection
 			IF rec.is_ref_point IS NULL THEN
 				-- Fleet moving in outer space
-				PERFORM sys.write_sql_log( 'Fleets' , 'TRACE'::log_level , 'About to perform outer space redirect; '
+				PERFORM sys.write_log( 'Fleets' , 'TRACE'::log_level , 'About to perform outer space redirect; '
 					|| 'OOFT/2 = ' || rec.flight_time || '; start(x;y)= (' || rec.os_start_x || ';' || rec.os_start_y
 					|| '); dest(x;y)= (' || rec.x || ';' || rec.y || '); time left: ' || rec.mv_state_time );
 				SELECT INTO cx , cy c_x , c_y FROM fleets.compute_current_location(
 						rec.flight_time , rec.os_start_x , rec.os_start_y , rec.x , rec.y ,
 						rec.mv_state_time );
-				PERFORM sys.write_sql_log( 'Fleets' , 'TRACE'::log_level , 'Computed current coordinates: (' || cx
+				PERFORM sys.write_log( 'Fleets' , 'TRACE'::log_level , 'Computed current coordinates: (' || cx
 					|| ';' || cy || ')' );
 				SELECT INTO dur , s_dur duration , s_duration
 					FROM fleets.compute_outerspace_redirect( rec.flight_time , cx , cy , dest_id );
-				PERFORM sys.write_sql_log( 'Fleets' , 'TRACE'::log_level , 'Computed new total/state duration: '
+				PERFORM sys.write_log( 'Fleets' , 'TRACE'::log_level , 'Computed new total/state duration: '
 					|| dur || ' / ' || s_dur );
 				UPDATE fleets.ms_space SET start_x = cx , start_y = cy
 					WHERE movement_id = rec.id; 
@@ -676,10 +677,10 @@ DECLARE
 	old_ft	INT;
 	new_ft	INT;
 	sp_ft	INT;
-	x		REAL;
-	y		REAL;
-	cx		REAL;
-	cy		REAL;
+	x		DOUBLE PRECISION;
+	y		DOUBLE PRECISION;
+	cx		DOUBLE PRECISION;
+	cy		DOUBLE PRECISION;
 	sid		INT;
 BEGIN
 	SELECT INTO main * FROM fleet_split_main;
@@ -705,7 +706,7 @@ BEGIN
 		IF new_ft <> old_ft THEN
 			IF ism_rec IS NULL THEN
 				-- Outer space movement
-				SELECT INTO x , y s.x::REAL , s.y::REAL
+				SELECT INTO x , y s.x , s.y
 					FROM verse.planets p
 						INNER JOIN verse.systems s ON s.id = p.system_id
 					WHERE p.name_id = main.location;
@@ -754,7 +755,7 @@ BEGIN
 				IF sp_ft <> old_ft THEN
 					IF ism_rec IS NULL THEN
 						-- Outer space movement
-						SELECT INTO x , y s.x::REAL , s.y::REAL
+						SELECT INTO x , y s.x , s.y
 							FROM verse.planets p
 								INNER JOIN verse.systems s ON s.id = p.system_id
 							WHERE p.name_id = main.location;
@@ -983,7 +984,7 @@ GRANT EXECUTE ON FUNCTION fleets.disband( INT , BIGINT[] ) TO :dbuser;
 --	tick	Current tick
 --
 
-CREATE OR REPLACE FUNCTION fleets.inflict_battle_damage( f_id BIGINT , dmg REAL , b_id BIGINT , tick BIGINT )
+CREATE OR REPLACE FUNCTION fleets.inflict_battle_damage( f_id BIGINT , dmg DOUBLE PRECISION , b_id BIGINT , tick BIGINT )
 		RETURNS VOID
 		STRICT VOLATILE
 		SECURITY INVOKER
@@ -995,12 +996,12 @@ DECLARE
 	bp_id	BIGINT;
 	bf_id	BIGINT;
 	rec		RECORD;
-	st_dmg	REAL;
+	st_dmg	DOUBLE PRECISION;
 	n_dest	INT;
 	found	INT;
 	deleted	INT;
 BEGIN
-	PERFORM sys.write_sql_log( 'BattleUpdate' , 'TRACE'::log_level , 'Inflicting '
+	PERFORM sys.write_log( 'BattleUpdate' , 'TRACE'::log_level , 'Inflicting '
 		|| dmg || ' damage to fleet #' || f_id );
 
 	-- Get total fleet power and battle protagonist
@@ -1066,19 +1067,19 @@ $$ LANGUAGE plpgsql;
 --	d_ratio		Debt damage ratio
 --
 
-CREATE OR REPLACE FUNCTION fleets.handle_debt( e_id INT , t_upkeep REAL , debt REAL , d_ratio REAL )
+CREATE OR REPLACE FUNCTION fleets.handle_debt( e_id INT , t_upkeep DOUBLE PRECISION , debt DOUBLE PRECISION , d_ratio DOUBLE PRECISION )
 		RETURNS VOID
 		STRICT VOLATILE
 		SECURITY INVOKER
 	AS $$
 DECLARE
-	tot_damage	REAL;
+	tot_damage	DOUBLE PRECISION;
 	f_rec		RECORD;
 	s_rec		RECORD;
 	n_found		INT;
 	n_killed	INT;
 	s_killed	INT;
-	s_damage	REAL;
+	s_damage	DOUBLE PRECISION;
 	n_ships		INT;
 	tick		BIGINT;
 	bp_id		BIGINT;
@@ -1086,15 +1087,15 @@ DECLARE
 	mv_rec		fleets.movements%ROWTYPE;
 	ism_rec		fleets.ms_system%ROWTYPE;
 	osm_rec		fleets.ms_space%ROWTYPE;
-	x			REAL;
-	y			REAL;
-	cx			REAL;
-	cy			REAL;
+	x			DOUBLE PRECISION;
+	y			DOUBLE PRECISION;
+	cx			DOUBLE PRECISION;
+	cy			DOUBLE PRECISION;
 	sid			INT;
 BEGIN
 	tick := sys.get_tick( ) - 1;
 	tot_damage := t_upkeep * d_ratio / debt;
-	PERFORM sys.write_sql_log( 'EmpireDebt' , 'DEBUG'::log_level , 'Inflicting debt damage to fleets; total upkeep: '
+	PERFORM sys.write_log( 'EmpireDebt' , 'DEBUG'::log_level , 'Inflicting debt damage to fleets; total upkeep: '
 		|| t_upkeep || ', damage ratio: ' || d_ratio || ', total damage: ' || tot_damage );
 
 	FOR f_rec IN SELECT f.id AS fleet , f.status , f.location_id AS location ,
@@ -1120,7 +1121,7 @@ BEGIN
 		n_killed := 0;
 		s_killed := 0;
 		FOR s_rec IN SELECT s.ship_id AS ship , s.amount AS amount , s.damage AS damage ,
-							( d.upkeep * s.amount )::REAL AS upkeep
+							d.upkeep * s.amount AS upkeep
 						FROM fleets.ships s
 							INNER JOIN tech.buildables d ON d.name_id = s.ship_id
 						WHERE s.fleet_id = f_rec.fleet
@@ -1174,7 +1175,7 @@ BEGIN
 
 			IF ism_rec IS NULL THEN
 				-- Outer space movement
-				SELECT INTO x , y s.x::REAL , s.y::REAL
+				SELECT INTO x , y s.x , s.y
 					FROM verse.planets p
 						INNER JOIN verse.systems s ON s.id = p.system_id
 					WHERE p.name_id = f_rec.location;
@@ -1386,7 +1387,7 @@ GRANT SELECT ON fleets.static_fleets TO :dbuser;
 CREATE VIEW fleets.outer_space_fleets
 	AS SELECT s.movement_id AS id , m.state_time_left AS time_left ,
 				s.start_x AS x0 , s.start_y AS y0 ,
-				ts.x::REAL AS x1 , ts.y::REAL AS y1
+				ts.x::DOUBLE PRECISION AS x1 , ts.y::DOUBLE PRECISION AS y1
 			FROM fleets.ms_space s
 				INNER JOIN fleets.movements m ON m.fleet_id = s.movement_id
 				INNER JOIN fleets.fleets f ON m.fleet_id = f.id
@@ -1422,14 +1423,14 @@ CREATE VIEW fleets.moving_fleets
 				f.location_id AS to_id , dn.name AS to_name ,
 				( CASE
 					WHEN osf.id IS NULL THEN isf.x
-					ELSE ( osf.x1 - osf.time_left::REAL * ( osf.x1 - osf.x0 )
+					ELSE ( osf.x1 - osf.time_left * ( osf.x1 - osf.x0 )
 						/ fleets.compute_outerspace_duration( fs.flight_time , osf.x0 , osf.y0 , osf.x1 , osf.y1 ) )
-				END )::REAL AS cx ,
+				END )::DOUBLE PRECISION AS cx ,
 				( CASE
 					WHEN osf.id IS NULL THEN isf.y
-					ELSE ( osf.y1 - osf.time_left::REAL * ( osf.y1 - osf.y0 )
+					ELSE ( osf.y1 - osf.time_left * ( osf.y1 - osf.y0 )
 						/ fleets.compute_outerspace_duration( fs.flight_time , osf.x0 , osf.y0 , osf.x1 , osf.y1 ) )
-				END )::REAL AS cy ,
+				END )::DOUBLE PRECISION AS cy ,
 				( CASE
 					WHEN osf.id IS NULL THEN isf.planet
 					ELSE NULL
@@ -1487,7 +1488,7 @@ GRANT SELECT ON fleets.ships_view TO :dbuser;
 CREATE VIEW fleets.short_static_fleets
 	AS SELECT sf.empire , sf.location AS location_id ,
 				fl.name AS location_name ,
-				fl.x::REAL AS x , fl.y::REAL AS y ,
+				fl.x::DOUBLE PRECISION AS x , fl.y::DOUBLE PRECISION AS y ,
 				sf.id , sf.name , sf.status , sf.penalty ,
 				fl.attacking , sf.power , sf.flight_time
 			FROM fleets.static_fleets sf
diff --git a/legacyworlds-server-data/db-structure/parts/040-functions/167-planet-list.sql b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/functions/167-planet-list.sql
similarity index 72%
rename from legacyworlds-server-data/db-structure/parts/040-functions/167-planet-list.sql
rename to legacyworlds-server/legacyworlds-server-data/db-structure/parts/functions/167-planet-list.sql
index e9ed6d1..0219833 100644
--- a/legacyworlds-server-data/db-structure/parts/040-functions/167-planet-list.sql
+++ b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/functions/167-planet-list.sql
@@ -3,7 +3,7 @@
 --
 -- Views for empires' planet lists
 --
--- Copyright(C) 2004-2012, DeepClone Development
+-- Copyright(C) 2004-2010, DeepClone Development
 -- --------------------------------------------------------
 
 
@@ -15,7 +15,7 @@ CREATE VIEW emp.planets_list_basic
 	AS SELECT e.name_id AS empire ,
 				p.name_id AS id , n.name ,
 				s.x , s.y , p.orbit ,
-				p.population , ph.current / p.population::REAL AS happiness ,
+				p.population , ph.current / p.population AS happiness ,
 				floor( pm.income )::BIGINT AS income ,
 				floor( pm.upkeep )::BIGINT AS upkeep
 			FROM emp.empires e
@@ -114,58 +114,6 @@ CREATE VIEW emp.planets_list_fleets
 			END );
 
 
-/*
- * Planet list resources information
- * ----------------------------------
- * 
- * This view is used to display the resources-related information in the
- * planet list pages. All rows in the view are ordered using the usual
- * resource ordering view.
- * 
- * FIXME: time-related constants are hardcoded.
- * FIXME: civilian and military investments are set to 0.
- * 
- * Columns:
- *		empire_id		The empire's identifier
- *		planet_id		The planet's identifier
- *		pres_income		The income for this type of resources on a period
- *							of 12h RT / one month GT.
- *		pres_upkeep		The upkeep for this type of resources on a period
- *							of 12h RT / one month GT.
- *		civ_investment	The current amount invested in the civillian build
- *							queue (FIXME: forced to 0)
- *		mil_investment	The current amount invested in the military build
- *							queue (FIXME: forced to 0)
- */
-DROP VIEW IF EXISTS emp.plist_resources_view;
-CREATE VIEW emp.plist_resources_view
-	AS SELECT _emp_planet.empire_id , _emp_planet.planet_id ,
-				_name.translated_string AS resource_name ,
-				FLOOR( _pres.pres_income * 720.0 )::BIGINT AS pres_income ,
-				CEIL( _pres.pres_upkeep * 720.0 )::BIGINT AS pres_upkeep ,
-				0::BIGINT AS civ_investment ,
-				0::BIGINT AS mil_investment
-			FROM emp.planets _emp_planet
-				INNER JOIN verse.planet_resources _pres
-					USING ( planet_id )
-				INNER JOIN naming.empire_names _emp_name
-					ON _emp_name.id = _emp_planet.empire_id
-				INNER JOIN users.credentials _creds
-					ON _creds.address_id = _emp_name.owner_id
-				INNER JOIN defs.translations _name
-					ON _name.string_id = resource_name_id
-						AND _name.lang_id = _creds.language_id
-				INNER JOIN defs.ordered_resources_view _res_def
-					USING ( resource_name_id )
-			WHERE _pres.pres_income > 0
-				OR _pres.pres_upkeep > 0
-			ORDER BY _res_def.resource_ordering;
-
-GRANT SELECT
-	ON emp.plist_resources_view
-	TO :dbuser;
-
-
 --
 -- Actual planet list
 --
diff --git a/legacyworlds-server-data/db-structure/parts/040-functions/170-events.sql b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/functions/170-event-functions.sql
similarity index 95%
rename from legacyworlds-server-data/db-structure/parts/040-functions/170-events.sql
rename to legacyworlds-server/legacyworlds-server-data/db-structure/parts/functions/170-event-functions.sql
index 75fe701..57c4d81 100644
--- a/legacyworlds-server-data/db-structure/parts/040-functions/170-events.sql
+++ b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/functions/170-event-functions.sql
@@ -3,11 +3,10 @@
 --
 -- Functions and views to create and manipulate events
 --
--- Copyright(C) 2004-2012, DeepClone Development
+-- Copyright(C) 2004-2010, DeepClone Development
 -- --------------------------------------------------------
 
 
-
 -- --------------------------------------------------------------------------------------------------------------------------------------------------------------- --
 -- --------------------------------------------------------------------------------------------------------------------------------------------------------------- --
 -- EVENT CREATION FUNCTIONS                                                                                                                                        -- 
@@ -229,6 +228,32 @@ $$ LANGUAGE plpgsql;
 
 
 
+--
+-- Creates an event for a technology's availability
+--
+-- Parameters:
+--	e_id		Empire identifier
+--	t_id		Technology identifier
+--
+
+CREATE OR REPLACE FUNCTION events.tech_ready_event( e_id INT , t_id INT )
+		RETURNS VOID
+		STRICT VOLATILE
+		SECURITY INVOKER
+	AS $$
+DECLARE
+	evt_id		BIGINT;
+BEGIN
+	INSERT INTO events.events ( empire_id , tick , evt_type , evt_subtype , status )
+		VALUES ( e_id , sys.get_tick( ) - 1 , 'EMPIRE' , 0 , 'READY' )
+		RETURNING event_id INTO evt_id;
+	INSERT INTO events.empire_events ( event_id , technology_id )
+		VALUES ( evt_id , t_id  );
+END;
+$$ LANGUAGE plpgsql;
+
+
+
 --
 -- Creates an event for start/end of debt
 --
@@ -831,6 +856,17 @@ CREATE VIEW events.queue_events_view
 GRANT SELECT ON events.queue_events_view TO :dbuser;
 
 
+CREATE VIEW events.empire_events_view
+	AS SELECT e.event_id AS id , e.evt_type , e.evt_subtype , e.tick , e.real_time , s.name AS technology
+			FROM events.events e
+				LEFT OUTER JOIN events.empire_events ed USING (event_id)
+				LEFT OUTER JOIN tech.technologies tl ON tl.name_id = ed.technology_id
+				LEFT OUTER JOIN defs.strings s ON s.id = tl.name_id
+			WHERE e.evt_type = 'EMPIRE';
+
+GRANT SELECT ON events.empire_events_view TO :dbuser;
+
+
 CREATE VIEW events.fleets_events_view
 	AS SELECT e.event_id AS id , e.evt_type , e.evt_subtype , e.tick , e.real_time ,
 				ed.* , s.x , s.y , p.orbit
diff --git a/legacyworlds-server-data/db-structure/parts/040-functions/180-messages.sql b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/functions/180-messages-functions.sql
similarity index 98%
rename from legacyworlds-server-data/db-structure/parts/040-functions/180-messages.sql
rename to legacyworlds-server/legacyworlds-server-data/db-structure/parts/functions/180-messages-functions.sql
index 65010e5..e7319b0 100644
--- a/legacyworlds-server-data/db-structure/parts/040-functions/180-messages.sql
+++ b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/functions/180-messages-functions.sql
@@ -585,13 +585,13 @@ BEGIN
 	-- Send message (or not)
 	IF do_send
 	THEN
-		PERFORM sys.write_sql_log( 'Messages' , 'DEBUG'::log_level , 'Delivering message from empire #' || e_id
+		PERFORM sys.write_log( 'Messages' , 'DEBUG'::log_level , 'Delivering message from empire #' || e_id
 			|| ' using method ' || s_meth || ' with target identifier ' || tg_id || ' (title text null? '
 			|| ( ttl_txt IS NULL ) || ' ; content text null? ' || (cnt_txt IS NULL) || ')' );
 		EXECUTE 'SELECT msgs.deliver_' || s_meth || '( $1 , $2 , $3 , $4 )'
 			USING e_id , tg_id , ttl_txt , cnt_txt;
 	ELSE
-		PERFORM sys.write_sql_log( 'Messages' , 'DEBUG'::log_level , 'Simulated message delivery from empire #' || e_id
+		PERFORM sys.write_log( 'Messages' , 'DEBUG'::log_level , 'Simulated message delivery from empire #' || e_id
 			|| ' using method ' || s_meth || ' with target identifier ' || tg_id || ' (title text null? '
 			|| ( ttl_txt IS NULL ) || ' ; content text null? ' || (cnt_txt IS NULL) || ')' );
 	END IF;
@@ -860,13 +860,13 @@ BEGIN
 	-- Send message (or not)
 	IF do_send
 	THEN
-		PERFORM sys.write_sql_log( 'Messages' , 'DEBUG'::log_level , 'Delivering message from admin #' || a_id
+		PERFORM sys.write_log( 'Messages' , 'DEBUG'::log_level , 'Delivering message from admin #' || a_id
 			|| ' using method ' || s_meth || ' with target identifier ' || tg_id || ' (title text null? '
 			|| ( ttl_txt IS NULL ) || ' ; content text null? ' || (cnt_txt IS NULL) || ')' );
 		EXECUTE 'SELECT msgs.deliver_admin_' || s_meth || '( $1 , $2 , $3 , $4 )'
 			USING a_id , tg_id , ttl_txt , cnt_txt;
 	ELSE
-		PERFORM sys.write_sql_log( 'Messages' , 'DEBUG'::log_level , 'Simulated message delivery from admin #' || a_id
+		PERFORM sys.write_log( 'Messages' , 'DEBUG'::log_level , 'Simulated message delivery from admin #' || a_id
 			|| ' using method ' || s_meth || ' with target identifier ' || tg_id || ' (title text null? '
 			|| ( ttl_txt IS NULL ) || ' ; content text null? ' || (cnt_txt IS NULL) || ')' );
 	END IF;
diff --git a/legacyworlds-server-data/db-structure/parts/040-functions/190-admin.sql b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/functions/190-admin-functions.sql
similarity index 99%
rename from legacyworlds-server-data/db-structure/parts/040-functions/190-admin.sql
rename to legacyworlds-server/legacyworlds-server-data/db-structure/parts/functions/190-admin-functions.sql
index d7221d9..fdf8c79 100644
--- a/legacyworlds-server-data/db-structure/parts/040-functions/190-admin.sql
+++ b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/functions/190-admin-functions.sql
@@ -663,7 +663,7 @@ BEGIN
 		INSERT INTO admin.archived_ban_requests ( request_id , credentials_id )
 			VALUES ( b_id , u_id );
 		DELETE FROM admin.active_ban_requests WHERE request_id = b_id;
-		PERFORM sys.write_sql_log( 'Bans' , 'INFO'::log_level , 'Ban request #' || b_id
+		PERFORM sys.write_log( 'Bans' , 'INFO'::log_level , 'Ban request #' || b_id
 			|| ' (user account #' || u_id || ') expired' );
 	END LOOP;
 END;
@@ -707,7 +707,7 @@ BEGIN
 	-- Delete empire and active account record
 	PERFORM emp.delete_empire( e_id );
 	DELETE FROM users.active_accounts WHERE credentials_id = a_id;
-	PERFORM sys.write_sql_log( 'Bans' , 'INFO'::log_level , 'Deleted empire #' || e_id
+	PERFORM sys.write_log( 'Bans' , 'INFO'::log_level , 'Deleted empire #' || e_id
 		|| ' (user account #' || a_id || ')' );
 
 	RETURN TRUE;
@@ -874,7 +874,7 @@ BEGIN
 					|| 's' ) :: INTERVAL;
 	g_time := ( floor(sys.get_constant('accounts.warnings.grace')) || 's' )::INTERVAL;
 	UPDATE admin.warnings SET last_received = now( ) - g_time , warnings = warnings - 1
-		WHERE now() - last_received >= g_time AND warnings > 0;
+		WHERE now() - last_received >= e_time AND warnings > 0;
 END;
 $$ LANGUAGE plpgsql;
 
@@ -934,4 +934,4 @@ CREATE VIEW admin.users_list
 				LEFT OUTER JOIN admin.warnings w ON w.credentials_id = av.id
 			ORDER BY av.address;
 
-GRANT SELECT ON admin.users_list TO :dbuser;
+GRANT SELECT ON admin.users_list TO :dbuser;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/parts/040-functions/200-bugs.sql b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/functions/200-bugs-functions.sql
similarity index 92%
rename from legacyworlds-server-data/db-structure/parts/040-functions/200-bugs.sql
rename to legacyworlds-server/legacyworlds-server-data/db-structure/parts/functions/200-bugs-functions.sql
index dedf305..184f20b 100644
--- a/legacyworlds-server-data/db-structure/parts/040-functions/200-bugs.sql
+++ b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/functions/200-bugs-functions.sql
@@ -1196,48 +1196,24 @@ GRANT SELECT ON bugs.dump_main_view TO :dbuser;
 
 
 CREATE VIEW bugs.dump_research_view
-	AS SELECT et.empire_id , tst.name AS name , et.emptech_state AS state ,
-				et.emptech_points AS points , et.emptech_priority AS priority
-			FROM emp.technologies et
-				INNER JOIN defs.strings tst ON tst.id = et.technology_name_id;
+	AS SELECT r.empire_id , ns.name , r.accumulated , r.priority
+		FROM emp.research r
+			INNER JOIN defs.strings ns ON ns.id = r.technology_id;
 
 GRANT SELECT ON bugs.dump_research_view TO :dbuser;
 
 
-/*
- * Empire resources view
- * ----------------------
- * 
- * This view contains the details about empires' resources as they are needed
- * by the XML dump generator.
- * 
- * Columns:
- *		empire_id			Identifier of the empire
- *		resource_name		Text-based identifier of the resource type
- *		empres_possessed	Amount of resources possessed by the empire
- *		empres_owed			Amount of resources owed by the empire
- *		mining_priority		Mining priority for this resource, or NULL if it
- *								is not a natural resource
- */
-DROP VIEW IF EXISTS bugs.dump_emp_resources_view CASCADE;
-CREATE VIEW bugs.dump_emp_resources_view
-	AS SELECT empire_id , name AS resource_name ,
-			empres_possessed , empres_owed ,
-			empmset_weight AS mining_priority
-		FROM emp.resources
-			INNER JOIN defs.strings
-				ON id = resource_name_id
-			LEFT OUTER JOIN emp.mining_settings
-				USING ( empire_id , resource_name_id );
+CREATE VIEW bugs.dump_technologies_view
+	AS SELECT et.empire_id , ns.name , et.implemented
+		FROM emp.researched_technologies et
+			INNER JOIN defs.strings ns ON ns.id = et.technology_id;
 
-GRANT SELECT
-	ON bugs.dump_emp_resources_view
-	TO :dbuser;
+GRANT SELECT ON bugs.dump_technologies_view TO :dbuser;
 
 
 CREATE VIEW bugs.dump_planets_view
 	AS SELECT ep.empire_id , ep.planet_id , p.population ,
-				( ph.current / p.population )::REAL AS current_happiness , ph.target AS target_happiness ,
+				ph.current / p.population AS current_happiness , ph.target AS target_happiness ,
 				cq.money AS civ_money , cq.work AS civ_work ,
 				mq.money AS mil_money , mq.work AS mil_work
 			FROM emp.planets ep
@@ -1250,62 +1226,6 @@ CREATE VIEW bugs.dump_planets_view
 GRANT SELECT ON bugs.dump_planets_view TO :dbuser;
 
 
-
-/*
- * Planet resources view for XML dumps
- * ------------------------------------
- * 
- * This view combines both planet resources and resource providers for all
- * empire-owned planets. It is meant to be used in the XML dump generator.
- * 
- * 
- * Columns:
- *		empire_id				The empire's identifier
- *		planet_id				The planet's identifier
- *		resource_name			The string identifying the resource
- *		pres_income				The planet's income for that resource type 
- *		pres_upkeep				The planet's upkeep for that resource type
- *		resprov_quantity_max	The resource provider's capacity, or NULL
- *									if there is no resource provider of that
- *									type on the planet
- *		resprov_quantity		The resource provider's current quantity, or
- *									NULL if there is no resource provider of
- *									that type on the planet
- *		resprov_difficulty		The resource provider's extraction difficulty,
- *									or NULL if there is no resource provider
- *									of that type on the planet
- *		resprov_recovery		The resource provider's recovery rate, or NULL
- *									if there is no resource provider of that
- *									 type on the planet
- *		mining_priority			The planet-specific mining priority for the
- *									current resource type, or NULL if there
- *									are no planet-specific settings or no
- *									provider of this type.
- */
-DROP VIEW IF EXISTS bugs.dump_planet_resources_view CASCADE;
-CREATE VIEW bugs.dump_planet_resources_view
-	AS SELECT empire_id , planet_id ,
-				name AS resource_name ,
-				pres_income , pres_upkeep ,
-				resprov_quantity_max , resprov_quantity ,
-				resprov_difficulty , resprov_recovery ,
-				emppmset_weight AS mining_priority
-			FROM emp.planets
-				INNER JOIN verse.planet_resources
-					USING ( planet_id )
-				INNER JOIN defs.strings
-					ON resource_name_id = id
-				LEFT OUTER JOIN verse.resource_providers
-					USING ( planet_id , resource_name_id )
-				LEFT OUTER JOIN emp.planet_mining_settings
-					USING ( empire_id , planet_id , resource_name_id )
-			ORDER BY name;
-
-GRANT SELECT
-	ON bugs.dump_planet_resources_view
-	TO :dbuser;
-
-
 CREATE VIEW bugs.dump_queues_view
 	AS SELECT ep.empire_id , ep.planet_id , FALSE AS military , q.queue_order ,
 				q.building_id AS item_id , qin.name AS item_name ,
@@ -1360,4 +1280,4 @@ CREATE VIEW bugs.dump_ships_view
 				INNER JOIN defs.strings sn ON sn.id = s.ship_id
 			ORDER BY s.ship_id;
 
-GRANT SELECT ON bugs.dump_ships_view TO :dbuser;
+GRANT SELECT ON bugs.dump_ships_view TO :dbuser;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/parts/040-functions/210-admin-overview.sql b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/functions/210-admin-overview.sql
similarity index 100%
rename from legacyworlds-server-data/db-structure/parts/040-functions/210-admin-overview.sql
rename to legacyworlds-server/legacyworlds-server-data/db-structure/parts/functions/210-admin-overview.sql
diff --git a/legacyworlds-server/legacyworlds-server-data/db-structure/parts/updates/000-updates-ctrl.sql b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/updates/000-updates-ctrl.sql
new file mode 100644
index 0000000..4622684
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/updates/000-updates-ctrl.sql
@@ -0,0 +1,182 @@
+-- LegacyWorlds Beta 6
+-- PostgreSQL database scripts
+--
+-- Game updates - control functions
+--
+-- Copyright(C) 2004-2010, DeepClone Development
+-- --------------------------------------------------------
+
+
+
+--
+-- Start a tick
+--
+
+CREATE OR REPLACE FUNCTION sys.start_tick( OUT tick_id BIGINT )
+		STRICT VOLATILE
+		SECURITY DEFINER
+	AS $$
+DECLARE
+	n_tick	BIGINT;
+	c_tick	BIGINT;
+BEGIN
+	-- Get next / current tick
+	SELECT INTO n_tick , c_tick next_tick , current_tick
+		FROM sys.status
+		WHERE maintenance_start IS NULL
+		FOR UPDATE;
+	IF NOT FOUND OR c_tick IS NOT NULL THEN
+		tick_id := NULL;
+		RETURN;
+	END IF;
+
+	-- Prepare game updates
+	UPDATE sys.updates SET last_tick = n_tick , status = 'FUTURE'
+		WHERE last_tick < n_tick;
+
+	-- Update system status
+	UPDATE sys.status SET current_tick = n_tick , next_tick = n_tick + 1;
+	
+	tick_id := n_tick;
+END;
+$$ LANGUAGE plpgsql;
+
+GRANT EXECUTE ON FUNCTION sys.start_tick( ) TO :dbuser;
+
+
+
+--
+-- Marks a tick as completed
+--
+
+CREATE OR REPLACE FUNCTION sys.end_tick( IN tick_id BIGINT )
+		RETURNS VOID
+		STRICT VOLATILE
+		SECURITY DEFINER
+	AS $$
+BEGIN
+	UPDATE events.events SET status = 'READY'
+		WHERE status = 'TICK' AND tick = tick_id;
+	UPDATE sys.status SET current_tick = NULL;
+	PERFORM msgs.deliver_internal( );
+END;
+$$ LANGUAGE plpgsql;
+
+GRANT EXECUTE ON FUNCTION sys.end_tick( BIGINT ) TO :dbuser;
+
+
+
+--
+-- Check if a tick got "stuck"
+--
+
+CREATE OR REPLACE FUNCTION sys.check_stuck_tick( OUT tick_id BIGINT )
+		STRICT VOLATILE
+		SECURITY DEFINER
+	AS $$
+DECLARE
+	c_tick	BIGINT;
+	u_count	INT;
+BEGIN
+	-- Get next / current tick
+	SELECT INTO c_tick current_tick
+		FROM sys.status
+		WHERE maintenance_start IS NULL
+		FOR UPDATE;
+	IF NOT FOUND OR c_tick IS NULL THEN
+		tick_id := NULL;
+		RETURN;
+	END IF;
+	
+	-- Are there any updates left?
+	SELECT INTO u_count count(*) FROM sys.updates
+		WHERE status = 'FUTURE' AND last_tick = c_tick;
+	IF u_count = 0 THEN
+		PERFORM sys.end_tick( c_tick );
+		tick_id := NULL;
+	ELSE
+		tick_id := c_tick;
+	END IF;
+END;
+$$ LANGUAGE plpgsql;
+
+GRANT EXECUTE ON FUNCTION sys.check_stuck_tick( ) TO :dbuser;
+
+
+
+--
+-- Prepare game updates
+--
+-- Parameters:
+--  u_id		Current update identifier
+--	u_type		Type of game updates to prepare
+--
+-- Returns:
+--	has_more	TRUE if there are more updates, FALSE otherwise
+--
+
+CREATE OR REPLACE FUNCTION sys.prepare_updates( IN u_id BIGINT , IN u_type update_type , OUT has_more BOOLEAN )
+		STRICT VOLATILE
+		SECURITY DEFINER
+	AS $$
+BEGIN
+	UPDATE sys.updates SET status = 'PROCESSING'
+		WHERE id IN (
+			SELECT id FROM sys.updates
+				WHERE gu_type = u_type
+					AND last_tick = u_id
+					AND status = 'FUTURE'
+				ORDER BY id
+				LIMIT sys.get_constant( 'game.batchSize' )::BIGINT
+			);
+
+	has_more := FOUND;
+END;
+$$ LANGUAGE plpgsql;
+
+GRANT EXECUTE ON FUNCTION sys.prepare_updates( BIGINT , update_type ) TO :dbuser;
+
+
+
+--
+-- Execute procedural game updates
+--
+-- Parameters:
+--	c_tick	Current tick identifier
+--	u_type	Type of updates to execute
+--
+
+CREATE OR REPLACE FUNCTION sys.exec_update_proc( IN c_tick BIGINT , IN u_type update_type )
+		RETURNS VOID
+		STRICT VOLATILE
+		SECURITY DEFINER
+	AS $$
+BEGIN
+	EXECUTE 'SELECT sys.process_' || lower( u_type::TEXT ) || '_updates( $1 )'
+			USING c_tick;
+END; 
+$$ LANGUAGE plpgsql;
+
+GRANT EXECUTE ON FUNCTION sys.exec_update_proc( BIGINT , update_type ) TO :dbuser;
+
+
+--
+-- Mark updates as processed
+--
+-- Parameters:
+--	c_tick	Current tick identifier
+--	u_type	Type of updates to execute
+--
+
+CREATE OR REPLACE FUNCTION sys.updates_processed( IN c_tick BIGINT , IN u_type update_type )
+	RETURNS VOID
+	STRICT VOLATILE
+	SECURITY DEFINER
+AS $$
+		UPDATE sys.updates SET status = 'PROCESSED'
+			WHERE status = 'PROCESSING'
+				AND last_tick = $1
+				AND gu_type = $2
+$$ LANGUAGE SQL;
+
+GRANT EXECUTE ON FUNCTION sys.updates_processed( BIGINT , update_type ) TO :dbuser;
diff --git a/legacyworlds-server-data/db-structure/parts/050-updates/010-empire-money.sql b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/updates/010-empire-money.sql
similarity index 69%
rename from legacyworlds-server-data/db-structure/parts/050-updates/010-empire-money.sql
rename to legacyworlds-server/legacyworlds-server-data/db-structure/parts/updates/010-empire-money.sql
index 26e3088..9cd715e 100644
--- a/legacyworlds-server-data/db-structure/parts/050-updates/010-empire-money.sql
+++ b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/updates/010-empire-money.sql
@@ -14,18 +14,17 @@ CREATE OR REPLACE FUNCTION sys.process_empire_money_updates( c_tick BIGINT )
 	AS $$
 DECLARE
 	rec		RECORD;
-	c_cash	REAL;
-	c_debt	REAL;
+	c_cash	DOUBLE PRECISION;
+	c_debt	DOUBLE PRECISION;
 BEGIN
 	-- Lock empires for update
-	PERFORM e.name_id
-		FROM sys.updates su
-			INNER JOIN emp.empires_updates eu 
-				USING ( updtgt_id , updtype_id , update_id )
+	PERFORM e.name_id FROM sys.updates su
+			INNER JOIN emp.updates eu 
+				ON eu.update_id = su.id
 			INNER JOIN emp.empires e
-				USING ( name_id )
-		WHERE su.update_last = c_tick
-			AND su.update_state = 'PROCESSING'
+				ON eu.empire_id = e.name_id
+		WHERE su.last_tick = c_tick AND su.status = 'PROCESSING'
+			AND su.gu_type = 'EMPIRE_MONEY'
 		FOR UPDATE OF e;
 
 	-- Select all money-related data from empires being updated
@@ -33,16 +32,14 @@ BEGIN
 						( pov.planet_income - pov.planet_upkeep ) AS p_money ,
 						fov.fleet_upkeep AS f_money , ( v.status = 'PROCESSED' ) AS on_vacation
 					FROM sys.updates su
-						INNER JOIN emp.empires_updates eu 
-							USING ( updtgt_id , updtype_id , update_id )
-						INNER JOIN emp.empires e
-							USING ( name_id )
+						INNER JOIN emp.updates eu ON eu.update_id = su.id
+						INNER JOIN emp.empires e ON eu.empire_id = e.name_id
 						INNER JOIN emp.fleets_overview fov ON fov.empire = e.name_id
 						INNER JOIN emp.planets_overview pov ON pov.empire = e.name_id
 						INNER JOIN naming.empire_names en ON en.id = e.name_id
 						LEFT OUTER JOIN users.vacations v ON v.account_id = en.owner_id
-					WHERE su.update_last = c_tick
-						AND su.update_state = 'PROCESSING'
+					WHERE su.last_tick = c_tick AND su.status = 'PROCESSING'
+						AND su.gu_type = 'EMPIRE_MONEY'
 	LOOP
 		-- Compute new cash reserve
 		c_cash := 0;
@@ -81,12 +78,4 @@ BEGIN
 			WHERE name_id = rec.id;
 	END LOOP;
 END;
-$$ LANGUAGE plpgsql;
-
-
-SELECT sys.register_update_type( 'Empires' , 'EmpireMoney' ,
-		'Empires'' money is being updated using the previous update''s results. '
-			|| 'This update type should disappear, as everything it does will '
-		 	|| 'be replaced by the resources update.' ,
-		'process_empire_money_updates'
-	);
\ No newline at end of file
+$$ LANGUAGE plpgsql;
\ No newline at end of file
diff --git a/legacyworlds-server/legacyworlds-server-data/db-structure/parts/updates/020-empire-research.sql b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/updates/020-empire-research.sql
new file mode 100644
index 0000000..f17ce33
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/updates/020-empire-research.sql
@@ -0,0 +1,166 @@
+-- LegacyWorlds Beta 6
+-- PostgreSQL database scripts
+--
+-- Game updates - empire research
+--
+-- Copyright(C) 2004-2010, DeepClone Development
+-- --------------------------------------------------------
+
+
+
+--
+-- Prepare the research update
+--
+-- Parameters:
+--	update_id	The current update's identifier
+--
+-- Returns:
+--	a set of tech._research_update_input records
+--
+
+CREATE OR REPLACE FUNCTION emp.prepare_research_update( update_id BIGINT )
+		RETURNS VOID
+		STRICT VOLATILE
+		SECURITY DEFINER
+	AS $$
+BEGIN
+	-- Lock empires for update and planets for share
+	PERFORM e.name_id FROM sys.updates su
+			INNER JOIN emp.updates eu ON eu.update_id = su.id
+			INNER JOIN emp.empires e ON eu.empire_id = e.name_id
+			INNER JOIN emp.planets ep ON ep.empire_id = e.name_id
+			INNER JOIN verse.planets p ON p.name_id = ep.planet_id
+		WHERE su.last_tick = update_id AND su.status = 'PROCESSING'
+			AND su.gu_type = 'EMPIRE_RESEARCH'
+		FOR UPDATE OF e
+		FOR SHARE OF ep , p;
+
+	-- Create temporary table for update output and grant INSERT privilege
+	-- to session user.
+	CREATE TEMPORARY TABLE research_update_output(
+		empire_id		INT ,
+		technology		TEXT ,
+		creation		BOOLEAN ,
+		points			DOUBLE PRECISION ,
+		priority		INT
+	);
+	IF session_user <> current_user THEN
+		EXECUTE 'GRANT INSERT ON research_update_output TO ' || session_user;
+	END IF;
+END;
+$$ LANGUAGE plpgsql;
+
+GRANT EXECUTE ON FUNCTION emp.prepare_research_update( update_id BIGINT ) TO :dbuser;
+
+
+--
+-- Research update input views
+--
+
+CREATE VIEW emp.rui_inprogress_view
+	AS SELECT su.last_tick AS update_id , er.empire_id , ns.name AS technology ,
+			er.accumulated AS points , er.priority AS priority
+		FROM sys.updates su
+			INNER JOIN emp.updates eu ON eu.update_id = su.id
+			INNER JOIN emp.research er ON er.empire_id = eu.empire_id
+			INNER JOIN defs.strings ns ON ns.id = er.technology_id
+		WHERE su.status = 'PROCESSING'
+			AND su.gu_type = 'EMPIRE_RESEARCH';
+
+
+CREATE VIEW emp.rui_researched_view
+	AS SELECT su.last_tick AS update_id , er.empire_id , ns.name AS technology ,
+			er.implemented AS implemented
+		FROM sys.updates su
+			INNER JOIN emp.updates eu ON eu.update_id = su.id
+			INNER JOIN emp.researched_technologies er
+				ON er.empire_id = eu.empire_id
+			INNER JOIN defs.strings ns ON ns.id = er.technology_id
+		WHERE su.status = 'PROCESSING'
+			AND su.gu_type = 'EMPIRE_RESEARCH';
+
+CREATE VIEW emp.research_update_input_view
+	AS SELECT update_id , empire_id , technology ,
+				NULL::BOOLEAN AS implemented , points , priority
+			FROM emp.rui_inprogress_view
+		UNION ALL SELECT update_id , empire_id , technology ,
+				implemented , NULL::DOUBLE PRECISION AS points ,
+				NULL::INT AS priority
+			FROM emp.rui_researched_view;
+
+GRANT SELECT ON emp.research_update_input_view TO :dbuser;
+
+
+--
+-- Research points production view
+--
+
+CREATE VIEW emp.research_points_production
+	AS SELECT su.last_tick AS update_id , e.name_id AS empire_id ,
+			( sum( p.population ) * sys.get_constant( 'game.research.perPopUnit' )
+				/ ( sys.get_constant( 'game.updatesPerDay' ) * ( CASE
+							WHEN v.status = 'PROCESSED' THEN
+								sys.get_constant( 'game.research.perPopUnit' )
+							ELSE
+								1.0
+					END ) ) ) AS points
+		FROM sys.updates su
+			INNER JOIN emp.updates eu ON eu.update_id = su.id
+			INNER JOIN emp.empires e ON eu.empire_id = e.name_id
+			INNER JOIN emp.planets ep ON ep.empire_id = e.name_id
+			INNER JOIN verse.planets p ON p.name_id = ep.planet_id
+			INNER JOIN naming.empire_names en ON en.id = e.name_id
+			LEFT OUTER JOIN users.vacations v ON v.account_id = en.owner_id
+		WHERE su.status = 'PROCESSING' AND su.gu_type = 'EMPIRE_RESEARCH'
+		GROUP BY su.last_tick , e.name_id , v.status;
+
+GRANT SELECT ON emp.research_points_production TO :dbuser;
+
+
+
+--
+-- Submit the contents of the research update table
+--
+
+CREATE OR REPLACE FUNCTION emp.submit_research_update( )
+		RETURNS VOID
+		STRICT VOLATILE
+		SECURITY DEFINER
+	AS $$
+BEGIN
+	-- Delete finished research topics
+	DELETE FROM emp.research er
+		USING research_update_output ruo , defs.strings ns
+		WHERE er.empire_id = ruo.empire_id
+			AND er.technology_id = ns.id AND ns.name = ruo.technology
+			AND ruo.points IS NULL;
+
+	-- Insert researched technologies
+	INSERT INTO emp.researched_technologies ( empire_id , technology_id , implemented )
+		SELECT ruo.empire_id , ns.id , FALSE
+			FROM research_update_output ruo
+				INNER JOIN defs.strings ns ON ns.name = ruo.technology
+			WHERE ruo.points IS NULL;
+
+	-- Insert new research topics
+	INSERT INTO emp.research ( empire_id , technology_id , accumulated , priority )
+		SELECT ruo.empire_id , ns.id , ruo.points , ruo.priority
+			FROM research_update_output ruo
+				INNER JOIN defs.strings ns ON ns.name = ruo.technology
+			WHERE ruo.points IS NOT NULL AND ruo.creation;
+
+	-- Update existing research topics
+	UPDATE emp.research er
+		SET accumulated = ruo.points , priority = ruo.priority
+		FROM research_update_output ruo , defs.strings ns
+		WHERE ruo.points IS NOT NULL AND NOT ruo.creation
+			AND ns.name = ruo.technology
+			AND er.technology_id = ns.id
+			AND er.empire_id = ruo.empire_id;
+
+	-- Drop temporary table
+	DROP TABLE research_update_output;
+END;
+$$ LANGUAGE plpgsql;
+
+GRANT EXECUTE ON FUNCTION emp.submit_research_update( ) TO :dbuser;
diff --git a/legacyworlds-server-data/db-structure/parts/050-updates/025-empire-debt.sql b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/updates/025-empire-debt.sql
similarity index 76%
rename from legacyworlds-server-data/db-structure/parts/050-updates/025-empire-debt.sql
rename to legacyworlds-server/legacyworlds-server-data/db-structure/parts/updates/025-empire-debt.sql
index aa1e849..89a7fae 100644
--- a/legacyworlds-server-data/db-structure/parts/050-updates/025-empire-debt.sql
+++ b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/updates/025-empire-debt.sql
@@ -15,23 +15,21 @@ CREATE OR REPLACE FUNCTION sys.process_empire_debt_updates( c_tick BIGINT )
 		SECURITY INVOKER
 	AS $$
 DECLARE
-	fleet_dr	REAL;
-	bld_dr		REAL;
+	fleet_dr	DOUBLE PRECISION;
+	bld_dr		DOUBLE PRECISION;
 	empire		INT;
-	debt		REAL;
-	upkeep		REAL;
+	debt		DOUBLE PRECISION;
+	upkeep		DOUBLE PRECISION;
 BEGIN
 	fleet_dr := sys.get_constant( 'game.debt.fleet');
 	bld_dr := sys.get_constant( 'game.debt.buildings');
 
 	FOR empire, debt IN SELECT e.name_id AS id , e.debt
-					FROM sys.updates _upd_sys
-						INNER JOIN emp.empires_updates eu
-							USING ( updtgt_id , updtype_id , update_id )
-						INNER JOIN emp.empires e USING ( name_id )
-					WHERE _upd_sys.update_last = c_tick
-						AND _upd_sys.update_state = 'PROCESSING'
-						AND e.debt > 0
+					FROM sys.updates su
+						INNER JOIN emp.updates eu ON eu.update_id = su.id
+						INNER JOIN emp.empires e ON eu.empire_id = e.name_id
+					WHERE su.last_tick = c_tick AND su.status = 'PROCESSING'
+						AND su.gu_type = 'EMPIRE_DEBT' AND e.debt > 0
 					FOR UPDATE
 	LOOP
 		PERFORM sys.write_log( 'EmpireDebt' , 'DEBUG'::log_level , 'Handling debt for empire #'
@@ -61,9 +59,4 @@ BEGIN
 		PERFORM verse.handle_debt( empire , upkeep , debt , bld_dr );
 	END LOOP;
 END;
-$$ LANGUAGE plpgsql;
-
-SELECT sys.register_update_type( 'Empires' , 'EmpireDebt' ,
-		'The effects of empires'' debts are being computed.' ,
-		'process_empire_debt_updates'
-	);
\ No newline at end of file
+$$ LANGUAGE plpgsql;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/parts/050-updates/030-fleet-arrivals.sql b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/updates/030-fleet-arrivals.sql
similarity index 79%
rename from legacyworlds-server-data/db-structure/parts/050-updates/030-fleet-arrivals.sql
rename to legacyworlds-server/legacyworlds-server-data/db-structure/parts/updates/030-fleet-arrivals.sql
index b5a939b..c9dd59e 100644
--- a/legacyworlds-server-data/db-structure/parts/050-updates/030-fleet-arrivals.sql
+++ b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/updates/030-fleet-arrivals.sql
@@ -7,7 +7,7 @@
 -- --------------------------------------------------------
 
 
-CREATE OR REPLACE FUNCTION sys.process_fleet_arrivals_updates( c_tick BIGINT )
+CREATE OR REPLACE FUNCTION sys.process_planet_fleet_arrivals_updates( c_tick BIGINT )
 		RETURNS VOID
 		STRICT VOLATILE
 		SECURITY INVOKER
@@ -18,16 +18,14 @@ DECLARE
 	f_ids	BIGINT[];
 BEGIN
 	-- Lock all records
-	PERFORM 1
-		FROM sys.updates su
-			INNER JOIN verse.planets_updates vu
-				USING ( update_id , updtype_id , updtgt_id )
-			INNER JOIN verse.planets p
-				USING ( name_id )
+	PERFORM f.id FROM sys.updates su
+			INNER JOIN verse.updates vu ON vu.update_id = su.id
+			INNER JOIN verse.planets p ON p.name_id = vu.planet_id
 			INNER JOIN fleets.fleets f ON f.location_id = p.name_id
 			INNER JOIN fleets.movements fm ON fm.fleet_id = f.id
 			INNER JOIN emp.empires e ON e.name_id = f.owner_id
-		WHERE su.update_last = c_tick AND su.update_state = 'PROCESSING'
+		WHERE su.last_tick = c_tick AND su.status = 'PROCESSING'
+					AND su.gu_type = 'PLANET_FLEET_ARRIVALS'
 					AND f.status = 'AVAILABLE' AND fm.time_left = 1
 		FOR UPDATE;
 
@@ -36,10 +34,8 @@ BEGIN
 					f.owner_id AS fleet_owner , ( v.status = 'PROCESSED' AND b.id IS NULL ) AS on_vacation ,
 					bool_or( f.attacking ) AS attacking
 				FROM sys.updates su
-					INNER JOIN verse.planets_updates vu
-						USING ( update_id , updtype_id , updtgt_id )
-					INNER JOIN verse.planets p
-						USING ( name_id )
+					INNER JOIN verse.updates vu ON vu.update_id = su.id
+					INNER JOIN verse.planets p ON p.name_id = vu.planet_id
 					INNER JOIN fleets.fleets f ON f.location_id = p.name_id
 					INNER JOIN fleets.movements fm ON fm.fleet_id = f.id
 					LEFT OUTER JOIN emp.planets ep ON ep.planet_id = p.name_id
@@ -47,8 +43,9 @@ BEGIN
 					LEFT OUTER JOIN users.vacations v ON v.account_id = en.owner_id
 					LEFT OUTER JOIN battles.battles b
 						ON b.location_id = p.name_id AND b.last_tick IS NULL
-				WHERE su.update_last = c_tick AND su.update_state = 'PROCESSING'
-						AND f.status = 'AVAILABLE' AND fm.time_left = 1
+				WHERE su.last_tick = c_tick AND su.status = 'PROCESSING'
+							AND su.gu_type = 'PLANET_FLEET_ARRIVALS'
+							AND f.status = 'AVAILABLE' AND fm.time_left = 1
 				GROUP BY p.name_id , ep.empire_id , f.owner_id , v.status , b.id
 	LOOP
 		-- Fleets owned by the planet's owner are never attacking, same for fleets arriving on
@@ -106,17 +103,16 @@ BEGIN
 		SELECT f.location_id , ln.name , f.owner_id , fon.name ,
 				f.name , fs.power , f.attacking , fm.source_id , sn.name
 			FROM sys.updates su
-					INNER JOIN verse.planets_updates vu
-						USING ( update_id , updtype_id , updtgt_id )
-					INNER JOIN verse.planets p
-						USING ( name_id )
+				INNER JOIN verse.updates vu ON vu.update_id = su.id
+				INNER JOIN verse.planets p ON p.name_id = vu.planet_id
 				INNER JOIN fleets.fleets f ON f.location_id = p.name_id
 				INNER JOIN fleets.movements fm ON fm.fleet_id = f.id
 				INNER JOIN fleets.stats_view fs ON fs.id = f.id
 				INNER JOIN naming.empire_names fon ON fon.id = f.owner_id
 				INNER JOIN naming.map_names ln ON ln.id = f.location_id
 				INNER JOIN naming.map_names sn ON sn.id = fm.source_id
-			WHERE su.update_last = c_tick AND su.update_state = 'PROCESSING'
+			WHERE su.last_tick = c_tick AND su.status = 'PROCESSING'
+						AND su.gu_type = 'PLANET_FLEET_ARRIVALS'
 						AND f.status = 'AVAILABLE' AND fm.time_left = 1;
 
 	-- Delete movement records, set redeployment penalties, update battles
@@ -124,16 +120,15 @@ BEGIN
 					f.attacking AS attacking , b.id AS battle ,
 					f.location_id AS location
 				FROM sys.updates su
-					INNER JOIN verse.planets_updates vu
-						USING ( update_id , updtype_id , updtgt_id )
-					INNER JOIN verse.planets p
-						USING ( name_id )
+					INNER JOIN verse.updates vu ON vu.update_id = su.id
+					INNER JOIN verse.planets p ON p.name_id = vu.planet_id
 					INNER JOIN fleets.fleets f ON f.location_id = p.name_id
 					INNER JOIN fleets.movements fm ON fm.fleet_id = f.id
 					INNER JOIN fleets.stats_view fs ON fs.id = f.id
 					LEFT OUTER JOIN battles.battles b
 						ON b.location_id = p.name_id AND b.last_tick IS NULL 
-				WHERE su.update_last = c_tick AND su.update_state = 'PROCESSING'
+				WHERE su.last_tick = c_tick AND su.status = 'PROCESSING'
+							AND su.gu_type = 'PLANET_FLEET_ARRIVALS'
 							AND f.status = 'AVAILABLE' AND fm.time_left = 1
 	LOOP
 		DELETE FROM fleets.movements
@@ -150,10 +145,4 @@ BEGIN
 	-- Send fleet arrival events
 	PERFORM events.commit_fleet_arrivals( c_tick );
 END;
-$$ LANGUAGE plpgsql;
-
-
-SELECT sys.register_update_type( 'Planets' , 'FleetArrivals' ,
-		'Fleets which were one update away are arriving at their destinations.' ,
-		'process_fleet_arrivals_updates'
-	);
\ No newline at end of file
+$$ LANGUAGE plpgsql;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/parts/050-updates/040-fleet-movements.sql b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/updates/040-fleet-movements.sql
similarity index 81%
rename from legacyworlds-server-data/db-structure/parts/050-updates/040-fleet-movements.sql
rename to legacyworlds-server/legacyworlds-server-data/db-structure/parts/updates/040-fleet-movements.sql
index 2151325..184aa0a 100644
--- a/legacyworlds-server-data/db-structure/parts/050-updates/040-fleet-movements.sql
+++ b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/updates/040-fleet-movements.sql
@@ -7,7 +7,7 @@
 -- --------------------------------------------------------
 
 
-CREATE OR REPLACE FUNCTION sys.process_fleet_movements_updates( c_tick BIGINT )
+CREATE OR REPLACE FUNCTION sys.process_planet_fleet_movements_updates( c_tick BIGINT )
 		RETURNS VOID
 		STRICT VOLATILE
 		SECURITY INVOKER
@@ -18,14 +18,13 @@ DECLARE
 BEGIN
 	-- Lock all records
 	PERFORM f.id FROM sys.updates su
-			INNER JOIN verse.planets_updates vu
-				USING ( update_id , updtype_id , updtgt_id )
-			INNER JOIN verse.planets p
-				USING ( name_id )
+			INNER JOIN verse.updates vu ON vu.update_id = su.id
+			INNER JOIN verse.planets p ON p.name_id = vu.planet_id
 			INNER JOIN fleets.fleets f ON f.location_id = p.name_id
 			INNER JOIN fleets.movements fm ON fm.fleet_id = f.id
 			INNER JOIN emp.empires e ON e.name_id = f.owner_id
-		WHERE su.update_last = c_tick AND su.update_state = 'PROCESSING'
+		WHERE su.last_tick = c_tick AND su.status = 'PROCESSING'
+			AND su.gu_type = 'PLANET_FLEET_MOVEMENTS'
 			AND f.status = 'AVAILABLE'
 		FOR UPDATE;
 
@@ -37,10 +36,8 @@ BEGIN
 					rp.system_id AS is_ref_point_system , rp.orbit AS is_ref_point_orbit ,
 					rps.x AS is_ref_point_x , rps.y AS is_ref_point_y
 				FROM sys.updates su
-					INNER JOIN verse.planets_updates vu
-						USING ( update_id , updtype_id , updtgt_id )
-					INNER JOIN verse.planets p
-						USING ( name_id )
+					INNER JOIN verse.updates vu ON vu.update_id = su.id
+					INNER JOIN verse.planets p ON p.name_id = vu.planet_id
 					INNER JOIN verse.systems s ON s.id = p.system_id
 					INNER JOIN fleets.fleets f ON f.location_id = p.name_id
 					INNER JOIN fleets.ships fs ON fs.fleet_id = f.id
@@ -49,7 +46,8 @@ BEGIN
 					LEFT OUTER JOIN fleets.ms_system isms ON isms.movement_id = f.id
 					LEFT OUTER JOIN verse.planets rp ON isms.ref_point_id = rp.name_id
 					LEFT OUTER JOIN verse.systems rps ON rps.id = rp.system_id
-				WHERE su.update_last = c_tick AND su.update_state = 'PROCESSING'
+				WHERE su.last_tick = c_tick AND su.status = 'PROCESSING'
+					AND su.gu_type = 'PLANET_FLEET_MOVEMENTS'
 					AND f.status = 'AVAILABLE' AND m.state_time_left = 1
 				GROUP BY f.id , s.x , s.y , s.id , isms.ref_point_id , isms.outwards ,
 					isms.past_ref_point , rp.system_id , rp.orbit , rps.x , rps.y
@@ -100,19 +98,13 @@ BEGIN
 			time_left = time_left - 1
 		WHERE fleet_id IN (
 			SELECT f.id FROM sys.updates su
-					INNER JOIN verse.planets_updates vu
-						USING ( update_id , updtype_id , updtgt_id )
-					INNER JOIN verse.planets p
-						USING ( name_id )
+					INNER JOIN verse.updates vu ON vu.update_id = su.id
+					INNER JOIN verse.planets p ON p.name_id = vu.planet_id
 					INNER JOIN fleets.fleets f ON f.location_id = p.name_id
 					INNER JOIN fleets.movements fm ON fm.fleet_id = f.id
 					INNER JOIN emp.empires e ON e.name_id = f.owner_id
-				WHERE su.update_last = c_tick AND su.update_state = 'PROCESSING'
+				WHERE su.last_tick = c_tick AND su.status = 'PROCESSING'
+					AND su.gu_type = 'PLANET_FLEET_MOVEMENTS'
 					AND f.status = 'AVAILABLE' );
 END;
-$$ LANGUAGE plpgsql;
-
-SELECT sys.register_update_type( 'Planets' , 'FleetMovements' ,
-		'Fleets are moving.' ,
-		'process_fleet_movements_updates'
-	);
\ No newline at end of file
+$$ LANGUAGE plpgsql;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/parts/050-updates/050-fleet-status.sql b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/updates/050-fleet-status.sql
similarity index 61%
rename from legacyworlds-server-data/db-structure/parts/050-updates/050-fleet-status.sql
rename to legacyworlds-server/legacyworlds-server-data/db-structure/parts/updates/050-fleet-status.sql
index c7b1fca..7249954 100644
--- a/legacyworlds-server-data/db-structure/parts/050-updates/050-fleet-status.sql
+++ b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/updates/050-fleet-status.sql
@@ -7,7 +7,7 @@
 -- --------------------------------------------------------
 
 
-CREATE OR REPLACE FUNCTION sys.process_fleet_status_updates( c_tick BIGINT )
+CREATE OR REPLACE FUNCTION sys.process_planet_fleet_status_updates( c_tick BIGINT )
 		RETURNS VOID
 		STRICT VOLATILE
 		SECURITY INVOKER
@@ -18,27 +18,26 @@ DECLARE
 BEGIN
 	-- Lock all records
 	PERFORM f.id FROM sys.updates su
-			INNER JOIN verse.planets_updates vu
-				USING ( update_id , updtype_id , updtgt_id )
-			INNER JOIN verse.planets p
-				USING ( name_id )
+			INNER JOIN verse.updates vu ON vu.update_id = su.id
+			INNER JOIN verse.planets p ON p.name_id = vu.planet_id
 			INNER JOIN fleets.fleets f ON f.location_id = p.name_id
 			INNER JOIN emp.empires e ON e.name_id = f.owner_id
-		WHERE su.update_last = c_tick AND su.update_state = 'PROCESSING'
+		WHERE su.last_tick = c_tick AND su.status = 'PROCESSING'
+					AND su.gu_type = 'PLANET_FLEET_STATUS'
 		FOR UPDATE;
 
 	-- Fleet deployments
 	FOR rec IN SELECT f.id AS fleet , f.owner_id AS owner , f.location_id AS location ,
 						b.id AS battle
 					FROM sys.updates su
-						INNER JOIN verse.planets_updates vu
-							USING ( update_id , updtype_id , updtgt_id )
-						INNER JOIN fleets.fleets f ON f.location_id = vu.name_id
+						INNER JOIN verse.updates vu ON vu.update_id = su.id
+						INNER JOIN fleets.fleets f ON f.location_id = vu.planet_id
 							AND f.status = 'DEPLOYING' AND f.penalty = 1
 						INNER JOIN emp.empires e ON e.name_id = f.owner_id
 						LEFT OUTER JOIN battles.battles b
 							ON b.location_id = f.location_id AND b.last_tick IS NULL 
-					WHERE su.update_last = c_tick AND su.update_state = 'PROCESSING'
+					WHERE su.last_tick = c_tick AND su.status = 'PROCESSING'
+						AND su.gu_type = 'PLANET_FLEET_STATUS'
 	LOOP
 		-- Add fleet to battle (will be ignored if battle is NULL)
 		PERFORM battles.add_fleet( rec.battle , rec.fleet , TRUE , c_tick );
@@ -63,21 +62,16 @@ BEGIN
 
 	-- Fleets that must become available
 	UPDATE fleets.fleets f SET status = 'AVAILABLE' , penalty = 0
-		FROM sys.updates su , verse.planets_updates vu
-		WHERE vu.update_id = su.update_id AND f.location_id = vu.name_id
-			AND f.penalty = 1
-			AND su.update_state = 'PROCESSING' AND su.update_last = c_tick;
+		FROM sys.updates su , verse.updates vu
+		WHERE vu.update_id = su.id AND f.location_id = vu.planet_id
+			AND f.penalty = 1 AND su.status = 'PROCESSING'
+			AND su.gu_type = 'PLANET_FLEET_STATUS' AND su.last_tick = c_tick;
 
 	-- Fleets that still have a penalty
 	UPDATE fleets.fleets f SET penalty = penalty - 1
-		FROM sys.updates su , verse.planets_updates vu
-		WHERE vu.update_id = su.update_id AND f.location_id = vu.name_id
-			AND f.penalty > 1
-			AND su.update_state = 'PROCESSING' AND su.update_last = c_tick;
+		FROM sys.updates su , verse.updates vu
+		WHERE vu.update_id = su.id AND f.location_id = vu.planet_id
+			AND f.penalty > 1 AND su.status = 'PROCESSING'
+			AND su.gu_type = 'PLANET_FLEET_STATUS' AND su.last_tick = c_tick;
 END;
-$$ LANGUAGE plpgsql;
-
-SELECT sys.register_update_type( 'Planets' , 'FleetStatus' ,
-		'Fleet states (e.g. "deploying", "unavailable", etc...) are being  updated.' ,
-		'process_fleet_status_updates'
-	);
\ No newline at end of file
+$$ LANGUAGE plpgsql;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/parts/050-updates/060-planet-battle.sql b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/updates/060-planet-battle.sql
similarity index 77%
rename from legacyworlds-server-data/db-structure/parts/050-updates/060-planet-battle.sql
rename to legacyworlds-server/legacyworlds-server-data/db-structure/parts/updates/060-planet-battle.sql
index 2cfb2e9..c2c8338 100644
--- a/legacyworlds-server-data/db-structure/parts/050-updates/060-planet-battle.sql
+++ b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/updates/060-planet-battle.sql
@@ -7,7 +7,7 @@
 -- --------------------------------------------------------
 
 
-CREATE OR REPLACE FUNCTION sys.process_battle_start_updates( c_tick BIGINT )
+CREATE OR REPLACE FUNCTION sys.process_planet_battle_start_updates( c_tick BIGINT )
 		RETURNS VOID
 		STRICT VOLATILE
 		SECURITY INVOKER
@@ -17,14 +17,12 @@ DECLARE
 BEGIN
 	FOR p_id IN SELECT p.name_id
 				FROM sys.updates su
-					INNER JOIN verse.planets_updates vu
-						USING ( update_id , updtype_id , updtgt_id )
-					INNER JOIN verse.planets p
-						USING ( name_id )
+					INNER JOIN verse.updates vu ON vu.update_id = su.id
+					INNER JOIN verse.planets p ON vu.planet_id = p.name_id
 					LEFT OUTER JOIN battles.battles b
 						ON b.location_id = p.name_id AND b.last_tick IS NULL
-				WHERE su.update_last = c_tick AND su.update_state = 'PROCESSING'
-					AND b.location_id IS NULL
+				WHERE su.last_tick = c_tick AND su.status = 'PROCESSING'
+					AND su.gu_type = 'PLANET_BATTLE_START' AND b.location_id IS NULL
 				FOR UPDATE OF p
 	LOOP
 		IF battles.check_start( p_id ) THEN
@@ -34,30 +32,27 @@ BEGIN
 END;
 $$ LANGUAGE plpgsql;
 
-SELECT sys.register_update_type( 'Planets' , 'BattleStart' ,
-		'Battles are being started.' ,
-		'process_battle_start_updates'
-	);
 
 
-CREATE OR REPLACE FUNCTION sys.process_battle_main_updates( c_tick BIGINT )
+
+CREATE OR REPLACE FUNCTION sys.process_planet_battle_main_updates( c_tick BIGINT )
 		RETURNS VOID
 		STRICT VOLATILE
 		SECURITY INVOKER
 	AS $$
 DECLARE
 	ttfi		INT;
-	initi		REAL;
-	dbonus		REAL;
-	dmg			REAL;
-	rdmg		REAL;
+	initi		DOUBLE PRECISION;
+	dbonus		DOUBLE PRECISION;
+	dmg			DOUBLE PRECISION;
+	rdmg		DOUBLE PRECISION;
 	rec			RECORD;
 	a_power		BIGINT;
 	d_power		BIGINT;
 	p_power		BIGINT;
-	bmod		REAL;
-	a_dmg		REAL;
-	d_dmg		REAL;
+	bmod		DOUBLE PRECISION;
+	a_dmg		DOUBLE PRECISION;
+	d_dmg		DOUBLE PRECISION;
 BEGIN
 	ttfi := floor( sys.get_constant( 'game.battle.timeToFullIntensity' ) )::INT;
 	initi := sys.get_constant( 'game.battle.initialIntensity' );
@@ -66,16 +61,15 @@ BEGIN
 	rdmg := sys.get_constant( 'game.battle.randomDamage' );
 
 	FOR rec IN SELECT b.id AS battle , b.first_tick AS first_tick ,
-					b.location_id AS location , ( ph.current / p.population )::REAL AS happiness
+					b.location_id AS location , ph.current / p.population AS happiness
 				FROM sys.updates su
-					INNER JOIN verse.planets_updates vu
-						USING ( update_id , updtype_id , updtgt_id )
-					INNER JOIN verse.planets p
-						USING ( name_id )
+					INNER JOIN verse.updates vu ON vu.update_id = su.id
+					INNER JOIN verse.planets p ON vu.planet_id = p.name_id
 					INNER JOIN verse.planet_happiness ph ON ph.planet_id = p.name_id
 					INNER JOIN battles.battles b
 						ON b.location_id = p.name_id AND b.last_tick IS NULL
-				WHERE su.update_last = c_tick AND su.update_state = 'PROCESSING'
+				WHERE su.last_tick = c_tick AND su.status = 'PROCESSING'
+					AND su.gu_type = 'PLANET_BATTLE_MAIN'
 				FOR UPDATE OF p , b
 	LOOP
 		PERFORM sys.write_log( 'BattleUpdate' , 'DEBUG'::log_level , 'Handling battle #' || rec.battle
@@ -121,14 +115,10 @@ BEGIN
 END;
 $$ LANGUAGE plpgsql;
 
-SELECT sys.register_update_type( 'Planets' , 'BattleCompute' ,
-		'In-progress battles are being updated.' ,
-		'process_battle_main_updates'
-	);
 
 
 
-CREATE OR REPLACE FUNCTION sys.process_battle_end_updates( c_tick BIGINT )
+CREATE OR REPLACE FUNCTION sys.process_planet_battle_end_updates( c_tick BIGINT )
 		RETURNS VOID
 		STRICT VOLATILE
 		SECURITY INVOKER
@@ -139,13 +129,12 @@ DECLARE
 BEGIN
 	FOR rec IN SELECT b.id AS battle , b.location_id AS location
 				FROM sys.updates su
-					INNER JOIN verse.planets_updates vu
-						USING ( update_id , updtype_id , updtgt_id )
-					INNER JOIN verse.planets p
-						USING ( name_id )
+					INNER JOIN verse.updates vu ON vu.update_id = su.id
+					INNER JOIN verse.planets p ON vu.planet_id = p.name_id
 					INNER JOIN battles.battles b
 						ON b.location_id = p.name_id AND b.last_tick IS NULL
-				WHERE su.update_last = c_tick AND su.update_state = 'PROCESSING'
+				WHERE su.last_tick = c_tick AND su.status = 'PROCESSING'
+					AND su.gu_type = 'PLANET_BATTLE_END'
 				FOR UPDATE OF p , b
 	LOOP
 		IF battles.get_fleets_power( rec.battle , c_tick , TRUE ) = 0 THEN
@@ -190,7 +179,3 @@ BEGIN
 END;
 $$ LANGUAGE plpgsql;
 
-SELECT sys.register_update_type( 'Planets' , 'BattleEnd' ,
-		'Finished battles are being ended.' ,
-		'process_battle_end_updates'
-	);
\ No newline at end of file
diff --git a/legacyworlds-server/legacyworlds-server-data/db-structure/parts/updates/070-planet-abandon.sql b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/updates/070-planet-abandon.sql
new file mode 100644
index 0000000..85128b7
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/updates/070-planet-abandon.sql
@@ -0,0 +1,48 @@
+-- LegacyWorlds Beta 6
+-- PostgreSQL database scripts
+--
+-- Game updates - abandon
+--
+-- Copyright(C) 2004-2010, DeepClone Development
+-- --------------------------------------------------------
+
+
+CREATE OR REPLACE FUNCTION sys.process_planet_abandon_updates( c_tick BIGINT )
+		RETURNS VOID
+		STRICT VOLATILE
+		SECURITY INVOKER
+	AS $$
+DECLARE
+	p_id	INT;
+BEGIN
+	-- Lock all records
+	PERFORM p.name_id FROM sys.updates su
+			INNER JOIN verse.updates vu ON vu.update_id = su.id
+			INNER JOIN verse.planets p ON p.name_id = vu.planet_id
+			INNER JOIN emp.planets ep ON p.name_id = vu.planet_id
+			INNER JOIN emp.empires e ON e.name_id = ep.empire_id
+			INNER JOIN emp.abandon a ON a.planet_id = p.name_id
+		WHERE su.last_tick = c_tick AND su.status = 'PROCESSING'
+			AND su.gu_type = 'PLANET_ABANDON'
+		FOR UPDATE;
+
+	-- Handle planets where time has run out
+	FOR p_id IN SELECT p.name_id
+					FROM sys.updates su
+						INNER JOIN verse.updates vu ON vu.update_id = su.id
+						INNER JOIN verse.planets p ON p.name_id = vu.planet_id
+						INNER JOIN emp.abandon a ON a.planet_id = p.name_id
+					WHERE su.last_tick = c_tick AND su.status = 'PROCESSING'
+							AND su.gu_type = 'PLANET_ABANDON' AND a.time_left = 1
+	LOOP
+		PERFORM emp.leave_planet( p_id );
+	END LOOP;
+	
+	-- Update all abandon records
+	UPDATE emp.abandon a SET time_left = a.time_left - 1
+		FROM sys.updates su
+			INNER JOIN verse.updates vu ON vu.update_id = su.id
+		WHERE su.last_tick = c_tick AND su.status = 'PROCESSING'
+			AND su.gu_type = 'PLANET_ABANDON' AND a.planet_id = vu.planet_id;
+END;
+$$ LANGUAGE plpgsql;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/parts/050-updates/080-planet-construction.sql b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/updates/080-planet-construction.sql
similarity index 89%
rename from legacyworlds-server-data/db-structure/parts/050-updates/080-planet-construction.sql
rename to legacyworlds-server/legacyworlds-server-data/db-structure/parts/updates/080-planet-construction.sql
index e9281bb..d2c7341 100644
--- a/legacyworlds-server-data/db-structure/parts/050-updates/080-planet-construction.sql
+++ b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/updates/080-planet-construction.sql
@@ -14,20 +14,20 @@ CREATE OR REPLACE FUNCTION sys.process_planet_construction_updates( c_tick BIGIN
 	AS $$
 DECLARE
 	rec			RECORD;
-	wu_per_pop	REAL;
-	dest_work	REAL;
-	dest_rec	REAL;
+	wu_per_pop	DOUBLE PRECISION;
+	dest_work	DOUBLE PRECISION;
+	dest_rec	DOUBLE PRECISION;
 	cur_empire	INT;
-	cur_cash	REAL;
+	cur_cash	DOUBLE PRECISION;
 	cur_planet	INT;
 	p_finished	BOOLEAN;
-	cur_wus		REAL;
-	cur_acc_c	REAL;
+	cur_wus		DOUBLE PRECISION;
+	cur_acc_c	DOUBLE PRECISION;
 	n_found		INT;
 	n_removed	INT;
-	i_work		REAL;
-	i_cost		REAL;
-	can_do		REAL;
+	i_work		DOUBLE PRECISION;
+	i_cost		DOUBLE PRECISION;
+	can_do		DOUBLE PRECISION;
 	must_do		INT;
 BEGIN
 	-- Get constants
@@ -39,17 +39,15 @@ BEGIN
 	cur_empire := NULL;
 	cur_planet := NULL;
 	FOR rec IN SELECT p.name_id AS id , p.population AS pop ,
-					( ph.current / p.population )::REAL AS happiness ,
+					ph.current / p.population AS happiness ,
 					e.name_id AS owner , e.cash AS cash ,
 					q.money AS acc_cash , q.work AS acc_work ,
 					qi.queue_order AS qorder , qi.amount AS amount ,
 					qi.destroy AS destroy , qi.building_id AS building ,
 					b.work AS req_work , b.cost AS req_cost
 				FROM sys.updates su
-					INNER JOIN verse.planets_updates vu
-						USING ( update_id , updtype_id , updtgt_id )
-					INNER JOIN verse.planets p
-						USING ( name_id )
+					INNER JOIN verse.updates vu ON vu.update_id = su.id
+					INNER JOIN verse.planets p ON vu.planet_id = p.name_id
 					INNER JOIN emp.planets ep ON ep.planet_id = p.name_id
 					INNER JOIN emp.empires e ON e.name_id = ep.empire_id
 					INNER JOIN verse.planet_happiness ph ON ph.planet_id = p.name_id
@@ -58,7 +56,8 @@ BEGIN
 					INNER JOIN tech.buildables b ON b.name_id = qi.building_id
 					INNER JOIN naming.empire_names en ON en.id = e.name_id
 					LEFT OUTER JOIN users.vacations v ON v.account_id = en.owner_id
-				WHERE su.update_last = c_tick AND su.update_state = 'PROCESSING'
+				WHERE su.last_tick = c_tick AND su.status = 'PROCESSING'
+					AND su.gu_type = 'PLANET_CONSTRUCTION'
 					AND ( v.account_id IS NULL OR v.status <> 'PROCESSED' )
 				ORDER BY e.name_id , p.name_id , qi.queue_order
 				FOR UPDATE OF p , e , q , qi
@@ -101,10 +100,7 @@ BEGIN
 		IF cur_planet IS NULL THEN
 			cur_planet := rec.id;
 			cur_cash := cur_cash + rec.acc_cash;
-			cur_wus := rec.acc_work + verse.adjust_production(
-				( rec.pop * wu_per_pop )::REAL ,
-				rec.happiness
-			);
+			cur_wus := rec.acc_work + verse.adjust_production( rec.pop * wu_per_pop , rec.happiness );
 			n_found := 1;
 			n_removed := 0;
 			cur_acc_c := 0;
@@ -216,8 +212,3 @@ BEGIN
 	END IF;
 END;
 $$ LANGUAGE plpgsql;
-
-SELECT sys.register_update_type( 'Planets' , 'CivilianConstruction' ,
-		'Civilian build queues are being processed.' ,
-		'process_planet_construction_updates'
-	);
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/parts/050-updates/090-planet-military.sql b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/updates/090-planet-military.sql
similarity index 92%
rename from legacyworlds-server-data/db-structure/parts/050-updates/090-planet-military.sql
rename to legacyworlds-server/legacyworlds-server-data/db-structure/parts/updates/090-planet-military.sql
index 1645fac..b1bc4eb 100644
--- a/legacyworlds-server-data/db-structure/parts/050-updates/090-planet-military.sql
+++ b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/updates/090-planet-military.sql
@@ -15,14 +15,14 @@ CREATE OR REPLACE FUNCTION sys.process_planet_military_updates( c_tick BIGINT )
 DECLARE
 	rec			RECORD;
 	cur_empire	INT;
-	cur_cash	REAL;
+	cur_cash	DOUBLE PRECISION;
 	cur_planet	INT;
 	p_finished	BOOLEAN;
-	cur_wus		REAL;
-	cur_acc_c	REAL;
+	cur_wus		DOUBLE PRECISION;
+	cur_acc_c	DOUBLE PRECISION;
 	n_found		INT;
 	n_removed	INT;
-	can_do		REAL;
+	can_do		DOUBLE PRECISION;
 	must_do		INT;
 	fl_id		BIGINT;
 BEGIN
@@ -38,16 +38,14 @@ BEGIN
 	cur_empire := NULL;
 	cur_planet := NULL;
 	FOR rec IN SELECT p.name_id AS id ,
-					( ph.current / p.population )::REAL AS happiness ,
+					ph.current / p.population AS happiness ,
 					e.name_id AS owner , e.cash AS cash ,
 					q.money AS acc_cash , q.work AS acc_work ,
 					qi.queue_order AS qorder , qi.amount AS amount ,
 					qi.ship_id AS ship , s.work AS req_work , s.cost AS req_cost
 				FROM sys.updates su
-					INNER JOIN verse.planets_updates vu
-						USING ( update_id , updtype_id , updtgt_id )
-					INNER JOIN verse.planets p
-						USING ( name_id )
+					INNER JOIN verse.updates vu ON vu.update_id = su.id
+					INNER JOIN verse.planets p ON vu.planet_id = p.name_id
 					INNER JOIN emp.planets ep ON ep.planet_id = p.name_id
 					INNER JOIN emp.empires e ON e.name_id = ep.empire_id
 					INNER JOIN verse.planet_happiness ph ON ph.planet_id = p.name_id
@@ -56,7 +54,8 @@ BEGIN
 					INNER JOIN tech.buildables s ON s.name_id = qi.ship_id
 					INNER JOIN naming.empire_names en ON en.id = e.name_id
 					LEFT OUTER JOIN users.vacations v ON v.account_id = en.owner_id
-				WHERE su.update_last = c_tick AND su.update_state = 'PROCESSING'
+				WHERE su.last_tick = c_tick AND su.status = 'PROCESSING'
+					AND su.gu_type = 'PLANET_MILITARY'
 					AND ( v.account_id IS NULL OR v.status <> 'PROCESSED' )
 				ORDER BY e.name_id , p.name_id , qi.queue_order
 				FOR UPDATE OF p , e , q , qi
@@ -226,8 +225,3 @@ BEGIN
 	DROP TABLE blt_ships;
 END;
 $$ LANGUAGE plpgsql;
-
-SELECT sys.register_update_type( 'Planets' , 'MilitaryConstruction' ,
-		'Military build queues are being processed.' ,
-		'process_planet_military_updates'
-	);
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/parts/050-updates/100-planet-population.sql b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/updates/100-planet-population.sql
similarity index 81%
rename from legacyworlds-server-data/db-structure/parts/050-updates/100-planet-population.sql
rename to legacyworlds-server/legacyworlds-server-data/db-structure/parts/updates/100-planet-population.sql
index 16a3d77..52d2d91 100644
--- a/legacyworlds-server-data/db-structure/parts/050-updates/100-planet-population.sql
+++ b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/updates/100-planet-population.sql
@@ -14,16 +14,16 @@ CREATE OR REPLACE FUNCTION sys.process_planet_population_updates( c_tick BIGINT
 	AS $$
 DECLARE
 	rec		RECORD;
-	rel_ch	REAL;
-	abs_ch	REAL;
-	g_fact	REAL;
-	gf_inc	REAL;
-	n_happ	REAL;
-	t_happ	REAL;
-	temp	REAL;
-	growth	REAL;
-	workers	REAL;
-	str_thr	REAL;
+	rel_ch	DOUBLE PRECISION;
+	abs_ch	DOUBLE PRECISION;
+	g_fact	DOUBLE PRECISION;
+	gf_inc	DOUBLE PRECISION;
+	n_happ	DOUBLE PRECISION;
+	t_happ	DOUBLE PRECISION;
+	temp	DOUBLE PRECISION;
+	growth	DOUBLE PRECISION;
+	workers	DOUBLE PRECISION;
+	str_thr	DOUBLE PRECISION;
 BEGIN
 	-- Get constants
 	rel_ch := sys.get_constant( 'game.happiness.relativeChange' );
@@ -35,14 +35,13 @@ BEGIN
 	-- Process planets
 	FOR rec IN SELECT p.name_id AS id , p.population AS pop ,
 					ph.target AS target , ph.current AS happy_pop ,
-					( ph.current / p.population )::REAL AS current
+					ph.current / p.population AS current
 				FROM sys.updates su
-					INNER JOIN verse.planets_updates vu
-						USING ( update_id , updtype_id , updtgt_id )
-					INNER JOIN verse.planets p
-						USING ( name_id )
+					INNER JOIN verse.updates vu ON vu.update_id = su.id
+					INNER JOIN verse.planets p ON vu.planet_id = p.name_id
 					INNER JOIN verse.planet_happiness ph ON ph.planet_id = p.name_id
-				WHERE su.update_last = c_tick AND su.update_state = 'PROCESSING'
+				WHERE su.last_tick = c_tick AND su.status = 'PROCESSING'
+					AND su.gu_type = 'PLANET_POPULATION'
 				FOR UPDATE OF p, ph
 	LOOP
 		IF round( rec.target / rel_ch ) = round( rec.current / rel_ch ) THEN
@@ -102,9 +101,4 @@ BEGIN
 		END IF;
 	END LOOP;
 END;
-$$ LANGUAGE plpgsql;
-
-SELECT sys.register_update_type( 'Planets' , 'PlanetPopulation' ,
-		'Planet populations are being updated.' ,
-		'process_planet_population_updates'
-	);
\ No newline at end of file
+$$ LANGUAGE plpgsql;
\ No newline at end of file
diff --git a/legacyworlds-server-data/db-structure/parts/050-updates/110-planet-money.sql b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/updates/110-planet-money.sql
similarity index 69%
rename from legacyworlds-server-data/db-structure/parts/050-updates/110-planet-money.sql
rename to legacyworlds-server/legacyworlds-server-data/db-structure/parts/updates/110-planet-money.sql
index 1822d7f..c22c86a 100644
--- a/legacyworlds-server-data/db-structure/parts/050-updates/110-planet-money.sql
+++ b/legacyworlds-server/legacyworlds-server-data/db-structure/parts/updates/110-planet-money.sql
@@ -14,20 +14,19 @@ CREATE OR REPLACE FUNCTION sys.process_planet_money_updates( c_tick BIGINT )
 	AS $$
 DECLARE
 	rec		RECORD;
-	incme	REAL;
+	incme	DOUBLE PRECISION;
 BEGIN
 	FOR rec IN SELECT p.name_id AS id , p.population AS pop ,
-					( ph.current / p.population )::REAL AS happiness ,
+					ph.current / p.population AS happiness ,
 					( ea.planet_id IS NULL ) AS produces_income
 				FROM sys.updates su
-					INNER JOIN verse.planets_updates vu
-						USING ( update_id , updtype_id , updtgt_id )
-					INNER JOIN verse.planets p
-						USING ( name_id )
+					INNER JOIN verse.updates vu ON vu.update_id = su.id
+					INNER JOIN verse.planets p ON vu.planet_id = p.name_id
 					INNER JOIN verse.planet_happiness ph ON ph.planet_id = p.name_id
 					INNER JOIN verse.planet_money pm ON pm.planet_id = p.name_id
 					LEFT OUTER JOIN emp.abandon ea ON ea.planet_id = p.name_id
-				WHERE su.update_last = c_tick AND su.update_state = 'PROCESSING'
+				WHERE su.last_tick = c_tick AND su.status = 'PROCESSING'
+					AND su.gu_type = 'PLANET_MONEY'
 				FOR UPDATE OF p, pm
 	LOOP
 		IF rec.produces_income THEN
@@ -43,9 +42,4 @@ BEGIN
 			WHERE planet_id = rec.id;
 	END LOOP;
 END;
-$$ LANGUAGE plpgsql;
-
-SELECT sys.register_update_type( 'Planets' , 'PlanetMoney' ,
-		'Planets'' income and upkeep are being updated.' ,
-		'process_planet_money_updates'
-	);
\ No newline at end of file
+$$ LANGUAGE plpgsql;
\ No newline at end of file
diff --git a/legacyworlds-server/legacyworlds-server-data/db-structure/test-mode.sql b/legacyworlds-server/legacyworlds-server-data/db-structure/test-mode.sql
new file mode 100644
index 0000000..777b268
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-data/db-structure/test-mode.sql
@@ -0,0 +1,7 @@
+INSERT INTO admin.administrators (appear_as, pass_md5 , pass_sha1, privileges)
+	VALUES ( 'Test' , '...' , '...' , 0 );
+SELECT sys.set_constant( 'game.growthFactor' , 200 , 1 );
+SELECT sys.set_constant( 'game.battle.damage' , 0.05 , 1 );
+SELECT sys.set_constant( 'game.battle.timeToFullIntensity' , 5 , 1 );
+SELECT sys.set_constant( 'map.names.minDelay' , 1 , 1 );
+SELECT sys.set_constant( 'game.work.wuPerPopUnit' , 0.5 , 1 );
diff --git a/legacyworlds-server-data/pom.xml b/legacyworlds-server/legacyworlds-server-data/pom.xml
similarity index 71%
rename from legacyworlds-server-data/pom.xml
rename to legacyworlds-server/legacyworlds-server-data/pom.xml
index 90ce316..be98172 100644
--- a/legacyworlds-server-data/pom.xml
+++ b/legacyworlds-server/legacyworlds-server-data/pom.xml
@@ -4,20 +4,21 @@
 	<parent>
 		<artifactId>legacyworlds-server</artifactId>
 		<groupId>com.deepclone.lw</groupId>
-		<version>1.0.0</version>
-		<relativePath>../legacyworlds-server/pom.xml</relativePath>
+		<version>5.99.2</version>
 	</parent>
 
+	<groupId>com.deepclone.lw</groupId>
 	<artifactId>legacyworlds-server-data</artifactId>
-	<version>${legacyworlds.version.main}.${legacyworlds.version.release}-${legacyworlds.version.build}</version>
-	<name>Legacy Worlds - Server - Data</name>
+	<name>Legacy Worlds server data</name>
+	<version>5.99.2</version>
 	<description>This package contains all data access classes for the Legacy Worlds server.</description>
 
 	<dependencies>
 		<dependency>
 			<groupId>com.deepclone.lw</groupId>
 			<artifactId>legacyworlds-session</artifactId>
+			<version>${project.version}</version>
 		</dependency>
 	</dependencies>
 
-</project>
+</project>
\ No newline at end of file
diff --git a/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/accounts/Account.java b/legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/accounts/Account.java
similarity index 100%
rename from legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/accounts/Account.java
rename to legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/accounts/Account.java
diff --git a/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/accounts/AccountOperationResult.java b/legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/accounts/AccountOperationResult.java
similarity index 100%
rename from legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/accounts/AccountOperationResult.java
rename to legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/accounts/AccountOperationResult.java
diff --git a/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/accounts/QuittingAccount.java b/legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/accounts/QuittingAccount.java
similarity index 100%
rename from legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/accounts/QuittingAccount.java
rename to legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/accounts/QuittingAccount.java
diff --git a/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/accounts/ValidationResult.java b/legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/accounts/ValidationResult.java
similarity index 100%
rename from legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/accounts/ValidationResult.java
rename to legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/accounts/ValidationResult.java
diff --git a/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/admin/AdminConnection.java b/legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/admin/AdminConnection.java
similarity index 100%
rename from legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/admin/AdminConnection.java
rename to legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/admin/AdminConnection.java
diff --git a/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/admin/AdminRecord.java b/legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/admin/AdminRecord.java
similarity index 100%
rename from legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/admin/AdminRecord.java
rename to legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/admin/AdminRecord.java
diff --git a/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/AllianceMembership.java b/legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/AllianceMembership.java
similarity index 100%
rename from legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/AllianceMembership.java
rename to legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/AllianceMembership.java
diff --git a/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/BuildingOutputType.java b/legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/BuildingOutputType.java
similarity index 88%
rename from legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/BuildingOutputType.java
rename to legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/BuildingOutputType.java
index 22b5bda..1301ef0 100644
--- a/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/BuildingOutputType.java
+++ b/legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/BuildingOutputType.java
@@ -6,7 +6,6 @@ public enum BuildingOutputType {
 	WORK ,
 	CASH ,
 	DEF ,
-	POP ,
-	MINE
+	POP
 
 }
diff --git a/legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/GeneralInformation.java b/legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/GeneralInformation.java
new file mode 100644
index 0000000..1b727f5
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/GeneralInformation.java
@@ -0,0 +1,76 @@
+package com.deepclone.lw.sqld.game;
+
+
+public class GeneralInformation
+{
+
+	private final Character status;
+
+	private final String name;
+
+	private final String tag;
+
+	private final String language;
+
+	private final long cash;
+
+	private final long nextTick;
+
+	private final int accountId;
+
+
+	public GeneralInformation( Character status , String name , String tag , String language , long cash ,
+			long nextTick , int accountId )
+	{
+		this.status = status;
+		this.name = name;
+		this.tag = tag;
+		this.language = language;
+		this.cash = cash;
+		this.nextTick = nextTick;
+		this.accountId = accountId;
+	}
+
+
+	public Character getStatus( )
+	{
+		return status;
+	}
+
+
+	public String getName( )
+	{
+		return name;
+	}
+
+
+	public String getTag( )
+	{
+		return tag;
+	}
+
+
+	public String getLanguage( )
+	{
+		return language;
+	}
+
+
+	public long getCash( )
+	{
+		return cash;
+	}
+
+
+	public long getNextTick( )
+	{
+		return nextTick;
+	}
+
+
+	public int getAccountId( )
+	{
+		return accountId;
+	}
+
+}
diff --git a/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/MapData.java b/legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/MapData.java
similarity index 100%
rename from legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/MapData.java
rename to legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/MapData.java
diff --git a/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/PlanetData.java b/legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/PlanetData.java
similarity index 82%
rename from legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/PlanetData.java
rename to legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/PlanetData.java
index 4200a91..1b47231 100644
--- a/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/PlanetData.java
+++ b/legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/PlanetData.java
@@ -22,7 +22,7 @@ public final class PlanetData
 
 		public AccessType getAccess( )
 		{
-			return this.access;
+			return access;
 		}
 
 
@@ -34,7 +34,7 @@ public final class PlanetData
 
 		public int getX( )
 		{
-			return this.x;
+			return x;
 		}
 
 
@@ -46,7 +46,7 @@ public final class PlanetData
 
 		public int getY( )
 		{
-			return this.y;
+			return y;
 		}
 
 
@@ -58,7 +58,7 @@ public final class PlanetData
 
 		public int getOrbit( )
 		{
-			return this.orbit;
+			return orbit;
 		}
 
 
@@ -70,7 +70,7 @@ public final class PlanetData
 
 		public int getPicture( )
 		{
-			return this.picture;
+			return picture;
 		}
 
 
@@ -82,7 +82,7 @@ public final class PlanetData
 
 		public String getName( )
 		{
-			return this.name;
+			return name;
 		}
 
 
@@ -94,7 +94,7 @@ public final class PlanetData
 
 		public String getTag( )
 		{
-			return this.tag;
+			return tag;
 		}
 
 
@@ -117,7 +117,7 @@ public final class PlanetData
 
 		public long getPopulation( )
 		{
-			return this.population;
+			return population;
 		}
 
 
@@ -129,7 +129,7 @@ public final class PlanetData
 
 		public long getDefence( )
 		{
-			return this.defence;
+			return defence;
 		}
 
 
@@ -141,7 +141,7 @@ public final class PlanetData
 
 		public long getOwnPower( )
 		{
-			return this.ownPower;
+			return ownPower;
 		}
 
 
@@ -153,7 +153,7 @@ public final class PlanetData
 
 		public long getFriendlyPower( )
 		{
-			return this.friendlyPower;
+			return friendlyPower;
 		}
 
 
@@ -165,7 +165,7 @@ public final class PlanetData
 
 		public long getHostilePower( )
 		{
-			return this.hostilePower;
+			return hostilePower;
 		}
 
 
@@ -177,7 +177,7 @@ public final class PlanetData
 
 		public Long getBattle( )
 		{
-			return this.battle;
+			return battle;
 		}
 
 
@@ -197,12 +197,11 @@ public final class PlanetData
 		private boolean renamePossible;
 		private boolean abandonPossible;
 		private Integer abandonTime;
-		private boolean ownSettings;
 
 
 		public int getHappiness( )
 		{
-			return this.happiness;
+			return happiness;
 		}
 
 
@@ -214,7 +213,7 @@ public final class PlanetData
 
 		public int gethChange( )
 		{
-			return this.hChange;
+			return hChange;
 		}
 
 
@@ -226,7 +225,7 @@ public final class PlanetData
 
 		public long getIncome( )
 		{
-			return this.income;
+			return income;
 		}
 
 
@@ -238,7 +237,7 @@ public final class PlanetData
 
 		public long getUpkeep( )
 		{
-			return this.upkeep;
+			return upkeep;
 		}
 
 
@@ -250,7 +249,7 @@ public final class PlanetData
 
 		public boolean isRenamePossible( )
 		{
-			return this.renamePossible;
+			return renamePossible;
 		}
 
 
@@ -262,7 +261,7 @@ public final class PlanetData
 
 		public boolean isAbandonPossible( )
 		{
-			return this.abandonPossible;
+			return abandonPossible;
 		}
 
 
@@ -274,7 +273,7 @@ public final class PlanetData
 
 		public Integer getAbandonTime( )
 		{
-			return this.abandonTime;
+			return abandonTime;
 		}
 
 
@@ -283,18 +282,6 @@ public final class PlanetData
 			this.abandonTime = abandonTime;
 		}
 
-
-		public boolean isOwnSettings( )
-		{
-			return this.ownSettings;
-		}
-
-
-		public void setOwnSettings( boolean ownSettings )
-		{
-			this.ownSettings = ownSettings;
-		}
-
 	}
 
 
diff --git a/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/RawFleetOwner.java b/legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/RawFleetOwner.java
similarity index 100%
rename from legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/RawFleetOwner.java
rename to legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/RawFleetOwner.java
diff --git a/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/RawFleetShip.java b/legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/RawFleetShip.java
similarity index 100%
rename from legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/RawFleetShip.java
rename to legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/RawFleetShip.java
diff --git a/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/RawStaticFleet.java b/legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/RawStaticFleet.java
similarity index 100%
rename from legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/RawStaticFleet.java
rename to legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/RawStaticFleet.java
diff --git a/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/battle/BattleListRecord.java b/legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/battle/BattleListRecord.java
similarity index 100%
rename from legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/battle/BattleListRecord.java
rename to legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/battle/BattleListRecord.java
diff --git a/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/battle/BuildingHistoryRecord.java b/legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/battle/BuildingHistoryRecord.java
similarity index 100%
rename from legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/battle/BuildingHistoryRecord.java
rename to legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/battle/BuildingHistoryRecord.java
diff --git a/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/battle/EmpireBattleRecord.java b/legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/battle/EmpireBattleRecord.java
similarity index 100%
rename from legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/battle/EmpireBattleRecord.java
rename to legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/battle/EmpireBattleRecord.java
diff --git a/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/battle/EventItemRecord.java b/legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/battle/EventItemRecord.java
similarity index 100%
rename from legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/battle/EventItemRecord.java
rename to legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/battle/EventItemRecord.java
diff --git a/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/battle/EventRecord.java b/legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/battle/EventRecord.java
similarity index 100%
rename from legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/battle/EventRecord.java
rename to legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/battle/EventRecord.java
diff --git a/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/battle/PresenceRecord.java b/legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/battle/PresenceRecord.java
similarity index 100%
rename from legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/battle/PresenceRecord.java
rename to legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/battle/PresenceRecord.java
diff --git a/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/battle/ProtagonistRecord.java b/legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/battle/ProtagonistRecord.java
similarity index 100%
rename from legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/battle/ProtagonistRecord.java
rename to legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/battle/ProtagonistRecord.java
diff --git a/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/battle/ShipHistoryRecord.java b/legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/battle/ShipHistoryRecord.java
similarity index 100%
rename from legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/battle/ShipHistoryRecord.java
rename to legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/battle/ShipHistoryRecord.java
diff --git a/legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/techs/Category.java b/legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/techs/Category.java
new file mode 100644
index 0000000..61b400c
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/techs/Category.java
@@ -0,0 +1,169 @@
+package com.deepclone.lw.sqld.game.techs;
+
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+
+
+/**
+ * A technology category for the technology graph.
+ * 
+ * @author tseeker
+ */
+public class Category
+{
+
+	/** The string identifier of the category's name */
+	private final String name;
+
+	/** The string identifier of the category's description */
+	private String description;
+
+	/**
+	 * Map of the technologies belonging to the category, with their name string identifier as the
+	 * index.
+	 */
+	private Map< String , Technology > technologies;
+
+
+	/**
+	 * Initialise a category's representation.
+	 * 
+	 * @param name
+	 *            string identifier of the category's name
+	 * @param description
+	 *            string identifier of the category's description
+	 */
+	Category( String name , String description )
+	{
+		this.name = name;
+		this.description = description;
+		this.technologies = new HashMap< String , Technology >( );
+	}
+
+
+	/**
+	 * Copy a category.
+	 * 
+	 * @param cat
+	 *            the category being copied.
+	 */
+	Category( Category cat )
+	{
+		this.name = cat.name;
+		this.description = cat.description;
+		this.technologies = new HashMap< String , Technology >( );
+		for ( Technology tech : cat.technologies.values( ) ) {
+			this.technologies.put( tech.getName( ) , new Technology( tech ) );
+		}
+	}
+
+
+	/** @return the string identifier of the category's name */
+	public String getName( )
+	{
+		return name;
+	}
+
+
+	/** @return the string identifier of the category's description */
+	public String getDescription( )
+	{
+		return description;
+	}
+
+
+	/**
+	 * Update the category's description.
+	 * 
+	 * @param description
+	 *            the string identifier of the category's description
+	 */
+	void setDescription( String description )
+	{
+		this.description = description;
+	}
+
+
+	/**
+	 * List technologies in the category.
+	 * 
+	 * @return an alphabetically ordered list of technology names
+	 */
+	public List< String > getTechnologies( )
+	{
+		List< String > names = new LinkedList< String >( this.technologies.keySet( ) );
+		Collections.sort( names );
+		return names;
+	}
+
+
+	/**
+	 * Find technology objects stored in the category.
+	 * 
+	 * @return the list of technology objects.
+	 */
+	Collection< Technology > getTechnologyObjects( )
+	{
+		return this.technologies.values( );
+	}
+
+
+	/**
+	 * Add a new technology to the category's record.
+	 * 
+	 * @param name
+	 *            string identifier of the technology's name
+	 * @param description
+	 *            string identifier of the technology's description
+	 * @param points
+	 *            research points required to implement the technology
+	 * @param cost
+	 *            cost of implementing the technology
+	 * @return the newly created {@link Technology} instance
+	 */
+	Technology addTechnology( String name , String description , int points , int cost )
+	{
+		Technology tech = new Technology( this , name , description , points , cost );
+		this.technologies.put( name , tech );
+		return tech;
+	}
+
+
+	/**
+	 * Move a technology from another category into the current category.
+	 * 
+	 * @param tech
+	 *            the technology to move
+	 */
+	void addExistingTechnology( Technology tech )
+	{
+		Category previous = tech.getCategory( );
+		if ( previous.name.equals( this.name ) ) {
+			return;
+		}
+
+		previous.technologies.remove( tech.getName( ) );
+		this.technologies.put( tech.getName( ) , tech );
+		tech.setCategory( this );
+	}
+
+
+	/**
+	 * Remove a technology from the category. This method is meant to be called from
+	 * {@link Technology#delete()}.
+	 * 
+	 * @param technology
+	 *            the technology to remove.
+	 */
+	void removeTechnology( Technology technology )
+	{
+		this.technologies.remove( technology );
+	}
+
+}
diff --git a/legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/techs/EmpireTechnology.java b/legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/techs/EmpireTechnology.java
new file mode 100644
index 0000000..b5dee91
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/techs/EmpireTechnology.java
@@ -0,0 +1,175 @@
+package com.deepclone.lw.sqld.game.techs;
+
+
+/**
+ * Empire technology and research record.
+ * 
+ * @author tseeker
+ */
+public class EmpireTechnology
+{
+
+	/** Numeric identifier used for unknown technologies */
+	private final Integer numericId;
+
+	/** Technology string name */
+	private final String identifier;
+
+	/** Status of the technology */
+	private final ResearchStatus status;
+
+	/** Whether additional details should be provided */
+	private final boolean detailed;
+
+	/** Research completion percentage */
+	private final Integer percentage;
+
+	/** Research priority */
+	private final Integer priority;
+
+	/** Implementation cost */
+	private final Integer cost;
+
+
+	/**
+	 * Initialise the record for an implemented technology.
+	 * 
+	 * @param identifier
+	 *            string identifier of the technology's name.
+	 */
+	public EmpireTechnology( String identifier )
+	{
+		this.numericId = null;
+		this.identifier = identifier;
+		this.status = ResearchStatus.IMPLEMENTED;
+		this.detailed = true;
+		this.percentage = null;
+		this.priority = null;
+		this.cost = null;
+	}
+
+
+	/**
+	 * Initialise the record for an unidentified technology being researched.
+	 * 
+	 * @param numericId
+	 *            numeric identifier of the technology
+	 * @param identifier
+	 *            string identifier of the technology's name
+	 * @param percentage
+	 *            research completion percentage
+	 * @param priority
+	 *            research priority
+	 */
+	public EmpireTechnology( int numericId , String identifier , int percentage , int priority )
+	{
+		this.numericId = numericId;
+		this.identifier = identifier;
+		this.status = ResearchStatus.IN_PROGRESS;
+		this.detailed = false;
+		this.percentage = percentage;
+		this.priority = priority;
+		this.cost = null;
+	}
+
+
+	/**
+	 * Initialise the record for an identified technology being researched.
+	 * 
+	 * @param identifier
+	 *            string identifier of the technology's name
+	 * @param percentage
+	 *            research completion percentage
+	 * @param priority
+	 *            research priority
+	 */
+	public EmpireTechnology( String identifier , int percentage , int priority )
+	{
+		this.numericId = null;
+		this.identifier = identifier;
+		this.status = ResearchStatus.IN_PROGRESS;
+		this.detailed = true;
+		this.percentage = percentage;
+		this.priority = priority;
+		this.cost = null;
+	}
+
+
+	/**
+	 * Initialise the record for a researched technology.
+	 * 
+	 * @param identifier
+	 *            string identifier of the technology's name
+	 * @param cost
+	 *            implementation cost
+	 */
+	public EmpireTechnology( String identifier , int cost )
+	{
+		this.numericId = null;
+		this.identifier = identifier;
+		this.status = ResearchStatus.RESEARCHED;
+		this.detailed = true;
+		this.percentage = null;
+		this.priority = null;
+		this.cost = cost;
+	}
+
+
+	/** @return the numeric identifier used for unknown technologies */
+	public Integer getNumericId( )
+	{
+		return this.numericId;
+	}
+
+
+	/** @return the string identifier of the technology's name */
+	public String getIdentifier( )
+	{
+		return this.identifier;
+	}
+
+
+	/** @return the technology's research status */
+	public ResearchStatus getStatus( )
+	{
+		return this.status;
+	}
+
+
+	/** @return whether details are to be displayed */
+	public boolean isDetailed( )
+	{
+		return this.detailed;
+	}
+
+
+	/**
+	 * @return the technology's research completion percentage or <code>null</code> if the
+	 *         technology is not under research.
+	 */
+	public Integer getPercentage( )
+	{
+		return this.percentage;
+	}
+
+
+	/**
+	 * @return the technology's research priority or <code>null</code> if the technology is not under
+	 *         research
+	 */
+	public Integer getPriority( )
+	{
+		return priority;
+	}
+
+
+	/**
+	 * @return the technology's implementation cost, or <code>null</code> if the technology is
+	 *         either implemented or being researched.
+	 */
+	public Integer getCost( )
+	{
+		return this.cost;
+	}
+
+}
diff --git a/legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/techs/ResearchStatus.java b/legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/techs/ResearchStatus.java
new file mode 100644
index 0000000..db2b066
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/techs/ResearchStatus.java
@@ -0,0 +1,20 @@
+package com.deepclone.lw.sqld.game.techs;
+
+
+/**
+ * Research status for empire technologies.
+ * 
+ * @author tseeker
+ */
+public enum ResearchStatus {
+
+	/** Research in progress */
+	IN_PROGRESS ,
+
+	/** Technology researched but unimplemented */
+	RESEARCHED ,
+
+	/** Technology researched and implemented */
+	IMPLEMENTED
+
+}
diff --git a/legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/techs/ResearchUpdateInput.java b/legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/techs/ResearchUpdateInput.java
new file mode 100644
index 0000000..fe50a45
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/techs/ResearchUpdateInput.java
@@ -0,0 +1,90 @@
+package com.deepclone.lw.sqld.game.techs;
+
+
+/**
+ * Record used as the input of the research update handler.
+ * 
+ * @author tseeker
+ */
+public class ResearchUpdateInput
+{
+
+	private final int empireId;
+	private final String technology;
+	private final ResearchStatus status;
+	private final Double points;
+	private final Integer priority;
+
+
+	/**
+	 * Initialise the record for a researched technology
+	 * 
+	 * @param empireId
+	 *            empire identifier
+	 * @param technology
+	 *            technology name
+	 * @param implemented
+	 *            whether the technology has been implemented or not
+	 */
+	public ResearchUpdateInput( int empireId , String technology , boolean implemented )
+	{
+		this.empireId = empireId;
+		this.technology = technology;
+		this.status = implemented ? ResearchStatus.IMPLEMENTED : ResearchStatus.RESEARCHED;
+		this.points = null;
+		this.priority = null;
+	}
+
+
+	/**
+	 * Initialise the record for an ongoing research process.
+	 * 
+	 * @param empireId
+	 *            empire identifier
+	 * @param technology
+	 *            technology name
+	 * @param points
+	 *            accumulated research points
+	 * @param priority
+	 *            current priority
+	 */
+	public ResearchUpdateInput( int empireId , String technology , double points , int priority )
+	{
+		this.empireId = empireId;
+		this.technology = technology;
+		this.status = ResearchStatus.IN_PROGRESS;
+		this.points = points;
+		this.priority = priority;
+	}
+
+
+	public int getEmpireId( )
+	{
+		return this.empireId;
+	}
+
+
+	public String getTechnology( )
+	{
+		return this.technology;
+	}
+
+
+	public ResearchStatus getStatus( )
+	{
+		return this.status;
+	}
+
+
+	public Double getPoints( )
+	{
+		return this.points;
+	}
+
+
+	public Integer getPriority( )
+	{
+		return this.priority;
+	}
+
+}
diff --git a/legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/techs/ResearchUpdateOutput.java b/legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/techs/ResearchUpdateOutput.java
new file mode 100644
index 0000000..6e338d2
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/techs/ResearchUpdateOutput.java
@@ -0,0 +1,134 @@
+package com.deepclone.lw.sqld.game.techs;
+
+
+/**
+ * Record that describes the output of the research update.
+ * 
+ * @author tseeker
+ */
+public class ResearchUpdateOutput
+{
+
+	private final int empireId;
+	private final String technology;
+	private final Boolean creation;
+	private Double points;
+	private Integer priority;
+
+
+	/**
+	 * Create a research update output record which indicates that a technology has been fully
+	 * researched.
+	 * 
+	 * @param empireId
+	 *            the empire's identifier
+	 * @param technology
+	 *            the name of the technology
+	 */
+	public ResearchUpdateOutput( int empireId , String technology )
+	{
+		this.empireId = empireId;
+		this.technology = technology;
+		this.creation = null;
+		this.points = null;
+		this.priority = null;
+	}
+
+
+	/**
+	 * Create a research update output record which indicates that a research progress row should be
+	 * either created or updated.
+	 * 
+	 * @param empireId
+	 *            the empire's identifier
+	 * @param technology
+	 *            the name of the technology
+	 * @param creation
+	 *            whether the research process for this technology is a new one
+	 * @param points
+	 *            amount of research points accumulated in the record
+	 * @param priority
+	 *            priority of the research process
+	 */
+	public ResearchUpdateOutput( int empireId , String technology , boolean creation , double points , int priority )
+	{
+		this.empireId = empireId;
+		this.technology = technology;
+		this.creation = creation;
+		this.points = points;
+		this.priority = priority;
+	}
+
+
+	/** @return the empire's identifier */
+	public int getEmpireId( )
+	{
+		return empireId;
+	}
+
+
+	/** @return the name of the technology */
+	public String getTechnology( )
+	{
+		return technology;
+	}
+
+
+	/**
+	 * @return whether the research process for this technology is a new one, or <code>null</code>
+	 *         if the record is about a fully researched technology
+	 */
+	public Boolean getCreation( )
+	{
+		return creation;
+	}
+
+
+	/**
+	 * @return the amount of accumulated research points for the research process or
+	 *         <code>null</code> if the record is about a fully researched technology
+	 */
+	public Double getPoints( )
+	{
+		return points;
+	}
+
+
+	/**
+	 * Update the accumulated research points
+	 * 
+	 * @param points
+	 *            the amount of points to add
+	 */
+	public void addPoints( Double points )
+	{
+		this.points = this.points + points;
+	}
+
+
+	/**
+	 * @return the research topic's priority or <code>null</code> if the record is about a fully
+	 *         researched technology
+	 */
+	public Integer getPriority( )
+	{
+		return priority;
+	}
+
+
+	/**
+	 * Set the priority of the research
+	 * 
+	 * @param priority
+	 *            the new priority
+	 */
+	public void setPriority( int priority )
+	{
+		if ( this.priority == null ) {
+			throw new IllegalArgumentException( "trying to set priority on known technology " + this.technology
+					+ " for empire #" + this.empireId );
+		}
+		this.priority = priority;
+	}
+
+}
diff --git a/legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/techs/TechGraph.java b/legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/techs/TechGraph.java
new file mode 100644
index 0000000..0d398a1
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/techs/TechGraph.java
@@ -0,0 +1,366 @@
+package com.deepclone.lw.sqld.game.techs;
+
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import com.deepclone.lw.sqld.game.techs.TechGraphException.Code;
+
+
+
+/**
+ * Representation of the whole technology graph.
+ */
+public class TechGraph
+{
+
+	/** List of all technologies */
+	private List< Technology > technologies;
+
+	/** Technologies indexed by name */
+	private Map< String , Technology > techsByName;
+
+	/** Technology categories indexed by name */
+	private Map< String , Category > categoriesByName;
+
+
+	/** Initialise an empty tech graph */
+	public TechGraph( )
+	{
+		this.technologies = new LinkedList< Technology >( );
+		this.techsByName = new HashMap< String , Technology >( );
+		this.categoriesByName = new HashMap< String , Category >( );
+	}
+
+
+	/**
+	 * Create a copy of an existing tech graph
+	 * 
+	 * @param graph
+	 *            the original tech graph
+	 */
+	public TechGraph( TechGraph graph )
+	{
+		this.technologies = new LinkedList< Technology >( );
+		this.techsByName = new HashMap< String , Technology >( );
+		this.categoriesByName = new HashMap< String , Category >( );
+
+		// Copy category and technology fields
+		for ( Category cat : graph.categoriesByName.values( ) ) {
+			Category copyCat = new Category( cat );
+			this.categoriesByName.put( cat.getName( ) , copyCat );
+
+			for ( Technology tech : copyCat.getTechnologyObjects( ) ) {
+				this.technologies.add( tech );
+				this.techsByName.put( tech.getName( ) , tech );
+			}
+		}
+
+		// Copy dependencies
+		for ( Technology tech : this.technologies ) {
+			for ( String depName : graph.techsByName.get( tech.getName( ) ).getDependencies( ) ) {
+				tech.addDependency( this.techsByName.get( depName ) );
+			}
+		}
+	}
+
+
+	/**
+	 * Register a new technology category.
+	 * 
+	 * @param name
+	 *            the name of the new category
+	 * @param description
+	 *            the description of the new category
+	 * 
+	 * @throws TechGraphException
+	 *             with {@link TechGraphException.Code#DUPLICATE_CATEGORY} if the category already
+	 *             exists.
+	 */
+	public void addCategory( String name , String description )
+			throws TechGraphException
+	{
+		if ( this.categoriesByName.containsKey( name ) ) {
+			throw new TechGraphException( Code.DUPLICATE_CATEGORY );
+		}
+		this.categoriesByName.put( name , new Category( name , description ) );
+	}
+
+
+	/**
+	 * List all categories in alphabetic order
+	 * 
+	 * @return the list of category names
+	 */
+	public List< String > getCategories( )
+	{
+		List< String > result = new LinkedList< String >( this.categoriesByName.keySet( ) );
+		Collections.sort( result );
+		return result;
+	}
+
+
+	/**
+	 * Access a registered category.
+	 * 
+	 * @param name
+	 *            the name of the category
+	 * 
+	 * @return the category's record
+	 * 
+	 * @throws TechGraphException
+	 *             with {@link TechGraphException.Code#MISSING_CATEGORY} if the category does not
+	 *             exist.
+	 */
+	public Category getCategory( String name )
+			throws TechGraphException
+	{
+		Category cat = this.categoriesByName.get( name );
+		if ( cat == null ) {
+			throw new TechGraphException( Code.MISSING_CATEGORY , name );
+		}
+		return cat;
+	}
+
+
+	/**
+	 * Set a category's description.
+	 * 
+	 * @param name
+	 *            the name of the category
+	 * 
+	 * @param description
+	 *            the string identifier of the new description
+	 * 
+	 * @throws TechGraphException
+	 *             with {@link TechGraphException.Code#MISSING_CATEGORY} if the category does not
+	 *             exist.
+	 */
+	public void updateCategory( String name , String description )
+			throws TechGraphException
+	{
+		this.getCategory( name ).setDescription( description );
+	}
+
+
+	/**
+	 * Delete a category from the graph's information.
+	 * 
+	 * @param name
+	 *            the name of the category
+	 * 
+	 * @throws TechGraphException
+	 *             with {@link TechGraphException.Code#MISSING_CATEGORY} if the category does not
+	 *             exist, or with {@link TechGraphException.Code#DEPENDENCY_ERROR} if the category
+	 *             contains technologies.
+	 */
+	public void deleteCategory( String name )
+			throws TechGraphException
+	{
+		Category cat = this.getCategory( name );
+		if ( !cat.getTechnologies( ).isEmpty( ) ) {
+			throw new TechGraphException( Code.DEPENDENCY_ERROR );
+		}
+		this.categoriesByName.remove( name );
+	}
+
+
+	/**
+	 * Register a technology into the graph.
+	 * 
+	 * @param category
+	 *            the name of the category the new technology will be added to
+	 * @param name
+	 *            the string identifier of name of the new technology
+	 * @param description
+	 *            the string identifier of description of the new technology
+	 * @param points
+	 *            the amount of research points required to research the technology
+	 * @param cost
+	 *            the monetary cost of implementing the technology
+	 * 
+	 * @throws TechGraphException
+	 *             with {@link TechGraphException.Code#MISSING_CATEGORY} if the category does not
+	 *             exist, or with {@link TechGraphException.Code#DUPLICATE_TECHNOLOGY} if the
+	 *             technology already exists.
+	 */
+	public void addTechnology( String category , String name , String description , int points , int cost )
+			throws TechGraphException
+	{
+		if ( this.techsByName.containsKey( name ) ) {
+			throw new TechGraphException( Code.DUPLICATE_TECHNOLOGY , name );
+		}
+
+		Technology tech = this.getCategory( category ).addTechnology( name , description , points , cost );
+		this.technologies.add( tech );
+		this.techsByName.put( name , tech );
+	}
+
+
+	/**
+	 * Access a technology's record.
+	 * 
+	 * @param technology
+	 *            the name of the technology
+	 * 
+	 * @return the {@link Technology} instance describing the technology
+	 * 
+	 * @throws TechGraphException
+	 *             with {@link TechGraphException.Code#MISSING_TECHNOLOGY} if the technology does
+	 *             not exist
+	 */
+	public Technology getTechnology( String technology )
+			throws TechGraphException
+	{
+		Technology tech = this.techsByName.get( technology );
+		if ( tech == null ) {
+			throw new TechGraphException( Code.MISSING_TECHNOLOGY , technology );
+		}
+		return tech;
+	}
+
+
+	/**
+	 * Update a technology's record.
+	 * 
+	 * @param technology
+	 *            the technology's name
+	 * @param description
+	 *            the string identifier of the new description, or <code>null</code> if the
+	 *            description must be kept.
+	 * @param points
+	 *            the new amount of research points for the technology, or <code>null</code> if the
+	 *            research points are not to be modified.
+	 * @param cost
+	 *            the new implementation cost of the technology, or <code>null</code> if the cost
+	 *            does not change.
+	 * 
+	 * @throws TechGraphException
+	 *             with {@link TechGraphException.Code#MISSING_TECHNOLOGY} if the technology does
+	 *             not exist
+	 */
+	public void updateTechnology( String technology , String description , Integer points , Integer cost )
+			throws TechGraphException
+	{
+		Technology tech = this.getTechnology( technology );
+		if ( description != null ) {
+			tech.setDescription( description );
+		}
+		if ( points != null ) {
+			tech.setPoints( points );
+		}
+		if ( cost != null ) {
+			tech.setCost( cost );
+		}
+	}
+
+
+	/**
+	 * Modify the category of a technology.
+	 * 
+	 * @param technology
+	 *            the name of the technology
+	 * @param category
+	 *            the name of the category the technology should be moved into
+	 * @throws TechGraphException
+	 *             with {@link TechGraphException.Code#MISSING_TECHNOLOGY} if the technology does
+	 *             not exist or with {@link TechGraphException.Code#MISSING_CATEGORY} if the
+	 *             category does not exist
+	 */
+	public void setCategory( String technology , String category )
+			throws TechGraphException
+	{
+		this.getCategory( category ).addExistingTechnology( this.getTechnology( technology ) );
+	}
+
+
+	/**
+	 * Add a dependency to a technology.
+	 * 
+	 * @param technology
+	 *            the name of the technology to add a dependency to
+	 * @param dependsOn
+	 *            the name of the new dependency
+	 * 
+	 * @throws TechGraphException
+	 *             with {@link TechGraphException.Code#MISSING_TECHNOLOGY} if the dependent
+	 *             technology does not exist, with
+	 *             {@link TechGraphException.Code#MISSING_DEPENDENCY} if the dependency does not
+	 *             exist, with {@link TechGraphException.Code#RECURSIVE_DEPENDENCY} if adding the
+	 *             dependency would cause a recursion in the graph, or with
+	 *             {@link TechGraphException.Code#DUPLICATE_DEPENDENCY} if the technology already
+	 *             depends on the specified technology (either directly or indirectly)
+	 */
+	public void addDependency( String technology , String dependsOn )
+			throws TechGraphException
+	{
+		Technology tech = this.getTechnology( technology );
+		Technology dep;
+		try {
+			dep = this.getTechnology( dependsOn );
+		} catch ( TechGraphException e ) {
+			throw new TechGraphException( Code.MISSING_DEPENDENCY );
+		}
+
+		if ( technology.equals( dependsOn ) || dep.hasDependency( technology ) ) {
+			throw new TechGraphException( Code.RECURSIVE_DEPENDENCY );
+		}
+		if ( tech.hasDependency( dependsOn ) ) {
+			throw new TechGraphException( Code.DUPLICATE_DEPENDENCY );
+		}
+
+		tech.addDependency( dep );
+	}
+
+
+	/**
+	 * Remove a dependency from a technology's definition.
+	 * 
+	 * @param technology
+	 *            the name of the dependent technology
+	 * @param dependency
+	 *            the name of the dependency to remove
+	 * @throws TechGraphException
+	 *             with {@link TechGraphException.Code#MISSING_TECHNOLOGY} if the dependent
+	 *             technology does not exist or with
+	 *             {@link TechGraphException.Code#MISSING_DEPENDENCY} if the technology does not
+	 *             have the specified dependency.
+	 */
+	public void removeDependency( String technology , String dependency )
+			throws TechGraphException
+	{
+		Technology tech = this.getTechnology( technology );
+		if ( !tech.hasDirectDependency( dependency ) ) {
+			throw new TechGraphException( Code.MISSING_DEPENDENCY );
+		}
+		tech.removeDependency( dependency );
+	}
+
+
+	/**
+	 * Delete a technology's definition.
+	 * 
+	 * @param technology
+	 *            the name of the technology to delete.
+	 * @throws TechGraphException
+	 *             with {@link TechGraphException.Code#MISSING_TECHNOLOGY} if the technology does
+	 *             not exist or with {@link TechGraphException.Code#DEPENDENCY_ERROR} if other
+	 *             technologies depend on the technology to delete.
+	 */
+	public void deleteTechnology( String technology )
+			throws TechGraphException
+	{
+		Technology tech = this.getTechnology( technology );
+		if ( tech.hasReverseDependencies( ) ) {
+			throw new TechGraphException( Code.DEPENDENCY_ERROR );
+		}
+
+		tech.delete( );
+		this.techsByName.remove( technology );
+		this.technologies.remove( tech );
+	}
+
+}
diff --git a/legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/techs/TechGraphException.java b/legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/techs/TechGraphException.java
new file mode 100644
index 0000000..12cf534
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/techs/TechGraphException.java
@@ -0,0 +1,69 @@
+package com.deepclone.lw.sqld.game.techs;
+
+
+/**
+ * Exceptions thrown by the {@link TechGraph} class when operations on the graph would result in an
+ * incorrect graph.
+ * 
+ * @author tseeker
+ * 
+ */
+@SuppressWarnings( "serial" )
+public class TechGraphException
+		extends Exception
+{
+
+	/** Error codes associated with tech graph exceptions */
+	public static enum Code {
+		/** Trying to add a duplicate category */
+		DUPLICATE_CATEGORY ,
+
+		/** Trying to access a category that does not exist */
+		MISSING_CATEGORY ,
+
+		/** Trying to delete a category or technology on which other technologies depend */
+		DEPENDENCY_ERROR ,
+
+		/** Trying to add a duplicate technology */
+		DUPLICATE_TECHNOLOGY ,
+
+		/** Trying to access a technology that does not exist */
+		MISSING_TECHNOLOGY ,
+
+		/** Trying to access a dependency that does not exist */
+		MISSING_DEPENDENCY ,
+
+		/** Trying to add a recursive dependency */
+		RECURSIVE_DEPENDENCY ,
+
+		/**
+		 * Trying to add a dependency that is already present (whether directly or through other
+		 * dependencies)
+		 */
+		DUPLICATE_DEPENDENCY ,
+	}
+
+	/** Error code for the exception */
+	private final Code code;
+
+
+	public TechGraphException( Code code )
+	{
+		super( code.toString( ) );
+		this.code = code;
+	}
+
+
+	public TechGraphException( Code code , String identifier )
+	{
+		super( code.toString( ) + " : " + identifier );
+		this.code = code;
+	}
+
+
+	public Code getCode( )
+	{
+		return code;
+	}
+
+}
diff --git a/legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/techs/Technology.java b/legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/techs/Technology.java
new file mode 100644
index 0000000..eda341b
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/game/techs/Technology.java
@@ -0,0 +1,285 @@
+package com.deepclone.lw.sqld.game.techs;
+
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+
+
+/**
+ * Representation of a technology from the technology graph.
+ * 
+ * @author tseeker
+ */
+public class Technology
+{
+
+	/** The string identifier of the technology's name */
+	private final String name;
+
+	/** The category the technology belongs to */
+	private Category category;
+
+	/** The string identifier of the technology's description */
+	private String description;
+
+	/** The amount of research points required before the technology can be implemented */
+	private double points;
+
+	/** The cost of implementing the technology */
+	private double cost;
+
+	/** Map of technologies the current technology depends on */
+	private final Map< String , Technology > dependencies;
+
+	/** Map of technologies that depend on the current technology */
+	private final Map< String , Technology > dependencyOf;
+
+	/** Names of all technologies the current technology depends on, whether directly or indirectly. */
+	private Set< String > fullDependencies;
+
+
+	/**
+	 * Initialise the technology's record. This method is meant to be called from
+	 * {@link Category#addTechnology(String, String, int, int)}.
+	 * 
+	 * @param category
+	 *            the category the technology belongs to
+	 * @param name
+	 *            string identifier of the technology's name
+	 * @param description
+	 *            string identifier of the technology's description
+	 * @param points
+	 *            amount of research points required before the technology can be implemented
+	 * @param cost
+	 *            cost of implementing the technology
+	 */
+	Technology( Category category , String name , String description , double points , double cost )
+	{
+		this.category = category;
+		this.name = name;
+		this.description = description;
+		this.points = points;
+		this.cost = cost;
+		this.dependencies = new HashMap< String , Technology >( );
+		this.dependencyOf = new HashMap< String , Technology >( );
+	}
+
+
+	/**
+	 * Create a partial copy of an existing technology. Dependencies will not be copied as they need
+	 * to be resolved after a full graph copy has been performed.
+	 * 
+	 * @param tech
+	 *            the technology to copy
+	 */
+	Technology( Technology tech )
+	{
+		this.category = tech.category;
+		this.name = tech.name;
+		this.description = tech.description;
+		this.points = tech.points;
+		this.cost = tech.cost;
+		this.dependencies = new HashMap< String , Technology >( );
+		this.dependencyOf = new HashMap< String , Technology >( );
+	}
+
+
+	/**
+	 * Check if the technology depends on another, whether directly or indirectly.
+	 * 
+	 * @param technology
+	 *            the name of the dependency to look for
+	 * @return <code>true</code> if the current technology depends on the specified technology,
+	 *         <code>false</code> otherwise
+	 */
+	public boolean hasDependency( String technology )
+	{
+		if ( this.fullDependencies == null ) {
+			this.buildDependencies( );
+		}
+		return this.fullDependencies.contains( technology );
+	}
+
+
+	/**
+	 * Build the contents of the {@link #fullDependencies} property based on the list of direct
+	 * dependencies.
+	 */
+	private void buildDependencies( )
+	{
+		Set< String > deps = new HashSet< String >( );
+		for ( Technology dep : this.dependencies.values( ) ) {
+			deps.add( dep.name );
+			if ( dep.fullDependencies == null ) {
+				dep.buildDependencies( );
+			}
+			deps.addAll( dep.fullDependencies );
+		}
+		this.fullDependencies = deps;
+	}
+
+
+	/**
+	 * Check if the current technology has another technology in its list of direct dependencies.
+	 * 
+	 * @param dependency
+	 *            the dependency to look for
+	 * @return <code>true</code> if the current technology depends on the specified technology
+	 *         directly, <code>false</code> otherwise.
+	 */
+	public boolean hasDirectDependency( String dependency )
+	{
+		return this.dependencies.containsKey( dependency );
+	}
+
+
+	/**
+	 * Check if there are technologies which depend on the current technology.
+	 * 
+	 * @return <code>true</code> if at least one technology depends on the current technology,
+	 *         <code>false</code> otherwise.
+	 */
+	public boolean hasReverseDependencies( )
+	{
+		return !this.dependencyOf.isEmpty( );
+	}
+
+
+	/**
+	 * Add a new dependency to the current technology.
+	 * 
+	 * @param dep
+	 *            the dependency to add
+	 */
+	void addDependency( Technology dep )
+	{
+		this.dependencies.put( dep.name , dep );
+		dep.dependencyOf.put( this.name , this );
+		this.fullDependencies = null;
+	}
+
+
+	/**
+	 * Remove an existing dependency from the current technology.
+	 * 
+	 * @param dependency
+	 *            the name of the dependency to remove
+	 */
+	void removeDependency( String dependency )
+	{
+		Technology dep = this.dependencies.get( dependency );
+		dep.dependencyOf.remove( this.name );
+		this.dependencies.remove( dependency );
+		this.fullDependencies = null;
+	}
+
+
+	/** @return the list of technology names the current technology directly depends on */
+	public List< String > getDependencies( )
+	{
+		return new LinkedList< String >( this.dependencies.keySet( ) );
+	}
+
+
+	/**
+	 * Delete the current technology, removing it from the reverse dependency lists of its
+	 * dependencies and from its category.
+	 */
+	void delete( )
+	{
+		List< String > deps = new LinkedList< String >( this.dependencies.keySet( ) );
+		for ( String dep : deps ) {
+			this.removeDependency( dep );
+		}
+		this.category.removeTechnology( this );
+	}
+
+
+	/** @return the string identifier of the technology's name */
+	public String getName( )
+	{
+		return this.name;
+	}
+
+
+	/** @return the category the technology belongs to. */
+	public Category getCategory( )
+	{
+		return category;
+	}
+
+
+	/** @return the string identifier of the technology's description */
+	public String getDescription( )
+	{
+		return description;
+	}
+
+
+	/**
+	 * Update the technology's category
+	 * 
+	 * @param category
+	 *            the new category
+	 */
+	void setCategory( Category category )
+	{
+		this.category = category;
+	}
+
+
+	/**
+	 * Update the string identifier of the technology's description
+	 * 
+	 * @param description
+	 *            the new description string ID
+	 */
+	void setDescription( String description )
+	{
+		this.description = description;
+	}
+
+
+	/** @return the amount of research points required to implement the technology */
+	public double getPoints( )
+	{
+		return points;
+	}
+
+
+	/**
+	 * Update the amount of research points required to implement the technology.
+	 * 
+	 * @param points
+	 *            the new amount of points
+	 */
+	void setPoints( int points )
+	{
+		this.points = points;
+	}
+
+
+	/** @return the implementation cost */
+	public double getCost( )
+	{
+		return cost;
+	}
+
+
+	/**
+	 * Update the implementation cost.
+	 * 
+	 * @param cost
+	 *            the new implementation cost.
+	 */
+	void setCost( int cost )
+	{
+		this.cost = cost;
+	}
+
+}
diff --git a/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/i18n/Translation.java b/legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/i18n/Translation.java
similarity index 100%
rename from legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/i18n/Translation.java
rename to legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/i18n/Translation.java
diff --git a/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/msgs/AdminEventRecord.java b/legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/msgs/AdminEventRecord.java
similarity index 100%
rename from legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/msgs/AdminEventRecord.java
rename to legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/msgs/AdminEventRecord.java
diff --git a/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/msgs/AllianceEventRecord.java b/legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/msgs/AllianceEventRecord.java
similarity index 100%
rename from legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/msgs/AllianceEventRecord.java
rename to legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/msgs/AllianceEventRecord.java
diff --git a/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/msgs/BugEventRecord.java b/legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/msgs/BugEventRecord.java
similarity index 100%
rename from legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/msgs/BugEventRecord.java
rename to legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/msgs/BugEventRecord.java
diff --git a/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/msgs/EmpireEventRecord.java b/legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/msgs/EmpireEventRecord.java
similarity index 100%
rename from legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/msgs/EmpireEventRecord.java
rename to legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/msgs/EmpireEventRecord.java
diff --git a/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/msgs/EventRecord.java b/legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/msgs/EventRecord.java
similarity index 100%
rename from legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/msgs/EventRecord.java
rename to legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/msgs/EventRecord.java
diff --git a/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/msgs/EventType.java b/legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/msgs/EventType.java
similarity index 100%
rename from legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/msgs/EventType.java
rename to legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/msgs/EventType.java
diff --git a/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/msgs/EventTypeRecord.java b/legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/msgs/EventTypeRecord.java
similarity index 100%
rename from legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/msgs/EventTypeRecord.java
rename to legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/msgs/EventTypeRecord.java
diff --git a/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/msgs/FleetEventFleet.java b/legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/msgs/FleetEventFleet.java
similarity index 100%
rename from legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/msgs/FleetEventFleet.java
rename to legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/msgs/FleetEventFleet.java
diff --git a/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/msgs/FleetEventRecord.java b/legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/msgs/FleetEventRecord.java
similarity index 100%
rename from legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/msgs/FleetEventRecord.java
rename to legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/msgs/FleetEventRecord.java
diff --git a/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/msgs/FormatType.java b/legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/msgs/FormatType.java
similarity index 100%
rename from legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/msgs/FormatType.java
rename to legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/msgs/FormatType.java
diff --git a/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/msgs/InboxRecord.java b/legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/msgs/InboxRecord.java
similarity index 100%
rename from legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/msgs/InboxRecord.java
rename to legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/msgs/InboxRecord.java
diff --git a/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/msgs/MessageDataRecord.java b/legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/msgs/MessageDataRecord.java
similarity index 100%
rename from legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/msgs/MessageDataRecord.java
rename to legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/msgs/MessageDataRecord.java
diff --git a/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/msgs/NotificationsRecord.java b/legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/msgs/NotificationsRecord.java
similarity index 100%
rename from legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/msgs/NotificationsRecord.java
rename to legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/msgs/NotificationsRecord.java
diff --git a/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/msgs/PlanetEventRecord.java b/legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/msgs/PlanetEventRecord.java
similarity index 100%
rename from legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/msgs/PlanetEventRecord.java
rename to legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/msgs/PlanetEventRecord.java
diff --git a/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/msgs/QueueEventLocation.java b/legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/msgs/QueueEventLocation.java
similarity index 100%
rename from legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/msgs/QueueEventLocation.java
rename to legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/msgs/QueueEventLocation.java
diff --git a/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/msgs/QueueEventRecord.java b/legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/msgs/QueueEventRecord.java
similarity index 100%
rename from legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/msgs/QueueEventRecord.java
rename to legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/msgs/QueueEventRecord.java
diff --git a/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/msgs/TextMessageRecord.java b/legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/msgs/TextMessageRecord.java
similarity index 100%
rename from legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/msgs/TextMessageRecord.java
rename to legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/msgs/TextMessageRecord.java
diff --git a/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/sys/Constant.java b/legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/sys/Constant.java
similarity index 84%
rename from legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/sys/Constant.java
rename to legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/sys/Constant.java
index 971b5ef..7d184eb 100644
--- a/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/sys/Constant.java
+++ b/legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/sys/Constant.java
@@ -71,13 +71,6 @@ public class Constant
 	}
 
 
-	public void setMinValue( Float minValue )
-	{
-
-		this.minValue = ( minValue == null ? null : minValue.doubleValue( ) );
-	}
-
-
 	public Double getMaxValue( )
 	{
 		return maxValue;
@@ -90,13 +83,6 @@ public class Constant
 	}
 
 
-	public void setMaxValue( Float maxValue )
-	{
-
-		this.maxValue = ( maxValue == null ? null : maxValue.doubleValue( ) );
-	}
-
-
 	public double getValue( )
 	{
 		return value;
diff --git a/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/sys/ExceptionLog.java b/legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/sys/ExceptionLog.java
similarity index 100%
rename from legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/sys/ExceptionLog.java
rename to legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/sys/ExceptionLog.java
diff --git a/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/sys/StackTraceLog.java b/legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/sys/StackTraceLog.java
similarity index 100%
rename from legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/sys/StackTraceLog.java
rename to legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/sys/StackTraceLog.java
diff --git a/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/sys/Status.java b/legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/sys/Status.java
similarity index 100%
rename from legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/sys/Status.java
rename to legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/sys/Status.java
diff --git a/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/sys/SystemLogEntry.java b/legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/sys/SystemLogEntry.java
similarity index 100%
rename from legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/sys/SystemLogEntry.java
rename to legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/sys/SystemLogEntry.java
diff --git a/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/sys/TickerTaskRecord.java b/legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/sys/TickerTaskRecord.java
similarity index 100%
rename from legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/sys/TickerTaskRecord.java
rename to legacyworlds-server/legacyworlds-server-data/src/main/java/com/deepclone/lw/sqld/sys/TickerTaskRecord.java
diff --git a/legacyworlds-server/legacyworlds-server-data/src/main/resources/configuration/transaction-bean.xml b/legacyworlds-server/legacyworlds-server-data/src/main/resources/configuration/transaction-bean.xml
new file mode 100644
index 0000000..6cf7b29
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-data/src/main/resources/configuration/transaction-bean.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xmlns:tx="http://www.springframework.org/schema/tx"
+	xsi:schemaLocation="
+                        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
+                        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
+
+	<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
+		<property name="dataSource" ref="dataSource" />
+	</bean>
+
+	<tx:annotation-driven transaction-manager="transactionManager"/>
+
+</beans>
diff --git a/legacyworlds-server/legacyworlds-server-interfaces/.classpath b/legacyworlds-server/legacyworlds-server-interfaces/.classpath
new file mode 100644
index 0000000..7c3d14f
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-interfaces/.classpath
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" output="target/classes" path="src/main/java"/>
+	<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources"/>
+	<classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
+	<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+	<classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER"/>
+	<classpathentry kind="output" path="target/classes"/>
+</classpath>
diff --git a/legacyworlds-server/legacyworlds-server-interfaces/.project b/legacyworlds-server/legacyworlds-server-interfaces/.project
new file mode 100644
index 0000000..25a4794
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-interfaces/.project
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>legacyworlds-server-interfaces</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.maven.ide.eclipse.maven2Builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.maven.ide.eclipse.maven2Nature</nature>
+	</natures>
+</projectDescription>
diff --git a/legacyworlds-server/legacyworlds-server-interfaces/.settings/org.eclipse.jdt.core.prefs b/legacyworlds-server/legacyworlds-server-interfaces/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..847aea3
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-interfaces/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,6 @@
+#Fri Apr 09 10:20:04 CEST 2010
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.6
diff --git a/legacyworlds-server-interfaces/pom.xml b/legacyworlds-server/legacyworlds-server-interfaces/pom.xml
similarity index 74%
rename from legacyworlds-server-interfaces/pom.xml
rename to legacyworlds-server/legacyworlds-server-interfaces/pom.xml
index 4581833..d8b5772 100644
--- a/legacyworlds-server-interfaces/pom.xml
+++ b/legacyworlds-server/legacyworlds-server-interfaces/pom.xml
@@ -4,24 +4,26 @@
 	<parent>
 		<artifactId>legacyworlds-server</artifactId>
 		<groupId>com.deepclone.lw</groupId>
-		<version>1.0.0</version>
-		<relativePath>../legacyworlds-server/pom.xml</relativePath>
+		<version>5.99.2</version>
 	</parent>
 
+	<groupId>com.deepclone.lw</groupId>
 	<artifactId>legacyworlds-server-interfaces</artifactId>
-	<version>${legacyworlds.version.main}.${legacyworlds.version.release}-${legacyworlds.version.build}</version>
+	<version>5.99.2</version>
 
-	<name>Legacy Worlds - Server - Component interfaces</name>
+	<name>Legacy Worlds server interfaces</name>
 	<description>This package contains interfaces for all beans provided by the various server components.</description>
 
 	<dependencies>
 		<dependency>
 			<groupId>com.deepclone.lw</groupId>
 			<artifactId>legacyworlds-server-data</artifactId>
+			<version>${project.version}</version>
 		</dependency>
 		<dependency>
 			<groupId>com.deepclone.lw</groupId>
 			<artifactId>legacyworlds-server-utils</artifactId>
+			<version>${project.version}</version>
 		</dependency>
 	</dependencies>
-</project>
+</project>
\ No newline at end of file
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/acm/AccountMailException.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/acm/AccountMailException.java
similarity index 100%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/acm/AccountMailException.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/acm/AccountMailException.java
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/acm/AccountManagement.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/acm/AccountManagement.java
similarity index 100%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/acm/AccountManagement.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/acm/AccountManagement.java
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/acm/AccountSession.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/acm/AccountSession.java
similarity index 100%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/acm/AccountSession.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/acm/AccountSession.java
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/acm/EmailChangeException.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/acm/EmailChangeException.java
similarity index 100%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/acm/EmailChangeException.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/acm/EmailChangeException.java
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/acm/JoinGameException.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/acm/JoinGameException.java
similarity index 100%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/acm/JoinGameException.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/acm/JoinGameException.java
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/acm/PasswordProhibitedException.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/acm/PasswordProhibitedException.java
similarity index 100%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/acm/PasswordProhibitedException.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/acm/PasswordProhibitedException.java
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/acm/PasswordRecoveryException.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/acm/PasswordRecoveryException.java
similarity index 100%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/acm/PasswordRecoveryException.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/acm/PasswordRecoveryException.java
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/acm/PermanentlyDisabledException.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/acm/PermanentlyDisabledException.java
similarity index 100%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/acm/PermanentlyDisabledException.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/acm/PermanentlyDisabledException.java
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/acm/UserSessionDAO.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/acm/UserSessionDAO.java
similarity index 100%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/acm/UserSessionDAO.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/acm/UserSessionDAO.java
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/acm/UsersDAO.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/acm/UsersDAO.java
similarity index 100%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/acm/UsersDAO.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/acm/UsersDAO.java
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/admin/AdminDAO.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/admin/AdminDAO.java
similarity index 100%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/admin/AdminDAO.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/admin/AdminDAO.java
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/admin/AdminDAOException.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/admin/AdminDAOException.java
similarity index 100%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/admin/AdminDAOException.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/admin/AdminDAOException.java
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/admin/Administration.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/admin/Administration.java
similarity index 100%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/admin/Administration.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/admin/Administration.java
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/admin/BanMailData.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/admin/BanMailData.java
similarity index 100%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/admin/BanMailData.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/admin/BanMailData.java
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/admin/BansDAO.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/admin/BansDAO.java
similarity index 100%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/admin/BansDAO.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/admin/BansDAO.java
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/admin/IpBan.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/admin/IpBan.java
similarity index 100%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/admin/IpBan.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/admin/IpBan.java
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/bt/AdminBugs.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/bt/AdminBugs.java
similarity index 100%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/bt/AdminBugs.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/bt/AdminBugs.java
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/bt/BugsDAO.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/bt/BugsDAO.java
similarity index 100%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/bt/BugsDAO.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/bt/BugsDAO.java
diff --git a/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/bt/EmpireSummary.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/bt/EmpireSummary.java
new file mode 100644
index 0000000..bd09629
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/bt/EmpireSummary.java
@@ -0,0 +1,9 @@
+package com.deepclone.lw.interfaces.bt;
+
+
+public interface EmpireSummary
+{
+
+	public String getSummary( int empireId );
+
+}
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/bt/PlayerBugs.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/bt/PlayerBugs.java
similarity index 100%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/bt/PlayerBugs.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/bt/PlayerBugs.java
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/eventlog/ExtendedLogEntry.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/eventlog/ExtendedLogEntry.java
similarity index 100%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/eventlog/ExtendedLogEntry.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/eventlog/ExtendedLogEntry.java
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/eventlog/LogReader.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/eventlog/LogReader.java
similarity index 100%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/eventlog/LogReader.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/eventlog/LogReader.java
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/eventlog/LogWriter.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/eventlog/LogWriter.java
similarity index 100%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/eventlog/LogWriter.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/eventlog/LogWriter.java
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/eventlog/Logger.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/eventlog/Logger.java
similarity index 100%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/eventlog/Logger.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/eventlog/Logger.java
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/eventlog/SystemLogger.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/eventlog/SystemLogger.java
similarity index 100%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/eventlog/SystemLogger.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/eventlog/SystemLogger.java
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/AllianceDAO.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/AllianceDAO.java
similarity index 100%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/AllianceDAO.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/AllianceDAO.java
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/AllianceManagement.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/AllianceManagement.java
similarity index 100%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/AllianceManagement.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/AllianceManagement.java
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/BattleViewer.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/BattleViewer.java
similarity index 100%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/BattleViewer.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/BattleViewer.java
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/BattlesCache.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/BattlesCache.java
similarity index 100%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/BattlesCache.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/BattlesCache.java
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/BattlesDAO.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/BattlesDAO.java
similarity index 100%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/BattlesDAO.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/BattlesDAO.java
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/EmpireDAO.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/EmpireDAO.java
similarity index 100%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/EmpireDAO.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/EmpireDAO.java
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/EmpireManagement.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/EmpireManagement.java
similarity index 74%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/EmpireManagement.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/EmpireManagement.java
index 26c27d6..bf4d1b3 100644
--- a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/EmpireManagement.java
+++ b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/EmpireManagement.java
@@ -6,6 +6,7 @@ import com.deepclone.lw.cmd.player.ListPlanetsResponse;
 import com.deepclone.lw.cmd.player.EmpireResponse;
 import com.deepclone.lw.cmd.player.elist.EnemyListResponse;
 import com.deepclone.lw.cmd.player.gdata.GamePageData;
+import com.deepclone.lw.interfaces.i18n.LanguageTranslator;
 import com.deepclone.lw.utils.EmailAddress;
 
 
@@ -19,6 +20,16 @@ public interface EmpireManagement
 	public GamePageData getGeneralInformation( int empireId );
 
 
+	/**
+	 * Generate a translation interface in the language used by the account who controls an empire.
+	 * 
+	 * @param empireId
+	 *            the empire's identifier
+	 * @return the translation interface
+	 */
+	public LanguageTranslator getTranslator( int empireId );
+
+
 	public EmpireResponse getOverview( int empireId );
 
 
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/FleetManagement.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/FleetManagement.java
similarity index 100%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/FleetManagement.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/FleetManagement.java
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/FleetsDAO.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/FleetsDAO.java
similarity index 100%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/FleetsDAO.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/FleetsDAO.java
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/MapViewParameters.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/MapViewParameters.java
similarity index 100%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/MapViewParameters.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/MapViewParameters.java
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/MapViewer.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/MapViewer.java
similarity index 100%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/MapViewer.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/MapViewer.java
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/PlanetDAO.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/PlanetDAO.java
similarity index 100%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/PlanetDAO.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/PlanetDAO.java
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/PlanetsManagement.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/PlanetsManagement.java
similarity index 100%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/PlanetsManagement.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/PlanetsManagement.java
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/UniverseDAO.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/UniverseDAO.java
similarity index 100%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/UniverseDAO.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/UniverseDAO.java
diff --git a/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/techs/EmpireTechnologyDAO.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/techs/EmpireTechnologyDAO.java
new file mode 100644
index 0000000..0274fac
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/techs/EmpireTechnologyDAO.java
@@ -0,0 +1,74 @@
+package com.deepclone.lw.interfaces.game.techs;
+
+
+import java.util.List;
+import java.util.Map;
+
+import com.deepclone.lw.sqld.game.techs.EmpireTechnology;
+
+
+
+/**
+ * Interface for the empire technology and research data access component.
+ * 
+ * @author tseeker
+ */
+public interface EmpireTechnologyDAO
+{
+	/**
+	 * List the technologies (implemented, researched and being researched) for the empire.
+	 * 
+	 * @param empireId
+	 *            the empire's identifier.
+	 * @return the list of technology records for the empire.
+	 */
+	public List< EmpireTechnology > getTechnologies( int empireId );
+
+
+	/**
+	 * Implement a technology for an empire.
+	 * 
+	 * @param empireId
+	 *            the empire's identifier
+	 * @param technology
+	 *            the technology's name
+	 * @return an error code:
+	 *         <ul>
+	 *         <li>0 on success,</li>
+	 *         <li>1 if the technology does not exist or is not in the correct status,</li>
+	 *         <li>2 if the empire does not have sufficient resources.</li>
+	 *         </ul>
+	 */
+	public int implementTechnology( int empireId , String technology );
+
+
+	/**
+	 * Prepare the temporary table used for a research priorities update.
+	 */
+	public void startPrioritiesUpdate( );
+
+
+	/**
+	 * Upload new research priority values into the temporary table used for priority updates.
+	 * 
+	 * @param priorities
+	 *            the map associating relative technology identifiers with priority values
+	 */
+	public void uploadPriorities( Map< String , Integer > priorities );
+
+
+	/**
+	 * Execute prepared research priority updates for an empire.
+	 * 
+	 * @param empireId
+	 *            the empire's identifier
+	 * @return an error code:
+	 *         <ul>
+	 *         <li>0 on success,</li>
+	 *         <li>1 if the listed technologies do not match the empire's current research,</li>
+	 *         <li>2 if the new priorities were invalid.</li>
+	 *         </ul>
+	 */
+	public int finishPrioritiesUpdate( int empireId );
+
+}
diff --git a/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/techs/EmpireTechnologyManager.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/techs/EmpireTechnologyManager.java
new file mode 100644
index 0000000..ac71688
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/techs/EmpireTechnologyManager.java
@@ -0,0 +1,53 @@
+package com.deepclone.lw.interfaces.game.techs;
+
+
+import java.util.Map;
+
+import com.deepclone.lw.cmd.player.research.ResearchOperationResponse;
+import com.deepclone.lw.cmd.player.research.ViewResearchResponse;
+
+
+
+/**
+ * Interface for the empire research and technology management component.
+ * 
+ * @author tseeker
+ */
+public interface EmpireTechnologyManager
+{
+
+	/**
+	 * Generate the response to a research view request.
+	 * 
+	 * @param empireId
+	 *            the empire for whom the research view is being displayed.
+	 * @return the response containing the view
+	 */
+	public ViewResearchResponse getResearchData( int empireId );
+
+
+	/**
+	 * Implement a technology for an empire.
+	 * 
+	 * @param empireId
+	 *            the empire trying to implement a technology.
+	 * @param technology
+	 *            the name of the technology to implement
+	 * 
+	 * @return the response describing the result of the operation
+	 */
+	public ResearchOperationResponse implementTechnology( int empireId , String technology );
+
+
+	/**
+	 * Set an empire's research priorities.
+	 * 
+	 * @param empireId
+	 *            the empire trying to set its research priorities.
+	 * @param priorities
+	 *            a map associating relative technology identifiers to priorities.
+	 * 
+	 * @return the response describing the result of the operation
+	 */
+	public ResearchOperationResponse setResearchPriorities( int empireId , Map< String , Integer > priorities );
+}
diff --git a/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/techs/ResearchUpdateDAO.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/techs/ResearchUpdateDAO.java
new file mode 100644
index 0000000..4b8537b
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/techs/ResearchUpdateDAO.java
@@ -0,0 +1,56 @@
+package com.deepclone.lw.interfaces.game.techs;
+
+
+import java.util.List;
+import java.util.Map;
+
+import com.deepclone.lw.sqld.game.techs.ResearchUpdateInput;
+import com.deepclone.lw.sqld.game.techs.ResearchUpdateOutput;
+
+
+
+/**
+ * Data access component for research updates.
+ * 
+ * @author tseeker
+ */
+public interface ResearchUpdateDAO
+{
+
+	/**
+	 * Prepare the database for a research update batch.
+	 * 
+	 * @param updateId
+	 *            the current update's identifier
+	 */
+	public void prepareUpdate( long updateId );
+
+
+	/**
+	 * Access the update's information.
+	 * 
+	 * @param updateId
+	 *            the current update's identifier
+	 * @return the current research status for the empires in the current batch.
+	 */
+	public List< ResearchUpdateInput > getUpdateData( long updateId );
+
+
+	/**
+	 * Load the amount of research points for each empire in the update.
+	 * 
+	 * @param updateId
+	 *            the current update's identifier.
+	 * @return a map which associates empire identifiers to amounts of research points.
+	 */
+	public Map< Integer , Double > getResearchPoints( long updateId );
+
+
+	/**
+	 * Submit the output of the research update.
+	 * 
+	 * @param output
+	 *            a list of changes to commit to the database
+	 */
+	public void submitUpdateData( List< ResearchUpdateOutput > output );
+}
diff --git a/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/techs/TechnologyGraphDAO.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/techs/TechnologyGraphDAO.java
new file mode 100644
index 0000000..9ce624e
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/techs/TechnologyGraphDAO.java
@@ -0,0 +1,27 @@
+package com.deepclone.lw.interfaces.game.techs;
+
+
+import com.deepclone.lw.sqld.game.techs.TechGraph;
+import com.deepclone.lw.sqld.game.techs.TechGraphException;
+
+
+
+/**
+ * Data access component for the technology graph.
+ * 
+ * @author tseeker
+ */
+public interface TechnologyGraphDAO
+{
+
+	/**
+	 * Load the technology graph from the database.
+	 * 
+	 * @return the technology graph's representation
+	 * @throws TechGraphException
+	 *             if some logic error occurs while the graph is being loaded (for example, circular
+	 *             dependencies).
+	 */
+	public TechGraph loadGraph( )
+			throws TechGraphException;
+}
diff --git a/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/techs/TechnologyGraphManager.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/techs/TechnologyGraphManager.java
new file mode 100644
index 0000000..3fcefa3
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/techs/TechnologyGraphManager.java
@@ -0,0 +1,36 @@
+package com.deepclone.lw.interfaces.game.techs;
+
+
+import java.util.List;
+
+import com.deepclone.lw.cmd.admin.techs.TechCategory;
+import com.deepclone.lw.sqld.game.techs.TechGraph;
+
+
+
+/**
+ * Interface for the technology graph manager, which allows queries on the technology graph, as well
+ * as updates.
+ * 
+ * @author tseeker
+ */
+public interface TechnologyGraphManager
+{
+
+	/**
+	 * Access a copy of the tech graph as it exists in the server's memory. This copy includes all
+	 * local changes.
+	 * 
+	 * @return a copy of the tech graph
+	 */
+	public TechGraph getGraph( );
+
+
+	/**
+	 * List all technology categories from the tech graph.
+	 * 
+	 * @return the list of technology categories
+	 */
+	public List< TechCategory > listCategories( );
+
+}
diff --git a/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/updates/DuplicateUpdateHandler.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/updates/DuplicateUpdateHandler.java
new file mode 100644
index 0000000..9df38a5
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/updates/DuplicateUpdateHandler.java
@@ -0,0 +1,30 @@
+package com.deepclone.lw.interfaces.game.updates;
+
+
+/**
+ * Runtime exception indicating a duplicate game update phase handler registration.
+ * 
+ * @author tseeker
+ */
+public class DuplicateUpdateHandler
+		extends RuntimeException
+{
+
+	private static final long serialVersionUID = 1L;
+
+	private final GameUpdatePhase phase;
+
+
+	public DuplicateUpdateHandler( GameUpdatePhase phase )
+	{
+		super( "duplicate handler for phase " + phase.toString( ) );
+		this.phase = phase;
+	}
+
+
+	public GameUpdatePhase getPhase( )
+	{
+		return phase;
+	}
+
+}
diff --git a/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/updates/GameUpdate.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/updates/GameUpdate.java
new file mode 100644
index 0000000..db8d796
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/updates/GameUpdate.java
@@ -0,0 +1,25 @@
+package com.deepclone.lw.interfaces.game.updates;
+
+
+/**
+ * Interface to the main game update component.
+ * 
+ * @author tseeker
+ */
+public interface GameUpdate
+{
+
+	/**
+	 * Register a handler component for a game update phase.
+	 * 
+	 * @param handler
+	 *            the handler to register
+	 * 
+	 * @throws DuplicateUpdateHandler
+	 *             if a handler has already been registered for the game update phase returned by
+	 *             the new handler's {@link GameUpdatePhaseHandler#getPhase()} method.
+	 */
+	public void registerHandler( GameUpdatePhaseHandler handler )
+			throws DuplicateUpdateHandler;
+
+}
diff --git a/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/updates/GameUpdatePhase.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/updates/GameUpdatePhase.java
new file mode 100644
index 0000000..9e49fa0
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/updates/GameUpdatePhase.java
@@ -0,0 +1,69 @@
+package com.deepclone.lw.interfaces.game.updates;
+
+
+/**
+ * The various phases of a game update. This enumeration should reflect the <em>update_type</em> SQL
+ * type.
+ * 
+ * @author tseeker
+ */
+public enum GameUpdatePhase {
+
+	/** Empire income and upkeep computation */
+	EMPIRE_MONEY( GameUpdateTarget.EMPIRE ) ,
+
+	/** Empire research update */
+	EMPIRE_RESEARCH( GameUpdateTarget.EMPIRE ) ,
+
+	/** Debt effects computation */
+	EMPIRE_DEBT( GameUpdateTarget.EMPIRE ) ,
+
+	/** Arrival of fleets on planets */
+	PLANET_FLEET_ARRIVALS( GameUpdateTarget.PLANET ) ,
+
+	/** Fleet movement computation */
+	PLANET_FLEET_MOVEMENTS( GameUpdateTarget.PLANET ) ,
+
+	/** Fleet status counter decrease */
+	PLANET_FLEET_STATUS( GameUpdateTarget.PLANET ) ,
+
+	/** Check for new battles */
+	PLANET_BATTLE_START( GameUpdateTarget.PLANET ) ,
+
+	/** Main battle computation */
+	PLANET_BATTLE_MAIN( GameUpdateTarget.PLANET ) ,
+
+	/** Check for battles that have ended */
+	PLANET_BATTLE_END( GameUpdateTarget.PLANET ) ,
+
+	/** Abandon planets */
+	PLANET_ABANDON( GameUpdateTarget.PLANET ) ,
+
+	/** Construct/destroy buildings */
+	PLANET_CONSTRUCTION( GameUpdateTarget.PLANET ) ,
+
+	/** Construct/destroy ships */
+	PLANET_MILITARY( GameUpdateTarget.PLANET ) ,
+
+	/** Update planetary population */
+	PLANET_POPULATION( GameUpdateTarget.PLANET ) ,
+
+	/** Compute planet income */
+	PLANET_MONEY( GameUpdateTarget.PLANET );
+
+	private final GameUpdateTarget target;
+
+
+	private GameUpdatePhase( GameUpdateTarget target )
+	{
+		this.target = target;
+	}
+
+
+	/** @return the type of target affected by the update */
+	public GameUpdateTarget getTarget( )
+	{
+		return target;
+	}
+
+}
diff --git a/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/updates/GameUpdatePhaseHandler.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/updates/GameUpdatePhaseHandler.java
new file mode 100644
index 0000000..19ccf3e
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/updates/GameUpdatePhaseHandler.java
@@ -0,0 +1,40 @@
+package com.deepclone.lw.interfaces.game.updates;
+
+
+/**
+ * Interface for handlers that implement a phase of the game update.
+ * 
+ * @author tseeker
+ */
+public interface GameUpdatePhaseHandler
+{
+
+	/**
+	 * @return the game update phase this handler is responsible for.
+	 */
+	public GameUpdatePhase getPhase( );
+
+
+	/**
+	 * Prepare the handler.
+	 * 
+	 * This method is called outside of any transaction before the update starts.
+	 * 
+	 * @param updateId
+	 *            the update's identifier
+	 */
+	public void onPhaseStart( long updateId );
+
+
+	/**
+	 * Update the game.
+	 * 
+	 * @param updateId
+	 *            the update's identifier.
+	 * 
+	 * @return <code>true</code> if there are more updates of this type to process,
+	 *         <code>false</code> if the phase is complete
+	 */
+	public boolean updateGame( long updateId );
+
+}
diff --git a/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/updates/GameUpdateTarget.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/updates/GameUpdateTarget.java
new file mode 100644
index 0000000..4baf750
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/updates/GameUpdateTarget.java
@@ -0,0 +1,17 @@
+package com.deepclone.lw.interfaces.game.updates;
+
+
+/**
+ * The type of item targeted by a game update phase.
+ * 
+ * @author tseeker
+ */
+public enum GameUpdateTarget {
+
+	/** Empire update */
+	EMPIRE ,
+
+	/** Planet update */
+	PLANET
+
+}
diff --git a/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/updates/UpdatesDAO.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/updates/UpdatesDAO.java
new file mode 100644
index 0000000..8ee39da
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/updates/UpdatesDAO.java
@@ -0,0 +1,46 @@
+package com.deepclone.lw.interfaces.game.updates;
+
+
+/**
+ * Interface of the game update data access component.
+ * 
+ * @author tseeker
+ */
+public interface UpdatesDAO
+{
+
+	/**
+	 * Prepare a batch of game updates.
+	 * 
+	 * @param updateId
+	 *            game update identifier
+	 * @param phase
+	 *            phase of the update
+	 * 
+	 * @return <code>true</code> if there are game updates to process in the specified phase,
+	 *         <code>false</code> if all updates in the current phase have been handled.
+	 */
+	public boolean prepareUpdates( long updateId , GameUpdatePhase phase );
+
+
+	/**
+	 * Execute a game update phase that is implemented as a stored procedure.
+	 * 
+	 * @param updateId
+	 *            game update identifier
+	 * @param phase
+	 *            phase of the game update to execute
+	 */
+	public void executeProceduralUpdate( long updateId , GameUpdatePhase phase );
+
+
+	/**
+	 * Mark a set of update records as processed.
+	 * 
+	 * @param updateId
+	 *            game update identifier
+	 * @param phase
+	 *            current phase of the game update
+	 */
+	public void validateUpdatedRecords( long updateId , GameUpdatePhase phase );
+}
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/i18n/DuplicateLanguageException.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/i18n/DuplicateLanguageException.java
similarity index 100%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/i18n/DuplicateLanguageException.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/i18n/DuplicateLanguageException.java
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/i18n/DuplicateStringException.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/i18n/DuplicateStringException.java
similarity index 100%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/i18n/DuplicateStringException.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/i18n/DuplicateStringException.java
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/i18n/I18NAdministration.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/i18n/I18NAdministration.java
similarity index 100%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/i18n/I18NAdministration.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/i18n/I18NAdministration.java
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/i18n/I18NException.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/i18n/I18NException.java
similarity index 100%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/i18n/I18NException.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/i18n/I18NException.java
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/i18n/I18NManager.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/i18n/I18NManager.java
similarity index 100%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/i18n/I18NManager.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/i18n/I18NManager.java
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/i18n/InvalidUpdateException.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/i18n/InvalidUpdateException.java
similarity index 100%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/i18n/InvalidUpdateException.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/i18n/InvalidUpdateException.java
diff --git a/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/i18n/LanguageTranslator.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/i18n/LanguageTranslator.java
new file mode 100644
index 0000000..d7eb180
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/i18n/LanguageTranslator.java
@@ -0,0 +1,31 @@
+package com.deepclone.lw.interfaces.i18n;
+
+
+/**
+ * Translation interface specific to a language
+ * 
+ * @author tseeker
+ */
+public interface LanguageTranslator
+{
+
+	/** @return the code of the interface's language */
+	public String getLanguage( );
+
+
+	/** @return the name of the interface's language */
+	public String getLanguageName( );
+
+
+	/**
+	 * Translate a string.
+	 * 
+	 * @param string
+	 *            the string identifier
+	 * @return the string's translation in the interface's language
+	 * @throws UnknownStringException
+	 *             if the string does not exist
+	 */
+	public String translate( String string )
+			throws UnknownStringException;
+}
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/i18n/TranslationException.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/i18n/TranslationException.java
similarity index 100%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/i18n/TranslationException.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/i18n/TranslationException.java
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/i18n/Translator.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/i18n/Translator.java
similarity index 64%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/i18n/Translator.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/i18n/Translator.java
index 92ada50..1990617 100644
--- a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/i18n/Translator.java
+++ b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/i18n/Translator.java
@@ -1,8 +1,6 @@
 package com.deepclone.lw.interfaces.i18n;
 
 
-import java.util.Collection;
-import java.util.Map;
 import java.util.Set;
 
 
@@ -10,12 +8,12 @@ import java.util.Set;
 /**
  * Translator service interface
  * 
- * <p>
  * This interface defines the methods available on the Translator service. One such service should
  * be present on all nodes. All Translator service instances are managed by the I18NManager service,
  * which is shared between nodes and notifies Translator instances of database updates.
  * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
+ * @author tseeker
+ * 
  */
 public interface Translator
 {
@@ -67,25 +65,14 @@ public interface Translator
 
 
 	/**
-	 * Translate multiple strings based on their identifiers
-	 * 
-	 * <p>
-	 * This method must be implemented to allow "en masse" string translations. It will fetch the
-	 * translations in a given language for an arbitrary quantity of string identifiers, returning
-	 * the results as a map of identifiers to translations.
+	 * Initialise a translator for a specific language
 	 * 
 	 * @param language
-	 *            the identifier of the language to translate to
-	 * @param strings
-	 *            a collection of string identifiers
-	 * 
-	 * @return a map associating string identifiers to translations
-	 * 
-	 * @throws UnknownStringException
-	 *             if one of the string identifiers does not match a string
+	 *            the identifier of the language
+	 * @return a translation interface for the language
 	 * @throws UnknownLanguageException
-	 *             if the language does not exist or is not supported
+	 *             if the specified language does not exist or is not supported
 	 */
-	public Map< String , String > translate( String language , Collection< String > strings )
-			throws UnknownStringException , UnknownLanguageException;
+	public LanguageTranslator getLanguageTranslator( String language )
+			throws UnknownLanguageException;
 }
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/i18n/UnknownLanguageException.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/i18n/UnknownLanguageException.java
similarity index 100%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/i18n/UnknownLanguageException.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/i18n/UnknownLanguageException.java
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/i18n/UnknownStringException.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/i18n/UnknownStringException.java
similarity index 100%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/i18n/UnknownStringException.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/i18n/UnknownStringException.java
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/mailer/AlreadySentException.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/mailer/AlreadySentException.java
similarity index 100%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/mailer/AlreadySentException.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/mailer/AlreadySentException.java
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/mailer/MailData.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/mailer/MailData.java
similarity index 100%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/mailer/MailData.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/mailer/MailData.java
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/mailer/Mailer.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/mailer/Mailer.java
similarity index 100%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/mailer/Mailer.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/mailer/Mailer.java
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/mailer/MailerException.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/mailer/MailerException.java
similarity index 100%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/mailer/MailerException.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/mailer/MailerException.java
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/mailer/MissingDataException.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/mailer/MissingDataException.java
similarity index 100%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/mailer/MissingDataException.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/mailer/MissingDataException.java
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/mailer/NotSentException.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/mailer/NotSentException.java
similarity index 100%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/mailer/NotSentException.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/mailer/NotSentException.java
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/msg/AdminMessages.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/msg/AdminMessages.java
similarity index 100%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/msg/AdminMessages.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/msg/AdminMessages.java
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/msg/EmpireMessages.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/msg/EmpireMessages.java
similarity index 100%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/msg/EmpireMessages.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/msg/EmpireMessages.java
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/msg/MessageBoxDAO.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/msg/MessageBoxDAO.java
similarity index 100%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/msg/MessageBoxDAO.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/msg/MessageBoxDAO.java
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/msg/MessageContentCache.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/msg/MessageContentCache.java
similarity index 100%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/msg/MessageContentCache.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/msg/MessageContentCache.java
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/msg/MessageExtractor.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/msg/MessageExtractor.java
similarity index 100%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/msg/MessageExtractor.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/msg/MessageExtractor.java
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/msg/MessageFormatRegistry.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/msg/MessageFormatRegistry.java
similarity index 100%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/msg/MessageFormatRegistry.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/msg/MessageFormatRegistry.java
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/msg/MessageFormatter.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/msg/MessageFormatter.java
similarity index 100%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/msg/MessageFormatter.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/msg/MessageFormatter.java
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/msg/MessageRecordsDAO.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/msg/MessageRecordsDAO.java
similarity index 100%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/msg/MessageRecordsDAO.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/msg/MessageRecordsDAO.java
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/msg/NotificationsDAO.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/msg/NotificationsDAO.java
similarity index 100%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/msg/NotificationsDAO.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/msg/NotificationsDAO.java
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/naming/EmpireNameException.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/naming/EmpireNameException.java
similarity index 100%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/naming/EmpireNameException.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/naming/EmpireNameException.java
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/naming/MapNameException.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/naming/MapNameException.java
similarity index 100%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/naming/MapNameException.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/naming/MapNameException.java
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/naming/NamesManager.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/naming/NamesManager.java
similarity index 100%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/naming/NamesManager.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/naming/NamesManager.java
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/naming/NamingDAO.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/naming/NamingDAO.java
similarity index 100%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/naming/NamingDAO.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/naming/NamingDAO.java
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/prefs/AccountPreferences.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/prefs/AccountPreferences.java
similarity index 100%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/prefs/AccountPreferences.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/prefs/AccountPreferences.java
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/prefs/Preference.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/prefs/Preference.java
similarity index 100%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/prefs/Preference.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/prefs/Preference.java
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/prefs/PreferenceDefinitionException.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/prefs/PreferenceDefinitionException.java
similarity index 100%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/prefs/PreferenceDefinitionException.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/prefs/PreferenceDefinitionException.java
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/prefs/PreferenceDefinitions.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/prefs/PreferenceDefinitions.java
similarity index 100%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/prefs/PreferenceDefinitions.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/prefs/PreferenceDefinitions.java
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/prefs/PreferenceGroup.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/prefs/PreferenceGroup.java
similarity index 100%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/prefs/PreferenceGroup.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/prefs/PreferenceGroup.java
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/prefs/PreferenceType.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/prefs/PreferenceType.java
similarity index 100%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/prefs/PreferenceType.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/prefs/PreferenceType.java
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/prefs/PreferenceTypesRegistry.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/prefs/PreferenceTypesRegistry.java
similarity index 100%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/prefs/PreferenceTypesRegistry.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/prefs/PreferenceTypesRegistry.java
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/prefs/PreferencesDAO.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/prefs/PreferencesDAO.java
similarity index 100%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/prefs/PreferencesDAO.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/prefs/PreferencesDAO.java
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/session/ServerSession.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/session/ServerSession.java
similarity index 100%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/session/ServerSession.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/session/ServerSession.java
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/session/SessionManager.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/session/SessionManager.java
similarity index 100%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/session/SessionManager.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/session/SessionManager.java
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/session/SessionTypeDefiner.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/session/SessionTypeDefiner.java
similarity index 100%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/session/SessionTypeDefiner.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/session/SessionTypeDefiner.java
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/sys/ConstantDefinition.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/sys/ConstantDefinition.java
similarity index 100%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/sys/ConstantDefinition.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/sys/ConstantDefinition.java
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/sys/ConstantsAdministration.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/sys/ConstantsAdministration.java
similarity index 100%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/sys/ConstantsAdministration.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/sys/ConstantsAdministration.java
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/sys/ConstantsManager.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/sys/ConstantsManager.java
similarity index 85%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/sys/ConstantsManager.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/sys/ConstantsManager.java
index 825e886..7b003b1 100644
--- a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/sys/ConstantsManager.java
+++ b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/sys/ConstantsManager.java
@@ -2,7 +2,6 @@ package com.deepclone.lw.interfaces.sys;
 
 
 import java.util.Collection;
-import java.util.Set;
 
 
 
@@ -32,15 +31,15 @@ public interface ConstantsManager
 
 
 	/**
-	 * Registers a constants user, which will need to be informed of the constants' changes. If the
+	 * Register a constants user, which will need to be informed of the constants' changes. If the
 	 * required constants have not been registered yet, the user instance will not be notified.
 	 * 
 	 * @param user
 	 *            the constants user component to register
 	 * @param constants
-	 *            set of constant names the user wants to be informed about
+	 *            constant names the user wants to be informed about
 	 */
-	public void registerUser( ConstantsUser user , Set< String > constants );
+	public void registerUser( ConstantsUser user , String... constants );
 
 
 	/**
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/sys/ConstantsUser.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/sys/ConstantsUser.java
similarity index 100%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/sys/ConstantsUser.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/sys/ConstantsUser.java
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/sys/EndAutowiredTransaction.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/sys/EndAutowiredTransaction.java
similarity index 100%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/sys/EndAutowiredTransaction.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/sys/EndAutowiredTransaction.java
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/sys/InvalidConstantValue.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/sys/InvalidConstantValue.java
similarity index 100%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/sys/InvalidConstantValue.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/sys/InvalidConstantValue.java
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/sys/MaintenanceData.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/sys/MaintenanceData.java
similarity index 100%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/sys/MaintenanceData.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/sys/MaintenanceData.java
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/sys/MaintenanceStatusException.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/sys/MaintenanceStatusException.java
similarity index 100%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/sys/MaintenanceStatusException.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/sys/MaintenanceStatusException.java
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/sys/SystemStatus.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/sys/SystemStatus.java
similarity index 87%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/sys/SystemStatus.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/sys/SystemStatus.java
index d8cc5d2..62fa5d0 100644
--- a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/sys/SystemStatus.java
+++ b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/sys/SystemStatus.java
@@ -50,4 +50,11 @@ public interface SystemStatus
 	public Long checkStuckTick( )
 			throws MaintenanceStatusException;
 
+
+	/**
+	 * Update the status when a game update has been completed.
+	 */
+	public void endTick( )
+			throws TickStatusException , MaintenanceStatusException;
+
 }
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/sys/TickStatusException.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/sys/TickStatusException.java
similarity index 100%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/sys/TickStatusException.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/sys/TickStatusException.java
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/sys/Ticker.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/sys/Ticker.java
similarity index 100%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/sys/Ticker.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/sys/Ticker.java
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/sys/TickerManager.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/sys/TickerManager.java
similarity index 100%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/sys/TickerManager.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/sys/TickerManager.java
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/sys/UnknownConstantError.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/sys/UnknownConstantError.java
similarity index 100%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/sys/UnknownConstantError.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/sys/UnknownConstantError.java
diff --git a/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/sys/WiringException.java b/legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/sys/WiringException.java
similarity index 100%
rename from legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/sys/WiringException.java
rename to legacyworlds-server/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/sys/WiringException.java
diff --git a/legacyworlds-server/legacyworlds-server-main/.classpath b/legacyworlds-server/legacyworlds-server-main/.classpath
new file mode 100644
index 0000000..7c3d14f
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-main/.classpath
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" output="target/classes" path="src/main/java"/>
+	<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources"/>
+	<classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
+	<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+	<classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER"/>
+	<classpathentry kind="output" path="target/classes"/>
+</classpath>
diff --git a/legacyworlds-server/legacyworlds-server-main/.project b/legacyworlds-server/legacyworlds-server-main/.project
new file mode 100644
index 0000000..4fabc51
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-main/.project
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>legacyworlds-server-main</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.maven.ide.eclipse.maven2Builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.maven.ide.eclipse.maven2Nature</nature>
+	</natures>
+</projectDescription>
diff --git a/legacyworlds-server/legacyworlds-server-main/.settings/org.eclipse.jdt.core.prefs b/legacyworlds-server/legacyworlds-server-main/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..deacd36
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-main/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,6 @@
+#Thu Apr 15 09:16:34 CEST 2010
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.6
diff --git a/legacyworlds-server/legacyworlds-server-main/.settings/org.maven.ide.eclipse.prefs b/legacyworlds-server/legacyworlds-server-main/.settings/org.maven.ide.eclipse.prefs
new file mode 100644
index 0000000..1a8e041
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-main/.settings/org.maven.ide.eclipse.prefs
@@ -0,0 +1,9 @@
+#Thu Apr 15 09:16:34 CEST 2010
+activeProfiles=
+eclipse.preferences.version=1
+fullBuildGoals=process-test-resources
+includeModules=false
+resolveWorkspaceProjects=true
+resourceFilterGoals=process-resources resources\:testResources
+skipCompilerPlugin=true
+version=1
diff --git a/legacyworlds-server-main/data-source.sample.xml b/legacyworlds-server/legacyworlds-server-main/data-source.xml
similarity index 87%
rename from legacyworlds-server-main/data-source.sample.xml
rename to legacyworlds-server/legacyworlds-server-main/data-source.xml
index 8dcf68d..fccf83f 100644
--- a/legacyworlds-server-main/data-source.sample.xml
+++ b/legacyworlds-server/legacyworlds-server-main/data-source.xml
@@ -2,7 +2,8 @@
 	<!-- Legacy Worlds Beta 6 - Default data source configuration -->
 	<!--
 		This file is provided as an example on how to configure the game
-		server's data source.
+		server's data sources. It configures a memory-based HSQL database,
+		initialising its schemas and structure.
 	-->
 <beans xmlns="http://www.springframework.org/schema/beans"
 	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
diff --git a/legacyworlds-server-main/data/buildables.xml b/legacyworlds-server/legacyworlds-server-main/data/buildables.xml
similarity index 76%
rename from legacyworlds-server-main/data/buildables.xml
rename to legacyworlds-server/legacyworlds-server-main/data/buildables.xml
index 5f6d22a..9b81696 100644
--- a/legacyworlds-server-main/data/buildables.xml
+++ b/legacyworlds-server/legacyworlds-server-main/data/buildables.xml
@@ -5,23 +5,20 @@
 	<building name="milFactory" description="milFactoryDescription" type="WORK" output="1" workers="200">
 		<cost build="100" upkeep="10" work="4800" />
 	</building>
-	<building name="mine" description="mineDescription" type="MINE" output="1" workers="50">
-		<cost build="100" upkeep="10" work="4800" />
-	</building>
 	<building name="turret" description="turretDescription" type="DEF" output="10" workers="5">
 		<cost build="40" upkeep="2" work="600" />
 	</building>
 	<building name="indFactory" description="indFactoryDescription" type="CASH" output="1" workers="500">
 		<cost build="500" upkeep="20" work="28800" />
-		<require-technology>indFactTech</require-technology>
+		<tech>indFactTech</tech>
 	</building>
 	<building name="reanimationCentre" description="reanimationCentreDescription" type="POP" output="1" workers="300">
 		<cost build="4000" upkeep="200" work="57600" />
-		<require-technology>reanimationTech</require-technology>
+		<tech>reanimationTech</tech>
 	</building>
 	<building name="superTurret" description="superTurretDescription" type="DEF" output="500" workers="1">
 		<cost build="4000" upkeep="10" work="20000" />
-		<require-technology>superTurretTech</require-technology>
+		<tech>superTurretTech</tech>
 	</building>
 
 	<ship name="fighter" description="fighterDescription" time="3" power="10">
@@ -29,15 +26,15 @@
 	</ship>
 	<ship name="cruiser" description="cruiserDescription" time="5" power="100">
 		<cost build="500" upkeep="80" work="5000" />
-		<require-technology>cruisersTech</require-technology>
+		<tech>cruisersTech</tech>
 	</ship>
 	<ship name="bCruiser" description="bCruiserDescription" time="4" power="335">
 		<cost build="2500" upkeep="320" work="25000" />
-		<require-technology>bCruisersTech</require-technology>
+		<tech>bCruisersTech</tech>
 	</ship>
 	<ship name="dreadnought" description="dreadnoughtDescription" time="6" power="5000">
 		<cost build="12500" upkeep="1280" work="125000" />
-		<require-technology>dreadnoughtsTech</require-technology>
+		<tech>dreadnoughtsTech</tech>
 	</ship>
 
 </buildables>
\ No newline at end of file
diff --git a/legacyworlds-server-main/data/buildables.xsd b/legacyworlds-server/legacyworlds-server-main/data/buildables.xsd
similarity index 87%
rename from legacyworlds-server-main/data/buildables.xsd
rename to legacyworlds-server/legacyworlds-server-main/data/buildables.xsd
index 73e6a39..7fad623 100644
--- a/legacyworlds-server-main/data/buildables.xsd
+++ b/legacyworlds-server/legacyworlds-server-main/data/buildables.xsd
@@ -19,14 +19,13 @@
 			<xs:enumeration value="DEF" />
 			<xs:enumeration value="POP" />
 			<xs:enumeration value="WORK" />
-			<xs:enumeration value="MINE" />
 		</xs:restriction>
 	</xs:simpleType>
 
 	<xs:complexType name="buildable" abstract="true">
 		<xs:sequence>
 			<xs:element name="cost" type="cost" />
-			<xs:element name="require-technology" type="xs:string" minOccurs="0" />
+			<xs:element name="tech" type="xs:token" minOccurs="0" />
 		</xs:sequence>
 		<xs:attribute name="name" use="required" type="xs:string" />
 		<xs:attribute name="description" use="required" type="xs:string" />
@@ -57,9 +56,4 @@
 		<xs:attribute name="upkeep" use="required" type="xs:nonNegativeInteger" />
 	</xs:complexType>
 
-	<xs:complexType name="tech">
-		<xs:attribute name="name" use="required" type="xs:string" />
-		<xs:attribute name="level" use="required" type="xs:positiveInteger" />
-	</xs:complexType>
-
 </xs:schema>
diff --git a/legacyworlds-server-main/data/i18n-text.xml b/legacyworlds-server/legacyworlds-server-main/data/i18n-text.xml
similarity index 55%
rename from legacyworlds-server-main/data/i18n-text.xml
rename to legacyworlds-server/legacyworlds-server-main/data/i18n-text.xml
index 0403da4..955d560 100644
--- a/legacyworlds-server-main/data/i18n-text.xml
+++ b/legacyworlds-server/legacyworlds-server-main/data/i18n-text.xml
@@ -1,23 +1,14 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<lw-text-data xmlns="http://www.deepclone.com/lw/b6/m1/i18n-text"
-		xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-		xsi:schemaLocation="http://www.deepclone.com/lw/b6/m1/i18n-text i18n-text.xsd">
+<lw-text-data xmlns="http://www.deepclone.com/lw/b6/m1/i18n-text" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://www.deepclone.com/lw/b6/m1/i18n-text i18n-text.xsd">
+	
+	<include>text/buildings.xml</include>
+	<include>text/mail.xml</include>
+	<include>text/preferences.xml</include>
+	<include>text/technologies.xml</include>
 
 	<language id="en" name="English">
-		<from-file id="registrationMail" source="i18n/en/registrationMail.txt" />
-		<from-file id="passwordRecoveryMail" source="i18n/en/passwordRecoveryMail.txt" />
-		<from-file id="reactivationMail" source="i18n/en/reactivationMail.txt" />
-		<from-file id="addressChangeMail" source="i18n/en/addressChangeMail.txt" />
-		<from-file id="adminRecapMail" source="i18n/adminRecapMail.txt" />
-		<from-file id="messageMail" source="i18n/en/messageMail.txt" />
-		<from-file id="recapMail" source="i18n/en/recapMail.txt" />
-		<from-file id="quitMail" source="i18n/en/quitMail.txt" />
-		<from-file id="bannedMail" source="i18n/en/bannedMail.txt" />
-		<from-file id="banLiftedMail" source="i18n/en/banLiftedMail.txt" />
-		<from-file id="adminErrorMail" source="i18n/adminErrorMail.txt" />
-		<from-file id="inactivityWarningMail" source="i18n/en/inactivityWarningMail.txt" />
-		<from-file id="inactivityQuitMail" source="i18n/en/inactivityQuitMail.txt" />
-		
+
 		<inline-string id="instantNotification">
 			<value>
 ***
@@ -47,95 +38,6 @@ ${text}
 			<value>Messages from administrators:</value>
 		</inline-string>
 
-		<inline-string id="civTech">
-			<value>Civilian technologies</value>
-		</inline-string>
-		<inline-string id="civTechDescription">
-			<value>They're not just your slaves, they're your scientists, poets and workers. Make the poets work first, then use these technologies to increase their productivity! Useless poets.</value>
-		</inline-string>
-
-		<inline-string id="indFactTech">
-			<value>Universal assemblers</value>
-		</inline-string>
-		<inline-string id="indFactTechDescription">
-			<value>You know how it is when you have a thingy-bob that you need to build but you just don't have the right tool. Well, fear no more, Universal Assemblers will solve all your problems! Build anything and everything with these clever machines, they are 1337.</value>
-		</inline-string>
-		<inline-string id="reanimationTech">
-			<value>Corpse reanimation</value>
-		</inline-string>
-		<inline-string id="reanimationTechDescription">
-			<value>Tired of workers dying too early? Want a little less perspiration in your corporation? Zombies will work, won't complain and best of all, they can be fed on almost anything! Feed them your enemies! But mostly, use them to increase factory productivity by a rather nice amount.</value>
-		</inline-string>
-		<inline-string id="superTurretTech">
-			<value>Biological generators</value>
-		</inline-string>
-		<inline-string id="superTurretTechDescription">
-			<value>For every turret a military commander wants, there is a bigger, stronger turret he wants more. Now you too can have such a turret! It will defend your planet with ease while you venture out into the galaxy, bending it to your will. Available in all good hardware stores.</value>
-		</inline-string>
-
-		<inline-string id="milTech">
-			<value>Military technologies</value>
-		</inline-string>
-		<inline-string id="milTechDescription">
-			<value>It is only one who is thoroughly acquainted with the evils of war that can thoroughly understand the profitable way of carrying it on. - Sun Tzu</value>
-		</inline-string>
-
-		<inline-string id="cruisersTech">
-			<value>Orbital construction</value>
-		</inline-string>
-		<inline-string id="cruisersTechDescription">
-			<value>Ships built on the ground must endure the stress of atmospheric flight before they are even able to dominate the vast emptiness of space. Build them in space and they will be sleeker, more powerful and now free of the need for windows. Use your brand new Cruisers to dominate the known universe.</value>
-		</inline-string>
-		<inline-string id="bCruisersTech">
-			<value>Structural reinforcement</value>
-		</inline-string>
-		<inline-string id="bCruisersTechDescription">
-			<value>The power of your Cruisers can be augmented by an improved design! Take advantage of a more structurally sound space vehicle that can bring empires to their knees with its speed and technological grace.</value>
-		</inline-string>
-		<inline-string id="dreadnoughtsTech">
-			<value>Automated space docks</value>
-		</inline-string>
-		<inline-string id="dreadnoughtsTechDescription">
-			<value>Technology has advanced. The ultimate weapon is now available. Claim the awesome power of the Dreadnought and crush your enemies. Ever wanted a tank in space? Well, now you have it. All their base are belong to you.</value>
-		</inline-string>
-
-		<inline-string id="mine">
-			<value>Mine</value>
-		</inline-string>
-		<inline-string id="mineDescription">
-			<value>Exactly what it says on the cover. Not the exploding kind, though. Even if that happens from time to time, anyway.</value>
-		</inline-string>
-		<inline-string id="milFactory">
-			<value>Ship parts factory</value>
-		</inline-string>
-		<inline-string id="milFactoryDescription">
-			<value>A Ship parts factory is a mass production factory for the creation of components used in your space faring vessels. They are essential to any space empire; Properly managed factories produce new vehicles quickly and efficiently.</value>
-		</inline-string>
-		<inline-string id="turret">
-			<value>Defence turret</value>
-		</inline-string>
-		<inline-string id="turretDescription">
-			<value>Exploration without vigilance is the action of a fool. Turrets are the last line of defence for the planet, super massive weapons capable of destroying orbital vehicles from the ground. They can be placed anywhere, on any building or vacant land in your domain and will defend your planets from attack.</value>
-		</inline-string>
-		<inline-string id="indFactory">
-			<value>Generic assembly line</value>
-		</inline-string>
-		<inline-string id="indFactoryDescription">
-			<value>Factories are the backbone of a thriving economy, providing goods and matériel to buy and sell on the free market. Your brand new Generic assembly lines will enhance your wealth and keep the population employed. Properly managed factories produce many economic benefits for an empire.</value>
-		</inline-string>
-		<inline-string id="reanimationCentre">
-			<value>Reanimation centre</value>
-		</inline-string>
-		<inline-string id="reanimationCentreDescription">
-			<value>People are frail but cheap and robots are hard wearing but expensive. Renew the life of your workers and you can take advantage of a cheap zombie resource, giving you a third option for keeping your empire thriving.</value>
-		</inline-string>
-		<inline-string id="superTurret">
-			<value>Biological turret</value>
-		</inline-string>
-		<inline-string id="superTurretDescription">
-			<value>The perfect union of man and machine, Biological Turrets are a blending of the technological and the biological to provide the ultimate defence for your planets. More powerful and accurate than Turrets, in ground based defence they are unmatched. Keep your people away from them, however, as they tend to hunger for human flesh.</value>
-		</inline-string>
-
 		<inline-string id="fighter">
 			<value>Fighter</value>
 		</inline-string>
@@ -161,64 +63,6 @@ ${text}
 			<value>Bring the Dread. The Dreadnought is a large capital ship with awesome power and capabilities, expensive and slow but the ultimate in space domination.</value>
 		</inline-string>
 
-		<inline-string id="pgDisplay">
-			<value>Display preferences</value>
-		</inline-string>
-		<inline-string id="pUseRLTime">
-			<value>Real-life time</value>
-		</inline-string>
-		<inline-string id="pUseRLTimeDescription">
-			<value>Selecting this option will cause all durations to be displayed using real-life minutes.</value>
-		</inline-string>
-		<inline-string id="pgMap">
-			<value>Map defaults</value>
-		</inline-string>
-		<inline-string id="pMapX">
-			<value>Map centre (X)</value>
-		</inline-string>
-		<inline-string id="pMapXDescription">
-			<value>The abscissa of the default map centre.</value>
-		</inline-string>
-		<inline-string id="pMapY">
-			<value>Map centre (Y)</value>
-		</inline-string>
-		<inline-string id="pMapYDescription">
-			<value>The ordinates of the default map centre.</value>
-		</inline-string>
-		<inline-string id="pMapSize">
-			<value>Map size</value>
-		</inline-string>
-		<inline-string id="pMapSizeDescription">
-			<value>The default size of the map.</value>
-		</inline-string>
-		<inline-string id="pgMail">
-			<value>E-mail settings</value>
-		</inline-string>
-		<inline-string id="pMailOnPM">
-			<value>Private messages</value>
-		</inline-string>
-		<inline-string id="pMailOnPMDescription">
-			<value>Select the type of e-mail notifications you will get for private messages sent by other empires.</value>
-		</inline-string>
-		<inline-string id="pMailOnAlliance">
-			<value>Alliance messages</value>
-		</inline-string>
-		<inline-string id="pMailOnAllianceDescription">
-			<value>Select the type of e-mail notifications you will get for alliance-wise messages.</value>
-		</inline-string>
-		<inline-string id="pMailOnIM">
-			<value>Internal messages</value>
-		</inline-string>
-		<inline-string id="pMailOnIMDescription">
-			<value>Select the type of e-mail notifications you will get for internal game messages.</value>
-		</inline-string>
-		<inline-string id="pMailOnAdmin">
-			<value>Messages from administrators</value>
-		</inline-string>
-		<inline-string id="pMailOnAdminDescription">
-			<value>Select the type of e-mail notifications you will get for messages sent by the game's administrators.</value>
-		</inline-string>
-
 		<inline-string id="mapSizeSmall">
 			<value>Small (3x3)</value>
 		</inline-string>
@@ -281,7 +125,7 @@ ${text}
 		<inline-string id="imEmptyMilQueues">
 			<value>Some of your planets have finished constructing ships:</value>
 		</inline-string>
-		
+
 		<inline-string id="imtEmptyMilQueue">
 			<value>Empty military queue at ${location}</value>
 		</inline-string>
@@ -296,7 +140,7 @@ ${text}
 		<inline-string id="imBattleStart">
 			<value>{{battle:${battleId} Battle #${battleId}}} has started at ${location}.</value>
 		</inline-string>
-		
+
 		<inline-string id="imtBattleEnd">
 			<value>Battle ended at ${location}</value>
 		</inline-string>
@@ -311,7 +155,7 @@ ${text}
 		<inline-string id="imStrikeStart">
 			<value>The citizens of ${location} are in a really bad mood and have started leaving their posts... We'd better do something about this.</value>
 		</inline-string>
-		
+
 		<inline-string id="imtStrikeEnd">
 			<value>Situation back to normal on ${location}</value>
 		</inline-string>
@@ -326,14 +170,14 @@ ${text}
 		<inline-string id="imLostPlanet">
 			<value>We have lost control of ${location}, which was taken from us by ${taker}.</value>
 		</inline-string>
-		
+
 		<inline-string id="imtAbandonPlanet">
 			<value>Planet ${location} abandoned</value>
 		</inline-string>
 		<inline-string id="imAbandonPlanet">
 			<value>Our forces have completed the evacuation of ${location}; the citizens of this world are left to fend for themselves.</value>
 		</inline-string>
-		
+
 		<!-- Internal messages - planet taken -->
 		<inline-string id="imtTakePlanet">
 			<value>Planet ${location} conquered</value>
@@ -344,7 +188,7 @@ ${text}
 		<inline-string id="imTakePlanet">
 			<value>We have seized control of planet ${location} from the clutches of ${owner}.</value>
 		</inline-string>
-		
+
 		<!-- Empire messages -->
 		<inline-string id="imtTechAvailable">
 			<value>${tech} available</value>
@@ -364,7 +208,7 @@ ${text}
 		<inline-string id="imDebtEnd">
 			<value>Good to see that our money problems are over, Sir. Good job. Well, of course it'd been better if these problems had never started... Sir? What are you doing with this handgu-</value>
 		</inline-string>
-		
+
 		<!-- Alliance messages -->
 		<inline-string id="imtPendingRequest">
 			<value>Pending alliance request</value>
@@ -414,7 +258,7 @@ ${text}
 		<inline-string id="imAllianceDisbanded">
 			<value>The leader has left and the alliance was disbanded.</value>
 		</inline-string>
-		
+
 		<!-- Fleets -->
 		<inline-string id="imtFleetArrival">
 			<value>Fleets have arrived at ${location}</value>
@@ -473,7 +317,7 @@ ${text}
 		<inline-string id="imfSwitchDefence">
 			<value>: switched to defence</value>
 		</inline-string>
-		
+
 		<!-- Administration messages -->
 		<inline-string id="imAdminWarning">
 			<value>You currently have ${warnings} warning(s). Please note that, upon reaching 3 warnings, the administration team will consider banning you.</value>
@@ -508,7 +352,7 @@ Your alliance, ${oldName}, had a name that was considered either vulgar, disresp
 
 It was disbanded.</value>
 		</inline-string>
-		
+
 		<!-- Bug tracker -->
 		<inline-string id="imtBugReportUpdate">
 			<value>Bug report #${id} updated</value>
@@ -519,95 +363,10 @@ It was disbanded.</value>
 		<inline-string id="imBugReportUpdateEmpire">
 			<value>Bug report ${bug} has been updated by the owner of empire ${submitter}.</value>
 		</inline-string>
-		
-		
-		<!-- Resource categories -->
-		<inline-string id="rcMinerals">
-			<value>Mineral resources</value>
-		</inline-string>
-		
-		<!-- Resource names and descriptions -->
-
-		<inline-string id="rnMoney">
-			<value>Money</value>
-		</inline-string>
-		<inline-string id="rdMoney">
-			<value>(Get Doug or Rendesh to write this)</value>
-		</inline-string>
-
-		<inline-string id="rnTitanium">
-			<value>Titanium</value>
-		</inline-string>
-		<inline-string id="rdTitanium">
-			<value>(Get Doug or Rendesh to write this)</value>
-		</inline-string>
-
-		<inline-string id="rnCopper">
-			<value>Copper</value>
-		</inline-string>
-		<inline-string id="rdCopper">
-			<value>(Get Doug or Rendesh to write this)</value>
-		</inline-string>
-
-		<inline-string id="rnStrentium">
-			<value>Strentium</value>
-		</inline-string>
-		<inline-string id="rdStrentium">
-			<value>(Get Doug or Rendesh to write this)</value>
-		</inline-string>
-
-		<inline-string id="rnDororhium">
-			<value>Dororhium</value>
-		</inline-string>
-		<inline-string id="rdDororhium">
-			<value>(Get Doug or Rendesh to write this)</value>
-		</inline-string>
-
-		<inline-string id="rnNothentium">
-			<value>Nothentium</value>
-		</inline-string>
-		<inline-string id="rdNothentium">
-			<value>(Get Doug or Rendesh to write this)</value>
-		</inline-string>
-		
-		<!-- Event names and templates -->
-		<inline-string id="evtBQProgressName">
-			<value>Build queue progress</value>
-		</inline-string>
-		<inline-string id="evtBQProgressTemplate">
-			<value>FIXME: this should be some FreeMarker code in a file</value>
-		</inline-string>
-		<inline-string id="evtBQEmptyName">
-			<value>Empty build queue</value>
-		</inline-string>
-		<inline-string id="evtBQEmptyTemplate">
-			<value>FIXME: this should be some FreeMarker code in a file</value>
-		</inline-string>
-		<inline-string id="evtResearchName">
-			<value>Technological breakthrough</value>
-		</inline-string>
-		<inline-string id="evtResearchTemplate">
-			<value>FIXME: this should be some FreeMarker code in a file</value>
-		</inline-string>
 
 	</language>
 
 	<language id="fr" name="Français">
-		<from-file id="registrationMail" source="i18n/fr/registrationMail.txt" />
-		<from-file id="passwordRecoveryMail" source="i18n/fr/passwordRecoveryMail.txt" />
-		<from-file id="reactivationMail" source="i18n/fr/reactivationMail.txt" />
-		<from-file id="addressChangeMail" source="i18n/fr/addressChangeMail.txt" />
-		<from-file id="messageMail" source="i18n/fr/messageMail.txt" />
-		<from-file id="recapMail" source="i18n/fr/recapMail.txt" />
-		<from-file id="quitMail" source="i18n/fr/quitMail.txt" />
-		<from-file id="bannedMail" source="i18n/fr/bannedMail.txt" />
-		<from-file id="banLiftedMail" source="i18n/fr/banLiftedMail.txt" />
-		<from-file id="inactivityWarningMail" source="i18n/fr/inactivityWarningMail.txt" />
-		<from-file id="inactivityQuitMail" source="i18n/fr/inactivityQuitMail.txt" />
-
-		<from-file id="adminRecapMail" source="i18n/adminRecapMail.txt" />
-		<from-file id="adminErrorMail" source="i18n/adminErrorMail.txt" />
-
 		<inline-string id="instantNotification">
 			<value>
 ***
@@ -637,95 +396,6 @@ ${text}
 			<value>Messages des administrateurs :</value>
 		</inline-string>
 
-		<inline-string id="civTech">
-			<value>Technologies civiles</value>
-		</inline-string>
-		<inline-string id="civTechDescription">
-			<value>Ce ne sont pas uniquement vos esclaves, ce sont vos chercheurs, poètes et ouvriers. Faites travailler d'abord les poètes, puis utilisez ces technologies pour augmenter leur productivité! Poètes inutiles...</value>
-		</inline-string>
-
-		<inline-string id="indFactTech">
-			<value>Assembleurs universels</value>
-		</inline-string>
-		<inline-string id="indFactTechDescription">
-			<value>Vous savez ce que c'est d'avoir un truc à construire, alors que malheureusement vous ne diposez pas du bon outil. Eh bien, plus de peur : les Assembleurs Universels vont résoudre tous vos problèmes! Construisez tout et n'importe quoi avec ces machines intelligentes, elles sont 1337.</value>
-		</inline-string>
-		<inline-string id="reanimationTech">
-			<value>Réanimation de cadavres</value>
-		</inline-string>
-		<inline-string id="reanimationTechDescription">
-			<value>Fatigué de ces ouvriers qui passent l'arme à gauche trop tôt? Vous voulez un peu plus de transpiration dans vos ateliers ? Les zombies vont travailler, ne vont pas se plaindre, et encore mieux ils peuvent être nourris avec n'importe quoi - y compris avec vos énemis! Mais surtout, utilisez les pour augmenter de manière significative la productivité de vos usines.</value>
-		</inline-string>
-		<inline-string id="superTurretTech">
-			<value>Générateurs biologiques</value>
-		</inline-string>
-		<inline-string id="superTurretTechDescription">
-			<value>Pour chaque tourelle qu'un commandant militaire réclame, il en est une qu'il désire encore plus. Maintenant, vous aussi pouvez avoir de telles tourelles! Elles défendront vos planètes avec aisance, pendant que vous vous aventurerez dans la galaxie, la pliant à votre volonté. Disponible chez tous les bons quincaillers.</value>
-		</inline-string>
-
-		<inline-string id="milTech">
-			<value>Technologies militaires</value>
-		</inline-string>
-		<inline-string id="milTechDescription">
-			<value>Ceux qui ne comprennent pas les dommages que la guerre peut causer n'en comprendront jamais les avantages. - Sun Tzu</value>
-		</inline-string>
-
-		<inline-string id="cruisersTech">
-			<value>Construction orbitale</value>
-		</inline-string>
-		<inline-string id="cruisersTechDescription">
-			<value>Les vaisseaux construits à la surface doivent subir le stress du vol atmosphérique avant même d'être lancés à assaut du grand vide interstellaire. Construisez-les dans l'espace et ils seront plus gracieux, plus puissants, et ne nécessiteront plus de fenêtres. Utilisez vos tout nouveaux croiseurs pour dominer l'univers connu.</value>
-		</inline-string>
-		<inline-string id="bCruisersTech">
-			<value>Consolidation structurelle</value>
-		</inline-string>
-		<inline-string id="bCruisersTechDescription">
-			<value>La puissance de vos croiseurs peut être augmentée par une conception améliorée! Profitez d'un véhicule à la structure mieux adaptée à l'espace qui peut mettre des empires à genoux grâce à sa vitesse et sa finesse technologique.</value>
-		</inline-string>
-		<inline-string id="dreadnoughtsTech">
-			<value>Docks orbitaux automatisés</value>
-		</inline-string>
-		<inline-string id="dreadnoughtsTechDescription">
-			<value>La technologie a évolué. L'arme ultime est maintenant disponible. Revendiquez la puissance écrasante du cuirassé et pulvérisez vos opposants. Déjà rêvé d'un tank de l'espace ? Eh bien, maintenant, vous l'avez. All their base are belong to you.</value>
-		</inline-string>
-
-		<inline-string id="mine">
-			<value>Mine</value>
-		</inline-string>
-		<inline-string id="mineDescription">
-			<value>Exactement ce qu'il y a marqué sur l'emballage. Enfin, ce n'est pas la variété qui explose. Même si parfois ça se produit quand même.</value>
-		</inline-string>
-		<inline-string id="milFactory">
-			<value>Fabrique de pièces de vaisseaux</value>
-		</inline-string>
-		<inline-string id="milFactoryDescription">
-			<value>Une fabrique de pièces de vaisseaux est une usine de production de masse pour la création des composants utilisés dans vos vaisseaux spatiaux. Elles sont essentielles à tout empire spatial ; bien gérées, elles produisent de nouveaux vaisseaux rapidement et efficacement.</value>
-		</inline-string>
-		<inline-string id="turret">
-			<value>Tourelle défensive</value>
-		</inline-string>
-		<inline-string id="turretDescription">
-			<value>Explorer sans être sur ses gardes est une statégie de lunatique. Les tourelles défensives sont la dernière ligne de défense d'une planète, énormes armes capables de détruire des véhicules en orbite depuis le sol. Elles peuvent être placées n'importe où, sur n'importe quel bâtiment ou espace dégagé de votre domaine, et défendront vos planètes contre les attaques.</value>
-		</inline-string>
-		<inline-string id="indFactory">
-			<value>Ligne de production générique</value>
-		</inline-string>
-		<inline-string id="indFactoryDescription">
-			<value>Les usines sont l'épine dorsale d'une économie florissante, fournissant des biens et pièces détachées qui peuvent être vendues sur le marché. Vos Lignes de production génériques flambant neuves vont augmenter votre richesse et conserver votre population dans l'emploi. Des usines bien gérées fournissent de nombreux bénéfices économiques à un empire.</value>
-		</inline-string>
-		<inline-string id="reanimationCentre">
-			<value>Centre de réanimation</value>
-		</inline-string>
-		<inline-string id="reanimationCentreDescription">
-			<value>Les humains sont frêles mais peu coûteux et les robots sont endurants mais très chers. Renouvelez la vie de vos travailleurs et vous pourrez tirer partie d'une ressource de zombies bon marché, vous permettant d'explorer une troisième voie pour conserver un empire florissant.</value>
-		</inline-string>
-		<inline-string id="superTurret">
-			<value>Tourelle biologique</value>
-		</inline-string>
-		<inline-string id="superTurretDescription">
-			<value>L'union parfaite de l'homme et de la machine, les tourelles biologiques sont un mélange du technologique et du biologique pour fournir la défense ultime à vos planètes. Plus puissantes et précises que les tourelles, au niveau défense au sol, elles ne peuvent être surclassées. Mais gardez votre population à distance, car elles ont tendance à avoir faim de chair humaine!</value>
-		</inline-string>
-
 		<inline-string id="fighter">
 			<value>Chasseur</value>
 		</inline-string>
@@ -751,64 +421,6 @@ ${text}
 			<value>Amenez la cuirasse. Le cuirassé est un énorme vaisseau aux performances et à la puissance impressionantes, cher et lent, mais le nec plus ultra de la domination spatiale.</value>
 		</inline-string>
 
-		<inline-string id="pgDisplay">
-			<value>Préférences d'affichage</value>
-		</inline-string>
-		<inline-string id="pUseRLTime">
-			<value>Temps réel</value>
-		</inline-string>
-		<inline-string id="pUseRLTimeDescription">
-			<value>Les durées seront affichées en utilisant de "vraies" mesures si cette option est sélectionnée.</value>
-		</inline-string>
-		<inline-string id="pgMap">
-			<value>Carte</value>
-		</inline-string>
-		<inline-string id="pMapX">
-			<value>Centre de la carte (X)</value>
-		</inline-string>
-		<inline-string id="pMapXDescription">
-			<value>L'abscisse par défaut du centre de la carte.</value>
-		</inline-string>
-		<inline-string id="pMapY">
-			<value>Centre de la carte (Y)</value>
-		</inline-string>
-		<inline-string id="pMapYDescription">
-			<value>L'ordonnée par défaut du centre de la carte.</value>
-		</inline-string>
-		<inline-string id="pMapSize">
-			<value>Taille de la carte</value>
-		</inline-string>
-		<inline-string id="pMapSizeDescription">
-			<value>La taille par défaut de la carte.</value>
-		</inline-string>
-		<inline-string id="pgMail">
-			<value>Envoi de courrier électronique</value>
-		</inline-string>
-		<inline-string id="pMailOnPM">
-			<value>Messages privés</value>
-		</inline-string>
-		<inline-string id="pMailOnPMDescription">
-			<value>Sélectionnez le type de notifications par courier électronique que vous recevrez lorsque d'autres empires vous envoient des messages privés.</value>
-		</inline-string>
-		<inline-string id="pMailOnAlliance">
-			<value>Messages d'alliance</value>
-		</inline-string>
-		<inline-string id="pMailOnAllianceDescription">
-			<value>Sélectionnez le type de notifications par courier électronique que vous recevrez lorsque vous recevez un message d'alliance.</value>
-		</inline-string>
-		<inline-string id="pMailOnIM">
-			<value>Messages internes</value>
-		</inline-string>
-		<inline-string id="pMailOnIMDescription">
-			<value>Sélectionnez le type de notifications par courier électronique que vous recevrez lorsque vous recevez un message interne du jeu.</value>
-		</inline-string>
-		<inline-string id="pMailOnAdmin">
-			<value>Messages des administrateurs</value>
-		</inline-string>
-		<inline-string id="pMailOnAdminDescription">
-			<value>Sélectionnez le type de notifications par courier électronique que vous recevrez lorsque vous recevez un message des administrateurs du jeu.</value>
-		</inline-string>
-
 		<inline-string id="mapSizeSmall">
 			<value>Petite (3x3)</value>
 		</inline-string>
@@ -871,7 +483,7 @@ ${text}
 		<inline-string id="imEmptyMilQueues">
 			<value>Certaines de vos planètes ont fini de construire des vaisseaux :</value>
 		</inline-string>
-		
+
 		<inline-string id="imtEmptyMilQueue">
 			<value>Liste de construction militaire vide sur ${location}</value>
 		</inline-string>
@@ -886,7 +498,7 @@ ${text}
 		<inline-string id="imBattleStart">
 			<value>{{battle:${battleId} La bataille #${battleId}}} a commencé sur ${location}.</value>
 		</inline-string>
-		
+
 		<inline-string id="imtBattleEnd">
 			<value>Bataille terminée sur ${location}</value>
 		</inline-string>
@@ -901,7 +513,7 @@ ${text}
 		<inline-string id="imStrikeStart">
 			<value>Les habitants de ${location} sont de très mauvaise humeur et ont commencé à quitter leurs postes... Nous devrions faire quelque chose à ce sujet.</value>
 		</inline-string>
-		
+
 		<inline-string id="imtStrikeEnd">
 			<value>Situation revenue à la normale sur ${location}</value>
 		</inline-string>
@@ -916,14 +528,14 @@ ${text}
 		<inline-string id="imLostPlanet">
 			<value>Nous avons perdu le contrôle de ${location}, qui nous a été prise par ${taker}.</value>
 		</inline-string>
-		
+
 		<inline-string id="imtAbandonPlanet">
 			<value>Abandon de la planète ${location}</value>
 		</inline-string>
 		<inline-string id="imAbandonPlanet">
 			<value>Nos forces ont terminé l'évacutation de ${location}; les habitants de ce monde sont livrés à eux-mêmes.</value>
 		</inline-string>
-		
+
 		<!-- Internal messages - planet taken -->
 		<inline-string id="imtTakePlanet">
 			<value>Conquête de la planète${location}</value>
@@ -934,7 +546,7 @@ ${text}
 		<inline-string id="imTakePlanet">
 			<value>Nous avons pris le contrôle de la planète ${location} des griffes de ${owner}.</value>
 		</inline-string>
-		
+
 		<!-- Empire messages -->
 		<inline-string id="imtTechAvailable">
 			<value>${tech} disponible</value>
@@ -954,7 +566,7 @@ ${text}
 		<inline-string id="imDebtEnd">
 			<value>C'est bon de voir que nos problèmes d'argent sont résolus, Chef. Bien joué. Bien sûr, ça aurait été mieux si ces problèmes n'avaient jamais eu lieu... Chef, qu'est ce que vous faites avec ce pistol-</value>
 		</inline-string>
-		
+
 		<!-- Alliance messages -->
 		<inline-string id="imtPendingRequest">
 			<value>Demande d'alliance en attente</value>
@@ -1004,7 +616,7 @@ ${text}
 		<inline-string id="imAllianceDisbanded">
 			<value>Le dirigeant est parti et l'alliance a été dissoute.</value>
 		</inline-string>
-		
+
 		<!-- Fleets -->
 		<inline-string id="imtFleetArrival">
 			<value>Arrivée de flottes sur ${location}</value>
@@ -1063,7 +675,7 @@ ${text}
 		<inline-string id="imfSwitchDefence">
 			<value>: est passée en défensee</value>
 		</inline-string>
-		
+
 		<!-- Administration messages -->
 		<inline-string id="imAdminWarning">
 			<value>Vous avez actuellement ${warnings} avertissement(s). Veuillez noter que, lorsque vous atteindrez 3 avertissements, l'équipe d'administration va envisager votre expulsion.</value>
@@ -1098,7 +710,7 @@ Votre alliance, ${oldName}, avait un nom qui a été considéré comme vulgaire,
 
 Elle a été dissoute.</value>
 		</inline-string>
-		
+
 		<!-- Bug tracker -->
 		<inline-string id="imtBugReportUpdate">
 			<value>Rapport de bug #${id} mis à jour</value>
@@ -1109,76 +721,6 @@ Elle a été dissoute.</value>
 		<inline-string id="imBugReportUpdateEmpire">
 			<value>Le rapport de bug ${bug} a été mis à jour par le propriétaire de l'empire ${submitter}.</value>
 		</inline-string>
-		
-		<!-- Resource categories -->
-		<inline-string id="rcMinerals">
-			<value>Minéraux</value>
-		</inline-string>
-		
-		<!-- Resource names and descriptions -->
-
-		<inline-string id="rnMoney">
-			<value>Monaie</value>
-		</inline-string>
-		<inline-string id="rdMoney">
-			<value>(À traduire quand il y aura une version anglaise)</value>
-		</inline-string>
-
-		<inline-string id="rnTitanium">
-			<value>Titane</value>
-		</inline-string>
-		<inline-string id="rdTitanium">
-			<value>(À traduire quand il y aura une version anglaise)</value>
-		</inline-string>
-
-		<inline-string id="rnCopper">
-			<value>Cuivre</value>
-		</inline-string>
-		<inline-string id="rdCopper">
-			<value>(À traduire quand il y aura une version anglaise)</value>
-		</inline-string>
-
-		<inline-string id="rnStrentium">
-			<value>Strentium</value>
-		</inline-string>
-		<inline-string id="rdStrentium">
-			<value>(À traduire quand il y aura une version anglaise)</value>
-		</inline-string>
-
-		<inline-string id="rnDororhium">
-			<value>Dororhium</value>
-		</inline-string>
-		<inline-string id="rdDororhium">
-			<value>(À traduire quand il y aura une version anglaise)</value>
-		</inline-string>
-
-		<inline-string id="rnNothentium">
-			<value>Nothentium</value>
-		</inline-string>
-		<inline-string id="rdNothentium">
-			<value>(À traduire quand il y aura une version anglaise)</value>
-		</inline-string>
-
-		
-		<!-- Event names and templates -->
-		<inline-string id="evtBQProgressName">
-			<value>Avancement des constructions</value>
-		</inline-string>
-		<inline-string id="evtBQProgressTemplate">
-			<value>FIXME: this should be some FreeMarker code in a file</value>
-		</inline-string>
-		<inline-string id="evtBQEmptyName">
-			<value>File de construction vide</value>
-		</inline-string>
-		<inline-string id="evtBQEmptyTemplate">
-			<value>FIXME: this should be some FreeMarker code in a file</value>
-		</inline-string>
-		<inline-string id="evtResearchName">
-			<value>Découverte scientifique</value>
-		</inline-string>
-		<inline-string id="evtResearchTemplate">
-			<value>FIXME: this should be some FreeMarker code in a file</value>
-		</inline-string>
 
 	</language>
 
diff --git a/legacyworlds-server-main/data/i18n-text.xsd b/legacyworlds-server/legacyworlds-server-main/data/i18n-text.xsd
similarity index 92%
rename from legacyworlds-server-main/data/i18n-text.xsd
rename to legacyworlds-server/legacyworlds-server-main/data/i18n-text.xsd
index 8f8932d..599b13d 100644
--- a/legacyworlds-server-main/data/i18n-text.xsd
+++ b/legacyworlds-server/legacyworlds-server-main/data/i18n-text.xsd
@@ -5,6 +5,7 @@
 	<xs:element name="lw-text-data">
 		<xs:complexType>
 			<xs:sequence>
+				<xs:element name="include" type="xs:anyURI" minOccurs="0" maxOccurs="unbounded" />
 				<xs:element name="language" type="language" minOccurs="0" maxOccurs="unbounded" />
 			</xs:sequence>
 		</xs:complexType>
diff --git a/legacyworlds-server/legacyworlds-server-main/data/techs.xml b/legacyworlds-server/legacyworlds-server-main/data/techs.xml
new file mode 100644
index 0000000..c15f5da
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-main/data/techs.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<technologies xmlns="http://www.deepclone.com/lw/b6/m1/techs" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://www.deepclone.com/lw/b6/m1/techs techs-m2.xsd">
+
+	<category name="milTech" description="milTechDescription" />
+	<category name="civTech" description="civTechDescription" />
+
+	<technology name="cruisersTech" category="milTech" description="cruisersTechDescription" points="5000" cost="10000" />
+	<technology name="bCruisersTech" category="milTech" description="bCruisersTechDescription" points="20000"
+		cost="30000">
+		<depends on="cruisersTech" />
+	</technology>
+	<technology name="dreadnoughtsTech" category="milTech" description="dreadnoughtsTechDescription" points="48000"
+		cost="100000">
+		<depends on="bCruisersTech" />
+	</technology>
+
+	<technology name="indFactTech" category="civTech" description="indFactTechDescription" points="2000" cost="5000" />
+	<technology name="reanimationTech" category="civTech" description="reanimationTechDescription" points="10000"
+		cost="25000">
+		<depends on="indFactTech" />
+	</technology>
+	<technology name="superTurretTech" category="civTech" description="superTurretTechDescription" points="30000"
+		cost="125000">
+		<depends on="reanimationTech" />
+	</technology>
+</technologies>
\ No newline at end of file
diff --git a/legacyworlds-server/legacyworlds-server-main/data/techs.xsd b/legacyworlds-server/legacyworlds-server-main/data/techs.xsd
new file mode 100644
index 0000000..cab088c
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-main/data/techs.xsd
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema xmlns="http://www.deepclone.com/lw/b6/m1/techs" targetNamespace="http://www.deepclone.com/lw/b6/m1/techs"
+	xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
+
+	<xs:element name="technologies">
+		<xs:complexType>
+			<xs:sequence>
+				<xs:element name="category" type="category" minOccurs="1" maxOccurs="unbounded" />
+				<xs:element name="technology" type="technology" minOccurs="1" maxOccurs="unbounded" />
+			</xs:sequence>
+		</xs:complexType>
+	</xs:element>
+
+	<xs:complexType name="category">
+		<xs:attribute name="name" use="required" type="xs:token" />
+		<xs:attribute name="description" use="required" type="xs:token" />
+	</xs:complexType>
+
+	<xs:complexType name="technology">
+		<xs:sequence>
+			<xs:element name="depends" type="dependency" minOccurs="0" maxOccurs="unbounded" />
+		</xs:sequence>
+		<xs:attribute name="name" use="required" type="xs:token" />
+		<xs:attribute name="category" use="required" type="xs:token" />
+		<xs:attribute name="description" use="required" type="xs:token" />
+		<xs:attribute name="points" use="required" type="xs:positiveInteger" />
+		<xs:attribute name="cost" use="required" type="xs:positiveInteger" />
+	</xs:complexType>
+	
+	<xs:complexType name="dependency">
+		<xs:attribute name="on" use="required" type="xs:token" />
+	</xs:complexType>
+
+</xs:schema>
\ No newline at end of file
diff --git a/legacyworlds-server/legacyworlds-server-main/data/text/buildings.xml b/legacyworlds-server/legacyworlds-server-main/data/text/buildings.xml
new file mode 100644
index 0000000..81cdcf2
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-main/data/text/buildings.xml
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<lw-text-data xmlns="http://www.deepclone.com/lw/b6/m1/i18n-text" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://www.deepclone.com/lw/b6/m1/i18n-text ../i18n-text.xsd">
+
+	<language id="en" name="English">
+
+		<inline-string id="milFactory">
+			<value>Ship parts factory</value>
+		</inline-string>
+		<inline-string id="milFactoryDescription">
+			<value>A Ship parts factory is a mass production factory for the creation of components used in your space faring vessels. They are essential to any space empire; Properly managed factories produce new vehicles quickly and efficiently.</value>
+		</inline-string>
+		<inline-string id="turret">
+			<value>Defence turret</value>
+		</inline-string>
+		<inline-string id="turretDescription">
+			<value>Exploration without vigilance is the action of a fool. Turrets are the last line of defence for the planet, super massive weapons capable of destroying orbital vehicles from the ground. They can be placed anywhere, on any building or vacant land in your domain and will defend your planets from attack.</value>
+		</inline-string>
+		<inline-string id="indFactory">
+			<value>Generic assembly line</value>
+		</inline-string>
+		<inline-string id="indFactoryDescription">
+			<value>Factories are the backbone of a thriving economy, providing goods and matériel to buy and sell on the free market. Your brand new Generic assembly lines will enhance your wealth and keep the population employed. Properly managed factories produce many economic benefits for an empire.</value>
+		</inline-string>
+		<inline-string id="reanimationCentre">
+			<value>Reanimation centre</value>
+		</inline-string>
+		<inline-string id="reanimationCentreDescription">
+			<value>People are frail but cheap and robots are hard wearing but expensive. Renew the life of your workers and you can take advantage of a cheap zombie resource, giving you a third option for keeping your empire thriving.</value>
+		</inline-string>
+		<inline-string id="superTurret">
+			<value>Biological turret</value>
+		</inline-string>
+		<inline-string id="superTurretDescription">
+			<value>The perfect union of man and machine, Biological Turrets are a blending of the technological and the biological to provide the ultimate defence for your planets. More powerful and accurate than Turrets, in ground based defence they are unmatched. Keep your people away from them, however, as they tend to hunger for human flesh.</value>
+		</inline-string>
+
+	</language>
+	
+	
+	<language name="Français" id="fr">
+
+		<inline-string id="milFactory">
+			<value>Fabrique de pièces de vaisseaux</value>
+		</inline-string>
+		<inline-string id="milFactoryDescription">
+			<value>Une fabrique de pièces de vaisseaux est une usine de production de masse pour la création des composants utilisés dans vos vaisseaux spatiaux. Elles sont essentielles à tout empire spatial ; bien gérées, elles produisent de nouveaux vaisseaux rapidement et efficacement.</value>
+		</inline-string>
+		<inline-string id="turret">
+			<value>Tourelle défensive</value>
+		</inline-string>
+		<inline-string id="turretDescription">
+			<value>Explorer sans être sur ses gardes est une statégie de lunatique. Les tourelles défensives sont la dernière ligne de défense d'une planète, énormes armes capables de détruire des véhicules en orbite depuis le sol. Elles peuvent être placées n'importe où, sur n'importe quel bâtiment ou espace dégagé de votre domaine, et défendront vos planètes contre les attaques.</value>
+		</inline-string>
+		<inline-string id="indFactory">
+			<value>Ligne de production générique</value>
+		</inline-string>
+		<inline-string id="indFactoryDescription">
+			<value>Les usines sont l'épine dorsale d'une économie florissante, fournissant des biens et pièces détachées qui peuvent être vendues sur le marché. Vos Lignes de production génériques flambant neuves vont augmenter votre richesse et conserver votre population dans l'emploi. Des usines bien gérées fournissent de nombreux bénéfices économiques à un empire.</value>
+		</inline-string>
+		<inline-string id="reanimationCentre">
+			<value>Centre de réanimation</value>
+		</inline-string>
+		<inline-string id="reanimationCentreDescription">
+			<value>Les humains sont frêles mais peu coûteux et les robots sont endurants mais très chers. Renouvelez la vie de vos travailleurs et vous pourrez tirer partie d'une ressource de zombies bon marché, vous permettant d'explorer une troisième voie pour conserver un empire florissant.</value>
+		</inline-string>
+		<inline-string id="superTurret">
+			<value>Tourelle biologique</value>
+		</inline-string>
+		<inline-string id="superTurretDescription">
+			<value>L'union parfaite de l'homme et de la machine, les tourelles biologiques sont un mélange du technologique et du biologique pour fournir la défense ultime à vos planètes. Plus puissantes et précises que les tourelles, au niveau défense au sol, elles ne peuvent être surclassées. Mais gardez votre population à distance, car elles ont tendance à avoir faim de chair humaine!</value>
+		</inline-string>
+
+	</language>
+
+</lw-text-data>
\ No newline at end of file
diff --git a/legacyworlds-server/legacyworlds-server-main/data/text/mail.xml b/legacyworlds-server/legacyworlds-server-main/data/text/mail.xml
new file mode 100644
index 0000000..ecd50f4
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-main/data/text/mail.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<lw-text-data xmlns="http://www.deepclone.com/lw/b6/m1/i18n-text" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://www.deepclone.com/lw/b6/m1/i18n-text ../i18n-text.xsd">
+
+	<language id="en" name="English">
+		<from-file id="registrationMail" source="mail/registrationMail-en.txt" />
+		<from-file id="passwordRecoveryMail" source="mail/passwordRecoveryMail-en.txt" />
+		<from-file id="reactivationMail" source="mail/reactivationMail-en.txt" />
+		<from-file id="addressChangeMail" source="mail/addressChangeMail-en.txt" />
+		<from-file id="adminRecapMail" source="mail/adminRecapMail.txt" />
+		<from-file id="messageMail" source="mail/messageMail-en.txt" />
+		<from-file id="recapMail" source="mail/recapMail-en.txt" />
+		<from-file id="quitMail" source="mail/quitMail-en.txt" />
+		<from-file id="bannedMail" source="mail/bannedMail-en.txt" />
+		<from-file id="banLiftedMail" source="mail/banLiftedMail-en.txt" />
+		<from-file id="adminErrorMail" source="mail/adminErrorMail.txt" />
+		<from-file id="inactivityWarningMail" source="mail/inactivityWarningMail-en.txt" />
+		<from-file id="inactivityQuitMail" source="mail/inactivityQuitMail-en.txt" />
+	</language>
+
+	<language id="fr" name="Français">
+		<from-file id="registrationMail" source="mail/registrationMail-fr.txt" />
+		<from-file id="passwordRecoveryMail" source="mail/passwordRecoveryMail-fr.txt" />
+		<from-file id="reactivationMail" source="mail/reactivationMail-fr.txt" />
+		<from-file id="addressChangeMail" source="mail/addressChangeMail-fr.txt" />
+		<from-file id="adminRecapMail" source="mail/adminRecapMail.txt" />
+		<from-file id="messageMail" source="mail/messageMail-fr.txt" />
+		<from-file id="recapMail" source="mail/recapMail-fr.txt" />
+		<from-file id="quitMail" source="mail/quitMail-fr.txt" />
+		<from-file id="bannedMail" source="mail/bannedMail-fr.txt" />
+		<from-file id="banLiftedMail" source="mail/banLiftedMail-fr.txt" />
+		<from-file id="adminErrorMail" source="mail/adminErrorMail.txt" />
+		<from-file id="inactivityWarningMail" source="mail/inactivityWarningMail-fr.txt" />
+		<from-file id="inactivityQuitMail" source="mail/inactivityQuitMail-fr.txt" />
+	</language>
+
+
+</lw-text-data>
\ No newline at end of file
diff --git a/legacyworlds-server-main/data/i18n/en/addressChangeMail.txt b/legacyworlds-server/legacyworlds-server-main/data/text/mail/addressChangeMail-en.txt
similarity index 82%
rename from legacyworlds-server-main/data/i18n/en/addressChangeMail.txt
rename to legacyworlds-server/legacyworlds-server-main/data/text/mail/addressChangeMail-en.txt
index 9dfc314..e424137 100644
--- a/legacyworlds-server-main/data/i18n/en/addressChangeMail.txt
+++ b/legacyworlds-server/legacyworlds-server-main/data/text/mail/addressChangeMail-en.txt
@@ -1,4 +1,4 @@
-Legacy Worlds (B6M1) - Address change
+Legacy Worlds (B6M2) - Address change
 Hello,
 
 You are receiving this message because an user of Legacy Worlds (you, presumably) requested to change his or her address to ${address}.
diff --git a/legacyworlds-server-main/data/i18n/fr/addressChangeMail.txt b/legacyworlds-server/legacyworlds-server-main/data/text/mail/addressChangeMail-fr.txt
similarity index 83%
rename from legacyworlds-server-main/data/i18n/fr/addressChangeMail.txt
rename to legacyworlds-server/legacyworlds-server-main/data/text/mail/addressChangeMail-fr.txt
index 569a8e9..04d7c49 100644
--- a/legacyworlds-server-main/data/i18n/fr/addressChangeMail.txt
+++ b/legacyworlds-server/legacyworlds-server-main/data/text/mail/addressChangeMail-fr.txt
@@ -1,4 +1,4 @@
-Legacy Worlds (B6M1) - Changement d'adresse
+Legacy Worlds (B6M2) - Changement d'adresse
 Bonjour,
 
 Vous avez reçu ce message car un utilisateur de Legacy Worlds (vous, probablement) a demandé à ce que son adresse soit changée pour ${address}.
diff --git a/legacyworlds-server-main/data/i18n/adminErrorMail.txt b/legacyworlds-server/legacyworlds-server-main/data/text/mail/adminErrorMail.txt
similarity index 76%
rename from legacyworlds-server-main/data/i18n/adminErrorMail.txt
rename to legacyworlds-server/legacyworlds-server-main/data/text/mail/adminErrorMail.txt
index f577aa2..b2e0240 100644
--- a/legacyworlds-server-main/data/i18n/adminErrorMail.txt
+++ b/legacyworlds-server/legacyworlds-server-main/data/text/mail/adminErrorMail.txt
@@ -1,4 +1,4 @@
-[LWB6-ADMIN] Server errors
+[LWB6M2-ADMIN] Server errors
 Errors have been found in the server's system log. Intervention might be required.
 
 ${contents}
diff --git a/legacyworlds-server-main/data/i18n/adminRecapMail.txt b/legacyworlds-server/legacyworlds-server-main/data/text/mail/adminRecapMail.txt
similarity index 73%
rename from legacyworlds-server-main/data/i18n/adminRecapMail.txt
rename to legacyworlds-server/legacyworlds-server-main/data/text/mail/adminRecapMail.txt
index 3d90b25..95a9335 100644
--- a/legacyworlds-server-main/data/i18n/adminRecapMail.txt
+++ b/legacyworlds-server/legacyworlds-server-main/data/text/mail/adminRecapMail.txt
@@ -1,4 +1,4 @@
-[LWB6-ADMIN] Recap
+[LWB6M2-ADMIN] Recap
 Here's what happened in the past 12 hours...
 
 ${contents}
diff --git a/legacyworlds-server-main/data/i18n/en/banLiftedMail.txt b/legacyworlds-server/legacyworlds-server-main/data/text/mail/banLiftedMail-en.txt
similarity index 79%
rename from legacyworlds-server-main/data/i18n/en/banLiftedMail.txt
rename to legacyworlds-server/legacyworlds-server-main/data/text/mail/banLiftedMail-en.txt
index 39ceb1d..edf84f9 100644
--- a/legacyworlds-server-main/data/i18n/en/banLiftedMail.txt
+++ b/legacyworlds-server/legacyworlds-server-main/data/text/mail/banLiftedMail-en.txt
@@ -1,4 +1,4 @@
-Legacy Worlds (B6M1) - Ban lifted
+Legacy Worlds (B6M2) - Ban lifted
 Hello,
 
 The ban on your account has been lifted.
diff --git a/legacyworlds-server-main/data/i18n/fr/banLiftedMail.txt b/legacyworlds-server/legacyworlds-server-main/data/text/mail/banLiftedMail-fr.txt
similarity index 77%
rename from legacyworlds-server-main/data/i18n/fr/banLiftedMail.txt
rename to legacyworlds-server/legacyworlds-server-main/data/text/mail/banLiftedMail-fr.txt
index 95b003f..7f43675 100644
--- a/legacyworlds-server-main/data/i18n/fr/banLiftedMail.txt
+++ b/legacyworlds-server/legacyworlds-server-main/data/text/mail/banLiftedMail-fr.txt
@@ -1,4 +1,4 @@
-Legacy Worlds (B6M1) - Bannissement levé
+Legacy Worlds (B6M2) - Bannissement levé
 Bonjour,
 
 Le bannissement de votre compte a été levé.
diff --git a/legacyworlds-server-main/data/i18n/en/bannedMail.txt b/legacyworlds-server/legacyworlds-server-main/data/text/mail/bannedMail-en.txt
similarity index 88%
rename from legacyworlds-server-main/data/i18n/en/bannedMail.txt
rename to legacyworlds-server/legacyworlds-server-main/data/text/mail/bannedMail-en.txt
index c546f78..2b344b8 100644
--- a/legacyworlds-server-main/data/i18n/en/bannedMail.txt
+++ b/legacyworlds-server/legacyworlds-server-main/data/text/mail/bannedMail-en.txt
@@ -1,4 +1,4 @@
-Legacy Worlds (B6M1) account banned
+Legacy Worlds (B6M2) account banned
 Hello,
 
 Your Legacy Worlds account has been banned by the game's administrators for the following reason:
diff --git a/legacyworlds-server-main/data/i18n/fr/bannedMail.txt b/legacyworlds-server/legacyworlds-server-main/data/text/mail/bannedMail-fr.txt
similarity index 90%
rename from legacyworlds-server-main/data/i18n/fr/bannedMail.txt
rename to legacyworlds-server/legacyworlds-server-main/data/text/mail/bannedMail-fr.txt
index a2fb65e..0576f6a 100644
--- a/legacyworlds-server-main/data/i18n/fr/bannedMail.txt
+++ b/legacyworlds-server/legacyworlds-server-main/data/text/mail/bannedMail-fr.txt
@@ -1,4 +1,4 @@
-Legacy Worlds (B6M1) - Compte banni
+Legacy Worlds (B6M2) - Compte banni
 Bonjour,
 
 Votre compte Legacy Worlds a été banni par les administrateurs du jeu pour la raison suivante :
diff --git a/legacyworlds-server-main/data/i18n/en/inactivityQuitMail.txt b/legacyworlds-server/legacyworlds-server-main/data/text/mail/inactivityQuitMail-en.txt
similarity index 88%
rename from legacyworlds-server-main/data/i18n/en/inactivityQuitMail.txt
rename to legacyworlds-server/legacyworlds-server-main/data/text/mail/inactivityQuitMail-en.txt
index d628f44..7b382c9 100644
--- a/legacyworlds-server-main/data/i18n/en/inactivityQuitMail.txt
+++ b/legacyworlds-server/legacyworlds-server-main/data/text/mail/inactivityQuitMail-en.txt
@@ -1,4 +1,4 @@
-Legacy Worlds (B6M1) - Inactive account closed
+Legacy Worlds (B6M2) - Inactive account closed
 Hello,
 
 This email is being sent to inform you that your account on Legacy Worlds has been disabled. It had been inactive for 28 days.
diff --git a/legacyworlds-server-main/data/i18n/fr/inactivityQuitMail.txt b/legacyworlds-server/legacyworlds-server-main/data/text/mail/inactivityQuitMail-fr.txt
similarity index 88%
rename from legacyworlds-server-main/data/i18n/fr/inactivityQuitMail.txt
rename to legacyworlds-server/legacyworlds-server-main/data/text/mail/inactivityQuitMail-fr.txt
index 7441c8b..94c0496 100644
--- a/legacyworlds-server-main/data/i18n/fr/inactivityQuitMail.txt
+++ b/legacyworlds-server/legacyworlds-server-main/data/text/mail/inactivityQuitMail-fr.txt
@@ -1,4 +1,4 @@
-Legacy Worlds (B6M1) - Fermeture de compte inactif
+Legacy Worlds (B6M2) - Fermeture de compte inactif
 Bonjour,
 
 Ce message vous a été envoyé pour vous prévenir que votre compte sur Legacy Worlds a été désactivé. Il a été inactif pendant 28 jours.
diff --git a/legacyworlds-server-main/data/i18n/en/inactivityWarningMail.txt b/legacyworlds-server/legacyworlds-server-main/data/text/mail/inactivityWarningMail-en.txt
similarity index 89%
rename from legacyworlds-server-main/data/i18n/en/inactivityWarningMail.txt
rename to legacyworlds-server/legacyworlds-server-main/data/text/mail/inactivityWarningMail-en.txt
index add97f3..b0f02fc 100644
--- a/legacyworlds-server-main/data/i18n/en/inactivityWarningMail.txt
+++ b/legacyworlds-server/legacyworlds-server-main/data/text/mail/inactivityWarningMail-en.txt
@@ -1,4 +1,4 @@
-Legacy Worlds (B6M1) - Inactivity
+Legacy Worlds (B6M2) - Inactivity
 Hello,
 
 This email is being sent to warn you that your account on Legacy Worlds has been inactive for the past three weeks. Unless you connect in the coming week, it will be closed and your empire will be lost.
diff --git a/legacyworlds-server-main/data/i18n/fr/inactivityWarningMail.txt b/legacyworlds-server/legacyworlds-server-main/data/text/mail/inactivityWarningMail-fr.txt
similarity index 91%
rename from legacyworlds-server-main/data/i18n/fr/inactivityWarningMail.txt
rename to legacyworlds-server/legacyworlds-server-main/data/text/mail/inactivityWarningMail-fr.txt
index d2e8f27..088cb4c 100644
--- a/legacyworlds-server-main/data/i18n/fr/inactivityWarningMail.txt
+++ b/legacyworlds-server/legacyworlds-server-main/data/text/mail/inactivityWarningMail-fr.txt
@@ -1,4 +1,4 @@
-Legacy Worlds (B6M1) - Inactivité
+Legacy Worlds (B6M2) - Inactivité
 Bonjour,
 
 Ce message vous a été envoyé pour vous prévenir que votre compte sur Legacy Worlds a été inactif pendant les trois dernières semaines. À moins que vous vous connectiez durant la semaine procahine, il sera fermé et votre empire sera perdu.
diff --git a/legacyworlds-server-main/data/i18n/en/messageMail.txt b/legacyworlds-server/legacyworlds-server-main/data/text/mail/messageMail-en.txt
similarity index 82%
rename from legacyworlds-server-main/data/i18n/en/messageMail.txt
rename to legacyworlds-server/legacyworlds-server-main/data/text/mail/messageMail-en.txt
index 299b5c3..7550d66 100644
--- a/legacyworlds-server-main/data/i18n/en/messageMail.txt
+++ b/legacyworlds-server/legacyworlds-server-main/data/text/mail/messageMail-en.txt
@@ -1,4 +1,4 @@
-Legacy Worlds (B6M1) - New messages
+Legacy Worlds (B6M2) - New messages
 Hello ${empire},
 
 You have just received new messages in Legacy Worlds.
diff --git a/legacyworlds-server-main/data/i18n/fr/messageMail.txt b/legacyworlds-server/legacyworlds-server-main/data/text/mail/messageMail-fr.txt
similarity index 77%
rename from legacyworlds-server-main/data/i18n/fr/messageMail.txt
rename to legacyworlds-server/legacyworlds-server-main/data/text/mail/messageMail-fr.txt
index d31af22..a7e81d7 100644
--- a/legacyworlds-server-main/data/i18n/fr/messageMail.txt
+++ b/legacyworlds-server/legacyworlds-server-main/data/text/mail/messageMail-fr.txt
@@ -1,4 +1,4 @@
-Legacy Worlds (B6M1) - Nouveaux messages
+Legacy Worlds (B6M2) - Nouveaux messages
 Bonjour ${empire},
 
 Vous venez de recevoir de nouveaux messages sur Legacy Worlds!
diff --git a/legacyworlds-server-main/data/i18n/en/passwordRecoveryMail.txt b/legacyworlds-server/legacyworlds-server-main/data/text/mail/passwordRecoveryMail-en.txt
similarity index 92%
rename from legacyworlds-server-main/data/i18n/en/passwordRecoveryMail.txt
rename to legacyworlds-server/legacyworlds-server-main/data/text/mail/passwordRecoveryMail-en.txt
index d7cf79b..c3508e2 100644
--- a/legacyworlds-server-main/data/i18n/en/passwordRecoveryMail.txt
+++ b/legacyworlds-server/legacyworlds-server-main/data/text/mail/passwordRecoveryMail-en.txt
@@ -1,4 +1,4 @@
-Legacy Worlds (B6M1) password recovery
+Legacy Worlds (B6M2) password recovery
 Hello,
 
 You are receiving this message because an user of Legacy Worlds (you, presumably) requested to recover his password.
diff --git a/legacyworlds-server-main/data/i18n/fr/passwordRecoveryMail.txt b/legacyworlds-server/legacyworlds-server-main/data/text/mail/passwordRecoveryMail-fr.txt
similarity index 91%
rename from legacyworlds-server-main/data/i18n/fr/passwordRecoveryMail.txt
rename to legacyworlds-server/legacyworlds-server-main/data/text/mail/passwordRecoveryMail-fr.txt
index 94bc15e..a9bc10c 100644
--- a/legacyworlds-server-main/data/i18n/fr/passwordRecoveryMail.txt
+++ b/legacyworlds-server/legacyworlds-server-main/data/text/mail/passwordRecoveryMail-fr.txt
@@ -1,4 +1,4 @@
-Legacy Worlds (B6M1) - Récupération de mot de passe
+Legacy Worlds (B6M2) - Récupération de mot de passe
 Bonjour,
 
 Vous avez reçu ce message car un utilisateur de Legacy Worlds (vous, probablement) a demandé à récupérer son mot de passe oublié.
diff --git a/legacyworlds-server-main/data/i18n/en/quitMail.txt b/legacyworlds-server/legacyworlds-server-main/data/text/mail/quitMail-en.txt
similarity index 91%
rename from legacyworlds-server-main/data/i18n/en/quitMail.txt
rename to legacyworlds-server/legacyworlds-server-main/data/text/mail/quitMail-en.txt
index 8f379e7..032eb95 100644
--- a/legacyworlds-server-main/data/i18n/en/quitMail.txt
+++ b/legacyworlds-server/legacyworlds-server-main/data/text/mail/quitMail-en.txt
@@ -1,4 +1,4 @@
-Legacy Worlds (B6M1) - Account closed
+Legacy Worlds (B6M2) - Account closed
 Hello,
 
 This email is being sent to confirm that your account has been closed as you requested.
diff --git a/legacyworlds-server-main/data/i18n/fr/quitMail.txt b/legacyworlds-server/legacyworlds-server-main/data/text/mail/quitMail-fr.txt
similarity index 85%
rename from legacyworlds-server-main/data/i18n/fr/quitMail.txt
rename to legacyworlds-server/legacyworlds-server-main/data/text/mail/quitMail-fr.txt
index 2788e38..c293f47 100644
--- a/legacyworlds-server-main/data/i18n/fr/quitMail.txt
+++ b/legacyworlds-server/legacyworlds-server-main/data/text/mail/quitMail-fr.txt
@@ -1,4 +1,4 @@
-Legacy Worlds (B6M1) - Compte désactivé
+Legacy Worlds (B6M2) - Compte désactivé
 Bonjour,
 
 Cet e-mail vous est envoyé pour confirmer que votre compte a été fermé à votre demande.
diff --git a/legacyworlds-server-main/data/i18n/en/reactivationMail.txt b/legacyworlds-server/legacyworlds-server-main/data/text/mail/reactivationMail-en.txt
similarity index 85%
rename from legacyworlds-server-main/data/i18n/en/reactivationMail.txt
rename to legacyworlds-server/legacyworlds-server-main/data/text/mail/reactivationMail-en.txt
index c0176e0..cc79827 100644
--- a/legacyworlds-server-main/data/i18n/en/reactivationMail.txt
+++ b/legacyworlds-server/legacyworlds-server-main/data/text/mail/reactivationMail-en.txt
@@ -1,8 +1,8 @@
-Legacy Worlds (B6M1) - Account reactivation
+Legacy Worlds (B6M2) - Account reactivation
 Hello,
 
 Thank you for revisiting at Legacy Worlds!
-Please note that you reactivated your account for "Beta 6 Milestone 1", a highly experimental, in-progress rewrite of the game. As this game does not include forums at this stage, you might want to register to Legacy Worlds Beta 5 to keep up with the game's news.
+Please note that you reactivated your account for "Beta 6 Milestone 2", a highly experimental, in-progress rewrite of the game. As this game does not include forums at this stage, you might want to register to Legacy Worlds Beta 5 to keep up with the game's news.
 
 Before we reactivate your account, there's just one more step to complete your request.
 You have to connect to the site using your e-mail address and password, then validate your account reactivation using the confirmation code below.
diff --git a/legacyworlds-server-main/data/i18n/fr/reactivationMail.txt b/legacyworlds-server/legacyworlds-server-main/data/text/mail/reactivationMail-fr.txt
similarity index 87%
rename from legacyworlds-server-main/data/i18n/fr/reactivationMail.txt
rename to legacyworlds-server/legacyworlds-server-main/data/text/mail/reactivationMail-fr.txt
index 3a97e3c..62f3800 100644
--- a/legacyworlds-server-main/data/i18n/fr/reactivationMail.txt
+++ b/legacyworlds-server/legacyworlds-server-main/data/text/mail/reactivationMail-fr.txt
@@ -1,8 +1,8 @@
-Legacy Worlds (B6M1) - Réactivation de votre compte
+Legacy Worlds (B6M2) - Réactivation de votre compte
 Bonjour,
 
 Merci de revenir sur Legacy Worlds!
-Veuillez remarquer que vous venez de réactiver un compte sur le jeu "Beta 6 Milestone 1", une récriture en cours et par conséquent hautement expérimentale du jeu. Comme cette version ne dispose pas de forums à l'heure actuelle, nous vous suggérons de vous enregistrer également à Legacy Worlds Beta 5 afin de vous tenir au courant des dernières nouvelles.
+Veuillez remarquer que vous venez de réactiver un compte sur le jeu "Beta 6 Milestone 2", une récriture en cours et par conséquent hautement expérimentale du jeu. Comme cette version ne dispose pas de forums à l'heure actuelle, nous vous suggérons de vous enregistrer également à Legacy Worlds Beta 5 afin de vous tenir au courant des dernières nouvelles.
 
 Avant que nous réactivions votre compte, il vous reste une dernière étape à accomplir.
 Vous allez devoir vous connecter au site en utilisant votre adresse électronique et votre mot de passe, puis valider la réactivation de votre compte en saisissant le code de confirmation ci-dessous.
diff --git a/legacyworlds-server-main/data/i18n/en/recapMail.txt b/legacyworlds-server/legacyworlds-server-main/data/text/mail/recapMail-en.txt
similarity index 77%
rename from legacyworlds-server-main/data/i18n/en/recapMail.txt
rename to legacyworlds-server/legacyworlds-server-main/data/text/mail/recapMail-en.txt
index c72810f..3b5f756 100644
--- a/legacyworlds-server-main/data/i18n/en/recapMail.txt
+++ b/legacyworlds-server/legacyworlds-server-main/data/text/mail/recapMail-en.txt
@@ -1,4 +1,4 @@
-Legacy Worlds (B6M1) - Today's messages
+Legacy Worlds (B6M2) - Today's messages
 Hello ${empire},
 
 Here is a reminder of the messages you received today.
diff --git a/legacyworlds-server-main/data/i18n/fr/recapMail.txt b/legacyworlds-server/legacyworlds-server-main/data/text/mail/recapMail-fr.txt
similarity index 72%
rename from legacyworlds-server-main/data/i18n/fr/recapMail.txt
rename to legacyworlds-server/legacyworlds-server-main/data/text/mail/recapMail-fr.txt
index 641f2d7..517d5a0 100644
--- a/legacyworlds-server-main/data/i18n/fr/recapMail.txt
+++ b/legacyworlds-server/legacyworlds-server-main/data/text/mail/recapMail-fr.txt
@@ -1,4 +1,4 @@
-Legacy Worlds (B6M1) - Messages du jour
+Legacy Worlds (B6M2) - Messages du jour
 Bonjour ${empire},
 
 Voici un récapitulatif des messages que vous avez reçu aujourd'hui.
diff --git a/legacyworlds-server-main/data/i18n/en/registrationMail.txt b/legacyworlds-server/legacyworlds-server-main/data/text/mail/registrationMail-en.txt
similarity index 86%
rename from legacyworlds-server-main/data/i18n/en/registrationMail.txt
rename to legacyworlds-server/legacyworlds-server-main/data/text/mail/registrationMail-en.txt
index e91d215..4193dee 100644
--- a/legacyworlds-server-main/data/i18n/en/registrationMail.txt
+++ b/legacyworlds-server/legacyworlds-server-main/data/text/mail/registrationMail-en.txt
@@ -1,8 +1,8 @@
-Legacy Worlds (B6M1) - Your account
+Legacy Worlds (B6M2) - Your account
 Hello,
 
 Thank you for registering at Legacy Worlds!
-Please note that you registered to "Beta 6 Milestone 1", a highly experimental, in-progress rewrite of the game. As this game does not include forums at this stage, you might want to register to Legacy Worlds Beta 5 to keep up with the game's news.
+Please note that you registered to "Beta 6 Milestone 2", a highly experimental, in-progress rewrite of the game. As this game does not include forums at this stage, you might want to register to Legacy Worlds Beta 5 to keep up with the game's news.
 
 Before we activate your account, there's just one more step to complete your registration.
 You have to connect to the site using the e-mail address and password you chose, then validate your account using the confirmation code below.
diff --git a/legacyworlds-server-main/data/i18n/fr/registrationMail.txt b/legacyworlds-server/legacyworlds-server-main/data/text/mail/registrationMail-fr.txt
similarity index 88%
rename from legacyworlds-server-main/data/i18n/fr/registrationMail.txt
rename to legacyworlds-server/legacyworlds-server-main/data/text/mail/registrationMail-fr.txt
index a6bc7bf..4cd8f80 100644
--- a/legacyworlds-server-main/data/i18n/fr/registrationMail.txt
+++ b/legacyworlds-server/legacyworlds-server-main/data/text/mail/registrationMail-fr.txt
@@ -1,8 +1,8 @@
-Legacy Worlds (B6M1) - Votre compte
+Legacy Worlds (B6M2) - Votre compte
 Bonjour,
 
 Merci de vous être enregistré(e) sur Legacy Worlds!
-Veuillez remarquer que vous venez de créer un compte sur le jeu "Beta 6 Milestone 1", une récriture en cours et par conséquent hautement expérimentale du jeu. Comme cette version ne dispose pas de forums à l'heure actuelle, nous vous suggérons de vous enregistrer également à Legacy Worlds Beta 5 afin de vous tenir au courant des dernières nouvelles.
+Veuillez remarquer que vous venez de créer un compte sur le jeu "Beta 6 Milestone 2", une récriture en cours et par conséquent hautement expérimentale du jeu. Comme cette version ne dispose pas de forums à l'heure actuelle, nous vous suggérons de vous enregistrer également à Legacy Worlds Beta 5 afin de vous tenir au courant des dernières nouvelles.
 
 Avant que nous activions votre compte, il vous reste une dernière étape à accomplir.
 Vous allez devoir vous connecter au site en utilisant l'adresse électronique et le mot de passe que vous avez choisi, puis valider votre compte en saisissant le code de confirmation ci-dessous.
diff --git a/legacyworlds-server/legacyworlds-server-main/data/text/preferences.xml b/legacyworlds-server/legacyworlds-server-main/data/text/preferences.xml
new file mode 100644
index 0000000..ad6e43e
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-main/data/text/preferences.xml
@@ -0,0 +1,130 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<lw-text-data xmlns="http://www.deepclone.com/lw/b6/m1/i18n-text" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://www.deepclone.com/lw/b6/m1/i18n-text ../i18n-text.xsd">
+
+	<language id="en" name="English">
+
+		<inline-string id="pgDisplay">
+			<value>Display preferences</value>
+		</inline-string>
+		<inline-string id="pUseRLTime">
+			<value>Real-life time</value>
+		</inline-string>
+		<inline-string id="pUseRLTimeDescription">
+			<value>Selecting this option will cause all durations to be displayed using real-life minutes.</value>
+		</inline-string>
+		<inline-string id="pgMap">
+			<value>Map defaults</value>
+		</inline-string>
+		<inline-string id="pMapX">
+			<value>Map centre (X)</value>
+		</inline-string>
+		<inline-string id="pMapXDescription">
+			<value>The abscissa of the default map centre.</value>
+		</inline-string>
+		<inline-string id="pMapY">
+			<value>Map centre (Y)</value>
+		</inline-string>
+		<inline-string id="pMapYDescription">
+			<value>The ordinates of the default map centre.</value>
+		</inline-string>
+		<inline-string id="pMapSize">
+			<value>Map size</value>
+		</inline-string>
+		<inline-string id="pMapSizeDescription">
+			<value>The default size of the map.</value>
+		</inline-string>
+		<inline-string id="pgMail">
+			<value>E-mail settings</value>
+		</inline-string>
+		<inline-string id="pMailOnPM">
+			<value>Private messages</value>
+		</inline-string>
+		<inline-string id="pMailOnPMDescription">
+			<value>Select the type of e-mail notifications you will get for private messages sent by other empires.</value>
+		</inline-string>
+		<inline-string id="pMailOnAlliance">
+			<value>Alliance messages</value>
+		</inline-string>
+		<inline-string id="pMailOnAllianceDescription">
+			<value>Select the type of e-mail notifications you will get for alliance-wise messages.</value>
+		</inline-string>
+		<inline-string id="pMailOnIM">
+			<value>Internal messages</value>
+		</inline-string>
+		<inline-string id="pMailOnIMDescription">
+			<value>Select the type of e-mail notifications you will get for internal game messages.</value>
+		</inline-string>
+		<inline-string id="pMailOnAdmin">
+			<value>Messages from administrators</value>
+		</inline-string>
+		<inline-string id="pMailOnAdminDescription">
+			<value>Select the type of e-mail notifications you will get for messages sent by the game's administrators.</value>
+		</inline-string>
+
+	</language>
+	
+	
+	<language name="Français" id="fr">
+
+		<inline-string id="pgDisplay">
+			<value>Préférences d'affichage</value>
+		</inline-string>
+		<inline-string id="pUseRLTime">
+			<value>Temps réel</value>
+		</inline-string>
+		<inline-string id="pUseRLTimeDescription">
+			<value>Les durées seront affichées en utilisant de "vraies" mesures si cette option est sélectionnée.</value>
+		</inline-string>
+		<inline-string id="pgMap">
+			<value>Carte</value>
+		</inline-string>
+		<inline-string id="pMapX">
+			<value>Centre de la carte (X)</value>
+		</inline-string>
+		<inline-string id="pMapXDescription">
+			<value>L'abscisse par défaut du centre de la carte.</value>
+		</inline-string>
+		<inline-string id="pMapY">
+			<value>Centre de la carte (Y)</value>
+		</inline-string>
+		<inline-string id="pMapYDescription">
+			<value>L'ordonnée par défaut du centre de la carte.</value>
+		</inline-string>
+		<inline-string id="pMapSize">
+			<value>Taille de la carte</value>
+		</inline-string>
+		<inline-string id="pMapSizeDescription">
+			<value>La taille par défaut de la carte.</value>
+		</inline-string>
+		<inline-string id="pgMail">
+			<value>Envoi de courrier électronique</value>
+		</inline-string>
+		<inline-string id="pMailOnPM">
+			<value>Messages privés</value>
+		</inline-string>
+		<inline-string id="pMailOnPMDescription">
+			<value>Sélectionnez le type de notifications par courier électronique que vous recevrez lorsque d'autres empires vous envoient des messages privés.</value>
+		</inline-string>
+		<inline-string id="pMailOnAlliance">
+			<value>Messages d'alliance</value>
+		</inline-string>
+		<inline-string id="pMailOnAllianceDescription">
+			<value>Sélectionnez le type de notifications par courier électronique que vous recevrez lorsque vous recevez un message d'alliance.</value>
+		</inline-string>
+		<inline-string id="pMailOnIM">
+			<value>Messages internes</value>
+		</inline-string>
+		<inline-string id="pMailOnIMDescription">
+			<value>Sélectionnez le type de notifications par courier électronique que vous recevrez lorsque vous recevez un message interne du jeu.</value>
+		</inline-string>
+		<inline-string id="pMailOnAdmin">
+			<value>Messages des administrateurs</value>
+		</inline-string>
+		<inline-string id="pMailOnAdminDescription">
+			<value>Sélectionnez le type de notifications par courier électronique que vous recevrez lorsque vous recevez un message des administrateurs du jeu.</value>
+		</inline-string>
+
+	</language>
+
+</lw-text-data>
\ No newline at end of file
diff --git a/legacyworlds-server/legacyworlds-server-main/data/text/technologies.xml b/legacyworlds-server/legacyworlds-server-main/data/text/technologies.xml
new file mode 100644
index 0000000..6285c28
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-main/data/text/technologies.xml
@@ -0,0 +1,118 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<lw-text-data xmlns="http://www.deepclone.com/lw/b6/m1/i18n-text" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://www.deepclone.com/lw/b6/m1/i18n-text ../i18n-text.xsd">
+
+	<language id="en" name="English">
+
+		<inline-string id="civTech">
+			<value>Civilian technologies</value>
+		</inline-string>
+		<inline-string id="civTechDescription">
+			<value>They're not just your slaves, they're your scientists, poets and workers. Make the poets work first, then use these technologies to increase their productivity! Useless poets.</value>
+		</inline-string>
+
+		<inline-string id="indFactTech">
+			<value>Universal assemblers</value>
+		</inline-string>
+		<inline-string id="indFactTechDescription">
+			<value>You know how it is when you have a thingy-bob that you need to build but you just don't have the right tool. Well, fear no more, Universal Assemblers will solve all your problems! Build anything and everything with these clever machines, they are 1337.</value>
+		</inline-string>
+		<inline-string id="reanimationTech">
+			<value>Corpse reanimation</value>
+		</inline-string>
+		<inline-string id="reanimationTechDescription">
+			<value>Tired of workers dying too early? Want a little less perspiration in your corporation? Zombies will work, won't complain and best of all, they can be fed on almost anything! Feed them your enemies! But mostly, use them to increase factory productivity by a rather nice amount.</value>
+		</inline-string>
+		<inline-string id="superTurretTech">
+			<value>Biological generators</value>
+		</inline-string>
+		<inline-string id="superTurretTechDescription">
+			<value>For every turret a military commander wants, there is a bigger, stronger turret he wants more. Now you too can have such a turret! It will defend your planet with ease while you venture out into the galaxy, bending it to your will. Available in all good hardware stores.</value>
+		</inline-string>
+
+		<inline-string id="milTech">
+			<value>Military technologies</value>
+		</inline-string>
+		<inline-string id="milTechDescription">
+			<value>It is only one who is thoroughly acquainted with the evils of war that can thoroughly understand the profitable way of carrying it on. - Sun Tzu</value>
+		</inline-string>
+
+		<inline-string id="cruisersTech">
+			<value>Orbital construction</value>
+		</inline-string>
+		<inline-string id="cruisersTechDescription">
+			<value>Ships built on the ground must endure the stress of atmospheric flight before they are even able to dominate the vast emptiness of space. Build them in space and they will be sleeker, more powerful and now free of the need for windows. Use your brand new Cruisers to dominate the known universe.</value>
+		</inline-string>
+		<inline-string id="bCruisersTech">
+			<value>Structural reinforcement</value>
+		</inline-string>
+		<inline-string id="bCruisersTechDescription">
+			<value>The power of your Cruisers can be augmented by an improved design! Take advantage of a more structurally sound space vehicle that can bring empires to their knees with its speed and technological grace.</value>
+		</inline-string>
+		<inline-string id="dreadnoughtsTech">
+			<value>Automated space docks</value>
+		</inline-string>
+		<inline-string id="dreadnoughtsTechDescription">
+			<value>Technology has advanced. The ultimate weapon is now available. Claim the awesome power of the Dreadnought and crush your enemies. Ever wanted a tank in space? Well, now you have it. All their base are belong to you.</value>
+		</inline-string>
+
+	</language>
+	
+	
+	<language name="Français" id="fr">
+
+		<inline-string id="civTech">
+			<value>Technologies civiles</value>
+		</inline-string>
+		<inline-string id="civTechDescription">
+			<value>Ce ne sont pas uniquement vos esclaves, ce sont vos chercheurs, poètes et ouvriers. Faites travailler d'abord les poètes, puis utilisez ces technologies pour augmenter leur productivité! Poètes inutiles...</value>
+		</inline-string>
+
+		<inline-string id="indFactTech">
+			<value>Assembleurs universels</value>
+		</inline-string>
+		<inline-string id="indFactTechDescription">
+			<value>Vous savez ce que c'est d'avoir un truc à construire, alors que malheureusement vous ne diposez pas du bon outil. Eh bien, plus de peur : les Assembleurs Universels vont résoudre tous vos problèmes! Construisez tout et n'importe quoi avec ces machines intelligentes, elles sont 1337.</value>
+		</inline-string>
+		<inline-string id="reanimationTech">
+			<value>Réanimation de cadavres</value>
+		</inline-string>
+		<inline-string id="reanimationTechDescription">
+			<value>Fatigué de ces ouvriers qui passent l'arme à gauche trop tôt? Vous voulez un peu plus de transpiration dans vos ateliers ? Les zombies vont travailler, ne vont pas se plaindre, et encore mieux ils peuvent être nourris avec n'importe quoi - y compris avec vos énemis! Mais surtout, utilisez les pour augmenter de manière significative la productivité de vos usines.</value>
+		</inline-string>
+		<inline-string id="superTurretTech">
+			<value>Générateurs biologiques</value>
+		</inline-string>
+		<inline-string id="superTurretTechDescription">
+			<value>Pour chaque tourelle qu'un commandant militaire réclame, il en est une qu'il désire encore plus. Maintenant, vous aussi pouvez avoir de telles tourelles! Elles défendront vos planètes avec aisance, pendant que vous vous aventurerez dans la galaxie, la pliant à votre volonté. Disponible chez tous les bons quincaillers.</value>
+		</inline-string>
+
+		<inline-string id="milTech">
+			<value>Technologies militaires</value>
+		</inline-string>
+		<inline-string id="milTechDescription">
+			<value>Ceux qui ne comprennent pas les dommages que la guerre peut causer n'en comprendront jamais les avantages. - Sun Tzu</value>
+		</inline-string>
+
+		<inline-string id="cruisersTech">
+			<value>Construction orbitale</value>
+		</inline-string>
+		<inline-string id="cruisersTechDescription">
+			<value>Les vaisseaux construits à la surface doivent subir le stress du vol atmosphérique avant même d'être lancés à assaut du grand vide interstellaire. Construisez-les dans l'espace et ils seront plus gracieux, plus puissants, et ne nécessiteront plus de fenêtres. Utilisez vos tout nouveaux croiseurs pour dominer l'univers connu.</value>
+		</inline-string>
+		<inline-string id="bCruisersTech">
+			<value>Consolidation structurelle</value>
+		</inline-string>
+		<inline-string id="bCruisersTechDescription">
+			<value>La puissance de vos croiseurs peut être augmentée par une conception améliorée! Profitez d'un véhicule à la structure mieux adaptée à l'espace qui peut mettre des empires à genoux grâce à sa vitesse et sa finesse technologique.</value>
+		</inline-string>
+		<inline-string id="dreadnoughtsTech">
+			<value>Docks orbitaux automatisés</value>
+		</inline-string>
+		<inline-string id="dreadnoughtsTechDescription">
+			<value>La technologie a évolué. L'arme ultime est maintenant disponible. Revendiquez la puissance écrasante du cuirassé et pulvérisez vos opposants. Déjà rêvé d'un tank de l'espace ? Eh bien, maintenant, vous l'avez. All their base are belong to you.</value>
+		</inline-string>
+
+	</language>
+
+</lw-text-data>
\ No newline at end of file
diff --git a/legacyworlds-server-main/pom.xml b/legacyworlds-server/legacyworlds-server-main/pom.xml
similarity index 64%
rename from legacyworlds-server-main/pom.xml
rename to legacyworlds-server/legacyworlds-server-main/pom.xml
index 09fa63d..fd89151 100644
--- a/legacyworlds-server-main/pom.xml
+++ b/legacyworlds-server/legacyworlds-server-main/pom.xml
@@ -4,77 +4,90 @@
 	<parent>
 		<artifactId>legacyworlds-server</artifactId>
 		<groupId>com.deepclone.lw</groupId>
-		<version>1.0.0</version>
-		<relativePath>../legacyworlds-server/pom.xml</relativePath>
+		<version>5.99.2</version>
 	</parent>
 
+	<groupId>com.deepclone.lw</groupId>
 	<artifactId>legacyworlds-server-main</artifactId>
-	<version>${legacyworlds.version.main}.${legacyworlds.version.release}-${legacyworlds.version.build}</version>
-	<name>Legacy Worlds - Server - Main executable</name>
+	<version>5.99.2</version>
+	<name>Legacy Worlds server</name>
 	<description>Server main classes and JAR builder.</description>
 
 	<dependencies>
 		<dependency>
 			<artifactId>legacyworlds-server-beans-accounts</artifactId>
 			<groupId>com.deepclone.lw</groupId>
+			<version>${project.version}</version>
 		</dependency>
 		<dependency>
 			<artifactId>legacyworlds-server-beans-bt</artifactId>
 			<groupId>com.deepclone.lw</groupId>
+			<version>${project.version}</version>
 		</dependency>
 		<dependency>
 			<artifactId>legacyworlds-server-beans-eventlog</artifactId>
 			<groupId>com.deepclone.lw</groupId>
+			<version>${project.version}</version>
 		</dependency>
 		<dependency>
 			<artifactId>legacyworlds-server-beans-events</artifactId>
 			<groupId>com.deepclone.lw</groupId>
+			<version>${project.version}</version>
 		</dependency>
 		<dependency>
 			<artifactId>legacyworlds-server-beans-i18n</artifactId>
 			<groupId>com.deepclone.lw</groupId>
+			<version>${project.version}</version>
 		</dependency>
 		<dependency>
 			<artifactId>legacyworlds-server-beans-mailer</artifactId>
 			<groupId>com.deepclone.lw</groupId>
+			<version>${project.version}</version>
 		</dependency>
 		<dependency>
 			<artifactId>legacyworlds-server-beans-naming</artifactId>
 			<groupId>com.deepclone.lw</groupId>
-		</dependency>
-		<dependency>
-			<artifactId>legacyworlds-server-beans-resources</artifactId>
-			<groupId>com.deepclone.lw</groupId>
+			<version>${project.version}</version>
 		</dependency>
 		<dependency>
 			<artifactId>legacyworlds-server-beans-simple</artifactId>
 			<groupId>com.deepclone.lw</groupId>
+			<version>${project.version}</version>
 		</dependency>
 		<dependency>
 			<artifactId>legacyworlds-server-beans-system</artifactId>
 			<groupId>com.deepclone.lw</groupId>
+			<version>${project.version}</version>
 		</dependency>
 		<dependency>
-			<artifactId>legacyworlds-server-beans-technologies</artifactId>
+			<artifactId>legacyworlds-server-beans-techs</artifactId>
 			<groupId>com.deepclone.lw</groupId>
+			<version>${project.version}</version>
 		</dependency>
 		<dependency>
 			<artifactId>legacyworlds-server-beans-updates</artifactId>
 			<groupId>com.deepclone.lw</groupId>
+			<version>${project.version}</version>
 		</dependency>
 		<dependency>
 			<artifactId>legacyworlds-server-beans-user</artifactId>
 			<groupId>com.deepclone.lw</groupId>
+			<version>${project.version}</version>
 		</dependency>
 
 		<dependency>
 			<groupId>com.thoughtworks.xstream</groupId>
 			<artifactId>xstream</artifactId>
+			<version>${com.thoughtworks.xstream.version}</version>
+			<type>jar</type>
 		</dependency>
 
 		<dependency>
 			<groupId>postgresql</groupId>
 			<artifactId>postgresql</artifactId>
+			<version>8.4-701.jdbc4</version>
+			<type>jar</type>
+			<scope>runtime</scope>
 		</dependency>
 
 	</dependencies>
@@ -82,7 +95,9 @@
 	<build>
 		<plugins>
 			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
 				<artifactId>maven-jar-plugin</artifactId>
+				<version>2.2</version>
 				<executions>
 					<execution>
 						<id>default-jar</id>
@@ -102,6 +117,25 @@
 					</execution>
 				</executions>
 			</plugin>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-dependency-plugin</artifactId>
+				<executions>
+					<execution>
+						<id>copy-dependencies</id>
+						<phase>package</phase>
+						<goals>
+							<goal>copy-dependencies</goal>
+						</goals>
+						<configuration>
+							<outputDirectory>${project.build.directory}/lib</outputDirectory>
+							<overWriteReleases>false</overWriteReleases>
+							<overWriteSnapshots>false</overWriteSnapshots>
+							<overWriteIfNewer>true</overWriteIfNewer>
+						</configuration>
+					</execution>
+				</executions>
+			</plugin>
 		</plugins>
 	</build>
 
diff --git a/legacyworlds-server-main/src/main/java/com/deepclone/lw/Main.java b/legacyworlds-server/legacyworlds-server-main/src/main/java/com/deepclone/lw/Main.java
similarity index 100%
rename from legacyworlds-server-main/src/main/java/com/deepclone/lw/Main.java
rename to legacyworlds-server/legacyworlds-server-main/src/main/java/com/deepclone/lw/Main.java
diff --git a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/CLITool.java b/legacyworlds-server/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/CLITool.java
similarity index 100%
rename from legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/CLITool.java
rename to legacyworlds-server/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/CLITool.java
diff --git a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/CreateSuperuser.java b/legacyworlds-server/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/CreateSuperuser.java
similarity index 98%
rename from legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/CreateSuperuser.java
rename to legacyworlds-server/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/CreateSuperuser.java
index 2446ae1..4c92d2b 100644
--- a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/CreateSuperuser.java
+++ b/legacyworlds-server/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/CreateSuperuser.java
@@ -43,7 +43,7 @@ public class CreateSuperuser
 
 		// Load transaction manager bean
 		String[] cfg = {
-			"configuration/transactions.xml"
+			"configuration/transaction-bean.xml"
 		};
 		return new ClassPathXmlApplicationContext( cfg , true , ctx );
 	}
diff --git a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/CreateUser.java b/legacyworlds-server/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/CreateUser.java
similarity index 99%
rename from legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/CreateUser.java
rename to legacyworlds-server/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/CreateUser.java
index b418617..77bc8f5 100644
--- a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/CreateUser.java
+++ b/legacyworlds-server/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/CreateUser.java
@@ -48,7 +48,7 @@ public class CreateUser
 
 		// Load transaction manager bean
 		String[] cfg = {
-			"configuration/transactions.xml"
+			"configuration/transaction-bean.xml"
 		};
 		return new ClassPathXmlApplicationContext( cfg , true , ctx );
 	}
diff --git a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/ExportDB.java b/legacyworlds-server/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/ExportDB.java
similarity index 96%
rename from legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/ExportDB.java
rename to legacyworlds-server/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/ExportDB.java
index 717823d..488d63a 100644
--- a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/ExportDB.java
+++ b/legacyworlds-server/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/ExportDB.java
@@ -14,8 +14,8 @@ import javax.sql.DataSource;
 import org.springframework.context.support.AbstractApplicationContext;
 import org.springframework.context.support.ClassPathXmlApplicationContext;
 import org.springframework.context.support.FileSystemXmlApplicationContext;
-import org.springframework.jdbc.core.JdbcTemplate;
 import org.springframework.jdbc.core.RowMapper;
+import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
 import org.springframework.transaction.PlatformTransactionManager;
 import org.springframework.transaction.TransactionStatus;
 import org.springframework.transaction.support.TransactionCallback;
@@ -67,7 +67,7 @@ public class ExportDB
 
 	private File file;
 	private TransactionTemplate tTemplate;
-	private JdbcTemplate dTemplate;
+	private SimpleJdbcTemplate dTemplate;
 
 
 	private ClassPathXmlApplicationContext createContext( )
@@ -93,7 +93,7 @@ public class ExportDB
 		PlatformTransactionManager tManager = ctx.getBean( PlatformTransactionManager.class );
 
 		this.tTemplate = new TransactionTemplate( tManager );
-		this.dTemplate = new JdbcTemplate( dSource );
+		this.dTemplate = new SimpleJdbcTemplate( dSource );
 	}
 
 
diff --git a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/ImportBuildables.java b/legacyworlds-server/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/ImportBuildables.java
similarity index 97%
rename from legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/ImportBuildables.java
rename to legacyworlds-server/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/ImportBuildables.java
index 30124a0..863cd28 100644
--- a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/ImportBuildables.java
+++ b/legacyworlds-server/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/ImportBuildables.java
@@ -52,7 +52,6 @@ public class ImportBuildables
 
 		public CostData cost;
 
-		@XStreamAlias( "require-technology" )
 		public String tech;
 	}
 
@@ -152,7 +151,7 @@ public class ImportBuildables
 
 		// Load Hibernate bean
 		String[] cfg = {
-			"configuration/transactions.xml"
+				"configuration/context-configuration.xml" , "configuration/transaction-bean.xml"
 		};
 		return new ClassPathXmlApplicationContext( cfg , true , ctx );
 	}
@@ -184,7 +183,7 @@ public class ImportBuildables
 		this.uocBuildingDep.addParameter( "workers" , Types.INTEGER );
 		this.uocBuildingDep.addParameter( "output_type" , "building_output_type" );
 		this.uocBuildingDep.addParameter( "output" , Types.INTEGER );
-		this.uocBuildingDep.addParameter( "_technology" , Types.VARCHAR );
+		this.uocBuildingDep.addParameter( "dep_name" , Types.VARCHAR );
 
 		this.uocShipNoDep = new StoredProc( dataSource , "tech" , "uoc_ship" );
 		this.uocShipNoDep.addParameter( "name" , Types.VARCHAR );
@@ -203,7 +202,7 @@ public class ImportBuildables
 		this.uocShipDep.addParameter( "upkeep" , Types.INTEGER );
 		this.uocShipDep.addParameter( "power" , Types.INTEGER );
 		this.uocShipDep.addParameter( "flight_time" , Types.INTEGER );
-		this.uocShipDep.addParameter( "_technology" , Types.VARCHAR );
+		this.uocShipDep.addParameter( "dep_name" , Types.VARCHAR );
 	}
 
 
diff --git a/legacyworlds-server/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/ImportTechs.java b/legacyworlds-server/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/ImportTechs.java
new file mode 100644
index 0000000..a6b944e
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/ImportTechs.java
@@ -0,0 +1,392 @@
+package com.deepclone.lw.cli;
+
+
+import java.io.*;
+import java.sql.Types;
+import java.util.List;
+
+import javax.sql.DataSource;
+
+import org.apache.log4j.Logger;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.support.AbstractApplicationContext;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+import org.springframework.context.support.FileSystemXmlApplicationContext;
+import org.springframework.transaction.PlatformTransactionManager;
+import org.springframework.transaction.TransactionStatus;
+import org.springframework.transaction.support.TransactionCallback;
+import org.springframework.transaction.support.TransactionTemplate;
+
+import com.deepclone.lw.utils.StoredProc;
+import com.thoughtworks.xstream.XStream;
+import com.thoughtworks.xstream.annotations.XStreamAlias;
+import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
+import com.thoughtworks.xstream.annotations.XStreamImplicit;
+
+
+
+public class ImportTechs
+		extends CLITool
+{
+
+	private final Logger logger = Logger.getLogger( ImportTechs.class );
+
+	private static class ImportError
+			extends RuntimeException
+	{
+		private static final long serialVersionUID = 1L;
+	}
+
+	@XStreamAlias( "technologies" )
+	@SuppressWarnings( "serial" )
+	public static class Technologies
+			implements Serializable
+	{
+		@XStreamImplicit( itemFieldName = "category" )
+		public List< Category > categories;
+
+		@XStreamImplicit( itemFieldName = "technology" )
+		public List< Technology > technologies;
+	}
+
+	@SuppressWarnings( "serial" )
+	public static class Category
+			implements Serializable
+	{
+		@XStreamAsAttribute
+		public String name;
+
+		@XStreamAsAttribute
+		public String description;
+	}
+
+	@SuppressWarnings( "serial" )
+	public static class Technology
+			implements Serializable
+	{
+		@XStreamAsAttribute
+		public String name;
+
+		@XStreamAsAttribute
+		public String category;
+
+		@XStreamAsAttribute
+		public String description;
+
+		@XStreamAsAttribute
+		public int points;
+
+		@XStreamAsAttribute
+		public int cost;
+
+		@XStreamImplicit( itemFieldName = "depends" )
+		public List< Dependency > dependencies;
+	}
+
+	@SuppressWarnings( "serial" )
+	public static class Dependency
+			implements Serializable
+	{
+		@XStreamAlias( "on" )
+		@XStreamAsAttribute
+		public String dependsOn;
+	}
+
+	/** The file from which technology definitions will be loaded */
+	private File file;
+
+	/** The transaction template used to execute the import transaction */
+	private TransactionTemplate tTemplate;
+
+	/** Wrapper for the stored procedure which updates or creates technology categories */
+	private StoredProc uocCategory;
+
+	/** Wrapper for the stored procedure which updates or creates technology definitions */
+	private StoredProc uocTechnology;
+
+	/** Wrapper for the stored procedure which adds a dependency to a technology */
+	private StoredProc addDependency;
+
+
+	/**
+	 * Initialise an XStream instance using the annotations on the {@link Technologies} class and
+	 * its various component classes.
+	 * 
+	 * @return the initialised XStream instance
+	 */
+	private XStream initXStream( )
+	{
+		XStream xstream = new XStream( );
+		xstream.processAnnotations( Technologies.class );
+		return xstream;
+	}
+
+
+	/**
+	 * Load technology definitions from an XML data file, deserialising it as a {@link Technologies}
+	 * instance through XStream.
+	 * 
+	 * @return the technology definition instance or <code>null</code> if an error occurs.
+	 */
+	private Technologies loadData( )
+	{
+		FileInputStream fis;
+		try {
+			fis = new FileInputStream( this.file );
+		} catch ( FileNotFoundException e ) {
+			return null;
+		}
+
+		try {
+			XStream xstream = this.initXStream( );
+			return (Technologies) xstream.fromXML( fis );
+		} catch ( Exception e ) {
+			e.printStackTrace( );
+			return null;
+		} finally {
+			try {
+				fis.close( );
+			} catch ( IOException e ) {
+				// EMPTY
+			}
+		}
+	}
+
+
+	/**
+	 * Create a basic Spring context containing the components that may be used to connect to the
+	 * database.
+	 * 
+	 * @return the initialised Spring context
+	 */
+	private ClassPathXmlApplicationContext createContext( )
+	{
+		// Load data source properties
+		String[] dataConfig = {
+			this.getDataSource( )
+		};
+		FileSystemXmlApplicationContext ctx = new FileSystemXmlApplicationContext( dataConfig );
+		ctx.refresh( );
+
+		// Load beans
+		String[] cfg = {
+				"configuration/context-configuration.xml" , "configuration/transaction-bean.xml"
+		};
+		return new ClassPathXmlApplicationContext( cfg , true , ctx );
+	}
+
+
+	/**
+	 * Create the {@link #tTemplate} transaction template from the transaction manager in the
+	 * context. In addition, initialise stored procedure wrappers {@link #uocCategory},
+	 * {@link #uocTechnology}.
+	 * 
+	 * @param ctx
+	 *            the Spring context
+	 */
+	private void getBeans( ApplicationContext ctx )
+	{
+		PlatformTransactionManager tManager = ctx.getBean( PlatformTransactionManager.class );
+		this.tTemplate = new TransactionTemplate( tManager );
+
+		DataSource dataSource = ctx.getBean( DataSource.class );
+
+		this.uocCategory = new StoredProc( dataSource , "tech" , "uoc_category" );
+		this.uocCategory.addOutput( "rv" , Types.INTEGER );
+		this.uocCategory.addParameter( "cat_name" , Types.VARCHAR );
+		this.uocCategory.addParameter( "cat_desc" , Types.VARCHAR );
+
+		this.uocTechnology = new StoredProc( dataSource , "tech" , "uoc_technology" );
+		this.uocTechnology.addOutput( "rv" , Types.INTEGER );
+		this.uocTechnology.addParameter( "nt_name" , Types.VARCHAR );
+		this.uocTechnology.addParameter( "nt_cat" , Types.VARCHAR );
+		this.uocTechnology.addParameter( "nt_desc" , Types.VARCHAR );
+		this.uocTechnology.addParameter( "nt_points" , Types.INTEGER );
+		this.uocTechnology.addParameter( "nt_cost" , Types.INTEGER );
+
+		this.addDependency = new StoredProc( dataSource , "tech" , "add_dependency" );
+		this.addDependency.addOutput( "rv" , Types.INTEGER );
+		this.addDependency.addParameter( "nd_name" , Types.VARCHAR );
+		this.addDependency.addParameter( "nd_dep" , Types.VARCHAR );
+	}
+
+
+	/**
+	 * Import the technology data stored as a {@link Technologies} instance.
+	 * 
+	 * @param data
+	 *            the technology categories and technology definitions to import
+	 * 
+	 * @throws ImportError
+	 *             if the definitions are erroneous
+	 */
+	private void importTechnologies( Technologies data )
+	{
+		this.importCategories( data.categories );
+		for ( Technology tech : data.technologies ) {
+			this.importTechnology( tech );
+		}
+	}
+
+
+	/**
+	 * Import a single technology definition, along with its dependencies.
+	 * 
+	 * @param technology
+	 *            the technology definition to import
+	 * 
+	 * @throws ImportError
+	 *             if the definition is incorrect
+	 */
+	private void importTechnology( Technology technology )
+	{
+		this.logger.debug( "Importing technology " + technology.name );
+
+		int result = (Integer) this.uocTechnology.execute( technology.name , technology.category ,
+				technology.description , technology.points , technology.cost ).get( "rv" );
+		switch ( result ) {
+			case 0:
+				break;
+			case 1:
+				this.logger.error( "Technology " + technology.name + ": name string not found" );
+				throw new ImportError( );
+			case 2:
+				this.logger.error( "Technology " + technology.name + ": category '" + technology.category
+						+ "' not found" );
+				throw new ImportError( );
+			case 3:
+				this.logger.error( "Technology " + technology.name + ": description string '" + technology.description
+						+ "' not found" );
+				throw new ImportError( );
+			case 4:
+				this.logger.error( "Technology " + technology.name + ": invalid points and/or cost" );
+				throw new ImportError( );
+		}
+
+		if ( technology.dependencies == null ) {
+			return;
+		}
+
+		for ( Dependency dep : technology.dependencies ) {
+			result = (Integer) this.addDependency.execute( technology.name , dep.dependsOn ).get( "rv" );
+			switch ( result ) {
+				case 0:
+					break;
+				case 1:
+					this.logger.error( "Technology " + technology.name + ": not found while adding dependency" );
+					throw new ImportError( );
+				case 2:
+					this.logger.error( "Technology " + technology.name + ": dependency '" + dep.dependsOn
+							+ "' not found" );
+					throw new ImportError( );
+				case 3:
+					this.logger.error( "Technology " + technology.name + ": duplicate dependency '" + dep.dependsOn
+							+ "'" );
+					throw new ImportError( );
+			}
+		}
+	}
+
+
+	/**
+	 * Import the list of categories into the database using the <em>tech.uoc_category</em> stored
+	 * procedure.
+	 * 
+	 * @param categories
+	 *            the list of categories
+	 * 
+	 * @throws ImportError
+	 *             if the stored procedure returns a failure code
+	 */
+	private void importCategories( List< Category > categories )
+	{
+		for ( Category category : categories ) {
+			this.logger.debug( "Importing category " + category.name );
+
+			int result = (Integer) this.uocCategory.execute( category.name , category.description ).get( "rv" );
+			switch ( result ) {
+				case 0:
+					break;
+				case 1:
+					this.logger.error( "Category " + category.name + ": name string not found" );
+					throw new ImportError( );
+				case 2:
+					this.logger.error( "Category " + category.name + ": description string '" + category.description
+							+ "' not found" );
+					throw new ImportError( );
+			}
+		}
+	}
+
+
+	/**
+	 * Load the technologies and related data from the file specified on the command line, then
+	 * start a database transaction during which categories, technologies and dependencies will be
+	 * created. If anything should go wrong during the import, rollback the transaction.
+	 * 
+	 */
+	@Override
+	public void run( )
+	{
+		final Technologies data = this.loadData( );
+		if ( data == null ) {
+			System.err.println( "could not read data" );
+			return;
+		}
+
+		AbstractApplicationContext ctx = this.createContext( );
+		this.getBeans( ctx );
+		boolean rv = this.tTemplate.execute( new TransactionCallback< Boolean >( ) {
+
+			@Override
+			public Boolean doInTransaction( TransactionStatus status )
+			{
+				boolean rv;
+				try {
+					importTechnologies( data );
+					rv = true;
+				} catch ( ImportError e ) {
+					rv = false;
+				} catch ( RuntimeException e ) {
+					logger.error( "error during import" , e );
+					rv = false;
+				}
+				if ( !rv ) {
+					status.setRollbackOnly( );
+				}
+				return rv;
+			}
+
+		} );
+
+		if ( rv ) {
+			this.logger.info( "Import successful" );
+		}
+
+		this.tTemplate = null;
+		ToolBase.destroyContext( ctx );
+	}
+
+
+	/**
+	 * Make sure that the command-line parameters of this tool consist in a single file name, that
+	 * the file exists and is readable, setting {@link #file} accordingly.
+	 * 
+	 * @param options
+	 *            the array of command line parameters
+	 * 
+	 * @return <code>true</code> if the parameters are ok, <code>false</code> otherwise.
+	 */
+	@Override
+	public boolean setOptions( String... options )
+	{
+		if ( options.length != 1 ) {
+			return false;
+		}
+		this.file = new File( options[ 0 ] );
+		if ( ! ( this.file.isFile( ) && this.file.canRead( ) ) ) {
+			return false;
+		}
+		return true;
+	}
+}
diff --git a/legacyworlds-server/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/ImportText.java b/legacyworlds-server/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/ImportText.java
new file mode 100644
index 0000000..c395263
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/ImportText.java
@@ -0,0 +1,145 @@
+package com.deepclone.lw.cli;
+
+
+import java.io.*;
+import java.util.Map;
+
+import javax.sql.DataSource;
+
+import org.apache.log4j.Logger;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.support.AbstractApplicationContext;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+import org.springframework.context.support.FileSystemXmlApplicationContext;
+import org.springframework.jdbc.core.SqlParameter;
+import org.springframework.jdbc.core.simple.SimpleJdbcCall;
+import org.springframework.transaction.PlatformTransactionManager;
+import org.springframework.transaction.TransactionStatus;
+import org.springframework.transaction.support.TransactionCallback;
+import org.springframework.transaction.support.TransactionTemplate;
+
+import com.deepclone.lw.cli.i18n.LoadableText;
+import com.deepclone.lw.cli.i18n.Loader;
+
+
+
+public class ImportText
+		extends CLITool
+{
+
+	private final Logger logger = Logger.getLogger( ImportText.class );
+
+	private File file;
+	private TransactionTemplate tTemplate;
+	private SimpleJdbcCall uocTranslation;
+	private SimpleJdbcCall uocLanguage;
+
+
+	private ClassPathXmlApplicationContext createContext( )
+	{
+		// Load data source and Hibernate properties
+		String[] dataConfig = {
+			this.getDataSource( ) ,
+		};
+		FileSystemXmlApplicationContext ctx = new FileSystemXmlApplicationContext( dataConfig );
+		ctx.refresh( );
+
+		// Load transaction manager bean
+		String[] cfg = {
+			"configuration/transaction-bean.xml"
+		};
+		return new ClassPathXmlApplicationContext( cfg , true , ctx );
+	}
+
+
+	private void createTemplates( ApplicationContext ctx )
+	{
+		DataSource dSource = ctx.getBean( DataSource.class );
+		PlatformTransactionManager tManager = ctx.getBean( PlatformTransactionManager.class );
+
+		this.uocLanguage = new SimpleJdbcCall( dSource ).withCatalogName( "defs" ).withProcedureName( "uoc_language" );
+		this.uocLanguage.withoutProcedureColumnMetaDataAccess( );
+		this.uocLanguage.declareParameters( new SqlParameter( "lid" , java.sql.Types.VARCHAR ) , new SqlParameter(
+				"lname" , java.sql.Types.VARCHAR ) );
+
+		this.uocTranslation = new SimpleJdbcCall( dSource ).withCatalogName( "defs" ).withProcedureName(
+				"uoc_translation" );
+		this.uocTranslation.withoutProcedureColumnMetaDataAccess( );
+		this.uocTranslation.declareParameters( new SqlParameter( "lid" , java.sql.Types.VARCHAR ) , new SqlParameter(
+				"sid" , java.sql.Types.VARCHAR ) , new SqlParameter( "trans" , java.sql.Types.VARCHAR ) );
+
+		this.tTemplate = new TransactionTemplate( tManager );
+	}
+
+
+	private void importText( LoadableText data )
+	{
+		for ( String lId : data.getLanguages( ) ) {
+			this.importLanguage( data , lId );
+		}
+	}
+
+
+	private void importLanguage( LoadableText data , String lId )
+	{
+		// Try creating or updating the language
+		this.uocLanguage.execute( lId , data.getLanguageName( lId ) );
+
+		// Import translations
+		for ( Map.Entry< String , String > string : data.getStrings( lId ) ) {
+			System.out.println( "Language " + lId + " string " + string.getKey( ) );
+			this.uocTranslation.execute( lId , string.getKey( ) , string.getValue( ) );
+		}
+	}
+
+
+	@Override
+	public void run( )
+	{
+		Loader textLoader = new Loader( this.file );
+		final LoadableText data = textLoader.load( );
+
+		AbstractApplicationContext ctx = this.createContext( );
+		this.createTemplates( ctx );
+		boolean rv = this.tTemplate.execute( new TransactionCallback< Boolean >( ) {
+
+			@Override
+			public Boolean doInTransaction( TransactionStatus status )
+			{
+				boolean rv;
+				try {
+					importText( data );
+					rv = true;
+				} catch ( RuntimeException e ) {
+					logger.error( "Caught runtime exception" , e );
+					rv = false;
+				}
+				if ( !rv ) {
+					status.setRollbackOnly( );
+				}
+				return rv;
+			}
+
+		} );
+
+		if ( rv ) {
+			System.out.println( "Text import successful" );
+		}
+
+		ToolBase.destroyContext( ctx );
+	}
+
+
+	@Override
+	public boolean setOptions( String... options )
+	{
+		if ( options.length != 1 ) {
+			return false;
+		}
+		this.file = new File( options[ 0 ] );
+		if ( ! ( this.file.isFile( ) && this.file.canRead( ) ) ) {
+			return false;
+		}
+		return true;
+	}
+}
diff --git a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/Stop.java b/legacyworlds-server/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/Stop.java
similarity index 100%
rename from legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/Stop.java
rename to legacyworlds-server/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/Stop.java
diff --git a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/Tick.java b/legacyworlds-server/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/Tick.java
similarity index 100%
rename from legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/Tick.java
rename to legacyworlds-server/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/Tick.java
diff --git a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/ToolBase.java b/legacyworlds-server/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/ToolBase.java
similarity index 100%
rename from legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/ToolBase.java
rename to legacyworlds-server/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/ToolBase.java
diff --git a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/dbexport/Administrator.java b/legacyworlds-server/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/dbexport/Administrator.java
similarity index 100%
rename from legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/dbexport/Administrator.java
rename to legacyworlds-server/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/dbexport/Administrator.java
diff --git a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/dbexport/BREComment.java b/legacyworlds-server/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/dbexport/BREComment.java
similarity index 100%
rename from legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/dbexport/BREComment.java
rename to legacyworlds-server/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/dbexport/BREComment.java
diff --git a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/dbexport/BREInitialReport.java b/legacyworlds-server/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/dbexport/BREInitialReport.java
similarity index 100%
rename from legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/dbexport/BREInitialReport.java
rename to legacyworlds-server/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/dbexport/BREInitialReport.java
diff --git a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/dbexport/BREMerger.java b/legacyworlds-server/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/dbexport/BREMerger.java
similarity index 100%
rename from legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/dbexport/BREMerger.java
rename to legacyworlds-server/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/dbexport/BREMerger.java
diff --git a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/dbexport/BREStatusChange.java b/legacyworlds-server/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/dbexport/BREStatusChange.java
similarity index 100%
rename from legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/dbexport/BREStatusChange.java
rename to legacyworlds-server/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/dbexport/BREStatusChange.java
diff --git a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/dbexport/BREVisibilityChange.java b/legacyworlds-server/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/dbexport/BREVisibilityChange.java
similarity index 100%
rename from legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/dbexport/BREVisibilityChange.java
rename to legacyworlds-server/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/dbexport/BREVisibilityChange.java
diff --git a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/dbexport/BugEventMapper.java b/legacyworlds-server/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/dbexport/BugEventMapper.java
similarity index 100%
rename from legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/dbexport/BugEventMapper.java
rename to legacyworlds-server/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/dbexport/BugEventMapper.java
diff --git a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/dbexport/BugGroup.java b/legacyworlds-server/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/dbexport/BugGroup.java
similarity index 100%
rename from legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/dbexport/BugGroup.java
rename to legacyworlds-server/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/dbexport/BugGroup.java
diff --git a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/dbexport/BugReportEvent.java b/legacyworlds-server/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/dbexport/BugReportEvent.java
similarity index 100%
rename from legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/dbexport/BugReportEvent.java
rename to legacyworlds-server/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/dbexport/BugReportEvent.java
diff --git a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/dbexport/BugReports.java b/legacyworlds-server/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/dbexport/BugReports.java
similarity index 100%
rename from legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/dbexport/BugReports.java
rename to legacyworlds-server/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/dbexport/BugReports.java
diff --git a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/dbexport/BugSubmitter.java b/legacyworlds-server/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/dbexport/BugSubmitter.java
similarity index 100%
rename from legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/dbexport/BugSubmitter.java
rename to legacyworlds-server/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/dbexport/BugSubmitter.java
diff --git a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/dbexport/LegacyWorldsDB.java b/legacyworlds-server/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/dbexport/LegacyWorldsDB.java
similarity index 100%
rename from legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/dbexport/LegacyWorldsDB.java
rename to legacyworlds-server/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/dbexport/LegacyWorldsDB.java
diff --git a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/dbexport/User.java b/legacyworlds-server/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/dbexport/User.java
similarity index 100%
rename from legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/dbexport/User.java
rename to legacyworlds-server/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/dbexport/User.java
diff --git a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/dbexport/UserMapper.java b/legacyworlds-server/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/dbexport/UserMapper.java
similarity index 100%
rename from legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/dbexport/UserMapper.java
rename to legacyworlds-server/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/dbexport/UserMapper.java
diff --git a/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/dbexport/Warnings.java b/legacyworlds-server/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/dbexport/Warnings.java
similarity index 100%
rename from legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/dbexport/Warnings.java
rename to legacyworlds-server/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/dbexport/Warnings.java
diff --git a/legacyworlds-server/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/i18n/FileString.java b/legacyworlds-server/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/i18n/FileString.java
new file mode 100644
index 0000000..d75eb08
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/i18n/FileString.java
@@ -0,0 +1,54 @@
+/**
+ * 
+ */
+package com.deepclone.lw.cli.i18n;
+
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+
+import com.thoughtworks.xstream.annotations.XStreamAlias;
+import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
+
+
+
+@SuppressWarnings( "serial" )
+@XStreamAlias( "from-file" )
+public class FileString
+		extends StringData
+{
+	private File sourceFile;
+
+	@XStreamAsAttribute
+	public String source;
+
+
+	@Override
+	public String getString( )
+	{
+		StringBuilder sBuilder = new StringBuilder( );
+		System.out.println( "Loading text from " + this.sourceFile.getAbsolutePath( ) );
+		try {
+			BufferedReader in = new BufferedReader( new FileReader( this.sourceFile ) );
+			String str;
+			while ( ( str = in.readLine( ) ) != null ) {
+				sBuilder.append( str );
+				sBuilder.append( "\n" );
+			}
+			in.close( );
+		} catch ( IOException e ) {
+			throw new RuntimeException( "Could not read " + this.sourceFile.getAbsolutePath( ) );
+		}
+
+		return sBuilder.toString( );
+	}
+
+
+	@Override
+	public void setLoader( Loader loader )
+	{
+		this.sourceFile = new File( loader.getDirectory( ) , this.source );
+	}
+}
\ No newline at end of file
diff --git a/legacyworlds-server/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/i18n/InlineString.java b/legacyworlds-server/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/i18n/InlineString.java
new file mode 100644
index 0000000..4114589
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/i18n/InlineString.java
@@ -0,0 +1,28 @@
+/**
+ * 
+ */
+package com.deepclone.lw.cli.i18n;
+
+import com.thoughtworks.xstream.annotations.XStreamAlias;
+
+@SuppressWarnings( "serial" )
+@XStreamAlias( "inline-string" )
+public class InlineString
+		extends StringData
+{
+	public String value;
+
+
+	@Override
+	public String getString( )
+	{
+		return this.value;
+	}
+
+
+	@Override
+	public void setLoader( Loader loader )
+	{
+		// EMPTY
+	}
+}
\ No newline at end of file
diff --git a/legacyworlds-server/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/i18n/LanguageData.java b/legacyworlds-server/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/i18n/LanguageData.java
new file mode 100644
index 0000000..f199bbe
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/i18n/LanguageData.java
@@ -0,0 +1,36 @@
+/**
+ * 
+ */
+package com.deepclone.lw.cli.i18n;
+
+
+import java.io.Serializable;
+import java.util.LinkedList;
+import java.util.List;
+
+import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
+import com.thoughtworks.xstream.annotations.XStreamImplicit;
+
+
+
+@SuppressWarnings( "serial" )
+public class LanguageData
+		implements Serializable
+{
+	@XStreamAsAttribute
+	public String id;
+
+	@XStreamAsAttribute
+	public String name;
+
+	@XStreamImplicit
+	public List< StringData > strings = new LinkedList< StringData >( );
+
+
+	public void setLoader( Loader loader )
+	{
+		for ( StringData sd : this.strings ) {
+			sd.setLoader( loader );
+		}
+	}
+}
\ No newline at end of file
diff --git a/legacyworlds-server/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/i18n/LoadableText.java b/legacyworlds-server/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/i18n/LoadableText.java
new file mode 100644
index 0000000..96655d3
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/i18n/LoadableText.java
@@ -0,0 +1,73 @@
+package com.deepclone.lw.cli.i18n;
+
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+
+
+public class LoadableText
+{
+
+	private final Map< String , String > languageNames;
+	private final Map< String , Map< String , String >> text;
+
+
+	public LoadableText( TextData data )
+	{
+		this.languageNames = new HashMap< String , String >( );
+		this.text = new HashMap< String , Map< String , String > >( );
+
+		if ( data.languages == null ) {
+			return;
+		}
+
+		for ( LanguageData language : data.languages ) {
+			this.languageNames.put( language.id , language.name );
+			Map< String , String > strings = new HashMap< String , String >( );
+			this.text.put( language.id , strings );
+
+			for ( StringData string : language.strings ) {
+				strings.put( string.id , string.getString( ) );
+			}
+		}
+	}
+
+
+	public void merge( LoadableText text )
+	{
+		for ( Map.Entry< String , String > entry : text.languageNames.entrySet( ) ) {
+			Map< String , String > lStrings = this.text.get( entry.getKey( ) );
+			if ( lStrings == null ) {
+				this.languageNames.put( entry.getKey( ) , entry.getValue( ) );
+				lStrings = new HashMap< String , String >( );
+				this.text.put( entry.getKey( ) , lStrings );
+			}
+
+			for ( Map.Entry< String , String > string : text.text.get( entry.getKey( ) ).entrySet( ) ) {
+				if ( lStrings.put( string.getKey( ) , string.getValue( ) ) != null ) {
+					throw new RuntimeException( "String '" + string.getKey( ) + "' defined more than once" );
+				}
+			}
+		}
+	}
+
+
+	public Set< String > getLanguages( )
+	{
+		return this.languageNames.keySet( );
+	}
+
+
+	public String getLanguageName( String lId )
+	{
+		return this.languageNames.get( lId );
+	}
+
+
+	public Set< Map.Entry< String , String >> getStrings( String lId )
+	{
+		return this.text.get( lId ).entrySet( );
+	}
+}
diff --git a/legacyworlds-server/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/i18n/Loader.java b/legacyworlds-server/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/i18n/Loader.java
new file mode 100644
index 0000000..f00f41e
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/i18n/Loader.java
@@ -0,0 +1,99 @@
+package com.deepclone.lw.cli.i18n;
+
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.Set;
+
+import com.thoughtworks.xstream.XStream;
+
+
+
+public class Loader
+{
+
+	private final Set< String > included;
+	private final XStream xstream;
+	private final File file;
+	private final String directory;
+
+
+	public Loader( File file )
+	{
+		this.included = new HashSet< String >( );
+		this.xstream = new XStream( );
+		this.xstream.processAnnotations( TextData.class );
+		this.xstream.processAnnotations( InlineString.class );
+		this.xstream.processAnnotations( FileString.class );
+		this.file = file;
+		this.directory = this.file.getAbsoluteFile( ).getParent( );
+	}
+
+
+	public Loader( Loader parent , String included )
+	{
+		this.included = parent.included;
+		this.xstream = parent.xstream;
+		if ( included.charAt( 0 ) == '/' ) {
+			this.file = new File( included );
+		} else {
+			this.file = new File( parent.directory , included );
+		}
+		this.directory = this.file.getAbsoluteFile( ).getParent( );
+	}
+
+
+	public LoadableText load( )
+	{
+		System.out.println( "Loading data file " + this.file.getAbsolutePath( ) );
+
+		TextData data = this.loadFile( );
+		data.setLoader( this );
+
+		LoadableText result = new LoadableText( data );
+		if ( data.includes != null ) {
+			for ( String file : data.includes ) {
+				Loader child = new Loader( this , file );
+				if ( this.included.contains( child.file.getAbsolutePath( ) ) ) {
+					continue;
+				}
+				this.included.add( child.file.getAbsolutePath( ) );
+				result.merge( child.load( ) );
+			}
+		}
+
+		return result;
+	}
+
+
+	private TextData loadFile( )
+	{
+		FileInputStream fis;
+		try {
+			fis = new FileInputStream( this.file );
+		} catch ( FileNotFoundException e ) {
+			throw new RuntimeException( e );
+		}
+
+		try {
+			return (TextData) this.xstream.fromXML( fis );
+		} catch ( Exception e ) {
+			throw new RuntimeException( e );
+		} finally {
+			try {
+				fis.close( );
+			} catch ( IOException e ) {
+				// EMPTY
+			}
+		}
+	}
+
+
+	public String getDirectory( )
+	{
+		return this.directory;
+	}
+}
diff --git a/legacyworlds-server/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/i18n/StringData.java b/legacyworlds-server/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/i18n/StringData.java
new file mode 100644
index 0000000..0dac4a5
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/i18n/StringData.java
@@ -0,0 +1,25 @@
+/**
+ * 
+ */
+package com.deepclone.lw.cli.i18n;
+
+
+import java.io.Serializable;
+
+import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
+
+
+
+@SuppressWarnings( "serial" )
+public abstract class StringData
+		implements Serializable
+{
+	@XStreamAsAttribute
+	public String id;
+
+
+	public abstract String getString( );
+
+
+	public abstract void setLoader( Loader loader );
+}
\ No newline at end of file
diff --git a/legacyworlds-server/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/i18n/TextData.java b/legacyworlds-server/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/i18n/TextData.java
new file mode 100644
index 0000000..3a93efc
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-main/src/main/java/com/deepclone/lw/cli/i18n/TextData.java
@@ -0,0 +1,34 @@
+/**
+ * 
+ */
+package com.deepclone.lw.cli.i18n;
+
+
+import java.io.Serializable;
+import java.util.LinkedList;
+import java.util.List;
+
+import com.thoughtworks.xstream.annotations.XStreamAlias;
+import com.thoughtworks.xstream.annotations.XStreamImplicit;
+
+
+
+@SuppressWarnings( "serial" )
+@XStreamAlias( "lw-text-data" )
+public class TextData
+		implements Serializable
+{
+	@XStreamImplicit( itemFieldName = "include" )
+	public List< String > includes = new LinkedList< String >( );
+
+	@XStreamImplicit( itemFieldName = "language" )
+	public List< LanguageData > languages = new LinkedList< LanguageData >( );
+
+
+	public void setLoader( Loader loader )
+	{
+		for ( LanguageData l : this.languages ) {
+			l.setLoader( loader );
+		}
+	}
+}
\ No newline at end of file
diff --git a/legacyworlds-server-main/src/main/java/com/deepclone/lw/srv/LogAppender.java b/legacyworlds-server/legacyworlds-server-main/src/main/java/com/deepclone/lw/srv/LogAppender.java
similarity index 100%
rename from legacyworlds-server-main/src/main/java/com/deepclone/lw/srv/LogAppender.java
rename to legacyworlds-server/legacyworlds-server-main/src/main/java/com/deepclone/lw/srv/LogAppender.java
diff --git a/legacyworlds-server-main/src/main/java/com/deepclone/lw/srv/Server.java b/legacyworlds-server/legacyworlds-server-main/src/main/java/com/deepclone/lw/srv/Server.java
similarity index 79%
rename from legacyworlds-server-main/src/main/java/com/deepclone/lw/srv/Server.java
rename to legacyworlds-server/legacyworlds-server-main/src/main/java/com/deepclone/lw/srv/Server.java
index f6a41e0..7f91446 100644
--- a/legacyworlds-server-main/src/main/java/com/deepclone/lw/srv/Server.java
+++ b/legacyworlds-server/legacyworlds-server-main/src/main/java/com/deepclone/lw/srv/Server.java
@@ -38,9 +38,10 @@ public class Server
 		builder.setScope( BeanDefinition.SCOPE_SINGLETON );
 		builder.addPropertyValue( "serviceName" , name );
 		builder.addPropertyValue( "service" , bean );
-		builder.addPropertyValue( "ServiceInterface" , iface.getCanonicalName( ) );
+		builder.addPropertyValue( "serviceInterface" , iface.getCanonicalName( ) );
 		builder.addPropertyValue( "registryPort" , String.valueOf( this.getRmiPort( ) ) );
 		builder.addPropertyValue( "servicePort" , String.valueOf( sPort ) );
+		builder.addPropertyValue( "registryHost" , "localhost" );
 		ctx.registerBeanDefinition( name , builder.getBeanDefinition( ) );
 	}
 
@@ -48,17 +49,31 @@ public class Server
 	private AbstractApplicationContext makeRMIContext( ApplicationContext parent )
 	{
 		GenericApplicationContext context = new GenericApplicationContext( parent );
-		this.addRMIService( context , "termSrv" , parent.getBean( "terminator" ) , ServerTerminator.class , this.getTerminationPort( ) );
-		this.addRMIService( context , "sessionSrv" , parent.getBean( "sessionManager" ) , SessionManager.class , this.getServicePort( ) );
+		this.addRMIRegistry( context );
+		this.addRMIService( context , "termSrv" , parent.getBean( "terminator" ) , ServerTerminator.class , this
+				.getTerminationPort( ) );
+		this.addRMIService( context , "sessionSrv" , parent.getBean( "sessionManager" ) , SessionManager.class , this
+				.getServicePort( ) );
 		context.refresh( );
 		return context;
 	}
 
 
+	private void addRMIRegistry( GenericApplicationContext context )
+	{
+		BeanDefinitionBuilder builder;
+		builder = BeanDefinitionBuilder.rootBeanDefinition( "org.springframework.remoting.rmi.RmiRegistryFactoryBean" );
+		builder.setScope( BeanDefinition.SCOPE_SINGLETON );
+		builder.addPropertyValue( "port" , String.valueOf( this.getRmiPort( ) ) );
+		builder.addPropertyValue( "alwaysCreate" , "true" );
+		context.registerBeanDefinition( "rmiRegistry" , builder.getBeanDefinition( ) );
+	}
+
+
 	private ApplicationContext makeDataConfigContext( )
 	{
 		String[] dSource = {
-				this.getDataSource( ) ,
+			this.getDataSource( ) ,
 		};
 		FileSystemXmlApplicationContext ctx = new FileSystemXmlApplicationContext( dSource );
 		ctx.refresh( );
diff --git a/legacyworlds-server-main/src/main/java/com/deepclone/lw/srv/ServerTerminator.java b/legacyworlds-server/legacyworlds-server-main/src/main/java/com/deepclone/lw/srv/ServerTerminator.java
similarity index 100%
rename from legacyworlds-server-main/src/main/java/com/deepclone/lw/srv/ServerTerminator.java
rename to legacyworlds-server/legacyworlds-server-main/src/main/java/com/deepclone/lw/srv/ServerTerminator.java
diff --git a/legacyworlds-server-main/src/main/java/com/deepclone/lw/srv/ServerTerminatorBean.java b/legacyworlds-server/legacyworlds-server-main/src/main/java/com/deepclone/lw/srv/ServerTerminatorBean.java
similarity index 100%
rename from legacyworlds-server-main/src/main/java/com/deepclone/lw/srv/ServerTerminatorBean.java
rename to legacyworlds-server/legacyworlds-server-main/src/main/java/com/deepclone/lw/srv/ServerTerminatorBean.java
diff --git a/legacyworlds-server/legacyworlds-server-main/src/main/resources/configuration/context-configuration.xml b/legacyworlds-server/legacyworlds-server-main/src/main/resources/configuration/context-configuration.xml
new file mode 100644
index 0000000..11e1a81
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-main/src/main/resources/configuration/context-configuration.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
+	xsi:schemaLocation="http://www.springframework.org/schema/beans 
+           http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
+           http://www.springframework.org/schema/context
+           http://www.springframework.org/schema/context/spring-context-3.0.xsd">
+
+	<context:annotation-config />
+
+</beans>
\ No newline at end of file
diff --git a/legacyworlds-server-main/src/main/resources/log4j.properties b/legacyworlds-server/legacyworlds-server-main/src/main/resources/log4j.properties
similarity index 97%
rename from legacyworlds-server-main/src/main/resources/log4j.properties
rename to legacyworlds-server/legacyworlds-server-main/src/main/resources/log4j.properties
index 066fac3..994c335 100644
--- a/legacyworlds-server-main/src/main/resources/log4j.properties
+++ b/legacyworlds-server/legacyworlds-server-main/src/main/resources/log4j.properties
@@ -36,4 +36,3 @@ log4j.logger.org.springframework=WARN, server
 log4j.logger.org.springframework=INFO, fullDebug
 log4j.logger.com.deepclone.lw=DEBUG, fullDebug
 log4j.logger.com.deepclone.lw.interfaces.eventlog=DEBUG, server
-log4j.logger.com.deepclone.lw.cli=INFO, stdout
diff --git a/legacyworlds-server/legacyworlds-server-main/src/main/resources/lw-server.xml b/legacyworlds-server/legacyworlds-server-main/src/main/resources/lw-server.xml
new file mode 100644
index 0000000..96b67dc
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-main/src/main/resources/lw-server.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
+	xsi:schemaLocation="
+                        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
+                        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
+
+	<context:annotation-config />
+
+	<!-- Server terminator bean -->
+	<bean id="terminator" class="com.deepclone.lw.srv.ServerTerminatorBean" />
+
+	<!-- Load transaction manager -->
+	<import resource="configuration/transaction-bean.xml" />
+
+	<!-- Load all server beans -->
+	<import resource="configuration/accounts-beans.xml" />
+	<import resource="configuration/bt-beans.xml" />
+	<import resource="configuration/eventlog-beans.xml" />
+	<import resource="configuration/i18n-beans.xml" />
+	<import resource="configuration/mailer-beans.xml" />
+	<import resource="configuration/naming-beans.xml" />
+	<import resource="configuration/simple-beans.xml" />
+	<import resource="configuration/system-beans.xml" />
+	<import resource="configuration/techs-beans.xml" />
+	<import resource="configuration/updates-beans.xml" />
+	<import resource="configuration/user-beans.xml" />
+
+</beans>
diff --git a/legacyworlds-server/legacyworlds-server-tests/.classpath b/legacyworlds-server/legacyworlds-server-tests/.classpath
new file mode 100644
index 0000000..7c3d14f
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-tests/.classpath
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" output="target/classes" path="src/main/java"/>
+	<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources"/>
+	<classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
+	<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+	<classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER"/>
+	<classpathentry kind="output" path="target/classes"/>
+</classpath>
diff --git a/legacyworlds-server/legacyworlds-server-tests/.project b/legacyworlds-server/legacyworlds-server-tests/.project
new file mode 100644
index 0000000..076ecb4
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-tests/.project
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>legacyworlds-server-tests</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.maven.ide.eclipse.maven2Builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.maven.ide.eclipse.maven2Nature</nature>
+	</natures>
+</projectDescription>
diff --git a/legacyworlds-server/legacyworlds-server-tests/.settings/org.eclipse.jdt.core.prefs b/legacyworlds-server/legacyworlds-server-tests/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..96c9dfc
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-tests/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,6 @@
+#Fri Apr 09 10:20:32 CEST 2010
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.6
diff --git a/legacyworlds-server-tests/pom.xml b/legacyworlds-server/legacyworlds-server-tests/pom.xml
similarity index 74%
rename from legacyworlds-server-tests/pom.xml
rename to legacyworlds-server/legacyworlds-server-tests/pom.xml
index 93d6a74..02965d2 100644
--- a/legacyworlds-server-tests/pom.xml
+++ b/legacyworlds-server/legacyworlds-server-tests/pom.xml
@@ -4,69 +4,72 @@
 	<parent>
 		<artifactId>legacyworlds-server</artifactId>
 		<groupId>com.deepclone.lw</groupId>
-		<version>1.0.0</version>
-		<relativePath>../legacyworlds-server/pom.xml</relativePath>
+		<version>5.99.2</version>
 	</parent>
 
+	<groupId>com.deepclone.lw</groupId>
 	<artifactId>legacyworlds-server-tests</artifactId>
-	<version>${legacyworlds.version.main}.${legacyworlds.version.release}-${legacyworlds.version.build}</version>
-	<name>Legacy Worlds - Server - Tests</name>
-	<description>This package contains all tests for server capabilities.</description>
+	<name>Legacy Worlds server tests</name>
+	<version>5.99.2</version>
+	<description>This package regroups all tests for server capabilities.</description>
 
 	<dependencies>
 		<dependency>
 			<artifactId>legacyworlds-server-beans-accounts</artifactId>
 			<groupId>com.deepclone.lw</groupId>
+			<version>${project.version}</version>
 		</dependency>
 		<dependency>
 			<artifactId>legacyworlds-server-beans-bt</artifactId>
 			<groupId>com.deepclone.lw</groupId>
+			<version>${project.version}</version>
 		</dependency>
 		<dependency>
 			<artifactId>legacyworlds-server-beans-eventlog</artifactId>
 			<groupId>com.deepclone.lw</groupId>
-		</dependency>
-		<dependency>
-			<artifactId>legacyworlds-server-beans-events</artifactId>
-			<groupId>com.deepclone.lw</groupId>
+			<version>${project.version}</version>
 		</dependency>
 		<dependency>
 			<artifactId>legacyworlds-server-beans-i18n</artifactId>
 			<groupId>com.deepclone.lw</groupId>
+			<version>${project.version}</version>
 		</dependency>
 		<dependency>
 			<artifactId>legacyworlds-server-beans-mailer</artifactId>
 			<groupId>com.deepclone.lw</groupId>
+			<version>${project.version}</version>
 		</dependency>
 		<dependency>
 			<artifactId>legacyworlds-server-beans-naming</artifactId>
 			<groupId>com.deepclone.lw</groupId>
+			<version>${project.version}</version>
 		</dependency>
 		<dependency>
 			<artifactId>legacyworlds-server-beans-simple</artifactId>
 			<groupId>com.deepclone.lw</groupId>
+			<version>${project.version}</version>
 		</dependency>
 		<dependency>
 			<artifactId>legacyworlds-server-beans-system</artifactId>
 			<groupId>com.deepclone.lw</groupId>
+			<version>${project.version}</version>
 		</dependency>
 		<dependency>
 			<artifactId>legacyworlds-server-beans-user</artifactId>
 			<groupId>com.deepclone.lw</groupId>
-		</dependency>
-		<dependency>
-			<artifactId>legacyworlds-server-main</artifactId>
-			<groupId>com.deepclone.lw</groupId>
+			<version>${project.version}</version>
 		</dependency>
 
 		<dependency>
 			<groupId>junit</groupId>
 			<artifactId>junit</artifactId>
+			<version>${junit.version}</version>
 			<scope>test</scope>
 		</dependency>
 		<dependency>
 			<groupId>org.springframework</groupId>
 			<artifactId>spring-test</artifactId>
+			<version>${org.springframework.version}</version>
 			<scope>test</scope>
 		</dependency>
 	</dependencies>
diff --git a/legacyworlds-server/legacyworlds-server-utils/.classpath b/legacyworlds-server/legacyworlds-server-utils/.classpath
new file mode 100644
index 0000000..7c3d14f
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-utils/.classpath
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" output="target/classes" path="src/main/java"/>
+	<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources"/>
+	<classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
+	<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+	<classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER"/>
+	<classpathentry kind="output" path="target/classes"/>
+</classpath>
diff --git a/legacyworlds-server/legacyworlds-server-utils/.project b/legacyworlds-server/legacyworlds-server-utils/.project
new file mode 100644
index 0000000..fc174e7
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-utils/.project
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>legacyworlds-server-utils</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.maven.ide.eclipse.maven2Builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.maven.ide.eclipse.maven2Nature</nature>
+	</natures>
+</projectDescription>
diff --git a/legacyworlds-server/legacyworlds-server-utils/.settings/org.eclipse.jdt.core.prefs b/legacyworlds-server/legacyworlds-server-utils/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..6939a66
--- /dev/null
+++ b/legacyworlds-server/legacyworlds-server-utils/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,6 @@
+#Fri Apr 09 10:20:36 CEST 2010
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.6
diff --git a/legacyworlds-server-utils/pom.xml b/legacyworlds-server/legacyworlds-server-utils/pom.xml
similarity index 71%
rename from legacyworlds-server-utils/pom.xml
rename to legacyworlds-server/legacyworlds-server-utils/pom.xml
index 6925d1c..989be1b 100644
--- a/legacyworlds-server-utils/pom.xml
+++ b/legacyworlds-server/legacyworlds-server-utils/pom.xml
@@ -4,19 +4,20 @@
 	<parent>
 		<artifactId>legacyworlds-server</artifactId>
 		<groupId>com.deepclone.lw</groupId>
-		<version>1.0.0</version>
-		<relativePath>../legacyworlds-server/pom.xml</relativePath>
+		<version>5.99.2</version>
 	</parent>
 
+	<groupId>com.deepclone.lw</groupId>
 	<artifactId>legacyworlds-server-utils</artifactId>
-	<version>${legacyworlds.version.main}.${legacyworlds.version.release}-${legacyworlds.version.build}</version>
-	<name>Legacy Worlds - Server - Utility classes</name>
+	<version>5.99.2</version>
+	<name>Legacy Worlds server utility classes</name>
 	<description>This package contains utility classes used by various parts of the server-side code.</description>
 
 	<dependencies>
 		<dependency>
 			<groupId>com.deepclone.lw</groupId>
 			<artifactId>legacyworlds-utils</artifactId>
+			<version>${project.version}</version>
 		</dependency>
 	</dependencies>
-</project>
+</project>
\ No newline at end of file
diff --git a/legacyworlds-server-utils/src/main/java/com/deepclone/lw/utils/Base64Serializer.java b/legacyworlds-server/legacyworlds-server-utils/src/main/java/com/deepclone/lw/utils/Base64Serializer.java
similarity index 100%
rename from legacyworlds-server-utils/src/main/java/com/deepclone/lw/utils/Base64Serializer.java
rename to legacyworlds-server/legacyworlds-server-utils/src/main/java/com/deepclone/lw/utils/Base64Serializer.java
diff --git a/legacyworlds-server-utils/src/main/java/com/deepclone/lw/utils/EmailAddress.java b/legacyworlds-server/legacyworlds-server-utils/src/main/java/com/deepclone/lw/utils/EmailAddress.java
similarity index 95%
rename from legacyworlds-server-utils/src/main/java/com/deepclone/lw/utils/EmailAddress.java
rename to legacyworlds-server/legacyworlds-server-utils/src/main/java/com/deepclone/lw/utils/EmailAddress.java
index 5f1a169..526ea78 100644
--- a/legacyworlds-server-utils/src/main/java/com/deepclone/lw/utils/EmailAddress.java
+++ b/legacyworlds-server/legacyworlds-server-utils/src/main/java/com/deepclone/lw/utils/EmailAddress.java
@@ -29,7 +29,7 @@ public class EmailAddress
 	private static final String quotedPair = "(\\\\" + asciiText + ")";
 
 	// RFC 2822 3.2.4 Atom:
-	private static final String atext = "[a-zA-Z0-9\\!\\#\\$\\%\\&amp;\\'\\*\\+\\-\\/\\=\\?\\^\\_\\`\\{\\|\\}\\~]";
+	private static final String atext = "[a-zA-Z0-9\\!\\#\\$\\%\\&\\'\\*\\+\\-\\/\\=\\?\\^\\_\\`\\{\\|\\}\\~]";
 	private static final String dotAtomText = atext + "+" + "(" + "\\." + atext + "+)*";
 	private static final String dotAtom = fwsp + "(" + dotAtomText + ")" + fwsp;
 
diff --git a/legacyworlds-server-utils/src/main/java/com/deepclone/lw/utils/Password.java b/legacyworlds-server/legacyworlds-server-utils/src/main/java/com/deepclone/lw/utils/Password.java
similarity index 100%
rename from legacyworlds-server-utils/src/main/java/com/deepclone/lw/utils/Password.java
rename to legacyworlds-server/legacyworlds-server-utils/src/main/java/com/deepclone/lw/utils/Password.java
diff --git a/legacyworlds-server-utils/src/main/java/com/deepclone/lw/utils/RandomStringGenerator.java b/legacyworlds-server/legacyworlds-server-utils/src/main/java/com/deepclone/lw/utils/RandomStringGenerator.java
similarity index 100%
rename from legacyworlds-server-utils/src/main/java/com/deepclone/lw/utils/RandomStringGenerator.java
rename to legacyworlds-server/legacyworlds-server-utils/src/main/java/com/deepclone/lw/utils/RandomStringGenerator.java
diff --git a/legacyworlds-server-utils/src/main/java/com/deepclone/lw/utils/StoredProc.java b/legacyworlds-server/legacyworlds-server-utils/src/main/java/com/deepclone/lw/utils/StoredProc.java
similarity index 100%
rename from legacyworlds-server-utils/src/main/java/com/deepclone/lw/utils/StoredProc.java
rename to legacyworlds-server/legacyworlds-server-utils/src/main/java/com/deepclone/lw/utils/StoredProc.java
diff --git a/legacyworlds-server/pom.xml b/legacyworlds-server/pom.xml
index 5d5ec72..c00caab 100644
--- a/legacyworlds-server/pom.xml
+++ b/legacyworlds-server/pom.xml
@@ -4,12 +4,12 @@
 	<parent>
 		<artifactId>legacyworlds</artifactId>
 		<groupId>com.deepclone.lw</groupId>
-		<version>1.0.0</version>
-		<relativePath>../legacyworlds/pom.xml</relativePath>
+		<version>5.99.2</version>
 	</parent>
-
+	<groupId>com.deepclone.lw</groupId>
 	<artifactId>legacyworlds-server</artifactId>
-	<name>Legacy Worlds - Server</name>
+	<name>Legacy Worlds server</name>
+	<version>5.99.2</version>
 	<packaging>pom</packaging>
 	<description>This metapackage is the root of the game server's components' code.</description>
 
@@ -18,53 +18,68 @@
 		<dependency>
 			<groupId>org.springframework</groupId>
 			<artifactId>spring-core</artifactId>
+			<version>${org.springframework.version}</version>
 		</dependency>
 		<dependency>
 			<groupId>org.springframework</groupId>
 			<artifactId>spring-context</artifactId>
+			<version>${org.springframework.version}</version>
+			<exclusions>
+				<exclusion>
+					<groupId>commons-logging</groupId>
+					<artifactId>commons-logging</artifactId>
+				</exclusion>
+			</exclusions>
 		</dependency>
 		<dependency>
 			<groupId>org.springframework</groupId>
 			<artifactId>spring-jdbc</artifactId>
+			<version>${org.springframework.version}</version>
 		</dependency>
 
 		<dependency>
 			<groupId>org.slf4j</groupId>
 			<artifactId>jcl-over-slf4j</artifactId>
+			<version>${org.slf4j.version}</version>
 		</dependency>
 		<dependency>
 			<groupId>org.slf4j</groupId>
 			<artifactId>slf4j-api</artifactId>
+			<version>${org.slf4j.version}</version>
 		</dependency>
 		<dependency>
 			<groupId>org.slf4j</groupId>
 			<artifactId>slf4j-log4j12</artifactId>
+			<version>${org.slf4j.version}</version>
 		</dependency>
+
 		<dependency>
 			<groupId>log4j</groupId>
 			<artifactId>log4j</artifactId>
+			<version>${log4j.version}</version>
 		</dependency>
 
 		<dependency>
 			<groupId>commons-dbcp</groupId>
 			<artifactId>commons-dbcp</artifactId>
+			<version>${commons.dbcp.version}</version>
 		</dependency>
 
 		<dependency>
 			<groupId>cglib</groupId>
 			<artifactId>cglib</artifactId>
+			<version>${cglib.version}</version>
 		</dependency>
 
 	</dependencies>
 
 	<modules>
-		<module>../legacyworlds-server-data</module>
-		<module>../legacyworlds-server-beans</module>
-		<module>../legacyworlds-server-tests</module>
-		<module>../legacyworlds-server-interfaces</module>
-		<module>../legacyworlds-server-utils</module>
-		<module>../legacyworlds-server-main</module>
-		<module>../legacyworlds-server-DIST</module>
+		<module>legacyworlds-server-data</module>
+		<module>legacyworlds-server-beans</module>
+		<module>legacyworlds-server-tests</module>
+		<module>legacyworlds-server-interfaces</module>
+		<module>legacyworlds-server-utils</module>
+		<module>legacyworlds-server-main</module>
 	</modules>
 
-</project>
+</project>
\ No newline at end of file
diff --git a/legacyworlds-session/.classpath b/legacyworlds-session/.classpath
new file mode 100644
index 0000000..7c3d14f
--- /dev/null
+++ b/legacyworlds-session/.classpath
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" output="target/classes" path="src/main/java"/>
+	<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources"/>
+	<classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
+	<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+	<classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER"/>
+	<classpathentry kind="output" path="target/classes"/>
+</classpath>
diff --git a/legacyworlds-session/.project b/legacyworlds-session/.project
new file mode 100644
index 0000000..a0b0b33
--- /dev/null
+++ b/legacyworlds-session/.project
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>legacyworlds-session</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.maven.ide.eclipse.maven2Builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.maven.ide.eclipse.maven2Nature</nature>
+	</natures>
+</projectDescription>
diff --git a/legacyworlds-session/.settings/org.eclipse.jdt.core.prefs b/legacyworlds-session/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..8d7d4ea
--- /dev/null
+++ b/legacyworlds-session/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,6 @@
+#Tue Apr 13 16:03:03 CEST 2010
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.6
diff --git a/legacyworlds-session/.settings/org.maven.ide.eclipse.prefs b/legacyworlds-session/.settings/org.maven.ide.eclipse.prefs
new file mode 100644
index 0000000..83991fa
--- /dev/null
+++ b/legacyworlds-session/.settings/org.maven.ide.eclipse.prefs
@@ -0,0 +1,9 @@
+#Tue Apr 13 16:03:03 CEST 2010
+activeProfiles=
+eclipse.preferences.version=1
+fullBuildGoals=process-test-resources
+includeModules=false
+resolveWorkspaceProjects=true
+resourceFilterGoals=process-resources resources\:testResources
+skipCompilerPlugin=true
+version=1
diff --git a/legacyworlds-session/pom.xml b/legacyworlds-session/pom.xml
index 605acc6..941a81d 100644
--- a/legacyworlds-session/pom.xml
+++ b/legacyworlds-session/pom.xml
@@ -4,13 +4,13 @@
 	<parent>
 		<artifactId>legacyworlds</artifactId>
 		<groupId>com.deepclone.lw</groupId>
-		<version>1.0.0</version>
-		<relativePath>../legacyworlds/pom.xml</relativePath>
+		<version>5.99.2</version>
 	</parent>
 
+	<groupId>com.deepclone.lw</groupId>
 	<artifactId>legacyworlds-session</artifactId>
-	<name>Legacy Worlds - Common packages - Sessions</name>
-	<version>${legacyworlds.version.main}.${legacyworlds.version.release}-${legacyworlds.version.build}</version>
+	<version>5.99.2</version>
+	<name>Legacy Worlds sessions</name>
 	<description>This module contains the definition of sessions used in client-server communications and all related classes and exceptions.</description>
 
-</project>
+</project>
\ No newline at end of file
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/CreateAuthChallengeCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/CreateAuthChallengeCommand.java
index 3a6bbef..9cc5a34 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/CreateAuthChallengeCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/CreateAuthChallengeCommand.java
@@ -1,11 +1,12 @@
 package com.deepclone.lw.cmd;
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 public class CreateAuthChallengeCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 }
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/CreateAuthChallengeResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/CreateAuthChallengeResponse.java
index 1e5ad58..d1d9692 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/CreateAuthChallengeResponse.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/CreateAuthChallengeResponse.java
@@ -1,6 +1,7 @@
 package com.deepclone.lw.cmd;
 
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.CommandResponse;
 
 
@@ -9,7 +10,7 @@ public class CreateAuthChallengeResponse
 		extends CommandResponse
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final String challenge;
 
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/MaintenanceResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/MaintenanceResponse.java
index efe9995..abd5a50 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/MaintenanceResponse.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/MaintenanceResponse.java
@@ -4,6 +4,7 @@ package com.deepclone.lw.cmd;
 import java.sql.Timestamp;
 import java.util.Date;
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.CommandResponse;
 
 
@@ -12,7 +13,7 @@ public class MaintenanceResponse
 		extends CommandResponse
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final Timestamp start;
 
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/ObjectNameError.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/ObjectNameError.java
index 493c435..650e8fb 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/ObjectNameError.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/ObjectNameError.java
@@ -1,27 +1,11 @@
 package com.deepclone.lw.cmd;
 
 
-/**
- * The results of a name validation operation
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- * 
- */
 public enum ObjectNameError {
 
-	/** The name is empty */
 	EMPTY ,
-
-	/** The name is used by another object (e.g. duplicate empire name) */
 	UNAVAILABLE ,
-
-	/** The name has been banned from being used again */
 	BANNED ,
-
-	/**
-	 * The name is invalid (too short, too long, sequences of white space, invalid characters, does
-	 * not start with a letter)
-	 */
 	INVALID
 
 }
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/AdminOverviewCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/AdminOverviewCommand.java
index fa340fe..f997300 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/AdminOverviewCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/AdminOverviewCommand.java
@@ -1,11 +1,12 @@
 package com.deepclone.lw.cmd.admin;
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 public class AdminOverviewCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 }
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/AdminOverviewResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/AdminOverviewResponse.java
index b292818..c7937c9 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/AdminOverviewResponse.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/AdminOverviewResponse.java
@@ -3,6 +3,7 @@ package com.deepclone.lw.cmd.admin;
 
 import com.deepclone.lw.cmd.admin.adata.AdminOverview;
 import com.deepclone.lw.cmd.admin.adata.Administrator;
+import com.deepclone.lw.session.API;
 
 
 
@@ -10,7 +11,7 @@ public class AdminOverviewResponse
 		extends AdminResponse
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 	private final AdminOverview overview;
 
 
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/AdminResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/AdminResponse.java
index 7be1d55..ec411f8 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/AdminResponse.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/AdminResponse.java
@@ -2,6 +2,7 @@ package com.deepclone.lw.cmd.admin;
 
 
 import com.deepclone.lw.cmd.admin.adata.Administrator;
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.CommandResponse;
 
 
@@ -10,7 +11,7 @@ public class AdminResponse
 		extends CommandResponse
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final Administrator admin;
 	private final boolean privilegeOk;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/NoOperationCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/NoOperationCommand.java
index 4765054..bc19cea 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/NoOperationCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/NoOperationCommand.java
@@ -2,6 +2,7 @@ package com.deepclone.lw.cmd.admin;
 
 
 import com.deepclone.lw.cmd.admin.adata.Privileges;
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -10,7 +11,7 @@ public class NoOperationCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final Privileges requirePrivilege;
 
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/SetPasswordCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/SetPasswordCommand.java
index 49eeb2f..baa5056 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/SetPasswordCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/SetPasswordCommand.java
@@ -1,6 +1,7 @@
 package com.deepclone.lw.cmd.admin;
 
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -9,7 +10,7 @@ public class SetPasswordCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final String sha1Auth;
 	private final String md5Auth;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/SetPasswordResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/SetPasswordResponse.java
index a4a429f..e1bcb86 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/SetPasswordResponse.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/SetPasswordResponse.java
@@ -2,6 +2,7 @@ package com.deepclone.lw.cmd.admin;
 
 
 import com.deepclone.lw.cmd.admin.adata.Administrator;
+import com.deepclone.lw.session.API;
 
 
 
@@ -9,7 +10,7 @@ public class SetPasswordResponse
 		extends AdminResponse
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	public static enum PasswordChangeStatus {
 		OK ,
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/adata/AdminOverview.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/adata/AdminOverview.java
index 4eb221b..dabaf57 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/adata/AdminOverview.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/adata/AdminOverview.java
@@ -3,13 +3,15 @@ package com.deepclone.lw.cmd.admin.adata;
 
 import java.io.Serializable;
 
+import com.deepclone.lw.session.API;
+
 
 
 public class AdminOverview
 		implements Serializable
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private int id;
 	private long newMessages;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/adata/Administrator.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/adata/Administrator.java
index 19c3dbf..91be442 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/adata/Administrator.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/adata/Administrator.java
@@ -3,13 +3,15 @@ package com.deepclone.lw.cmd.admin.adata;
 
 import java.util.List;
 
+import com.deepclone.lw.session.API;
+
 
 
 public class Administrator
 		extends AdministratorBasics
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private String address;
 	private boolean passwordChange;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/adata/AdministratorBasics.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/adata/AdministratorBasics.java
index 2f7342b..cb04d79 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/adata/AdministratorBasics.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/adata/AdministratorBasics.java
@@ -4,13 +4,15 @@ package com.deepclone.lw.cmd.admin.adata;
 import java.io.Serializable;
 import java.util.List;
 
+import com.deepclone.lw.session.API;
+
 
 
 public class AdministratorBasics
 		implements Serializable
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private int id;
 	private String name;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/adata/Privileges.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/adata/Privileges.java
index 824fb65..412c49f 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/adata/Privileges.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/adata/Privileges.java
@@ -20,6 +20,7 @@ public enum Privileges {
 	BUGM( 0x00000200 , "Receiving automated error e-mail" ) ,
 	BUGT( 0x00000400 , "Managing bugs reported through the bug tracker" ) ,
 	MNTM( 0x00000800 , "Activating/disabling maintenance mode" ) ,
+	GDAT( 0x00001000 , "Modifying game data" ) ,
 	SUPER( 0x80000000 , "Superuser (all privileges + admin management)" );
 
 	private final int bits;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bans/ArchivedBanRequest.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bans/ArchivedBanRequest.java
index d04e0ce..32d6336 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bans/ArchivedBanRequest.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bans/ArchivedBanRequest.java
@@ -3,13 +3,15 @@ package com.deepclone.lw.cmd.admin.bans;
 
 import java.sql.Timestamp;
 
+import com.deepclone.lw.session.API;
+
 
 
 public class ArchivedBanRequest
 		extends BanRequest
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private Timestamp update;
 	private boolean expired;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bans/BanRequest.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bans/BanRequest.java
index dee4b52..1a7f3d6 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bans/BanRequest.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bans/BanRequest.java
@@ -4,13 +4,15 @@ package com.deepclone.lw.cmd.admin.bans;
 import java.io.Serializable;
 import java.sql.Timestamp;
 
+import com.deepclone.lw.session.API;
+
 
 
 public class BanRequest
 		implements Serializable
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private int id;
 	private int requestedById;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bans/BansSummaryCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bans/BansSummaryCommand.java
index 6b54955..0bfdf9b 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bans/BansSummaryCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bans/BansSummaryCommand.java
@@ -1,6 +1,7 @@
 package com.deepclone.lw.cmd.admin.bans;
 
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -9,6 +10,6 @@ public class BansSummaryCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 }
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bans/BansSummaryResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bans/BansSummaryResponse.java
index 9cfe672..1d21b10 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bans/BansSummaryResponse.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bans/BansSummaryResponse.java
@@ -5,6 +5,7 @@ import java.util.List;
 
 import com.deepclone.lw.cmd.admin.AdminResponse;
 import com.deepclone.lw.cmd.admin.adata.Administrator;
+import com.deepclone.lw.session.API;
 
 
 
@@ -12,7 +13,7 @@ public class BansSummaryResponse
 		extends AdminResponse
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final List< SummaryEntry > entries;
 
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bans/ConfirmBanCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bans/ConfirmBanCommand.java
index 3ff608c..e19fca2 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bans/ConfirmBanCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bans/ConfirmBanCommand.java
@@ -1,6 +1,7 @@
 package com.deepclone.lw.cmd.admin.bans;
 
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -9,7 +10,7 @@ public class ConfirmBanCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final int id;
 
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bans/LiftBanCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bans/LiftBanCommand.java
index 24f2067..98d6b96 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bans/LiftBanCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bans/LiftBanCommand.java
@@ -1,6 +1,7 @@
 package com.deepclone.lw.cmd.admin.bans;
 
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -9,7 +10,7 @@ public class LiftBanCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final int id;
 
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bans/ListBansCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bans/ListBansCommand.java
index 1ba7c91..60f8463 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bans/ListBansCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bans/ListBansCommand.java
@@ -1,6 +1,7 @@
 package com.deepclone.lw.cmd.admin.bans;
 
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -9,7 +10,7 @@ public class ListBansCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final BanType type;
 
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bans/ListBansResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bans/ListBansResponse.java
index c956cec..205398a 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bans/ListBansResponse.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bans/ListBansResponse.java
@@ -5,6 +5,7 @@ import java.util.List;
 
 import com.deepclone.lw.cmd.admin.AdminResponse;
 import com.deepclone.lw.cmd.admin.adata.Administrator;
+import com.deepclone.lw.session.API;
 
 
 
@@ -12,7 +13,7 @@ public class ListBansResponse
 		extends AdminResponse
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final BanType type;
 	private final List< BanRequest > bans;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bans/RejectBanCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bans/RejectBanCommand.java
index 1e5e56b..0fc9092 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bans/RejectBanCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bans/RejectBanCommand.java
@@ -1,6 +1,7 @@
 package com.deepclone.lw.cmd.admin.bans;
 
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -9,7 +10,7 @@ public class RejectBanCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final int id;
 	private final String reason;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bans/RejectBanResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bans/RejectBanResponse.java
index caa0a1e..38cf2d5 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bans/RejectBanResponse.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bans/RejectBanResponse.java
@@ -3,6 +3,7 @@ package com.deepclone.lw.cmd.admin.bans;
 
 import com.deepclone.lw.cmd.admin.AdminResponse;
 import com.deepclone.lw.cmd.admin.adata.Administrator;
+import com.deepclone.lw.session.API;
 
 
 
@@ -10,7 +11,7 @@ public class RejectBanResponse
 		extends AdminResponse
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 	private final boolean error;
 	private final int id;
 
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bans/RequestBanCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bans/RequestBanCommand.java
index 8f6e882..cee952c 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bans/RequestBanCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bans/RequestBanCommand.java
@@ -1,6 +1,7 @@
 package com.deepclone.lw.cmd.admin.bans;
 
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -9,7 +10,7 @@ public class RequestBanCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final String user;
 	private final boolean empire;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bans/RequestBanResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bans/RequestBanResponse.java
index 8637681..31365eb 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bans/RequestBanResponse.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bans/RequestBanResponse.java
@@ -3,6 +3,7 @@ package com.deepclone.lw.cmd.admin.bans;
 
 import com.deepclone.lw.cmd.admin.AdminResponse;
 import com.deepclone.lw.cmd.admin.adata.Administrator;
+import com.deepclone.lw.session.API;
 
 
 
@@ -10,7 +11,7 @@ public class RequestBanResponse
 		extends AdminResponse
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	public static enum Error {
 		NOT_FOUND ,
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bans/SummaryEntry.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bans/SummaryEntry.java
index 0fcfa02..ce4c74b 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bans/SummaryEntry.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bans/SummaryEntry.java
@@ -3,13 +3,15 @@ package com.deepclone.lw.cmd.admin.bans;
 
 import java.io.Serializable;
 
+import com.deepclone.lw.session.API;
+
 
 
 public class SummaryEntry
 		implements Serializable
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final BanType type;
 	private final long count;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bans/ValidatedBanRequest.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bans/ValidatedBanRequest.java
index dfa6945..12586b7 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bans/ValidatedBanRequest.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bans/ValidatedBanRequest.java
@@ -3,13 +3,15 @@ package com.deepclone.lw.cmd.admin.bans;
 
 import java.sql.Timestamp;
 
+import com.deepclone.lw.session.API;
+
 
 
 public class ValidatedBanRequest
 		extends BanRequest
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private Timestamp update;
 	private boolean redeemable;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bt/BugsSummaryCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bt/BugsSummaryCommand.java
index d5846a0..efbecb9 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bt/BugsSummaryCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bt/BugsSummaryCommand.java
@@ -1,5 +1,6 @@
 package com.deepclone.lw.cmd.admin.bt;
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -7,6 +8,6 @@ public class BugsSummaryCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 }
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bt/BugsSummaryResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bt/BugsSummaryResponse.java
index c399f41..05315ba 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bt/BugsSummaryResponse.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bt/BugsSummaryResponse.java
@@ -3,6 +3,7 @@ package com.deepclone.lw.cmd.admin.bt;
 
 import com.deepclone.lw.cmd.admin.AdminResponse;
 import com.deepclone.lw.cmd.admin.adata.Administrator;
+import com.deepclone.lw.session.API;
 
 
 
@@ -10,7 +11,7 @@ public class BugsSummaryResponse
 		extends AdminResponse
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final long pending;
 	private final long open;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bt/GetSnapshotCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bt/GetSnapshotCommand.java
index 9aa671a..df41a9a 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bt/GetSnapshotCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bt/GetSnapshotCommand.java
@@ -1,6 +1,7 @@
 package com.deepclone.lw.cmd.admin.bt;
 
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -9,7 +10,7 @@ public class GetSnapshotCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final long bugId;
 
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bt/GetSnapshotResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bt/GetSnapshotResponse.java
index 439c768..d7dae36 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bt/GetSnapshotResponse.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bt/GetSnapshotResponse.java
@@ -3,6 +3,7 @@ package com.deepclone.lw.cmd.admin.bt;
 
 import com.deepclone.lw.cmd.admin.AdminResponse;
 import com.deepclone.lw.cmd.admin.adata.Administrator;
+import com.deepclone.lw.session.API;
 
 
 
@@ -10,7 +11,7 @@ public class GetSnapshotResponse
 		extends AdminResponse
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final String snapshot;
 
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bt/ListBugsResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bt/ListBugsResponse.java
index 4975ab8..5e18e62 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bt/ListBugsResponse.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bt/ListBugsResponse.java
@@ -7,6 +7,7 @@ import com.deepclone.lw.cmd.admin.AdminResponse;
 import com.deepclone.lw.cmd.admin.adata.Administrator;
 import com.deepclone.lw.cmd.bt.data.BugReport;
 import com.deepclone.lw.cmd.bt.data.BugStatus;
+import com.deepclone.lw.session.API;
 
 
 
@@ -14,7 +15,7 @@ public class ListBugsResponse
 		extends AdminResponse
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final BugStatus status;
 	private final boolean ownOnly;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bt/MergeReportsCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bt/MergeReportsCommand.java
index f95de2f..0997f53 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bt/MergeReportsCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bt/MergeReportsCommand.java
@@ -1,6 +1,7 @@
 package com.deepclone.lw.cmd.admin.bt;
 
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -9,7 +10,7 @@ public class MergeReportsCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final long id1;
 	private final long id2;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bt/MergeReportsResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bt/MergeReportsResponse.java
index aedcc55..accb14f 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bt/MergeReportsResponse.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bt/MergeReportsResponse.java
@@ -6,6 +6,7 @@ import java.util.List;
 import com.deepclone.lw.cmd.admin.adata.Administrator;
 import com.deepclone.lw.cmd.bt.data.BugEvent;
 import com.deepclone.lw.cmd.bt.data.BugReport;
+import com.deepclone.lw.session.API;
 
 
 
@@ -13,7 +14,7 @@ public class MergeReportsResponse
 		extends ViewBugResponse
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final MergeError mergeError;
 	private final long mergeId;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bt/ModerateCommentCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bt/ModerateCommentCommand.java
index f648c86..2c3b6b3 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bt/ModerateCommentCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bt/ModerateCommentCommand.java
@@ -1,6 +1,7 @@
 package com.deepclone.lw.cmd.admin.bt;
 
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -9,7 +10,7 @@ public class ModerateCommentCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final long id;
 	private final boolean validation;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bt/PostCommentResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bt/PostCommentResponse.java
index 13a97f0..e1375ba 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bt/PostCommentResponse.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bt/PostCommentResponse.java
@@ -7,6 +7,7 @@ import com.deepclone.lw.cmd.ObjectNameError;
 import com.deepclone.lw.cmd.admin.adata.Administrator;
 import com.deepclone.lw.cmd.bt.data.BugEvent;
 import com.deepclone.lw.cmd.bt.data.BugReport;
+import com.deepclone.lw.session.API;
 
 
 
@@ -14,7 +15,7 @@ public class PostCommentResponse
 		extends ViewBugResponse
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final boolean posted;
 	private final ObjectNameError commentError;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bt/ReportBugResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bt/ReportBugResponse.java
index 3231103..4f1fa99 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bt/ReportBugResponse.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bt/ReportBugResponse.java
@@ -4,6 +4,7 @@ package com.deepclone.lw.cmd.admin.bt;
 import com.deepclone.lw.cmd.ObjectNameError;
 import com.deepclone.lw.cmd.admin.AdminResponse;
 import com.deepclone.lw.cmd.admin.adata.Administrator;
+import com.deepclone.lw.session.API;
 
 
 
@@ -11,7 +12,7 @@ public class ReportBugResponse
 		extends AdminResponse
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final long bugId;
 	private final ObjectNameError titleError;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bt/ReportStatusCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bt/ReportStatusCommand.java
index 2f7ee85..9d8f155 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bt/ReportStatusCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bt/ReportStatusCommand.java
@@ -2,6 +2,7 @@ package com.deepclone.lw.cmd.admin.bt;
 
 
 import com.deepclone.lw.cmd.bt.data.BugStatus;
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -10,7 +11,7 @@ public class ReportStatusCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final long id;
 	private final BugStatus status;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bt/ReportVisibilityCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bt/ReportVisibilityCommand.java
index 04d82c1..ae97fe3 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bt/ReportVisibilityCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bt/ReportVisibilityCommand.java
@@ -1,6 +1,7 @@
 package com.deepclone.lw.cmd.admin.bt;
 
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -9,7 +10,7 @@ public class ReportVisibilityCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final long id;
 
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bt/ValidateReportCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bt/ValidateReportCommand.java
index 704c018..60c65ea 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bt/ValidateReportCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bt/ValidateReportCommand.java
@@ -2,6 +2,7 @@ package com.deepclone.lw.cmd.admin.bt;
 
 
 import com.deepclone.lw.cmd.bt.data.BugStatus;
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -10,7 +11,7 @@ public class ValidateReportCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final long id;
 	private final BugStatus status;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bt/ViewBugResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bt/ViewBugResponse.java
index eccb9d5..60ae71e 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bt/ViewBugResponse.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/bt/ViewBugResponse.java
@@ -7,6 +7,7 @@ import com.deepclone.lw.cmd.admin.AdminResponse;
 import com.deepclone.lw.cmd.admin.adata.Administrator;
 import com.deepclone.lw.cmd.bt.data.BugEvent;
 import com.deepclone.lw.cmd.bt.data.BugReport;
+import com.deepclone.lw.session.API;
 
 
 
@@ -14,7 +15,7 @@ public class ViewBugResponse
 		extends AdminResponse
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final BugReport report;
 	private final List< BugEvent > events;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/constants/Category.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/constants/Category.java
index 774a70a..89d82c5 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/constants/Category.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/constants/Category.java
@@ -5,13 +5,15 @@ import java.io.Serializable;
 import java.util.Collections;
 import java.util.List;
 
+import com.deepclone.lw.session.API;
+
 
 
 public class Category
 		implements Serializable , Comparable< Category >
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final String name;
 	private final List< Definition > definitions;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/constants/Definition.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/constants/Definition.java
index 7115438..f5fb206 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/constants/Definition.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/constants/Definition.java
@@ -3,13 +3,15 @@ package com.deepclone.lw.cmd.admin.constants;
 
 import java.io.Serializable;
 
+import com.deepclone.lw.session.API;
+
 
 
 public class Definition
 		implements Serializable , Comparable< Definition >
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private String name;
 	private String description;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/constants/GetConstantsCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/constants/GetConstantsCommand.java
index 93920a5..6fa7d41 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/constants/GetConstantsCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/constants/GetConstantsCommand.java
@@ -1,11 +1,12 @@
 package com.deepclone.lw.cmd.admin.constants;
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 public class GetConstantsCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 }
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/constants/GetConstantsResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/constants/GetConstantsResponse.java
index a31d96f..ca03aca 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/constants/GetConstantsResponse.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/constants/GetConstantsResponse.java
@@ -6,13 +6,14 @@ import java.util.List;
 
 import com.deepclone.lw.cmd.admin.AdminResponse;
 import com.deepclone.lw.cmd.admin.adata.Administrator;
+import com.deepclone.lw.session.API;
 
 
 
 public class GetConstantsResponse
 		extends AdminResponse
 {
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 	private List< Category > categories;
 
 
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/constants/SetConstantCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/constants/SetConstantCommand.java
index d2efe93..e506cf3 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/constants/SetConstantCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/constants/SetConstantCommand.java
@@ -1,6 +1,7 @@
 package com.deepclone.lw.cmd.admin.constants;
 
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -9,7 +10,7 @@ public class SetConstantCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final String name;
 	private final double value;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/constants/SetConstantResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/constants/SetConstantResponse.java
index cec5d9c..d5522c8 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/constants/SetConstantResponse.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/constants/SetConstantResponse.java
@@ -4,6 +4,7 @@ package com.deepclone.lw.cmd.admin.constants;
 import java.util.List;
 
 import com.deepclone.lw.cmd.admin.adata.Administrator;
+import com.deepclone.lw.session.API;
 
 
 
@@ -11,7 +12,7 @@ public class SetConstantResponse
 		extends GetConstantsResponse
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final boolean error;
 	private final String name;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/i18n/ChangeLanguageCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/i18n/ChangeLanguageCommand.java
index 9882fd5..0dea93c 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/i18n/ChangeLanguageCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/i18n/ChangeLanguageCommand.java
@@ -1,6 +1,7 @@
 package com.deepclone.lw.cmd.admin.i18n;
 
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -9,7 +10,7 @@ public class ChangeLanguageCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final String id;
 	private final String name;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/i18n/ChangeLanguageResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/i18n/ChangeLanguageResponse.java
index fd23d8e..57545ca 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/i18n/ChangeLanguageResponse.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/i18n/ChangeLanguageResponse.java
@@ -4,6 +4,7 @@ package com.deepclone.lw.cmd.admin.i18n;
 import java.util.List;
 
 import com.deepclone.lw.cmd.admin.adata.Administrator;
+import com.deepclone.lw.session.API;
 
 
 
@@ -11,7 +12,7 @@ public class ChangeLanguageResponse
 		extends GetLanguageResponse
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final boolean nameError;
 
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/i18n/GetLanguageCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/i18n/GetLanguageCommand.java
index 9ed73bb..4a66401 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/i18n/GetLanguageCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/i18n/GetLanguageCommand.java
@@ -1,6 +1,7 @@
 package com.deepclone.lw.cmd.admin.i18n;
 
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -9,7 +10,7 @@ public class GetLanguageCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final String language;
 
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/i18n/GetLanguageResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/i18n/GetLanguageResponse.java
index 68cbe5a..6f46e63 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/i18n/GetLanguageResponse.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/i18n/GetLanguageResponse.java
@@ -6,6 +6,7 @@ import java.util.List;
 
 import com.deepclone.lw.cmd.admin.AdminResponse;
 import com.deepclone.lw.cmd.admin.adata.Administrator;
+import com.deepclone.lw.session.API;
 
 
 
@@ -13,7 +14,7 @@ public class GetLanguageResponse
 		extends AdminResponse
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final Language language;
 	private final List< I18NString > strings;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/i18n/I18NString.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/i18n/I18NString.java
index 06ada37..72691e9 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/i18n/I18NString.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/i18n/I18NString.java
@@ -3,13 +3,15 @@ package com.deepclone.lw.cmd.admin.i18n;
 
 import java.io.Serializable;
 
+import com.deepclone.lw.session.API;
+
 
 
 public class I18NString
 		implements Serializable , Comparable< I18NString >
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final String id;
 	private final String text;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/i18n/Language.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/i18n/Language.java
index 6258920..ec8c299 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/i18n/Language.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/i18n/Language.java
@@ -3,13 +3,15 @@ package com.deepclone.lw.cmd.admin.i18n;
 
 import java.io.Serializable;
 
+import com.deepclone.lw.session.API;
+
 
 
 public class Language
 		implements Serializable , Comparable< Language >
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private String id;
 	private String name;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/i18n/SetStringCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/i18n/SetStringCommand.java
index 8cff779..77e7bb4 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/i18n/SetStringCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/i18n/SetStringCommand.java
@@ -1,6 +1,7 @@
 package com.deepclone.lw.cmd.admin.i18n;
 
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -9,7 +10,7 @@ public class SetStringCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final String language;
 	private final String id;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/i18n/SetStringResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/i18n/SetStringResponse.java
index 5b3af0f..6242475 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/i18n/SetStringResponse.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/i18n/SetStringResponse.java
@@ -4,6 +4,7 @@ package com.deepclone.lw.cmd.admin.i18n;
 import java.util.List;
 
 import com.deepclone.lw.cmd.admin.adata.Administrator;
+import com.deepclone.lw.session.API;
 
 
 
@@ -11,7 +12,7 @@ public class SetStringResponse
 		extends GetLanguageResponse
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final String edited;
 
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/i18n/ViewLanguagesCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/i18n/ViewLanguagesCommand.java
index 5a22e75..0f6f313 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/i18n/ViewLanguagesCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/i18n/ViewLanguagesCommand.java
@@ -1,5 +1,6 @@
 package com.deepclone.lw.cmd.admin.i18n;
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -7,6 +8,6 @@ public class ViewLanguagesCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 }
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/i18n/ViewLanguagesResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/i18n/ViewLanguagesResponse.java
index 96e66cf..9c5f2b1 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/i18n/ViewLanguagesResponse.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/i18n/ViewLanguagesResponse.java
@@ -6,6 +6,7 @@ import java.util.List;
 
 import com.deepclone.lw.cmd.admin.AdminResponse;
 import com.deepclone.lw.cmd.admin.adata.Administrator;
+import com.deepclone.lw.session.API;
 
 
 
@@ -13,7 +14,7 @@ public class ViewLanguagesResponse
 		extends AdminResponse
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final List< Language > languages;
 
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/logs/ExceptionEntry.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/logs/ExceptionEntry.java
index 55d4aa3..31aeddb 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/logs/ExceptionEntry.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/logs/ExceptionEntry.java
@@ -4,13 +4,15 @@ package com.deepclone.lw.cmd.admin.logs;
 import java.io.Serializable;
 import java.util.List;
 
+import com.deepclone.lw.session.API;
+
 
 
 public class ExceptionEntry
 		implements Serializable
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final String className;
 	private final String message;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/logs/GetEntryCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/logs/GetEntryCommand.java
index c07f7c9..00361bd 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/logs/GetEntryCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/logs/GetEntryCommand.java
@@ -1,6 +1,7 @@
 package com.deepclone.lw.cmd.admin.logs;
 
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -9,7 +10,7 @@ public class GetEntryCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final long id;
 
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/logs/GetEntryResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/logs/GetEntryResponse.java
index 8d20250..7ed89d9 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/logs/GetEntryResponse.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/logs/GetEntryResponse.java
@@ -5,13 +5,14 @@ import java.util.List;
 
 import com.deepclone.lw.cmd.admin.AdminResponse;
 import com.deepclone.lw.cmd.admin.adata.Administrator;
+import com.deepclone.lw.session.API;
 
 
 
 public class GetEntryResponse
 		extends AdminResponse
 {
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final LogEntry entry;
 	private final List< ExceptionEntry > exceptions;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/logs/LogEntry.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/logs/LogEntry.java
index f203bb6..d5c567f 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/logs/LogEntry.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/logs/LogEntry.java
@@ -4,13 +4,15 @@ package com.deepclone.lw.cmd.admin.logs;
 import java.io.Serializable;
 import java.sql.Timestamp;
 
+import com.deepclone.lw.session.API;
+
 
 
 public class LogEntry
 		implements Serializable
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private Long id;
 	private Timestamp timestamp;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/logs/TraceEntry.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/logs/TraceEntry.java
index 885c6f4..3226647 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/logs/TraceEntry.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/logs/TraceEntry.java
@@ -3,13 +3,15 @@ package com.deepclone.lw.cmd.admin.logs;
 
 import java.io.Serializable;
 
+import com.deepclone.lw.session.API;
+
 
 
 public class TraceEntry
 		implements Serializable
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final String location;
 	private final String fileName;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/logs/ViewLogCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/logs/ViewLogCommand.java
index d3f3ad7..a67b15f 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/logs/ViewLogCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/logs/ViewLogCommand.java
@@ -1,6 +1,7 @@
 package com.deepclone.lw.cmd.admin.logs;
 
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -9,7 +10,7 @@ public class ViewLogCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final LogType type;
 	private final long firstEntry;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/logs/ViewLogResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/logs/ViewLogResponse.java
index 3964c7e..f9a1ab0 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/logs/ViewLogResponse.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/logs/ViewLogResponse.java
@@ -5,6 +5,7 @@ import java.util.List;
 
 import com.deepclone.lw.cmd.admin.AdminResponse;
 import com.deepclone.lw.cmd.admin.adata.Administrator;
+import com.deepclone.lw.session.API;
 
 
 
@@ -12,7 +13,7 @@ public class ViewLogResponse
 		extends AdminResponse
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final long count;
 	private final List< LogEntry > entries;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/mntm/EnableMaintenanceCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/mntm/EnableMaintenanceCommand.java
index 2848b92..6929073 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/mntm/EnableMaintenanceCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/mntm/EnableMaintenanceCommand.java
@@ -1,6 +1,7 @@
 package com.deepclone.lw.cmd.admin.mntm;
 
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -9,7 +10,7 @@ public class EnableMaintenanceCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final String reason;
 	private final int duration;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/mntm/EndMaintenanceCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/mntm/EndMaintenanceCommand.java
index 11d5a82..da99e6e 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/mntm/EndMaintenanceCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/mntm/EndMaintenanceCommand.java
@@ -1,6 +1,7 @@
 package com.deepclone.lw.cmd.admin.mntm;
 
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -9,6 +10,6 @@ public class EndMaintenanceCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 }
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/mntm/ExtendMaintenanceCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/mntm/ExtendMaintenanceCommand.java
index 4a40d58..3f30964 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/mntm/ExtendMaintenanceCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/mntm/ExtendMaintenanceCommand.java
@@ -1,6 +1,7 @@
 package com.deepclone.lw.cmd.admin.mntm;
 
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -9,7 +10,7 @@ public class ExtendMaintenanceCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final int duration;
 
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/mntm/MaintenanceChangeResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/mntm/MaintenanceChangeResponse.java
index c5ea32c..6a9e4e7 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/mntm/MaintenanceChangeResponse.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/mntm/MaintenanceChangeResponse.java
@@ -5,6 +5,7 @@ import java.util.Date;
 
 import com.deepclone.lw.cmd.ObjectNameError;
 import com.deepclone.lw.cmd.admin.adata.Administrator;
+import com.deepclone.lw.session.API;
 
 
 
@@ -12,7 +13,7 @@ public class MaintenanceChangeResponse
 		extends MaintenanceStatusResponse
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final String newReason;
 	private final ObjectNameError reasonError;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/mntm/MaintenanceStatusCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/mntm/MaintenanceStatusCommand.java
index c0fd9b0..b4d08b9 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/mntm/MaintenanceStatusCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/mntm/MaintenanceStatusCommand.java
@@ -1,6 +1,7 @@
 package com.deepclone.lw.cmd.admin.mntm;
 
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -9,6 +10,6 @@ public class MaintenanceStatusCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 }
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/mntm/MaintenanceStatusResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/mntm/MaintenanceStatusResponse.java
index 4f98983..9b441b6 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/mntm/MaintenanceStatusResponse.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/mntm/MaintenanceStatusResponse.java
@@ -5,6 +5,7 @@ import java.util.Date;
 
 import com.deepclone.lw.cmd.admin.AdminResponse;
 import com.deepclone.lw.cmd.admin.adata.Administrator;
+import com.deepclone.lw.session.API;
 
 
 
@@ -12,7 +13,7 @@ public class MaintenanceStatusResponse
 		extends AdminResponse
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final String reason;
 	private final Date started;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/msg/ComposeMessageCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/msg/ComposeMessageCommand.java
index 5eb5314..db5078c 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/msg/ComposeMessageCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/msg/ComposeMessageCommand.java
@@ -2,6 +2,7 @@ package com.deepclone.lw.cmd.admin.msg;
 
 
 import com.deepclone.lw.cmd.msgdata.MessageType;
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -10,7 +11,7 @@ public class ComposeMessageCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final Boolean inbox;
 	private final Long replyTo;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/msg/ComposeMessageResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/msg/ComposeMessageResponse.java
index 7b01bc4..c95a7e5 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/msg/ComposeMessageResponse.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/msg/ComposeMessageResponse.java
@@ -5,6 +5,7 @@ import com.deepclone.lw.cmd.admin.AdminResponse;
 import com.deepclone.lw.cmd.admin.adata.Administrator;
 import com.deepclone.lw.cmd.msgdata.Message;
 import com.deepclone.lw.cmd.msgdata.MessageType;
+import com.deepclone.lw.session.API;
 
 
 
@@ -12,7 +13,7 @@ public class ComposeMessageResponse
 		extends AdminResponse
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private MessageType messageType;
 	private String target;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/msg/GetMessagesCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/msg/GetMessagesCommand.java
index f6019f1..b1175b1 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/msg/GetMessagesCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/msg/GetMessagesCommand.java
@@ -1,6 +1,7 @@
 package com.deepclone.lw.cmd.admin.msg;
 
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -9,7 +10,7 @@ public class GetMessagesCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final boolean inbox;
 
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/msg/GetMessagesResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/msg/GetMessagesResponse.java
index bd0c6da..ee774d3 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/msg/GetMessagesResponse.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/msg/GetMessagesResponse.java
@@ -6,6 +6,7 @@ import java.util.List;
 import com.deepclone.lw.cmd.admin.AdminResponse;
 import com.deepclone.lw.cmd.admin.adata.Administrator;
 import com.deepclone.lw.cmd.msgdata.MessageListEntry;
+import com.deepclone.lw.session.API;
 
 
 
@@ -13,7 +14,7 @@ public class GetMessagesResponse
 		extends AdminResponse
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final List< MessageListEntry > messages;
 
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/msg/MessageBoxCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/msg/MessageBoxCommand.java
index c7431f2..5b2dfd2 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/msg/MessageBoxCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/msg/MessageBoxCommand.java
@@ -1,6 +1,7 @@
 package com.deepclone.lw.cmd.admin.msg;
 
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -9,7 +10,7 @@ public class MessageBoxCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final MessageBoxAction action;
 	private final boolean inbox;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/msg/PrepareMessageCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/msg/PrepareMessageCommand.java
index 0da0140..244779c 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/msg/PrepareMessageCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/msg/PrepareMessageCommand.java
@@ -2,6 +2,7 @@ package com.deepclone.lw.cmd.admin.msg;
 
 
 import com.deepclone.lw.cmd.msgdata.MessageType;
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -10,7 +11,7 @@ public class PrepareMessageCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final MessageType type;
 	private final Long id;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/msg/ReadMessageCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/msg/ReadMessageCommand.java
index e4d178f..57db7bf 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/msg/ReadMessageCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/msg/ReadMessageCommand.java
@@ -1,6 +1,7 @@
 package com.deepclone.lw.cmd.admin.msg;
 
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -9,7 +10,7 @@ public class ReadMessageCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final boolean inbox;
 	private final long id;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/msg/ReadMessageResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/msg/ReadMessageResponse.java
index c310b93..096124d 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/msg/ReadMessageResponse.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/msg/ReadMessageResponse.java
@@ -4,6 +4,7 @@ package com.deepclone.lw.cmd.admin.msg;
 import com.deepclone.lw.cmd.admin.AdminResponse;
 import com.deepclone.lw.cmd.admin.adata.Administrator;
 import com.deepclone.lw.cmd.msgdata.Message;
+import com.deepclone.lw.session.API;
 
 
 
@@ -11,7 +12,7 @@ public class ReadMessageResponse
 		extends AdminResponse
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final boolean inbox;
 	private final Message message;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/msg/SendSpamCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/msg/SendSpamCommand.java
index b282bcc..9acc488 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/msg/SendSpamCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/msg/SendSpamCommand.java
@@ -1,6 +1,7 @@
 package com.deepclone.lw.cmd.admin.msg;
 
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -9,7 +10,7 @@ public class SendSpamCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final String title;
 	private final String body;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/naming/GetNamesCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/naming/GetNamesCommand.java
index 1502f47..bcd08ea 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/naming/GetNamesCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/naming/GetNamesCommand.java
@@ -1,6 +1,7 @@
 package com.deepclone.lw.cmd.admin.naming;
 
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -9,7 +10,7 @@ public class GetNamesCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final NameType type;
 
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/naming/GetNamesResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/naming/GetNamesResponse.java
index 735a487..54a68ba 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/naming/GetNamesResponse.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/naming/GetNamesResponse.java
@@ -5,6 +5,7 @@ import java.util.List;
 
 import com.deepclone.lw.cmd.admin.AdminResponse;
 import com.deepclone.lw.cmd.admin.adata.Administrator;
+import com.deepclone.lw.session.API;
 
 
 
@@ -12,7 +13,7 @@ public class GetNamesResponse
 		extends AdminResponse
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final NameType type;
 	private final List< Name > names;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/naming/Name.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/naming/Name.java
index c3f67e8..3c71848 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/naming/Name.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/naming/Name.java
@@ -3,13 +3,15 @@ package com.deepclone.lw.cmd.admin.naming;
 
 import java.io.Serializable;
 
+import com.deepclone.lw.session.API;
+
 
 
 public class Name
 		implements Serializable
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final int id;
 	private final String name;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/naming/NamesActionCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/naming/NamesActionCommand.java
index 0b778e1..e808868 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/naming/NamesActionCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/naming/NamesActionCommand.java
@@ -1,6 +1,7 @@
 package com.deepclone.lw.cmd.admin.naming;
 
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -9,7 +10,7 @@ public class NamesActionCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final NameType type;
 	private final NameAction action;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/naming/NamesSummaryCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/naming/NamesSummaryCommand.java
index 96ea84a..325c47e 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/naming/NamesSummaryCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/naming/NamesSummaryCommand.java
@@ -1,6 +1,7 @@
 package com.deepclone.lw.cmd.admin.naming;
 
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -9,6 +10,6 @@ public class NamesSummaryCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 }
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/naming/NamesSummaryResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/naming/NamesSummaryResponse.java
index adbb523..746f7d6 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/naming/NamesSummaryResponse.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/naming/NamesSummaryResponse.java
@@ -6,6 +6,7 @@ import java.util.List;
 
 import com.deepclone.lw.cmd.admin.AdminResponse;
 import com.deepclone.lw.cmd.admin.adata.Administrator;
+import com.deepclone.lw.session.API;
 
 
 
@@ -13,7 +14,7 @@ public class NamesSummaryResponse
 		extends AdminResponse
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	@SuppressWarnings( "serial" )
 	public static class Entry
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/prefs/GetPrefDefaultsCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/prefs/GetPrefDefaultsCommand.java
index 0946c22..25b876b 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/prefs/GetPrefDefaultsCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/prefs/GetPrefDefaultsCommand.java
@@ -1,6 +1,7 @@
 package com.deepclone.lw.cmd.admin.prefs;
 
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -9,6 +10,6 @@ public class GetPrefDefaultsCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 }
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/prefs/PrefDefaultsResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/prefs/PrefDefaultsResponse.java
index fed8047..e36f9ec 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/prefs/PrefDefaultsResponse.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/prefs/PrefDefaultsResponse.java
@@ -6,6 +6,7 @@ import java.util.List;
 import com.deepclone.lw.cmd.admin.AdminResponse;
 import com.deepclone.lw.cmd.admin.adata.Administrator;
 import com.deepclone.lw.cmd.player.gdata.account.PrefCategory;
+import com.deepclone.lw.session.API;
 
 
 
@@ -13,7 +14,7 @@ public class PrefDefaultsResponse
 		extends AdminResponse
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final List< PrefCategory > preferences;
 
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/prefs/SetPrefDefaultCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/prefs/SetPrefDefaultCommand.java
index 35f3945..64a778e 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/prefs/SetPrefDefaultCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/prefs/SetPrefDefaultCommand.java
@@ -1,6 +1,7 @@
 package com.deepclone.lw.cmd.admin.prefs;
 
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -9,7 +10,7 @@ public class SetPrefDefaultCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final String preference;
 	private final String value;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/su/AddAdministratorCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/su/AddAdministratorCommand.java
index ed1eeb8..77febe4 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/su/AddAdministratorCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/su/AddAdministratorCommand.java
@@ -6,6 +6,7 @@ import java.util.HashSet;
 import java.util.Set;
 
 import com.deepclone.lw.cmd.admin.adata.Privileges;
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -14,7 +15,7 @@ public class AddAdministratorCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final String address;
 	private final String appearAs;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/su/AddAdministratorResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/su/AddAdministratorResponse.java
index a31e6d4..f1a9067 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/su/AddAdministratorResponse.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/su/AddAdministratorResponse.java
@@ -7,13 +7,14 @@ import com.deepclone.lw.cmd.ObjectNameError;
 import com.deepclone.lw.cmd.admin.AdminResponse;
 import com.deepclone.lw.cmd.admin.adata.Administrator;
 import com.deepclone.lw.cmd.admin.adata.PrivEntry;
+import com.deepclone.lw.session.API;
 
 
 
 public class AddAdministratorResponse
 		extends AdminResponse
 {
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	public static enum AddressError {
 		EMPTY ,
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/su/ListAdministratorsCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/su/ListAdministratorsCommand.java
index 8133b1c..e6930e1 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/su/ListAdministratorsCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/su/ListAdministratorsCommand.java
@@ -1,11 +1,12 @@
 package com.deepclone.lw.cmd.admin.su;
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 public class ListAdministratorsCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 }
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/su/ListAdministratorsResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/su/ListAdministratorsResponse.java
index 9a49ab2..39208b4 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/su/ListAdministratorsResponse.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/su/ListAdministratorsResponse.java
@@ -5,6 +5,7 @@ import java.util.List;
 
 import com.deepclone.lw.cmd.admin.AdminResponse;
 import com.deepclone.lw.cmd.admin.adata.Administrator;
+import com.deepclone.lw.session.API;
 
 
 
@@ -12,7 +13,7 @@ public class ListAdministratorsResponse
 		extends AdminResponse
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final List< Administrator > administrators;
 
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/su/ResetAdminPasswordCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/su/ResetAdminPasswordCommand.java
index 78c5bb0..6023fc3 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/su/ResetAdminPasswordCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/su/ResetAdminPasswordCommand.java
@@ -1,10 +1,12 @@
 package com.deepclone.lw.cmd.admin.su;
 
+import com.deepclone.lw.session.API;
+
 
 public class ResetAdminPasswordCommand
 		extends ViewAdministratorCommand
 {
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 
 	public ResetAdminPasswordCommand( int identifier )
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/su/SetPrivilegesCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/su/SetPrivilegesCommand.java
index ea902e3..8fc8ad7 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/su/SetPrivilegesCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/su/SetPrivilegesCommand.java
@@ -6,6 +6,7 @@ import java.util.HashSet;
 import java.util.Set;
 
 import com.deepclone.lw.cmd.admin.adata.Privileges;
+import com.deepclone.lw.session.API;
 
 
 
@@ -13,7 +14,7 @@ public class SetPrivilegesCommand
 		extends ViewAdministratorCommand
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final Set< Privileges > privileges;
 
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/su/ViewAdministratorCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/su/ViewAdministratorCommand.java
index 8b6e119..c3aa977 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/su/ViewAdministratorCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/su/ViewAdministratorCommand.java
@@ -1,6 +1,7 @@
 package com.deepclone.lw.cmd.admin.su;
 
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -9,7 +10,7 @@ public class ViewAdministratorCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final int identifier;
 
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/su/ViewAdministratorResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/su/ViewAdministratorResponse.java
index a903ccc..176d54a 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/su/ViewAdministratorResponse.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/su/ViewAdministratorResponse.java
@@ -3,6 +3,7 @@ package com.deepclone.lw.cmd.admin.su;
 
 import com.deepclone.lw.cmd.admin.AdminResponse;
 import com.deepclone.lw.cmd.admin.adata.Administrator;
+import com.deepclone.lw.session.API;
 
 
 
@@ -10,7 +11,7 @@ public class ViewAdministratorResponse
 		extends AdminResponse
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final Administrator view;
 
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/techs/GetTechnologyCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/techs/GetTechnologyCommand.java
new file mode 100644
index 0000000..2695f5f
--- /dev/null
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/techs/GetTechnologyCommand.java
@@ -0,0 +1,29 @@
+package com.deepclone.lw.cmd.admin.techs;
+
+
+import com.deepclone.lw.session.API;
+import com.deepclone.lw.session.Command;
+
+
+
+public class GetTechnologyCommand
+		extends Command
+{
+
+	private static final long serialVersionUID = API.Version;
+
+	private final String technology;
+
+
+	public GetTechnologyCommand( String technology )
+	{
+		this.technology = technology;
+	}
+
+
+	public String getTechnology( )
+	{
+		return technology;
+	}
+
+}
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/techs/GetTechnologyResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/techs/GetTechnologyResponse.java
new file mode 100644
index 0000000..ec14a8c
--- /dev/null
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/techs/GetTechnologyResponse.java
@@ -0,0 +1,62 @@
+package com.deepclone.lw.cmd.admin.techs;
+
+
+import java.util.LinkedList;
+import java.util.List;
+
+import com.deepclone.lw.cmd.admin.AdminResponse;
+import com.deepclone.lw.cmd.admin.adata.Administrator;
+import com.deepclone.lw.session.API;
+
+
+
+public class GetTechnologyResponse
+		extends AdminResponse
+{
+
+	private static final long serialVersionUID = API.Version;
+
+	public final TechEntry technology;
+
+	public final List< String > categories;
+
+	public final List< String > strings;
+
+
+	public GetTechnologyResponse( Administrator admin , boolean privError )
+	{
+		super( admin , privError );
+		this.technology = null;
+		this.categories = null;
+		this.strings = null;
+	}
+
+
+	public GetTechnologyResponse( Administrator admin , TechEntry technology , List< String > categories ,
+			List< String > strings )
+	{
+		super( admin , false );
+		this.technology = technology;
+		this.categories = categories;
+		this.strings = strings;
+	}
+
+
+	public TechEntry getTechnology( )
+	{
+		return this.technology;
+	}
+
+
+	public List< String > getCategories( )
+	{
+		return new LinkedList< String >( this.categories );
+	}
+
+
+	public List< String > getStrings( )
+	{
+		return new LinkedList< String >( this.strings );
+	}
+
+}
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/techs/ListCategoriesCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/techs/ListCategoriesCommand.java
new file mode 100644
index 0000000..736b187
--- /dev/null
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/techs/ListCategoriesCommand.java
@@ -0,0 +1,15 @@
+package com.deepclone.lw.cmd.admin.techs;
+
+
+import com.deepclone.lw.session.API;
+import com.deepclone.lw.session.Command;
+
+
+
+public class ListCategoriesCommand
+		extends Command
+{
+
+	private static final long serialVersionUID = API.Version;
+
+}
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/techs/ListCategoriesResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/techs/ListCategoriesResponse.java
new file mode 100644
index 0000000..e5446a3
--- /dev/null
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/techs/ListCategoriesResponse.java
@@ -0,0 +1,40 @@
+package com.deepclone.lw.cmd.admin.techs;
+
+
+import java.util.LinkedList;
+import java.util.List;
+
+import com.deepclone.lw.cmd.admin.AdminResponse;
+import com.deepclone.lw.cmd.admin.adata.Administrator;
+import com.deepclone.lw.session.API;
+
+
+
+public class ListCategoriesResponse
+		extends AdminResponse
+{
+
+	private static final long serialVersionUID = API.Version;
+
+	private final List< TechCategory > categories;
+
+
+	public ListCategoriesResponse( Administrator admin )
+	{
+		super( admin , false );
+		this.categories = null;
+	}
+
+
+	public ListCategoriesResponse( Administrator admin , List< TechCategory > categories )
+	{
+		super( admin , true );
+		this.categories = categories;
+	}
+
+
+	public List< TechCategory > getCategories( )
+	{
+		return new LinkedList< TechCategory >( this.categories );
+	}
+}
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/techs/TechCategory.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/techs/TechCategory.java
new file mode 100644
index 0000000..b85721c
--- /dev/null
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/techs/TechCategory.java
@@ -0,0 +1,50 @@
+package com.deepclone.lw.cmd.admin.techs;
+
+
+import java.io.Serializable;
+import java.util.LinkedList;
+import java.util.List;
+
+import com.deepclone.lw.session.API;
+
+
+
+public class TechCategory
+		implements Serializable
+{
+
+	private static final long serialVersionUID = API.Version;
+
+	private final String name;
+
+	private final String description;
+
+	private final List< String > techs;
+
+
+	public TechCategory( String name , String description , List< String > techs )
+	{
+		this.name = name;
+		this.description = description;
+		this.techs = new LinkedList< String >( techs );
+	}
+
+
+	public String getName( )
+	{
+		return name;
+	}
+
+
+	public String getDescription( )
+	{
+		return description;
+	}
+
+
+	public List< String > getTechs( )
+	{
+		return techs;
+	}
+
+}
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/techs/TechEntry.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/techs/TechEntry.java
new file mode 100644
index 0000000..cc4a2d2
--- /dev/null
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/techs/TechEntry.java
@@ -0,0 +1,62 @@
+package com.deepclone.lw.cmd.admin.techs;
+
+
+import java.io.Serializable;
+
+import com.deepclone.lw.session.API;
+
+
+
+public class TechEntry
+		implements Serializable
+{
+
+	private static final long serialVersionUID = API.Version;
+
+	private final String category;
+	private final String name;
+	private final String description;
+	private final int points;
+	private final int cost;
+
+
+	public TechEntry( String category , String name , String description , int points , int cost )
+	{
+		this.category = category;
+		this.name = name;
+		this.description = description;
+		this.points = points;
+		this.cost = cost;
+	}
+
+
+	public String getCategory( )
+	{
+		return category;
+	}
+
+
+	public String getName( )
+	{
+		return name;
+	}
+
+
+	public String getDescription( )
+	{
+		return description;
+	}
+
+
+	public int getPoints( )
+	{
+		return points;
+	}
+
+
+	public int getCost( )
+	{
+		return cost;
+	}
+
+}
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/tick/SetTaskStatusCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/tick/SetTaskStatusCommand.java
index 82645b8..dca5056 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/tick/SetTaskStatusCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/tick/SetTaskStatusCommand.java
@@ -1,6 +1,7 @@
 package com.deepclone.lw.cmd.admin.tick;
 
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -9,7 +10,7 @@ public class SetTaskStatusCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final int task;
 	private final TickerTaskStatus newStatus;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/tick/TickerStatusCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/tick/TickerStatusCommand.java
index e6dda40..42f7694 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/tick/TickerStatusCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/tick/TickerStatusCommand.java
@@ -1,6 +1,7 @@
 package com.deepclone.lw.cmd.admin.tick;
 
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -9,6 +10,6 @@ public class TickerStatusCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 }
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/tick/TickerStatusResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/tick/TickerStatusResponse.java
index 9de84db..ad401cd 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/tick/TickerStatusResponse.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/tick/TickerStatusResponse.java
@@ -5,6 +5,7 @@ import java.util.List;
 
 import com.deepclone.lw.cmd.admin.AdminResponse;
 import com.deepclone.lw.cmd.admin.adata.Administrator;
+import com.deepclone.lw.session.API;
 
 
 
@@ -12,7 +13,7 @@ public class TickerStatusResponse
 		extends AdminResponse
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final boolean paused;
 	private final List< TickerTaskInfo > tasks;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/tick/TickerTaskInfo.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/tick/TickerTaskInfo.java
index 5f189de..88780dd 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/tick/TickerTaskInfo.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/tick/TickerTaskInfo.java
@@ -4,13 +4,15 @@ package com.deepclone.lw.cmd.admin.tick;
 import java.io.Serializable;
 import java.sql.Timestamp;
 
+import com.deepclone.lw.session.API;
+
 
 
 public class TickerTaskInfo
 		implements Serializable , Comparable< TickerTaskInfo >
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private int id;
 	private String name;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/tick/ToggleTickerCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/tick/ToggleTickerCommand.java
index 797781f..95b9f94 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/tick/ToggleTickerCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/tick/ToggleTickerCommand.java
@@ -1,6 +1,7 @@
 package com.deepclone.lw.cmd.admin.tick;
 
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -9,6 +10,6 @@ public class ToggleTickerCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 }
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/users/AccountBanEntry.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/users/AccountBanEntry.java
index 6f124e0..5212f12 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/users/AccountBanEntry.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/users/AccountBanEntry.java
@@ -3,13 +3,15 @@ package com.deepclone.lw.cmd.admin.users;
 
 import java.io.Serializable;
 
+import com.deepclone.lw.session.API;
+
 
 
 public class AccountBanEntry
 		implements Serializable
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private String requestedByName;
 	private int requestedById;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/users/AccountListEntry.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/users/AccountListEntry.java
index f102958..ec88fc0 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/users/AccountListEntry.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/users/AccountListEntry.java
@@ -3,13 +3,15 @@ package com.deepclone.lw.cmd.admin.users;
 
 import java.io.Serializable;
 
+import com.deepclone.lw.session.API;
+
 
 
 public class AccountListEntry
 		implements Serializable
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private int id;
 	private String address;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/users/AccountSessionEntry.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/users/AccountSessionEntry.java
index ff8594d..2a432a6 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/users/AccountSessionEntry.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/users/AccountSessionEntry.java
@@ -3,12 +3,14 @@ package com.deepclone.lw.cmd.admin.users;
 
 import java.util.List;
 
+import com.deepclone.lw.session.API;
+
 
 
 public class AccountSessionEntry
 		extends AccountListEntry
 {
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private List< UserSession > sessions;
 
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/users/AccountViewEntry.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/users/AccountViewEntry.java
index 44ff78d..8d4b36e 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/users/AccountViewEntry.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/users/AccountViewEntry.java
@@ -5,13 +5,15 @@ import java.sql.Timestamp;
 import java.util.ArrayList;
 import java.util.List;
 
+import com.deepclone.lw.session.API;
+
 
 
 public class AccountViewEntry
 		extends AccountListEntry
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private Integer empireId;
 	private int gameCredits;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/users/GiveCreditsCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/users/GiveCreditsCommand.java
index 5ab9330..5a72297 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/users/GiveCreditsCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/users/GiveCreditsCommand.java
@@ -1,6 +1,7 @@
 package com.deepclone.lw.cmd.admin.users;
 
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -9,7 +10,7 @@ public class GiveCreditsCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final int id;
 	private final int credits;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/users/ListAccountsCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/users/ListAccountsCommand.java
index 5b52707..58b84ed 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/users/ListAccountsCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/users/ListAccountsCommand.java
@@ -1,6 +1,7 @@
 package com.deepclone.lw.cmd.admin.users;
 
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -9,7 +10,7 @@ public class ListAccountsCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final AccountStatus status;
 	private final boolean online;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/users/ListAccountsResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/users/ListAccountsResponse.java
index 389bd1e..d93d8dc 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/users/ListAccountsResponse.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/users/ListAccountsResponse.java
@@ -5,6 +5,7 @@ import java.util.List;
 
 import com.deepclone.lw.cmd.admin.AdminResponse;
 import com.deepclone.lw.cmd.admin.adata.Administrator;
+import com.deepclone.lw.session.API;
 
 
 
@@ -12,7 +13,7 @@ public class ListAccountsResponse
 		extends AdminResponse
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final AccountStatus status;
 	private final boolean online;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/users/ListSessionsCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/users/ListSessionsCommand.java
index 0dd8336..de06eb1 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/users/ListSessionsCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/users/ListSessionsCommand.java
@@ -1,6 +1,7 @@
 package com.deepclone.lw.cmd.admin.users;
 
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -9,7 +10,7 @@ public class ListSessionsCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final int id;
 
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/users/ListSessionsResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/users/ListSessionsResponse.java
index a9ae818..87bc72c 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/users/ListSessionsResponse.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/users/ListSessionsResponse.java
@@ -3,6 +3,7 @@ package com.deepclone.lw.cmd.admin.users;
 
 import com.deepclone.lw.cmd.admin.AdminResponse;
 import com.deepclone.lw.cmd.admin.adata.Administrator;
+import com.deepclone.lw.session.API;
 
 
 
@@ -10,7 +11,7 @@ public class ListSessionsResponse
 		extends AdminResponse
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final AccountSessionEntry account;
 
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/users/UserSession.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/users/UserSession.java
index b66cb2b..11a0265 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/users/UserSession.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/users/UserSession.java
@@ -4,13 +4,15 @@ package com.deepclone.lw.cmd.admin.users;
 import java.io.Serializable;
 import java.sql.Timestamp;
 
+import com.deepclone.lw.session.API;
+
 
 
 public class UserSession
 		implements Serializable
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private long id;
 	private int credentialsId;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/users/ViewAccountCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/users/ViewAccountCommand.java
index aa05383..584f465 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/users/ViewAccountCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/users/ViewAccountCommand.java
@@ -1,6 +1,7 @@
 package com.deepclone.lw.cmd.admin.users;
 
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -9,7 +10,7 @@ public class ViewAccountCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final int id;
 
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/users/ViewAccountResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/users/ViewAccountResponse.java
index add90f9..efa7255 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/users/ViewAccountResponse.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/admin/users/ViewAccountResponse.java
@@ -3,6 +3,7 @@ package com.deepclone.lw.cmd.admin.users;
 
 import com.deepclone.lw.cmd.admin.AdminResponse;
 import com.deepclone.lw.cmd.admin.adata.Administrator;
+import com.deepclone.lw.session.API;
 
 
 
@@ -10,7 +11,7 @@ public class ViewAccountResponse
 		extends AdminResponse
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final AccountViewEntry account;
 
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/bt/ListBugsCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/bt/ListBugsCommand.java
index 18763af..ae33a05 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/bt/ListBugsCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/bt/ListBugsCommand.java
@@ -2,6 +2,7 @@ package com.deepclone.lw.cmd.bt;
 
 
 import com.deepclone.lw.cmd.bt.data.BugStatus;
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -10,7 +11,7 @@ public class ListBugsCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final BugStatus status;
 	private final boolean ownOnly;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/bt/PostCommentCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/bt/PostCommentCommand.java
index d032610..82ee37f 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/bt/PostCommentCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/bt/PostCommentCommand.java
@@ -1,6 +1,7 @@
 package com.deepclone.lw.cmd.bt;
 
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -9,7 +10,7 @@ public class PostCommentCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final long id;
 	private final String comment;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/bt/ReportBugCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/bt/ReportBugCommand.java
index 92425fe..bd57fd1 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/bt/ReportBugCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/bt/ReportBugCommand.java
@@ -1,6 +1,7 @@
 package com.deepclone.lw.cmd.bt;
 
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -9,7 +10,7 @@ public class ReportBugCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final String title;
 	private final String description;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/bt/ViewBugCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/bt/ViewBugCommand.java
index 1ef74ba..ed25758 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/bt/ViewBugCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/bt/ViewBugCommand.java
@@ -1,6 +1,7 @@
 package com.deepclone.lw.cmd.bt;
 
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -9,7 +10,7 @@ public class ViewBugCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final long id;
 
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/bt/data/BugEvent.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/bt/data/BugEvent.java
index 027b9d7..f53cf16 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/bt/data/BugEvent.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/bt/data/BugEvent.java
@@ -4,13 +4,15 @@ package com.deepclone.lw.cmd.bt.data;
 import java.io.Serializable;
 import java.sql.Timestamp;
 
+import com.deepclone.lw.session.API;
+
 
 
 public class BugEvent
 		implements Serializable
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private long id;
 	private BugEventType type;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/bt/data/BugReport.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/bt/data/BugReport.java
index 2767173..f4be6c6 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/bt/data/BugReport.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/bt/data/BugReport.java
@@ -4,13 +4,15 @@ package com.deepclone.lw.cmd.bt.data;
 import java.io.Serializable;
 import java.sql.Timestamp;
 
+import com.deepclone.lw.session.API;
+
 
 
 public class BugReport
 		implements Serializable
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private long reportId;
 	private String title;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/bt/data/BugSubmitter.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/bt/data/BugSubmitter.java
index 3e6e5b8..729ef38 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/bt/data/BugSubmitter.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/bt/data/BugSubmitter.java
@@ -3,13 +3,15 @@ package com.deepclone.lw.cmd.bt.data;
 
 import java.io.Serializable;
 
+import com.deepclone.lw.session.API;
+
 
 
 public class BugSubmitter
 		implements Serializable
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private boolean isAdmin;
 	private String name;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/ext/ConfirmPasswordRecoveryCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/ext/ConfirmPasswordRecoveryCommand.java
index fe21b7d..56b45af 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/ext/ConfirmPasswordRecoveryCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/ext/ConfirmPasswordRecoveryCommand.java
@@ -1,6 +1,7 @@
 package com.deepclone.lw.cmd.ext;
 
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -9,7 +10,7 @@ public class ConfirmPasswordRecoveryCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final String mailAddress;
 
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/ext/ConfirmPasswordRecoveryResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/ext/ConfirmPasswordRecoveryResponse.java
index 4342cdd..0fdb4b3 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/ext/ConfirmPasswordRecoveryResponse.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/ext/ConfirmPasswordRecoveryResponse.java
@@ -1,6 +1,7 @@
 package com.deepclone.lw.cmd.ext;
 
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.CommandResponse;
 
 
@@ -9,7 +10,7 @@ public class ConfirmPasswordRecoveryResponse
 		extends CommandResponse
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	public static enum PasswordRecoveryStatus {
 		OK ,
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/ext/CreateAccountCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/ext/CreateAccountCommand.java
index a4d0d32..60ff472 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/ext/CreateAccountCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/ext/CreateAccountCommand.java
@@ -1,6 +1,7 @@
 package com.deepclone.lw.cmd.ext;
 
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -9,7 +10,7 @@ public final class CreateAccountCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 	private final String mail;
 	private final String mailConfirm;
 	private final String password;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/ext/CreateAccountResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/ext/CreateAccountResponse.java
index d7fff8b..f997c37 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/ext/CreateAccountResponse.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/ext/CreateAccountResponse.java
@@ -5,6 +5,7 @@ import java.util.Map;
 
 import com.deepclone.lw.cmd.MailError;
 import com.deepclone.lw.cmd.PasswordError;
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.CommandResponse;
 
 
@@ -13,7 +14,7 @@ public final class CreateAccountResponse
 		extends CommandResponse
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final boolean created;
 
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/ext/ListLanguagesCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/ext/ListLanguagesCommand.java
index d04a39e..5fc3027 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/ext/ListLanguagesCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/ext/ListLanguagesCommand.java
@@ -1,6 +1,7 @@
 package com.deepclone.lw.cmd.ext;
 
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -9,6 +10,6 @@ public class ListLanguagesCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 }
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/ext/ListLanguagesResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/ext/ListLanguagesResponse.java
index 5f046c3..4815584 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/ext/ListLanguagesResponse.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/ext/ListLanguagesResponse.java
@@ -7,6 +7,7 @@ import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.CommandResponse;
 
 
@@ -15,12 +16,12 @@ public class ListLanguagesResponse
 		extends CommandResponse
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	public static class Language
 			implements Serializable
 	{
-		private static final long serialVersionUID = 1L;
+		private static final long serialVersionUID = API.Version;
 
 		private final String id;
 
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/ext/RequestPasswordRecoveryCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/ext/RequestPasswordRecoveryCommand.java
index dea1b75..5d78bef 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/ext/RequestPasswordRecoveryCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/ext/RequestPasswordRecoveryCommand.java
@@ -1,6 +1,7 @@
 package com.deepclone.lw.cmd.ext;
 
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -9,7 +10,7 @@ public class RequestPasswordRecoveryCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final String mailAddress;
 
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/ext/RequestPasswordRecoveryResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/ext/RequestPasswordRecoveryResponse.java
index cdf6407..bbe7753 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/ext/RequestPasswordRecoveryResponse.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/ext/RequestPasswordRecoveryResponse.java
@@ -1,6 +1,7 @@
 package com.deepclone.lw.cmd.ext;
 
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.CommandResponse;
 
 
@@ -9,7 +10,7 @@ public class RequestPasswordRecoveryResponse
 		extends CommandResponse
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	public static enum PasswordRecoveryRequestStatus {
 		OK ,
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/msgdata/Message.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/msgdata/Message.java
index d3e8547..d11c1db 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/msgdata/Message.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/msgdata/Message.java
@@ -5,6 +5,7 @@ import java.io.Serializable;
 import java.sql.Timestamp;
 
 import com.deepclone.lw.cmd.player.gdata.GameTime;
+import com.deepclone.lw.session.API;
 
 
 
@@ -12,7 +13,7 @@ public class Message
 		implements Serializable
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private long id;
 	private Long previous;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/msgdata/MessageListEntry.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/msgdata/MessageListEntry.java
index aee6cac..12809b2 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/msgdata/MessageListEntry.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/msgdata/MessageListEntry.java
@@ -4,13 +4,15 @@ package com.deepclone.lw.cmd.msgdata;
 import java.io.Serializable;
 import java.sql.Timestamp;
 
+import com.deepclone.lw.session.API;
+
 
 
 public class MessageListEntry
 		implements Serializable
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private long id;
 	private MessageType type;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/EmpireResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/EmpireResponse.java
index 4fa9dd3..3fa9bcb 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/EmpireResponse.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/EmpireResponse.java
@@ -7,6 +7,7 @@ import com.deepclone.lw.cmd.player.gdata.GamePageData;
 import com.deepclone.lw.cmd.player.gdata.GameResponseBase;
 import com.deepclone.lw.cmd.player.gdata.battles.BattleListEntry;
 import com.deepclone.lw.cmd.player.gdata.empire.OverviewData;
+import com.deepclone.lw.session.API;
 
 
 
@@ -14,7 +15,7 @@ public class EmpireResponse
 		extends GameResponseBase
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 	private final OverviewData overview;
 	private final List< BattleListEntry > battles;
 
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/GetNewPlanetCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/GetNewPlanetCommand.java
index 0901c47..f8984af 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/GetNewPlanetCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/GetNewPlanetCommand.java
@@ -1,6 +1,7 @@
 package com.deepclone.lw.cmd.player;
 
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -9,7 +10,7 @@ public class GetNewPlanetCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final String name;
 
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/GetNewPlanetResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/GetNewPlanetResponse.java
index 772d507..269e75a 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/GetNewPlanetResponse.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/GetNewPlanetResponse.java
@@ -4,6 +4,7 @@ package com.deepclone.lw.cmd.player;
 import com.deepclone.lw.cmd.ObjectNameError;
 import com.deepclone.lw.cmd.player.gdata.GamePageData;
 import com.deepclone.lw.cmd.player.gdata.GameResponseBase;
+import com.deepclone.lw.session.API;
 
 
 
@@ -11,7 +12,7 @@ public class GetNewPlanetResponse
 		extends GameResponseBase
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final String name;
 	private final ObjectNameError error;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/ListPlanetsCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/ListPlanetsCommand.java
index bf8b5e8..28ad77c 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/ListPlanetsCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/ListPlanetsCommand.java
@@ -1,6 +1,7 @@
 package com.deepclone.lw.cmd.player;
 
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -9,6 +10,6 @@ public class ListPlanetsCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 }
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/ListPlanetsResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/ListPlanetsResponse.java
index 0e93aac..47a01b3 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/ListPlanetsResponse.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/ListPlanetsResponse.java
@@ -7,6 +7,7 @@ import java.util.List;
 import com.deepclone.lw.cmd.player.gdata.GamePageData;
 import com.deepclone.lw.cmd.player.gdata.GameResponseBase;
 import com.deepclone.lw.cmd.player.gdata.PlanetListData;
+import com.deepclone.lw.session.API;
 
 
 
@@ -14,7 +15,7 @@ public class ListPlanetsResponse
 		extends GameResponseBase
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final List< PlanetListData > planets;
 
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/OverviewCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/OverviewCommand.java
index 030a27b..c61817b 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/OverviewCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/OverviewCommand.java
@@ -1,6 +1,7 @@
 package com.deepclone.lw.cmd.player;
 
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -9,6 +10,6 @@ public class OverviewCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 }
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/UpdateEmpireMiningSettingsCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/UpdateEmpireMiningSettingsCommand.java
deleted file mode 100644
index 757417d..0000000
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/UpdateEmpireMiningSettingsCommand.java
+++ /dev/null
@@ -1,50 +0,0 @@
-package com.deepclone.lw.cmd.player;
-
-
-import java.util.Map;
-
-import com.deepclone.lw.session.Command;
-
-
-
-/**
- * Command that updates empire mining settings
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-public class UpdateEmpireMiningSettingsCommand
-		extends Command
-{
-
-	/**
-	 * Serialisation version identifier
-	 * 
-	 * <ul>
-	 * <li>Introduced in B6M2
-	 * </ul>
-	 */
-	private static final long serialVersionUID = 1L;
-
-	/** The new empire mining settings */
-	private final Map< String , Integer > settings;
-
-
-	/**
-	 * Initialise the command using mining settings
-	 * 
-	 * @param settings
-	 *            a map that associates resource identifiers to priorities
-	 */
-	public UpdateEmpireMiningSettingsCommand( Map< String , Integer > settings )
-	{
-		this.settings = settings;
-	}
-
-
-	/** @return the mining settings to apply */
-	public Map< String , Integer > getSettings( )
-	{
-		return this.settings;
-	}
-
-}
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/ViewMapCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/ViewMapCommand.java
index 2eb03bb..4ef2af4 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/ViewMapCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/ViewMapCommand.java
@@ -2,6 +2,7 @@ package com.deepclone.lw.cmd.player;
 
 
 import com.deepclone.lw.cmd.player.gdata.MapSize;
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -10,7 +11,7 @@ public class ViewMapCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final boolean defaults;
 	private final Integer x;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/ViewMapResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/ViewMapResponse.java
index 703b122..cca0e46 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/ViewMapResponse.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/ViewMapResponse.java
@@ -8,6 +8,7 @@ import com.deepclone.lw.cmd.player.gdata.GamePageData;
 import com.deepclone.lw.cmd.player.gdata.GameResponseBase;
 import com.deepclone.lw.cmd.player.gdata.MapSize;
 import com.deepclone.lw.cmd.player.gdata.map.MapSystemData;
+import com.deepclone.lw.session.API;
 
 
 
@@ -15,7 +16,7 @@ public class ViewMapResponse
 		extends GameResponseBase
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final int x;
 	private final int y;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/account/AccountReactivationCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/account/AccountReactivationCommand.java
index 2634d43..7d9967c 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/account/AccountReactivationCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/account/AccountReactivationCommand.java
@@ -1,6 +1,7 @@
 package com.deepclone.lw.cmd.player.account;
 
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -9,6 +10,6 @@ public class AccountReactivationCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 }
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/account/AccountReactivationResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/account/AccountReactivationResponse.java
index 9eddc44..a7cd609 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/account/AccountReactivationResponse.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/account/AccountReactivationResponse.java
@@ -1,6 +1,7 @@
 package com.deepclone.lw.cmd.player.account;
 
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.CommandResponse;
 
 
@@ -9,7 +10,7 @@ public class AccountReactivationResponse
 		extends CommandResponse
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final String address;
 
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/account/AccountValidationCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/account/AccountValidationCommand.java
index 9854256..6b37962 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/account/AccountValidationCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/account/AccountValidationCommand.java
@@ -1,6 +1,7 @@
 package com.deepclone.lw.cmd.player.account;
 
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -9,7 +10,7 @@ public class AccountValidationCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final boolean initialisation;
 
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/account/AccountValidationResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/account/AccountValidationResponse.java
index 8bd908f..cfa6bc3 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/account/AccountValidationResponse.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/account/AccountValidationResponse.java
@@ -5,6 +5,7 @@ import java.util.Collections;
 import java.util.List;
 
 import com.deepclone.lw.cmd.ObjectNameError;
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.CommandResponse;
 
 
@@ -13,7 +14,7 @@ public class AccountValidationResponse
 		extends CommandResponse
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final boolean validated;
 
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/account/BanDetailsCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/account/BanDetailsCommand.java
index dca68e4..3667bae 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/account/BanDetailsCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/account/BanDetailsCommand.java
@@ -1,6 +1,7 @@
 package com.deepclone.lw.cmd.player.account;
 
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -9,6 +10,6 @@ public class BanDetailsCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 }
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/account/BanDetailsResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/account/BanDetailsResponse.java
index 20e70c3..76b4d1c 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/account/BanDetailsResponse.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/account/BanDetailsResponse.java
@@ -3,6 +3,7 @@ package com.deepclone.lw.cmd.player.account;
 
 import java.sql.Timestamp;
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.CommandResponse;
 
 
@@ -11,7 +12,7 @@ public class BanDetailsResponse
 		extends CommandResponse
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final Timestamp banTime;
 	private final String banReason;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/account/CancelQuitCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/account/CancelQuitCommand.java
index 062f377..d4ba67f 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/account/CancelQuitCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/account/CancelQuitCommand.java
@@ -1,6 +1,7 @@
 package com.deepclone.lw.cmd.player.account;
 
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -9,6 +10,6 @@ public class CancelQuitCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 }
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/account/GetAccountCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/account/GetAccountCommand.java
index e51d582..63b4c7c 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/account/GetAccountCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/account/GetAccountCommand.java
@@ -1,11 +1,12 @@
 package com.deepclone.lw.cmd.player.account;
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 public class GetAccountCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 }
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/account/GetAccountResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/account/GetAccountResponse.java
index 3deb26c..913f598 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/account/GetAccountResponse.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/account/GetAccountResponse.java
@@ -4,6 +4,7 @@ package com.deepclone.lw.cmd.player.account;
 import com.deepclone.lw.cmd.player.gdata.GamePageData;
 import com.deepclone.lw.cmd.player.gdata.GameResponseBase;
 import com.deepclone.lw.cmd.player.gdata.account.AccountData;
+import com.deepclone.lw.session.API;
 
 
 
@@ -11,7 +12,7 @@ public class GetAccountResponse
 		extends GameResponseBase
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final AccountData account;
 
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/account/GetLanguageCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/account/GetLanguageCommand.java
index b60f61c..f86484f 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/account/GetLanguageCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/account/GetLanguageCommand.java
@@ -1,6 +1,7 @@
 package com.deepclone.lw.cmd.player.account;
 
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -9,6 +10,6 @@ public class GetLanguageCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 }
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/account/GetLanguageResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/account/GetLanguageResponse.java
index c18ad3d..d6d2bc4 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/account/GetLanguageResponse.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/account/GetLanguageResponse.java
@@ -1,6 +1,7 @@
 package com.deepclone.lw.cmd.player.account;
 
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.CommandResponse;
 
 
@@ -9,7 +10,7 @@ public class GetLanguageResponse
 		extends CommandResponse
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final String language;
 
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/account/QuitGameCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/account/QuitGameCommand.java
index c0a4776..a3bfd28 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/account/QuitGameCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/account/QuitGameCommand.java
@@ -1,6 +1,7 @@
 package com.deepclone.lw.cmd.player.account;
 
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -9,7 +10,7 @@ public class QuitGameCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final String reason;
 
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/account/SetAddressCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/account/SetAddressCommand.java
index 3362047..8ec0ddb 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/account/SetAddressCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/account/SetAddressCommand.java
@@ -1,6 +1,7 @@
 package com.deepclone.lw.cmd.player.account;
 
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -9,7 +10,7 @@ public class SetAddressCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final String sha1Auth;
 	private final String md5Auth;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/account/SetAddressResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/account/SetAddressResponse.java
index b281611..1f780e0 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/account/SetAddressResponse.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/account/SetAddressResponse.java
@@ -3,6 +3,7 @@ package com.deepclone.lw.cmd.player.account;
 
 import com.deepclone.lw.cmd.player.gdata.GamePageData;
 import com.deepclone.lw.cmd.player.gdata.account.AccountData;
+import com.deepclone.lw.session.API;
 
 
 
@@ -10,7 +11,7 @@ public class SetAddressResponse
 		extends GetAccountResponse
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	public static enum AddressChangeStatus {
 		OK ,
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/account/SetLanguageCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/account/SetLanguageCommand.java
index 75b7984..c38d16e 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/account/SetLanguageCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/account/SetLanguageCommand.java
@@ -1,6 +1,7 @@
 package com.deepclone.lw.cmd.player.account;
 
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -9,7 +10,7 @@ public class SetLanguageCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final String language;
 
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/account/SetPasswordCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/account/SetPasswordCommand.java
index ef777be..55f2aaf 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/account/SetPasswordCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/account/SetPasswordCommand.java
@@ -1,6 +1,7 @@
 package com.deepclone.lw.cmd.player.account;
 
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -9,7 +10,7 @@ public class SetPasswordCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final String sha1Auth;
 	private final String md5Auth;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/account/SetPasswordResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/account/SetPasswordResponse.java
index 3d6e71d..93fe53a 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/account/SetPasswordResponse.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/account/SetPasswordResponse.java
@@ -3,6 +3,7 @@ package com.deepclone.lw.cmd.player.account;
 
 import com.deepclone.lw.cmd.player.gdata.GamePageData;
 import com.deepclone.lw.cmd.player.gdata.account.AccountData;
+import com.deepclone.lw.session.API;
 
 
 
@@ -10,7 +11,7 @@ public class SetPasswordResponse
 		extends GetAccountResponse
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	public static enum PasswordChangeStatus {
 		OK ,
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/account/SetPreferencesCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/account/SetPreferencesCommand.java
index d1c4057..9d9b293 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/account/SetPreferencesCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/account/SetPreferencesCommand.java
@@ -3,6 +3,7 @@ package com.deepclone.lw.cmd.player.account;
 
 import java.util.Map;
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -11,7 +12,7 @@ public class SetPreferencesCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final Map< String , String > values;
 
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/account/ToggleVacationCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/account/ToggleVacationCommand.java
index da6d81a..4e910ee 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/account/ToggleVacationCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/account/ToggleVacationCommand.java
@@ -1,6 +1,7 @@
 package com.deepclone.lw.cmd.player.account;
 
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -9,6 +10,6 @@ public class ToggleVacationCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 }
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/account/ValidateSetAddressCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/account/ValidateSetAddressCommand.java
index 69ad994..feb53cd 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/account/ValidateSetAddressCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/account/ValidateSetAddressCommand.java
@@ -1,6 +1,7 @@
 package com.deepclone.lw.cmd.player.account;
 
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -9,7 +10,7 @@ public class ValidateSetAddressCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final boolean cancel;
 	private final String code;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/account/ValidateSetAddressResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/account/ValidateSetAddressResponse.java
index 5f1f15a..52b8cb0 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/account/ValidateSetAddressResponse.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/account/ValidateSetAddressResponse.java
@@ -3,6 +3,7 @@ package com.deepclone.lw.cmd.player.account;
 
 import com.deepclone.lw.cmd.player.gdata.GamePageData;
 import com.deepclone.lw.cmd.player.gdata.account.AccountData;
+import com.deepclone.lw.session.API;
 
 
 
@@ -10,7 +11,7 @@ public class ValidateSetAddressResponse
 		extends GetAccountResponse
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final boolean codeError;
 	private final String code;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/alliances/AllianceStatusCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/alliances/AllianceStatusCommand.java
index ceeb01c..a8d7220 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/alliances/AllianceStatusCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/alliances/AllianceStatusCommand.java
@@ -1,6 +1,7 @@
 package com.deepclone.lw.cmd.player.alliances;
 
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -9,6 +10,6 @@ public class AllianceStatusCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 }
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/alliances/AllianceStatusResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/alliances/AllianceStatusResponse.java
index f2eea70..63fb7c2 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/alliances/AllianceStatusResponse.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/alliances/AllianceStatusResponse.java
@@ -4,6 +4,7 @@ package com.deepclone.lw.cmd.player.alliances;
 import com.deepclone.lw.cmd.player.gdata.GamePageData;
 import com.deepclone.lw.cmd.player.gdata.GameResponseBase;
 import com.deepclone.lw.cmd.player.gdata.alliance.AllianceData;
+import com.deepclone.lw.session.API;
 
 
 
@@ -11,7 +12,7 @@ public class AllianceStatusResponse
 		extends GameResponseBase
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final AllianceData alliance;
 
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/alliances/CancelJoinCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/alliances/CancelJoinCommand.java
index 54af717..5610612 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/alliances/CancelJoinCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/alliances/CancelJoinCommand.java
@@ -1,6 +1,7 @@
 package com.deepclone.lw.cmd.player.alliances;
 
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -9,6 +10,6 @@ public class CancelJoinCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 }
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/alliances/CreateAllianceCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/alliances/CreateAllianceCommand.java
index 5e250e7..8ca082f 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/alliances/CreateAllianceCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/alliances/CreateAllianceCommand.java
@@ -1,6 +1,7 @@
 package com.deepclone.lw.cmd.player.alliances;
 
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -8,7 +9,7 @@ import com.deepclone.lw.session.Command;
 public class CreateAllianceCommand
 		extends Command
 {
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final String tag;
 	private final String name;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/alliances/CreateAllianceResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/alliances/CreateAllianceResponse.java
index c484453..133e48f 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/alliances/CreateAllianceResponse.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/alliances/CreateAllianceResponse.java
@@ -4,6 +4,7 @@ package com.deepclone.lw.cmd.player.alliances;
 import com.deepclone.lw.cmd.player.gdata.GamePageData;
 import com.deepclone.lw.cmd.player.gdata.alliance.AllianceCreationStatus;
 import com.deepclone.lw.cmd.player.gdata.alliance.AllianceData;
+import com.deepclone.lw.session.API;
 
 
 
@@ -11,7 +12,7 @@ public class CreateAllianceResponse
 		extends AllianceStatusResponse
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final AllianceCreationStatus creation;
 
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/alliances/JoinAllianceCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/alliances/JoinAllianceCommand.java
index e0fe9cd..5a6c4bf 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/alliances/JoinAllianceCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/alliances/JoinAllianceCommand.java
@@ -1,6 +1,7 @@
 package com.deepclone.lw.cmd.player.alliances;
 
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -8,7 +9,7 @@ import com.deepclone.lw.session.Command;
 public class JoinAllianceCommand
 		extends Command
 {
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final String tag;
 
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/alliances/JoinAllianceResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/alliances/JoinAllianceResponse.java
index d544543..9bf4f40 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/alliances/JoinAllianceResponse.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/alliances/JoinAllianceResponse.java
@@ -3,6 +3,7 @@ package com.deepclone.lw.cmd.player.alliances;
 
 import com.deepclone.lw.cmd.player.gdata.GamePageData;
 import com.deepclone.lw.cmd.player.gdata.alliance.AllianceData;
+import com.deepclone.lw.session.API;
 
 
 
@@ -10,7 +11,7 @@ public class JoinAllianceResponse
 		extends AllianceStatusResponse
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final String joinFailure;
 
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/alliances/KickMembersCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/alliances/KickMembersCommand.java
index fddf2a3..7c430db 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/alliances/KickMembersCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/alliances/KickMembersCommand.java
@@ -1,6 +1,7 @@
 package com.deepclone.lw.cmd.player.alliances;
 
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -9,7 +10,7 @@ public class KickMembersCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final int[] members;
 
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/alliances/LeaveAllianceCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/alliances/LeaveAllianceCommand.java
index 4cf33da..bb518ae 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/alliances/LeaveAllianceCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/alliances/LeaveAllianceCommand.java
@@ -1,6 +1,7 @@
 package com.deepclone.lw.cmd.player.alliances;
 
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -9,6 +10,6 @@ public class LeaveAllianceCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 }
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/alliances/ManageRequestsCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/alliances/ManageRequestsCommand.java
index 826e1a1..7f78179 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/alliances/ManageRequestsCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/alliances/ManageRequestsCommand.java
@@ -1,6 +1,7 @@
 package com.deepclone.lw.cmd.player.alliances;
 
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -9,7 +10,7 @@ public class ManageRequestsCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final int[] members;
 	private final boolean accept;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/alliances/TransferLeadershipCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/alliances/TransferLeadershipCommand.java
index 558d360..c0671df 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/alliances/TransferLeadershipCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/alliances/TransferLeadershipCommand.java
@@ -1,6 +1,7 @@
 package com.deepclone.lw.cmd.player.alliances;
 
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -9,7 +10,7 @@ public class TransferLeadershipCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final int toMember;
 
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/alliances/ViewAllianceCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/alliances/ViewAllianceCommand.java
index aa201bf..cea77b0 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/alliances/ViewAllianceCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/alliances/ViewAllianceCommand.java
@@ -1,6 +1,7 @@
 package com.deepclone.lw.cmd.player.alliances;
 
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -8,7 +9,7 @@ import com.deepclone.lw.session.Command;
 public class ViewAllianceCommand
 		extends Command
 {
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final String tag;
 
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/alliances/ViewAllianceResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/alliances/ViewAllianceResponse.java
index 2f3e083..29da170 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/alliances/ViewAllianceResponse.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/alliances/ViewAllianceResponse.java
@@ -4,6 +4,7 @@ package com.deepclone.lw.cmd.player.alliances;
 import com.deepclone.lw.cmd.player.gdata.GamePageData;
 import com.deepclone.lw.cmd.player.gdata.alliance.AllianceData;
 import com.deepclone.lw.cmd.player.gdata.alliance.PublicAllianceInformation;
+import com.deepclone.lw.session.API;
 
 
 
@@ -11,7 +12,7 @@ public class ViewAllianceResponse
 		extends AllianceStatusResponse
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final String requested;
 	private final PublicAllianceInformation info;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/battles/GetBattleCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/battles/GetBattleCommand.java
index 555c2f4..c65ef39 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/battles/GetBattleCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/battles/GetBattleCommand.java
@@ -1,6 +1,7 @@
 package com.deepclone.lw.cmd.player.battles;
 
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -9,7 +10,7 @@ public class GetBattleCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final long battle;
 	private final Long tick;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/battles/GetBattleResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/battles/GetBattleResponse.java
index bf46be5..ce78d6b 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/battles/GetBattleResponse.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/battles/GetBattleResponse.java
@@ -4,13 +4,14 @@ package com.deepclone.lw.cmd.player.battles;
 import com.deepclone.lw.cmd.player.gdata.GamePageData;
 import com.deepclone.lw.cmd.player.gdata.GameResponseBase;
 import com.deepclone.lw.cmd.player.gdata.battles.BattleView;
+import com.deepclone.lw.session.API;
 
 
 
 public class GetBattleResponse
 		extends GameResponseBase
 {
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 	private final BattleView battle;
 
 
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/battles/ListBattlesCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/battles/ListBattlesCommand.java
index 6b8041a..9ee8ee7 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/battles/ListBattlesCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/battles/ListBattlesCommand.java
@@ -1,6 +1,7 @@
 package com.deepclone.lw.cmd.player.battles;
 
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -9,7 +10,7 @@ public class ListBattlesCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final int page;
 
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/battles/ListBattlesResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/battles/ListBattlesResponse.java
index a4856c7..2681b84 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/battles/ListBattlesResponse.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/battles/ListBattlesResponse.java
@@ -6,6 +6,7 @@ import java.util.List;
 import com.deepclone.lw.cmd.player.gdata.GamePageData;
 import com.deepclone.lw.cmd.player.gdata.GameResponseBase;
 import com.deepclone.lw.cmd.player.gdata.battles.BattleListEntry;
+import com.deepclone.lw.session.API;
 
 
 
@@ -13,7 +14,7 @@ public class ListBattlesResponse
 		extends GameResponseBase
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 	private final List< BattleListEntry > list;
 	private final int currentPage;
 	private final int pages;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/bt/ListBugsResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/bt/ListBugsResponse.java
index 6481ab0..21e84ee 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/bt/ListBugsResponse.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/bt/ListBugsResponse.java
@@ -7,6 +7,7 @@ import com.deepclone.lw.cmd.bt.data.BugReport;
 import com.deepclone.lw.cmd.bt.data.BugStatus;
 import com.deepclone.lw.cmd.player.gdata.GamePageData;
 import com.deepclone.lw.cmd.player.gdata.GameResponseBase;
+import com.deepclone.lw.session.API;
 
 
 
@@ -14,7 +15,7 @@ public class ListBugsResponse
 		extends GameResponseBase
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final BugStatus status;
 	private final boolean ownOnly;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/bt/PostCommentResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/bt/PostCommentResponse.java
index 2c7c353..97af985 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/bt/PostCommentResponse.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/bt/PostCommentResponse.java
@@ -7,6 +7,7 @@ import com.deepclone.lw.cmd.ObjectNameError;
 import com.deepclone.lw.cmd.bt.data.BugEvent;
 import com.deepclone.lw.cmd.bt.data.BugReport;
 import com.deepclone.lw.cmd.player.gdata.GamePageData;
+import com.deepclone.lw.session.API;
 
 
 
@@ -14,7 +15,7 @@ public class PostCommentResponse
 		extends ViewBugResponse
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final boolean posted;
 	private final ObjectNameError commentError;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/bt/ReportBugResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/bt/ReportBugResponse.java
index 6fb47c9..c5657cb 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/bt/ReportBugResponse.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/bt/ReportBugResponse.java
@@ -4,6 +4,7 @@ package com.deepclone.lw.cmd.player.bt;
 import com.deepclone.lw.cmd.ObjectNameError;
 import com.deepclone.lw.cmd.player.gdata.GamePageData;
 import com.deepclone.lw.cmd.player.gdata.GameResponseBase;
+import com.deepclone.lw.session.API;
 
 
 
@@ -11,7 +12,7 @@ public class ReportBugResponse
 		extends GameResponseBase
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final long bugId;
 	private final ObjectNameError titleError;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/bt/ViewBugResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/bt/ViewBugResponse.java
index 0f487c5..a7d18f3 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/bt/ViewBugResponse.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/bt/ViewBugResponse.java
@@ -7,6 +7,7 @@ import com.deepclone.lw.cmd.bt.data.BugEvent;
 import com.deepclone.lw.cmd.bt.data.BugReport;
 import com.deepclone.lw.cmd.player.gdata.GamePageData;
 import com.deepclone.lw.cmd.player.gdata.GameResponseBase;
+import com.deepclone.lw.session.API;
 
 
 
@@ -14,7 +15,7 @@ public class ViewBugResponse
 		extends GameResponseBase
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final BugReport report;
 	private final List< BugEvent > events;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/elist/AddEnemyCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/elist/AddEnemyCommand.java
index f4342b2..5ee13fd 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/elist/AddEnemyCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/elist/AddEnemyCommand.java
@@ -1,6 +1,7 @@
 package com.deepclone.lw.cmd.player.elist;
 
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -9,7 +10,7 @@ public class AddEnemyCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final boolean alliance;
 	private final String name;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/elist/AddEnemyResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/elist/AddEnemyResponse.java
index 0e3e7e2..99f369f 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/elist/AddEnemyResponse.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/elist/AddEnemyResponse.java
@@ -6,6 +6,7 @@ import java.util.List;
 import com.deepclone.lw.cmd.ObjectNameError;
 import com.deepclone.lw.cmd.player.gdata.GamePageData;
 import com.deepclone.lw.cmd.player.gdata.NameIdPair;
+import com.deepclone.lw.session.API;
 
 
 
@@ -13,7 +14,7 @@ public class AddEnemyResponse
 		extends EnemyListResponse
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final ObjectNameError error;
 	private final boolean alliance;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/elist/EnemyListCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/elist/EnemyListCommand.java
index d72bf7d..c8e85a1 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/elist/EnemyListCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/elist/EnemyListCommand.java
@@ -1,6 +1,7 @@
 package com.deepclone.lw.cmd.player.elist;
 
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -9,6 +10,6 @@ public class EnemyListCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 }
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/elist/EnemyListResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/elist/EnemyListResponse.java
index 85ebd0d..8abccc6 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/elist/EnemyListResponse.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/elist/EnemyListResponse.java
@@ -6,13 +6,14 @@ import java.util.List;
 import com.deepclone.lw.cmd.player.gdata.GamePageData;
 import com.deepclone.lw.cmd.player.gdata.GameResponseBase;
 import com.deepclone.lw.cmd.player.gdata.NameIdPair;
+import com.deepclone.lw.session.API;
 
 
 
 public class EnemyListResponse
 		extends GameResponseBase
 {
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final List< NameIdPair > empires;
 	private final List< NameIdPair > alliances;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/elist/RemoveEnemiesCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/elist/RemoveEnemiesCommand.java
index 9a3ffbe..617ea27 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/elist/RemoveEnemiesCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/elist/RemoveEnemiesCommand.java
@@ -1,6 +1,7 @@
 package com.deepclone.lw.cmd.player.elist;
 
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -9,7 +10,7 @@ public class RemoveEnemiesCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final boolean alliance;
 	private final int[] identifiers;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/fleets/DisbandFleetsCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/fleets/DisbandFleetsCommand.java
index 4ac3589..a61e613 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/fleets/DisbandFleetsCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/fleets/DisbandFleetsCommand.java
@@ -1,11 +1,13 @@
 package com.deepclone.lw.cmd.player.fleets;
 
+import com.deepclone.lw.session.API;
+
 
 public class DisbandFleetsCommand
 		extends MultiFleetsCommand
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final boolean confirm;
 
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/fleets/DisbandFleetsResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/fleets/DisbandFleetsResponse.java
index 9eace3b..ec51c4b 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/fleets/DisbandFleetsResponse.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/fleets/DisbandFleetsResponse.java
@@ -2,6 +2,7 @@ package com.deepclone.lw.cmd.player.fleets;
 
 
 import com.deepclone.lw.cmd.player.gdata.GamePageData;
+import com.deepclone.lw.session.API;
 
 
 
@@ -9,7 +10,7 @@ public class DisbandFleetsResponse
 		extends MultiFleetsResponse
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 
 	public DisbandFleetsResponse( GamePageData page )
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/fleets/MergeFleetsCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/fleets/MergeFleetsCommand.java
index f5029ce..24ba678 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/fleets/MergeFleetsCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/fleets/MergeFleetsCommand.java
@@ -1,11 +1,13 @@
 package com.deepclone.lw.cmd.player.fleets;
 
+import com.deepclone.lw.session.API;
+
 
 public class MergeFleetsCommand
 		extends MultiFleetsCommand
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 
 	public MergeFleetsCommand( long[] fleets )
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/fleets/MergeFleetsResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/fleets/MergeFleetsResponse.java
index f0e92a5..642dde5 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/fleets/MergeFleetsResponse.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/fleets/MergeFleetsResponse.java
@@ -2,6 +2,7 @@ package com.deepclone.lw.cmd.player.fleets;
 
 
 import com.deepclone.lw.cmd.player.gdata.GamePageData;
+import com.deepclone.lw.session.API;
 
 
 
@@ -9,7 +10,7 @@ public class MergeFleetsResponse
 		extends MultiFleetsResponse
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 
 	public MergeFleetsResponse( GamePageData page )
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/fleets/MoveFleetsCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/fleets/MoveFleetsCommand.java
index 1efee46..8a8c811 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/fleets/MoveFleetsCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/fleets/MoveFleetsCommand.java
@@ -1,11 +1,13 @@
 package com.deepclone.lw.cmd.player.fleets;
 
+import com.deepclone.lw.session.API;
+
 
 public class MoveFleetsCommand
 		extends MultiFleetsCommand
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 	
 	private final String destination;
 	private final Boolean mode;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/fleets/MoveFleetsResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/fleets/MoveFleetsResponse.java
index e524398..77f9631 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/fleets/MoveFleetsResponse.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/fleets/MoveFleetsResponse.java
@@ -2,6 +2,7 @@ package com.deepclone.lw.cmd.player.fleets;
 
 
 import com.deepclone.lw.cmd.player.gdata.GamePageData;
+import com.deepclone.lw.session.API;
 
 
 
@@ -9,7 +10,7 @@ public class MoveFleetsResponse
 		extends MultiFleetsResponse
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private boolean error;
 	private String destination;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/fleets/MultiFleetsCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/fleets/MultiFleetsCommand.java
index 4ebc86c..ef11bda 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/fleets/MultiFleetsCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/fleets/MultiFleetsCommand.java
@@ -1,6 +1,7 @@
 package com.deepclone.lw.cmd.player.fleets;
 
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -8,7 +9,7 @@ import com.deepclone.lw.session.Command;
 public abstract class MultiFleetsCommand
 		extends Command
 {
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final long fleets[];
 
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/fleets/MultiFleetsResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/fleets/MultiFleetsResponse.java
index 3728e18..a7bea2b 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/fleets/MultiFleetsResponse.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/fleets/MultiFleetsResponse.java
@@ -7,6 +7,7 @@ import java.util.List;
 import com.deepclone.lw.cmd.player.gdata.GamePageData;
 import com.deepclone.lw.cmd.player.gdata.GameResponseBase;
 import com.deepclone.lw.cmd.player.gdata.fleets.ShortFleetView;
+import com.deepclone.lw.session.API;
 
 
 
@@ -14,7 +15,7 @@ public abstract class MultiFleetsResponse
 		extends GameResponseBase
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final List< ShortFleetView > fleets = new LinkedList< ShortFleetView >( );
 
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/fleets/RenameFleetsCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/fleets/RenameFleetsCommand.java
index 95393e6..1dd1331 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/fleets/RenameFleetsCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/fleets/RenameFleetsCommand.java
@@ -1,11 +1,13 @@
 package com.deepclone.lw.cmd.player.fleets;
 
+import com.deepclone.lw.session.API;
+
 
 public class RenameFleetsCommand
 		extends MultiFleetsCommand
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final boolean rename;
 	private final String name;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/fleets/RenameFleetsResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/fleets/RenameFleetsResponse.java
index e20a569..d5b792d 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/fleets/RenameFleetsResponse.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/fleets/RenameFleetsResponse.java
@@ -2,6 +2,7 @@ package com.deepclone.lw.cmd.player.fleets;
 
 
 import com.deepclone.lw.cmd.player.gdata.GamePageData;
+import com.deepclone.lw.session.API;
 
 
 
@@ -9,7 +10,7 @@ public class RenameFleetsResponse
 		extends MultiFleetsResponse
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private boolean error;
 	private String name;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/fleets/SetFleetsModeCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/fleets/SetFleetsModeCommand.java
index 3f44ab3..4a253bd 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/fleets/SetFleetsModeCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/fleets/SetFleetsModeCommand.java
@@ -1,11 +1,13 @@
 package com.deepclone.lw.cmd.player.fleets;
 
+import com.deepclone.lw.session.API;
+
 
 public class SetFleetsModeCommand
 		extends MultiFleetsCommand
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final boolean attack;
 	private final boolean confirm;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/fleets/SetFleetsModeResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/fleets/SetFleetsModeResponse.java
index edf245c..bc515ef 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/fleets/SetFleetsModeResponse.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/fleets/SetFleetsModeResponse.java
@@ -2,6 +2,7 @@ package com.deepclone.lw.cmd.player.fleets;
 
 
 import com.deepclone.lw.cmd.player.gdata.GamePageData;
+import com.deepclone.lw.session.API;
 
 
 
@@ -9,7 +10,7 @@ public class SetFleetsModeResponse
 		extends MultiFleetsResponse
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private boolean attack;
 
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/fleets/SplitFleetCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/fleets/SplitFleetCommand.java
index 686a3c2..dbdbacd 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/fleets/SplitFleetCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/fleets/SplitFleetCommand.java
@@ -3,6 +3,7 @@ package com.deepclone.lw.cmd.player.fleets;
 
 import java.util.Map;
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -11,7 +12,7 @@ public class SplitFleetCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final long fleet;
 	private final Map< Integer , Integer > ships;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/fleets/SplitFleetResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/fleets/SplitFleetResponse.java
index 6351066..c59f9d2 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/fleets/SplitFleetResponse.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/fleets/SplitFleetResponse.java
@@ -8,6 +8,7 @@ import com.deepclone.lw.cmd.player.gdata.GamePageData;
 import com.deepclone.lw.cmd.player.gdata.GameResponseBase;
 import com.deepclone.lw.cmd.player.gdata.fleets.ShortFleetView;
 import com.deepclone.lw.cmd.player.gdata.fleets.SplitShips;
+import com.deepclone.lw.session.API;
 
 
 
@@ -15,7 +16,7 @@ public class SplitFleetResponse
 		extends GameResponseBase
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private ShortFleetView initialFleet;
 	private final List< SplitShips > ships = new LinkedList< SplitShips >( );
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/fleets/ViewFleetsCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/fleets/ViewFleetsCommand.java
index 67f33d3..ab631d1 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/fleets/ViewFleetsCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/fleets/ViewFleetsCommand.java
@@ -1,6 +1,7 @@
 package com.deepclone.lw.cmd.player.fleets;
 
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -9,6 +10,6 @@ public class ViewFleetsCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 }
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/fleets/ViewFleetsResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/fleets/ViewFleetsResponse.java
index d1c6484..2b53ce4 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/fleets/ViewFleetsResponse.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/fleets/ViewFleetsResponse.java
@@ -4,6 +4,7 @@ package com.deepclone.lw.cmd.player.fleets;
 import com.deepclone.lw.cmd.player.gdata.GamePageData;
 import com.deepclone.lw.cmd.player.gdata.GameResponseBase;
 import com.deepclone.lw.cmd.player.gdata.fleets.FleetsView;
+import com.deepclone.lw.session.API;
 
 
 
@@ -11,7 +12,7 @@ public class ViewFleetsResponse
 		extends GameResponseBase
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 	private final FleetsView fleets;
 
 
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/AbstractResourceRecord.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/AbstractResourceRecord.java
deleted file mode 100644
index 605a4ac..0000000
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/AbstractResourceRecord.java
+++ /dev/null
@@ -1,109 +0,0 @@
-package com.deepclone.lw.cmd.player.gdata;
-
-
-import java.io.Serializable;
-
-
-
-public abstract class AbstractResourceRecord
-		implements Serializable
-{
-
-	/**
-	 * The serialisation version identifier
-	 * 
-	 * <ul>
-	 * <li>Introduced in B6M2 with ID 1
-	 * </ul>
-	 */
-	private static final long serialVersionUID = 1L;
-
-	/** The text identifier of the resource */
-	private String identifier;
-
-	/** The internationalised name of the resource's category */
-	private String category;
-
-	/** The internationalised name of the resource */
-	private String title;
-
-	/** The internationalised description of the resource */
-	private String description;
-
-
-	/** @return the text identifying the resource */
-	public String getIdentifier( )
-	{
-		return this.identifier;
-	}
-
-
-	/**
-	 * Set the text identifying the resource
-	 * 
-	 * @param identifier
-	 *            the text identifying the resource
-	 */
-	public void setIdentifier( String identifier )
-	{
-		this.identifier = identifier;
-	}
-
-
-	/** @return the internationalised title of the resource */
-	public String getTitle( )
-	{
-		return this.title;
-	}
-
-
-	/**
-	 * Set the internationalised title of the resource
-	 * 
-	 * @param title
-	 *            the internationalised title of the resource
-	 */
-	public void setTitle( String title )
-	{
-		this.title = title;
-	}
-
-
-	/** @return the internationalised name of the category of the resource */
-	public String getCategory( )
-	{
-		return this.category;
-	}
-
-
-	/**
-	 * Set the internationalised name of the category of the resource
-	 * 
-	 * @param category
-	 *            the internationalised name of the category of the resource
-	 */
-	public void setCategory( String category )
-	{
-		this.category = category;
-	}
-
-
-	/** @return the internationalised description of the resource */
-	public String getDescription( )
-	{
-		return this.description;
-	}
-
-
-	/**
-	 * Set the internationalised description of the resource
-	 * 
-	 * @param description
-	 *            the internationalised description of the resource
-	 */
-	public void setDescription( String description )
-	{
-		this.description = description;
-	}
-
-}
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/GamePageData.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/GamePageData.java
index 59cef53..16fdf2c 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/GamePageData.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/GamePageData.java
@@ -6,93 +6,27 @@ import java.util.Collections;
 import java.util.Date;
 import java.util.List;
 
+import com.deepclone.lw.session.API;
+
 
 
-/**
- * General information included in a game response
- * 
- * <p>
- * This class stores common information which is included in most in-game responses. This
- * information includes some essential preferences, the general state of the empire, and some
- * information about the server's state.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
 public class GamePageData
 		implements Serializable
 {
-	/**
-	 * The serialisation version identifier
-	 * 
-	 * <ul>
-	 * <li>Introduced in B6M1 with ID 1
-	 * <li>Modified in B6M2, ID set to 2
-	 * </ul>
-	 */
-	private static final long serialVersionUID = 1L;
 
-	/** The name of the current empire */
+	private static final long serialVersionUID = API.Version;
 	private final String empire;
-
-	/**
-	 * State of the account
-	 * 
-	 * <p>
-	 * This field indicates the "special" state of the account: <code>q</code> is for accounts that
-	 * are quitting, <code>v</code> for accounts in vacation mode and <code>s</code> for accounts
-	 * that are about to enter vacation mode. <code>null</code> indicates "none of the above".
-	 */
 	private final Character special;
-
-	/** Alliance tag, or <code>null</code> if not a full member of any alliance */
 	private final String alliance;
-
-	/**
-	 * Current cash of the empire
-	 * 
-	 * <p>
-	 * FIXME: will be replaced with actual resources
-	 */
 	private final long cash;
-
-	/** Timestamp from the server's system */
 	private final Date serverTime;
-
-	/** Current game time (from last update identifier) */
 	private final GameTime gameTime;
-
-	/** Planets owned by the empire */
 	private final List< NameIdPair > planets;
-
-	/** Whether the player wants to see "real" times or in-game times */
 	private final boolean useRLTime;
 
-	/** Code of selected language */
-	private final String language;
 
-
-	/**
-	 * Initialise the general game information record
-	 * 
-	 * @param empire
-	 *            the empire's name
-	 * @param special
-	 *            the special account state character (see {@link #special})
-	 * @param alliance
-	 *            current alliance tag
-	 * @param cash
-	 *            current cash
-	 * @param gameTime
-	 *            last update identifier
-	 * @param planets
-	 *            list of planets owned by the empire
-	 * @param useRLTime
-	 *            whether the player wants to see "real" times or in-game times
-	 * @param language
-	 *            selected language code
-	 */
 	public GamePageData( String empire , Character special , String alliance , long cash , long gameTime ,
-			List< NameIdPair > planets , boolean useRLTime , String language )
+			List< NameIdPair > planets , boolean useRLTime )
 	{
 		this.empire = empire;
 		this.special = special;
@@ -102,107 +36,54 @@ public class GamePageData
 		this.gameTime = new GameTime( gameTime );
 		this.planets = Collections.unmodifiableList( planets );
 		this.useRLTime = useRLTime;
-		this.language = language;
 	}
 
 
-	/**
-	 * Gets the name of the current empire.
-	 * 
-	 * @return the name of the current empire
-	 */
 	public String getEmpire( )
 	{
-		return this.empire;
+		return empire;
 	}
 
 
-	/**
-	 * Gets the state of the account
-	 * 
-	 * @return the state of the account
-	 */
 	public Character getSpecial( )
 	{
-		return this.special;
+		return special;
 	}
 
 
-	/**
-	 * Gets the alliance tag
-	 * 
-	 * @return the alliance tag, or <code>null</code> if not a full member of any alliance
-	 */
 	public String getAlliance( )
 	{
-		return this.alliance;
+		return alliance;
 	}
 
 
-	/**
-	 * Gets the current cash of the empire
-	 * 
-	 * @return the current cash of the empire
-	 */
 	public long getCash( )
 	{
-		return this.cash;
+		return cash;
 	}
 
 
-	/**
-	 * Gets the timestamp from the server's system.
-	 * 
-	 * @return the timestamp from the server's system
-	 */
 	public Date getServerTime( )
 	{
-		return this.serverTime;
+		return serverTime;
 	}
 
 
-	/**
-	 * Gets the current game time
-	 * 
-	 * @return the current game time
-	 */
 	public GameTime getGameTime( )
 	{
-		return this.gameTime;
+		return gameTime;
 	}
 
 
-	/**
-	 * Gets the planets owned by the empire.
-	 * 
-	 * @return the list of planets owned by the empire
-	 */
 	public List< NameIdPair > getPlanets( )
 	{
-		return this.planets;
+		return planets;
 	}
 
 
-	/**
-	 * Checks if the player wants to see "real" times or in-game times.
-	 * 
-	 * @return <code>true</code> if the player wants to see "real" times, <code>false</code> for
-	 *         in-game times
-	 */
 	public boolean isUseRLTime( )
 	{
-		return this.useRLTime;
-	}
-
-
-	/**
-	 * Gets the code of selected language.
-	 * 
-	 * @return the code of selected language
-	 */
-	public String getLanguage( )
-	{
-		return this.language;
+		return useRLTime;
 	}
 
 }
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/GameResponseBase.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/GameResponseBase.java
index f535b9d..45de365 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/GameResponseBase.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/GameResponseBase.java
@@ -1,6 +1,7 @@
 package com.deepclone.lw.cmd.player.gdata;
 
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.CommandResponse;
 
 
@@ -9,7 +10,7 @@ public abstract class GameResponseBase
 		extends CommandResponse
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final GamePageData page;
 
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/GameTime.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/GameTime.java
index ac2c9b1..9aa4302 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/GameTime.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/GameTime.java
@@ -3,13 +3,15 @@ package com.deepclone.lw.cmd.player.gdata;
 
 import java.io.Serializable;
 
+import com.deepclone.lw.session.API;
+
 
 
 public class GameTime
 		implements Serializable
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final int years;
 	private final int weeks;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/NameIdPair.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/NameIdPair.java
index 4bea9e4..11010d0 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/NameIdPair.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/NameIdPair.java
@@ -3,13 +3,15 @@ package com.deepclone.lw.cmd.player.gdata;
 
 import java.io.Serializable;
 
+import com.deepclone.lw.session.API;
+
 
 
 public class NameIdPair
 		implements Serializable
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final long id;
 	private final String name;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/PlanetListData.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/PlanetListData.java
index 7814d38..4a1bf05 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/PlanetListData.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/PlanetListData.java
@@ -2,663 +2,333 @@ package com.deepclone.lw.cmd.player.gdata;
 
 
 import java.io.Serializable;
-import java.util.List;
+
+import com.deepclone.lw.session.API;
 
 
 
-/**
- * An entry in the planet list
- * 
- * <p>
- * This class represents an entry in the planet list. It contains all available information about a
- * single planet.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
 public class PlanetListData
 		implements Serializable
 {
 
-	/**
-	 * Serialisation version identifier
-	 * 
-	 * <ul>
-	 * <li>Introduced in B6M1 with ID 1
-	 * <li>Modified in B6M2, ID set to 2
-	 * </ul>
-	 */
-	private static final long serialVersionUID = 2L;
+	private static final long serialVersionUID = API.Version;
 
-	/** Identifier of the planet */
 	private int id;
-	/** Name of the planet */
 	private String name;
 
-	/** Abscissa of the planet's system */
 	private int x;
-	/** Ordinates of the planet's system */
 	private int y;
-	/** Orbit of the planet in its system */
 	private int orbit;
 
-	/** Current population */
 	private long population;
-	/** Happiness percentage */
 	private int happiness;
 
-	/** Resources information (income, upkeep, etc...) */
-	private List< PlanetListResourceRecord > resources;
-
-	/** Monetary income of the planet */
 	private long income;
-	/** Monetary upkeep of the planet */
 	private long upkeep;
 
-	/** Current military production */
 	private long militaryProduction;
-	/** Current industrial production */
 	private long industrialProduction;
-	/** Current "extra population growth" production */
 	private long growthProduction;
 
-	/** Money invested in the civilian queue */
 	private long civInvestment;
-	/** Amount of buildings in the civilian queue */
 	private int civAmount;
-	/** Whether the current operation on the civilian queue is a destruction */
 	private boolean civDestroy;
-	/** Name of the buildings being destroyed or constructed */
 	private String civName;
 
-	/** Money invested in the military build queue */
 	private long milInvestment;
-	/** Amount of ships in the civilian queue */
 	private int milAmount;
-	/** Name of the ships being constructed */
 	private String milName;
 
-	/** Fleet power from turrets */
 	private long fpStatic;
-	/** Power of the owner's fleets */
 	private long fpOwn;
-	/** Power of the friendly fleets */
 	private long fpFriendly;
-	/** Power of the hostile fleets */
 	private long fpHostile;
 
-	/** Battle identifier or <code>null</code> if there is no battle */
 	private Long battle;
 
 
-	/**
-	 * Gets the identifier of the planet.
-	 * 
-	 * @return the identifier of the planet
-	 */
 	public int getId( )
 	{
-		return this.id;
+		return id;
 	}
 
 
-	/**
-	 * Sets the identifier of the planet.
-	 * 
-	 * @param id
-	 *            the new identifier of the planet
-	 */
 	public void setId( int id )
 	{
 		this.id = id;
 	}
 
 
-	/**
-	 * Gets the name of the planet.
-	 * 
-	 * @return the name of the planet
-	 */
 	public String getName( )
 	{
-		return this.name;
+		return name;
 	}
 
 
-	/**
-	 * Sets the name of the planet.
-	 * 
-	 * @param name
-	 *            the new name of the planet
-	 */
 	public void setName( String name )
 	{
 		this.name = name;
 	}
 
 
-	/**
-	 * Gets the abscissa of the planet's system.
-	 * 
-	 * @return the abscissa of the planet's system
-	 */
 	public int getX( )
 	{
-		return this.x;
+		return x;
 	}
 
 
-	/**
-	 * Sets the abscissa of the planet's system.
-	 * 
-	 * @param x
-	 *            the new abscissa of the planet's system
-	 */
 	public void setX( int x )
 	{
 		this.x = x;
 	}
 
 
-	/**
-	 * Gets the ordinates of the planet's system.
-	 * 
-	 * @return the ordinates of the planet's system
-	 */
 	public int getY( )
 	{
-		return this.y;
+		return y;
 	}
 
 
-	/**
-	 * Sets the ordinates of the planet's system.
-	 * 
-	 * @param y
-	 *            the new ordinates of the planet's system
-	 */
 	public void setY( int y )
 	{
 		this.y = y;
 	}
 
 
-	/**
-	 * Gets the orbit of the planet in its system.
-	 * 
-	 * @return the orbit of the planet in its system
-	 */
 	public int getOrbit( )
 	{
-		return this.orbit;
+		return orbit;
 	}
 
 
-	/**
-	 * Sets the orbit of the planet in its system.
-	 * 
-	 * @param orbit
-	 *            the new orbit of the planet in its system
-	 */
 	public void setOrbit( int orbit )
 	{
 		this.orbit = orbit;
 	}
 
 
-	/**
-	 * Gets the current population.
-	 * 
-	 * @return the current population
-	 */
 	public long getPopulation( )
 	{
-		return this.population;
+		return population;
 	}
 
 
-	/**
-	 * Sets the current population.
-	 * 
-	 * @param population
-	 *            the new current population
-	 */
 	public void setPopulation( long population )
 	{
 		this.population = population;
 	}
 
 
-	/**
-	 * Gets the happiness percentage.
-	 * 
-	 * @return the happiness percentage
-	 */
 	public int getHappiness( )
 	{
-		return this.happiness;
+		return happiness;
 	}
 
 
-	/**
-	 * Sets the happiness percentage.
-	 * 
-	 * @param happiness
-	 *            the new happiness percentage
-	 */
 	public void setHappiness( int happiness )
 	{
 		this.happiness = happiness;
 	}
 
 
-	/**
-	 * Gets the resources information records
-	 * 
-	 * @return the resources information records
-	 */
-	public List< PlanetListResourceRecord > getResources( )
-	{
-		return this.resources;
-	}
-
-
-	/**
-	 * Sets the resources information records
-	 * 
-	 * @param resources
-	 *            the new resources information records
-	 */
-	public void setResources( List< PlanetListResourceRecord > resources )
-	{
-		this.resources = resources;
-	}
-
-
-	/**
-	 * Gets the monetary income of the planet.
-	 * 
-	 * @return the monetary income of the planet
-	 */
 	public long getIncome( )
 	{
-		return this.income;
+		return income;
 	}
 
 
-	/**
-	 * Sets the monetary income of the planet.
-	 * 
-	 * @param income
-	 *            the new monetary income of the planet
-	 */
 	public void setIncome( long income )
 	{
 		this.income = income;
 	}
 
 
-	/**
-	 * Gets the monetary upkeep of the planet.
-	 * 
-	 * @return the monetary upkeep of the planet
-	 */
 	public long getUpkeep( )
 	{
-		return this.upkeep;
+		return upkeep;
 	}
 
 
-	/**
-	 * Sets the monetary upkeep of the planet.
-	 * 
-	 * @param upkeep
-	 *            the new monetary upkeep of the planet
-	 */
 	public void setUpkeep( long upkeep )
 	{
 		this.upkeep = upkeep;
 	}
 
 
-	/**
-	 * Gets the current military production.
-	 * 
-	 * @return the current military production
-	 */
 	public long getMilitaryProduction( )
 	{
-		return this.militaryProduction;
+		return militaryProduction;
 	}
 
 
-	/**
-	 * Sets the current military production.
-	 * 
-	 * @param militaryProduction
-	 *            the new current military production
-	 */
 	public void setMilitaryProduction( long militaryProduction )
 	{
 		this.militaryProduction = militaryProduction;
 	}
 
 
-	/**
-	 * Gets the current industrial production.
-	 * 
-	 * @return the current industrial production
-	 */
 	public long getIndustrialProduction( )
 	{
-		return this.industrialProduction;
+		return industrialProduction;
 	}
 
 
-	/**
-	 * Sets the current industrial production.
-	 * 
-	 * @param industrialProduction
-	 *            the new current industrial production
-	 */
 	public void setIndustrialProduction( long industrialProduction )
 	{
 		this.industrialProduction = industrialProduction;
 	}
 
 
-	/**
-	 * Gets the current "extra population growth" production.
-	 * 
-	 * @return the current "extra population growth" production
-	 */
 	public long getGrowthProduction( )
 	{
-		return this.growthProduction;
+		return growthProduction;
 	}
 
 
-	/**
-	 * Sets the current "extra population growth" production.
-	 * 
-	 * @param growthProduction
-	 *            the new current "extra population growth" production
-	 */
 	public void setGrowthProduction( long growthProduction )
 	{
 		this.growthProduction = growthProduction;
 	}
 
 
-	/**
-	 * Gets the money invested in the civilian queue.
-	 * 
-	 * @return the money invested in the civilian queue
-	 */
 	public long getCivInvestment( )
 	{
-		return this.civInvestment;
+		return civInvestment;
 	}
 
 
-	/**
-	 * Sets the money invested in the civilian queue.
-	 * 
-	 * @param civInvestment
-	 *            the new money invested in the civilian queue
-	 */
 	public void setCivInvestment( long civInvestment )
 	{
 		this.civInvestment = civInvestment;
 	}
 
 
-	/**
-	 * Gets the amount of buildings in the civilian queue.
-	 * 
-	 * @return the amount of buildings in the civilian queue
-	 */
 	public int getCivAmount( )
 	{
-		return this.civAmount;
+		return civAmount;
 	}
 
 
-	/**
-	 * Sets the amount of buildings in the civilian queue.
-	 * 
-	 * @param civAmount
-	 *            the new amount of buildings in the civilian queue
-	 */
 	public void setCivAmount( int civAmount )
 	{
 		this.civAmount = civAmount;
 	}
 
 
-	/**
-	 * Checks whether the current operation on the civilian queue is a destruction.
-	 * 
-	 * @return <code>true</code> if the current operation on the civilian queue is a destruction
-	 */
 	public boolean isCivDestroy( )
 	{
-		return this.civDestroy;
+		return civDestroy;
 	}
 
 
-	/**
-	 * Sets whether the current operation on the civilian queue is a destruction.
-	 * 
-	 * @param civDestroy
-	 *            <code>true</code> if the current operation on the civilian queue is a destruction
-	 */
 	public void setCivDestroy( boolean civDestroy )
 	{
 		this.civDestroy = civDestroy;
 	}
 
 
-	/**
-	 * Gets the name of the buildings being destroyed or constructed.
-	 * 
-	 * @return the name of the buildings being destroyed or constructed
-	 */
 	public String getCivName( )
 	{
-		return this.civName;
+		return civName;
 	}
 
 
-	/**
-	 * Sets the name of the buildings being destroyed or constructed.
-	 * 
-	 * @param civName
-	 *            the new name of the buildings being destroyed or constructed
-	 */
 	public void setCivName( String civName )
 	{
 		this.civName = civName;
 	}
 
 
-	/**
-	 * Gets the money invested in the military build queue.
-	 * 
-	 * @return the money invested in the military build queue
-	 */
 	public long getMilInvestment( )
 	{
-		return this.milInvestment;
+		return milInvestment;
 	}
 
 
-	/**
-	 * Sets the money invested in the military build queue.
-	 * 
-	 * @param milInvestment
-	 *            the new money invested in the military build queue
-	 */
 	public void setMilInvestment( long milInvestment )
 	{
 		this.milInvestment = milInvestment;
 	}
 
 
-	/**
-	 * Gets the amount of ships in the civilian queue.
-	 * 
-	 * @return the amount of ships in the civilian queue
-	 */
 	public int getMilAmount( )
 	{
-		return this.milAmount;
+		return milAmount;
 	}
 
 
-	/**
-	 * Sets the amount of ships in the civilian queue.
-	 * 
-	 * @param milAmount
-	 *            the new amount of ships in the civilian queue
-	 */
 	public void setMilAmount( int milAmount )
 	{
 		this.milAmount = milAmount;
 	}
 
 
-	/**
-	 * Gets the name of the ships being constructed.
-	 * 
-	 * @return the name of the ships being constructed
-	 */
 	public String getMilName( )
 	{
-		return this.milName;
+		return milName;
 	}
 
 
-	/**
-	 * Sets the name of the ships being constructed.
-	 * 
-	 * @param milName
-	 *            the new name of the ships being constructed
-	 */
 	public void setMilName( String milName )
 	{
 		this.milName = milName;
 	}
 
 
-	/**
-	 * Gets the fleet power from turrets.
-	 * 
-	 * @return the fleet power from turrets
-	 */
 	public long getFpStatic( )
 	{
-		return this.fpStatic;
+		return fpStatic;
 	}
 
 
-	/**
-	 * Sets the fleet power from turrets.
-	 * 
-	 * @param fpStatic
-	 *            the new fleet power from turrets
-	 */
 	public void setFpStatic( long fpStatic )
 	{
 		this.fpStatic = fpStatic;
 	}
 
 
-	/**
-	 * Gets the power of the owner's fleets.
-	 * 
-	 * @return the power of the owner's fleets
-	 */
 	public long getFpOwn( )
 	{
-		return this.fpOwn;
+		return fpOwn;
 	}
 
 
-	/**
-	 * Sets the power of the owner's fleets.
-	 * 
-	 * @param fpOwn
-	 *            the new power of the owner's fleets
-	 */
 	public void setFpOwn( long fpOwn )
 	{
 		this.fpOwn = fpOwn;
 	}
 
 
-	/**
-	 * Gets the power of the friendly fleets.
-	 * 
-	 * @return the power of the friendly fleets
-	 */
 	public long getFpFriendly( )
 	{
-		return this.fpFriendly;
+		return fpFriendly;
 	}
 
 
-	/**
-	 * Sets the power of the friendly fleets.
-	 * 
-	 * @param fpFriendly
-	 *            the new power of the friendly fleets
-	 */
 	public void setFpFriendly( long fpFriendly )
 	{
 		this.fpFriendly = fpFriendly;
 	}
 
 
-	/**
-	 * Gets the power of the hostile fleets.
-	 * 
-	 * @return the power of the hostile fleets
-	 */
 	public long getFpHostile( )
 	{
-		return this.fpHostile;
+		return fpHostile;
 	}
 
 
-	/**
-	 * Sets the power of the hostile fleets.
-	 * 
-	 * @param fpHostile
-	 *            the new power of the hostile fleets
-	 */
 	public void setFpHostile( long fpHostile )
 	{
 		this.fpHostile = fpHostile;
 	}
 
 
-	/**
-	 * Gets the battle identifier or <code>null</code> if there is no battle.
-	 * 
-	 * @return the battle identifier or <code>null</code> if there is no battle
-	 */
 	public Long getBattle( )
 	{
-		return this.battle;
+		return battle;
 	}
 
 
-	/**
-	 * Sets the battle identifier.
-	 * 
-	 * @param battle
-	 *            the new battle identifier or <code>null</code> if there is no battle
-	 */
 	public void setBattle( Long battle )
 	{
 		this.battle = battle;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/PlanetListResourceRecord.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/PlanetListResourceRecord.java
deleted file mode 100644
index d1c16ac..0000000
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/PlanetListResourceRecord.java
+++ /dev/null
@@ -1,161 +0,0 @@
-package com.deepclone.lw.cmd.player.gdata;
-
-
-import java.io.Serializable;
-
-
-
-/**
- * A resource record for the planet list
- * 
- * <p>
- * This class is used by {@link PlanetListData} to carry information about resources for the planet
- * list page.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-public class PlanetListResourceRecord
-		implements Serializable
-
-{
-
-	/**
-	 * Serialisation version identifier
-	 * 
-	 * <ul>
-	 * <li>Introduced in B6M2 with ID 1
-	 * </ul>
-	 */
-	private static final long serialVersionUID = 1L;
-
-	/** The name of the resource */
-	private String name;
-
-	/** The income for that resource type */
-	private long income;
-
-	/** The upkeep for that resource type */
-	private long upkeep;
-
-	/** The amount of that resource invested into the civilian construction queue */
-	private long civInvestment;
-
-	/** The amount of that resource invested into the military construction queue */
-	private long milInvestment;
-
-
-	/**
-	 * Gets the name of the resource.
-	 * 
-	 * @return the name of the resource
-	 */
-	public String getName( )
-	{
-		return this.name;
-	}
-
-
-	/**
-	 * Sets the name of the resource.
-	 * 
-	 * @param name
-	 *            the new name of the resource
-	 */
-	public void setName( String name )
-	{
-		this.name = name;
-	}
-
-
-	/**
-	 * Gets the income for that resource type.
-	 * 
-	 * @return the income for that resource type
-	 */
-	public long getIncome( )
-	{
-		return this.income;
-	}
-
-
-	/**
-	 * Sets the income for that resource type.
-	 * 
-	 * @param income
-	 *            the new income for that resource type
-	 */
-	public void setIncome( long income )
-	{
-		this.income = income;
-	}
-
-
-	/**
-	 * Gets the upkeep for that resource type.
-	 * 
-	 * @return the upkeep for that resource type
-	 */
-	public long getUpkeep( )
-	{
-		return this.upkeep;
-	}
-
-
-	/**
-	 * Sets the upkeep for that resource type.
-	 * 
-	 * @param upkeep
-	 *            the new upkeep for that resource type
-	 */
-	public void setUpkeep( long upkeep )
-	{
-		this.upkeep = upkeep;
-	}
-
-
-	/**
-	 * Gets the amount of that resource invested into the civilian construction queue.
-	 * 
-	 * @return the amount of that resource invested into the civilian construction queue
-	 */
-	public long getCivInvestment( )
-	{
-		return this.civInvestment;
-	}
-
-
-	/**
-	 * Sets the amount of that resource invested into the civilian construction queue.
-	 * 
-	 * @param civInvestment
-	 *            the new amount of that resource invested into the civilian construction queue
-	 */
-	public void setCivInvestment( long civInvestment )
-	{
-		this.civInvestment = civInvestment;
-	}
-
-
-	/**
-	 * Gets the amount of that resource invested into the military construction queue.
-	 * 
-	 * @return the amount of that resource invested into the military construction queue
-	 */
-	public long getMilInvestment( )
-	{
-		return this.milInvestment;
-	}
-
-
-	/**
-	 * Sets the amount of that resource invested into the military construction queue.
-	 * 
-	 * @param milInvestment
-	 *            the new amount of that resource invested into the military construction queue
-	 */
-	public void setMilInvestment( long milInvestment )
-	{
-		this.milInvestment = milInvestment;
-	}
-
-}
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/PlanetReference.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/PlanetReference.java
index fb111b3..277ff4f 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/PlanetReference.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/PlanetReference.java
@@ -3,13 +3,15 @@ package com.deepclone.lw.cmd.player.gdata;
 
 import java.io.Serializable;
 
+import com.deepclone.lw.session.API;
+
 
 
 public class PlanetReference
 		implements Serializable
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final long identifier;
 	private final String name;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/ShortBattleView.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/ShortBattleView.java
index 111f17e..92ad295 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/ShortBattleView.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/ShortBattleView.java
@@ -3,13 +3,15 @@ package com.deepclone.lw.cmd.player.gdata;
 
 import java.io.Serializable;
 
+import com.deepclone.lw.session.API;
+
 
 
 public class ShortBattleView
 		implements Serializable
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private long id;
 	private long friendly;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/TimeCombo.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/TimeCombo.java
index 4f180d2..891da10 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/TimeCombo.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/TimeCombo.java
@@ -3,13 +3,15 @@ package com.deepclone.lw.cmd.player.gdata;
 
 import java.io.Serializable;
 
+import com.deepclone.lw.session.API;
+
 
 
 public class TimeCombo
 		implements Serializable
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private long ticks;
 	private GameTime gameTime;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/account/AccountData.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/account/AccountData.java
index 8b94e01..8027ffa 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/account/AccountData.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/account/AccountData.java
@@ -8,6 +8,7 @@ import java.util.List;
 
 import com.deepclone.lw.cmd.ext.ListLanguagesResponse;
 import com.deepclone.lw.cmd.player.gdata.GameTime;
+import com.deepclone.lw.session.API;
 
 
 
@@ -15,7 +16,7 @@ public class AccountData
 		implements Serializable
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private String address;
 	private int gameCredits;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/account/MailChangeData.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/account/MailChangeData.java
index 65957a1..f930ae4 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/account/MailChangeData.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/account/MailChangeData.java
@@ -4,13 +4,15 @@ package com.deepclone.lw.cmd.player.gdata.account;
 import java.io.Serializable;
 import java.sql.Timestamp;
 
+import com.deepclone.lw.session.API;
+
 
 
 public class MailChangeData
 		implements Serializable
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final Timestamp until;
 
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/account/PrefCategory.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/account/PrefCategory.java
index 6641104..0c4591b 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/account/PrefCategory.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/account/PrefCategory.java
@@ -5,13 +5,15 @@ import java.io.Serializable;
 import java.util.LinkedList;
 import java.util.List;
 
+import com.deepclone.lw.session.API;
+
 
 
 public class PrefCategory
 		implements Serializable
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private String name;
 	private List< PrefValue > preferences = new LinkedList< PrefValue >( );
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/account/PrefChoice.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/account/PrefChoice.java
index fe45669..54d9b83 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/account/PrefChoice.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/account/PrefChoice.java
@@ -3,12 +3,14 @@ package com.deepclone.lw.cmd.player.gdata.account;
 
 import java.io.Serializable;
 
+import com.deepclone.lw.session.API;
+
 
 
 public class PrefChoice
 		implements Serializable
 {
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private String value;
 	private String display;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/account/PrefValue.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/account/PrefValue.java
index 1ed93ed..a8b598a 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/account/PrefValue.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/account/PrefValue.java
@@ -4,13 +4,15 @@ package com.deepclone.lw.cmd.player.gdata.account;
 import java.io.Serializable;
 import java.util.List;
 
+import com.deepclone.lw.session.API;
+
 
 
 public class PrefValue
 		implements Serializable
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private String id;
 	private String name;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/alliance/AllianceCreationStatus.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/alliance/AllianceCreationStatus.java
index 241b5a3..19b52a2 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/alliance/AllianceCreationStatus.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/alliance/AllianceCreationStatus.java
@@ -4,6 +4,7 @@ package com.deepclone.lw.cmd.player.gdata.alliance;
 import java.io.Serializable;
 
 import com.deepclone.lw.cmd.ObjectNameError;
+import com.deepclone.lw.session.API;
 
 
 
@@ -11,7 +12,7 @@ public class AllianceCreationStatus
 		implements Serializable
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final String tag;
 	private final ObjectNameError tagError;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/alliance/AllianceData.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/alliance/AllianceData.java
index 08b670c..442e7ce 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/alliance/AllianceData.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/alliance/AllianceData.java
@@ -3,6 +3,8 @@ package com.deepclone.lw.cmd.player.gdata.alliance;
 
 import java.io.Serializable;
 
+import com.deepclone.lw.session.API;
+
 
 
 
@@ -10,7 +12,7 @@ public class AllianceData
 		implements Serializable
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final PublicAllianceInformation main;
 	private final AllianceMemberData member;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/alliance/AllianceLeaderData.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/alliance/AllianceLeaderData.java
index a5293df..fda58ba 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/alliance/AllianceLeaderData.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/alliance/AllianceLeaderData.java
@@ -5,6 +5,7 @@ import java.io.Serializable;
 import java.util.List;
 
 import com.deepclone.lw.cmd.player.gdata.NameIdPair;
+import com.deepclone.lw.session.API;
 
 
 
@@ -12,7 +13,7 @@ public class AllianceLeaderData
 		implements Serializable
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final List< NameIdPair > requests;
 
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/alliance/AllianceMemberData.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/alliance/AllianceMemberData.java
index 48f35a3..ac147a8 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/alliance/AllianceMemberData.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/alliance/AllianceMemberData.java
@@ -5,6 +5,7 @@ import java.io.Serializable;
 import java.util.List;
 
 import com.deepclone.lw.cmd.player.gdata.NameIdPair;
+import com.deepclone.lw.session.API;
 
 
 
@@ -12,7 +13,7 @@ public class AllianceMemberData
 		implements Serializable
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final List< NameIdPair > members;
 	private final List< AlliancePlanetData > planets;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/alliance/AlliancePlanetData.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/alliance/AlliancePlanetData.java
index a17aa8a..b0acb87 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/alliance/AlliancePlanetData.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/alliance/AlliancePlanetData.java
@@ -3,13 +3,15 @@ package com.deepclone.lw.cmd.player.gdata.alliance;
 
 import java.io.Serializable;
 
+import com.deepclone.lw.session.API;
+
 
 
 public class AlliancePlanetData
 		implements Serializable
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private int id;
 	private String name;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/alliance/PublicAllianceInformation.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/alliance/PublicAllianceInformation.java
index 76463c1..ebee786 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/alliance/PublicAllianceInformation.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/alliance/PublicAllianceInformation.java
@@ -3,13 +3,15 @@ package com.deepclone.lw.cmd.player.gdata.alliance;
 
 import java.io.Serializable;
 
+import com.deepclone.lw.session.API;
+
 
 
 public class PublicAllianceInformation
 		implements Serializable
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final int id;
 	private final String tag;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/battles/BattleDescription.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/battles/BattleDescription.java
index 22eed1e..80b8217 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/battles/BattleDescription.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/battles/BattleDescription.java
@@ -4,6 +4,7 @@ package com.deepclone.lw.cmd.player.gdata.battles;
 import java.io.Serializable;
 
 import com.deepclone.lw.cmd.player.gdata.NameIdPair;
+import com.deepclone.lw.session.API;
 
 
 
@@ -11,7 +12,7 @@ public class BattleDescription
 		implements Serializable
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private long id;
 	private NameIdPair location;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/battles/BattleDisplay.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/battles/BattleDisplay.java
index e6d94d0..4e1ea82 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/battles/BattleDisplay.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/battles/BattleDisplay.java
@@ -6,6 +6,7 @@ import java.util.LinkedList;
 import java.util.List;
 
 import com.deepclone.lw.cmd.player.gdata.TimeCombo;
+import com.deepclone.lw.session.API;
 
 
 
@@ -13,7 +14,7 @@ public class BattleDisplay
 		implements Serializable
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private TimeCombo current;
 	private TimeCombo previous;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/battles/BattleEvent.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/battles/BattleEvent.java
index 6e99a05..340be4b 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/battles/BattleEvent.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/battles/BattleEvent.java
@@ -5,13 +5,15 @@ import java.io.Serializable;
 import java.util.LinkedList;
 import java.util.List;
 
+import com.deepclone.lw.session.API;
+
 
 
 public class BattleEvent
 		implements Serializable
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private BattleEventType type;
 	private boolean planet;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/battles/BattleHistoryInterval.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/battles/BattleHistoryInterval.java
index 7c15e5e..c2f5be5 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/battles/BattleHistoryInterval.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/battles/BattleHistoryInterval.java
@@ -6,6 +6,7 @@ import java.util.LinkedList;
 import java.util.List;
 
 import com.deepclone.lw.cmd.player.gdata.TimeCombo;
+import com.deepclone.lw.session.API;
 
 
 
@@ -13,7 +14,7 @@ public class BattleHistoryInterval
 		implements Serializable
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private TimeCombo begin;
 	private boolean battleBegins;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/battles/BattleHistoryTick.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/battles/BattleHistoryTick.java
index 526de4f..12929fe 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/battles/BattleHistoryTick.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/battles/BattleHistoryTick.java
@@ -6,6 +6,7 @@ import java.util.LinkedList;
 import java.util.List;
 
 import com.deepclone.lw.cmd.player.gdata.TimeCombo;
+import com.deepclone.lw.session.API;
 
 
 
@@ -13,7 +14,7 @@ public class BattleHistoryTick
 		implements Serializable
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final TimeCombo time;
 	private final List< BattleEvent > events = new LinkedList< BattleEvent >( );
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/battles/BattleListEntry.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/battles/BattleListEntry.java
index aca40ad..fddda87 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/battles/BattleListEntry.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/battles/BattleListEntry.java
@@ -5,6 +5,7 @@ import java.io.Serializable;
 
 import com.deepclone.lw.cmd.player.gdata.NameIdPair;
 import com.deepclone.lw.cmd.player.gdata.TimeCombo;
+import com.deepclone.lw.session.API;
 
 
 
@@ -12,7 +13,7 @@ public class BattleListEntry
 		implements Serializable
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private long id;
 	private NameIdPair location;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/battles/BattlePlanetBuildings.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/battles/BattlePlanetBuildings.java
index d416dd1..2fc4cbe 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/battles/BattlePlanetBuildings.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/battles/BattlePlanetBuildings.java
@@ -2,6 +2,7 @@ package com.deepclone.lw.cmd.player.gdata.battles;
 
 
 import com.deepclone.lw.cmd.player.gdata.PlanetRelationType;
+import com.deepclone.lw.session.API;
 
 
 
@@ -9,7 +10,7 @@ public class BattlePlanetBuildings
 		extends BattleShipsList
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private PlanetRelationType relation;
 
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/battles/BattlePlayerShips.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/battles/BattlePlayerShips.java
index af042d8..66b2c38 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/battles/BattlePlayerShips.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/battles/BattlePlayerShips.java
@@ -2,6 +2,7 @@ package com.deepclone.lw.cmd.player.gdata.battles;
 
 
 import com.deepclone.lw.cmd.player.gdata.NameIdPair;
+import com.deepclone.lw.session.API;
 
 
 
@@ -9,7 +10,7 @@ public class BattlePlayerShips
 		extends BattleShipsList
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private NameIdPair player;
 
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/battles/BattleShipType.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/battles/BattleShipType.java
index 3133440..65d5129 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/battles/BattleShipType.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/battles/BattleShipType.java
@@ -3,13 +3,15 @@ package com.deepclone.lw.cmd.player.gdata.battles;
 
 import java.io.Serializable;
 
+import com.deepclone.lw.session.API;
+
 
 
 public class BattleShipType
 		implements Serializable , Comparable< BattleShipType >
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private String name;
 	private long cAmount;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/battles/BattleShipsList.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/battles/BattleShipsList.java
index 389771b..922d4c4 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/battles/BattleShipsList.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/battles/BattleShipsList.java
@@ -5,13 +5,15 @@ import java.io.Serializable;
 import java.util.LinkedList;
 import java.util.List;
 
+import com.deepclone.lw.session.API;
+
 
 
 public abstract class BattleShipsList
 		implements Serializable
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	protected List< BattleShipType > ships = new LinkedList< BattleShipType >( );
 	protected long cPower = 0;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/battles/BattleShipsView.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/battles/BattleShipsView.java
index d38d726..bd7f6f2 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/battles/BattleShipsView.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/battles/BattleShipsView.java
@@ -3,13 +3,15 @@ package com.deepclone.lw.cmd.player.gdata.battles;
 
 import java.io.Serializable;
 
+import com.deepclone.lw.session.API;
+
 
 
 public class BattleShipsView
 		implements Serializable
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final BattlePlayerShips own = new BattlePlayerShips( );
 	private final BattleSideShips friendly = new BattleSideShips( false );
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/battles/BattleSideShips.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/battles/BattleSideShips.java
index 6dca7ad..613069f 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/battles/BattleSideShips.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/battles/BattleSideShips.java
@@ -5,13 +5,15 @@ import java.util.Collections;
 import java.util.LinkedList;
 import java.util.List;
 
+import com.deepclone.lw.session.API;
+
 
 
 public class BattleSideShips
 		extends BattleShipsList
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final boolean hostile;
 	private final List< BattlePlayerShips > players = new LinkedList< BattlePlayerShips >( );
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/battles/BattleView.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/battles/BattleView.java
index c9fc728..31acef8 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/battles/BattleView.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/battles/BattleView.java
@@ -5,13 +5,15 @@ import java.io.Serializable;
 import java.util.LinkedList;
 import java.util.List;
 
+import com.deepclone.lw.session.API;
+
 
 
 public class BattleView
 		implements Serializable
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private BattleDescription description;
 	private BattleDisplay display;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/empire/EmpireResourceRecord.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/empire/EmpireResourceRecord.java
deleted file mode 100644
index 9a9bd64..0000000
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/empire/EmpireResourceRecord.java
+++ /dev/null
@@ -1,152 +0,0 @@
-package com.deepclone.lw.cmd.player.gdata.empire;
-
-
-import com.deepclone.lw.cmd.player.gdata.AbstractResourceRecord;
-
-
-
-/**
- * Resource economic record
- * 
- * <p>
- * This record describes a resource. It is used in the empire overview's economic information and
- * for mining settings.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- * 
- */
-public class EmpireResourceRecord
-		extends AbstractResourceRecord
-{
-
-	/**
-	 * The serialisation version identifier
-	 * 
-	 * <ul>
-	 * <li>Introduced in B6M2 with ID 1
-	 * </ul>
-	 */
-	private static final long serialVersionUID = 1L;
-
-	/** The income for this type of resource over 12h RT / 1 month GT */
-	private long income;
-
-	/** The planet upkeep for this type of resource over 12h RT / 1 month GT */
-	private long planetUpkeep;
-
-	/** The fleet upkeep for this type of resource over 12h RT / 1 month GT */
-	private long fleetUpkeep;
-
-	/** The amount of resources of this type possessed by the empire */
-	private long stockpiled;
-
-	/** The resource's mining priority, or <code>null</code> for basic resources */
-	private Integer miningPriority;
-
-
-	/** @return the income for this type of resource over a period of 12h RT / 1 month GT */
-	public long getIncome( )
-	{
-		return this.income;
-	}
-
-
-	/**
-	 * Set the income for this type of resource over a period of 12h RT / 1 month GT
-	 * 
-	 * @param income
-	 *            the income for this type of resource over a period of 12h RT / 1 month GT
-	 */
-	public void setIncome( long income )
-	{
-		this.income = income;
-	}
-
-
-	/** @return the upkeep for this type of resource over a period of 12h RT / 1 month GT on planets */
-	public long getPlanetUpkeep( )
-	{
-		return this.planetUpkeep;
-	}
-
-
-	/**
-	 * Set the upkeep for this type of resource over a period of 12h RT / 1 month GT on planets
-	 * 
-	 * @param planetUpkeep
-	 *            the upkeep for this type of resource over a period of 12h RT / 1 month GT on
-	 *            planets
-	 */
-	public void setPlanetUpkeep( long planetUpkeep )
-	{
-		this.planetUpkeep = planetUpkeep;
-	}
-
-
-	/** @return the upkeep for this type of resource over a period of 12h RT / 1 month GT on planets */
-	public long getFleetUpkeep( )
-	{
-		return this.fleetUpkeep;
-	}
-
-
-	/**
-	 * Set the fleet upkeep for this type of resource over a period of 12h RT / 1 month GT
-	 * 
-	 * @param fleetUpkeep
-	 *            the fleet upkeep for this type of resource over a period of 12h RT / 1 month GT
-	 */
-	public void setFleetUpkeep( long fleetUpkeep )
-	{
-		this.fleetUpkeep = fleetUpkeep;
-	}
-
-
-	/** @return the total upkeep (including both fleet and planet upkeep) */
-	public long getUpkeep( )
-	{
-		return this.fleetUpkeep + this.planetUpkeep;
-	}
-
-
-	/** @return the amount of resources of this type the empire possesses */
-	public long getStockpiled( )
-	{
-		return this.stockpiled;
-	}
-
-
-	/**
-	 * Set the amount of resources of this type the empire possesses
-	 * 
-	 * @param stockpiled
-	 *            the amount of resources of this type the empire possesses
-	 */
-	public void setStockpiled( long stockpiled )
-	{
-		this.stockpiled = stockpiled;
-	}
-
-
-	/**
-	 * @return the mining priority for this type of resource, or <code>null</code> if it is a basic
-	 *         resource
-	 */
-	public Integer getMiningPriority( )
-	{
-		return this.miningPriority;
-	}
-
-
-	/**
-	 * Set the mining priority for this type of resource
-	 * 
-	 * @param miningPriority
-	 *            the mining priority for this type of resource
-	 */
-	public void setMiningPriority( int miningPriority )
-	{
-		this.miningPriority = miningPriority;
-	}
-
-}
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/empire/OverviewData.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/empire/OverviewData.java
index 9858969..fabcfad 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/empire/OverviewData.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/empire/OverviewData.java
@@ -2,7 +2,8 @@ package com.deepclone.lw.cmd.player.gdata.empire;
 
 
 import java.io.Serializable;
-import java.util.List;
+
+import com.deepclone.lw.session.API;
 
 
 
@@ -10,234 +11,124 @@ public class OverviewData
 		implements Serializable
 {
 
-	/**
-	 * Serialisation version identifier
-	 * 
-	 * <ul>
-	 * <li>Introduced in B6M1 with ID 1
-	 * <li>Modified in B6M2, ID set to 2
-	 * </ul>
-	 */
-	private static final long serialVersionUID = 2L;
+	private static final long serialVersionUID = API.Version;
 
-	/** Quantity of planets owned by the empire */
 	private long planets;
-
-	/** Amount of unread messages */
 	private int newMessages;
-
-	/** Total population in the empire */
 	private long population;
-
-	/** Average happiness of the population on the planets, as a percentage */
 	private int avgHappiness;
-
-	/** Total fleet power */
 	private long fleetPower;
-
-	/** Total monetary income from planets */
 	private long planetIncome;
-
-	/** Total monetary upkeep for planets */
 	private long planetUpkeep;
-
-	/** Total monetary fleet upkeep */
 	private long fleetUpkeep;
-
-	/** Total amount of money in the various queues */
 	private long investment;
 
-	/** Economic information */
-	private List< EmpireResourceRecord > economy;
 
-
-	/** @return the quantity of planets owned by the empire */
 	public long getPlanets( )
 	{
-		return this.planets;
+		return planets;
 	}
 
 
-	/**
-	 * Set the quantity of planets owned by the empire
-	 * 
-	 * @param planets
-	 *            the quantity of planets owned by the empire
-	 */
 	public void setPlanets( long planets )
 	{
 		this.planets = planets;
 	}
 
 
-	/** @return the quantity of unread messages */
 	public int getNewMessages( )
 	{
-		return this.newMessages;
+		return newMessages;
 	}
 
 
-	/**
-	 * Set the quantity of unread messages
-	 * 
-	 * @param newMessages
-	 *            the quantity of unread messages
-	 */
 	public void setNewMessages( int newMessages )
 	{
 		this.newMessages = newMessages;
 	}
 
 
-	/** @return the empire's total population */
 	public long getPopulation( )
 	{
-		return this.population;
+		return population;
 	}
 
 
-	/**
-	 * Set the empire's total population
-	 * 
-	 * @param population
-	 *            the empire's total population
-	 */
 	public void setPopulation( long population )
 	{
 		this.population = population;
 	}
 
 
-	/** @return the average happiness on the empire's planets */
 	public int getAvgHappiness( )
 	{
-		return this.avgHappiness;
+		return avgHappiness;
 	}
 
 
-	/**
-	 * Set the average happiness on the empire's planets
-	 * 
-	 * @param avgHappiness
-	 *            the average happiness on the empire's planets
-	 */
 	public void setAvgHappiness( int avgHappiness )
 	{
 		this.avgHappiness = avgHappiness;
 	}
 
 
-	/** @return the total fleet power */
 	public long getFleetPower( )
 	{
-		return this.fleetPower;
+		return fleetPower;
 	}
 
 
-	/**
-	 * Set the total fleet power
-	 * 
-	 * @param fleetPower
-	 *            the total fleet power
-	 */
 	public void setFleetPower( long fleetPower )
 	{
 		this.fleetPower = fleetPower;
 	}
 
 
-	/** @return the monetary income from the empire's planets */
 	public long getPlanetIncome( )
 	{
-		return this.planetIncome;
+		return planetIncome;
 	}
 
 
-	/**
-	 * Set the monetary income from the empire's planets
-	 * 
-	 * @param planetIncome
-	 *            the monetary income from the empire's planets
-	 */
 	public void setPlanetIncome( long planetIncome )
 	{
 		this.planetIncome = planetIncome;
 	}
 
 
-	/** @return the monetary upkeep for the empire's planets */
 	public long getPlanetUpkeep( )
 	{
-		return this.planetUpkeep;
+		return planetUpkeep;
 	}
 
 
-	/**
-	 * Set the monetary upkeep for the empire's planets
-	 * 
-	 * @param planetUpkeep
-	 *            the monetary upkeep for the empire's planets
-	 */
 	public void setPlanetUpkeep( long planetUpkeep )
 	{
 		this.planetUpkeep = planetUpkeep;
 	}
 
 
-	/** @return the monetary upkeep for the empire's fleets */
 	public long getFleetUpkeep( )
 	{
-		return this.fleetUpkeep;
+		return fleetUpkeep;
 	}
 
 
-	/**
-	 * Set the monetary upkeep for the empire's fleets
-	 * 
-	 * @param fleetUpkeep
-	 *            the monetary upkeep for the empire's fleets
-	 */
 	public void setFleetUpkeep( long fleetUpkeep )
 	{
 		this.fleetUpkeep = fleetUpkeep;
 	}
 
 
-	/** @return the total amount of money invested in civilian or military queues */
 	public long getInvestment( )
 	{
-		return this.investment;
+		return investment;
 	}
 
 
-	/**
-	 * Set the total amount of money invested in civilian or military queues
-	 * 
-	 * @param investment
-	 *            the total amount of money invested in civilian or military queues
-	 */
 	public void setInvestment( long investment )
 	{
 		this.investment = investment;
 	}
 
-
-	/** @return the list of economic information records */
-	public List< EmpireResourceRecord > getEconomy( )
-	{
-		return this.economy;
-	}
-
-
-	/**
-	 * Set the list of economic information records
-	 * 
-	 * @param economy
-	 *            the list of economic information records
-	 */
-	public void setEconomy( List< EmpireResourceRecord > economy )
-	{
-		this.economy = economy;
-	}
-
 }
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/empire/ResearchData.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/empire/ResearchData.java
index a6f63d0..5af296b 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/empire/ResearchData.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/empire/ResearchData.java
@@ -2,410 +2,223 @@ package com.deepclone.lw.cmd.player.gdata.empire;
 
 
 import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.LinkedList;
-import java.util.List;
+
+import com.deepclone.lw.session.API;
 
 
 
-/**
- * An entry from the research page
- * 
- * <p>
- * This class represents entries from the research page. It is capable of representing in-progress
- * research (with or without details), as well as pending and implemented technologies.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
 public class ResearchData
 		implements Serializable , Comparable< ResearchData >
 {
 
-	/**
-	 * The serialisation version identifier
-	 * 
-	 * <ul>
-	 * <li>Introduced in B6M2 with ID 1
-	 * </ul>
-	 */
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
-	/** The identifier of the technology */
-	private String identifier;
+	private final String identifier;
+
+	private int completion;
 
-	/** The category the technology belongs to */
 	private String category;
-
-	/**
-	 * The translated name of the technology, or <code>null</code> if the technology is being
-	 * researched and progress is insufficient to display details.
-	 */
 	private String name;
-
-	/**
-	 * The description of the technology, or <code>null</code> if the technology is being researched
-	 * and progress is insufficient to display details.
-	 */
 	private String description;
 
-	/**
-	 * The implementation price of the technology, or <code>null</code> if the technology is being
-	 * researched and progress is insufficient to display details.
-	 */
-	private Long price;
-
-	/**
-	 * The completion percentage of the technology, or <code>null</code> if the technology has been
-	 * fully researched.
-	 */
-	private Integer completion;
-
-	/**
-	 * Priority of the research on this technology, or <code>null</code> if the technology is not
-	 * being researched.
-	 */
 	private Integer priority;
+	private Integer cost;
 
-	/**
-	 * Whether the technology is being researched (<code>null</code>), pending implementation (
-	 * <code>false</code>) or implemented (<code>true</code>).
-	 */
-	private Boolean implemented;
-
-	/** List of identifiers of technologies the current technology depends on. */
-	private List< String > dependencies = new ArrayList< String >( );
-
-	/** List of identifiers of technologies that depend on the current technology. */
-	private final List< String > revDependencies = new LinkedList< String >( );
-
-	/** List of buildings the current technology unlocks. */
-	private List< String > buildings = new ArrayList< String >( );
+	private String[] dependsOn;
 
 
 	/**
-	 * Gets the identifier of the technology.
+	 * Create a research data record for a technology that hasn't been identified yet.
 	 * 
-	 * @return the identifier of the technology
+	 * @param numericId
+	 *            numeric identifier of the technology
+	 * @param category
+	 *            name of the category the technology belongs to
+	 * @param completion
+	 *            completion percentage
+	 * @param priority
+	 *            research priority
 	 */
-	public String getIdentifier( )
+	public ResearchData( int numericId , String category , int completion , int priority )
 	{
-		return this.identifier;
+		this.identifier = "unknown-" + numericId;
+		this.completion = completion;
+		this.priority = priority;
+		this.category = category;
+		this.name = null;
+		this.description = null;
+		this.cost = null;
+		this.dependsOn = null;
 	}
 
 
 	/**
-	 * Sets the identifier of the technology.
+	 * Create a research data record for an identified technology that is still being researched.
 	 * 
 	 * @param identifier
-	 *            the new identifier of the technology
+	 *            technology identifier
+	 * @param category
+	 *            name of the category the technology belongs to
+	 * @param name
+	 *            name of the technology
+	 * @param description
+	 *            description of the technology
+	 * @param dependsOn
+	 *            identifiers of the technologies this technology depends on
+	 * @param completion
+	 *            completion percentage
+	 * @param priority
+	 *            research priority
 	 */
-	public void setIdentifier( String identifier )
+	public ResearchData( String identifier , String category , String name , String description , String[] dependsOn ,
+			int completion , int priority )
 	{
 		this.identifier = identifier;
+		this.category = category;
+		this.name = name;
+		this.description = description;
+		this.dependsOn = dependsOn.clone( );
+		this.completion = completion;
+		this.priority = priority;
+		this.cost = null;
 	}
 
 
 	/**
-	 * Gets the category the technology belongs to.
+	 * Create a research data record for a technology that needs to be implemented.
 	 * 
-	 * @return the category the technology belongs to
+	 * @param identifier
+	 *            technology identifier
+	 * @param category
+	 *            name of the category the technology belongs to
+	 * @param name
+	 *            name of the technology
+	 * @param description
+	 *            description of the technology
+	 * @param dependsOn
+	 *            identifiers of the technologies this technology depends on
+	 * @param cost
+	 *            research priority
 	 */
+	public ResearchData( String identifier , String category , String name , String description , String[] dependsOn ,
+			int cost )
+	{
+		this.identifier = identifier;
+		this.category = category;
+		this.name = name;
+		this.description = description;
+		this.dependsOn = dependsOn.clone( );
+		this.completion = 100;
+		this.priority = null;
+		this.cost = cost;
+	}
+
+
+	@Override
+	public int compareTo( ResearchData o )
+	{
+		if ( this.cost != null && o.cost == null ) {
+			return -1;
+		} else if ( this.cost == null && o.cost != null ) {
+			return 1;
+		} else if ( this.name != null && o.name != null ) {
+			return this.name.compareTo( o.name );
+		} else if ( this.name != null ) {
+			return -1;
+		} else if ( o.name != null ) {
+			return 1;
+		}
+		return this.identifier.compareTo( o.identifier );
+	}
+
+
+	public int getCompletion( )
+	{
+		return completion;
+	}
+
+
+	public void setCompletion( int completion )
+	{
+		this.completion = completion;
+	}
+
+
 	public String getCategory( )
 	{
-		return this.category;
+		return category;
 	}
 
 
-	/**
-	 * Sets the category the technology belongs to.
-	 * 
-	 * @param category
-	 *            the new category the technology belongs to
-	 */
 	public void setCategory( String category )
 	{
 		this.category = category;
 	}
 
 
-	/**
-	 * Gets the translated name of the technology
-	 * 
-	 * @return the translated name of the technology, or <code>null</code> if the technology is
-	 *         being researched and progress is insufficient to display details
-	 */
 	public String getName( )
 	{
-		return this.name;
+		return name;
 	}
 
 
-	/**
-	 * Sets the translated name of the technology
-	 * 
-	 * @param name
-	 *            the new translated name of the technology
-	 */
 	public void setName( String name )
 	{
 		this.name = name;
 	}
 
 
-	/**
-	 * Gets the description of the technology
-	 * 
-	 * @return the description of the technology, or <code>null</code> if the technology is being
-	 *         researched and progress is insufficient to display details
-	 */
 	public String getDescription( )
 	{
-		return this.description;
+		return description;
 	}
 
 
-	/**
-	 * Sets the description of the technology
-	 * 
-	 * @param description
-	 *            the new description of the technology
-	 */
 	public void setDescription( String description )
 	{
 		this.description = description;
 	}
 
 
-	/**
-	 * Gets the implementation price of the technology
-	 * 
-	 * @return the implementation price of the technology, or <code>null</code> if the technology is
-	 *         being researched and progress is insufficient to display details
-	 */
-	public Long getPrice( )
-	{
-		return this.price;
-	}
-
-
-	/**
-	 * Sets the implementation price of the technology
-	 * 
-	 * @param price
-	 *            the new implementation price of the technology
-	 */
-	public void setPrice( Long price )
-	{
-		this.price = price;
-	}
-
-
-	/**
-	 * Gets the completion percentage of the technology.
-	 * 
-	 * @return the completion percentage of the technology, or <code>null</code> if the technology
-	 *         has been fully researched
-	 */
-	public Integer getCompletion( )
-	{
-		return this.completion;
-	}
-
-
-	/**
-	 * Sets the completion percentage of the technology.
-	 * 
-	 * @param completion
-	 *            the new completion percentage of the technology
-	 */
-	public void setCompletion( Integer completion )
-	{
-		this.completion = completion;
-	}
-
-
-	/**
-	 * Gets the priority of the research on this technology
-	 * 
-	 * @return the priority of the research on this technology, or <code>null</code> if the
-	 *         technology is not being researched
-	 */
 	public Integer getPriority( )
 	{
-		return this.priority;
+		return priority;
 	}
 
 
-	/**
-	 * Sets the priority of the research on this technology.
-	 * 
-	 * @param priority
-	 *            the new priority of the research on this technology
-	 */
 	public void setPriority( Integer priority )
 	{
 		this.priority = priority;
 	}
 
 
-	/**
-	 * Gets whether the technology is being researched (<code>null</code>), pending implementation (
-	 * <code>false</code>) or implemented (<code>true</code>).
-	 * 
-	 * @return whether the technology is being researched (<code>null</code>), pending
-	 *         implementation ( <code>false</code>) or implemented (<code>true</code>)
-	 */
-	public Boolean getImplemented( )
+	public Integer getCost( )
 	{
-		return this.implemented;
+		return cost;
 	}
 
 
-	/**
-	 * Sets whether the technology is being researched (<code>null</code>), pending implementation (
-	 * <code>false</code>) or implemented (<code>true</code>).
-	 * 
-	 * @param implemented
-	 *            whether the technology is being researched (<code>null</code>), pending
-	 *            implementation ( <code>false</code>) or implemented (<code>true</code>)
-	 */
-	public void setImplemented( Boolean implemented )
+	public void setCost( Integer cost )
 	{
-		this.implemented = implemented;
+		this.cost = cost;
 	}
 
 
-	/**
-	 * Get the list of dependencies
-	 * 
-	 * @return the list of dependencies
-	 */
-	public List< String > getDependencies( )
+	public String[] getDependsOn( )
 	{
-		return Collections.unmodifiableList( this.dependencies );
+		return dependsOn;
 	}
 
 
-	/**
-	 * Update the list of dependencies
-	 * 
-	 * @param dependencies
-	 *            the new list of dependencies
-	 */
-	public void setDependencies( String[] dependencies )
+	public void setDependsOn( String[] dependsOn )
 	{
-		this.dependencies = Arrays.asList( dependencies );
+		this.dependsOn = dependsOn;
 	}
 
 
-	/**
-	 * Get the list of reverse dependencies
-	 * 
-	 * @return the list of reverse dependencies
-	 */
-	public List< String > getReverseDependencies( )
+	public String getIdentifier( )
 	{
-		return this.revDependencies;
-	}
-
-
-	/**
-	 * Add a reverse dependency
-	 * 
-	 * @param identifier
-	 *            the identifier of the reverse dependency
-	 */
-	public void addReverseDependency( String identifier )
-	{
-		this.revDependencies.add( identifier );
-	}
-
-
-	/**
-	 * Update the list of unlocked buildings
-	 * 
-	 * @param buildings
-	 *            the new list of buildings
-	 */
-	public void setBuildings( String[] buildings )
-	{
-		this.buildings = Arrays.asList( buildings );
-	}
-
-
-	/**
-	 * Update the list of unlocked buildings
-	 * 
-	 * @param buildings
-	 *            the new list of buildings
-	 */
-	public void setBuildings( List< String > buildings )
-	{
-		this.buildings = buildings;
-	}
-
-
-	/**
-	 * Gets the list of buildings the current technology unlocks.
-	 * 
-	 * @return the list of buildings the current technology unlocks
-	 */
-	public List< String > getBuildings( )
-	{
-		return this.buildings;
-	}
-
-
-	/**
-	 * Research page entry comparison
-	 * 
-	 * <p>
-	 * This method compares research entries based on:
-	 * <ul>
-	 * <li>The entries' states (in progress, pending implementation, implemented),
-	 * <li>For in-progress entries, their current completion ratio,
-	 * <li>The entries' names
-	 * </ul>
-	 * 
-	 * @param other
-	 *            the entry to compare to
-	 * 
-	 * @return 1 if the current entry is "bigger", -1 if it is "smaller", and 0 if both entries are
-	 *         equal
-	 */
-	@Override
-	public int compareTo( ResearchData other )
-	{
-		if ( other == null ) {
-			return 1;
-		}
-
-		if ( this.implemented == null && other.implemented != null ) {
-			return -1;
-		}
-		if ( other.implemented == null && this.implemented != null ) {
-			return 1;
-		}
-
-		if ( this.implemented != null ) {
-			if ( this.implemented && !other.implemented ) {
-				return 1;
-			}
-			if ( other.implemented && !this.implemented ) {
-				return -1;
-			}
-			return this.name.compareTo( other.name );
-		}
-
-		if ( this.completion != other.completion ) {
-			return other.completion - this.completion;
-		}
-		if ( this.name == null ) {
-			return other.name == null ? 0 : -1;
-		}
-		return this.name.compareTo( other.name );
+		return identifier;
 	}
 
 }
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/empire/TechnologyCategoryData.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/empire/TechnologyCategoryData.java
new file mode 100644
index 0000000..67d3dc1
--- /dev/null
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/empire/TechnologyCategoryData.java
@@ -0,0 +1,55 @@
+package com.deepclone.lw.cmd.player.gdata.empire;
+
+
+import java.io.Serializable;
+import java.util.LinkedList;
+import java.util.List;
+
+import com.deepclone.lw.session.API;
+
+
+
+public class TechnologyCategoryData
+		implements Serializable , Comparable< TechnologyCategoryData >
+{
+
+	private static final long serialVersionUID = API.Version;
+
+	private final String name;
+	private final String description;
+	private final List< TechnologyData > technologies;
+
+
+	public TechnologyCategoryData( String name , String description , List< TechnologyData > technologies )
+	{
+		this.name = name;
+		this.description = description;
+		this.technologies = new LinkedList< TechnologyData >( technologies );
+	}
+
+
+	public String getName( )
+	{
+		return this.name;
+	}
+
+
+	public String getDescription( )
+	{
+		return this.description;
+	}
+
+
+	public List< TechnologyData > getTechnologies( )
+	{
+		return this.technologies;
+	}
+
+
+	@Override
+	public int compareTo( TechnologyCategoryData o )
+	{
+		return this.name.compareTo( o.name );
+	}
+
+}
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/empire/TechnologyData.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/empire/TechnologyData.java
new file mode 100644
index 0000000..a598f72
--- /dev/null
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/empire/TechnologyData.java
@@ -0,0 +1,72 @@
+package com.deepclone.lw.cmd.player.gdata.empire;
+
+
+import java.io.Serializable;
+import java.util.List;
+
+import com.deepclone.lw.session.API;
+
+
+
+public class TechnologyData
+		implements Serializable , Comparable< TechnologyData >
+{
+
+	private static final long serialVersionUID = API.Version;
+
+	private final String identifier;
+	private final String name;
+	private final String description;
+
+	private final List< String > dependsOn;
+	private final List< String > dependencyOf;
+
+
+	public TechnologyData( String identifier , String name , String description , List< String > dependsOn ,
+			List< String > dependencyOf )
+	{
+		this.identifier = identifier;
+		this.name = name;
+		this.description = description;
+		this.dependsOn = dependsOn;
+		this.dependencyOf = dependencyOf;
+	}
+
+
+	public String getIdentifier( )
+	{
+		return this.identifier;
+	}
+
+
+	public String getName( )
+	{
+		return this.name;
+	}
+
+
+	public String getDescription( )
+	{
+		return this.description;
+	}
+
+
+	public List< String > getDependsOn( )
+	{
+		return this.dependsOn;
+	}
+
+
+	public List< String > getDependencyOf( )
+	{
+		return this.dependencyOf;
+	}
+
+
+	@Override
+	public int compareTo( TechnologyData o )
+	{
+		return this.name.compareTo( o.name );
+	}
+
+}
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/fleets/FleetLocation.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/fleets/FleetLocation.java
index 464936b..b3e259b 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/fleets/FleetLocation.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/fleets/FleetLocation.java
@@ -6,6 +6,7 @@ import java.util.List;
 
 import com.deepclone.lw.cmd.player.gdata.NameIdPair;
 import com.deepclone.lw.cmd.player.gdata.ShortBattleView;
+import com.deepclone.lw.session.API;
 
 
 
@@ -13,7 +14,7 @@ public class FleetLocation
 		extends NameIdPair
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private boolean own;
 	private boolean attacking;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/fleets/FleetOwner.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/fleets/FleetOwner.java
index 2653142..d88bfed 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/fleets/FleetOwner.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/fleets/FleetOwner.java
@@ -6,6 +6,7 @@ import java.util.List;
 
 import com.deepclone.lw.cmd.player.gdata.NameIdPair;
 import com.deepclone.lw.cmd.player.gdata.PlanetRelationType;
+import com.deepclone.lw.session.API;
 
 
 
@@ -15,7 +16,7 @@ public class FleetOwner
 		extends NameIdPair
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final PlanetRelationType relation;
 	private final List< StaticFleet > fleets = new LinkedList< StaticFleet >( );
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/fleets/FleetShips.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/fleets/FleetShips.java
index a29a8a6..074a691 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/fleets/FleetShips.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/fleets/FleetShips.java
@@ -3,13 +3,15 @@ package com.deepclone.lw.cmd.player.gdata.fleets;
 
 import java.io.Serializable;
 
+import com.deepclone.lw.session.API;
+
 
 
 public class FleetShips
 		implements Serializable
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private int type;
 	private String name;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/fleets/FleetsView.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/fleets/FleetsView.java
index dc16fe4..3fbeed6 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/fleets/FleetsView.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/fleets/FleetsView.java
@@ -5,13 +5,15 @@ import java.io.Serializable;
 import java.util.LinkedList;
 import java.util.List;
 
+import com.deepclone.lw.session.API;
+
 
 
 public class FleetsView
 		implements Serializable
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final List< FleetLocation > locations = new LinkedList< FleetLocation >( );
 	private final List< MovingFleet > moving = new LinkedList< MovingFleet >( );
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/fleets/MovingFleet.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/fleets/MovingFleet.java
index e37a38f..3bc0311 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/fleets/MovingFleet.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/fleets/MovingFleet.java
@@ -3,6 +3,7 @@ package com.deepclone.lw.cmd.player.gdata.fleets;
 
 import com.deepclone.lw.cmd.player.gdata.GameTime;
 import com.deepclone.lw.cmd.player.gdata.NameIdPair;
+import com.deepclone.lw.session.API;
 
 
 
@@ -10,7 +11,7 @@ public class MovingFleet
 		extends StaticFleet
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private long timeLeft;
 	private boolean attacking;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/fleets/ShortFleetView.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/fleets/ShortFleetView.java
index a19833a..4f273bd 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/fleets/ShortFleetView.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/fleets/ShortFleetView.java
@@ -3,6 +3,7 @@ package com.deepclone.lw.cmd.player.gdata.fleets;
 
 import com.deepclone.lw.cmd.player.gdata.GameTime;
 import com.deepclone.lw.cmd.player.gdata.NameIdPair;
+import com.deepclone.lw.session.API;
 
 
 
@@ -10,7 +11,7 @@ public class ShortFleetView
 		extends NameIdPair
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private int flightTime;
 	private GameTime gameFlightTime;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/fleets/SplitShips.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/fleets/SplitShips.java
index b464387..f36a872 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/fleets/SplitShips.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/fleets/SplitShips.java
@@ -1,11 +1,13 @@
 package com.deepclone.lw.cmd.player.gdata.fleets;
 
+import com.deepclone.lw.session.API;
+
 
 public class SplitShips
 		extends FleetShips
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private int id;
 	private int selectedAmount = 0;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/fleets/StaticFleet.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/fleets/StaticFleet.java
index 32d9ac9..d07362d 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/fleets/StaticFleet.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/fleets/StaticFleet.java
@@ -6,6 +6,7 @@ import java.util.List;
 
 import com.deepclone.lw.cmd.player.gdata.GameTime;
 import com.deepclone.lw.cmd.player.gdata.NameIdPair;
+import com.deepclone.lw.session.API;
 
 
 
@@ -13,7 +14,7 @@ public class StaticFleet
 		extends NameIdPair
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private FleetStatus status;
 	private long penalty;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/map/MapPlanetData.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/map/MapPlanetData.java
index 8a04d19..783db11 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/map/MapPlanetData.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/map/MapPlanetData.java
@@ -4,6 +4,7 @@ package com.deepclone.lw.cmd.player.gdata.map;
 import java.io.Serializable;
 
 import com.deepclone.lw.cmd.player.gdata.PlanetRelationType;
+import com.deepclone.lw.session.API;
 
 
 
@@ -11,7 +12,7 @@ public class MapPlanetData
 		implements Serializable
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final long id;
 	private final int picture;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/map/MapSystemData.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/map/MapSystemData.java
index db7a54a..c9c9f7d 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/map/MapSystemData.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/map/MapSystemData.java
@@ -3,13 +3,15 @@ package com.deepclone.lw.cmd.player.gdata.map;
 
 import java.io.Serializable;
 
+import com.deepclone.lw.session.API;
+
 
 
 public class MapSystemData
 		implements Serializable
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final MapPlanetData planets[] = new MapPlanetData[ 5 ];
 
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/planets/BuildableBuildingData.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/planets/BuildableBuildingData.java
index 34c5ce6..25ce6f7 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/planets/BuildableBuildingData.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/planets/BuildableBuildingData.java
@@ -1,11 +1,13 @@
 package com.deepclone.lw.cmd.player.gdata.planets;
 
+import com.deepclone.lw.session.API;
+
 
 public class BuildableBuildingData
 		extends BuildableItemData
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private int workers;
 	private String prodType;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/planets/BuildableItemData.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/planets/BuildableItemData.java
index 5ae878e..32ab59d 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/planets/BuildableItemData.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/planets/BuildableItemData.java
@@ -4,6 +4,7 @@ package com.deepclone.lw.cmd.player.gdata.planets;
 import java.io.Serializable;
 
 import com.deepclone.lw.cmd.player.gdata.GameTime;
+import com.deepclone.lw.session.API;
 
 
 
@@ -11,7 +12,7 @@ public abstract class BuildableItemData
 		implements Serializable
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private int id;
 	private String name;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/planets/BuildableShipData.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/planets/BuildableShipData.java
index 99c6d5b..6277e0f 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/planets/BuildableShipData.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/planets/BuildableShipData.java
@@ -1,13 +1,14 @@
 package com.deepclone.lw.cmd.player.gdata.planets;
 
 import com.deepclone.lw.cmd.player.gdata.GameTime;
+import com.deepclone.lw.session.API;
 
 
 public class BuildableShipData
 		extends BuildableItemData
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private int power;
 	private int flightTime;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/planets/BuildingData.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/planets/BuildingData.java
index 7647c24..c62df08 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/planets/BuildingData.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/planets/BuildingData.java
@@ -3,13 +3,15 @@ package com.deepclone.lw.cmd.player.gdata.planets;
 
 import java.io.Serializable;
 
+import com.deepclone.lw.session.API;
+
 
 
 public class BuildingData
 		implements Serializable
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private Integer id;
 	private String name;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/planets/OwnPlanetStatusData.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/planets/OwnPlanetStatusData.java
index 6013826..34bc000 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/planets/OwnPlanetStatusData.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/planets/OwnPlanetStatusData.java
@@ -4,6 +4,7 @@ package com.deepclone.lw.cmd.player.gdata.planets;
 import java.io.Serializable;
 
 import com.deepclone.lw.cmd.player.gdata.GameTime;
+import com.deepclone.lw.session.API;
 
 
 
@@ -11,7 +12,7 @@ public class OwnPlanetStatusData
 		implements Serializable
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private boolean abandonPossible;
 	private boolean renamePossible;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/planets/PlanetBasicView.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/planets/PlanetBasicView.java
index 31de86e..2e9adb4 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/planets/PlanetBasicView.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/planets/PlanetBasicView.java
@@ -3,13 +3,15 @@ package com.deepclone.lw.cmd.player.gdata.planets;
 
 import java.io.Serializable;
 
+import com.deepclone.lw.session.API;
+
 
 
 public class PlanetBasicView
 		implements Serializable
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final String name;
 	private final int picture;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/planets/PlanetOrbitalView.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/planets/PlanetOrbitalView.java
index 5992b9c..fc48a1d 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/planets/PlanetOrbitalView.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/planets/PlanetOrbitalView.java
@@ -4,13 +4,15 @@ package com.deepclone.lw.cmd.player.gdata.planets;
 import java.io.Serializable;
 import java.util.List;
 
+import com.deepclone.lw.session.API;
+
 
 
 public class PlanetOrbitalView
 		implements Serializable
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private long population;
 	private long defencePoints;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/planets/PlanetOwnView.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/planets/PlanetOwnView.java
index 9dfc71f..b61f708 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/planets/PlanetOwnView.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/planets/PlanetOwnView.java
@@ -4,285 +4,132 @@ package com.deepclone.lw.cmd.player.gdata.planets;
 import java.io.Serializable;
 import java.util.List;
 
+import com.deepclone.lw.session.API;
+
 
 
-/**
- * Planet view details available to planet owners
- * 
- * <p>
- * This class carries the part of the planet view which is only available to empires owning the
- * planet being viewed.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
 public class PlanetOwnView
 		implements Serializable
 {
 
-	/**
-	 * Serialisation version identifier
-	 * 
-	 * <ul>
-	 * <li>Introduced in B6M1 with ID 1
-	 * <li>Modified in B6M2, ID set to 2
-	 * </ul>
-	 */
-	private static final long serialVersionUID = 2L;
+	private static final long serialVersionUID = API.Version;
 
-	/** Happiness of the planet's population as a percentage */
 	private int happiness;
-
-	/**
-	 * Happiness change indicator
-	 * 
-	 * <p>
-	 * This field's value is an integer between -2 and 2 (inclusive). It indicates the direction of
-	 * the happiness' change (positive meaning that the happiness is increasing, negative meaning it
-	 * is decreasing), and the strength of the change (absolute value 1 meaning a relatively small
-	 * change, 2 a bigger one)
-	 */
 	private int hChange;
-
-	/** Planet monetary income for 24h of RL time */
 	private long income;
-
-	/** Planet monetary upkeep for 24h of RL time */
 	private long upkeep;
-
-	/**
-	 * Various planet state indicators
-	 * 
-	 * <p>
-	 * This field carries a few flags about whether it is possible to rename or abandon the planet,
-	 * and similar information.
-	 */
 	private OwnPlanetStatusData status;
-
-	/** Civilian construction queue */
 	private QueueData civQueue;
-
-	/** Military construction queue */
 	private QueueData milQueue;
-
-	/** Descriptions of ships that can be built */
 	private List< BuildableShipData > bShips;
-
-	/** Descriptions of buildings that can be constructed */
 	private List< BuildableBuildingData > bBuildings;
 
-	/** List of the planet's resources */
-	private List< PlanetResourceRecord > resources;
 
-	/** Is the planet using specific mining settings? */
-	private boolean ownMiningSettings;
-
-
-	/** @return the planet's happiness */
 	public int getHappiness( )
 	{
-		return this.happiness;
+		return happiness;
 	}
 
 
-	/**
-	 * Set the planet's happiness
-	 * 
-	 * @param happiness
-	 *            the planet's happiness
-	 */
 	public void setHappiness( int happiness )
 	{
 		this.happiness = happiness;
 	}
 
 
-	/** @return the planet's happiness change indicator */
 	public int gethChange( )
 	{
-		return this.hChange;
+		return hChange;
 	}
 
 
-	/**
-	 * Set the planet's happiness change indicator
-	 * 
-	 * @param hChange
-	 *            the planet's happiness change indicator
-	 */
 	public void sethChange( int hChange )
 	{
 		this.hChange = hChange;
 	}
 
 
-	/** @return the planet's monetary income */
 	public long getIncome( )
 	{
-		return this.income;
+		return income;
 	}
 
 
-	/**
-	 * Set the planet's monetary income
-	 * 
-	 * @param income
-	 *            the planet's monetary income
-	 */
 	public void setIncome( long income )
 	{
 		this.income = income;
 	}
 
 
-	/** @return the planet's monetary upkeep */
 	public long getUpkeep( )
 	{
-		return this.upkeep;
+		return upkeep;
 	}
 
 
-	/**
-	 * Set the planet's monetary upkeep
-	 * 
-	 * @param upkeep
-	 *            the planet's monetary upkeep
-	 */
 	public void setUpkeep( long upkeep )
 	{
 		this.upkeep = upkeep;
 	}
 
 
-	/** @return the planet status object */
 	public OwnPlanetStatusData getStatus( )
 	{
-		return this.status;
+		return status;
 	}
 
 
-	/**
-	 * Set the planet status object
-	 * 
-	 * @param status
-	 *            the planet status object
-	 */
 	public void setStatus( OwnPlanetStatusData status )
 	{
 		this.status = status;
 	}
 
 
-	/** @return the civilian construction queue */
 	public QueueData getCivQueue( )
 	{
-		return this.civQueue;
+		return civQueue;
 	}
 
 
-	/**
-	 * Set the civilian construction queue
-	 * 
-	 * @param civQueue
-	 *            the civilian construction queue
-	 */
 	public void setCivQueue( QueueData civQueue )
 	{
 		this.civQueue = civQueue;
 	}
 
 
-	/** @return the military construction queue */
 	public QueueData getMilQueue( )
 	{
-		return this.milQueue;
+		return milQueue;
 	}
 
 
-	/**
-	 * Set the military construction queue
-	 * 
-	 * @param milQueue
-	 *            the military construction queue
-	 */
 	public void setMilQueue( QueueData milQueue )
 	{
 		this.milQueue = milQueue;
 	}
 
 
-	/** @return the descriptions of all ships which can be constructed */
 	public List< BuildableShipData > getbShips( )
 	{
-		return this.bShips;
+		return bShips;
 	}
 
 
-	/**
-	 * Set the descriptions of ships which can be constructed
-	 * 
-	 * @param bShips
-	 *            the descriptions of ships which can be constructed
-	 */
 	public void setbShips( List< BuildableShipData > bShips )
 	{
 		this.bShips = bShips;
 	}
 
 
-	/** @return the descriptions of all buildings which can be constructed */
 	public List< BuildableBuildingData > getbBuildings( )
 	{
-		return this.bBuildings;
+		return bBuildings;
 	}
 
 
-	/**
-	 * Set the descriptions of buildings which can be constructed
-	 * 
-	 * @param bBuildings
-	 *            the descriptions of buildings which can be constructed
-	 */
 	public void setbBuildings( List< BuildableBuildingData > bBuildings )
 	{
 		this.bBuildings = bBuildings;
 	}
 
-
-	/** @return the list of resources */
-	public List< PlanetResourceRecord > getResources( )
-	{
-		return this.resources;
-	}
-
-
-	/**
-	 * Set the list of resources
-	 * 
-	 * @param resourceProviders
-	 *            the list of resources
-	 */
-	public void setResources( List< PlanetResourceRecord > resources )
-	{
-		this.resources = resources;
-	}
-
-
-	/** @return whether the planet is using specific mining settings */
-	public boolean getOwnMiningSettings( )
-	{
-		return this.ownMiningSettings;
-	}
-
-
-	/**
-	 * Set whether the planet is using specific mining settings
-	 * 
-	 * @param ownMiningSettings
-	 *            whether the planet is using specific mining settings
-	 */
-	public void setOwnMiningSettings( boolean ownMiningSettings )
-	{
-		this.ownMiningSettings = ownMiningSettings;
-	}
-
 }
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/planets/PlanetResourceRecord.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/planets/PlanetResourceRecord.java
deleted file mode 100644
index 704e422..0000000
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/planets/PlanetResourceRecord.java
+++ /dev/null
@@ -1,125 +0,0 @@
-package com.deepclone.lw.cmd.player.gdata.planets;
-
-
-import com.deepclone.lw.cmd.player.gdata.AbstractResourceRecord;
-
-
-
-/**
- * Planet resources information
- * 
- * <p>
- * This class carries information about a resource type, including all required strings, as well as
- * income, upkeep and investment. It also contains information about the planet's resource provider
- * if there is one.
- * 
- * <p>
- * The class is used by {@link PlanetOwnView} to represent all of a planet's resources.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-public class PlanetResourceRecord
-		extends AbstractResourceRecord
-{
-
-	/**
-	 * The serialisation version identifier
-	 * 
-	 * <ul>
-	 * <li>Introduced in B6M2 with ID 1
-	 * </ul>
-	 */
-	private static final long serialVersionUID = 1L;
-
-	/** Income for 12h RT / 1 month GT */
-	private long income;
-
-	/** Upkeep for 12h RT / 1 month GT */
-	private long upkeep;
-
-	/** Quantity of that resource that will be used by the planet's queues */
-	private long invested;
-
-	/** Information about the planet's resource provider of that type, if there is one */
-	private ResourceProviderRecord resourceProvider;
-
-
-	/** @return the planet's income for that resource, over 12h RT / 1 month GT */
-	public long getIncome( )
-	{
-		return this.income;
-	}
-
-
-	/**
-	 * Set the planet's income for that resource
-	 * 
-	 * @param income
-	 *            the planet's income for that resource, over 12h RT / 1 month GT
-	 */
-	public void setIncome( long income )
-	{
-		this.income = income;
-	}
-
-
-	/** @return the planet's upkeep for that resource, over 12h RT / 1 month GT */
-	public long getUpkeep( )
-	{
-		return this.upkeep;
-	}
-
-
-	/**
-	 * Set the planet's upkeep for that resource
-	 * 
-	 * @param upkeep
-	 *            the planet's upkeep for that resource, over 12h RT / 1 month GT
-	 */
-	public void setUpkeep( long upkeep )
-	{
-		this.upkeep = upkeep;
-	}
-
-
-	/** @return the amount of that resource invested in the planet's build queues */
-	public long getInvested( )
-	{
-		return this.invested;
-	}
-
-
-	/**
-	 * Set the amount of that resource invested in the planet's build queues
-	 * 
-	 * @param invested
-	 *            the amount of that resource invested in the planet's build queues
-	 */
-	public void setInvested( long invested )
-	{
-		this.invested = invested;
-	}
-
-
-	/**
-	 * @return the resource provider data on that planet for the current resource type or
-	 *         <code>null</code> if there is no resource provider of that type.
-	 */
-	public ResourceProviderRecord getResourceProvider( )
-	{
-		return this.resourceProvider;
-	}
-
-
-	/**
-	 * Set the resource provider data on that planet for the current resource type
-	 * 
-	 * @param resourceProvider
-	 *            the resource provider data on that planet for the current resource type
-	 */
-	public void setResourceProvider( ResourceProviderRecord resourceProvider )
-	{
-		this.resourceProvider = resourceProvider;
-	}
-
-}
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/planets/QueueData.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/planets/QueueData.java
index 8aad730..90f4610 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/planets/QueueData.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/planets/QueueData.java
@@ -5,13 +5,15 @@ import java.io.Serializable;
 import java.util.Collections;
 import java.util.List;
 
+import com.deepclone.lw.session.API;
+
 
 
 public class QueueData
 		implements Serializable
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final boolean appendPossible;
 	private final List< QueueItemData > items;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/planets/QueueItemData.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/planets/QueueItemData.java
index a1000df..7de850f 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/planets/QueueItemData.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/planets/QueueItemData.java
@@ -4,6 +4,7 @@ package com.deepclone.lw.cmd.player.gdata.planets;
 import java.io.Serializable;
 
 import com.deepclone.lw.cmd.player.gdata.GameTime;
+import com.deepclone.lw.session.API;
 
 
 
@@ -11,7 +12,7 @@ public class QueueItemData
 		implements Serializable
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private String name;
 	private String description;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/planets/ResourceProviderRecord.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/planets/ResourceProviderRecord.java
deleted file mode 100644
index dee594d..0000000
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/planets/ResourceProviderRecord.java
+++ /dev/null
@@ -1,117 +0,0 @@
-package com.deepclone.lw.cmd.player.gdata.planets;
-
-
-import java.io.Serializable;
-
-
-
-/**
- * Information displayed about a resource provider
- * 
- * <p>
- * This class carries the information about a resource provider and associated mining priorities.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-public class ResourceProviderRecord
-		implements Serializable
-{
-
-	/**
-	 * The serialisation version identifier
-	 * 
-	 * <ul>
-	 * <li>Introduced in B6M2 with ID 1
-	 * </ul>
-	 */
-	private static final long serialVersionUID = 1L;
-
-	/** The resource provider's capacity (maximal quantity of resources) */
-	private long capacity;
-
-	/** The current quantity of resources in the provider */
-	private long quantity;
-
-	/** The extraction difficulty as a percentage */
-	private int difficulty;
-
-	/** The extraction priority */
-	private int priority;
-
-
-	/** @return the resource provider's capacity */
-	public long getCapacity( )
-	{
-		return this.capacity;
-	}
-
-
-	/**
-	 * Set the resource provider's capacity
-	 * 
-	 * @param capacity
-	 *            the resource provider's capacity
-	 */
-	public void setCapacity( long capacity )
-	{
-		this.capacity = capacity;
-	}
-
-
-	/** @return the resource provider's current quantity */
-	public long getQuantity( )
-	{
-		return this.quantity;
-	}
-
-
-	/**
-	 * Set the resource provider's current quantity
-	 * 
-	 * @param quantity
-	 *            the resource provider's current quantity
-	 */
-	public void setQuantity( long quantity )
-	{
-		this.quantity = quantity;
-	}
-
-
-	/** @return the extraction difficulty */
-	public int getDifficulty( )
-	{
-		return this.difficulty;
-	}
-
-
-	/**
-	 * Set the extraction difficulty
-	 * 
-	 * @param difficulty
-	 *            the extraction difficulty
-	 */
-	public void setDifficulty( int difficulty )
-	{
-		this.difficulty = difficulty;
-	}
-
-
-	/** @return the extraction priority */
-	public int getPriority( )
-	{
-		return this.priority;
-	}
-
-
-	/**
-	 * Set the extraction priority
-	 * 
-	 * @param priority
-	 *            the extraction priority
-	 */
-	public void setPriority( int priority )
-	{
-		this.priority = priority;
-	}
-
-}
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/msgs/ComposeMessageCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/msgs/ComposeMessageCommand.java
index 8d7a441..d655d6b 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/msgs/ComposeMessageCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/msgs/ComposeMessageCommand.java
@@ -2,6 +2,7 @@ package com.deepclone.lw.cmd.player.msgs;
 
 
 import com.deepclone.lw.cmd.msgdata.MessageType;
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -10,7 +11,7 @@ public class ComposeMessageCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final Boolean inbox;
 	private final Long replyTo;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/msgs/ComposeMessageResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/msgs/ComposeMessageResponse.java
index 45b95c0..f9b82b2 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/msgs/ComposeMessageResponse.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/msgs/ComposeMessageResponse.java
@@ -5,6 +5,7 @@ import com.deepclone.lw.cmd.msgdata.Message;
 import com.deepclone.lw.cmd.msgdata.MessageType;
 import com.deepclone.lw.cmd.player.gdata.GamePageData;
 import com.deepclone.lw.cmd.player.gdata.GameResponseBase;
+import com.deepclone.lw.session.API;
 
 
 
@@ -12,7 +13,7 @@ public class ComposeMessageResponse
 		extends GameResponseBase
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private MessageType messageType;
 	private String target;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/msgs/GetMessagesCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/msgs/GetMessagesCommand.java
index 92d24ef..3accf00 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/msgs/GetMessagesCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/msgs/GetMessagesCommand.java
@@ -1,6 +1,7 @@
 package com.deepclone.lw.cmd.player.msgs;
 
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -9,7 +10,7 @@ public class GetMessagesCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final boolean inbox;
 
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/msgs/GetMessagesResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/msgs/GetMessagesResponse.java
index 09025bc..94b67a7 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/msgs/GetMessagesResponse.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/msgs/GetMessagesResponse.java
@@ -6,6 +6,7 @@ import java.util.List;
 import com.deepclone.lw.cmd.msgdata.MessageListEntry;
 import com.deepclone.lw.cmd.player.gdata.GamePageData;
 import com.deepclone.lw.cmd.player.gdata.GameResponseBase;
+import com.deepclone.lw.session.API;
 
 
 
@@ -13,7 +14,7 @@ public class GetMessagesResponse
 		extends GameResponseBase
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final List< MessageListEntry > messages;
 
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/msgs/ListTargetsCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/msgs/ListTargetsCommand.java
index 9809a62..5974e5b 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/msgs/ListTargetsCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/msgs/ListTargetsCommand.java
@@ -1,6 +1,7 @@
 package com.deepclone.lw.cmd.player.msgs;
 
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -9,6 +10,6 @@ public class ListTargetsCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 }
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/msgs/ListTargetsResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/msgs/ListTargetsResponse.java
index 28aa092..6c5fd7f 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/msgs/ListTargetsResponse.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/msgs/ListTargetsResponse.java
@@ -8,6 +8,7 @@ import com.deepclone.lw.cmd.player.gdata.GamePageData;
 import com.deepclone.lw.cmd.player.gdata.GameResponseBase;
 import com.deepclone.lw.cmd.player.gdata.NameIdPair;
 import com.deepclone.lw.cmd.player.gdata.alliance.PublicAllianceInformation;
+import com.deepclone.lw.session.API;
 
 
 
@@ -15,7 +16,7 @@ public class ListTargetsResponse
 		extends GameResponseBase
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final List< NameIdPair > empires;
 	private final List< PublicAllianceInformation > alliances;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/msgs/MessageBoxCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/msgs/MessageBoxCommand.java
index 757cd99..8891e05 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/msgs/MessageBoxCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/msgs/MessageBoxCommand.java
@@ -1,6 +1,7 @@
 package com.deepclone.lw.cmd.player.msgs;
 
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -9,7 +10,7 @@ public class MessageBoxCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final MessageBoxAction action;
 	private final boolean inbox;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/msgs/PrepareMessageCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/msgs/PrepareMessageCommand.java
index 3abe09e..c6ce810 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/msgs/PrepareMessageCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/msgs/PrepareMessageCommand.java
@@ -2,6 +2,7 @@ package com.deepclone.lw.cmd.player.msgs;
 
 
 import com.deepclone.lw.cmd.msgdata.MessageType;
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -10,7 +11,7 @@ public class PrepareMessageCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final MessageType type;
 	private final Long id;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/msgs/ReadMessageCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/msgs/ReadMessageCommand.java
index 1656175..e1bd6fc 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/msgs/ReadMessageCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/msgs/ReadMessageCommand.java
@@ -1,6 +1,7 @@
 package com.deepclone.lw.cmd.player.msgs;
 
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -9,7 +10,7 @@ public class ReadMessageCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final boolean inbox;
 	private final long id;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/msgs/ReadMessageResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/msgs/ReadMessageResponse.java
index 436de68..fe110a9 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/msgs/ReadMessageResponse.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/msgs/ReadMessageResponse.java
@@ -4,6 +4,7 @@ package com.deepclone.lw.cmd.player.msgs;
 import com.deepclone.lw.cmd.msgdata.Message;
 import com.deepclone.lw.cmd.player.gdata.GamePageData;
 import com.deepclone.lw.cmd.player.gdata.GameResponseBase;
+import com.deepclone.lw.session.API;
 
 
 
@@ -11,7 +12,7 @@ public class ReadMessageResponse
 		extends GameResponseBase
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final boolean inbox;
 	private final Message message;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/planets/AbandonPlanetCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/planets/AbandonPlanetCommand.java
index 34711e2..149fd04 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/planets/AbandonPlanetCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/planets/AbandonPlanetCommand.java
@@ -1,10 +1,12 @@
 package com.deepclone.lw.cmd.player.planets;
 
+import com.deepclone.lw.session.API;
+
 
 public class AbandonPlanetCommand
 		extends ViewPlanetCommand
 {
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final boolean cancel;
 
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/planets/BuildShipsCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/planets/BuildShipsCommand.java
index 62d8521..12c159b 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/planets/BuildShipsCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/planets/BuildShipsCommand.java
@@ -1,11 +1,13 @@
 package com.deepclone.lw.cmd.player.planets;
 
+import com.deepclone.lw.session.API;
+
 
 public class BuildShipsCommand
 		extends ViewPlanetCommand
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final int sType;
 	private final int amount;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/planets/BuildingActionCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/planets/BuildingActionCommand.java
index 4d7ec2b..53e985e 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/planets/BuildingActionCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/planets/BuildingActionCommand.java
@@ -1,11 +1,13 @@
 package com.deepclone.lw.cmd.player.planets;
 
+import com.deepclone.lw.session.API;
+
 
 public class BuildingActionCommand
 		extends ViewPlanetCommand
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final int bType;
 	private final int amount;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/planets/BuildingActionResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/planets/BuildingActionResponse.java
index 86a4daf..c1a30b8 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/planets/BuildingActionResponse.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/planets/BuildingActionResponse.java
@@ -5,6 +5,7 @@ import com.deepclone.lw.cmd.player.gdata.GamePageData;
 import com.deepclone.lw.cmd.player.gdata.planets.PlanetBasicView;
 import com.deepclone.lw.cmd.player.gdata.planets.PlanetOrbitalView;
 import com.deepclone.lw.cmd.player.gdata.planets.PlanetOwnView;
+import com.deepclone.lw.session.API;
 
 
 
@@ -12,7 +13,7 @@ public class BuildingActionResponse
 		extends ViewPlanetResponse
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final boolean destructionFailed;
 
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/planets/FlushQueueCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/planets/FlushQueueCommand.java
index d2e1b08..5a456e0 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/planets/FlushQueueCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/planets/FlushQueueCommand.java
@@ -1,10 +1,12 @@
 package com.deepclone.lw.cmd.player.planets;
 
+import com.deepclone.lw.session.API;
+
 
 public class FlushQueueCommand
 		extends ViewPlanetCommand
 {
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final boolean military;
 
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/planets/RenamePlanetCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/planets/RenamePlanetCommand.java
index 09a586d..d0153ce 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/planets/RenamePlanetCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/planets/RenamePlanetCommand.java
@@ -1,11 +1,13 @@
 package com.deepclone.lw.cmd.player.planets;
 
+import com.deepclone.lw.session.API;
+
 
 public class RenamePlanetCommand
 		extends ViewPlanetCommand
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final String name;
 
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/planets/RenamePlanetResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/planets/RenamePlanetResponse.java
index 9073eb6..52b65e0 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/planets/RenamePlanetResponse.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/planets/RenamePlanetResponse.java
@@ -5,6 +5,7 @@ import com.deepclone.lw.cmd.player.gdata.GamePageData;
 import com.deepclone.lw.cmd.player.gdata.planets.PlanetBasicView;
 import com.deepclone.lw.cmd.player.gdata.planets.PlanetOrbitalView;
 import com.deepclone.lw.cmd.player.gdata.planets.PlanetOwnView;
+import com.deepclone.lw.session.API;
 
 
 
@@ -12,7 +13,7 @@ public class RenamePlanetResponse
 		extends ViewPlanetResponse
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final String renamingTo;
 	private final String renameError;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/planets/ToggleMiningSettingsCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/planets/ToggleMiningSettingsCommand.java
deleted file mode 100644
index c15dc0e..0000000
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/planets/ToggleMiningSettingsCommand.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package com.deepclone.lw.cmd.player.planets;
-
-
-/**
- * Command sent to toggle between empire-wide and planet-specific mining settings
- * 
- * <p>
- * Sending this command to the server will try to switch between empire-wide and planet-specific
- * settings on a given planet. The planet must be owned by the empire sending the command.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-public class ToggleMiningSettingsCommand
-		extends ViewPlanetCommand
-{
-
-	/**
-	 * Serialisation version identifier
-	 * 
-	 * <ul>
-	 * <li>Introduced in B6M2 with ID 1.
-	 * </ul>
-	 */
-	private static final long serialVersionUID = 1L;
-
-
-	/**
-	 * Initialise the command
-	 * 
-	 * @param planet
-	 *            the planet's identifier
-	 */
-	public ToggleMiningSettingsCommand( int planet )
-	{
-		super( planet );
-	}
-
-}
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/planets/UpdatePlanetMiningSettingsCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/planets/UpdatePlanetMiningSettingsCommand.java
deleted file mode 100644
index c29291c..0000000
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/planets/UpdatePlanetMiningSettingsCommand.java
+++ /dev/null
@@ -1,56 +0,0 @@
-package com.deepclone.lw.cmd.player.planets;
-
-
-import java.util.Map;
-
-
-
-/**
- * Command that updates a planet's mining settings
- * 
- * <p>
- * This command must be sent with the identifier of a planet that belongs to the current empire. If
- * the planet doesn't exist, if its ownership changed, or if it's configured to use empire-wide
- * settings, the command will be ignored.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-public class UpdatePlanetMiningSettingsCommand
-		extends ViewPlanetCommand
-{
-
-	/**
-	 * Serialisation version identifier
-	 * 
-	 * <ul>
-	 * <li>Introduced in B6M2 with ID 1
-	 * </ul>
-	 */
-	private static final long serialVersionUID = 1L;
-
-	/** The new mining settings */
-	private final Map< String , Integer > settings;
-
-
-	/**
-	 * Initialise the command using a planet identifier and mining settings
-	 * 
-	 * @param planet
-	 *            identifier of the planet to update 
-	 * @param settings
-	 *            a map that associates resource identifiers to priorities
-	 */
-	public UpdatePlanetMiningSettingsCommand( int planet , Map< String , Integer > settings )
-	{
-		super( planet );
-		this.settings = settings;
-	}
-
-
-	/** @return the mining settings to apply */
-	public Map< String , Integer > getSettings( )
-	{
-		return this.settings;
-	}
-
-}
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/planets/ViewPlanetCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/planets/ViewPlanetCommand.java
index b3d1137..c4c7a6f 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/planets/ViewPlanetCommand.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/planets/ViewPlanetCommand.java
@@ -1,6 +1,7 @@
 package com.deepclone.lw.cmd.player.planets;
 
 
+import com.deepclone.lw.session.API;
 import com.deepclone.lw.session.Command;
 
 
@@ -9,7 +10,7 @@ public class ViewPlanetCommand
 		extends Command
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final int id;
 
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/planets/ViewPlanetResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/planets/ViewPlanetResponse.java
index 6761652..03c4810 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/planets/ViewPlanetResponse.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/planets/ViewPlanetResponse.java
@@ -6,6 +6,7 @@ import com.deepclone.lw.cmd.player.gdata.GameResponseBase;
 import com.deepclone.lw.cmd.player.gdata.planets.PlanetBasicView;
 import com.deepclone.lw.cmd.player.gdata.planets.PlanetOrbitalView;
 import com.deepclone.lw.cmd.player.gdata.planets.PlanetOwnView;
+import com.deepclone.lw.session.API;
 
 
 
@@ -13,7 +14,7 @@ public class ViewPlanetResponse
 		extends GameResponseBase
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private final Integer id;
 	private final boolean ownershipError;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/research/ImplementTechCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/research/ImplementTechCommand.java
new file mode 100644
index 0000000..d5187ac
--- /dev/null
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/research/ImplementTechCommand.java
@@ -0,0 +1,29 @@
+package com.deepclone.lw.cmd.player.research;
+
+
+import com.deepclone.lw.session.API;
+import com.deepclone.lw.session.Command;
+
+
+
+public class ImplementTechCommand
+		extends Command
+{
+
+	private static final long serialVersionUID = API.Version;
+
+	private final String tech;
+
+
+	public ImplementTechCommand( String tech )
+	{
+		this.tech = tech;
+	}
+
+
+	public String getTech( )
+	{
+		return tech;
+	}
+
+}
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/research/ResearchOperationResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/research/ResearchOperationResponse.java
new file mode 100644
index 0000000..9be7842
--- /dev/null
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/research/ResearchOperationResponse.java
@@ -0,0 +1,87 @@
+package com.deepclone.lw.cmd.player.research;
+
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.deepclone.lw.cmd.player.gdata.GamePageData;
+import com.deepclone.lw.cmd.player.gdata.empire.ResearchData;
+import com.deepclone.lw.cmd.player.gdata.empire.TechnologyCategoryData;
+import com.deepclone.lw.session.API;
+
+
+
+/**
+ * Response to a research operation ({@link SetResearchPrioritiesCommand} or
+ * {@link ImplementTechCommand}). When the operation was successful, the response does not carry any
+ * actual data; when an error occurs, however, it includes the standard research view.
+ * 
+ * @author tseeker
+ */
+public class ResearchOperationResponse
+		extends ViewResearchResponse
+{
+
+	private static final long serialVersionUID = API.Version;
+
+	/**
+	 * Possible results of the operation
+	 */
+	public static enum Result {
+		/** The operation succeeded */
+		OK ,
+
+		/** Not enough resources (when the command was {@link ImplementTechCommand}) */
+		ERR_RESOURCES ,
+
+		/**
+		 * Technology already implemented (when the command was {@link ImplementTechCommand}) or
+		 * list of research topics modified (when the command was
+		 * {@link SetResearchPrioritiesCommand}).
+		 */
+		ERR_STATE_CHANGED ,
+
+		/** Invalid priority values (total is not 100, negative values, etc...) */
+		ERR_INVALID
+	}
+
+	/** Result of the operation */
+	private final Result result;
+
+
+	/** Create a response indicating a successful operation */
+	public ResearchOperationResponse( )
+	{
+		super( null , new ArrayList< ResearchData >( ) , new ArrayList< TechnologyCategoryData >( ) );
+		this.result = Result.OK;
+	}
+
+
+	/**
+	 * Create a response indicating an error during the operation.
+	 * 
+	 * @param page
+	 *            the basic page information
+	 * @param research
+	 *            the list of research topics
+	 * @param implemented
+	 *            the list of implemented technologies
+	 * @param result
+	 *            the error code.
+	 */
+	public ResearchOperationResponse( GamePageData page , List< ResearchData > research ,
+			List< TechnologyCategoryData > implemented , Result result )
+	{
+		super( page , research , implemented );
+		assert ( result != Result.OK );
+		this.result = result;
+	}
+
+
+	/** @return the result of the operation */
+	public Result getResult( )
+	{
+		return result;
+	}
+
+}
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/research/SetResearchPrioritiesCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/research/SetResearchPrioritiesCommand.java
new file mode 100644
index 0000000..44134a7
--- /dev/null
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/research/SetResearchPrioritiesCommand.java
@@ -0,0 +1,32 @@
+package com.deepclone.lw.cmd.player.research;
+
+
+import java.util.HashMap;
+import java.util.Map;
+
+import com.deepclone.lw.session.API;
+import com.deepclone.lw.session.Command;
+
+
+
+public class SetResearchPrioritiesCommand
+		extends Command
+{
+
+	private static final long serialVersionUID = API.Version;
+
+	private final Map< String , Integer > priorities;
+
+
+	public SetResearchPrioritiesCommand( Map< String , Integer > priorities )
+	{
+		this.priorities = new HashMap< String , Integer >( priorities );
+	}
+
+
+	public Map< String , Integer > getPriorities( )
+	{
+		return priorities;
+	}
+
+}
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/research/ViewResearchCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/research/ViewResearchCommand.java
new file mode 100644
index 0000000..66c8cf6
--- /dev/null
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/research/ViewResearchCommand.java
@@ -0,0 +1,15 @@
+package com.deepclone.lw.cmd.player.research;
+
+
+import com.deepclone.lw.session.API;
+import com.deepclone.lw.session.Command;
+
+
+
+public class ViewResearchCommand
+		extends Command
+{
+
+	private static final long serialVersionUID = API.Version;
+
+}
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/research/ViewResearchResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/research/ViewResearchResponse.java
new file mode 100644
index 0000000..c11df9d
--- /dev/null
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/research/ViewResearchResponse.java
@@ -0,0 +1,45 @@
+package com.deepclone.lw.cmd.player.research;
+
+
+import java.util.Collections;
+import java.util.List;
+
+import com.deepclone.lw.cmd.player.gdata.GamePageData;
+import com.deepclone.lw.cmd.player.gdata.GameResponseBase;
+import com.deepclone.lw.cmd.player.gdata.empire.ResearchData;
+import com.deepclone.lw.cmd.player.gdata.empire.TechnologyCategoryData;
+import com.deepclone.lw.session.API;
+
+
+
+public class ViewResearchResponse
+		extends GameResponseBase
+{
+
+	private static final long serialVersionUID = API.Version;
+
+	private final List< ResearchData > research;
+	private final List< TechnologyCategoryData > implementedTechnologies;
+
+
+	public ViewResearchResponse( GamePageData page , List< ResearchData > research ,
+			List< TechnologyCategoryData > implemented )
+	{
+		super( page );
+		this.research = Collections.unmodifiableList( research );
+		this.implementedTechnologies = Collections.unmodifiableList( implemented );
+	}
+
+
+	public List< ResearchData > getResearch( )
+	{
+		return this.research;
+	}
+
+
+	public List< TechnologyCategoryData > getImplementedTechnologies( )
+	{
+		return this.implementedTechnologies;
+	}
+
+}
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/tech/GetResearchCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/tech/GetResearchCommand.java
deleted file mode 100644
index f5961c3..0000000
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/tech/GetResearchCommand.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package com.deepclone.lw.cmd.player.tech;
-
-
-import com.deepclone.lw.session.Command;
-
-
-
-/**
- * Command that obtains the current research &amp; technology data
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-public class GetResearchCommand
-		extends Command
-{
-
-	/**
-	 * The serialisation version identifier
-	 * 
-	 * <ul>
-	 * <li>Introduced in B6M2 with ID 1
-	 * </ul>
-	 */
-	private static final long serialVersionUID = 1L;
-
-}
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/tech/GetResearchResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/tech/GetResearchResponse.java
deleted file mode 100644
index 22fd824..0000000
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/tech/GetResearchResponse.java
+++ /dev/null
@@ -1,66 +0,0 @@
-package com.deepclone.lw.cmd.player.tech;
-
-
-import java.util.Collections;
-import java.util.LinkedList;
-import java.util.List;
-
-import com.deepclone.lw.cmd.player.gdata.GamePageData;
-import com.deepclone.lw.cmd.player.gdata.GameResponseBase;
-import com.deepclone.lw.cmd.player.gdata.empire.ResearchData;
-
-
-
-/**
- * Response that lists all research entries (sent by the server in response to
- * {@link GetResearchCommand})
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-public class GetResearchResponse
-		extends GameResponseBase
-{
-
-	/**
-	 * The serialisation version identifier
-	 * 
-	 * <ul>
-	 * <li>Introduced in B6M2 with ID 1
-	 * </ul>
-	 */
-	private static final long serialVersionUID = 1L;
-
-	/** Sorted list of research entries */
-	private final List< ResearchData > researchData;
-
-
-	/**
-	 * Initialise the response
-	 * 
-	 * <p>
-	 * Copy and sort the list of research entries
-	 * 
-	 * @param page
-	 *            the common page information
-	 * @param technologies
-	 *            the list of research entries
-	 */
-	public GetResearchResponse( GamePageData page , List< ResearchData > technologies )
-	{
-		super( page );
-		this.researchData = new LinkedList< ResearchData >( technologies );
-		Collections.sort( this.researchData );
-	}
-
-
-	/**
-	 * Get the list of research entries
-	 * 
-	 * @return the sorted list of research entries
-	 */
-	public List< ResearchData > getResearchData( )
-	{
-		return this.researchData;
-	}
-
-}
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/tech/ImplementTechCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/tech/ImplementTechCommand.java
deleted file mode 100644
index b3dbc93..0000000
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/tech/ImplementTechCommand.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package com.deepclone.lw.cmd.player.tech;
-
-
-import com.deepclone.lw.session.Command;
-
-
-
-/**
- * Technology implementation command
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-public class ImplementTechCommand
-		extends Command
-{
-
-	/**
-	 * The serialisation version identifier
-	 * 
-	 * <ul>
-	 * <li>Introduced in B6M1 with ID 1
-	 * <li>Modified in B6M2, ID set to 2
-	 * </ul>
-	 */
-	private static final long serialVersionUID = 2L;
-
-	/** Identifier of the technology to implement */
-	private final String tech;
-
-
-	/**
-	 * Initialise the command
-	 * 
-	 * @param tech
-	 *            the identifier of the technology to implement
-	 */
-	public ImplementTechCommand( String tech )
-	{
-		this.tech = tech;
-	}
-
-
-	/**
-	 * Get the identifier of the technology to implement
-	 * 
-	 * @return the identifier of the technology to implement
-	 */
-	public String getTech( )
-	{
-		return this.tech;
-	}
-
-}
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/tech/UpdateResearchPrioritiesCommand.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/tech/UpdateResearchPrioritiesCommand.java
deleted file mode 100644
index 4dd5b08..0000000
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/tech/UpdateResearchPrioritiesCommand.java
+++ /dev/null
@@ -1,50 +0,0 @@
-package com.deepclone.lw.cmd.player.tech;
-
-
-import java.util.Map;
-
-import com.deepclone.lw.session.Command;
-
-
-
-/**
- * Command that updates research priorities
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-public class UpdateResearchPrioritiesCommand
-		extends Command
-{
-
-	/**
-	 * Serialisation version identifier
-	 * 
-	 * <ul>
-	 * <li>Introduced in B6M2
-	 * </ul>
-	 */
-	private static final long serialVersionUID = 1L;
-
-	/** The new research priorities */
-	private final Map< String , Integer > priorities;
-
-
-	/**
-	 * Initialise the command using research priority values
-	 * 
-	 * @param priorities
-	 *            a map that associates technology identifiers to priorities
-	 */
-	public UpdateResearchPrioritiesCommand( Map< String , Integer > priorities )
-	{
-		this.priorities = priorities;
-	}
-
-
-	/** @return the new research priorities */
-	public Map< String , Integer > getPriorities( )
-	{
-		return this.priorities;
-	}
-
-}
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/session/API.java b/legacyworlds-session/src/main/java/com/deepclone/lw/session/API.java
new file mode 100644
index 0000000..84e513e
--- /dev/null
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/session/API.java
@@ -0,0 +1,15 @@
+package com.deepclone.lw.session;
+
+
+public final class API
+{
+	
+	public static final long Version = 0x005099002;
+
+	/* Prevent construction */
+	private API( )
+	{
+		// EMPTY
+	}
+
+}
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/session/Command.java b/legacyworlds-session/src/main/java/com/deepclone/lw/session/Command.java
index 5733eae..419f17d 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/session/Command.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/session/Command.java
@@ -8,7 +8,7 @@ import java.io.Serializable;
 public abstract class Command
 		implements Serializable
 {
-
-	private static final long serialVersionUID = 1L;
+	
+	private static final long serialVersionUID = API.Version;
 
 }
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/session/CommandResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/session/CommandResponse.java
index bef3cd8..f9d0eaf 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/session/CommandResponse.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/session/CommandResponse.java
@@ -9,6 +9,6 @@ public abstract class CommandResponse
 		implements Serializable
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 }
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/session/NullResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/session/NullResponse.java
index a7f44ab..19dfc94 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/session/NullResponse.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/session/NullResponse.java
@@ -5,6 +5,6 @@ public final class NullResponse
 		extends CommandResponse
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 }
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/session/SessionCommandException.java b/legacyworlds-session/src/main/java/com/deepclone/lw/session/SessionCommandException.java
index bc53083..671f59c 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/session/SessionCommandException.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/session/SessionCommandException.java
@@ -5,7 +5,7 @@ public class SessionCommandException
 		extends SessionException
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 
 	public SessionCommandException( String message )
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/session/SessionException.java b/legacyworlds-session/src/main/java/com/deepclone/lw/session/SessionException.java
index 8490fb9..708fdf9 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/session/SessionException.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/session/SessionException.java
@@ -5,7 +5,7 @@ public abstract class SessionException
 		extends Exception
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	private boolean keepSession;
 
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/session/SessionIdentifierException.java b/legacyworlds-session/src/main/java/com/deepclone/lw/session/SessionIdentifierException.java
index 4273f76..3218562 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/session/SessionIdentifierException.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/session/SessionIdentifierException.java
@@ -10,7 +10,7 @@ public final class SessionIdentifierException
 		extends SessionException
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 
 	public SessionIdentifierException( String identifier )
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/session/SessionInternalException.java b/legacyworlds-session/src/main/java/com/deepclone/lw/session/SessionInternalException.java
index 42474ee..f0b1614 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/session/SessionInternalException.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/session/SessionInternalException.java
@@ -10,7 +10,7 @@ public final class SessionInternalException
 		extends SessionException
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 
 	public SessionInternalException( boolean keep , Throwable cause )
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/session/SessionReference.java b/legacyworlds-session/src/main/java/com/deepclone/lw/session/SessionReference.java
index 4e7fb70..7605943 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/session/SessionReference.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/session/SessionReference.java
@@ -19,7 +19,7 @@ public final class SessionReference
 		implements Serializable
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	/** String identifier of the session */
 	public final String identifier;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/session/SessionResponse.java b/legacyworlds-session/src/main/java/com/deepclone/lw/session/SessionResponse.java
index 6071671..2ebc3ac 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/session/SessionResponse.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/session/SessionResponse.java
@@ -14,7 +14,7 @@ public class SessionResponse
 		implements Serializable
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 	/** Updated session reference */
 	public final SessionReference session;
diff --git a/legacyworlds-session/src/main/java/com/deepclone/lw/session/SessionStateException.java b/legacyworlds-session/src/main/java/com/deepclone/lw/session/SessionStateException.java
index eaa69e5..45ed6e0 100644
--- a/legacyworlds-session/src/main/java/com/deepclone/lw/session/SessionStateException.java
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/session/SessionStateException.java
@@ -10,7 +10,7 @@ public final class SessionStateException
 		extends SessionException
 {
 
-	private static final long serialVersionUID = 1L;
+	private static final long serialVersionUID = API.Version;
 
 
 	public SessionStateException( )
diff --git a/legacyworlds-session/src/main/resources/.empty b/legacyworlds-session/src/main/resources/.empty
deleted file mode 100644
index e69de29..0000000
diff --git a/legacyworlds-session/src/test/java/.empty b/legacyworlds-session/src/test/java/.empty
deleted file mode 100644
index e69de29..0000000
diff --git a/legacyworlds-session/src/test/resources/.empty b/legacyworlds-session/src/test/resources/.empty
deleted file mode 100644
index e69de29..0000000
diff --git a/legacyworlds-tests/pom.xml b/legacyworlds-tests/pom.xml
deleted file mode 100644
index 176f5da..0000000
--- a/legacyworlds-tests/pom.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-	<modelVersion>4.0.0</modelVersion>
-	<parent>
-		<artifactId>legacyworlds</artifactId>
-		<groupId>com.deepclone.lw</groupId>
-		<version>1.0.0</version>
-		<relativePath>../legacyworlds/pom.xml</relativePath>
-	</parent>
-
-	<artifactId>legacyworlds-tests</artifactId>
-	<version>${legacyworlds.version.main}.${legacyworlds.version.release}-${legacyworlds.version.build}</version>
-	<name>Legacy Worlds - Common packages - Tests</name>
-	<description>This package contains all tests for classes in common packages.</description>
-
-	<dependencies>
-		<dependency>
-			<artifactId>legacyworlds-session</artifactId>
-			<groupId>com.deepclone.lw</groupId>
-			<scope>test</scope>
-		</dependency>
-		<dependency>
-			<artifactId>legacyworlds-utils</artifactId>
-			<groupId>com.deepclone.lw</groupId>
-			<scope>test</scope>
-		</dependency>
-
-		<dependency>
-			<groupId>junit</groupId>
-			<artifactId>junit</artifactId>
-			<scope>test</scope>
-		</dependency>
-		<dependency>
-			<groupId>org.springframework</groupId>
-			<artifactId>spring-test</artifactId>
-			<scope>test</scope>
-		</dependency>
-	</dependencies>
-</project>
\ No newline at end of file
diff --git a/legacyworlds-tests/src/main/java/.empty b/legacyworlds-tests/src/main/java/.empty
deleted file mode 100644
index e69de29..0000000
diff --git a/legacyworlds-tests/src/main/resources/.empty b/legacyworlds-tests/src/main/resources/.empty
deleted file mode 100644
index e69de29..0000000
diff --git a/legacyworlds-tests/src/test/java/.empty b/legacyworlds-tests/src/test/java/.empty
deleted file mode 100644
index e69de29..0000000
diff --git a/legacyworlds-tests/src/test/java/com/deepclone/lw/cmd/player/gdata/TestAbstractResourceRecord.java b/legacyworlds-tests/src/test/java/com/deepclone/lw/cmd/player/gdata/TestAbstractResourceRecord.java
deleted file mode 100644
index e4a0e5c..0000000
--- a/legacyworlds-tests/src/test/java/com/deepclone/lw/cmd/player/gdata/TestAbstractResourceRecord.java
+++ /dev/null
@@ -1,88 +0,0 @@
-package com.deepclone.lw.cmd.player.gdata;
-
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
-
-import org.junit.Before;
-import org.junit.Test;
-
-
-
-/**
- * Tests of the {@link AbstractResourceRecord} class
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-public class TestAbstractResourceRecord
-{
-	/** String used in tests */
-	private static final String TEST_STRING = "Test";
-
-	/** Class used in the tests */
-	@SuppressWarnings( "serial" )
-	private static class FakeChild
-			extends AbstractResourceRecord
-	{
-		// EMPTY
-	}
-
-	/** Guinea pig instance */
-	private FakeChild resource;
-
-
-	/** Create the "guinea pig" instance */
-	@Before
-	public void setUp( )
-	{
-		this.resource = new FakeChild( );
-	}
-
-
-	/** Test default values */
-	@Test
-	public void testDefaults( )
-	{
-		assertNull( this.resource.getIdentifier( ) );
-		assertNull( this.resource.getCategory( ) );
-		assertNull( this.resource.getTitle( ) );
-		assertNull( this.resource.getDescription( ) );
-	}
-
-
-	/** Test setting and reading the identifier */
-	@Test
-	public void testIdentifier( )
-	{
-		this.resource.setIdentifier( TEST_STRING );
-		assertEquals( TEST_STRING , this.resource.getIdentifier( ) );
-	}
-
-
-	/** Test setting and reading the category */
-	@Test
-	public void testCategory( )
-	{
-		this.resource.setCategory( TEST_STRING );
-		assertEquals( TEST_STRING , this.resource.getCategory( ) );
-	}
-
-
-	/** Test setting and reading the title */
-	@Test
-	public void testTitle( )
-	{
-		this.resource.setTitle( TEST_STRING );
-		assertEquals( TEST_STRING , this.resource.getTitle( ) );
-	}
-
-
-	/** Test setting and reading the description */
-	@Test
-	public void testDescription( )
-	{
-		this.resource.setDescription( TEST_STRING );
-		assertEquals( TEST_STRING , this.resource.getDescription( ) );
-	}
-
-}
diff --git a/legacyworlds-tests/src/test/java/com/deepclone/lw/cmd/player/gdata/empire/TestEmpireResourceRecord.java b/legacyworlds-tests/src/test/java/com/deepclone/lw/cmd/player/gdata/empire/TestEmpireResourceRecord.java
deleted file mode 100644
index 02f3ea7..0000000
--- a/legacyworlds-tests/src/test/java/com/deepclone/lw/cmd/player/gdata/empire/TestEmpireResourceRecord.java
+++ /dev/null
@@ -1,125 +0,0 @@
-package com.deepclone.lw.cmd.player.gdata.empire;
-
-
-import static org.junit.Assert.*;
-
-import org.junit.Before;
-import org.junit.Test;
-
-
-
-/**
- * Tests for the {@link EmpireResourceRecord} class
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-public class TestEmpireResourceRecord
-{
-	/** String used in tests */
-	private static final String TEST_STRING = "Test";
-
-	/** Long integer used in tests */
-	private static final long TEST_LONG = 42L;
-
-	private static final int TEST_INTEGER = 42;
-
-	/** The "guinea pig" instance */
-	private EmpireResourceRecord instance;
-
-
-	/** Create the "guinea pig" instance */
-	@Before
-	public void setUp( )
-	{
-		this.instance = new EmpireResourceRecord( );
-	}
-
-
-	/** Check default values */
-	@Test
-	public void testDefaults( )
-	{
-		assertNull( this.instance.getIdentifier( ) );
-		assertNull( this.instance.getDescription( ) );
-		assertEquals( 0L , this.instance.getIncome( ) );
-		assertEquals( 0L , this.instance.getPlanetUpkeep( ) );
-		assertEquals( 0L , this.instance.getFleetUpkeep( ) );
-		assertEquals( 0L , this.instance.getUpkeep( ) );
-		assertEquals( 0L , this.instance.getStockpiled( ) );
-		assertNull( this.instance.getMiningPriority( ) );
-	}
-
-
-	/** Setting and reading the identifier */
-	@Test
-	public void testIdentifier( )
-	{
-		this.instance.setIdentifier( TEST_STRING );
-		assertEquals( TEST_STRING , this.instance.getIdentifier( ) );
-	}
-
-
-	/** Setting and reading the description */
-	@Test
-	public void testDescription( )
-	{
-		this.instance.setDescription( TEST_STRING );
-		assertEquals( TEST_STRING , this.instance.getDescription( ) );
-	}
-
-
-	/** Setting and reading the income */
-	@Test
-	public void testIncome( )
-	{
-		this.instance.setIncome( TEST_LONG );
-		assertEquals( TEST_LONG , this.instance.getIncome( ) );
-	}
-
-
-	/** Setting and reading the planet upkeep */
-	@Test
-	public void testPlanetUpkeep( )
-	{
-		this.instance.setPlanetUpkeep( TEST_LONG );
-		assertEquals( TEST_LONG , this.instance.getPlanetUpkeep( ) );
-	}
-
-
-	/** Setting and reading the fleet upkeep */
-	@Test
-	public void testFleetUpkeep( )
-	{
-		this.instance.setFleetUpkeep( TEST_LONG );
-		assertEquals( TEST_LONG , this.instance.getFleetUpkeep( ) );
-	}
-
-
-	/** Setting and reading the stockpiled quantity */
-	@Test
-	public void testStockpiled( )
-	{
-		this.instance.setStockpiled( TEST_LONG );
-		assertEquals( TEST_LONG , this.instance.getStockpiled( ) );
-	}
-
-
-	/** Setting and reading the mining priority */
-	@Test
-	public void testMiningPriority( )
-	{
-		this.instance.setMiningPriority( TEST_INTEGER );
-		assertEquals( (Integer) TEST_INTEGER , this.instance.getMiningPriority( ) );
-	}
-
-
-	/** Total upkeep = fleet upkeep + planet upkeep */
-	@Test
-	public void testTotalUpkeep( )
-	{
-		this.instance.setPlanetUpkeep( TEST_LONG );
-		assertEquals( TEST_LONG , this.instance.getUpkeep( ) );
-		this.instance.setFleetUpkeep( TEST_LONG + 1 );
-		assertEquals( TEST_LONG * 2 + 1 , this.instance.getUpkeep( ) );
-	}
-}
diff --git a/legacyworlds-tests/src/test/java/com/deepclone/lw/cmd/player/gdata/planets/TestPlanetResourceRecord.java b/legacyworlds-tests/src/test/java/com/deepclone/lw/cmd/player/gdata/planets/TestPlanetResourceRecord.java
deleted file mode 100644
index 30818de..0000000
--- a/legacyworlds-tests/src/test/java/com/deepclone/lw/cmd/player/gdata/planets/TestPlanetResourceRecord.java
+++ /dev/null
@@ -1,82 +0,0 @@
-package com.deepclone.lw.cmd.player.gdata.planets;
-
-
-import static org.junit.Assert.*;
-
-import org.junit.Before;
-import org.junit.Test;
-
-
-
-/**
- * Tests for the {@link PlanetResourceRecord} class.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-public class TestPlanetResourceRecord
-{
-	/** Long integer used in tests */
-	private static final long TEST_LONG = 42L;
-
-	/** Resource data instance to test on */
-	private PlanetResourceRecord resourceData;
-
-
-	/** Create the "guinea pig" instance */
-	@Before
-	public void setUp( )
-	{
-		this.resourceData = new PlanetResourceRecord( );
-	}
-
-
-	/** Test default values */
-	@Test
-	public void testDefaults( )
-	{
-		assertEquals( 0L , this.resourceData.getIncome( ) );
-		assertEquals( 0L , this.resourceData.getUpkeep( ) );
-		assertEquals( 0L , this.resourceData.getInvested( ) );
-		assertNull( this.resourceData.getResourceProvider( ) );
-	}
-
-
-	/** Test setting and reading the income */
-	@Test
-	public void testIncome( )
-	{
-		this.resourceData.setIncome( TEST_LONG );
-		assertEquals( TEST_LONG , this.resourceData.getIncome( ) );
-	}
-
-
-	/** Test setting and reading the upkeep */
-	@Test
-	public void testUpkeep( )
-	{
-		this.resourceData.setUpkeep( TEST_LONG );
-		assertEquals( TEST_LONG , this.resourceData.getUpkeep( ) );
-	}
-
-
-	/** Test setting and reading the invested amount */
-	@Test
-	public void testInvested( )
-	{
-		this.resourceData.setInvested( TEST_LONG );
-		assertEquals( TEST_LONG , this.resourceData.getInvested( ) );
-	}
-
-
-	/** Test setting and reading the resource provider */
-	@Test
-	public void testResourceProvider( )
-	{
-		ResourceProviderRecord rpd = new ResourceProviderRecord( );
-		rpd.setCapacity( TEST_LONG );
-		this.resourceData.setResourceProvider( rpd );
-		rpd = this.resourceData.getResourceProvider( );
-		assertNotNull( rpd );
-		assertEquals( TEST_LONG , rpd.getCapacity( ) );
-	}
-}
diff --git a/legacyworlds-tests/src/test/java/com/deepclone/lw/cmd/player/gdata/planets/TestResourceProviderRecord.java b/legacyworlds-tests/src/test/java/com/deepclone/lw/cmd/player/gdata/planets/TestResourceProviderRecord.java
deleted file mode 100644
index cac3037..0000000
--- a/legacyworlds-tests/src/test/java/com/deepclone/lw/cmd/player/gdata/planets/TestResourceProviderRecord.java
+++ /dev/null
@@ -1,83 +0,0 @@
-package com.deepclone.lw.cmd.player.gdata.planets;
-
-
-import static org.junit.Assert.*;
-
-import org.junit.Before;
-import org.junit.Test;
-
-
-
-/**
- * Tests for the {@link ResourceProviderRecord} class.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- * 
- */
-public class TestResourceProviderRecord
-{
-
-	/** Long integer used in tests */
-	private static final long TEST_LONG = 42L;
-
-	/** Integer used in tests */
-	private static final int TEST_INT = 42;
-
-	/** Resource provider data instance to test on */
-	private ResourceProviderRecord resProvData;
-
-
-	/** Create the "guinea pig" instance */
-	@Before
-	public void setUp( )
-	{
-		this.resProvData = new ResourceProviderRecord( );
-	}
-	
-	/** Check default values */
-	@Test
-	public void testDefaults( )
-	{
-		assertEquals( 0L , this.resProvData.getCapacity( ) );
-		assertEquals( 0L , this.resProvData.getQuantity( ) );
-		assertEquals( 0 , this.resProvData.getDifficulty( ) );
-		assertEquals( 0 , this.resProvData.getPriority( ) );
-	}
-
-
-	/** Setting and reading the capacity */
-	@Test
-	public void testSetCapacity( )
-	{
-		this.resProvData.setCapacity( TEST_LONG );
-		assertEquals( TEST_LONG , this.resProvData.getCapacity( ) );
-	}
-
-
-	/** Setting and reading the quantity */
-	@Test
-	public void testSetQuantity( )
-	{
-		this.resProvData.setQuantity( TEST_LONG );
-		assertEquals( TEST_LONG , this.resProvData.getQuantity( ) );
-	}
-
-
-	/** Setting and reading the difficulty */
-	@Test
-	public void testSetDifficulty( )
-	{
-		this.resProvData.setDifficulty( TEST_INT );
-		assertEquals( TEST_INT , this.resProvData.getDifficulty( ) );
-	}
-
-
-	/** Setting and reading the priority */
-	@Test
-	public void testSetPriority( )
-	{
-		this.resProvData.setPriority( TEST_INT );
-		assertEquals( TEST_INT , this.resProvData.getPriority( ) );
-	}
-
-}
diff --git a/legacyworlds-tests/src/test/resources/.empty b/legacyworlds-tests/src/test/resources/.empty
deleted file mode 100644
index e69de29..0000000
diff --git a/legacyworlds-utils/.classpath b/legacyworlds-utils/.classpath
new file mode 100644
index 0000000..7c3d14f
--- /dev/null
+++ b/legacyworlds-utils/.classpath
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" output="target/classes" path="src/main/java"/>
+	<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources"/>
+	<classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
+	<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+	<classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER"/>
+	<classpathentry kind="output" path="target/classes"/>
+</classpath>
diff --git a/legacyworlds-utils/.project b/legacyworlds-utils/.project
new file mode 100644
index 0000000..fd839fa
--- /dev/null
+++ b/legacyworlds-utils/.project
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>legacyworlds-utils</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.maven.ide.eclipse.maven2Builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.maven.ide.eclipse.maven2Nature</nature>
+	</natures>
+</projectDescription>
diff --git a/legacyworlds-utils/.settings/org.eclipse.jdt.core.prefs b/legacyworlds-utils/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..878d24f
--- /dev/null
+++ b/legacyworlds-utils/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,6 @@
+#Mon Apr 19 12:23:34 CEST 2010
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.6
diff --git a/legacyworlds-utils/.settings/org.maven.ide.eclipse.prefs b/legacyworlds-utils/.settings/org.maven.ide.eclipse.prefs
new file mode 100644
index 0000000..762f9e9
--- /dev/null
+++ b/legacyworlds-utils/.settings/org.maven.ide.eclipse.prefs
@@ -0,0 +1,9 @@
+#Mon Apr 19 12:23:33 CEST 2010
+activeProfiles=
+eclipse.preferences.version=1
+fullBuildGoals=process-test-resources
+includeModules=false
+resolveWorkspaceProjects=true
+resourceFilterGoals=process-resources resources\:testResources
+skipCompilerPlugin=true
+version=1
diff --git a/legacyworlds-utils/pom.xml b/legacyworlds-utils/pom.xml
index 574f035..cf05448 100644
--- a/legacyworlds-utils/pom.xml
+++ b/legacyworlds-utils/pom.xml
@@ -4,19 +4,21 @@
 	<parent>
 		<artifactId>legacyworlds</artifactId>
 		<groupId>com.deepclone.lw</groupId>
-		<version>1.0.0</version>
-		<relativePath>../legacyworlds/pom.xml</relativePath>
+		<version>5.99.2</version>
 	</parent>
 
+	<groupId>com.deepclone.lw</groupId>
 	<artifactId>legacyworlds-utils</artifactId>
-	<version>${legacyworlds.version.main}.${legacyworlds.version.release}-${legacyworlds.version.build}</version>
-	<name>Legacy Worlds - Common packages - Utilities</name>
+	<version>5.99.2</version>
+	<name>Legacy Worlds common utilities</name>
 	<description>The classes in this package are used by all parts of the Legacy Worlds code.</description>
 
 	<dependencies>
 		<dependency>
 			<groupId>commons-codec</groupId>
 			<artifactId>commons-codec</artifactId>
+			<version>${commons.codec.version}</version>
+			<type>jar</type>
 		</dependency>
 	</dependencies>
-</project>
+</project>
\ No newline at end of file
diff --git a/legacyworlds-utils/src/main/resources/.empty b/legacyworlds-utils/src/main/resources/.empty
deleted file mode 100644
index e69de29..0000000
diff --git a/legacyworlds-utils/src/test/java/.empty b/legacyworlds-utils/src/test/java/.empty
deleted file mode 100644
index e69de29..0000000
diff --git a/legacyworlds-utils/src/test/resources/.empty b/legacyworlds-utils/src/test/resources/.empty
deleted file mode 100644
index e69de29..0000000
diff --git a/legacyworlds-web-DIST/pom.xml b/legacyworlds-web-DIST/pom.xml
deleted file mode 100644
index a503c67..0000000
--- a/legacyworlds-web-DIST/pom.xml
+++ /dev/null
@@ -1,74 +0,0 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-	<modelVersion>4.0.0</modelVersion>
-	<parent>
-		<artifactId>legacyworlds-web</artifactId>
-		<groupId>com.deepclone.lw</groupId>
-		<version>1.0.0</version>
-		<relativePath>../legacyworlds-web/pom.xml</relativePath>
-	</parent>
-
-	<artifactId>legacyworlds-web-DIST</artifactId>
-	<version>${legacyworlds.version.main}.${legacyworlds.version.release}-${legacyworlds.version.build}</version>
-
-	<packaging>pom</packaging>
-	<name>Legacy Worlds - Web - Packaging</name>
-	<description>This Maven module is responsible for creating the Legacy Worlds web interface's packaging.</description>
-
-
-	<!-- Depend on both WAR projects -->
-	<dependencies>
-		<dependency>
-			<groupId>com.deepclone.lw</groupId>
-			<artifactId>legacyworlds-web-main</artifactId>
-			<version>${project.version}</version>
-			<type>war</type>
-		</dependency>
-		<dependency>
-			<groupId>com.deepclone.lw</groupId>
-			<artifactId>legacyworlds-web-admin</artifactId>
-			<version>${project.version}</version>
-			<type>war</type>
-		</dependency>
-	</dependencies>
-
-	<build>
-		<plugins>
-			<!-- Clean the target directory before generating the distribution -->
-			<plugin>
-				<artifactId>maven-clean-plugin</artifactId>
-				<executions>
-					<execution>
-						<id>clean-before-assembly</id>
-						<phase>initialize</phase>
-						<goals>
-							<goal>clean</goal>
-						</goals>
-					</execution>
-				</executions>
-			</plugin>
-
-			<!-- Use the assembly plug-in to generate the distribution -->
-			<plugin>
-				<artifactId>maven-assembly-plugin</artifactId>
-				<executions>
-					<execution>
-						<id>distribution-assembly</id>
-						<phase>package</phase>
-						<goals>
-							<goal>single</goal>
-						</goals>
-						<configuration>
-							<attach>false</attach>
-							<finalName>legacyworlds-web-${project.version}</finalName>
-							<descriptors>
-								<descriptor>src/web.xml</descriptor>
-							</descriptors>
-							<appendAssemblyId>false</appendAssemblyId>
-						</configuration>
-					</execution>
-				</executions>
-			</plugin>
-		</plugins>
-	</build>
-</project>
diff --git a/legacyworlds-web-DIST/src/web.xml b/legacyworlds-web-DIST/src/web.xml
deleted file mode 100644
index f7ffb97..0000000
--- a/legacyworlds-web-DIST/src/web.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<assembly
-	xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
-	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
-
-	<!-- Legacy Worlds web interface assembly -->
-
-	<id>legacyworlds-web</id>
-	<formats>
-		<format>dir</format>
-	</formats>
-	<includeBaseDirectory>false</includeBaseDirectory>
-
-	<dependencySets>
-
-		<dependencySet>
-			<useProjectArtifact>false</useProjectArtifact>
-			<outputDirectory>.</outputDirectory>
-			<unpack>false</unpack>
-			<includes>
-				<include>*:war</include>
-			</includes>
-		</dependencySet>
-
-	</dependencySets>
-
-</assembly>
diff --git a/legacyworlds-web-admin/Content/Filtered/fm/version.ftl b/legacyworlds-web-admin/Content/Filtered/fm/version.ftl
deleted file mode 100644
index c3974e0..0000000
--- a/legacyworlds-web-admin/Content/Filtered/fm/version.ftl
+++ /dev/null
@@ -1,2 +0,0 @@
-<#macro version>${legacyworlds.version.string}</#macro>
-<#macro full_version>Beta 6 ${legacyworlds.version.string} (${legacyworlds.version.main}.${legacyworlds.version.release} b${legacyworlds.version.build})</#macro>
\ No newline at end of file
diff --git a/legacyworlds-web-admin/pom.xml b/legacyworlds-web-admin/pom.xml
deleted file mode 100644
index a126184..0000000
--- a/legacyworlds-web-admin/pom.xml
+++ /dev/null
@@ -1,51 +0,0 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-	<modelVersion>4.0.0</modelVersion>
-	<parent>
-		<artifactId>legacyworlds-web</artifactId>
-		<groupId>com.deepclone.lw</groupId>
-		<version>1.0.0</version>
-		<relativePath>../legacyworlds-web/pom.xml</relativePath>
-	</parent>
-
-	<artifactId>legacyworlds-web-admin</artifactId>
-	<version>${legacyworlds.version.main}.${legacyworlds.version.release}-${legacyworlds.version.build}</version>
-
-	<packaging>war</packaging>
-	<name>Legacy Worlds - Web - Administration</name>
-
-	<dependencies>
-		<dependency>
-			<groupId>com.deepclone.lw</groupId>
-			<artifactId>legacyworlds-web-beans</artifactId>
-		</dependency>
-
-		<dependency>
-			<groupId>org.freemarker</groupId>
-			<artifactId>freemarker</artifactId>
-			<scope>runtime</scope>
-		</dependency>
-
-		<dependency>
-			<groupId>com.thoughtworks.xstream</groupId>
-			<artifactId>xstream</artifactId>
-		</dependency>
-	</dependencies>
-
-	<build>
-		<plugins>
-			<plugin>
-				<groupId>org.apache.maven.plugins</groupId>
-				<artifactId>maven-war-plugin</artifactId>
-			</plugin>
-			<plugin>
-				<groupId>org.codehaus.mojo</groupId>
-				<artifactId>tomcat-maven-plugin</artifactId>
-				<configuration>
-					<path>/lwadmin</path>
-				</configuration>
-			</plugin>
-		</plugins>
-	</build>
-
-</project>
diff --git a/legacyworlds-web-admin/src/test/java/.empty b/legacyworlds-web-admin/src/test/java/.empty
deleted file mode 100644
index e69de29..0000000
diff --git a/legacyworlds-web-admin/src/test/resources/.empty b/legacyworlds-web-admin/src/test/resources/.empty
deleted file mode 100644
index e69de29..0000000
diff --git a/legacyworlds-web-beans/src/main/resources/.empty b/legacyworlds-web-beans/src/main/resources/.empty
deleted file mode 100644
index e69de29..0000000
diff --git a/legacyworlds-web-beans/src/test/java/.empty b/legacyworlds-web-beans/src/test/java/.empty
deleted file mode 100644
index e69de29..0000000
diff --git a/legacyworlds-web-beans/src/test/resources/.empty b/legacyworlds-web-beans/src/test/resources/.empty
deleted file mode 100644
index e69de29..0000000
diff --git a/legacyworlds-web-main/Content/Filtered/fm/version.ftl b/legacyworlds-web-main/Content/Filtered/fm/version.ftl
deleted file mode 100644
index c3974e0..0000000
--- a/legacyworlds-web-main/Content/Filtered/fm/version.ftl
+++ /dev/null
@@ -1,2 +0,0 @@
-<#macro version>${legacyworlds.version.string}</#macro>
-<#macro full_version>Beta 6 ${legacyworlds.version.string} (${legacyworlds.version.main}.${legacyworlds.version.release} b${legacyworlds.version.build})</#macro>
\ No newline at end of file
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/containers/game.ftl b/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/containers/game.ftl
deleted file mode 100644
index ce53339..0000000
--- a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/containers/game.ftl
+++ /dev/null
@@ -1,91 +0,0 @@
-<#include "../game.ftl">
-<#macro page title hidePlanets=false>
-<?xml version="1.0" encoding="utf-8"?>
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
-	<head>
-		<title>Legacy Worlds Beta 6 <@version/> - ${title?xhtml}</title>
-		<link rel="stylesheet" type="text/css" href="css/main.css" />
-		<script type="text/javascript" charset="utf-8" src="js/jquery-1.7.1.min.js"></script>
-		<script type="text/javascript" charset="utf-8" src="js/main.js"></script>
-	</head>
-	<body>
-		<!-- Header -->
-		<div id="hd-top">
-			<div id="hd-logo">
-				<a href="home" title="Legacy Worlds home page"><span>Legacy Worlds Beta 6 <@version/></span></a>
-			</div>
-			<div id="hd-bar">
-				<div id="hd-summary">
-					<strong>${data.page.empire}</strong>
-					<#if data.page.alliance?has_content>
-						[<strong>${data.page.alliance}</strong>]
-					</#if><br/>
-					<span id="gi-cash">${data.page.cash?string(",##0")}</span> <@abbr_bgc/><br/>
-					<#if data.page.special?has_content>
-						<span class="special-info">
-							<#switch data.page.special>
-								<#case 'v'>ON VACATION<#break>
-								<#case 's'>ENTERING VACATION<#break>
-								<#case 'q'>QUITTING<#break>
-							</#switch>
-						</span>
-					</#if>
-					<br/>
-					<a href="account">Account</a> - <a href="logout.action">Log out</a>
-				</div>
-				<div id="hd-page">
-					<h1>${title?xhtml}</h1>
-				</div>
-			</div>
-			<div id="hd-text"><@abbr_gt/>: <@game_time record=data.page.gameTime /> / <@abbr_st/>: ${data.page.serverTime?string("yyyy-MM-dd HH:mm:ss ZZZZZ")}</div>
-		</div>
-		<div id="menu-left">
-			<div class="button">
-				<a href="planets" title="Planets">Planets</a>
-			</div>
-			<#if !hidePlanets>
-				<#if data.page.planets?size == 0>
-					<div class="button sub-menu">
-						<a href="get-planet">Get new planet</a>
-					</div>
-				<#else>
-					<#list data.page.planets as planet>
-						<div class="button sub-menu">
-							<a href="planet-${planet.id}">${planet.name?xhtml}</a>
-						</div>
-					</#list>
-				</#if>
-			</#if>
-			<div class="button">
-				<a href="fleets" title="Fleets">Fleets</a>
-			</div>
-			<div class="button">
-				<a href="map" title="Map of the universe">Map</a>
-			</div>
-			<div class="button">
-				<a href="research" title="Manage research priorities, implement new technologies and browse known technologies">Research</a>
-			</div>
-			<div class="button">
-				<a href="alliance" title="Alliance">Alliance</a>
-			</div>
-			<div class="button">
-				<a href="enemies" title="Manage enemy players and alliances">Enemy list</a>
-			</div>
-			<div class="button">
-				<a href="messages" title="Messages">Messages</a>
-			</div>
-			<div class="button">
-				<a href="bugtrack" title="Bug tracking application">Bug tracker</a>
-			</div>
-		</div>
-
-		<div id="page-contents"><#nested></div>
-
-		<div id="footer">
-			Copyright (C) 2004-2012,
-			<a title="DeepClone Development" href="http://www.deepclone.com">DeepClone Development</a>
-		</div>
-	</body>
-</html>
-</#macro>
\ No newline at end of file
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/containers/offline.ftl b/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/containers/offline.ftl
deleted file mode 100644
index 9f11354..0000000
--- a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/containers/offline.ftl
+++ /dev/null
@@ -1,39 +0,0 @@
-<#macro page title>
-<?xml version="1.0" encoding="utf-8"?>
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
-	<head>
-		<title>Legacy Worlds Beta 6 <@version/> - ${title?xhtml}</title>
-		<link rel="stylesheet" type="text/css" href="css/main.css" />
-		<script type="text/javascript" charset="utf-8" src="js/jquery-1.7.1.min.js"></script>
-		<script type="text/javascript" charset="utf-8" src="js/main.js"></script>
-	</head>
-	<body>
-		<!-- Header -->
-		<div id="hd-top">
-			<div id="hd-logo">
-				<a href="home" title="Legacy Worlds home page"><span>Legacy Worlds Beta 6 <@version/></span></a>
-			</div>
-			<div id="hd-bar">
-				<div id="hd-summary" />
-				<div id="hd-page">
-					<h1>${title?xhtml}</h1>
-				</div>
-			</div>
-			<div id="hd-text">current version: <@full_version/></div>
-		</div>
-		<div id="menu-left">
-			<div class="button">
-				<a href="?" title="Try again">Retry</a>
-			</div>
-		</div>
-
-		<div id="page-contents"><#nested></div>
-
-		<div id="footer">
-			Copyright (C) 2004-2012,
-			<a title="DeepClone Development" href="http://www.deepclone.com">DeepClone Development</a>
-		</div>
-	</body>
-</html>
-</#macro>
\ No newline at end of file
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/containers/restricted.ftl b/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/containers/restricted.ftl
deleted file mode 100644
index b3677e5..0000000
--- a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/containers/restricted.ftl
+++ /dev/null
@@ -1,39 +0,0 @@
-<#macro page title>
-<?xml version="1.0" encoding="utf-8"?>
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
-	<head>
-		<title>Legacy Worlds Beta 6 <@version/> - ${title?xhtml}</title>
-		<link rel="stylesheet" type="text/css" href="css/main.css" />
-		<script type="text/javascript" charset="utf-8" src="js/jquery-1.7.1.min.js"></script>
-		<script type="text/javascript" charset="utf-8" src="js/main.js"></script>
-	</head>
-	<body>
-		<!-- Header -->
-		<div id="hd-top">
-			<div id="hd-logo">
-				<a href="home" title="Legacy Worlds home page"><span>Legacy Worlds Beta 6 <@version/></span></a>
-			</div>
-			<div id="hd-bar">
-				<div id="hd-summary" />
-				<div id="hd-page">
-					<h1>${title?xhtml}</h1>
-				</div>
-			</div>
-			<div id="hd-text">current version: <@full_version/></div>
-		</div>
-		<div id="menu-left">
-			<div class="button">
-				<a href="logout.action" title="Log out">Log out</a>
-			</div>
-		</div>
-
-		<div id="page-contents"><#nested></div>
-
-		<div id="footer">
-			Copyright (C) 2004-2012,
-			<a title="DeepClone Development" href="http://www.deepclone.com">DeepClone Development</a>
-		</div>
-	</body>
-</html>
-</#macro>
\ No newline at end of file
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/overview/resources.ftl b/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/overview/resources.ftl
deleted file mode 100644
index 7206f92..0000000
--- a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/overview/resources.ftl
+++ /dev/null
@@ -1,64 +0,0 @@
-<#macro overviewResources>
-<form action="update-mining-settings.action" method="POST"><@listview>
-	<@lv_line headers=true>
-		<@lv_column width=30>&nbsp;</@lv_column>
-		<@lv_column width="x">Resource</@lv_column>
-		<@lv_column width=100 centered=true><@over_time "Income" /></@lv_column>
-		<@lv_column width=100 centered=true><@over_time "Upkeep" /></@lv_column>
-		<@lv_column width=100 centered=true>Reserves</@lv_column>
-		<@lv_column width=100 centered=true>Mining priority</@lv_column>
-	</@lv_line>
-		
-	<#list ov.economy as resource>
-
-		<#if previousCategory?has_content && !resource.category?has_content
-				|| resource.category?has_content && !previousCategory?has_content
-				|| resource.category?has_content && previousCategory?has_content
-					&& resource.category != previousCategory>
-			<@lv_line>
-				<#if resource.category?has_content>
-					<td colspan="5"><strong>${resource.category?xhtml}</strong></td>
-				<#else>
-					<td colspan="5"><hr /></td>
-				</#if>
-			</@lv_line>
-			<#local previousCategory=resource.category>
-		</#if>
-		
-		<@lv_line>
-			<@lv_column>&nbsp;</@lv_column>
-			<@lv_column>${resource.title?xhtml}
-				<div class="auto-hide">${resource.description?xhtml}</div>
-			</@lv_column>
-			<@lv_column centered=true>${resource.income?string(",##0")}</@lv_column>
-			<@lv_column centered=true>${resource.upkeep?string(",##0")}</@lv_column>
-			<@lv_column centered=true>${resource.stockpiled?string(",##0")}</@lv_column>
-			<@lv_column centered=true>
-				<#if resource.miningPriority?has_content>
-					<select name="ems-${resource.identifier?xhtml}" class="input">
-						<option style="padding: 0 5px" value="0" <#if resource.miningPriority = 0>selected="selected"</#if>>lowest</option>
-						<option style="padding: 0 5px" value="1" <#if resource.miningPriority = 1>selected="selected"</#if>>low</option>
-						<option style="padding: 0 5px" value="2" <#if resource.miningPriority = 2>selected="selected"</#if>>normal</option>
-						<option style="padding: 0 5px" value="3" <#if resource.miningPriority = 3>selected="selected"</#if>>high</option>
-						<option style="padding: 0 5px" value="4" <#if resource.miningPriority = 4>selected="selected"</#if>>highest</option>
-					</select>
-				<#else>
-					N/A
-				</#if>
-			</@lv_column>
-		</@lv_line>
-
-	</#list>
-	
-	<@lv_line headers=true>
-		<@lv_column width="x" colspan=6>&nbsp;</@lv_column>
-	</@lv_line>
-	<@lv_line>
-		<@lv_column colspan=4>&nbsp;</@lv_column>
-		<@lv_column right=true colspan=2>
-			<input type="submit" value="Update mining priorities" class="input" style="margin: 15px 0 0 0" />
-		</@lv_column>
-	</@lv_line>
-
-</@listview></form>
-</#macro>
\ No newline at end of file
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/planet/natres.ftl b/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/planet/natres.ftl
deleted file mode 100644
index 001a30d..0000000
--- a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/planet/natres.ftl
+++ /dev/null
@@ -1,80 +0,0 @@
-<#macro RenderNaturalResources>			
-	<#list data.own.resources as resource>
-		<#if resource.resourceProvider?has_content>
-			<#local showResources=true>
-			<#break>
-		</#if>
-	</#list>
-	
-	<#if showResources?has_content>
-		<@tab id="natres" title="Natural resources">
-			<form action="planet-${data.id}-update-mset.action" method="POST">
-
-				<@listview>
-					<@lv_line headers=true>
-						<@lv_column width="x">Resource</@lv_column>
-						<@lv_column width=100 right=true>Quantity&nbsp;</@lv_column>
-						<@lv_column width=100>&nbsp;&nbsp;Capacity</@lv_column>
-						<@lv_column width=100 centered=true>Extraction<br/>difficulty</@lv_column>
-						<@lv_column width=100 centered=true>Priority</@lv_column>
-					</@lv_line>
-					
-					<#list data.own.resources as resource>
-						<#if resource.resourceProvider?has_content>
-							<#local resProv=resource.resourceProvider>
-		
-							<@lv_line>
-								<@lv_column>
-									${resource.title?xhtml}
-									<div class="auto-hide">${resource.description?xhtml}</div>
-								</@lv_column>
-								<@lv_column right=true>${resProv.quantity?string(",##0")}&nbsp;</@lv_column>
-								<@lv_column>/&nbsp;${resProv.capacity?string(",##0")}</@lv_column>
-								<@lv_column centered=true>${resProv.difficulty}&nbsp;%</@lv_column>
-								<@lv_column centered=true>
-									<#if data.own.ownMiningSettings>
-										<select name="pms-${resource.identifier?xhtml}" class="input">
-											<option style="padding: 0 5px" value="0" <#if resProv.priority = 0>selected="selected"</#if>>lowest</option>
-											<option style="padding: 0 5px" value="1" <#if resProv.priority = 1>selected="selected"</#if>>low</option>
-											<option style="padding: 0 5px" value="2" <#if resProv.priority = 2>selected="selected"</#if>>normal</option>
-											<option style="padding: 0 5px" value="3" <#if resProv.priority = 3>selected="selected"</#if>>high</option>
-											<option style="padding: 0 5px" value="4" <#if resProv.priority = 4>selected="selected"</#if>>highest</option>
-										</select>
-									<#else>
-										<#switch resProv.priority>
-											<#case 0>lowest<#break>
-											<#case 1>low<#break>
-											<#case 2>normal<#break>
-											<#case 3>high<#break>
-											<#case 4>highest<#break>
-										</#switch>
-									</#if>
-								</@lv_column>
-							</@lv_line>
-		
-						</#if>
-					</#list>
-					
-					<@lv_line headers=true>
-						<@lv_column width="x" colspan=5>&nbsp;</@lv_column>
-					</@lv_line>
-					<@lv_line>
-						<@lv_column right=true colspan=5>
-							<#if data.own.ownMiningSettings>
-								This planet follows planet-specific mining priorities.
-								<input type="submit" name="toggle-settings" value="Use empire priorities" class="input" style="margin: 15px 0 0 0" />
-								<input type="submit" name="update-pms" value="Update priorities" class="input" style="margin: 15px 0 0 0" />
-							<#else>
-								This planet follows empire-wide mining priorities.
-								<input type="submit" name="toggle-settings" value="Use specific priorities" class="input" style="margin: 15px 0 0 0" />
-							</#if>
-						</@lv_column>
-					</@lv_line>
-
-				</@listview>
-
-			</form>
-
-		</@tab>
-	</#if>
-</#macro>
\ No newline at end of file
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/planets/economy.ftl b/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/planets/economy.ftl
deleted file mode 100644
index 58f20ee..0000000
--- a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/planets/economy.ftl
+++ /dev/null
@@ -1,56 +0,0 @@
-<#macro RenderEconomy>			
-	<@tab id="economy" title="Economy"> 
-		<@listview>
-			<@lv_line headers=true>
-				<@lv_column width="x">Name</@lv_column>
-				<@lv_column width="x">Resource</@lv_column>
-				<@lv_column width=110 right=true>Income</@lv_column>
-				<@lv_column width=110 right=true>Upkeep</@lv_column>
-				<@lv_column width=110 right=true>Profit</@lv_column>
-			</@lv_line>
-
-			<#list pl as planet>
-				<#if planet.resources?size = 0>
-					<@lv_line>
-						<@lv_column><a href="planet-${planet.id}#resources">${planet.name?xhtml}</a></@lv_column>
-						<@lv_column colspan=4 centered=true><em>No income or upkeep</em></@lv_column>
-					</@lv_line>
-				<#else>
-					<#list planet.resources as resource>
-						<@lv_line>
-							<@lv_column>
-								<#if resource_index = 0>
-									<a href="planet-${planet.id}#resources">${planet.name?xhtml}</a>
-								<#else>
-									&nbsp;
-								</#if>
-							</@lv_column>
-							<@lv_column>${resource.name?xhtml}</@lv_column>
-							<@lv_column right=true>${resource.income?string(",##0")}</@lv_column>
-							<@lv_column right=true>${resource.upkeep?string(",##0")}</@lv_column>
-							<@lv_column right=true>
-								<#if resource.upkeep gt resource.income>
-									<span style="color: red">
-								</#if>
-								${( resource.income - resource.upkeep )?string(",##0")}
-								<#if resource.upkeep gt resource.income>
-									</span>
-								</#if>
-							</@lv_column>
-						</@lv_line>
-					</#list>
-				</#if>
-			</#list>
-
-			<@lv_line headers=true>
-				<@lv_column width="x" colspan=6>&nbsp;</@lv_column>
-			</@lv_line>
-			<@lv_line>
-				<@lv_column centered=true colspan=6>
-					Incomes, upkeeps and profits are displayed for a period of one game month (12 actual hours).
-				</@lv_column>
-			</@lv_line>
-
-		</@listview>
-	</@tab>
-</#macro>
\ No newline at end of file
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/research.ftl b/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/research.ftl
deleted file mode 100644
index ce4a1ba..0000000
--- a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/research.ftl
+++ /dev/null
@@ -1,264 +0,0 @@
-<#--
-	Macro that starts a research tab for one of the 3 existing modes
-	
-	Parameters:
-		curMode		The tab to start: R for "in progress", P for pending, K for implemented
- -->
-<#macro startResearchTab curMode>
-	<#switch curMode>
-
-		<#case 'R'>
-			<@tabStart "research" "In progress" />
-			<@rawFormStart "research-set-priorities" "form-priorities" "research" />
-			<@listviewStart />
-			<@lv_line headers=true>
-				<@lv_column width=150>Category</@lv_column>
-				<@lv_column width="x">Name</@lv_column>
-				<@lv_column width=100 centered=true>Progress</@lv_column>
-				<@lv_column width=150 centered=true>Priority</@lv_column>
-			</@lv_line>
-			<#break>
-
-		<#case 'P'>
-			<@tabStart "pending" "Pending implementation" />
-			<@listviewStart />
-			<@lv_line headers=true>
-				<@lv_column width=150>Category</@lv_column>
-				<@lv_column width="x">Name</@lv_column>
-				<@lv_column width=150 right=true>Cost</@lv_column>
-				<@lv_column width=100 centered=true>&nbsp;</@lv_column>
-			</@lv_line>
-			<#break>
-
-		<#case 'K'>
-			<@tabStart "implemented" "Implemented" />
-			<@listviewStart />
-			<@lv_line headers=true>
-				<@lv_column width=150>Category</@lv_column>
-				<@lv_column width="x">Name</@lv_column>
-			</@lv_line>
-			<#break> 
-
-	</#switch>
-</#macro>
-<#--
-	Macro that finishes a research tab depending on its type
-	
-	Parameters:
-		mode		The type of tab that is being closed
-  -->
-<#macro endResearchTab mode>
-	<#switch mode>
-
-		<#case 'R'>
-			<@lv_line headers=true>
-				<@lv_column width="x" colspan=4>&nbsp;</@lv_column>
-			</@lv_line>
-			<@lv_line>
-				<@lv_column colspan=3>&nbsp;</@lv_column>
-				<@lv_column centered=true>
-					<input type="submit" value="Update" class="input" style="margin: 15px 0 0 0" />
-				</@lv_column>
-			</@lv_line>
-			<@listviewEnd />
-			</form>
-			<#break>
-
-		<#case 'P'>
-		<#case 'K'>
-			<@listviewEnd />
-			<#break>
-
-	</#switch>
-	<@tabEnd />
-</#macro>
-<#--
-	Macro that renders an in-progress research entry
-	
-	Parameters:
-		entry		the entry
--->
-<#macro drawInProgressResearch entry>
-	<@lv_line id="tl-${entry.identifier?xhtml}" class="tech-line">
-		<@lv_column>${entry.category?xhtml}</@lv_column>
-		<@lv_column>
-			<#if entry.name?has_content>
-				<strong>${entry.name?xhtml}</strong>
-			<#else>
-				Unknown technology
-			</#if>
-		</@lv_column>
-		<@lv_column centered=true>${entry.completion} %</@lv_column>
-		<@lv_column centered=true>
-			<select name="rp-${entry.identifier?xhtml}" class="input">
-				<option style="padding: 0 5px" value="0" <#if entry.priority = 0>selected="selected"</#if>>lowest</option>
-				<option style="padding: 0 5px" value="1" <#if entry.priority = 1>selected="selected"</#if>>low</option>
-				<option style="padding: 0 5px" value="2" <#if entry.priority = 2>selected="selected"</#if>>normal</option>
-				<option style="padding: 0 5px" value="3" <#if entry.priority = 3>selected="selected"</#if>>high</option>
-				<option style="padding: 0 5px" value="4" <#if entry.priority = 4>selected="selected"</#if>>highest</option>
-			</select>
-		</@lv_column>
-	</@lv_line>
-</#macro>
-<#--
-	Macro that renders a pending technology
-	
-	Parameters:
-		entry		the technology
--->
-<#macro drawPendingTechnology entry>
-	<@lv_line id="tl-${entry.identifier?xhtml}" class="tech-line">
-		<@lv_column>${entry.category?xhtml}</@lv_column>
-		<@lv_column>
-			<strong>${entry.name?xhtml}</strong>
-		</@lv_column>
-		<@lv_column right=true>
-			<strong>${entry.price?string(",##0")}</strong> <@abbr_bgc/>
-		</@lv_column>
-		<@lv_column right=true>
-			<#if data.page.cash &gt;= entry.price>
-				<@rawFormStart "research-implement" "form-implement-${entry.identifier}" entry.identifier />
-					<input type="hidden" name="technology" value="${entry.identifier?xhtml}" />
-					<input type="submit" value="Implement" class="input" />
-				</form>
-			<#else>
-				&nbsp;
-			</#if>
-		</@lv_column>
-	</@lv_line>
-</#macro>
-<#--
-	Macro that renders an implemented technology
-	
-	Parameters:
-		entry		the technology
--->
-<#macro drawImplementedTechnology entry>
-	<@lv_line id="tl-${entry.identifier?xhtml}" class="tech-line">
-		<@lv_column>${entry.category?xhtml}</@lv_column>
-		<@lv_column>
-			<strong>${entry.name?xhtml}</strong>
-		</@lv_column>
-	</@lv_line>
-</#macro>
-<#--
-	Macro that renders a single entry
-	
-	Parameters:
-		mode		the current tab (see startResearchTab for details)
-		entry		the entry
--->
-<#macro drawResearchEntry mode entry>
-	<#switch mode>
-
-		<#case 'R'>
-			<@drawInProgressResearch entry />
-			<#break>
-
-		<#case 'P'>
-			<@drawPendingTechnology entry />
-			<#break>
-
-		<#case 'K'>
-			<@drawImplementedTechnology entry />
-			<#break>
- 
-	</#switch>
-</#macro>
-<#--
-	Render the visible part of the research page
-	
-	Parameters:
-		entries		the sorted list of research entries 
-  -->
-<#macro renderResearchTabs entries>
-	<#local prevMode = ''>
-
-	<@tabs>
-		<#list entries as entry>
-
-			<#-- Determine type of entry to display -->
-			<#if entry.implemented?has_content>
-				<#if entry.implemented>
-					<#local curMode = 'K'>
-				<#else>
-					<#local curMode = 'P'>
-				</#if>
-			<#else>
-				<#local curMode = 'R'>
-			</#if>
-
-			<#-- Start/end tabs -->
-			<#if curMode != prevMode>
-				<#if prevMode != ''>
-					<@endResearchTab prevMode />
-				</#if>
-				<@startResearchTab curMode />
-				<#local prevMode = curMode>
-			</#if>
-			
-			
-			<@drawResearchEntry curMode entry />
-	
-		</#list>
-		<@endResearchTab prevMode />
-	</@tabs>
-</#macro>
-<#--
-	Render all research information in a hidden layer which will be used by
-	the client-side code to display more information.
-  -->
-<#macro renderFullResearchData entries>
-	<div style="display: none">
-		<#list entries as tech>
-			<div class="tech-description" id="tdesc-${tech.identifier?xhtml}">
-				<h4><#if tech.name?has_content>${tech.name?xhtml}<#else>Unknown technology</#if></h4>
-				<div class="tech-info"><strong>Category:</strong> ${tech.category?xhtml}</div>
-				<#if tech.description?has_content><div class="tech-info">${tech.description?xhtml}</div></#if>
-				<#if tech.price?has_content>
-					<div class="tech-info"><strong>Implementation cost:</strong> ${tech.price?string(",##0")} <@abbr_bgc /></div>
-				</#if>
-				<#if tech.dependencies?has_content>
-					<div class="tech-info"><strong>Depends on:</strong>
-						<ul>
-							<#list tech.dependencies as depId>
-								<li class="dep">${depId}</li>
-							</#list>
-						</ul>
-					</div>
-				</#if>
-				<#if tech.reverseDependencies?has_content>
-					<div class="tech-info"><strong>Required by:</strong>
-						<ul>
-							<#list tech.reverseDependencies as depId>
-								<li class="dep">${depId}</li>
-							</#list>
-						</ul>
-					</div>
-				</#if>
-				<#if tech.buildings?has_content>
-					<div class="tech-info"><strong>Unlocks buildings:</strong>
-						<ul>
-							<#list tech.buildings as building>
-								<li>${building}</li>
-							</#list>
-						</ul>
-					</div>
-				</#if>
-			</div>
-		</#list>
-	</div>
-	<script type="text/javascript" charset="utf-8" src="js/research.js"></script>
-</#macro>
-<#--
-	Main research page
-  -->
-<#macro render>
-<@page title="Research">
-
-	<#local entries = data.researchData>
-	<@renderResearchTabs entries />
-	<@renderFullResearchData entries />
-
-</@page>
-</#macro>
\ No newline at end of file
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/containers/external.ftl b/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/containers/external.ftl
deleted file mode 100644
index 9e9a0e8..0000000
--- a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/containers/external.ftl
+++ /dev/null
@@ -1,61 +0,0 @@
-<#macro page title>
-<?xml version="1.0" encoding="utf-8"?>
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr">
-	<head>
-		<title>Legacy Worlds Beta 6 <@version/> - ${title?xhtml}</title>
-		<link rel="stylesheet" type="text/css" href="css/main.css" />
-		<script type="text/javascript" charset="utf-8" src="js/jquery-1.7.1.min.js"></script>
-		<script type="text/javascript" charset="utf-8" src="js/main.js"></script>
-	</head>
-	<body>
-		<!-- Header -->
-		<div id="hd-top">
-			<div id="hd-logo">
-				<a href="home" title="Page d'accueil de Legacy Worlds"><span>Legacy Worlds Beta 6 <@version/></span></a>
-			</div>
-			
-			<!-- Title / login bar -->
-			<div id="hd-bar">
-				<div id="hd-summary">
-					<form method="post" action="login.action">
-						<div>
-							Adresse e-mail : <input type="text" name="mail" value="" size="15" maxlength="128" class='input' /><br/>
-							Mot de passe : <input type="password" name="password" value='' size="15" maxlength="128" class='input' /><br/>
-							<a title="Récupération de mot de passe" href="password-recovery">Mot de passe oublié ?</a>
-							<input type="submit" value='Connexion' class='input' />
-						</div>
-					</form>
-				</div>
-				<div id="hd-page">
-					<h1>${title?xhtml}</h1>
-				</div>
-			</div>
-			<div id="hd-text">version courante : <@full_version/></div>
-		</div>
-
-		<!-- Menu
-		   -
-		   - FIXME: set "current" style on button for the current page
-		  -->
-		<div id="menu-left">
-			<div class="button">
-				<a href="scope" title="Portée de ce jalon">Portée</a>
-			</div>
-			<div class="button">
-				<a href="rules" title="Règles du jeu">Règles</a>
-			</div>
-			<div class="button">
-				<a href="register" title="Inscription">Inscription</a>
-			</div>
-		</div>
-
-		<div id="page-contents"><#nested></div>
-
-		<div id="footer">
-			Copyright (C) 2004-2012,
-			<a title="DeepClone Development" href="http://www.deepclone.com">DeepClone Development</a>
-		</div>
-	</body>
-</html>
-</#macro>
\ No newline at end of file
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/containers/game.ftl b/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/containers/game.ftl
deleted file mode 100644
index 3568606..0000000
--- a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/containers/game.ftl
+++ /dev/null
@@ -1,91 +0,0 @@
-<#include "../game.ftl">
-<#macro page title hidePlanets=false>
-<?xml version="1.0" encoding="utf-8"?>
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr">
-	<head>
-		<title>Legacy Worlds Beta 6 <@version/> - ${title?xhtml}</title>
-		<link rel="stylesheet" type="text/css" href="css/main.css" />
-		<script type="text/javascript" charset="utf-8" src="js/jquery-1.7.1.min.js"></script>
-		<script type="text/javascript" charset="utf-8" src="js/main.js"></script>
-	</head>
-	<body>
-		<!-- Header -->
-		<div id="hd-top">
-			<div id="hd-logo">
-				<a href="overview" title="Page Empire"><span>Legacy Worlds Beta 6 <@version/></span></a>
-			</div>
-			<div id="hd-bar">
-				<div id="hd-summary">
-					<strong>${data.page.empire}</strong>
-					<#if data.page.alliance?has_content>
-						[<strong>${data.page.alliance}</strong>]
-					</#if><br/>
-					<span id="gi-cash">${data.page.cash?string(",##0")}</span> <@abbr_bgc/><br/>
-					<#if data.page.special?has_content>
-						<span class="special-info">
-							<#switch data.page.special>
-								<#case 'v'>EN VACANCES<#break>
-								<#case 's'>PRELIMINAIRES AUX VACANCES<#break>
-								<#case 'q'>EN TRAIN D'ABANDONNER<#break>
-							</#switch>
-						</span>
-					</#if>
-					<br/>
-					<a href="account">Compte</a> - <a href="logout.action">Déconnexion</a>
-				</div>
-				<div id="hd-page">
-					<h1>${title?xhtml}</h1>
-				</div>
-			</div>
-			<div id="hd-text"><@abbr_gt/>: <@game_time record=data.page.gameTime /> / <@abbr_st/>: ${data.page.serverTime?string("yyyy-MM-dd HH:mm:ss ZZZZZ")}</div>
-		</div>
-		<div id="menu-left">
-			<div class="button">
-				<a href="planets" title="Planètes">Planètes</a>
-			</div>
-			<#if !hidePlanets>
-				<#if data.page.planets?size == 0>
-					<div class="button sub-menu">
-						<a href="get-planet" title="Obtenir une nouvelle planète">Nouvelle planète</a>
-					</div>
-				<#else>
-					<#list data.page.planets as planet>
-						<div class="button sub-menu">
-							<a href="planet-${planet.id}">${planet.name?xhtml}</a>
-						</div>
-					</#list>
-				</#if>
-			</#if>
-			<div class="button">
-				<a href="fleets" title="Flottes">Flottes</a>
-			</div>
-			<div class="button">
-				<a href="map" title="Carte de l'univers">Carte</a>
-			</div>
-			<div class="button">
-				<a href="research" title="Gestion des priorités de recherche, implémentation et visualisation de technologies">Recherche</a>
-			</div>
-			<div class="button">
-				<a href="alliance" title="Alliance">Alliance</a>
-			</div>
-			<div class="button">
-				<a href="enemies" title="Gestion des listes de joueurs et alliances ennemis">Listes d'ennemis</a>
-			</div>
-			<div class="button">
-				<a href="messages" title="Messages">Messages</a>
-			</div>
-			<div class="button">
-				<a href="bugtrack" title="Application de suivi des bugs">Suivi des bugs</a>
-			</div>
-		</div>
-
-		<div id="page-contents"><#nested></div>
-
-		<div id="footer">
-			Copyright (C) 2004-2012,
-			<a title="DeepClone Development" href="http://www.deepclone.com">DeepClone Development</a>
-		</div>
-	</body>
-</html>
-</#macro>
\ No newline at end of file
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/containers/offline.ftl b/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/containers/offline.ftl
deleted file mode 100644
index 115707c..0000000
--- a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/containers/offline.ftl
+++ /dev/null
@@ -1,39 +0,0 @@
-<#macro page title>
-<?xml version="1.0" encoding="utf-8"?>
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr">
-	<head>
-		<title>Legacy Worlds Beta 6 <@version/> - ${title?xhtml}</title>
-		<link rel="stylesheet" type="text/css" href="css/main.css" />
-		<script type="text/javascript" charset="utf-8" src="js/jquery-1.7.1.min.js"></script>
-		<script type="text/javascript" charset="utf-8" src="js/main.js"></script>
-	</head>
-	<body>
-		<!-- Header -->
-		<div id="hd-top">
-			<div id="hd-logo">
-				<a href="home" title="Page d'accueil de Legacy Worlds"><span>Legacy Worlds Beta 6 <@version/></span></a>
-			</div>
-			<div id="hd-bar">
-				<div id="hd-summary" />
-				<div id="hd-page">
-					<h1>${title?xhtml}</h1>
-				</div>
-			</div>
-			<div id="hd-text">version courante : <@full_version/></div>
-		</div>
-		<div id="menu-left">
-			<div class="button">
-				<a href="?">Réessayer</a>
-			</div>
-		</div>
-
-		<div id="page-contents"><#nested></div>
-
-		<div id="footer">
-			Copyright (C) 2004-2012,
-			<a title="DeepClone Development" href="http://www.deepclone.com">DeepClone Development</a>
-		</div>
-	</body>
-</html>
-</#macro>
\ No newline at end of file
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/containers/restricted.ftl b/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/containers/restricted.ftl
deleted file mode 100644
index 7bdb362..0000000
--- a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/containers/restricted.ftl
+++ /dev/null
@@ -1,39 +0,0 @@
-<#macro page title>
-<?xml version="1.0" encoding="utf-8"?>
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
-	<head>
-		<title>Legacy Worlds Beta 6 <@version/> - ${title?xhtml}</title>
-		<link rel="stylesheet" type="text/css" href="css/main.css" />
-		<script type="text/javascript" charset="utf-8" src="js/jquery-1.7.1.min.js"></script>
-		<script type="text/javascript" charset="utf-8" src="js/main.js"></script>
-	</head>
-	<body>
-		<!-- Header -->
-		<div id="hd-top">
-			<div id="hd-logo">
-				<a href="home" title="Page d'accueil de Legacy Worlds"><span>Legacy Worlds Beta 6 <@version/></span></a>
-			</div>
-			<div id="hd-bar">
-				<div id="hd-summary" />
-				<div id="hd-page">
-					<h1>${title?xhtml}</h1>
-				</div>
-			</div>
-			<div id="hd-text">version courante : <@full_version/></div>
-		</div>
-		<div id="menu-left">
-			<div class="button">
-				<a href="logout.action" title="Déconnexion">Déconnexion</a>
-			</div>
-		</div>
-
-		<div id="page-contents"><#nested></div>
-
-		<div id="footer">
-			Copyright (C) 2004-2012,
-			<a title="DeepClone Development" href="http://www.deepclone.com">DeepClone Development</a>
-		</div>
-	</body>
-</html>
-</#macro>
\ No newline at end of file
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/overview/resources.ftl b/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/overview/resources.ftl
deleted file mode 100644
index fd0a77f..0000000
--- a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/overview/resources.ftl
+++ /dev/null
@@ -1,64 +0,0 @@
-<#macro overviewResources>
-<form action="update-mining-settings.action" method="POST"><@listview>
-	<@lv_line headers=true>
-		<@lv_column width=30>&nbsp;</@lv_column>
-		<@lv_column width="x">Ressource</@lv_column>
-		<@lv_column width=100 centered=true><@over_time "Bénéfice" /></@lv_column>
-		<@lv_column width=100 centered=true><@over_time title="Charges" feminin=true pluriel=true /></@lv_column>
-		<@lv_column width=100 centered=true>Réserves</@lv_column>
-		<@lv_column width=100 centered=true>Priorité d'extraction</@lv_column>
-	</@lv_line>
-		
-	<#list ov.economy as resource>
-
-		<#if previousCategory?has_content && !resource.category?has_content
-				|| resource.category?has_content && !previousCategory?has_content
-				|| resource.category?has_content && previousCategory?has_content
-					&& resource.category != previousCategory>
-			<@lv_line>
-				<#if resource.category?has_content>
-					<td colspan="5"><strong>${resource.category?xhtml}</strong></td>
-				<#else>
-					<td colspan="5"><hr /></td>
-				</#if>
-			</@lv_line>
-			<#local previousCategory=resource.category>
-		</#if>
-		
-		<@lv_line>
-			<@lv_column>&nbsp;</@lv_column>
-			<@lv_column>${resource.title?xhtml}
-				<div class="auto-hide">${resource.description?xhtml}</div>
-			</@lv_column>
-			<@lv_column centered=true>${resource.income?string(",##0")}</@lv_column>
-			<@lv_column centered=true>${resource.upkeep?string(",##0")}</@lv_column>
-			<@lv_column centered=true>${resource.stockpiled?string(",##0")}</@lv_column>
-			<@lv_column centered=true>
-				<#if resource.miningPriority?has_content>
-					<select name="ems-${resource.identifier?xhtml}" class="input">
-						<option style="padding: 0 5px" value="0" <#if resource.miningPriority = 0>selected="selected"</#if>>très basse</option>
-						<option style="padding: 0 5px" value="1" <#if resource.miningPriority = 1>selected="selected"</#if>>basse</option>
-						<option style="padding: 0 5px" value="2" <#if resource.miningPriority = 2>selected="selected"</#if>>normale</option>
-						<option style="padding: 0 5px" value="3" <#if resource.miningPriority = 3>selected="selected"</#if>>haute</option>
-						<option style="padding: 0 5px" value="4" <#if resource.miningPriority = 4>selected="selected"</#if>>très haute</option>
-					</select>
-				<#else>
-					N/A
-				</#if>
-			</@lv_column>
-		</@lv_line>
-
-	</#list>
-	
-	<@lv_line headers=true>
-		<@lv_column width="x" colspan=6>&nbsp;</@lv_column>
-	</@lv_line>
-	<@lv_line>
-		<@lv_column colspan=4>&nbsp;</@lv_column>
-		<@lv_column right=true colspan=2>
-			<input type="submit" value="Modifier les priorités" class="input" style="margin: 15px 0 0 0" />
-		</@lv_column>
-	</@lv_line>
-
-</@listview></form>
-</#macro>
\ No newline at end of file
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/planet/natres.ftl b/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/planet/natres.ftl
deleted file mode 100644
index 2f30d41..0000000
--- a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/planet/natres.ftl
+++ /dev/null
@@ -1,80 +0,0 @@
-<#macro RenderNaturalResources>			
-	<#list data.own.resources as resource>
-		<#if resource.resourceProvider?has_content>
-			<#local showResources=true>
-			<#break>
-		</#if>
-	</#list>
-	
-	<#if showResources?has_content>
-				<@tab id="natres" title="Ressources naturelles">
-			<form action="planet-${data.id}-update-mset.action" method="POST">
-
-				<@listview>
-					<@lv_line headers=true>
-						<@lv_column width="x">Ressource</@lv_column>
-						<@lv_column width=100 right=true>Quantité&nbsp;</@lv_column>
-						<@lv_column width=100>&nbsp;&nbsp;Capacité</@lv_column>
-						<@lv_column width=100 centered=true>Difficulté<br/>d'extraction</@lv_column>
-						<@lv_column width=100 centered=true>Priorité</@lv_column>
-					</@lv_line>
-					
-					<#list data.own.resources as resource>
-						<#if resource.resourceProvider?has_content>
-							<#local resProv=resource.resourceProvider>
-		
-							<@lv_line>
-								<@lv_column>
-									${resource.title?xhtml}
-									<div class="auto-hide">${resource.description?xhtml}</div>
-								</@lv_column>
-								<@lv_column right=true>${resProv.quantity?string(",##0")}&nbsp;</@lv_column>
-								<@lv_column>/&nbsp;${resProv.capacity?string(",##0")}</@lv_column>
-								<@lv_column centered=true>${resProv.difficulty}&nbsp;%</@lv_column>
-								<@lv_column centered=true>
-									<#if data.own.ownMiningSettings>
-										<select name="pms-${resource.identifier?xhtml}" class="input">
-											<option style="padding: 0 5px" value="0" <#if resProv.priority = 0>selected="selected"</#if>>très basse</option>
-											<option style="padding: 0 5px" value="1" <#if resProv.priority = 1>selected="selected"</#if>>basse</option>
-											<option style="padding: 0 5px" value="2" <#if resProv.priority = 2>selected="selected"</#if>>normale</option>
-											<option style="padding: 0 5px" value="3" <#if resProv.priority = 3>selected="selected"</#if>>haute</option>
-											<option style="padding: 0 5px" value="4" <#if resProv.priority = 4>selected="selected"</#if>>très haute</option>
-										</select>
-									<#else>
-										<#switch resProv.priority>
-											<#case 0>très basse<#break>
-											<#case 1>basse<#break>
-											<#case 2>normale<#break>
-											<#case 3>haute<#break>
-											<#case 4>très haute<#break>
-										</#switch>
-									</#if>
-								</@lv_column>
-							</@lv_line>
-		
-						</#if>
-					</#list>
-					
-					<@lv_line headers=true>
-						<@lv_column width="x" colspan=5>&nbsp;</@lv_column>
-					</@lv_line>
-					<@lv_line>
-						<@lv_column right=true colspan=5>
-							<#if data.own.ownMiningSettings>
-								Cette planète utilise des priorités d'extraction qui lui sont spécifiques.
-								<input type="submit" name="toggle-settings" value="Utiliser les priorités de l'empire" class="input" style="margin: 15px 0 0 0" />
-								<input type="submit" name="update-pms" value="Mettre à jour les priorités" class="input" style="margin: 15px 0 0 0" />
-							<#else>
-								Cette planète utilise les priorités d'extraction de l'empire.
-								<input type="submit" name="toggle-settings" value="Utiliser des priorités spécifiques" class="input" style="margin: 15px 0 0 0" />
-							</#if>
-						</@lv_column>
-					</@lv_line>
-
-				</@listview>
-
-			</form>
-
-		</@tab>
-	</#if>
-</#macro>
\ No newline at end of file
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/planets/economy.ftl b/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/planets/economy.ftl
deleted file mode 100644
index 695a8b6..0000000
--- a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/planets/economy.ftl
+++ /dev/null
@@ -1,56 +0,0 @@
-<#macro RenderEconomy>			
-	<@tab id="economy" title="Economie">
-		<@listview>
-			<@lv_line headers=true>
-				<@lv_column width="x">Name</@lv_column>
-				<@lv_column width="x">Resource</@lv_column>
-				<@lv_column width=110 right=true>Revenus</@lv_column>
-				<@lv_column width=110 right=true>Charges</@lv_column>
-				<@lv_column width=110 right=true>Bénéfices</@lv_column>
-			</@lv_line>
-
-			<#list pl as planet>
-				<#if planet.resources?size = 0>
-					<@lv_line>
-						<@lv_column><a href="planet-${planet.id}#resources">${planet.name?xhtml}</a></@lv_column>
-						<@lv_column colspan=4 centered=true><em>Aucune entrée pour cette planète</em></@lv_column>
-					</@lv_line>
-				<#else>
-					<#list planet.resources as resource>
-						<@lv_line>
-							<@lv_column>
-								<#if resource_index = 0>
-									<a href="planet-${planet.id}#resources">${planet.name?xhtml}</a>
-								<#else>
-									&nbsp;
-								</#if>
-							</@lv_column>
-							<@lv_column>${resource.name?xhtml}</@lv_column>
-							<@lv_column right=true>${resource.income?string(",##0")}</@lv_column>
-							<@lv_column right=true>${resource.upkeep?string(",##0")}</@lv_column>
-							<@lv_column right=true>
-								<#if resource.upkeep gt resource.income>
-									<span style="color: red">
-								</#if>
-								${( resource.income - resource.upkeep )?string(",##0")}
-								<#if resource.upkeep gt resource.income>
-									</span>
-								</#if>
-							</@lv_column>
-						</@lv_line>
-					</#list>
-				</#if>
-			</#list>
-
-			<@lv_line headers=true>
-				<@lv_column width="x" colspan=6>&nbsp;</@lv_column>
-			</@lv_line>
-			<@lv_line>
-				<@lv_column centered=true colspan=6>
-					Les revenus, charges et bénéfices sont indiqués pour une durée d'un mois en temps de jeu, soit 12 heures réelles.
-				</@lv_column>
-			</@lv_line>
-
-		</@listview>
-	</@tab>
-</#macro>
\ No newline at end of file
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/research.ftl b/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/research.ftl
deleted file mode 100644
index c9c982c..0000000
--- a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/research.ftl
+++ /dev/null
@@ -1,264 +0,0 @@
-<#--
-	Macro that starts a research tab for one of the 3 existing modes
-	
-	Parameters:
-		curMode		The tab to start: R for "in progress", P for pending, K for implemented
- -->
-<#macro startResearchTab curMode>
-	<#switch curMode>
-
-		<#case 'R'>
-			<@tabStart "research" "En cours" />
-			<@rawFormStart "research-set-priorities" "form-priorities" "research" />
-			<@listviewStart />
-			<@lv_line headers=true>
-				<@lv_column width=150>Catégorie</@lv_column>
-				<@lv_column width="x">Nom</@lv_column>
-				<@lv_column width=100 centered=true>Progrès</@lv_column>
-				<@lv_column width=150 centered=true>Priorité</@lv_column>
-			</@lv_line>
-			<#break>
-
-		<#case 'P'>
-			<@tabStart "pending" "En attente" />
-			<@listviewStart />
-			<@lv_line headers=true>
-				<@lv_column width=150>Catégorie</@lv_column>
-				<@lv_column width="x">Nom</@lv_column>
-				<@lv_column width=150 right=true>Coût</@lv_column>
-				<@lv_column width=100 centered=true>&nbsp;</@lv_column>
-			</@lv_line>
-			<#break>
-
-		<#case 'K'>
-			<@tabStart "implemented" "Recherchées" />
-			<@listviewStart />
-			<@lv_line headers=true>
-				<@lv_column width=150>Catégorie</@lv_column>
-				<@lv_column width="x">Nom</@lv_column>
-			</@lv_line>
-			<#break> 
-
-	</#switch>
-</#macro>
-<#--
-	Macro that finishes a research tab depending on its type
-	
-	Parameters:
-		mode		The type of tab that is being closed
-  -->
-<#macro endResearchTab mode>
-	<#switch mode>
-
-		<#case 'R'>
-			<@lv_line headers=true>
-				<@lv_column width="x" colspan=4>&nbsp;</@lv_column>
-			</@lv_line>
-			<@lv_line>
-				<@lv_column colspan=3>&nbsp;</@lv_column>
-				<@lv_column centered=true>
-					<input type="submit" value="Modifier" class="input" style="margin: 15px 0 0 0" />
-				</@lv_column>
-			</@lv_line>
-			<@listviewEnd />
-			</form>
-			<#break>
-
-		<#case 'P'>
-		<#case 'K'>
-			<@listviewEnd />
-			<#break>
-
-	</#switch>
-	<@tabEnd />
-</#macro>
-<#--
-	Macro that renders an in-progress research entry
-	
-	Parameters:
-		entry		the entry
--->
-<#macro drawInProgressResearch entry>
-	<@lv_line id="tl-${entry.identifier?xhtml}" class="tech-line">
-		<@lv_column>${entry.category?xhtml}</@lv_column>
-		<@lv_column>
-			<#if entry.name?has_content>
-				<strong>${entry.name?xhtml}</strong>
-			<#else>
-				Technologie inconnue
-			</#if>
-		</@lv_column>
-		<@lv_column centered=true>${entry.completion} %</@lv_column>
-		<@lv_column centered=true>
-			<select name="rp-${entry.identifier?xhtml}" class="input">
-				<option style="padding: 0 5px" value="0" <#if entry.priority = 0>selected="selected"</#if>>très basse</option>
-				<option style="padding: 0 5px" value="1" <#if entry.priority = 1>selected="selected"</#if>>basse</option>
-				<option style="padding: 0 5px" value="2" <#if entry.priority = 2>selected="selected"</#if>>normale</option>
-				<option style="padding: 0 5px" value="3" <#if entry.priority = 3>selected="selected"</#if>>élevée</option>
-				<option style="padding: 0 5px" value="4" <#if entry.priority = 4>selected="selected"</#if>>très élevée</option>
-			</select>
-		</@lv_column>
-	</@lv_line>
-</#macro>
-<#--
-	Macro that renders a pending technology
-	
-	Parameters:
-		entry		the technology
--->
-<#macro drawPendingTechnology entry>
-	<@lv_line id="tl-${entry.identifier?xhtml}" class="tech-line">
-		<@lv_column>${entry.category?xhtml}</@lv_column>
-		<@lv_column>
-			<strong>${entry.name?xhtml}</strong>
-		</@lv_column>
-		<@lv_column right=true>
-			<strong>${entry.price?string(",##0")}</strong> <@abbr_bgc/>
-		</@lv_column>
-		<@lv_column right=true>
-			<#if data.page.cash &gt;= entry.price>
-				<@rawFormStart "research-implement" "form-implement-${entry.identifier}" entry.identifier />
-					<input type="hidden" name="technology" value="${entry.identifier?xhtml}" />
-					<input type="submit" value="Implémenter" class="input" />
-				</form>
-			<#else>
-				&nbsp;
-			</#if>
-		</@lv_column>
-	</@lv_line>
-</#macro>
-<#--
-	Macro that renders an implemented technology
-	
-	Parameters:
-		entry		the technology
--->
-<#macro drawImplementedTechnology entry>
-	<@lv_line id="tl-${entry.identifier?xhtml}" class="tech-line">
-		<@lv_column>${entry.category?xhtml}</@lv_column>
-		<@lv_column>
-			<strong>${entry.name?xhtml}</strong>
-		</@lv_column>
-	</@lv_line>
-</#macro>
-<#--
-	Macro that renders a single entry
-	
-	Parameters:
-		mode		the current tab (see startResearchTab for details)
-		entry		the entry
--->
-<#macro drawResearchEntry mode entry>
-	<#switch mode>
-
-		<#case 'R'>
-			<@drawInProgressResearch entry />
-			<#break>
-
-		<#case 'P'>
-			<@drawPendingTechnology entry />
-			<#break>
-
-		<#case 'K'>
-			<@drawImplementedTechnology entry />
-			<#break>
- 
-	</#switch>
-</#macro>
-<#--
-	Render the visible part of the research page
-	
-	Parameters:
-		entries		the sorted list of research entries 
-  -->
-<#macro renderResearchTabs entries>
-	<#local prevMode = ''>
-
-	<@tabs>
-		<#list entries as entry>
-
-			<#-- Determine type of entry to display -->
-			<#if entry.implemented?has_content>
-				<#if entry.implemented>
-					<#local curMode = 'K'>
-				<#else>
-					<#local curMode = 'P'>
-				</#if>
-			<#else>
-				<#local curMode = 'R'>
-			</#if>
-
-			<#-- Start/end tabs -->
-			<#if curMode != prevMode>
-				<#if prevMode != ''>
-					<@endResearchTab prevMode />
-				</#if>
-				<@startResearchTab curMode />
-				<#local prevMode = curMode>
-			</#if>
-			
-			
-			<@drawResearchEntry curMode entry />
-	
-		</#list>
-		<@endResearchTab prevMode />
-	</@tabs>
-</#macro>
-<#--
-	Render all research information in a hidden layer which will be used by
-	the client-side code to display more information.
-  -->
-<#macro renderFullResearchData entries>
-	<div style="display: none">
-		<#list entries as tech>
-			<div class="tech-description" id="tdesc-${tech.identifier?xhtml}">
-				<h4><#if tech.name?has_content>${tech.name?xhtml}<#else>Technologie inconnue</#if></h4>
-				<div class="tech-info"><strong>Catégorie:</strong> ${tech.category?xhtml}</div>
-				<#if tech.description?has_content><div class="tech-info">${tech.description?xhtml}</div></#if>
-				<#if tech.price?has_content>
-					<div class="tech-info"><strong>Coût d'implémentation:</strong> ${tech.price?string(",##0")} <@abbr_bgc /></div>
-				</#if>
-				<#if tech.dependencies?has_content>
-					<div class="tech-info"><strong>Requiert:</strong>
-						<ul>
-							<#list tech.dependencies as depId>
-								<li class="dep">${depId}</li>
-							</#list>
-						</ul>
-					</div>
-				</#if>
-				<#if tech.reverseDependencies?has_content>
-					<div class="tech-info"><strong>Requis par:</strong>
-						<ul>
-							<#list tech.reverseDependencies as depId>
-								<li class="dep">${depId}</li>
-							</#list>
-						</ul>
-					</div>
-				</#if>
-				<#if tech.buildings?has_content>
-					<div class="tech-info"><strong>Nouveaux bâtiments:</strong>
-						<ul>
-							<#list tech.buildings as building>
-								<li>${building}</li>
-							</#list>
-						</ul>
-					</div>
-				</#if>
-			</div>
-		</#list>
-	</div>
-	<script type="text/javascript" charset="utf-8" src="js/research.js"></script>
-</#macro>
-<#--
-	Main research page
-  -->
-<#macro render>
-<@page title="Recherche">
-
-	<#local entries = data.researchData>
-	<@renderResearchTabs entries />
-	<@renderFullResearchData entries />
-
-</@page>
-</#macro>
\ No newline at end of file
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/layout/lists.ftl b/legacyworlds-web-main/Content/Raw/WEB-INF/fm/layout/lists.ftl
deleted file mode 100644
index 93ce018..0000000
--- a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/layout/lists.ftl
+++ /dev/null
@@ -1,31 +0,0 @@
-<#macro listviewStart>
-	<table class="list-view">
-</#macro> 
-<#macro listviewEnd>
-	</table>
-</#macro> 
-<#macro listview>
-	<@listviewStart />
-		<#nested>
-	<@listviewEnd />
-</#macro>
-<#macro lv_line headers=false class="" id="">
-	<tr<#if class != ""> class="${class}<#if headers>headers</#if>"<#elseif headers> class="headers"</#if><#if id != ""> id="${id?xhtml}"</#if>>
-		<#nested>
-	</tr>
-</#macro>
-<#macro lv_column width=0 centered=false right=false colspan=0 id="">
-	<#if width?is_string>
-		<th style="text-align: <#if centered>center<#elseif right>right<#else>left</#if>"<#if colspan gt 1> colspan="${colspan}"</#if><#if id != ""> id="${id?xhtml}"</#if>>
-			<#nested>
-		</th>
-	<#elseif width gt 0>
-		<th style="width: ${width}px; text-align: <#if centered>center<#elseif right>right<#else>left</#if>"<#if colspan gt 1> colspan="${colspan}"</#if><#if id != ""> id="${id?xhtml}"</#if>>
-			<#nested>
-		</th>
-	<#else>
-		<td style="text-align: <#if centered>center<#elseif right>right<#else>left</#if>"<#if colspan gt 1> colspan="${colspan}"</#if><#if id != ""> id="${id?xhtml}"</#if>>
-			<#nested>
-		</td>
-	</#if>
-</#macro>
\ No newline at end of file
diff --git a/legacyworlds-web-main/Content/Raw/img/background.jpg b/legacyworlds-web-main/Content/Raw/img/background.jpg
deleted file mode 100644
index 6f101d0..0000000
Binary files a/legacyworlds-web-main/Content/Raw/img/background.jpg and /dev/null differ
diff --git a/legacyworlds-web-main/Content/Raw/img/logo.png b/legacyworlds-web-main/Content/Raw/img/logo.png
deleted file mode 100644
index 5d082bc..0000000
Binary files a/legacyworlds-web-main/Content/Raw/img/logo.png and /dev/null differ
diff --git a/legacyworlds-web-main/Content/Raw/img/rust.png b/legacyworlds-web-main/Content/Raw/img/rust.png
deleted file mode 100644
index 223ba46..0000000
Binary files a/legacyworlds-web-main/Content/Raw/img/rust.png and /dev/null differ
diff --git a/legacyworlds-web-main/Content/Raw/js/jquery-1.7.1.min.js b/legacyworlds-web-main/Content/Raw/js/jquery-1.7.1.min.js
deleted file mode 100644
index 198b3ff..0000000
--- a/legacyworlds-web-main/Content/Raw/js/jquery-1.7.1.min.js
+++ /dev/null
@@ -1,4 +0,0 @@
-/*! jQuery v1.7.1 jquery.com | jquery.org/license */
-(function(a,b){function cy(a){return f.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cv(a){if(!ck[a]){var b=c.body,d=f("<"+a+">").appendTo(b),e=d.css("display");d.remove();if(e==="none"||e===""){cl||(cl=c.createElement("iframe"),cl.frameBorder=cl.width=cl.height=0),b.appendChild(cl);if(!cm||!cl.createElement)cm=(cl.contentWindow||cl.contentDocument).document,cm.write((c.compatMode==="CSS1Compat"?"<!doctype html>":"")+"<html><body>"),cm.close();d=cm.createElement(a),cm.body.appendChild(d),e=f.css(d,"display"),b.removeChild(cl)}ck[a]=e}return ck[a]}function cu(a,b){var c={};f.each(cq.concat.apply([],cq.slice(0,b)),function(){c[this]=a});return c}function ct(){cr=b}function cs(){setTimeout(ct,0);return cr=f.now()}function cj(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function ci(){try{return new a.XMLHttpRequest}catch(b){}}function cc(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var d=a.dataTypes,e={},g,h,i=d.length,j,k=d[0],l,m,n,o,p;for(g=1;g<i;g++){if(g===1)for(h in a.converters)typeof h=="string"&&(e[h.toLowerCase()]=a.converters[h]);l=k,k=d[g];if(k==="*")k=l;else if(l!=="*"&&l!==k){m=l+" "+k,n=e[m]||e["* "+k];if(!n){p=b;for(o in e){j=o.split(" ");if(j[0]===l||j[0]==="*"){p=e[j[1]+" "+k];if(p){o=e[o],o===!0?n=p:p===!0&&(n=o);break}}}}!n&&!p&&f.error("No conversion from "+m.replace(" "," to ")),n!==!0&&(c=n?n(c):p(o(c)))}}return c}function cb(a,c,d){var e=a.contents,f=a.dataTypes,g=a.responseFields,h,i,j,k;for(i in g)i in d&&(c[g[i]]=d[i]);while(f[0]==="*")f.shift(),h===b&&(h=a.mimeType||c.getResponseHeader("content-type"));if(h)for(i in e)if(e[i]&&e[i].test(h)){f.unshift(i);break}if(f[0]in d)j=f[0];else{for(i in d){if(!f[0]||a.converters[i+" "+f[0]]){j=i;break}k||(k=i)}j=j||k}if(j){j!==f[0]&&f.unshift(j);return d[j]}}function ca(a,b,c,d){if(f.isArray(b))f.each(b,function(b,e){c||bE.test(a)?d(a,e):ca(a+"["+(typeof e=="object"||f.isArray(e)?b:"")+"]",e,c,d)});else if(!c&&b!=null&&typeof b=="object")for(var e in b)ca(a+"["+e+"]",b[e],c,d);else d(a,b)}function b_(a,c){var d,e,g=f.ajaxSettings.flatOptions||{};for(d in c)c[d]!==b&&((g[d]?a:e||(e={}))[d]=c[d]);e&&f.extend(!0,a,e)}function b$(a,c,d,e,f,g){f=f||c.dataTypes[0],g=g||{},g[f]=!0;var h=a[f],i=0,j=h?h.length:0,k=a===bT,l;for(;i<j&&(k||!l);i++)l=h[i](c,d,e),typeof l=="string"&&(!k||g[l]?l=b:(c.dataTypes.unshift(l),l=b$(a,c,d,e,l,g)));(k||!l)&&!g["*"]&&(l=b$(a,c,d,e,"*",g));return l}function bZ(a){return function(b,c){typeof b!="string"&&(c=b,b="*");if(f.isFunction(c)){var d=b.toLowerCase().split(bP),e=0,g=d.length,h,i,j;for(;e<g;e++)h=d[e],j=/^\+/.test(h),j&&(h=h.substr(1)||"*"),i=a[h]=a[h]||[],i[j?"unshift":"push"](c)}}}function bC(a,b,c){var d=b==="width"?a.offsetWidth:a.offsetHeight,e=b==="width"?bx:by,g=0,h=e.length;if(d>0){if(c!=="border")for(;g<h;g++)c||(d-=parseFloat(f.css(a,"padding"+e[g]))||0),c==="margin"?d+=parseFloat(f.css(a,c+e[g]))||0:d-=parseFloat(f.css(a,"border"+e[g]+"Width"))||0;return d+"px"}d=bz(a,b,b);if(d<0||d==null)d=a.style[b]||0;d=parseFloat(d)||0;if(c)for(;g<h;g++)d+=parseFloat(f.css(a,"padding"+e[g]))||0,c!=="padding"&&(d+=parseFloat(f.css(a,"border"+e[g]+"Width"))||0),c==="margin"&&(d+=parseFloat(f.css(a,c+e[g]))||0);return d+"px"}function bp(a,b){b.src?f.ajax({url:b.src,async:!1,dataType:"script"}):f.globalEval((b.text||b.textContent||b.innerHTML||"").replace(bf,"/*$0*/")),b.parentNode&&b.parentNode.removeChild(b)}function bo(a){var b=c.createElement("div");bh.appendChild(b),b.innerHTML=a.outerHTML;return b.firstChild}function bn(a){var b=(a.nodeName||"").toLowerCase();b==="input"?bm(a):b!=="script"&&typeof a.getElementsByTagName!="undefined"&&f.grep(a.getElementsByTagName("input"),bm)}function bm(a){if(a.type==="checkbox"||a.type==="radio")a.defaultChecked=a.checked}function bl(a){return typeof a.getElementsByTagName!="undefined"?a.getElementsByTagName("*"):typeof a.querySelectorAll!="undefined"?a.querySelectorAll("*"):[]}function bk(a,b){var c;if(b.nodeType===1){b.clearAttributes&&b.clearAttributes(),b.mergeAttributes&&b.mergeAttributes(a),c=b.nodeName.toLowerCase();if(c==="object")b.outerHTML=a.outerHTML;else if(c!=="input"||a.type!=="checkbox"&&a.type!=="radio"){if(c==="option")b.selected=a.defaultSelected;else if(c==="input"||c==="textarea")b.defaultValue=a.defaultValue}else a.checked&&(b.defaultChecked=b.checked=a.checked),b.value!==a.value&&(b.value=a.value);b.removeAttribute(f.expando)}}function bj(a,b){if(b.nodeType===1&&!!f.hasData(a)){var c,d,e,g=f._data(a),h=f._data(b,g),i=g.events;if(i){delete h.handle,h.events={};for(c in i)for(d=0,e=i[c].length;d<e;d++)f.event.add(b,c+(i[c][d].namespace?".":"")+i[c][d].namespace,i[c][d],i[c][d].data)}h.data&&(h.data=f.extend({},h.data))}}function bi(a,b){return f.nodeName(a,"table")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function U(a){var b=V.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}function T(a,b,c){b=b||0;if(f.isFunction(b))return f.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return f.grep(a,function(a,d){return a===b===c});if(typeof b=="string"){var d=f.grep(a,function(a){return a.nodeType===1});if(O.test(b))return f.filter(b,d,!c);b=f.filter(b,d)}return f.grep(a,function(a,d){return f.inArray(a,b)>=0===c})}function S(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function K(){return!0}function J(){return!1}function n(a,b,c){var d=b+"defer",e=b+"queue",g=b+"mark",h=f._data(a,d);h&&(c==="queue"||!f._data(a,e))&&(c==="mark"||!f._data(a,g))&&setTimeout(function(){!f._data(a,e)&&!f._data(a,g)&&(f.removeData(a,d,!0),h.fire())},0)}function m(a){for(var b in a){if(b==="data"&&f.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function l(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(k,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:f.isNumeric(d)?parseFloat(d):j.test(d)?f.parseJSON(d):d}catch(g){}f.data(a,c,d)}else d=b}return d}function h(a){var b=g[a]={},c,d;a=a.split(/\s+/);for(c=0,d=a.length;c<d;c++)b[a[c]]=!0;return b}var c=a.document,d=a.navigator,e=a.location,f=function(){function J(){if(!e.isReady){try{c.documentElement.doScroll("left")}catch(a){setTimeout(J,1);return}e.ready()}}var e=function(a,b){return new e.fn.init(a,b,h)},f=a.jQuery,g=a.$,h,i=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,j=/\S/,k=/^\s+/,l=/\s+$/,m=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,n=/^[\],:{}\s]*$/,o=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,p=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,q=/(?:^|:|,)(?:\s*\[)+/g,r=/(webkit)[ \/]([\w.]+)/,s=/(opera)(?:.*version)?[ \/]([\w.]+)/,t=/(msie) ([\w.]+)/,u=/(mozilla)(?:.*? rv:([\w.]+))?/,v=/-([a-z]|[0-9])/ig,w=/^-ms-/,x=function(a,b){return(b+"").toUpperCase()},y=d.userAgent,z,A,B,C=Object.prototype.toString,D=Object.prototype.hasOwnProperty,E=Array.prototype.push,F=Array.prototype.slice,G=String.prototype.trim,H=Array.prototype.indexOf,I={};e.fn=e.prototype={constructor:e,init:function(a,d,f){var g,h,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!d&&c.body){this.context=c,this[0]=c.body,this.selector=a,this.length=1;return this}if(typeof a=="string"){a.charAt(0)!=="<"||a.charAt(a.length-1)!==">"||a.length<3?g=i.exec(a):g=[null,a,null];if(g&&(g[1]||!d)){if(g[1]){d=d instanceof e?d[0]:d,k=d?d.ownerDocument||d:c,j=m.exec(a),j?e.isPlainObject(d)?(a=[c.createElement(j[1])],e.fn.attr.call(a,d,!0)):a=[k.createElement(j[1])]:(j=e.buildFragment([g[1]],[k]),a=(j.cacheable?e.clone(j.fragment):j.fragment).childNodes);return e.merge(this,a)}h=c.getElementById(g[2]);if(h&&h.parentNode){if(h.id!==g[2])return f.find(a);this.length=1,this[0]=h}this.context=c,this.selector=a;return this}return!d||d.jquery?(d||f).find(a):this.constructor(d).find(a)}if(e.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return e.makeArray(a,this)},selector:"",jquery:"1.7.1",length:0,size:function(){return this.length},toArray:function(){return F.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=this.constructor();e.isArray(a)?E.apply(d,a):e.merge(d,a),d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")");return d},each:function(a,b){return e.each(this,a,b)},ready:function(a){e.bindReady(),A.add(a);return this},eq:function(a){a=+a;return a===-1?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(F.apply(this,arguments),"slice",F.call(arguments).join(","))},map:function(a){return this.pushStack(e.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:E,sort:[].sort,splice:[].splice},e.fn.init.prototype=e.fn,e.extend=e.fn.extend=function(){var a,c,d,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i=="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!="object"&&!e.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j<k;j++)if((a=arguments[j])!=null)for(c in a){d=i[c],f=a[c];if(i===f)continue;l&&f&&(e.isPlainObject(f)||(g=e.isArray(f)))?(g?(g=!1,h=d&&e.isArray(d)?d:[]):h=d&&e.isPlainObject(d)?d:{},i[c]=e.extend(l,h,f)):f!==b&&(i[c]=f)}return i},e.extend({noConflict:function(b){a.$===e&&(a.$=g),b&&a.jQuery===e&&(a.jQuery=f);return e},isReady:!1,readyWait:1,holdReady:function(a){a?e.readyWait++:e.ready(!0)},ready:function(a){if(a===!0&&!--e.readyWait||a!==!0&&!e.isReady){if(!c.body)return setTimeout(e.ready,1);e.isReady=!0;if(a!==!0&&--e.readyWait>0)return;A.fireWith(c,[e]),e.fn.trigger&&e(c).trigger("ready").off("ready")}},bindReady:function(){if(!A){A=e.Callbacks("once memory");if(c.readyState==="complete")return setTimeout(e.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",B,!1),a.addEventListener("load",e.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",B),a.attachEvent("onload",e.ready);var b=!1;try{b=a.frameElement==null}catch(d){}c.documentElement.doScroll&&b&&J()}}},isFunction:function(a){return e.type(a)==="function"},isArray:Array.isArray||function(a){return e.type(a)==="array"},isWindow:function(a){return a&&typeof a=="object"&&"setInterval"in a},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):I[C.call(a)]||"object"},isPlainObject:function(a){if(!a||e.type(a)!=="object"||a.nodeType||e.isWindow(a))return!1;try{if(a.constructor&&!D.call(a,"constructor")&&!D.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||D.call(a,d)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw new Error(a)},parseJSON:function(b){if(typeof b!="string"||!b)return null;b=e.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(n.test(b.replace(o,"@").replace(p,"]").replace(q,"")))return(new Function("return "+b))();e.error("Invalid JSON: "+b)},parseXML:function(c){var d,f;try{a.DOMParser?(f=new DOMParser,d=f.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(g){d=b}(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&e.error("Invalid XML: "+c);return d},noop:function(){},globalEval:function(b){b&&j.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(w,"ms-").replace(v,x)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var f,g=0,h=a.length,i=h===b||e.isFunction(a);if(d){if(i){for(f in a)if(c.apply(a[f],d)===!1)break}else for(;g<h;)if(c.apply(a[g++],d)===!1)break}else if(i){for(f in a)if(c.call(a[f],f,a[f])===!1)break}else for(;g<h;)if(c.call(a[g],g,a[g++])===!1)break;return a},trim:G?function(a){return a==null?"":G.call(a)}:function(a){return a==null?"":(a+"").replace(k,"").replace(l,"")},makeArray:function(a,b){var c=b||[];if(a!=null){var d=e.type(a);a.length==null||d==="string"||d==="function"||d==="regexp"||e.isWindow(a)?E.call(c,a):e.merge(c,a)}return c},inArray:function(a,b,c){var d;if(b){if(H)return H.call(b,a,c);d=b.length,c=c?c<0?Math.max(0,d+c):c:0;for(;c<d;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,c){var d=a.length,e=0;if(typeof c.length=="number")for(var f=c.length;e<f;e++)a[d++]=c[e];else while(c[e]!==b)a[d++]=c[e++];a.length=d;return a},grep:function(a,b,c){var d=[],e;c=!!c;for(var f=0,g=a.length;f<g;f++)e=!!b(a[f],f),c!==e&&d.push(a[f]);return d},map:function(a,c,d){var f,g,h=[],i=0,j=a.length,k=a instanceof e||j!==b&&typeof j=="number"&&(j>0&&a[0]&&a[j-1]||j===0||e.isArray(a));if(k)for(;i<j;i++)f=c(a[i],i,d),f!=null&&(h[h.length]=f);else for(g in a)f=c(a[g],g,d),f!=null&&(h[h.length]=f);return h.concat.apply([],h)},guid:1,proxy:function(a,c){if(typeof c=="string"){var d=a[c];c=a,a=d}if(!e.isFunction(a))return b;var f=F.call(arguments,2),g=function(){return a.apply(c,f.concat(F.call(arguments)))};g.guid=a.guid=a.guid||g.guid||e.guid++;return g},access:function(a,c,d,f,g,h){var i=a.length;if(typeof c=="object"){for(var j in c)e.access(a,j,c[j],f,g,d);return a}if(d!==b){f=!h&&f&&e.isFunction(d);for(var k=0;k<i;k++)g(a[k],c,f?d.call(a[k],k,g(a[k],c)):d,h);return a}return i?g(a[0],c):b},now:function(){return(new Date).getTime()},uaMatch:function(a){a=a.toLowerCase();var b=r.exec(a)||s.exec(a)||t.exec(a)||a.indexOf("compatible")<0&&u.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},sub:function(){function a(b,c){return new a.fn.init(b,c)}e.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.sub=this.sub,a.fn.init=function(d,f){f&&f instanceof e&&!(f instanceof a)&&(f=a(f));return e.fn.init.call(this,d,f,b)},a.fn.init.prototype=a.fn;var b=a(c);return a},browser:{}}),e.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(a,b){I["[object "+b+"]"]=b.toLowerCase()}),z=e.uaMatch(y),z.browser&&(e.browser[z.browser]=!0,e.browser.version=z.version),e.browser.webkit&&(e.browser.safari=!0),j.test(" ")&&(k=/^[\s\xA0]+/,l=/[\s\xA0]+$/),h=e(c),c.addEventListener?B=function(){c.removeEventListener("DOMContentLoaded",B,!1),e.ready()}:c.attachEvent&&(B=function(){c.readyState==="complete"&&(c.detachEvent("onreadystatechange",B),e.ready())});return e}(),g={};f.Callbacks=function(a){a=a?g[a]||h(a):{};var c=[],d=[],e,i,j,k,l,m=function(b){var d,e,g,h,i;for(d=0,e=b.length;d<e;d++)g=b[d],h=f.type(g),h==="array"?m(g):h==="function"&&(!a.unique||!o.has(g))&&c.push(g)},n=function(b,f){f=f||[],e=!a.memory||[b,f],i=!0,l=j||0,j=0,k=c.length;for(;c&&l<k;l++)if(c[l].apply(b,f)===!1&&a.stopOnFalse){e=!0;break}i=!1,c&&(a.once?e===!0?o.disable():c=[]:d&&d.length&&(e=d.shift(),o.fireWith(e[0],e[1])))},o={add:function(){if(c){var a=c.length;m(arguments),i?k=c.length:e&&e!==!0&&(j=a,n(e[0],e[1]))}return this},remove:function(){if(c){var b=arguments,d=0,e=b.length;for(;d<e;d++)for(var f=0;f<c.length;f++)if(b[d]===c[f]){i&&f<=k&&(k--,f<=l&&l--),c.splice(f--,1);if(a.unique)break}}return this},has:function(a){if(c){var b=0,d=c.length;for(;b<d;b++)if(a===c[b])return!0}return!1},empty:function(){c=[];return this},disable:function(){c=d=e=b;return this},disabled:function(){return!c},lock:function(){d=b,(!e||e===!0)&&o.disable();return this},locked:function(){return!d},fireWith:function(b,c){d&&(i?a.once||d.push([b,c]):(!a.once||!e)&&n(b,c));return this},fire:function(){o.fireWith(this,arguments);return this},fired:function(){return!!e}};return o};var i=[].slice;f.extend({Deferred:function(a){var b=f.Callbacks("once memory"),c=f.Callbacks("once memory"),d=f.Callbacks("memory"),e="pending",g={resolve:b,reject:c,notify:d},h={done:b.add,fail:c.add,progress:d.add,state:function(){return e},isResolved:b.fired,isRejected:c.fired,then:function(a,b,c){i.done(a).fail(b).progress(c);return this},always:function(){i.done.apply(i,arguments).fail.apply(i,arguments);return this},pipe:function(a,b,c){return f.Deferred(function(d){f.each({done:[a,"resolve"],fail:[b,"reject"],progress:[c,"notify"]},function(a,b){var c=b[0],e=b[1],g;f.isFunction(c)?i[a](function(){g=c.apply(this,arguments),g&&f.isFunction(g.promise)?g.promise().then(d.resolve,d.reject,d.notify):d[e+"With"](this===i?d:this,[g])}):i[a](d[e])})}).promise()},promise:function(a){if(a==null)a=h;else for(var b in h)a[b]=h[b];return a}},i=h.promise({}),j;for(j in g)i[j]=g[j].fire,i[j+"With"]=g[j].fireWith;i.done(function(){e="resolved"},c.disable,d.lock).fail(function(){e="rejected"},b.disable,d.lock),a&&a.call(i,i);return i},when:function(a){function m(a){return function(b){e[a]=arguments.length>1?i.call(arguments,0):b,j.notifyWith(k,e)}}function l(a){return function(c){b[a]=arguments.length>1?i.call(arguments,0):c,--g||j.resolveWith(j,b)}}var b=i.call(arguments,0),c=0,d=b.length,e=Array(d),g=d,h=d,j=d<=1&&a&&f.isFunction(a.promise)?a:f.Deferred(),k=j.promise();if(d>1){for(;c<d;c++)b[c]&&b[c].promise&&f.isFunction(b[c].promise)?b[c].promise().then(l(c),j.reject,m(c)):--g;g||j.resolveWith(j,b)}else j!==a&&j.resolveWith(j,d?[a]:[]);return k}}),f.support=function(){var b,d,e,g,h,i,j,k,l,m,n,o,p,q=c.createElement("div"),r=c.documentElement;q.setAttribute("className","t"),q.innerHTML="   <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>",d=q.getElementsByTagName("*"),e=q.getElementsByTagName("a")[0];if(!d||!d.length||!e)return{};g=c.createElement("select"),h=g.appendChild(c.createElement("option")),i=q.getElementsByTagName("input")[0],b={leadingWhitespace:q.firstChild.nodeType===3,tbody:!q.getElementsByTagName("tbody").length,htmlSerialize:!!q.getElementsByTagName("link").length,style:/top/.test(e.getAttribute("style")),hrefNormalized:e.getAttribute("href")==="/a",opacity:/^0.55/.test(e.style.opacity),cssFloat:!!e.style.cssFloat,checkOn:i.value==="on",optSelected:h.selected,getSetAttribute:q.className!=="t",enctype:!!c.createElement("form").enctype,html5Clone:c.createElement("nav").cloneNode(!0).outerHTML!=="<:nav></:nav>",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0},i.checked=!0,b.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,b.optDisabled=!h.disabled;try{delete q.test}catch(s){b.deleteExpando=!1}!q.addEventListener&&q.attachEvent&&q.fireEvent&&(q.attachEvent("onclick",function(){b.noCloneEvent=!1}),q.cloneNode(!0).fireEvent("onclick")),i=c.createElement("input"),i.value="t",i.setAttribute("type","radio"),b.radioValue=i.value==="t",i.setAttribute("checked","checked"),q.appendChild(i),k=c.createDocumentFragment(),k.appendChild(q.lastChild),b.checkClone=k.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=i.checked,k.removeChild(i),k.appendChild(q),q.innerHTML="",a.getComputedStyle&&(j=c.createElement("div"),j.style.width="0",j.style.marginRight="0",q.style.width="2px",q.appendChild(j),b.reliableMarginRight=(parseInt((a.getComputedStyle(j,null)||{marginRight:0}).marginRight,10)||0)===0);if(q.attachEvent)for(o in{submit:1,change:1,focusin:1})n="on"+o,p=n in q,p||(q.setAttribute(n,"return;"),p=typeof q[n]=="function"),b[o+"Bubbles"]=p;k.removeChild(q),k=g=h=j=q=i=null,f(function(){var a,d,e,g,h,i,j,k,m,n,o,r=c.getElementsByTagName("body")[0];!r||(j=1,k="position:absolute;top:0;left:0;width:1px;height:1px;margin:0;",m="visibility:hidden;border:0;",n="style='"+k+"border:5px solid #000;padding:0;'",o="<div "+n+"><div></div></div>"+"<table "+n+" cellpadding='0' cellspacing='0'>"+"<tr><td></td></tr></table>",a=c.createElement("div"),a.style.cssText=m+"width:0;height:0;position:static;top:0;margin-top:"+j+"px",r.insertBefore(a,r.firstChild),q=c.createElement("div"),a.appendChild(q),q.innerHTML="<table><tr><td style='padding:0;border:0;display:none'></td><td>t</td></tr></table>",l=q.getElementsByTagName("td"),p=l[0].offsetHeight===0,l[0].style.display="",l[1].style.display="none",b.reliableHiddenOffsets=p&&l[0].offsetHeight===0,q.innerHTML="",q.style.width=q.style.paddingLeft="1px",f.boxModel=b.boxModel=q.offsetWidth===2,typeof q.style.zoom!="undefined"&&(q.style.display="inline",q.style.zoom=1,b.inlineBlockNeedsLayout=q.offsetWidth===2,q.style.display="",q.innerHTML="<div style='width:4px;'></div>",b.shrinkWrapBlocks=q.offsetWidth!==2),q.style.cssText=k+m,q.innerHTML=o,d=q.firstChild,e=d.firstChild,h=d.nextSibling.firstChild.firstChild,i={doesNotAddBorder:e.offsetTop!==5,doesAddBorderForTableAndCells:h.offsetTop===5},e.style.position="fixed",e.style.top="20px",i.fixedPosition=e.offsetTop===20||e.offsetTop===15,e.style.position=e.style.top="",d.style.overflow="hidden",d.style.position="relative",i.subtractsBorderForOverflowNotVisible=e.offsetTop===-5,i.doesNotIncludeMarginInBodyOffset=r.offsetTop!==j,r.removeChild(a),q=a=null,f.extend(b,i))});return b}();var j=/^(?:\{.*\}|\[.*\])$/,k=/([A-Z])/g;f.extend({cache:{},uuid:0,expando:"jQuery"+(f.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?f.cache[a[f.expando]]:a[f.expando];return!!a&&!m(a)},data:function(a,c,d,e){if(!!f.acceptData(a)){var g,h,i,j=f.expando,k=typeof c=="string",l=a.nodeType,m=l?f.cache:a,n=l?a[j]:a[j]&&j,o=c==="events";if((!n||!m[n]||!o&&!e&&!m[n].data)&&k&&d===b)return;n||(l?a[j]=n=++f.uuid:n=j),m[n]||(m[n]={},l||(m[n].toJSON=f.noop));if(typeof c=="object"||typeof c=="function")e?m[n]=f.extend(m[n],c):m[n].data=f.extend(m[n].data,c);g=h=m[n],e||(h.data||(h.data={}),h=h.data),d!==b&&(h[f.camelCase(c)]=d);if(o&&!h[c])return g.events;k?(i=h[c],i==null&&(i=h[f.camelCase(c)])):i=h;return i}},removeData:function(a,b,c){if(!!f.acceptData(a)){var d,e,g,h=f.expando,i=a.nodeType,j=i?f.cache:a,k=i?a[h]:h;if(!j[k])return;if(b){d=c?j[k]:j[k].data;if(d){f.isArray(b)||(b in d?b=[b]:(b=f.camelCase(b),b in d?b=[b]:b=b.split(" ")));for(e=0,g=b.length;e<g;e++)delete d[b[e]];if(!(c?m:f.isEmptyObject)(d))return}}if(!c){delete j[k].data;if(!m(j[k]))return}f.support.deleteExpando||!j.setInterval?delete j[k]:j[k]=null,i&&(f.support.deleteExpando?delete a[h]:a.removeAttribute?a.removeAttribute(h):a[h]=null)}},_data:function(a,b,c){return f.data(a,b,c,!0)},acceptData:function(a){if(a.nodeName){var b=f.noData[a.nodeName.toLowerCase()];if(b)return b!==!0&&a.getAttribute("classid")===b}return!0}}),f.fn.extend({data:function(a,c){var d,e,g,h=null;if(typeof a=="undefined"){if(this.length){h=f.data(this[0]);if(this[0].nodeType===1&&!f._data(this[0],"parsedAttrs")){e=this[0].attributes;for(var i=0,j=e.length;i<j;i++)g=e[i].name,g.indexOf("data-")===0&&(g=f.camelCase(g.substring(5)),l(this[0],g,h[g]));f._data(this[0],"parsedAttrs",!0)}}return h}if(typeof a=="object")return this.each(function(){f.data(this,a)});d=a.split("."),d[1]=d[1]?"."+d[1]:"";if(c===b){h=this.triggerHandler("getData"+d[1]+"!",[d[0]]),h===b&&this.length&&(h=f.data(this[0],a),h=l(this[0],a,h));return h===b&&d[1]?this.data(d[0]):h}return this.each(function(){var b=f(this),e=[d[0],c];b.triggerHandler("setData"+d[1]+"!",e),f.data(this,a,c),b.triggerHandler("changeData"+d[1]+"!",e)})},removeData:function(a){return this.each(function(){f.removeData(this,a)})}}),f.extend({_mark:function(a,b){a&&(b=(b||"fx")+"mark",f._data(a,b,(f._data(a,b)||0)+1))},_unmark:function(a,b,c){a!==!0&&(c=b,b=a,a=!1);if(b){c=c||"fx";var d=c+"mark",e=a?0:(f._data(b,d)||1)-1;e?f._data(b,d,e):(f.removeData(b,d,!0),n(b,c,"mark"))}},queue:function(a,b,c){var d;if(a){b=(b||"fx")+"queue",d=f._data(a,b),c&&(!d||f.isArray(c)?d=f._data(a,b,f.makeArray(c)):d.push(c));return d||[]}},dequeue:function(a,b){b=b||"fx";var c=f.queue(a,b),d=c.shift(),e={};d==="inprogress"&&(d=c.shift()),d&&(b==="fx"&&c.unshift("inprogress"),f._data(a,b+".run",e),d.call(a,function(){f.dequeue(a,b)},e)),c.length||(f.removeData(a,b+"queue "+b+".run",!0),n(a,b,"queue"))}}),f.fn.extend({queue:function(a,c){typeof a!="string"&&(c=a,a="fx");if(c===b)return f.queue(this[0],a);return this.each(function(){var b=f.queue(this,a,c);a==="fx"&&b[0]!=="inprogress"&&f.dequeue(this,a)})},dequeue:function(a){return this.each(function(){f.dequeue(this,a)})},delay:function(a,b){a=f.fx?f.fx.speeds[a]||a:a,b=b||"fx";return this.queue(b,function(b,c){var d=setTimeout(b,a);c.stop=function(){clearTimeout(d)}})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,c){function m(){--h||d.resolveWith(e,[e])}typeof a!="string"&&(c=a,a=b),a=a||"fx";var d=f.Deferred(),e=this,g=e.length,h=1,i=a+"defer",j=a+"queue",k=a+"mark",l;while(g--)if(l=f.data(e[g],i,b,!0)||(f.data(e[g],j,b,!0)||f.data(e[g],k,b,!0))&&f.data(e[g],i,f.Callbacks("once memory"),!0))h++,l.add(m);m();return d.promise()}});var o=/[\n\t\r]/g,p=/\s+/,q=/\r/g,r=/^(?:button|input)$/i,s=/^(?:button|input|object|select|textarea)$/i,t=/^a(?:rea)?$/i,u=/^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,v=f.support.getSetAttribute,w,x,y;f.fn.extend({attr:function(a,b){return f.access(this,a,b,!0,f.attr)},removeAttr:function(a){return this.each(function(){f.removeAttr(this,a)})},prop:function(a,b){return f.access(this,a,b,!0,f.prop)},removeProp:function(a){a=f.propFix[a]||a;return this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,g,h,i;if(f.isFunction(a))return this.each(function(b){f(this).addClass(a.call(this,b,this.className))});if(a&&typeof a=="string"){b=a.split(p);for(c=0,d=this.length;c<d;c++){e=this[c];if(e.nodeType===1)if(!e.className&&b.length===1)e.className=a;else{g=" "+e.className+" ";for(h=0,i=b.length;h<i;h++)~g.indexOf(" "+b[h]+" ")||(g+=b[h]+" ");e.className=f.trim(g)}}}return this},removeClass:function(a){var c,d,e,g,h,i,j;if(f.isFunction(a))return this.each(function(b){f(this).removeClass(a.call(this,b,this.className))});if(a&&typeof a=="string"||a===b){c=(a||"").split(p);for(d=0,e=this.length;d<e;d++){g=this[d];if(g.nodeType===1&&g.className)if(a){h=(" "+g.className+" ").replace(o," ");for(i=0,j=c.length;i<j;i++)h=h.replace(" "+c[i]+" "," ");g.className=f.trim(h)}else g.className=""}}return this},toggleClass:function(a,b){var c=typeof a,d=typeof b=="boolean";if(f.isFunction(a))return this.each(function(c){f(this).toggleClass(a.call(this,c,this.className,b),b)});return this.each(function(){if(c==="string"){var e,g=0,h=f(this),i=b,j=a.split(p);while(e=j[g++])i=d?i:!h.hasClass(e),h[i?"addClass":"removeClass"](e)}else if(c==="undefined"||c==="boolean")this.className&&f._data(this,"__className__",this.className),this.className=this.className||a===!1?"":f._data(this,"__className__")||""})},hasClass:function(a){var b=" "+a+" ",c=0,d=this.length;for(;c<d;c++)if(this[c].nodeType===1&&(" "+this[c].className+" ").replace(o," ").indexOf(b)>-1)return!0;return!1},val:function(a){var c,d,e,g=this[0];{if(!!arguments.length){e=f.isFunction(a);return this.each(function(d){var g=f(this),h;if(this.nodeType===1){e?h=a.call(this,d,g.val()):h=a,h==null?h="":typeof h=="number"?h+="":f.isArray(h)&&(h=f.map(h,function(a){return a==null?"":a+""})),c=f.valHooks[this.nodeName.toLowerCase()]||f.valHooks[this.type];if(!c||!("set"in c)||c.set(this,h,"value")===b)this.value=h}})}if(g){c=f.valHooks[g.nodeName.toLowerCase()]||f.valHooks[g.type];if(c&&"get"in c&&(d=c.get(g,"value"))!==b)return d;d=g.value;return typeof d=="string"?d.replace(q,""):d==null?"":d}}}}),f.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,g=a.selectedIndex,h=[],i=a.options,j=a.type==="select-one";if(g<0)return null;c=j?g:0,d=j?g+1:i.length;for(;c<d;c++){e=i[c];if(e.selected&&(f.support.optDisabled?!e.disabled:e.getAttribute("disabled")===null)&&(!e.parentNode.disabled||!f.nodeName(e.parentNode,"optgroup"))){b=f(e).val();if(j)return b;h.push(b)}}if(j&&!h.length&&i.length)return f(i[g]).val();return h},set:function(a,b){var c=f.makeArray(b);f(a).find("option").each(function(){this.selected=f.inArray(f(this).val(),c)>=0}),c.length||(a.selectedIndex=-1);return c}}},attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attr:function(a,c,d,e){var g,h,i,j=a.nodeType;if(!!a&&j!==3&&j!==8&&j!==2){if(e&&c in f.attrFn)return f(a)[c](d);if(typeof a.getAttribute=="undefined")return f.prop(a,c,d);i=j!==1||!f.isXMLDoc(a),i&&(c=c.toLowerCase(),h=f.attrHooks[c]||(u.test(c)?x:w));if(d!==b){if(d===null){f.removeAttr(a,c);return}if(h&&"set"in h&&i&&(g=h.set(a,d,c))!==b)return g;a.setAttribute(c,""+d);return d}if(h&&"get"in h&&i&&(g=h.get(a,c))!==null)return g;g=a.getAttribute(c);return g===null?b:g}},removeAttr:function(a,b){var c,d,e,g,h=0;if(b&&a.nodeType===1){d=b.toLowerCase().split(p),g=d.length;for(;h<g;h++)e=d[h],e&&(c=f.propFix[e]||e,f.attr(a,e,""),a.removeAttribute(v?e:c),u.test(e)&&c in a&&(a[c]=!1))}},attrHooks:{type:{set:function(a,b){if(r.test(a.nodeName)&&a.parentNode)f.error("type property can't be changed");else if(!f.support.radioValue&&b==="radio"&&f.nodeName(a,"input")){var c=a.value;a.setAttribute("type",b),c&&(a.value=c);return b}}},value:{get:function(a,b){if(w&&f.nodeName(a,"button"))return w.get(a,b);return b in a?a.value:null},set:function(a,b,c){if(w&&f.nodeName(a,"button"))return w.set(a,b,c);a.value=b}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(a,c,d){var e,g,h,i=a.nodeType;if(!!a&&i!==3&&i!==8&&i!==2){h=i!==1||!f.isXMLDoc(a),h&&(c=f.propFix[c]||c,g=f.propHooks[c]);return d!==b?g&&"set"in g&&(e=g.set(a,d,c))!==b?e:a[c]=d:g&&"get"in g&&(e=g.get(a,c))!==null?e:a[c]}},propHooks:{tabIndex:{get:function(a){var c=a.getAttributeNode("tabindex");return c&&c.specified?parseInt(c.value,10):s.test(a.nodeName)||t.test(a.nodeName)&&a.href?0:b}}}}),f.attrHooks.tabindex=f.propHooks.tabIndex,x={get:function(a,c){var d,e=f.prop(a,c);return e===!0||typeof e!="boolean"&&(d=a.getAttributeNode(c))&&d.nodeValue!==!1?c.toLowerCase():b},set:function(a,b,c){var d;b===!1?f.removeAttr(a,c):(d=f.propFix[c]||c,d in a&&(a[d]=!0),a.setAttribute(c,c.toLowerCase()));return c}},v||(y={name:!0,id:!0},w=f.valHooks.button={get:function(a,c){var d;d=a.getAttributeNode(c);return d&&(y[c]?d.nodeValue!=="":d.specified)?d.nodeValue:b},set:function(a,b,d){var e=a.getAttributeNode(d);e||(e=c.createAttribute(d),a.setAttributeNode(e));return e.nodeValue=b+""}},f.attrHooks.tabindex.set=w.set,f.each(["width","height"],function(a,b){f.attrHooks[b]=f.extend(f.attrHooks[b],{set:function(a,c){if(c===""){a.setAttribute(b,"auto");return c}}})}),f.attrHooks.contenteditable={get:w.get,set:function(a,b,c){b===""&&(b="false"),w.set(a,b,c)}}),f.support.hrefNormalized||f.each(["href","src","width","height"],function(a,c){f.attrHooks[c]=f.extend(f.attrHooks[c],{get:function(a){var d=a.getAttribute(c,2);return d===null?b:d}})}),f.support.style||(f.attrHooks.style={get:function(a){return a.style.cssText.toLowerCase()||b},set:function(a,b){return a.style.cssText=""+b}}),f.support.optSelected||(f.propHooks.selected=f.extend(f.propHooks.selected,{get:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex);return null}})),f.support.enctype||(f.propFix.enctype="encoding"),f.support.checkOn||f.each(["radio","checkbox"],function(){f.valHooks[this]={get:function(a){return a.getAttribute("value")===null?"on":a.value}}}),f.each(["radio","checkbox"],function(){f.valHooks[this]=f.extend(f.valHooks[this],{set:function(a,b){if(f.isArray(b))return a.checked=f.inArray(f(a).val(),b)>=0}})});var z=/^(?:textarea|input|select)$/i,A=/^([^\.]*)?(?:\.(.+))?$/,B=/\bhover(\.\S+)?\b/,C=/^key/,D=/^(?:mouse|contextmenu)|click/,E=/^(?:focusinfocus|focusoutblur)$/,F=/^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,G=function(a){var b=F.exec(a);b&&(b[1]=(b[1]||"").toLowerCase(),b[3]=b[3]&&new RegExp("(?:^|\\s)"+b[3]+"(?:\\s|$)"));return b},H=function(a,b){var c=a.attributes||{};return(!b[1]||a.nodeName.toLowerCase()===b[1])&&(!b[2]||(c.id||{}).value===b[2])&&(!b[3]||b[3].test((c["class"]||{}).value))},I=function(a){return f.event.special.hover?a:a.replace(B,"mouseenter$1 mouseleave$1")};
-f.event={add:function(a,c,d,e,g){var h,i,j,k,l,m,n,o,p,q,r,s;if(!(a.nodeType===3||a.nodeType===8||!c||!d||!(h=f._data(a)))){d.handler&&(p=d,d=p.handler),d.guid||(d.guid=f.guid++),j=h.events,j||(h.events=j={}),i=h.handle,i||(h.handle=i=function(a){return typeof f!="undefined"&&(!a||f.event.triggered!==a.type)?f.event.dispatch.apply(i.elem,arguments):b},i.elem=a),c=f.trim(I(c)).split(" ");for(k=0;k<c.length;k++){l=A.exec(c[k])||[],m=l[1],n=(l[2]||"").split(".").sort(),s=f.event.special[m]||{},m=(g?s.delegateType:s.bindType)||m,s=f.event.special[m]||{},o=f.extend({type:m,origType:l[1],data:e,handler:d,guid:d.guid,selector:g,quick:G(g),namespace:n.join(".")},p),r=j[m];if(!r){r=j[m]=[],r.delegateCount=0;if(!s.setup||s.setup.call(a,e,n,i)===!1)a.addEventListener?a.addEventListener(m,i,!1):a.attachEvent&&a.attachEvent("on"+m,i)}s.add&&(s.add.call(a,o),o.handler.guid||(o.handler.guid=d.guid)),g?r.splice(r.delegateCount++,0,o):r.push(o),f.event.global[m]=!0}a=null}},global:{},remove:function(a,b,c,d,e){var g=f.hasData(a)&&f._data(a),h,i,j,k,l,m,n,o,p,q,r,s;if(!!g&&!!(o=g.events)){b=f.trim(I(b||"")).split(" ");for(h=0;h<b.length;h++){i=A.exec(b[h])||[],j=k=i[1],l=i[2];if(!j){for(j in o)f.event.remove(a,j+b[h],c,d,!0);continue}p=f.event.special[j]||{},j=(d?p.delegateType:p.bindType)||j,r=o[j]||[],m=r.length,l=l?new RegExp("(^|\\.)"+l.split(".").sort().join("\\.(?:.*\\.)?")+"(\\.|$)"):null;for(n=0;n<r.length;n++)s=r[n],(e||k===s.origType)&&(!c||c.guid===s.guid)&&(!l||l.test(s.namespace))&&(!d||d===s.selector||d==="**"&&s.selector)&&(r.splice(n--,1),s.selector&&r.delegateCount--,p.remove&&p.remove.call(a,s));r.length===0&&m!==r.length&&((!p.teardown||p.teardown.call(a,l)===!1)&&f.removeEvent(a,j,g.handle),delete o[j])}f.isEmptyObject(o)&&(q=g.handle,q&&(q.elem=null),f.removeData(a,["events","handle"],!0))}},customEvent:{getData:!0,setData:!0,changeData:!0},trigger:function(c,d,e,g){if(!e||e.nodeType!==3&&e.nodeType!==8){var h=c.type||c,i=[],j,k,l,m,n,o,p,q,r,s;if(E.test(h+f.event.triggered))return;h.indexOf("!")>=0&&(h=h.slice(0,-1),k=!0),h.indexOf(".")>=0&&(i=h.split("."),h=i.shift(),i.sort());if((!e||f.event.customEvent[h])&&!f.event.global[h])return;c=typeof c=="object"?c[f.expando]?c:new f.Event(h,c):new f.Event(h),c.type=h,c.isTrigger=!0,c.exclusive=k,c.namespace=i.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+i.join("\\.(?:.*\\.)?")+"(\\.|$)"):null,o=h.indexOf(":")<0?"on"+h:"";if(!e){j=f.cache;for(l in j)j[l].events&&j[l].events[h]&&f.event.trigger(c,d,j[l].handle.elem,!0);return}c.result=b,c.target||(c.target=e),d=d!=null?f.makeArray(d):[],d.unshift(c),p=f.event.special[h]||{};if(p.trigger&&p.trigger.apply(e,d)===!1)return;r=[[e,p.bindType||h]];if(!g&&!p.noBubble&&!f.isWindow(e)){s=p.delegateType||h,m=E.test(s+h)?e:e.parentNode,n=null;for(;m;m=m.parentNode)r.push([m,s]),n=m;n&&n===e.ownerDocument&&r.push([n.defaultView||n.parentWindow||a,s])}for(l=0;l<r.length&&!c.isPropagationStopped();l++)m=r[l][0],c.type=r[l][1],q=(f._data(m,"events")||{})[c.type]&&f._data(m,"handle"),q&&q.apply(m,d),q=o&&m[o],q&&f.acceptData(m)&&q.apply(m,d)===!1&&c.preventDefault();c.type=h,!g&&!c.isDefaultPrevented()&&(!p._default||p._default.apply(e.ownerDocument,d)===!1)&&(h!=="click"||!f.nodeName(e,"a"))&&f.acceptData(e)&&o&&e[h]&&(h!=="focus"&&h!=="blur"||c.target.offsetWidth!==0)&&!f.isWindow(e)&&(n=e[o],n&&(e[o]=null),f.event.triggered=h,e[h](),f.event.triggered=b,n&&(e[o]=n));return c.result}},dispatch:function(c){c=f.event.fix(c||a.event);var d=(f._data(this,"events")||{})[c.type]||[],e=d.delegateCount,g=[].slice.call(arguments,0),h=!c.exclusive&&!c.namespace,i=[],j,k,l,m,n,o,p,q,r,s,t;g[0]=c,c.delegateTarget=this;if(e&&!c.target.disabled&&(!c.button||c.type!=="click")){m=f(this),m.context=this.ownerDocument||this;for(l=c.target;l!=this;l=l.parentNode||this){o={},q=[],m[0]=l;for(j=0;j<e;j++)r=d[j],s=r.selector,o[s]===b&&(o[s]=r.quick?H(l,r.quick):m.is(s)),o[s]&&q.push(r);q.length&&i.push({elem:l,matches:q})}}d.length>e&&i.push({elem:this,matches:d.slice(e)});for(j=0;j<i.length&&!c.isPropagationStopped();j++){p=i[j],c.currentTarget=p.elem;for(k=0;k<p.matches.length&&!c.isImmediatePropagationStopped();k++){r=p.matches[k];if(h||!c.namespace&&!r.namespace||c.namespace_re&&c.namespace_re.test(r.namespace))c.data=r.data,c.handleObj=r,n=((f.event.special[r.origType]||{}).handle||r.handler).apply(p.elem,g),n!==b&&(c.result=n,n===!1&&(c.preventDefault(),c.stopPropagation()))}}return c.result},props:"attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(a,b){a.which==null&&(a.which=b.charCode!=null?b.charCode:b.keyCode);return a}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(a,d){var e,f,g,h=d.button,i=d.fromElement;a.pageX==null&&d.clientX!=null&&(e=a.target.ownerDocument||c,f=e.documentElement,g=e.body,a.pageX=d.clientX+(f&&f.scrollLeft||g&&g.scrollLeft||0)-(f&&f.clientLeft||g&&g.clientLeft||0),a.pageY=d.clientY+(f&&f.scrollTop||g&&g.scrollTop||0)-(f&&f.clientTop||g&&g.clientTop||0)),!a.relatedTarget&&i&&(a.relatedTarget=i===a.target?d.toElement:i),!a.which&&h!==b&&(a.which=h&1?1:h&2?3:h&4?2:0);return a}},fix:function(a){if(a[f.expando])return a;var d,e,g=a,h=f.event.fixHooks[a.type]||{},i=h.props?this.props.concat(h.props):this.props;a=f.Event(g);for(d=i.length;d;)e=i[--d],a[e]=g[e];a.target||(a.target=g.srcElement||c),a.target.nodeType===3&&(a.target=a.target.parentNode),a.metaKey===b&&(a.metaKey=a.ctrlKey);return h.filter?h.filter(a,g):a},special:{ready:{setup:f.bindReady},load:{noBubble:!0},focus:{delegateType:"focusin"},blur:{delegateType:"focusout"},beforeunload:{setup:function(a,b,c){f.isWindow(this)&&(this.onbeforeunload=c)},teardown:function(a,b){this.onbeforeunload===b&&(this.onbeforeunload=null)}}},simulate:function(a,b,c,d){var e=f.extend(new f.Event,c,{type:a,isSimulated:!0,originalEvent:{}});d?f.event.trigger(e,null,b):f.event.dispatch.call(b,e),e.isDefaultPrevented()&&c.preventDefault()}},f.event.handle=f.event.dispatch,f.removeEvent=c.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)}:function(a,b,c){a.detachEvent&&a.detachEvent("on"+b,c)},f.Event=function(a,b){if(!(this instanceof f.Event))return new f.Event(a,b);a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||a.returnValue===!1||a.getPreventDefault&&a.getPreventDefault()?K:J):this.type=a,b&&f.extend(this,b),this.timeStamp=a&&a.timeStamp||f.now(),this[f.expando]=!0},f.Event.prototype={preventDefault:function(){this.isDefaultPrevented=K;var a=this.originalEvent;!a||(a.preventDefault?a.preventDefault():a.returnValue=!1)},stopPropagation:function(){this.isPropagationStopped=K;var a=this.originalEvent;!a||(a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=K,this.stopPropagation()},isDefaultPrevented:J,isPropagationStopped:J,isImmediatePropagationStopped:J},f.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){f.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c=this,d=a.relatedTarget,e=a.handleObj,g=e.selector,h;if(!d||d!==c&&!f.contains(c,d))a.type=e.origType,h=e.handler.apply(this,arguments),a.type=b;return h}}}),f.support.submitBubbles||(f.event.special.submit={setup:function(){if(f.nodeName(this,"form"))return!1;f.event.add(this,"click._submit keypress._submit",function(a){var c=a.target,d=f.nodeName(c,"input")||f.nodeName(c,"button")?c.form:b;d&&!d._submit_attached&&(f.event.add(d,"submit._submit",function(a){this.parentNode&&!a.isTrigger&&f.event.simulate("submit",this.parentNode,a,!0)}),d._submit_attached=!0)})},teardown:function(){if(f.nodeName(this,"form"))return!1;f.event.remove(this,"._submit")}}),f.support.changeBubbles||(f.event.special.change={setup:function(){if(z.test(this.nodeName)){if(this.type==="checkbox"||this.type==="radio")f.event.add(this,"propertychange._change",function(a){a.originalEvent.propertyName==="checked"&&(this._just_changed=!0)}),f.event.add(this,"click._change",function(a){this._just_changed&&!a.isTrigger&&(this._just_changed=!1,f.event.simulate("change",this,a,!0))});return!1}f.event.add(this,"beforeactivate._change",function(a){var b=a.target;z.test(b.nodeName)&&!b._change_attached&&(f.event.add(b,"change._change",function(a){this.parentNode&&!a.isSimulated&&!a.isTrigger&&f.event.simulate("change",this.parentNode,a,!0)}),b._change_attached=!0)})},handle:function(a){var b=a.target;if(this!==b||a.isSimulated||a.isTrigger||b.type!=="radio"&&b.type!=="checkbox")return a.handleObj.handler.apply(this,arguments)},teardown:function(){f.event.remove(this,"._change");return z.test(this.nodeName)}}),f.support.focusinBubbles||f.each({focus:"focusin",blur:"focusout"},function(a,b){var d=0,e=function(a){f.event.simulate(b,a.target,f.event.fix(a),!0)};f.event.special[b]={setup:function(){d++===0&&c.addEventListener(a,e,!0)},teardown:function(){--d===0&&c.removeEventListener(a,e,!0)}}}),f.fn.extend({on:function(a,c,d,e,g){var h,i;if(typeof a=="object"){typeof c!="string"&&(d=c,c=b);for(i in a)this.on(i,c,d,a[i],g);return this}d==null&&e==null?(e=c,d=c=b):e==null&&(typeof c=="string"?(e=d,d=b):(e=d,d=c,c=b));if(e===!1)e=J;else if(!e)return this;g===1&&(h=e,e=function(a){f().off(a);return h.apply(this,arguments)},e.guid=h.guid||(h.guid=f.guid++));return this.each(function(){f.event.add(this,a,e,d,c)})},one:function(a,b,c,d){return this.on.call(this,a,b,c,d,1)},off:function(a,c,d){if(a&&a.preventDefault&&a.handleObj){var e=a.handleObj;f(a.delegateTarget).off(e.namespace?e.type+"."+e.namespace:e.type,e.selector,e.handler);return this}if(typeof a=="object"){for(var g in a)this.off(g,c,a[g]);return this}if(c===!1||typeof c=="function")d=c,c=b;d===!1&&(d=J);return this.each(function(){f.event.remove(this,a,d,c)})},bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},live:function(a,b,c){f(this.context).on(a,this.selector,b,c);return this},die:function(a,b){f(this.context).off(a,this.selector||"**",b);return this},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return arguments.length==1?this.off(a,"**"):this.off(b,a,c)},trigger:function(a,b){return this.each(function(){f.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0])return f.event.trigger(a,b,this[0],!0)},toggle:function(a){var b=arguments,c=a.guid||f.guid++,d=0,e=function(c){var e=(f._data(this,"lastToggle"+a.guid)||0)%d;f._data(this,"lastToggle"+a.guid,e+1),c.preventDefault();return b[e].apply(this,arguments)||!1};e.guid=c;while(d<b.length)b[d++].guid=c;return this.click(e)},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}}),f.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(a,b){f.fn[b]=function(a,c){c==null&&(c=a,a=null);return arguments.length>0?this.on(b,null,a,c):this.trigger(b)},f.attrFn&&(f.attrFn[b]=!0),C.test(b)&&(f.event.fixHooks[b]=f.event.keyHooks),D.test(b)&&(f.event.fixHooks[b]=f.event.mouseHooks)}),function(){function x(a,b,c,e,f,g){for(var h=0,i=e.length;h<i;h++){var j=e[h];if(j){var k=!1;j=j[a];while(j){if(j[d]===c){k=e[j.sizset];break}if(j.nodeType===1){g||(j[d]=c,j.sizset=h);if(typeof b!="string"){if(j===b){k=!0;break}}else if(m.filter(b,[j]).length>0){k=j;break}}j=j[a]}e[h]=k}}}function w(a,b,c,e,f,g){for(var h=0,i=e.length;h<i;h++){var j=e[h];if(j){var k=!1;j=j[a];while(j){if(j[d]===c){k=e[j.sizset];break}j.nodeType===1&&!g&&(j[d]=c,j.sizset=h);if(j.nodeName.toLowerCase()===b){k=j;break}j=j[a]}e[h]=k}}}var a=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,d="sizcache"+(Math.random()+"").replace(".",""),e=0,g=Object.prototype.toString,h=!1,i=!0,j=/\\/g,k=/\r\n/g,l=/\W/;[0,0].sort(function(){i=!1;return 0});var m=function(b,d,e,f){e=e||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!="string")return e;var i,j,k,l,n,q,r,t,u=!0,v=m.isXML(d),w=[],x=b;do{a.exec(""),i=a.exec(x);if(i){x=i[3],w.push(i[1]);if(i[2]){l=i[3];break}}}while(i);if(w.length>1&&p.exec(b))if(w.length===2&&o.relative[w[0]])j=y(w[0]+w[1],d,f);else{j=o.relative[w[0]]?[d]:m(w.shift(),d);while(w.length)b=w.shift(),o.relative[b]&&(b+=w.shift()),j=y(b,j,f)}else{!f&&w.length>1&&d.nodeType===9&&!v&&o.match.ID.test(w[0])&&!o.match.ID.test(w[w.length-1])&&(n=m.find(w.shift(),d,v),d=n.expr?m.filter(n.expr,n.set)[0]:n.set[0]);if(d){n=f?{expr:w.pop(),set:s(f)}:m.find(w.pop(),w.length===1&&(w[0]==="~"||w[0]==="+")&&d.parentNode?d.parentNode:d,v),j=n.expr?m.filter(n.expr,n.set):n.set,w.length>0?k=s(j):u=!1;while(w.length)q=w.pop(),r=q,o.relative[q]?r=w.pop():q="",r==null&&(r=d),o.relative[q](k,r,v)}else k=w=[]}k||(k=j),k||m.error(q||b);if(g.call(k)==="[object Array]")if(!u)e.push.apply(e,k);else if(d&&d.nodeType===1)for(t=0;k[t]!=null;t++)k[t]&&(k[t]===!0||k[t].nodeType===1&&m.contains(d,k[t]))&&e.push(j[t]);else for(t=0;k[t]!=null;t++)k[t]&&k[t].nodeType===1&&e.push(j[t]);else s(k,e);l&&(m(l,h,e,f),m.uniqueSort(e));return e};m.uniqueSort=function(a){if(u){h=i,a.sort(u);if(h)for(var b=1;b<a.length;b++)a[b]===a[b-1]&&a.splice(b--,1)}return a},m.matches=function(a,b){return m(a,null,null,b)},m.matchesSelector=function(a,b){return m(b,null,null,[a]).length>0},m.find=function(a,b,c){var d,e,f,g,h,i;if(!a)return[];for(e=0,f=o.order.length;e<f;e++){h=o.order[e];if(g=o.leftMatch[h].exec(a)){i=g[1],g.splice(1,1);if(i.substr(i.length-1)!=="\\"){g[1]=(g[1]||"").replace(j,""),d=o.find[h](g,b,c);if(d!=null){a=a.replace(o.match[h],"");break}}}}d||(d=typeof b.getElementsByTagName!="undefined"?b.getElementsByTagName("*"):[]);return{set:d,expr:a}},m.filter=function(a,c,d,e){var f,g,h,i,j,k,l,n,p,q=a,r=[],s=c,t=c&&c[0]&&m.isXML(c[0]);while(a&&c.length){for(h in o.filter)if((f=o.leftMatch[h].exec(a))!=null&&f[2]){k=o.filter[h],l=f[1],g=!1,f.splice(1,1);if(l.substr(l.length-1)==="\\")continue;s===r&&(r=[]);if(o.preFilter[h]){f=o.preFilter[h](f,s,d,r,e,t);if(!f)g=i=!0;else if(f===!0)continue}if(f)for(n=0;(j=s[n])!=null;n++)j&&(i=k(j,f,n,s),p=e^i,d&&i!=null?p?g=!0:s[n]=!1:p&&(r.push(j),g=!0));if(i!==b){d||(s=r),a=a.replace(o.match[h],"");if(!g)return[];break}}if(a===q)if(g==null)m.error(a);else break;q=a}return s},m.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)};var n=m.getText=function(a){var b,c,d=a.nodeType,e="";if(d){if(d===1||d===9){if(typeof a.textContent=="string")return a.textContent;if(typeof a.innerText=="string")return a.innerText.replace(k,"");for(a=a.firstChild;a;a=a.nextSibling)e+=n(a)}else if(d===3||d===4)return a.nodeValue}else for(b=0;c=a[b];b++)c.nodeType!==8&&(e+=n(c));return e},o=m.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,CLASS:/\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(a){return a.getAttribute("href")},type:function(a){return a.getAttribute("type")}},relative:{"+":function(a,b){var c=typeof b=="string",d=c&&!l.test(b),e=c&&!d;d&&(b=b.toLowerCase());for(var f=0,g=a.length,h;f<g;f++)if(h=a[f]){while((h=h.previousSibling)&&h.nodeType!==1);a[f]=e||h&&h.nodeName.toLowerCase()===b?h||!1:h===b}e&&m.filter(b,a,!0)},">":function(a,b){var c,d=typeof b=="string",e=0,f=a.length;if(d&&!l.test(b)){b=b.toLowerCase();for(;e<f;e++){c=a[e];if(c){var g=c.parentNode;a[e]=g.nodeName.toLowerCase()===b?g:!1}}}else{for(;e<f;e++)c=a[e],c&&(a[e]=d?c.parentNode:c.parentNode===b);d&&m.filter(b,a,!0)}},"":function(a,b,c){var d,f=e++,g=x;typeof b=="string"&&!l.test(b)&&(b=b.toLowerCase(),d=b,g=w),g("parentNode",b,f,a,d,c)},"~":function(a,b,c){var d,f=e++,g=x;typeof b=="string"&&!l.test(b)&&(b=b.toLowerCase(),d=b,g=w),g("previousSibling",b,f,a,d,c)}},find:{ID:function(a,b,c){if(typeof b.getElementById!="undefined"&&!c){var d=b.getElementById(a[1]);return d&&d.parentNode?[d]:[]}},NAME:function(a,b){if(typeof b.getElementsByName!="undefined"){var c=[],d=b.getElementsByName(a[1]);for(var e=0,f=d.length;e<f;e++)d[e].getAttribute("name")===a[1]&&c.push(d[e]);return c.length===0?null:c}},TAG:function(a,b){if(typeof b.getElementsByTagName!="undefined")return b.getElementsByTagName(a[1])}},preFilter:{CLASS:function(a,b,c,d,e,f){a=" "+a[1].replace(j,"")+" ";if(f)return a;for(var g=0,h;(h=b[g])!=null;g++)h&&(e^(h.className&&(" "+h.className+" ").replace(/[\t\n\r]/g," ").indexOf(a)>=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(j,"")},TAG:function(a,b){return a[1].replace(j,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||m.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&m.error(a[0]);a[0]=e++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(j,"");!f&&o.attrMap[g]&&(a[1]=o.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(j,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=m(b[3],null,null,c);else{var g=m.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(o.match.POS.test(b[0])||o.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!m(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute("type"),c=a.type;return a.nodeName.toLowerCase()==="input"&&"text"===c&&(b===c||b===null)},radio:function(a){return a.nodeName.toLowerCase()==="input"&&"radio"===a.type},checkbox:function(a){return a.nodeName.toLowerCase()==="input"&&"checkbox"===a.type},file:function(a){return a.nodeName.toLowerCase()==="input"&&"file"===a.type},password:function(a){return a.nodeName.toLowerCase()==="input"&&"password"===a.type},submit:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"submit"===a.type},image:function(a){return a.nodeName.toLowerCase()==="input"&&"image"===a.type},reset:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"reset"===a.type},button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&"button"===a.type||b==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)},focus:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return b<c[3]-0},gt:function(a,b,c){return b>c[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=o.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||n([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h<i;h++)if(g[h]===a)return!1;return!0}m.error(e)},CHILD:function(a,b){var c,e,f,g,h,i,j,k=b[1],l=a;switch(k){case"only":case"first":while(l=l.previousSibling)if(l.nodeType===1)return!1;if(k==="first")return!0;l=a;case"last":while(l=l.nextSibling)if(l.nodeType===1)return!1;return!0;case"nth":c=b[2],e=b[3];if(c===1&&e===0)return!0;f=b[0],g=a.parentNode;if(g&&(g[d]!==f||!a.nodeIndex)){i=0;for(l=g.firstChild;l;l=l.nextSibling)l.nodeType===1&&(l.nodeIndex=++i);g[d]=f}j=a.nodeIndex-e;return c===0?j===0:j%c===0&&j/c>=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||!!a.nodeName&&a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=m.attr?m.attr(a,c):o.attrHandle[c]?o.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":!f&&m.attr?d!=null:f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=o.setFilters[e];if(f)return f(a,c,b,d)}}},p=o.match.POS,q=function(a,b){return"\\"+(b-0+1)};for(var r in o.match)o.match[r]=new RegExp(o.match[r].source+/(?![^\[]*\])(?![^\(]*\))/.source),o.leftMatch[r]=new RegExp(/(^(?:.|\r|\n)*?)/.source+o.match[r].source.replace(/\\(\d+)/g,q));var s=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(t){s=function(a,b){var c=0,d=b||[];if(g.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length=="number")for(var e=a.length;c<e;c++)d.push(a[c]);else for(;a[c];c++)d.push(a[c]);return d}}var u,v;c.documentElement.compareDocumentPosition?u=function(a,b){if(a===b){h=!0;return 0}if(!a.compareDocumentPosition||!b.compareDocumentPosition)return a.compareDocumentPosition?-1:1;return a.compareDocumentPosition(b)&4?-1:1}:(u=function(a,b){if(a===b){h=!0;return 0}if(a.sourceIndex&&b.sourceIndex)return a.sourceIndex-b.sourceIndex;var c,d,e=[],f=[],g=a.parentNode,i=b.parentNode,j=g;if(g===i)return v(a,b);if(!g)return-1;if(!i)return 1;while(j)e.unshift(j),j=j.parentNode;j=i;while(j)f.unshift(j),j=j.parentNode;c=e.length,d=f.length;for(var k=0;k<c&&k<d;k++)if(e[k]!==f[k])return v(e[k],f[k]);return k===c?v(a,f[k],-1):v(e[k],b,1)},v=function(a,b,c){if(a===b)return c;var d=a.nextSibling;while(d){if(d===b)return-1;d=d.nextSibling}return 1}),function(){var a=c.createElement("div"),d="script"+(new Date).getTime(),e=c.documentElement;a.innerHTML="<a name='"+d+"'/>",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(o.find.ID=function(a,c,d){if(typeof c.getElementById!="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},o.filter.ID=function(a,b){var c=typeof a.getAttributeNode!="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(o.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="<a href='#'></a>",a.firstChild&&typeof a.firstChild.getAttribute!="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(o.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=m,b=c.createElement("div"),d="__sizzle__";b.innerHTML="<p class='TEST'></p>";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){m=function(b,e,f,g){e=e||c;if(!g&&!m.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return s(e.getElementsByTagName(b),f);if(h[2]&&o.find.CLASS&&e.getElementsByClassName)return s(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return s([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return s([],f);if(i.id===h[3])return s([i],f)}try{return s(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var k=e,l=e.getAttribute("id"),n=l||d,p=e.parentNode,q=/^\s*[+~]/.test(b);l?n=n.replace(/'/g,"\\$&"):e.setAttribute("id",n),q&&p&&(e=e.parentNode);try{if(!q||p)return s(e.querySelectorAll("[id='"+n+"'] "+b),f)}catch(r){}finally{l||k.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)m[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var d=!b.call(c.createElement("div"),"div"),e=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(f){e=!0}m.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!m.isXML(a))try{if(e||!o.match.PSEUDO.test(c)&&!/!=/.test(c)){var f=b.call(a,c);if(f||!d||a.document&&a.document.nodeType!==11)return f}}catch(g){}return m(c,null,null,[a]).length>0}}}(),function(){var a=c.createElement("div");a.innerHTML="<div class='test e'></div><div class='test'></div>";if(!!a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;o.order.splice(1,0,"CLASS"),o.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?m.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?m.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:m.contains=function(){return!1},m.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var y=function(a,b,c){var d,e=[],f="",g=b.nodeType?[b]:b;while(d=o.match.PSEUDO.exec(a))f+=d[0],a=a.replace(o.match.PSEUDO,"");a=o.relative[a]?a+"*":a;for(var h=0,i=g.length;h<i;h++)m(a,g[h],e,c);return m.filter(f,e)};m.attr=f.attr,m.selectors.attrMap={},f.find=m,f.expr=m.selectors,f.expr[":"]=f.expr.filters,f.unique=m.uniqueSort,f.text=m.getText,f.isXMLDoc=m.isXML,f.contains=m.contains}();var L=/Until$/,M=/^(?:parents|prevUntil|prevAll)/,N=/,/,O=/^.[^:#\[\.,]*$/,P=Array.prototype.slice,Q=f.expr.match.POS,R={children:!0,contents:!0,next:!0,prev:!0};f.fn.extend({find:function(a){var b=this,c,d;if(typeof a!="string")return f(a).filter(function(){for(c=0,d=b.length;c<d;c++)if(f.contains(b[c],this))return!0});var e=this.pushStack("","find",a),g,h,i;for(c=0,d=this.length;c<d;c++){g=e.length,f.find(a,this[c],e);if(c>0)for(h=g;h<e.length;h++)for(i=0;i<g;i++)if(e[i]===e[h]){e.splice(h--,1);break}}return e},has:function(a){var b=f(a);return this.filter(function(){for(var a=0,c=b.length;a<c;a++)if(f.contains(this,b[a]))return!0})},not:function(a){return this.pushStack(T(this,a,!1),"not",a)},filter:function(a){return this.pushStack(T(this,a,!0),"filter",a)},is:function(a){return!!a&&(typeof a=="string"?Q.test(a)?f(a,this.context).index(this[0])>=0:f.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c=[],d,e,g=this[0];if(f.isArray(a)){var h=1;while(g&&g.ownerDocument&&g!==b){for(d=0;d<a.length;d++)f(g).is(a[d])&&c.push({selector:a[d],elem:g,level:h});g=g.parentNode,h++}return c}var i=Q.test(a)||typeof a!="string"?f(a,b||this.context):0;for(d=0,e=this.length;d<e;d++){g=this[d];while(g){if(i?i.index(g)>-1:f.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b||g.nodeType===11)break}}c=c.length>1?f.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a)return this[0]&&this[0].parentNode?this.prevAll().length:-1;if(typeof a=="string")return f.inArray(this[0],f(a));return f.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a=="string"?f(a,b):f.makeArray(a&&a.nodeType?[a]:a),d=f.merge(this.get(),c);return this.pushStack(S(c[0])||S(d[0])?d:f.unique(d))},andSelf:function(){return this.add(this.prevObject)}}),f.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return f.dir(a,"parentNode")},parentsUntil:function(a,b,c){return f.dir(a,"parentNode",c)},next:function(a){return f.nth(a,2,"nextSibling")},prev:function(a){return f.nth(a,2,"previousSibling")},nextAll:function(a){return f.dir(a,"nextSibling")},prevAll:function(a){return f.dir(a,"previousSibling")},nextUntil:function(a,b,c){return f.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return f.dir(a,"previousSibling",c)},siblings:function(a){return f.sibling(a.parentNode.firstChild,a)},children:function(a){return f.sibling(a.firstChild)},contents:function(a){return f.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:f.makeArray(a.childNodes)}},function(a,b){f.fn[a]=function(c,d){var e=f.map(this,b,c);L.test(a)||(d=c),d&&typeof d=="string"&&(e=f.filter(d,e)),e=this.length>1&&!R[a]?f.unique(e):e,(this.length>1||N.test(d))&&M.test(a)&&(e=e.reverse());return this.pushStack(e,a,P.call(arguments).join(","))}}),f.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?f.find.matchesSelector(b[0],a)?[b[0]]:[]:f.find.matches(a,b)},dir:function(a,c,d){var e=[],g=a[c];while(g&&g.nodeType!==9&&(d===b||g.nodeType!==1||!f(g).is(d)))g.nodeType===1&&e.push(g),g=g[c];return e},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var V="abbr|article|aside|audio|canvas|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",W=/ jQuery\d+="(?:\d+|null)"/g,X=/^\s+/,Y=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,Z=/<([\w:]+)/,$=/<tbody/i,_=/<|&#?\w+;/,ba=/<(?:script|style)/i,bb=/<(?:script|object|embed|option|style)/i,bc=new RegExp("<(?:"+V+")","i"),bd=/checked\s*(?:[^=]|=\s*.checked.)/i,be=/\/(java|ecma)script/i,bf=/^\s*<!(?:\[CDATA\[|\-\-)/,bg={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]},bh=U(c);bg.optgroup=bg.option,bg.tbody=bg.tfoot=bg.colgroup=bg.caption=bg.thead,bg.th=bg.td,f.support.htmlSerialize||(bg._default=[1,"div<div>","</div>"]),f.fn.extend({text:function(a){if(f.isFunction(a))return this.each(function(b){var c=f(this);c.text(a.call(this,b,c.text()))});if(typeof a!="object"&&a!==b)return this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a));return f.text(this)},wrapAll:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapAll(a.call(this,b))});if(this[0]){var b=f(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapInner(a.call(this,b))});return this.each(function(){var b=f(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=f.isFunction(a);return this.each(function(c){f(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){f.nodeName(this,"body")||f(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=f.clean(arguments);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,f.clean(arguments));return a}},remove:function(a,b){for(var c=0,d;(d=this[c])!=null;c++)if(!a||f.filter(a,[d]).length)!b&&d.nodeType===1&&(f.cleanData(d.getElementsByTagName("*")),f.cleanData([d])),d.parentNode&&d.parentNode.removeChild(d);return this},empty:function()
-{for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&f.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return f.clone(this,a,b)})},html:function(a){if(a===b)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(W,""):null;if(typeof a=="string"&&!ba.test(a)&&(f.support.leadingWhitespace||!X.test(a))&&!bg[(Z.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Y,"<$1></$2>");try{for(var c=0,d=this.length;c<d;c++)this[c].nodeType===1&&(f.cleanData(this[c].getElementsByTagName("*")),this[c].innerHTML=a)}catch(e){this.empty().append(a)}}else f.isFunction(a)?this.each(function(b){var c=f(this);c.html(a.call(this,b,c.html()))}):this.empty().append(a);return this},replaceWith:function(a){if(this[0]&&this[0].parentNode){if(f.isFunction(a))return this.each(function(b){var c=f(this),d=c.html();c.replaceWith(a.call(this,b,d))});typeof a!="string"&&(a=f(a).detach());return this.each(function(){var b=this.nextSibling,c=this.parentNode;f(this).remove(),b?f(b).before(a):f(c).append(a)})}return this.length?this.pushStack(f(f.isFunction(a)?a():a),"replaceWith",a):this},detach:function(a){return this.remove(a,!0)},domManip:function(a,c,d){var e,g,h,i,j=a[0],k=[];if(!f.support.checkClone&&arguments.length===3&&typeof j=="string"&&bd.test(j))return this.each(function(){f(this).domManip(a,c,d,!0)});if(f.isFunction(j))return this.each(function(e){var g=f(this);a[0]=j.call(this,e,c?g.html():b),g.domManip(a,c,d)});if(this[0]){i=j&&j.parentNode,f.support.parentNode&&i&&i.nodeType===11&&i.childNodes.length===this.length?e={fragment:i}:e=f.buildFragment(a,this,k),h=e.fragment,h.childNodes.length===1?g=h=h.firstChild:g=h.firstChild;if(g){c=c&&f.nodeName(g,"tr");for(var l=0,m=this.length,n=m-1;l<m;l++)d.call(c?bi(this[l],g):this[l],e.cacheable||m>1&&l<n?f.clone(h,!0,!0):h)}k.length&&f.each(k,bp)}return this}}),f.buildFragment=function(a,b,d){var e,g,h,i,j=a[0];b&&b[0]&&(i=b[0].ownerDocument||b[0]),i.createDocumentFragment||(i=c),a.length===1&&typeof j=="string"&&j.length<512&&i===c&&j.charAt(0)==="<"&&!bb.test(j)&&(f.support.checkClone||!bd.test(j))&&(f.support.html5Clone||!bc.test(j))&&(g=!0,h=f.fragments[j],h&&h!==1&&(e=h)),e||(e=i.createDocumentFragment(),f.clean(a,i,e,d)),g&&(f.fragments[j]=h?e:1);return{fragment:e,cacheable:g}},f.fragments={},f.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){f.fn[a]=function(c){var d=[],e=f(c),g=this.length===1&&this[0].parentNode;if(g&&g.nodeType===11&&g.childNodes.length===1&&e.length===1){e[b](this[0]);return this}for(var h=0,i=e.length;h<i;h++){var j=(h>0?this.clone(!0):this).get();f(e[h])[b](j),d=d.concat(j)}return this.pushStack(d,a,e.selector)}}),f.extend({clone:function(a,b,c){var d,e,g,h=f.support.html5Clone||!bc.test("<"+a.nodeName)?a.cloneNode(!0):bo(a);if((!f.support.noCloneEvent||!f.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!f.isXMLDoc(a)){bk(a,h),d=bl(a),e=bl(h);for(g=0;d[g];++g)e[g]&&bk(d[g],e[g])}if(b){bj(a,h);if(c){d=bl(a),e=bl(h);for(g=0;d[g];++g)bj(d[g],e[g])}}d=e=null;return h},clean:function(a,b,d,e){var g;b=b||c,typeof b.createElement=="undefined"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);var h=[],i;for(var j=0,k;(k=a[j])!=null;j++){typeof k=="number"&&(k+="");if(!k)continue;if(typeof k=="string")if(!_.test(k))k=b.createTextNode(k);else{k=k.replace(Y,"<$1></$2>");var l=(Z.exec(k)||["",""])[1].toLowerCase(),m=bg[l]||bg._default,n=m[0],o=b.createElement("div");b===c?bh.appendChild(o):U(b).appendChild(o),o.innerHTML=m[1]+k+m[2];while(n--)o=o.lastChild;if(!f.support.tbody){var p=$.test(k),q=l==="table"&&!p?o.firstChild&&o.firstChild.childNodes:m[1]==="<table>"&&!p?o.childNodes:[];for(i=q.length-1;i>=0;--i)f.nodeName(q[i],"tbody")&&!q[i].childNodes.length&&q[i].parentNode.removeChild(q[i])}!f.support.leadingWhitespace&&X.test(k)&&o.insertBefore(b.createTextNode(X.exec(k)[0]),o.firstChild),k=o.childNodes}var r;if(!f.support.appendChecked)if(k[0]&&typeof (r=k.length)=="number")for(i=0;i<r;i++)bn(k[i]);else bn(k);k.nodeType?h.push(k):h=f.merge(h,k)}if(d){g=function(a){return!a.type||be.test(a.type)};for(j=0;h[j];j++)if(e&&f.nodeName(h[j],"script")&&(!h[j].type||h[j].type.toLowerCase()==="text/javascript"))e.push(h[j].parentNode?h[j].parentNode.removeChild(h[j]):h[j]);else{if(h[j].nodeType===1){var s=f.grep(h[j].getElementsByTagName("script"),g);h.splice.apply(h,[j+1,0].concat(s))}d.appendChild(h[j])}}return h},cleanData:function(a){var b,c,d=f.cache,e=f.event.special,g=f.support.deleteExpando;for(var h=0,i;(i=a[h])!=null;h++){if(i.nodeName&&f.noData[i.nodeName.toLowerCase()])continue;c=i[f.expando];if(c){b=d[c];if(b&&b.events){for(var j in b.events)e[j]?f.event.remove(i,j):f.removeEvent(i,j,b.handle);b.handle&&(b.handle.elem=null)}g?delete i[f.expando]:i.removeAttribute&&i.removeAttribute(f.expando),delete d[c]}}}});var bq=/alpha\([^)]*\)/i,br=/opacity=([^)]*)/,bs=/([A-Z]|^ms)/g,bt=/^-?\d+(?:px)?$/i,bu=/^-?\d/,bv=/^([\-+])=([\-+.\de]+)/,bw={position:"absolute",visibility:"hidden",display:"block"},bx=["Left","Right"],by=["Top","Bottom"],bz,bA,bB;f.fn.css=function(a,c){if(arguments.length===2&&c===b)return this;return f.access(this,a,c,!0,function(a,c,d){return d!==b?f.style(a,c,d):f.css(a,c)})},f.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=bz(a,"opacity","opacity");return c===""?"1":c}return a.style.opacity}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":f.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,d,e){if(!!a&&a.nodeType!==3&&a.nodeType!==8&&!!a.style){var g,h,i=f.camelCase(c),j=a.style,k=f.cssHooks[i];c=f.cssProps[i]||i;if(d===b){if(k&&"get"in k&&(g=k.get(a,!1,e))!==b)return g;return j[c]}h=typeof d,h==="string"&&(g=bv.exec(d))&&(d=+(g[1]+1)*+g[2]+parseFloat(f.css(a,c)),h="number");if(d==null||h==="number"&&isNaN(d))return;h==="number"&&!f.cssNumber[i]&&(d+="px");if(!k||!("set"in k)||(d=k.set(a,d))!==b)try{j[c]=d}catch(l){}}},css:function(a,c,d){var e,g;c=f.camelCase(c),g=f.cssHooks[c],c=f.cssProps[c]||c,c==="cssFloat"&&(c="float");if(g&&"get"in g&&(e=g.get(a,!0,d))!==b)return e;if(bz)return bz(a,c)},swap:function(a,b,c){var d={};for(var e in b)d[e]=a.style[e],a.style[e]=b[e];c.call(a);for(e in b)a.style[e]=d[e]}}),f.curCSS=f.css,f.each(["height","width"],function(a,b){f.cssHooks[b]={get:function(a,c,d){var e;if(c){if(a.offsetWidth!==0)return bC(a,b,d);f.swap(a,bw,function(){e=bC(a,b,d)});return e}},set:function(a,b){if(!bt.test(b))return b;b=parseFloat(b);if(b>=0)return b+"px"}}}),f.support.opacity||(f.cssHooks.opacity={get:function(a,b){return br.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=f.isNumeric(b)?"alpha(opacity="+b*100+")":"",g=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&f.trim(g.replace(bq,""))===""){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bq.test(g)?g.replace(bq,e):g+" "+e}}),f(function(){f.support.reliableMarginRight||(f.cssHooks.marginRight={get:function(a,b){var c;f.swap(a,{display:"inline-block"},function(){b?c=bz(a,"margin-right","marginRight"):c=a.style.marginRight});return c}})}),c.defaultView&&c.defaultView.getComputedStyle&&(bA=function(a,b){var c,d,e;b=b.replace(bs,"-$1").toLowerCase(),(d=a.ownerDocument.defaultView)&&(e=d.getComputedStyle(a,null))&&(c=e.getPropertyValue(b),c===""&&!f.contains(a.ownerDocument.documentElement,a)&&(c=f.style(a,b)));return c}),c.documentElement.currentStyle&&(bB=function(a,b){var c,d,e,f=a.currentStyle&&a.currentStyle[b],g=a.style;f===null&&g&&(e=g[b])&&(f=e),!bt.test(f)&&bu.test(f)&&(c=g.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),g.left=b==="fontSize"?"1em":f||0,f=g.pixelLeft+"px",g.left=c,d&&(a.runtimeStyle.left=d));return f===""?"auto":f}),bz=bA||bB,f.expr&&f.expr.filters&&(f.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!f.support.reliableHiddenOffsets&&(a.style&&a.style.display||f.css(a,"display"))==="none"},f.expr.filters.visible=function(a){return!f.expr.filters.hidden(a)});var bD=/%20/g,bE=/\[\]$/,bF=/\r?\n/g,bG=/#.*$/,bH=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bI=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bJ=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,bK=/^(?:GET|HEAD)$/,bL=/^\/\//,bM=/\?/,bN=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,bO=/^(?:select|textarea)/i,bP=/\s+/,bQ=/([?&])_=[^&]*/,bR=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,bS=f.fn.load,bT={},bU={},bV,bW,bX=["*/"]+["*"];try{bV=e.href}catch(bY){bV=c.createElement("a"),bV.href="",bV=bV.href}bW=bR.exec(bV.toLowerCase())||[],f.fn.extend({load:function(a,c,d){if(typeof a!="string"&&bS)return bS.apply(this,arguments);if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var g=a.slice(e,a.length);a=a.slice(0,e)}var h="GET";c&&(f.isFunction(c)?(d=c,c=b):typeof c=="object"&&(c=f.param(c,f.ajaxSettings.traditional),h="POST"));var i=this;f.ajax({url:a,type:h,dataType:"html",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?f("<div>").append(c.replace(bN,"")).find(g):c)),d&&i.each(d,[c,b,a])}});return this},serialize:function(){return f.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?f.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bO.test(this.nodeName)||bI.test(this.type))}).map(function(a,b){var c=f(this).val();return c==null?null:f.isArray(c)?f.map(c,function(a,c){return{name:b.name,value:a.replace(bF,"\r\n")}}):{name:b.name,value:c.replace(bF,"\r\n")}}).get()}}),f.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){f.fn[b]=function(a){return this.on(b,a)}}),f.each(["get","post"],function(a,c){f[c]=function(a,d,e,g){f.isFunction(d)&&(g=g||e,e=d,d=b);return f.ajax({type:c,url:a,data:d,success:e,dataType:g})}}),f.extend({getScript:function(a,c){return f.get(a,b,c,"script")},getJSON:function(a,b,c){return f.get(a,b,c,"json")},ajaxSetup:function(a,b){b?b_(a,f.ajaxSettings):(b=a,a=f.ajaxSettings),b_(a,b);return a},ajaxSettings:{url:bV,isLocal:bJ.test(bW[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":bX},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":f.parseJSON,"text xml":f.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:bZ(bT),ajaxTransport:bZ(bU),ajax:function(a,c){function w(a,c,l,m){if(s!==2){s=2,q&&clearTimeout(q),p=b,n=m||"",v.readyState=a>0?4:0;var o,r,u,w=c,x=l?cb(d,v,l):b,y,z;if(a>=200&&a<300||a===304){if(d.ifModified){if(y=v.getResponseHeader("Last-Modified"))f.lastModified[k]=y;if(z=v.getResponseHeader("Etag"))f.etag[k]=z}if(a===304)w="notmodified",o=!0;else try{r=cc(d,x),w="success",o=!0}catch(A){w="parsererror",u=A}}else{u=w;if(!w||a)w="error",a<0&&(a=0)}v.status=a,v.statusText=""+(c||w),o?h.resolveWith(e,[r,w,v]):h.rejectWith(e,[v,w,u]),v.statusCode(j),j=b,t&&g.trigger("ajax"+(o?"Success":"Error"),[v,d,o?r:u]),i.fireWith(e,[v,w]),t&&(g.trigger("ajaxComplete",[v,d]),--f.active||f.event.trigger("ajaxStop"))}}typeof a=="object"&&(c=a,a=b),c=c||{};var d=f.ajaxSetup({},c),e=d.context||d,g=e!==d&&(e.nodeType||e instanceof f)?f(e):f.event,h=f.Deferred(),i=f.Callbacks("once memory"),j=d.statusCode||{},k,l={},m={},n,o,p,q,r,s=0,t,u,v={readyState:0,setRequestHeader:function(a,b){if(!s){var c=a.toLowerCase();a=m[c]=m[c]||a,l[a]=b}return this},getAllResponseHeaders:function(){return s===2?n:null},getResponseHeader:function(a){var c;if(s===2){if(!o){o={};while(c=bH.exec(n))o[c[1].toLowerCase()]=c[2]}c=o[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){s||(d.mimeType=a);return this},abort:function(a){a=a||"abort",p&&p.abort(a),w(0,a);return this}};h.promise(v),v.success=v.done,v.error=v.fail,v.complete=i.add,v.statusCode=function(a){if(a){var b;if(s<2)for(b in a)j[b]=[j[b],a[b]];else b=a[v.status],v.then(b,b)}return this},d.url=((a||d.url)+"").replace(bG,"").replace(bL,bW[1]+"//"),d.dataTypes=f.trim(d.dataType||"*").toLowerCase().split(bP),d.crossDomain==null&&(r=bR.exec(d.url.toLowerCase()),d.crossDomain=!(!r||r[1]==bW[1]&&r[2]==bW[2]&&(r[3]||(r[1]==="http:"?80:443))==(bW[3]||(bW[1]==="http:"?80:443)))),d.data&&d.processData&&typeof d.data!="string"&&(d.data=f.param(d.data,d.traditional)),b$(bT,d,c,v);if(s===2)return!1;t=d.global,d.type=d.type.toUpperCase(),d.hasContent=!bK.test(d.type),t&&f.active++===0&&f.event.trigger("ajaxStart");if(!d.hasContent){d.data&&(d.url+=(bM.test(d.url)?"&":"?")+d.data,delete d.data),k=d.url;if(d.cache===!1){var x=f.now(),y=d.url.replace(bQ,"$1_="+x);d.url=y+(y===d.url?(bM.test(d.url)?"&":"?")+"_="+x:"")}}(d.data&&d.hasContent&&d.contentType!==!1||c.contentType)&&v.setRequestHeader("Content-Type",d.contentType),d.ifModified&&(k=k||d.url,f.lastModified[k]&&v.setRequestHeader("If-Modified-Since",f.lastModified[k]),f.etag[k]&&v.setRequestHeader("If-None-Match",f.etag[k])),v.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(d.dataTypes[0]!=="*"?", "+bX+"; q=0.01":""):d.accepts["*"]);for(u in d.headers)v.setRequestHeader(u,d.headers[u]);if(d.beforeSend&&(d.beforeSend.call(e,v,d)===!1||s===2)){v.abort();return!1}for(u in{success:1,error:1,complete:1})v[u](d[u]);p=b$(bU,d,c,v);if(!p)w(-1,"No Transport");else{v.readyState=1,t&&g.trigger("ajaxSend",[v,d]),d.async&&d.timeout>0&&(q=setTimeout(function(){v.abort("timeout")},d.timeout));try{s=1,p.send(l,w)}catch(z){if(s<2)w(-1,z);else throw z}}return v},param:function(a,c){var d=[],e=function(a,b){b=f.isFunction(b)?b():b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=f.ajaxSettings.traditional);if(f.isArray(a)||a.jquery&&!f.isPlainObject(a))f.each(a,function(){e(this.name,this.value)});else for(var g in a)ca(g,a[g],c,e);return d.join("&").replace(bD,"+")}}),f.extend({active:0,lastModified:{},etag:{}});var cd=f.now(),ce=/(\=)\?(&|$)|\?\?/i;f.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return f.expando+"_"+cd++}}),f.ajaxPrefilter("json jsonp",function(b,c,d){var e=b.contentType==="application/x-www-form-urlencoded"&&typeof b.data=="string";if(b.dataTypes[0]==="jsonp"||b.jsonp!==!1&&(ce.test(b.url)||e&&ce.test(b.data))){var g,h=b.jsonpCallback=f.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l="$1"+h+"$2";b.jsonp!==!1&&(j=j.replace(ce,l),b.url===j&&(e&&(k=k.replace(ce,l)),b.data===k&&(j+=(/\?/.test(j)?"&":"?")+b.jsonp+"="+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},d.always(function(){a[h]=i,g&&f.isFunction(i)&&a[h](g[0])}),b.converters["script json"]=function(){g||f.error(h+" was not called");return g[0]},b.dataTypes[0]="json";return"script"}}),f.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){f.globalEval(a);return a}}}),f.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),f.ajaxTransport("script",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName("head")[0]||c.documentElement;return{send:function(f,g){d=c.createElement("script"),d.async="async",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(c||!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,"success")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var cf=a.ActiveXObject?function(){for(var a in ch)ch[a](0,1)}:!1,cg=0,ch;f.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&ci()||cj()}:ci,function(a){f.extend(f.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(f.ajaxSettings.xhr()),f.support.ajax&&f.ajaxTransport(function(c){if(!c.crossDomain||f.support.cors){var d;return{send:function(e,g){var h=c.xhr(),i,j;c.username?h.open(c.type,c.url,c.async,c.username,c.password):h.open(c.type,c.url,c.async);if(c.xhrFields)for(j in c.xhrFields)h[j]=c.xhrFields[j];c.mimeType&&h.overrideMimeType&&h.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(j in e)h.setRequestHeader(j,e[j])}catch(k){}h.send(c.hasContent&&c.data||null),d=function(a,e){var j,k,l,m,n;try{if(d&&(e||h.readyState===4)){d=b,i&&(h.onreadystatechange=f.noop,cf&&delete ch[i]);if(e)h.readyState!==4&&h.abort();else{j=h.status,l=h.getAllResponseHeaders(),m={},n=h.responseXML,n&&n.documentElement&&(m.xml=n),m.text=h.responseText;try{k=h.statusText}catch(o){k=""}!j&&c.isLocal&&!c.crossDomain?j=m.text?200:404:j===1223&&(j=204)}}}catch(p){e||g(-1,p)}m&&g(j,k,m,l)},!c.async||h.readyState===4?d():(i=++cg,cf&&(ch||(ch={},f(a).unload(cf)),ch[i]=d),h.onreadystatechange=d)},abort:function(){d&&d(0,1)}}}});var ck={},cl,cm,cn=/^(?:toggle|show|hide)$/,co=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,cp,cq=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]],cr;f.fn.extend({show:function(a,b,c){var d,e;if(a||a===0)return this.animate(cu("show",3),a,b,c);for(var g=0,h=this.length;g<h;g++)d=this[g],d.style&&(e=d.style.display,!f._data(d,"olddisplay")&&e==="none"&&(e=d.style.display=""),e===""&&f.css(d,"display")==="none"&&f._data(d,"olddisplay",cv(d.nodeName)));for(g=0;g<h;g++){d=this[g];if(d.style){e=d.style.display;if(e===""||e==="none")d.style.display=f._data(d,"olddisplay")||""}}return this},hide:function(a,b,c){if(a||a===0)return this.animate(cu("hide",3),a,b,c);var d,e,g=0,h=this.length;for(;g<h;g++)d=this[g],d.style&&(e=f.css(d,"display"),e!=="none"&&!f._data(d,"olddisplay")&&f._data(d,"olddisplay",e));for(g=0;g<h;g++)this[g].style&&(this[g].style.display="none");return this},_toggle:f.fn.toggle,toggle:function(a,b,c){var d=typeof a=="boolean";f.isFunction(a)&&f.isFunction(b)?this._toggle.apply(this,arguments):a==null||d?this.each(function(){var b=d?a:f(this).is(":hidden");f(this)[b?"show":"hide"]()}):this.animate(cu("toggle",3),a,b,c);return this},fadeTo:function(a,b,c,d){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){function g(){e.queue===!1&&f._mark(this);var b=f.extend({},e),c=this.nodeType===1,d=c&&f(this).is(":hidden"),g,h,i,j,k,l,m,n,o;b.animatedProperties={};for(i in a){g=f.camelCase(i),i!==g&&(a[g]=a[i],delete a[i]),h=a[g],f.isArray(h)?(b.animatedProperties[g]=h[1],h=a[g]=h[0]):b.animatedProperties[g]=b.specialEasing&&b.specialEasing[g]||b.easing||"swing";if(h==="hide"&&d||h==="show"&&!d)return b.complete.call(this);c&&(g==="height"||g==="width")&&(b.overflow=[this.style.overflow,this.style.overflowX,this.style.overflowY],f.css(this,"display")==="inline"&&f.css(this,"float")==="none"&&(!f.support.inlineBlockNeedsLayout||cv(this.nodeName)==="inline"?this.style.display="inline-block":this.style.zoom=1))}b.overflow!=null&&(this.style.overflow="hidden");for(i in a)j=new f.fx(this,b,i),h=a[i],cn.test(h)?(o=f._data(this,"toggle"+i)||(h==="toggle"?d?"show":"hide":0),o?(f._data(this,"toggle"+i,o==="show"?"hide":"show"),j[o]()):j[h]()):(k=co.exec(h),l=j.cur(),k?(m=parseFloat(k[2]),n=k[3]||(f.cssNumber[i]?"":"px"),n!=="px"&&(f.style(this,i,(m||1)+n),l=(m||1)/j.cur()*l,f.style(this,i,l+n)),k[1]&&(m=(k[1]==="-="?-1:1)*m+l),j.custom(l,m,n)):j.custom(l,h,""));return!0}var e=f.speed(b,c,d);if(f.isEmptyObject(a))return this.each(e.complete,[!1]);a=f.extend({},a);return e.queue===!1?this.each(g):this.queue(e.queue,g)},stop:function(a,c,d){typeof a!="string"&&(d=c,c=a,a=b),c&&a!==!1&&this.queue(a||"fx",[]);return this.each(function(){function h(a,b,c){var e=b[c];f.removeData(a,c,!0),e.stop(d)}var b,c=!1,e=f.timers,g=f._data(this);d||f._unmark(!0,this);if(a==null)for(b in g)g[b]&&g[b].stop&&b.indexOf(".run")===b.length-4&&h(this,g,b);else g[b=a+".run"]&&g[b].stop&&h(this,g,b);for(b=e.length;b--;)e[b].elem===this&&(a==null||e[b].queue===a)&&(d?e[b](!0):e[b].saveState(),c=!0,e.splice(b,1));(!d||!c)&&f.dequeue(this,a)})}}),f.each({slideDown:cu("show",1),slideUp:cu("hide",1),slideToggle:cu("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){f.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),f.extend({speed:function(a,b,c){var d=a&&typeof a=="object"?f.extend({},a):{complete:c||!c&&b||f.isFunction(a)&&a,duration:a,easing:c&&b||b&&!f.isFunction(b)&&b};d.duration=f.fx.off?0:typeof d.duration=="number"?d.duration:d.duration in f.fx.speeds?f.fx.speeds[d.duration]:f.fx.speeds._default;if(d.queue==null||d.queue===!0)d.queue="fx";d.old=d.complete,d.complete=function(a){f.isFunction(d.old)&&d.old.call(this),d.queue?f.dequeue(this,d.queue):a!==!1&&f._unmark(this)};return d},easing:{linear:function(a,b,c,d){return c+d*a},swing:function(a,b,c,d){return(-Math.cos(a*Math.PI)/2+.5)*d+c}},timers:[],fx:function(a,b,c){this.options=b,this.elem=a,this.prop=c,b.orig=b.orig||{}}}),f.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this),(f.fx.step[this.prop]||f.fx.step._default)(this)},cur:function(){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];var a,b=f.css(this.elem,this.prop);return isNaN(a=parseFloat(b))?!b||b==="auto"?0:b:a},custom:function(a,c,d){function h(a){return e.step(a)}var e=this,g=f.fx;this.startTime=cr||cs(),this.end=c,this.now=this.start=a,this.pos=this.state=0,this.unit=d||this.unit||(f.cssNumber[this.prop]?"":"px"),h.queue=this.options.queue,h.elem=this.elem,h.saveState=function(){e.options.hide&&f._data(e.elem,"fxshow"+e.prop)===b&&f._data(e.elem,"fxshow"+e.prop,e.start)},h()&&f.timers.push(h)&&!cp&&(cp=setInterval(g.tick,g.interval))},show:function(){var a=f._data(this.elem,"fxshow"+this.prop);this.options.orig[this.prop]=a||f.style(this.elem,this.prop),this.options.show=!0,a!==b?this.custom(this.cur(),a):this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur()),f(this.elem).show()},hide:function(){this.options.orig[this.prop]=f._data(this.elem,"fxshow"+this.prop)||f.style(this.elem,this.prop),this.options.hide=!0,this.custom(this.cur(),0)},step:function(a){var b,c,d,e=cr||cs(),g=!0,h=this.elem,i=this.options;if(a||e>=i.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),i.animatedProperties[this.prop]=!0;for(b in i.animatedProperties)i.animatedProperties[b]!==!0&&(g=!1);if(g){i.overflow!=null&&!f.support.shrinkWrapBlocks&&f.each(["","X","Y"],function(a,b){h.style["overflow"+b]=i.overflow[a]}),i.hide&&f(h).hide();if(i.hide||i.show)for(b in i.animatedProperties)f.style(h,b,i.orig[b]),f.removeData(h,"fxshow"+b,!0),f.removeData(h,"toggle"+b,!0);d=i.complete,d&&(i.complete=!1,d.call(h))}return!1}i.duration==Infinity?this.now=e:(c=e-this.startTime,this.state=c/i.duration,this.pos=f.easing[i.animatedProperties[this.prop]](this.state,c,0,1,i.duration),this.now=this.start+(this.end-this.start)*this.pos),this.update();return!0}},f.extend(f.fx,{tick:function(){var a,b=f.timers,c=0;for(;c<b.length;c++)a=b[c],!a()&&b[c]===a&&b.splice(c--,1);b.length||f.fx.stop()},interval:13,stop:function(){clearInterval(cp),cp=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){f.style(a.elem,"opacity",a.now)},_default:function(a){a.elem.style&&a.elem.style[a.prop]!=null?a.elem.style[a.prop]=a.now+a.unit:a.elem[a.prop]=a.now}}}),f.each(["width","height"],function(a,b){f.fx.step[b]=function(a){f.style(a.elem,b,Math.max(0,a.now)+a.unit)}}),f.expr&&f.expr.filters&&(f.expr.filters.animated=function(a){return f.grep(f.timers,function(b){return a===b.elem}).length});var cw=/^t(?:able|d|h)$/i,cx=/^(?:body|html)$/i;"getBoundingClientRect"in c.documentElement?f.fn.offset=function(a){var b=this[0],c;if(a)return this.each(function(b){f.offset.setOffset(this,a,b)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return f.offset.bodyOffset(b);try{c=b.getBoundingClientRect()}catch(d){}var e=b.ownerDocument,g=e.documentElement;if(!c||!f.contains(g,b))return c?{top:c.top,left:c.left}:{top:0,left:0};var h=e.body,i=cy(e),j=g.clientTop||h.clientTop||0,k=g.clientLeft||h.clientLeft||0,l=i.pageYOffset||f.support.boxModel&&g.scrollTop||h.scrollTop,m=i.pageXOffset||f.support.boxModel&&g.scrollLeft||h.scrollLeft,n=c.top+l-j,o=c.left+m-k;return{top:n,left:o}}:f.fn.offset=function(a){var b=this[0];if(a)return this.each(function(b){f.offset.setOffset(this,a,b)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return f.offset.bodyOffset(b);var c,d=b.offsetParent,e=b,g=b.ownerDocument,h=g.documentElement,i=g.body,j=g.defaultView,k=j?j.getComputedStyle(b,null):b.currentStyle,l=b.offsetTop,m=b.offsetLeft;while((b=b.parentNode)&&b!==i&&b!==h){if(f.support.fixedPosition&&k.position==="fixed")break;c=j?j.getComputedStyle(b,null):b.currentStyle,l-=b.scrollTop,m-=b.scrollLeft,b===d&&(l+=b.offsetTop,m+=b.offsetLeft,f.support.doesNotAddBorder&&(!f.support.doesAddBorderForTableAndCells||!cw.test(b.nodeName))&&(l+=parseFloat(c.borderTopWidth)||0,m+=parseFloat(c.borderLeftWidth)||0),e=d,d=b.offsetParent),f.support.subtractsBorderForOverflowNotVisible&&c.overflow!=="visible"&&(l+=parseFloat(c.borderTopWidth)||0,m+=parseFloat(c.borderLeftWidth)||0),k=c}if(k.position==="relative"||k.position==="static")l+=i.offsetTop,m+=i.offsetLeft;f.support.fixedPosition&&k.position==="fixed"&&(l+=Math.max(h.scrollTop,i.scrollTop),m+=Math.max(h.scrollLeft,i.scrollLeft));return{top:l,left:m}},f.offset={bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;f.support.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(f.css(a,"marginTop"))||0,c+=parseFloat(f.css(a,"marginLeft"))||0);return{top:b,left:c}},setOffset:function(a,b,c){var d=f.css(a,"position");d==="static"&&(a.style.position="relative");var e=f(a),g=e.offset(),h=f.css(a,"top"),i=f.css(a,"left"),j=(d==="absolute"||d==="fixed")&&f.inArray("auto",[h,i])>-1,k={},l={},m,n;j?(l=e.position(),m=l.top,n=l.left):(m=parseFloat(h)||0,n=parseFloat(i)||0),f.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using"in b?b.using.call(a,k):e.css(k)}},f.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),d=cx.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(f.css(a,"marginTop"))||0,c.left-=parseFloat(f.css(a,"marginLeft"))||0,d.top+=parseFloat(f.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(f.css(b[0],"borderLeftWidth"))||0;return{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&!cx.test(a.nodeName)&&f.css(a,"position")==="static")a=a.offsetParent;return a})}}),f.each(["Left","Top"],function(a,c){var d="scroll"+c;f.fn[d]=function(c){var e,g;if(c===b){e=this[0];if(!e)return null;g=cy(e);return g?"pageXOffset"in g?g[a?"pageYOffset":"pageXOffset"]:f.support.boxModel&&g.document.documentElement[d]||g.document.body[d]:e[d]}return this.each(function(){g=cy(this),g?g.scrollTo(a?f(g).scrollLeft():c,a?c:f(g).scrollTop()):this[d]=c})}}),f.each(["Height","Width"],function(a,c){var d=c.toLowerCase();f.fn["inner"+c]=function(){var a=this[0];return a?a.style?parseFloat(f.css(a,d,"padding")):this[d]():null},f.fn["outer"+c]=function(a){var b=this[0];return b?b.style?parseFloat(f.css(b,d,a?"margin":"border")):this[d]():null},f.fn[d]=function(a){var e=this[0];if(!e)return a==null?null:this;if(f.isFunction(a))return this.each(function(b){var c=f(this);c[d](a.call(this,b,c[d]()))});if(f.isWindow(e)){var g=e.document.documentElement["client"+c],h=e.document.body;return e.document.compatMode==="CSS1Compat"&&g||h&&h["client"+c]||g}if(e.nodeType===9)return Math.max(e.documentElement["client"+c],e.body["scroll"+c],e.documentElement["scroll"+c],e.body["offset"+c],e.documentElement["offset"+c]);if(a===b){var i=f.css(e,d),j=parseFloat(i);return f.isNumeric(j)?j:i}return this.css(d,typeof a=="string"?a:a+"px")}}),a.jQuery=a.$=f,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return f})})(window);
\ No newline at end of file
diff --git a/legacyworlds-web-main/Content/Raw/js/research.js b/legacyworlds-web-main/Content/Raw/js/research.js
deleted file mode 100644
index 31cdbfe..0000000
--- a/legacyworlds-web-main/Content/Raw/js/research.js
+++ /dev/null
@@ -1,87 +0,0 @@
-$(function() {
-
-	/* Replace dependency identifiers */
-	$('.tech-info li.dep').each(
-			function() {
-				var _id = this.innerHTML;
-				var _targetTitle = $('#tdesc-' + _id + ' h4');
-				this.innerHTML = '';
-				$('<a/>').attr('href', '#tl-' + _id)
-						.append(_targetTitle.html()).appendTo($(this));
-			});
-
-	/* Map entries to tabs */
-	var _entries = {};
-	var _tabs = {};
-	$('.tech-line').each(
-			function() {
-				var _id = $(this).attr('id').replace(/^tl-/, '');
-				var _tab = $(this).parents('.tab-contents').attr('id').replace(
-						/^tabc-/, '');
-				_entries[_id] = _tab;
-				if (!_tabs[_tab]) {
-					_tabs[_tab] = [];
-				}
-				_tabs[_tab].push(_id);
-			});
-	var _selected = {};
-	for ( var _tab in _tabs) {
-		_selected[_tab] = _tabs[_tab][0];
-		$('#tl-' + _selected[_tab]).toggleClass('selected');
-	}
-
-	/* Insert viewing area */
-	var _viewingArea = $('<div/>').css({
-		'float' : 'right',
-		'width' : '300px',
-		'position' : 'relative',
-	}).attr('class', 'tech-view').prependTo($('#page-contents'));
-	$('div.tabs').css({
-		'margin-right' : '300px'
-	});
-
-	/* When an entry is clicked, set contents of viewing area */
-	var _displayed = '';
-	$('.tech-line').click(function() {
-		var _id = $(this).attr('id').replace(/^tl-/, '');
-		if (_id == _displayed) {
-			return true;
-		}
-		_viewingArea.html($('#tdesc-' + _id).html());
-		$('a', _viewingArea).click(function() {
-			var _target = $(this).attr('href').replace(/^#tl-/, '');
-			$('#tabb-' + _entries[_target]).click();
-			$('#tl-' + _target).click();
-		});
-		if (_selected[_entries[_id]] != _id) {
-			$('#tl-' + _selected[_entries[_id]]).toggleClass('selected');
-			$(this).toggleClass('selected');
-			_selected[_entries[_id]] = _id;
-		}
-		location.hash = '#tl-'+_id;
-		return true;
-	});
-
-	/* When a tab button is clicked, select the appropriate entry */
-	$('.tab-buttons a').click(function() {
-		var _id = $(this).attr('id').replace(/^tabb-/, '');
-		var _tech = _selected[_id];
-		$('#tl-' + _tech).click();
-	});
-
-	(function() {
-		var _current = location.hash;
-		if (_current.match(/^#tl-/)) {
-			_current = _current.replace(/#tl-/, '');
-		} else if (_current.match(/^#/)) {
-			_current = _selected[_current.replace(/^#/, '')];
-		} else {
-			for ( var _tab in _selected) {
-				_current = _selected[_tab];
-				break;
-			}
-		}
-		$('#tabb-' + _entries[_current]).click();
-		$('#tl-' + _current).click();
-	})();
-});
\ No newline at end of file
diff --git a/legacyworlds-web-main/pom.xml b/legacyworlds-web-main/pom.xml
deleted file mode 100644
index 61cb214..0000000
--- a/legacyworlds-web-main/pom.xml
+++ /dev/null
@@ -1,45 +0,0 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-	<modelVersion>4.0.0</modelVersion>
-	<parent>
-		<artifactId>legacyworlds-web</artifactId>
-		<groupId>com.deepclone.lw</groupId>
-		<version>1.0.0</version>
-		<relativePath>../legacyworlds-web/pom.xml</relativePath>
-	</parent>
-
-	<artifactId>legacyworlds-web-main</artifactId>
-	<version>${legacyworlds.version.main}.${legacyworlds.version.release}-${legacyworlds.version.build}</version>
-	<packaging>war</packaging>
-	<name>Legacy Worlds - Web - Game</name>
-
-	<dependencies>
-		<dependency>
-			<groupId>com.deepclone.lw</groupId>
-			<artifactId>legacyworlds-web-beans</artifactId>
-		</dependency>
-
-		<dependency>
-			<groupId>org.freemarker</groupId>
-			<artifactId>freemarker</artifactId>
-			<scope>runtime</scope>
-		</dependency>
-	</dependencies>
-
-	<build>
-		<plugins>
-			<plugin>
-				<groupId>org.apache.maven.plugins</groupId>
-				<artifactId>maven-war-plugin</artifactId>
-			</plugin>
-			<plugin>
-				<groupId>org.codehaus.mojo</groupId>
-				<artifactId>tomcat-maven-plugin</artifactId>
-				<configuration>
-					<path>/lwmain</path>
-				</configuration>
-			</plugin>
-		</plugins>
-	</build>
-
-</project>
diff --git a/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/game/OverviewPage.java b/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/game/OverviewPage.java
deleted file mode 100644
index 50024d2..0000000
--- a/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/game/OverviewPage.java
+++ /dev/null
@@ -1,153 +0,0 @@
-package com.deepclone.lw.web.main.game;
-
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Map.Entry;
-
-import javax.servlet.http.HttpServletRequest;
-
-import org.springframework.stereotype.Controller;
-import org.springframework.ui.Model;
-import org.springframework.web.bind.annotation.ModelAttribute;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.bind.annotation.SessionAttributes;
-
-import com.deepclone.lw.session.SessionException;
-import com.deepclone.lw.web.beans.intercept.SessionRequirement;
-import com.deepclone.lw.web.beans.session.SessionMaintenanceException;
-import com.deepclone.lw.web.beans.session.SessionServerException;
-import com.deepclone.lw.web.beans.view.PageControllerBase;
-import com.deepclone.lw.web.csess.PlayerSession;
-
-
-
-/**
- * Overview page controller
- * 
- * <p>
- * This page controller implements the "Overview" page, as well as the commands it supports
- * (implement technology, update empire mining settings).
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-@Controller
-@SessionRequirement( value = true , redirectTo = "player-session" , subType = "game" )
-@SessionAttributes( "language" )
-public class OverviewPage
-		extends PageControllerBase
-{
-
-	/**
-	 * Main overview display
-	 * 
-	 * <p>
-	 * This method is mapped to the overview page's URL. It will fetch the empire overview from the
-	 * server and display the appropriate page.
-	 * 
-	 * @param request
-	 *            the HTTP request
-	 * @param language
-	 *            the language from the session
-	 * @param model
-	 *            the model
-	 * 
-	 * @return the overview page rendering order
-	 * 
-	 * @throws SessionException
-	 *             if some error occurs on the server
-	 * @throws SessionServerException
-	 *             if the server is unreachable
-	 * @throws SessionMaintenanceException
-	 *             if the game is under maintenance
-	 */
-	@RequestMapping( "/overview" )
-	public String overview( HttpServletRequest request , @ModelAttribute( "language" ) String language , Model model )
-			throws SessionException , SessionServerException , SessionMaintenanceException
-	{
-		PlayerSession pSession = this.getSession( PlayerSession.class , request );
-		return this.render( model , "game" , language , "overview" , pSession.getOverview( ) );
-	}
-
-
-	/**
-	 * Empire-wide mining settings update command
-	 * 
-	 * <p>
-	 * This method is called when a command to update empire-wide mining settings is received.
-	 * 
-	 * @param request
-	 *            the HTTP request
-	 * 
-	 * @return a redirection to the overview page's "economy" tab
-	 * 
-	 * @throws SessionException
-	 *             if some error occurs on the server
-	 * @throws SessionServerException
-	 *             if the server is unreachable
-	 * @throws SessionMaintenanceException
-	 *             if the game is under maintenance
-	 */
-	@RequestMapping( value = "/update-mining-settings.action" , method = RequestMethod.POST )
-	public String updateMiningSettings( HttpServletRequest request )
-			throws SessionException , SessionServerException , SessionMaintenanceException
-	{
-		Map< String , Integer > miningSettings = this.getMiningSettings( request );
-		if ( miningSettings != null ) {
-			this.getSession( PlayerSession.class , request ).updateEmpireMiningSettings( miningSettings );
-		}
-		return this.redirect( "overview#economy" );
-	}
-
-
-	/**
-	 * Extract mining priorities from the HTTP request
-	 * 
-	 * <p>
-	 * Look for all submitted fields that begin with "ems-" then try to extract their values into a
-	 * map that associates resource identifiers to priorities.
-	 * 
-	 * @param request
-	 *            the HTTP request
-	 * 
-	 * @return the map containing the submitted mining settings, or <code>null</code> if one of the
-	 *         values was incorrect.
-	 */
-	private Map< String , Integer > getMiningSettings( HttpServletRequest request )
-	{
-		Map< String , Object > input = this.getInput( request );
-		Map< String , Integer > miningSettings = new HashMap< String , Integer >( );
-		for ( Entry< String , Object > entry : input.entrySet( ) ) {
-			// Ignore items which are not mining settings
-			String name = entry.getKey( );
-			if ( !name.startsWith( "ems-" ) ) {
-				continue;
-			}
-			name = name.substring( 4 );
-
-			// Get values
-			if ( ! ( entry.getValue( ) instanceof String[] ) ) {
-				continue;
-			}
-			String[] values = (String[]) entry.getValue( );
-			if ( values.length < 1 ) {
-				continue;
-			}
-
-			// Pre-validate them
-			int value;
-			try {
-				value = Integer.parseInt( values[ 0 ] );
-			} catch ( NumberFormatException e ) {
-				value = -1;
-			}
-			if ( value < 0 || value > 4 ) {
-				return null;
-			}
-
-			miningSettings.put( name , value );
-		}
-		return miningSettings;
-	}
-}
diff --git a/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/game/ResearchPage.java b/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/game/ResearchPage.java
deleted file mode 100644
index 79c9beb..0000000
--- a/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/game/ResearchPage.java
+++ /dev/null
@@ -1,186 +0,0 @@
-package com.deepclone.lw.web.main.game;
-
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Map.Entry;
-
-import javax.servlet.http.HttpServletRequest;
-
-import org.springframework.stereotype.Controller;
-import org.springframework.ui.Model;
-import org.springframework.web.bind.annotation.ModelAttribute;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.bind.annotation.RequestParam;
-import org.springframework.web.bind.annotation.SessionAttributes;
-
-import com.deepclone.lw.session.SessionException;
-import com.deepclone.lw.web.beans.intercept.SessionRequirement;
-import com.deepclone.lw.web.beans.session.SessionMaintenanceException;
-import com.deepclone.lw.web.beans.session.SessionServerException;
-import com.deepclone.lw.web.beans.view.PageControllerBase;
-import com.deepclone.lw.web.csess.PlayerSession;
-
-
-
-/**
- * Controller for the Research page
- * 
- * <p>
- * This controller contains all URL handlers associated with the research page: viewing research
- * state, setting research priorities, and implementing technologies.
- * 
- * @author <a href="mailto:tseeker@legacyworlds.com">E. Benoît</a>
- */
-@Controller
-@SessionRequirement( value = true , redirectTo = "player-session" , subType = "game" )
-@SessionAttributes( "language" )
-public class ResearchPage
-		extends PageControllerBase
-{
-
-	/**
-	 * Research page view
-	 * 
-	 * <p>
-	 * This method fetches all research information from the game server then requests the page
-	 * rendering.
-	 * 
-	 * @param request
-	 *            the HTTP request
-	 * @param language
-	 *            the language from the session
-	 * @param model
-	 *            the model
-	 * 
-	 * @return the research page rendering information
-	 * 
-	 * @throws SessionException
-	 *             if some error occurs on the server
-	 * @throws SessionServerException
-	 *             if the server is unreachable
-	 * @throws SessionMaintenanceException
-	 *             if the game is under maintenance
-	 */
-	@RequestMapping( "/research" )
-	public String view( HttpServletRequest request , @ModelAttribute( "language" ) String language , Model model )
-			throws SessionException , SessionServerException , SessionMaintenanceException
-	{
-		PlayerSession pSession = this.getSession( PlayerSession.class , request );
-		return this.render( model , "game" , language , "research" , pSession.getResearch( ) );
-	}
-
-
-	/**
-	 * Research priorities update command
-	 * 
-	 * <p>
-	 * This method handles the research priorities update command, which is triggered when the
-	 * "Update" button is clicked on the "In progress" tab of the research page.
-	 * 
-	 * @param request
-	 *            the HTTP request
-	 * 
-	 * @return a redirection to the research page's "in progress" tab
-	 * 
-	 * @throws SessionException
-	 *             if some error occurs on the server
-	 * @throws SessionServerException
-	 *             if the server is unreachable
-	 * @throws SessionMaintenanceException
-	 *             if the game is under maintenance
-	 */
-	@RequestMapping( value = "/research-set-priorities.action" , method = RequestMethod.POST )
-	public String setPriorities( HttpServletRequest request )
-			throws SessionException , SessionServerException , SessionMaintenanceException
-	{
-		Map< String , Integer > priorities = this.getPriorities( request );
-		if ( priorities != null ) {
-			this.getSession( PlayerSession.class , request ).updateResearchPriorities( priorities );
-		}
-		return this.redirect( "research#research" );
-	}
-
-
-	/**
-	 * Extract research priorities from the HTTP request
-	 * 
-	 * <p>
-	 * Look for all submitted fields that begin with "rp-" then try to extract their values into a
-	 * map that associates technology identifiers to priorities.
-	 * 
-	 * @param request
-	 *            the HTTP request
-	 * 
-	 * @return the map containing the submitted priorities, or <code>null</code> if one of the
-	 *         values was incorrect.
-	 */
-	private Map< String , Integer > getPriorities( HttpServletRequest request )
-	{
-		Map< String , Object > input = this.getInput( request );
-		Map< String , Integer > priorities = new HashMap< String , Integer >( );
-		for ( Entry< String , Object > entry : input.entrySet( ) ) {
-			// Ignore items which are not priorities
-			String name = entry.getKey( );
-			if ( !name.startsWith( "rp-" ) ) {
-				continue;
-			}
-			name = name.substring( 3 );
-
-			// Get values
-			if ( ! ( entry.getValue( ) instanceof String[] ) ) {
-				continue;
-			}
-			String[] values = (String[]) entry.getValue( );
-			if ( values.length < 1 ) {
-				continue;
-			}
-
-			// Pre-validate them
-			int value;
-			try {
-				value = Integer.parseInt( values[ 0 ] );
-			} catch ( NumberFormatException e ) {
-				value = -1;
-			}
-			if ( value < 0 || value > 4 ) {
-				return null;
-			}
-
-			priorities.put( name , value );
-		}
-		return priorities;
-	}
-
-
-	/**
-	 * Technology implementation command
-	 * 
-	 * <p>
-	 * This method handles the technology implementation command, which is triggered when the
-	 * "Implement" button is clicked on the "Pending" tab of the research page.
-	 * 
-	 * @param request
-	 *            the HTTP request
-	 * @param tech
-	 *            the identifier of the technology
-	 * 
-	 * @return a redirection to the research page's "Implemented" tab
-	 * 
-	 * @throws SessionException
-	 *             if some error occurs on the server
-	 * @throws SessionServerException
-	 *             if the server is unreachable
-	 * @throws SessionMaintenanceException
-	 *             if the game is under maintenance
-	 */
-	@RequestMapping( value = "/research-implement.action" , method = RequestMethod.POST )
-	public String implement( HttpServletRequest request , @RequestParam( "technology" ) String technology )
-			throws SessionException , SessionServerException , SessionMaintenanceException
-	{
-		this.getSession( PlayerSession.class , request ).implementTechnology( technology );
-		return this.redirect( "research#implemented" );
-	}
-
-}
diff --git a/legacyworlds-web-main/src/test/java/.empty b/legacyworlds-web-main/src/test/java/.empty
deleted file mode 100644
index e69de29..0000000
diff --git a/legacyworlds-web-main/src/test/resources/.empty b/legacyworlds-web-main/src/test/resources/.empty
deleted file mode 100644
index e69de29..0000000
diff --git a/legacyworlds-web-tests/pom.xml b/legacyworlds-web-tests/pom.xml
deleted file mode 100644
index 4f626a6..0000000
--- a/legacyworlds-web-tests/pom.xml
+++ /dev/null
@@ -1,49 +0,0 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-	<modelVersion>4.0.0</modelVersion>
-	<parent>
-		<artifactId>legacyworlds</artifactId>
-		<groupId>com.deepclone.lw</groupId>
-		<version>1.0.0</version>
-		<relativePath>../legacyworlds/pom.xml</relativePath>
-	</parent>
-
-	<artifactId>legacyworlds-web-tests</artifactId>
-	<version>${legacyworlds.version.main}.${legacyworlds.version.release}-${legacyworlds.version.build}</version>
-	<name>Legacy Worlds - Web - Tests</name>
-	<description>This package contains all tests for web clients functionalities.</description>
-
-	<dependencies>
-		<dependency>
-			<artifactId>legacyworlds-web-admin</artifactId>
-			<groupId>com.deepclone.lw</groupId>
-			<version>${legacyworlds.version.main}.${legacyworlds.version.release}-${legacyworlds.version.build}</version>
-			<type>war</type>
-			<scope>test</scope>
-		</dependency>
-		<dependency>
-			<artifactId>legacyworlds-web-beans</artifactId>
-			<groupId>com.deepclone.lw</groupId>
-			<scope>test</scope>
-		</dependency>
-		<dependency>
-			<artifactId>legacyworlds-web-main</artifactId>
-			<groupId>com.deepclone.lw</groupId>
-			<version>${legacyworlds.version.main}.${legacyworlds.version.release}-${legacyworlds.version.build}</version>
-			<type>war</type>
-			<scope>test</scope>
-		</dependency>
-
-		<dependency>
-			<groupId>junit</groupId>
-			<artifactId>junit</artifactId>
-			<scope>test</scope>
-		</dependency>
-		<dependency>
-			<groupId>org.springframework</groupId>
-			<artifactId>spring-test</artifactId>
-			<scope>test</scope>
-		</dependency>
-	</dependencies>
-
-</project>
\ No newline at end of file
diff --git a/legacyworlds-web-tests/src/main/java/.empty b/legacyworlds-web-tests/src/main/java/.empty
deleted file mode 100644
index e69de29..0000000
diff --git a/legacyworlds-web-tests/src/main/resources/.empty b/legacyworlds-web-tests/src/main/resources/.empty
deleted file mode 100644
index e69de29..0000000
diff --git a/legacyworlds-web-tests/src/test/java/.empty b/legacyworlds-web-tests/src/test/java/.empty
deleted file mode 100644
index e69de29..0000000
diff --git a/legacyworlds-web-tests/src/test/resources/.empty b/legacyworlds-web-tests/src/test/resources/.empty
deleted file mode 100644
index e69de29..0000000
diff --git a/legacyworlds-web/.project b/legacyworlds-web/.project
new file mode 100644
index 0000000..b64463a
--- /dev/null
+++ b/legacyworlds-web/.project
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>legacyworlds-web</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.maven.ide.eclipse.maven2Builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.maven.ide.eclipse.maven2Nature</nature>
+	</natures>
+</projectDescription>
diff --git a/legacyworlds-web/.settings/org.maven.ide.eclipse.prefs b/legacyworlds-web/.settings/org.maven.ide.eclipse.prefs
new file mode 100644
index 0000000..32dc0c3
--- /dev/null
+++ b/legacyworlds-web/.settings/org.maven.ide.eclipse.prefs
@@ -0,0 +1,9 @@
+#Thu Apr 15 18:51:39 CEST 2010
+activeProfiles=
+eclipse.preferences.version=1
+fullBuildGoals=process-test-resources
+includeModules=false
+resolveWorkspaceProjects=true
+resourceFilterGoals=process-resources resources\:testResources
+skipCompilerPlugin=true
+version=1
diff --git a/legacyworlds-web/legacyworlds-web-admin/.classpath b/legacyworlds-web/legacyworlds-web-admin/.classpath
new file mode 100644
index 0000000..3d4e21c
--- /dev/null
+++ b/legacyworlds-web/legacyworlds-web-admin/.classpath
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" output="target/classes" path="src/main/java"/>
+	<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources"/>
+	<classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
+	<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources"/>
+	<classpathentry exported="true" kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER">
+		<attributes>
+			<attribute name="org.eclipse.jst.component.dependency" value="/WEB-INF/lib"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="con" path="org.eclipse.jst.j2ee.internal.web.container"/>
+	<classpathentry kind="con" path="org.eclipse.jst.j2ee.internal.module.container"/>
+	<classpathentry kind="con" path="org.eclipse.jst.server.core.container/org.eclipse.jst.server.tomcat.runtimeTarget/Apache Tomcat v6.0">
+		<attributes>
+			<attribute name="owner.project.facets" value="jst.web"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/java-6-openjdk">
+		<attributes>
+			<attribute name="owner.project.facets" value="jst.java"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="output" path="target/classes"/>
+</classpath>
diff --git a/legacyworlds-web/legacyworlds-web-admin/.project b/legacyworlds-web/legacyworlds-web-admin/.project
new file mode 100644
index 0000000..073b138
--- /dev/null
+++ b/legacyworlds-web/legacyworlds-web-admin/.project
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>legacyworlds-web-admin</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.wst.jsdt.core.javascriptValidator</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.maven.ide.eclipse.maven2Builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.wst.validation.validationbuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jem.workbench.JavaEMFNature</nature>
+		<nature>org.eclipse.wst.common.modulecore.ModuleCoreNature</nature>
+		<nature>org.eclipse.wst.common.project.facet.core.nature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.maven.ide.eclipse.maven2Nature</nature>
+		<nature>org.eclipse.wst.jsdt.core.jsNature</nature>
+	</natures>
+</projectDescription>
diff --git a/legacyworlds-web/legacyworlds-web-admin/.settings/.jsdtscope b/legacyworlds-web/legacyworlds-web-admin/.settings/.jsdtscope
new file mode 100644
index 0000000..bbb8e68
--- /dev/null
+++ b/legacyworlds-web/legacyworlds-web-admin/.settings/.jsdtscope
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="con" path="org.eclipse.wst.jsdt.launching.JRE_CONTAINER"/>
+	<classpathentry kind="con" path="org.eclipse.wst.jsdt.launching.WebProject">
+		<attributes>
+			<attribute name="hide" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="con" path="org.eclipse.wst.jsdt.launching.baseBrowserLibrary"/>
+	<classpathentry kind="output" path=""/>
+</classpath>
diff --git a/legacyworlds-web/legacyworlds-web-admin/.settings/org.eclipse.jdt.core.prefs b/legacyworlds-web/legacyworlds-web-admin/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..4e54f2c
--- /dev/null
+++ b/legacyworlds-web/legacyworlds-web-admin/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,8 @@
+#Thu Apr 15 19:33:04 CEST 2010
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.6
diff --git a/legacyworlds-web/legacyworlds-web-admin/.settings/org.eclipse.wst.common.component b/legacyworlds-web/legacyworlds-web-admin/.settings/org.eclipse.wst.common.component
new file mode 100644
index 0000000..45b17b5
--- /dev/null
+++ b/legacyworlds-web/legacyworlds-web-admin/.settings/org.eclipse.wst.common.component
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project-modules id="moduleCoreId" project-version="1.5.0">
+    <wb-module deploy-name="legacyworlds-web-admin">
+        <wb-resource deploy-path="/" source-path="/WebContent"/>
+        <wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/java"/>
+        <wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/resources"/>
+        <wb-resource deploy-path="/WEB-INF/classes" source-path="/src/test/java"/>
+        <wb-resource deploy-path="/WEB-INF/classes" source-path="/src/test/resources"/>
+        <property name="context-root" value="legacyworlds-web-admin"/>
+        <property name="java-output-path" value="/legacyworlds-web-admin/target/classes"/>
+    </wb-module>
+</project-modules>
diff --git a/legacyworlds-web/legacyworlds-web-admin/.settings/org.eclipse.wst.common.project.facet.core.xml b/legacyworlds-web/legacyworlds-web-admin/.settings/org.eclipse.wst.common.project.facet.core.xml
new file mode 100644
index 0000000..9680654
--- /dev/null
+++ b/legacyworlds-web/legacyworlds-web-admin/.settings/org.eclipse.wst.common.project.facet.core.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<faceted-project>
+  <runtime name="Apache Tomcat v6.0"/>
+  <installed facet="jst.java" version="6.0"/>
+  <installed facet="jst.web" version="2.4"/>
+</faceted-project>
diff --git a/legacyworlds-web/legacyworlds-web-admin/.settings/org.eclipse.wst.jsdt.ui.superType.container b/legacyworlds-web/legacyworlds-web-admin/.settings/org.eclipse.wst.jsdt.ui.superType.container
new file mode 100644
index 0000000..3bd5d0a
--- /dev/null
+++ b/legacyworlds-web/legacyworlds-web-admin/.settings/org.eclipse.wst.jsdt.ui.superType.container
@@ -0,0 +1 @@
+org.eclipse.wst.jsdt.launching.baseBrowserLibrary
\ No newline at end of file
diff --git a/legacyworlds-web/legacyworlds-web-admin/.settings/org.eclipse.wst.jsdt.ui.superType.name b/legacyworlds-web/legacyworlds-web-admin/.settings/org.eclipse.wst.jsdt.ui.superType.name
new file mode 100644
index 0000000..05bd71b
--- /dev/null
+++ b/legacyworlds-web/legacyworlds-web-admin/.settings/org.eclipse.wst.jsdt.ui.superType.name
@@ -0,0 +1 @@
+Window
\ No newline at end of file
diff --git a/legacyworlds-web/legacyworlds-web-admin/.settings/org.eclipse.wst.ws.service.policy.prefs b/legacyworlds-web/legacyworlds-web-admin/.settings/org.eclipse.wst.ws.service.policy.prefs
new file mode 100644
index 0000000..5095f8b
--- /dev/null
+++ b/legacyworlds-web/legacyworlds-web-admin/.settings/org.eclipse.wst.ws.service.policy.prefs
@@ -0,0 +1,3 @@
+#Mon Apr 19 12:39:12 CEST 2010
+eclipse.preferences.version=1
+org.eclipse.wst.ws.service.policy.projectEnabled=false
diff --git a/legacyworlds-web/legacyworlds-web-admin/.settings/org.maven.ide.eclipse.prefs b/legacyworlds-web/legacyworlds-web-admin/.settings/org.maven.ide.eclipse.prefs
new file mode 100644
index 0000000..bb79aef
--- /dev/null
+++ b/legacyworlds-web/legacyworlds-web-admin/.settings/org.maven.ide.eclipse.prefs
@@ -0,0 +1,9 @@
+#Thu Apr 15 19:11:01 CEST 2010
+activeProfiles=
+eclipse.preferences.version=1
+fullBuildGoals=process-test-resources
+includeModules=false
+resolveWorkspaceProjects=true
+resourceFilterGoals=process-resources resources\:testResources
+skipCompilerPlugin=true
+version=1
diff --git a/legacyworlds-web-admin/Content/Raw/META-INF/MANIFEST.MF b/legacyworlds-web/legacyworlds-web-admin/WebContent/META-INF/MANIFEST.MF
similarity index 100%
rename from legacyworlds-web-admin/Content/Raw/META-INF/MANIFEST.MF
rename to legacyworlds-web/legacyworlds-web-admin/WebContent/META-INF/MANIFEST.MF
diff --git a/legacyworlds-web-admin/Content/Raw/WEB-INF/admin-servlet.xml b/legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/admin-servlet.xml
similarity index 100%
rename from legacyworlds-web-admin/Content/Raw/WEB-INF/admin-servlet.xml
rename to legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/admin-servlet.xml
diff --git a/legacyworlds-web-admin/Content/Raw/WEB-INF/fm/ROOT.ftl b/legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/ROOT.ftl
similarity index 100%
rename from legacyworlds-web-admin/Content/Raw/WEB-INF/fm/ROOT.ftl
rename to legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/ROOT.ftl
diff --git a/legacyworlds-web-admin/Content/Raw/WEB-INF/fm/containers/external.ftl b/legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/containers/external.ftl
similarity index 100%
rename from legacyworlds-web-admin/Content/Raw/WEB-INF/fm/containers/external.ftl
rename to legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/containers/external.ftl
diff --git a/legacyworlds-web-admin/Content/Raw/WEB-INF/fm/containers/internal.ftl b/legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/containers/internal.ftl
similarity index 100%
rename from legacyworlds-web-admin/Content/Raw/WEB-INF/fm/containers/internal.ftl
rename to legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/containers/internal.ftl
diff --git a/legacyworlds-web-admin/Content/Raw/WEB-INF/fm/layout/columns.ftl b/legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/layout/columns.ftl
similarity index 100%
rename from legacyworlds-web-admin/Content/Raw/WEB-INF/fm/layout/columns.ftl
rename to legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/layout/columns.ftl
diff --git a/legacyworlds-web-admin/Content/Raw/WEB-INF/fm/layout/datatable.ftl b/legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/layout/datatable.ftl
similarity index 100%
rename from legacyworlds-web-admin/Content/Raw/WEB-INF/fm/layout/datatable.ftl
rename to legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/layout/datatable.ftl
diff --git a/legacyworlds-web-admin/Content/Raw/WEB-INF/fm/layout/fields.ftl b/legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/layout/fields.ftl
similarity index 100%
rename from legacyworlds-web-admin/Content/Raw/WEB-INF/fm/layout/fields.ftl
rename to legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/layout/fields.ftl
diff --git a/legacyworlds-web-admin/Content/Raw/WEB-INF/fm/layout/form.ftl b/legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/layout/form.ftl
similarity index 100%
rename from legacyworlds-web-admin/Content/Raw/WEB-INF/fm/layout/form.ftl
rename to legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/layout/form.ftl
diff --git a/legacyworlds-web-admin/Content/Raw/WEB-INF/fm/layout/lists.ftl b/legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/layout/lists.ftl
similarity index 100%
rename from legacyworlds-web-admin/Content/Raw/WEB-INF/fm/layout/lists.ftl
rename to legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/layout/lists.ftl
diff --git a/legacyworlds-web-admin/Content/Raw/WEB-INF/fm/layout/tabs.ftl b/legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/layout/tabs.ftl
similarity index 100%
rename from legacyworlds-web-admin/Content/Raw/WEB-INF/fm/layout/tabs.ftl
rename to legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/layout/tabs.ftl
diff --git a/legacyworlds-web-admin/Content/Raw/WEB-INF/fm/types/addAdmin.ftl b/legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/types/addAdmin.ftl
similarity index 100%
rename from legacyworlds-web-admin/Content/Raw/WEB-INF/fm/types/addAdmin.ftl
rename to legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/types/addAdmin.ftl
diff --git a/legacyworlds-web-admin/Content/Raw/WEB-INF/fm/types/admins.ftl b/legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/types/admins.ftl
similarity index 100%
rename from legacyworlds-web-admin/Content/Raw/WEB-INF/fm/types/admins.ftl
rename to legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/types/admins.ftl
diff --git a/legacyworlds-web-admin/Content/Raw/WEB-INF/fm/types/banReject.ftl b/legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/types/banReject.ftl
similarity index 100%
rename from legacyworlds-web-admin/Content/Raw/WEB-INF/fm/types/banReject.ftl
rename to legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/types/banReject.ftl
diff --git a/legacyworlds-web-admin/Content/Raw/WEB-INF/fm/types/banRequest.ftl b/legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/types/banRequest.ftl
similarity index 100%
rename from legacyworlds-web-admin/Content/Raw/WEB-INF/fm/types/banRequest.ftl
rename to legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/types/banRequest.ftl
diff --git a/legacyworlds-web-admin/Content/Raw/WEB-INF/fm/types/bans.ftl b/legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/types/bans.ftl
similarity index 100%
rename from legacyworlds-web-admin/Content/Raw/WEB-INF/fm/types/bans.ftl
rename to legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/types/bans.ftl
diff --git a/legacyworlds-web-admin/Content/Raw/WEB-INF/fm/types/bansSummary.ftl b/legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/types/bansSummary.ftl
similarity index 100%
rename from legacyworlds-web-admin/Content/Raw/WEB-INF/fm/types/bansSummary.ftl
rename to legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/types/bansSummary.ftl
diff --git a/legacyworlds-web-admin/Content/Raw/WEB-INF/fm/types/bugsList.ftl b/legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/types/bugsList.ftl
similarity index 100%
rename from legacyworlds-web-admin/Content/Raw/WEB-INF/fm/types/bugsList.ftl
rename to legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/types/bugsList.ftl
diff --git a/legacyworlds-web-admin/Content/Raw/WEB-INF/fm/types/bugsReport.ftl b/legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/types/bugsReport.ftl
similarity index 100%
rename from legacyworlds-web-admin/Content/Raw/WEB-INF/fm/types/bugsReport.ftl
rename to legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/types/bugsReport.ftl
diff --git a/legacyworlds-web-admin/Content/Raw/WEB-INF/fm/types/bugsSummary.ftl b/legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/types/bugsSummary.ftl
similarity index 100%
rename from legacyworlds-web-admin/Content/Raw/WEB-INF/fm/types/bugsSummary.ftl
rename to legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/types/bugsSummary.ftl
diff --git a/legacyworlds-web-admin/Content/Raw/WEB-INF/fm/types/bugsTabs.ftl b/legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/types/bugsTabs.ftl
similarity index 100%
rename from legacyworlds-web-admin/Content/Raw/WEB-INF/fm/types/bugsTabs.ftl
rename to legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/types/bugsTabs.ftl
diff --git a/legacyworlds-web-admin/Content/Raw/WEB-INF/fm/types/bugsView.ftl b/legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/types/bugsView.ftl
similarity index 100%
rename from legacyworlds-web-admin/Content/Raw/WEB-INF/fm/types/bugsView.ftl
rename to legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/types/bugsView.ftl
diff --git a/legacyworlds-web-admin/Content/Raw/WEB-INF/fm/types/changePassword.ftl b/legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/types/changePassword.ftl
similarity index 100%
rename from legacyworlds-web-admin/Content/Raw/WEB-INF/fm/types/changePassword.ftl
rename to legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/types/changePassword.ftl
diff --git a/legacyworlds-web-admin/Content/Raw/WEB-INF/fm/types/constants.ftl b/legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/types/constants.ftl
similarity index 100%
rename from legacyworlds-web-admin/Content/Raw/WEB-INF/fm/types/constants.ftl
rename to legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/types/constants.ftl
diff --git a/legacyworlds-web-admin/Content/Raw/WEB-INF/fm/types/language.ftl b/legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/types/language.ftl
similarity index 100%
rename from legacyworlds-web-admin/Content/Raw/WEB-INF/fm/types/language.ftl
rename to legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/types/language.ftl
diff --git a/legacyworlds-web-admin/Content/Raw/WEB-INF/fm/types/languages.ftl b/legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/types/languages.ftl
similarity index 100%
rename from legacyworlds-web-admin/Content/Raw/WEB-INF/fm/types/languages.ftl
rename to legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/types/languages.ftl
diff --git a/legacyworlds-web-admin/Content/Raw/WEB-INF/fm/types/logEntry.ftl b/legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/types/logEntry.ftl
similarity index 100%
rename from legacyworlds-web-admin/Content/Raw/WEB-INF/fm/types/logEntry.ftl
rename to legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/types/logEntry.ftl
diff --git a/legacyworlds-web-admin/Content/Raw/WEB-INF/fm/types/login.ftl b/legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/types/login.ftl
similarity index 100%
rename from legacyworlds-web-admin/Content/Raw/WEB-INF/fm/types/login.ftl
rename to legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/types/login.ftl
diff --git a/legacyworlds-web-admin/Content/Raw/WEB-INF/fm/types/logs.ftl b/legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/types/logs.ftl
similarity index 100%
rename from legacyworlds-web-admin/Content/Raw/WEB-INF/fm/types/logs.ftl
rename to legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/types/logs.ftl
diff --git a/legacyworlds-web-admin/Content/Raw/WEB-INF/fm/types/main.ftl b/legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/types/main.ftl
similarity index 100%
rename from legacyworlds-web-admin/Content/Raw/WEB-INF/fm/types/main.ftl
rename to legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/types/main.ftl
diff --git a/legacyworlds-web-admin/Content/Raw/WEB-INF/fm/types/maintenance.ftl b/legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/types/maintenance.ftl
similarity index 100%
rename from legacyworlds-web-admin/Content/Raw/WEB-INF/fm/types/maintenance.ftl
rename to legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/types/maintenance.ftl
diff --git a/legacyworlds-web-admin/Content/Raw/WEB-INF/fm/types/message.ftl b/legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/types/message.ftl
similarity index 100%
rename from legacyworlds-web-admin/Content/Raw/WEB-INF/fm/types/message.ftl
rename to legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/types/message.ftl
diff --git a/legacyworlds-web-admin/Content/Raw/WEB-INF/fm/types/messageBox.ftl b/legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/types/messageBox.ftl
similarity index 100%
rename from legacyworlds-web-admin/Content/Raw/WEB-INF/fm/types/messageBox.ftl
rename to legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/types/messageBox.ftl
diff --git a/legacyworlds-web-admin/Content/Raw/WEB-INF/fm/types/messageTabs.ftl b/legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/types/messageTabs.ftl
similarity index 100%
rename from legacyworlds-web-admin/Content/Raw/WEB-INF/fm/types/messageTabs.ftl
rename to legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/types/messageTabs.ftl
diff --git a/legacyworlds-web-admin/Content/Raw/WEB-INF/fm/types/messageWriter.ftl b/legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/types/messageWriter.ftl
similarity index 100%
rename from legacyworlds-web-admin/Content/Raw/WEB-INF/fm/types/messageWriter.ftl
rename to legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/types/messageWriter.ftl
diff --git a/legacyworlds-web-admin/Content/Raw/WEB-INF/fm/types/names.ftl b/legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/types/names.ftl
similarity index 100%
rename from legacyworlds-web-admin/Content/Raw/WEB-INF/fm/types/names.ftl
rename to legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/types/names.ftl
diff --git a/legacyworlds-web-admin/Content/Raw/WEB-INF/fm/types/namesSummary.ftl b/legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/types/namesSummary.ftl
similarity index 100%
rename from legacyworlds-web-admin/Content/Raw/WEB-INF/fm/types/namesSummary.ftl
rename to legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/types/namesSummary.ftl
diff --git a/legacyworlds-web-admin/Content/Raw/WEB-INF/fm/types/offline.ftl b/legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/types/offline.ftl
similarity index 100%
rename from legacyworlds-web-admin/Content/Raw/WEB-INF/fm/types/offline.ftl
rename to legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/types/offline.ftl
diff --git a/legacyworlds-web-admin/Content/Raw/WEB-INF/fm/types/preferences.ftl b/legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/types/preferences.ftl
similarity index 100%
rename from legacyworlds-web-admin/Content/Raw/WEB-INF/fm/types/preferences.ftl
rename to legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/types/preferences.ftl
diff --git a/legacyworlds-web-admin/Content/Raw/WEB-INF/fm/types/resetAdmin.ftl b/legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/types/resetAdmin.ftl
similarity index 100%
rename from legacyworlds-web-admin/Content/Raw/WEB-INF/fm/types/resetAdmin.ftl
rename to legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/types/resetAdmin.ftl
diff --git a/legacyworlds-web-admin/Content/Raw/WEB-INF/fm/types/spam.ftl b/legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/types/spam.ftl
similarity index 100%
rename from legacyworlds-web-admin/Content/Raw/WEB-INF/fm/types/spam.ftl
rename to legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/types/spam.ftl
diff --git a/legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/types/technologies.ftl b/legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/types/technologies.ftl
new file mode 100644
index 0000000..dd03803
--- /dev/null
+++ b/legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/types/technologies.ftl
@@ -0,0 +1,22 @@
+<@page title="Technologies">
+	<h1>Technologies</h1>
+	<#if data.categories?size == 0>
+		<p>No technologies have been defined.</p>
+	<#else>
+		<#list data.categories as category>
+			<ul><li><span style="font-size: larger">Category ${category.name?xhtml}</span>
+				(<a href="tech-category-${category.name?url}">edit</a>)
+				<#if category.techs?size == 0>
+					<ul><li>No technologies in this category.</li></ul>
+				<#else>
+					<ul>
+						<#list category.techs as tech>
+							<li>${tech?xhtml}</li>
+						</#list>
+					</ul>
+				</#if>
+			</li></ul>
+			<p>&nbsp;</p>
+		</#list>
+	</#if>
+</@page>
\ No newline at end of file
diff --git a/legacyworlds-web-admin/Content/Raw/WEB-INF/fm/types/ticker.ftl b/legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/types/ticker.ftl
similarity index 100%
rename from legacyworlds-web-admin/Content/Raw/WEB-INF/fm/types/ticker.ftl
rename to legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/types/ticker.ftl
diff --git a/legacyworlds-web-admin/Content/Raw/WEB-INF/fm/types/user.ftl b/legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/types/user.ftl
similarity index 100%
rename from legacyworlds-web-admin/Content/Raw/WEB-INF/fm/types/user.ftl
rename to legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/types/user.ftl
diff --git a/legacyworlds-web-admin/Content/Raw/WEB-INF/fm/types/userSessions.ftl b/legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/types/userSessions.ftl
similarity index 100%
rename from legacyworlds-web-admin/Content/Raw/WEB-INF/fm/types/userSessions.ftl
rename to legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/types/userSessions.ftl
diff --git a/legacyworlds-web-admin/Content/Raw/WEB-INF/fm/types/users.ftl b/legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/types/users.ftl
similarity index 100%
rename from legacyworlds-web-admin/Content/Raw/WEB-INF/fm/types/users.ftl
rename to legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/types/users.ftl
diff --git a/legacyworlds-web-admin/Content/Raw/WEB-INF/fm/types/viewAdmin.ftl b/legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/types/viewAdmin.ftl
similarity index 100%
rename from legacyworlds-web-admin/Content/Raw/WEB-INF/fm/types/viewAdmin.ftl
rename to legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/types/viewAdmin.ftl
diff --git a/legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/version.ftl b/legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/version.ftl
new file mode 100644
index 0000000..e4abdb7
--- /dev/null
+++ b/legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/fm/version.ftl
@@ -0,0 +1,2 @@
+<#macro version>Milestone 2</#macro>
+<#macro full_version>Beta 6 milestone 2 (5.99.2)</#macro>
\ No newline at end of file
diff --git a/legacyworlds-web-admin/Content/Raw/WEB-INF/web.xml b/legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/web.xml
similarity index 100%
rename from legacyworlds-web-admin/Content/Raw/WEB-INF/web.xml
rename to legacyworlds-web/legacyworlds-web-admin/WebContent/WEB-INF/web.xml
diff --git a/legacyworlds-web-admin/Content/Raw/css/main.css b/legacyworlds-web/legacyworlds-web-admin/WebContent/css/main.css
similarity index 100%
rename from legacyworlds-web-admin/Content/Raw/css/main.css
rename to legacyworlds-web/legacyworlds-web-admin/WebContent/css/main.css
diff --git a/legacyworlds-web/legacyworlds-web-admin/pom.xml b/legacyworlds-web/legacyworlds-web-admin/pom.xml
new file mode 100644
index 0000000..824b028
--- /dev/null
+++ b/legacyworlds-web/legacyworlds-web-admin/pom.xml
@@ -0,0 +1,95 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+	<parent>
+		<artifactId>legacyworlds-web</artifactId>
+		<groupId>com.deepclone.lw</groupId>
+		<version>5.99.2</version>
+	</parent>
+	
+	<groupId>com.deepclone.lw</groupId>
+	<artifactId>legacyworlds-web-admin</artifactId>
+	<version>5.99.2</version>
+	<packaging>war</packaging>
+	<name>Legacy Worlds administration site</name>
+
+	<dependencies>
+		<dependency>
+			<groupId>com.deepclone.lw</groupId>
+			<artifactId>legacyworlds-web-beans</artifactId>
+			<version>${project.version}</version>
+		</dependency>
+
+		<dependency>
+			<groupId>javax.servlet</groupId>
+			<artifactId>servlet-api</artifactId>
+			<version>2.5</version>
+			<scope>provided</scope>
+		</dependency>
+		
+		<dependency>
+			<groupId>org.freemarker</groupId>
+			<artifactId>freemarker</artifactId>
+			<version>${org.freemarker.version}</version>
+			<scope>runtime</scope>
+		</dependency>
+		
+		<dependency>
+			<groupId>com.thoughtworks.xstream</groupId>
+			<artifactId>xstream</artifactId>
+			<version>${com.thoughtworks.xstream.version}</version>
+			<type>jar</type>
+		</dependency>
+	</dependencies>
+
+	<build>
+		<plugins>
+
+			<!-- 
+			<plugin>
+				<groupId>org.codehaus.mojo</groupId>
+				<artifactId>tomcat-maven-plugin</artifactId>
+				<version>1.0-beta-1</version>
+				<configuration>
+					<url>http://localhost:8080/manager</url>
+					<path>/lwadmin</path>
+					<update>true</update>
+				</configuration>
+				<executions>
+					<execution>
+						<id>deploy-admin-site</id>
+						<phase>package</phase>
+						<goals>
+							<goal>deploy</goal>
+						</goals>
+					</execution>
+				</executions>
+			</plugin>
+			-->
+
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-war-plugin</artifactId>
+				<version>2.0</version>
+				<configuration>
+					<webResources>
+						<resource>
+							<directory>legacyworlds-web/legacyworlds-web-admin/WebContent</directory>
+						</resource>
+					</webResources>
+				</configuration>
+				<executions>
+					<execution>
+						<id>build-admin-war</id>
+						<phase>package</phase>
+						<goals>
+							<goal>war</goal>
+						</goals>
+					</execution>
+				</executions>
+			</plugin>
+
+		</plugins>
+	</build>
+
+</project>
\ No newline at end of file
diff --git a/legacyworlds-web-admin/src/main/java/com/deepclone/lw/web/admin/BanhammerPages.java b/legacyworlds-web/legacyworlds-web-admin/src/main/java/com/deepclone/lw/web/admin/BanhammerPages.java
similarity index 100%
rename from legacyworlds-web-admin/src/main/java/com/deepclone/lw/web/admin/BanhammerPages.java
rename to legacyworlds-web/legacyworlds-web-admin/src/main/java/com/deepclone/lw/web/admin/BanhammerPages.java
diff --git a/legacyworlds-web-admin/src/main/java/com/deepclone/lw/web/admin/BugTrackerPages.java b/legacyworlds-web/legacyworlds-web-admin/src/main/java/com/deepclone/lw/web/admin/BugTrackerPages.java
similarity index 100%
rename from legacyworlds-web-admin/src/main/java/com/deepclone/lw/web/admin/BugTrackerPages.java
rename to legacyworlds-web/legacyworlds-web-admin/src/main/java/com/deepclone/lw/web/admin/BugTrackerPages.java
diff --git a/legacyworlds-web-admin/src/main/java/com/deepclone/lw/web/admin/ConstantsPages.java b/legacyworlds-web/legacyworlds-web-admin/src/main/java/com/deepclone/lw/web/admin/ConstantsPages.java
similarity index 100%
rename from legacyworlds-web-admin/src/main/java/com/deepclone/lw/web/admin/ConstantsPages.java
rename to legacyworlds-web/legacyworlds-web-admin/src/main/java/com/deepclone/lw/web/admin/ConstantsPages.java
diff --git a/legacyworlds-web-admin/src/main/java/com/deepclone/lw/web/admin/ErrorHandlerBean.java b/legacyworlds-web/legacyworlds-web-admin/src/main/java/com/deepclone/lw/web/admin/ErrorHandlerBean.java
similarity index 100%
rename from legacyworlds-web-admin/src/main/java/com/deepclone/lw/web/admin/ErrorHandlerBean.java
rename to legacyworlds-web/legacyworlds-web-admin/src/main/java/com/deepclone/lw/web/admin/ErrorHandlerBean.java
diff --git a/legacyworlds-web-admin/src/main/java/com/deepclone/lw/web/admin/I18NPages.java b/legacyworlds-web/legacyworlds-web-admin/src/main/java/com/deepclone/lw/web/admin/I18NPages.java
similarity index 100%
rename from legacyworlds-web-admin/src/main/java/com/deepclone/lw/web/admin/I18NPages.java
rename to legacyworlds-web/legacyworlds-web-admin/src/main/java/com/deepclone/lw/web/admin/I18NPages.java
diff --git a/legacyworlds-web-admin/src/main/java/com/deepclone/lw/web/admin/LogPages.java b/legacyworlds-web/legacyworlds-web-admin/src/main/java/com/deepclone/lw/web/admin/LogPages.java
similarity index 100%
rename from legacyworlds-web-admin/src/main/java/com/deepclone/lw/web/admin/LogPages.java
rename to legacyworlds-web/legacyworlds-web-admin/src/main/java/com/deepclone/lw/web/admin/LogPages.java
diff --git a/legacyworlds-web-admin/src/main/java/com/deepclone/lw/web/admin/LoginPage.java b/legacyworlds-web/legacyworlds-web-admin/src/main/java/com/deepclone/lw/web/admin/LoginPage.java
similarity index 100%
rename from legacyworlds-web-admin/src/main/java/com/deepclone/lw/web/admin/LoginPage.java
rename to legacyworlds-web/legacyworlds-web-admin/src/main/java/com/deepclone/lw/web/admin/LoginPage.java
diff --git a/legacyworlds-web-admin/src/main/java/com/deepclone/lw/web/admin/MaintenancePages.java b/legacyworlds-web/legacyworlds-web-admin/src/main/java/com/deepclone/lw/web/admin/MaintenancePages.java
similarity index 100%
rename from legacyworlds-web-admin/src/main/java/com/deepclone/lw/web/admin/MaintenancePages.java
rename to legacyworlds-web/legacyworlds-web-admin/src/main/java/com/deepclone/lw/web/admin/MaintenancePages.java
diff --git a/legacyworlds-web-admin/src/main/java/com/deepclone/lw/web/admin/MessageBoxView.java b/legacyworlds-web/legacyworlds-web-admin/src/main/java/com/deepclone/lw/web/admin/MessageBoxView.java
similarity index 100%
rename from legacyworlds-web-admin/src/main/java/com/deepclone/lw/web/admin/MessageBoxView.java
rename to legacyworlds-web/legacyworlds-web-admin/src/main/java/com/deepclone/lw/web/admin/MessageBoxView.java
diff --git a/legacyworlds-web-admin/src/main/java/com/deepclone/lw/web/admin/MessagesPages.java b/legacyworlds-web/legacyworlds-web-admin/src/main/java/com/deepclone/lw/web/admin/MessagesPages.java
similarity index 100%
rename from legacyworlds-web-admin/src/main/java/com/deepclone/lw/web/admin/MessagesPages.java
rename to legacyworlds-web/legacyworlds-web-admin/src/main/java/com/deepclone/lw/web/admin/MessagesPages.java
diff --git a/legacyworlds-web-admin/src/main/java/com/deepclone/lw/web/admin/NamesPages.java b/legacyworlds-web/legacyworlds-web-admin/src/main/java/com/deepclone/lw/web/admin/NamesPages.java
similarity index 100%
rename from legacyworlds-web-admin/src/main/java/com/deepclone/lw/web/admin/NamesPages.java
rename to legacyworlds-web/legacyworlds-web-admin/src/main/java/com/deepclone/lw/web/admin/NamesPages.java
diff --git a/legacyworlds-web-admin/src/main/java/com/deepclone/lw/web/admin/PasswordPages.java b/legacyworlds-web/legacyworlds-web-admin/src/main/java/com/deepclone/lw/web/admin/PasswordPages.java
similarity index 100%
rename from legacyworlds-web-admin/src/main/java/com/deepclone/lw/web/admin/PasswordPages.java
rename to legacyworlds-web/legacyworlds-web-admin/src/main/java/com/deepclone/lw/web/admin/PasswordPages.java
diff --git a/legacyworlds-web-admin/src/main/java/com/deepclone/lw/web/admin/PreferencesPages.java b/legacyworlds-web/legacyworlds-web-admin/src/main/java/com/deepclone/lw/web/admin/PreferencesPages.java
similarity index 100%
rename from legacyworlds-web-admin/src/main/java/com/deepclone/lw/web/admin/PreferencesPages.java
rename to legacyworlds-web/legacyworlds-web-admin/src/main/java/com/deepclone/lw/web/admin/PreferencesPages.java
diff --git a/legacyworlds-web-admin/src/main/java/com/deepclone/lw/web/admin/SessionPages.java b/legacyworlds-web/legacyworlds-web-admin/src/main/java/com/deepclone/lw/web/admin/SessionPages.java
similarity index 100%
rename from legacyworlds-web-admin/src/main/java/com/deepclone/lw/web/admin/SessionPages.java
rename to legacyworlds-web/legacyworlds-web-admin/src/main/java/com/deepclone/lw/web/admin/SessionPages.java
diff --git a/legacyworlds-web-admin/src/main/java/com/deepclone/lw/web/admin/SpamPages.java b/legacyworlds-web/legacyworlds-web-admin/src/main/java/com/deepclone/lw/web/admin/SpamPages.java
similarity index 100%
rename from legacyworlds-web-admin/src/main/java/com/deepclone/lw/web/admin/SpamPages.java
rename to legacyworlds-web/legacyworlds-web-admin/src/main/java/com/deepclone/lw/web/admin/SpamPages.java
diff --git a/legacyworlds-web-admin/src/main/java/com/deepclone/lw/web/admin/SuperUserPages.java b/legacyworlds-web/legacyworlds-web-admin/src/main/java/com/deepclone/lw/web/admin/SuperUserPages.java
similarity index 100%
rename from legacyworlds-web-admin/src/main/java/com/deepclone/lw/web/admin/SuperUserPages.java
rename to legacyworlds-web/legacyworlds-web-admin/src/main/java/com/deepclone/lw/web/admin/SuperUserPages.java
diff --git a/legacyworlds-web/legacyworlds-web-admin/src/main/java/com/deepclone/lw/web/admin/TechnologyPages.java b/legacyworlds-web/legacyworlds-web-admin/src/main/java/com/deepclone/lw/web/admin/TechnologyPages.java
new file mode 100644
index 0000000..ff32e08
--- /dev/null
+++ b/legacyworlds-web/legacyworlds-web-admin/src/main/java/com/deepclone/lw/web/admin/TechnologyPages.java
@@ -0,0 +1,37 @@
+package com.deepclone.lw.web.admin;
+
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import com.deepclone.lw.cmd.admin.techs.ListCategoriesResponse;
+import com.deepclone.lw.session.SessionException;
+import com.deepclone.lw.web.beans.intercept.SessionRequirement;
+import com.deepclone.lw.web.beans.session.SessionMaintenanceException;
+import com.deepclone.lw.web.beans.session.SessionServerException;
+import com.deepclone.lw.web.beans.view.PageControllerBase;
+import com.deepclone.lw.web.csess.AdminSession;
+
+
+
+@Controller
+@SessionRequirement( value = true , subType = "main" , redirectTo = "admin-session" )
+public class TechnologyPages
+		extends PageControllerBase
+{
+
+	@RequestMapping( "/techs" )
+	public String viewStatus( HttpServletRequest request , Model model )
+			throws SessionException , SessionServerException , SessionMaintenanceException
+	{
+		ListCategoriesResponse response = this.getSession( AdminSession.class , request ).getTechList( );
+		if ( !response.isPrivilegeOk( ) ) {
+			return this.redirect( "main" );
+		}
+		return this.render( model , "internal" , "en" , "technologies" , response );
+	}
+
+}
diff --git a/legacyworlds-web-admin/src/main/java/com/deepclone/lw/web/admin/TickerPages.java b/legacyworlds-web/legacyworlds-web-admin/src/main/java/com/deepclone/lw/web/admin/TickerPages.java
similarity index 100%
rename from legacyworlds-web-admin/src/main/java/com/deepclone/lw/web/admin/TickerPages.java
rename to legacyworlds-web/legacyworlds-web-admin/src/main/java/com/deepclone/lw/web/admin/TickerPages.java
diff --git a/legacyworlds-web-admin/src/main/java/com/deepclone/lw/web/admin/UsersPages.java b/legacyworlds-web/legacyworlds-web-admin/src/main/java/com/deepclone/lw/web/admin/UsersPages.java
similarity index 100%
rename from legacyworlds-web-admin/src/main/java/com/deepclone/lw/web/admin/UsersPages.java
rename to legacyworlds-web/legacyworlds-web-admin/src/main/java/com/deepclone/lw/web/admin/UsersPages.java
diff --git a/legacyworlds-web-admin/src/main/java/com/deepclone/lw/web/admin/i18ne/LanguageExport.java b/legacyworlds-web/legacyworlds-web-admin/src/main/java/com/deepclone/lw/web/admin/i18ne/LanguageExport.java
similarity index 100%
rename from legacyworlds-web-admin/src/main/java/com/deepclone/lw/web/admin/i18ne/LanguageExport.java
rename to legacyworlds-web/legacyworlds-web-admin/src/main/java/com/deepclone/lw/web/admin/i18ne/LanguageExport.java
diff --git a/legacyworlds-web-admin/src/main/java/com/deepclone/lw/web/admin/i18ne/StringExport.java b/legacyworlds-web/legacyworlds-web-admin/src/main/java/com/deepclone/lw/web/admin/i18ne/StringExport.java
similarity index 100%
rename from legacyworlds-web-admin/src/main/java/com/deepclone/lw/web/admin/i18ne/StringExport.java
rename to legacyworlds-web/legacyworlds-web-admin/src/main/java/com/deepclone/lw/web/admin/i18ne/StringExport.java
diff --git a/legacyworlds-web-admin/src/main/resources/log4j.properties b/legacyworlds-web/legacyworlds-web-admin/src/main/resources/log4j.properties
similarity index 100%
rename from legacyworlds-web-admin/src/main/resources/log4j.properties
rename to legacyworlds-web/legacyworlds-web-admin/src/main/resources/log4j.properties
diff --git a/legacyworlds-web/legacyworlds-web-beans/.classpath b/legacyworlds-web/legacyworlds-web-beans/.classpath
new file mode 100644
index 0000000..7c3d14f
--- /dev/null
+++ b/legacyworlds-web/legacyworlds-web-beans/.classpath
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" output="target/classes" path="src/main/java"/>
+	<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources"/>
+	<classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
+	<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+	<classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER"/>
+	<classpathentry kind="output" path="target/classes"/>
+</classpath>
diff --git a/legacyworlds-web/legacyworlds-web-beans/.project b/legacyworlds-web/legacyworlds-web-beans/.project
new file mode 100644
index 0000000..5702a99
--- /dev/null
+++ b/legacyworlds-web/legacyworlds-web-beans/.project
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>legacyworlds-web-beans</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.maven.ide.eclipse.maven2Builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.maven.ide.eclipse.maven2Nature</nature>
+	</natures>
+</projectDescription>
diff --git a/legacyworlds-web/legacyworlds-web-beans/.settings/org.eclipse.jdt.core.prefs b/legacyworlds-web/legacyworlds-web-beans/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..34724f2
--- /dev/null
+++ b/legacyworlds-web/legacyworlds-web-beans/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,6 @@
+#Fri Apr 16 07:54:29 CEST 2010
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.6
diff --git a/legacyworlds-web/legacyworlds-web-beans/.settings/org.maven.ide.eclipse.prefs b/legacyworlds-web/legacyworlds-web-beans/.settings/org.maven.ide.eclipse.prefs
new file mode 100644
index 0000000..b3bba2f
--- /dev/null
+++ b/legacyworlds-web/legacyworlds-web-beans/.settings/org.maven.ide.eclipse.prefs
@@ -0,0 +1,9 @@
+#Fri Apr 16 07:54:27 CEST 2010
+activeProfiles=
+eclipse.preferences.version=1
+fullBuildGoals=process-test-resources
+includeModules=false
+resolveWorkspaceProjects=true
+resourceFilterGoals=process-resources resources\:testResources
+skipCompilerPlugin=true
+version=1
diff --git a/legacyworlds-web-beans/pom.xml b/legacyworlds-web/legacyworlds-web-beans/pom.xml
similarity index 72%
rename from legacyworlds-web-beans/pom.xml
rename to legacyworlds-web/legacyworlds-web-beans/pom.xml
index 07e567e..faef876 100644
--- a/legacyworlds-web-beans/pom.xml
+++ b/legacyworlds-web/legacyworlds-web-beans/pom.xml
@@ -4,13 +4,13 @@
 	<parent>
 		<artifactId>legacyworlds-web</artifactId>
 		<groupId>com.deepclone.lw</groupId>
-		<version>1.0.0</version>
-		<relativePath>../legacyworlds-web/pom.xml</relativePath>
+		<version>5.99.2</version>
 	</parent>
 
+	<groupId>com.deepclone.lw</groupId>
 	<artifactId>legacyworlds-web-beans</artifactId>
-	<version>${legacyworlds.version.main}.${legacyworlds.version.release}-${legacyworlds.version.build}</version>
-	<name>Legacy Worlds - Web - Common components</name>
+	<version>5.99.2</version>
+	<name>Legacy Worlds common web beans</name>
 	<description>Module for common web-related beans. </description>
 	<packaging>jar</packaging>
 
@@ -18,43 +18,53 @@
 		<dependency>
 			<groupId>com.deepclone.lw</groupId>
 			<artifactId>legacyworlds-session</artifactId>
+			<version>${project.version}</version>
 		</dependency>
 		<dependency>
 			<groupId>com.deepclone.lw</groupId>
 			<artifactId>legacyworlds-utils</artifactId>
+			<version>${project.version}</version>
 		</dependency>
 
 		<dependency>
 			<groupId>org.springframework</groupId>
 			<artifactId>spring-core</artifactId>
+			<version>${org.springframework.version}</version>
 		</dependency>
 		<dependency>
 			<groupId>org.springframework</groupId>
 			<artifactId>spring-context</artifactId>
+			<version>${org.springframework.version}</version>
 		</dependency>
 		<dependency>
 			<groupId>org.springframework</groupId>
 			<artifactId>spring-webmvc</artifactId>
+			<version>${org.springframework.version}</version>
 		</dependency>
 
 		<dependency>
 			<groupId>log4j</groupId>
 			<artifactId>log4j</artifactId>
+			<version>${log4j.version}</version>
 		</dependency>
 
 		<dependency>
 			<groupId>commons-dbcp</groupId>
 			<artifactId>commons-dbcp</artifactId>
+			<version>${commons.dbcp.version}</version>
 		</dependency>
 
 		<dependency>
 			<groupId>cglib</groupId>
 			<artifactId>cglib</artifactId>
+			<version>${cglib.version}</version>
 		</dependency>
 
 		<dependency>
 			<groupId>javax.servlet</groupId>
 			<artifactId>servlet-api</artifactId>
+			<version>2.5</version>
+			<scope>provided</scope>
 		</dependency>
 	</dependencies>
-</project>
+</project>
\ No newline at end of file
diff --git a/legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/beans/intercept/IEContentTypeBean.java b/legacyworlds-web/legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/beans/intercept/IEContentTypeBean.java
similarity index 100%
rename from legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/beans/intercept/IEContentTypeBean.java
rename to legacyworlds-web/legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/beans/intercept/IEContentTypeBean.java
diff --git a/legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/beans/intercept/LanguageInterceptorBean.java b/legacyworlds-web/legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/beans/intercept/LanguageInterceptorBean.java
similarity index 100%
rename from legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/beans/intercept/LanguageInterceptorBean.java
rename to legacyworlds-web/legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/beans/intercept/LanguageInterceptorBean.java
diff --git a/legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/beans/intercept/SessionInterceptorBean.java b/legacyworlds-web/legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/beans/intercept/SessionInterceptorBean.java
similarity index 100%
rename from legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/beans/intercept/SessionInterceptorBean.java
rename to legacyworlds-web/legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/beans/intercept/SessionInterceptorBean.java
diff --git a/legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/beans/intercept/SessionRequirement.java b/legacyworlds-web/legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/beans/intercept/SessionRequirement.java
similarity index 100%
rename from legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/beans/intercept/SessionRequirement.java
rename to legacyworlds-web/legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/beans/intercept/SessionRequirement.java
diff --git a/legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/beans/msgs/MessageFormatter.java b/legacyworlds-web/legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/beans/msgs/MessageFormatter.java
similarity index 100%
rename from legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/beans/msgs/MessageFormatter.java
rename to legacyworlds-web/legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/beans/msgs/MessageFormatter.java
diff --git a/legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/beans/msgs/MessageFormatterBean.java b/legacyworlds-web/legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/beans/msgs/MessageFormatterBean.java
similarity index 100%
rename from legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/beans/msgs/MessageFormatterBean.java
rename to legacyworlds-web/legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/beans/msgs/MessageFormatterBean.java
diff --git a/legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/beans/session/ClientSessionReference.java b/legacyworlds-web/legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/beans/session/ClientSessionReference.java
similarity index 100%
rename from legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/beans/session/ClientSessionReference.java
rename to legacyworlds-web/legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/beans/session/ClientSessionReference.java
diff --git a/legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/beans/session/MaintenanceStatus.java b/legacyworlds-web/legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/beans/session/MaintenanceStatus.java
similarity index 100%
rename from legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/beans/session/MaintenanceStatus.java
rename to legacyworlds-web/legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/beans/session/MaintenanceStatus.java
diff --git a/legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/beans/session/MaintenanceStatusBean.java b/legacyworlds-web/legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/beans/session/MaintenanceStatusBean.java
similarity index 100%
rename from legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/beans/session/MaintenanceStatusBean.java
rename to legacyworlds-web/legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/beans/session/MaintenanceStatusBean.java
diff --git a/legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/beans/session/Session.java b/legacyworlds-web/legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/beans/session/Session.java
similarity index 97%
rename from legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/beans/session/Session.java
rename to legacyworlds-web/legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/beans/session/Session.java
index 81e6a3a..b826f25 100644
--- a/legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/beans/session/Session.java
+++ b/legacyworlds-web/legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/beans/session/Session.java
@@ -11,6 +11,7 @@ import com.deepclone.lw.session.SessionException;
 public abstract class Session
 {
 
+	private static final long serialVersionUID = 1L;
 	private ClientSessionReference reference;
 	private SessionClient sClient;
 
diff --git a/legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/beans/session/SessionClient.java b/legacyworlds-web/legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/beans/session/SessionClient.java
similarity index 100%
rename from legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/beans/session/SessionClient.java
rename to legacyworlds-web/legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/beans/session/SessionClient.java
diff --git a/legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/beans/session/SessionClientBean.java b/legacyworlds-web/legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/beans/session/SessionClientBean.java
similarity index 100%
rename from legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/beans/session/SessionClientBean.java
rename to legacyworlds-web/legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/beans/session/SessionClientBean.java
diff --git a/legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/beans/session/SessionMaintenanceException.java b/legacyworlds-web/legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/beans/session/SessionMaintenanceException.java
similarity index 100%
rename from legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/beans/session/SessionMaintenanceException.java
rename to legacyworlds-web/legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/beans/session/SessionMaintenanceException.java
diff --git a/legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/beans/session/SessionServerException.java b/legacyworlds-web/legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/beans/session/SessionServerException.java
similarity index 100%
rename from legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/beans/session/SessionServerException.java
rename to legacyworlds-web/legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/beans/session/SessionServerException.java
diff --git a/legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/beans/session/SessionType.java b/legacyworlds-web/legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/beans/session/SessionType.java
similarity index 100%
rename from legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/beans/session/SessionType.java
rename to legacyworlds-web/legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/beans/session/SessionType.java
diff --git a/legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/beans/view/BugTrackerBase.java b/legacyworlds-web/legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/beans/view/BugTrackerBase.java
similarity index 100%
rename from legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/beans/view/BugTrackerBase.java
rename to legacyworlds-web/legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/beans/view/BugTrackerBase.java
diff --git a/legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/beans/view/Page.java b/legacyworlds-web/legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/beans/view/Page.java
similarity index 100%
rename from legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/beans/view/Page.java
rename to legacyworlds-web/legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/beans/view/Page.java
diff --git a/legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/beans/view/PageControllerBase.java b/legacyworlds-web/legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/beans/view/PageControllerBase.java
similarity index 100%
rename from legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/beans/view/PageControllerBase.java
rename to legacyworlds-web/legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/beans/view/PageControllerBase.java
diff --git a/legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/csess/AdminSession.java b/legacyworlds-web/legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/csess/AdminSession.java
similarity index 97%
rename from legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/csess/AdminSession.java
rename to legacyworlds-web/legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/csess/AdminSession.java
index 2f89e3e..cd5522b 100644
--- a/legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/csess/AdminSession.java
+++ b/legacyworlds-web/legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/csess/AdminSession.java
@@ -17,6 +17,8 @@ import com.deepclone.lw.cmd.admin.msg.*;
 import com.deepclone.lw.cmd.admin.naming.*;
 import com.deepclone.lw.cmd.admin.prefs.*;
 import com.deepclone.lw.cmd.admin.su.*;
+import com.deepclone.lw.cmd.admin.techs.ListCategoriesCommand;
+import com.deepclone.lw.cmd.admin.techs.ListCategoriesResponse;
 import com.deepclone.lw.cmd.admin.tick.*;
 import com.deepclone.lw.cmd.admin.users.*;
 import com.deepclone.lw.cmd.bt.*;
@@ -539,4 +541,13 @@ public class AdminSession
 		this.execute( new EndMaintenanceCommand( ) );
 	}
 
+
+	/* Technology graph */
+
+	public ListCategoriesResponse getTechList( )
+			throws SessionException , SessionServerException , SessionMaintenanceException
+	{
+		return (ListCategoriesResponse) this.execute( new ListCategoriesCommand( ) );
+	}
+
 }
diff --git a/legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/csess/ExternalSession.java b/legacyworlds-web/legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/csess/ExternalSession.java
similarity index 100%
rename from legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/csess/ExternalSession.java
rename to legacyworlds-web/legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/csess/ExternalSession.java
diff --git a/legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/csess/PlayerSession.java b/legacyworlds-web/legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/csess/PlayerSession.java
similarity index 89%
rename from legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/csess/PlayerSession.java
rename to legacyworlds-web/legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/csess/PlayerSession.java
index f47b989..70559b6 100644
--- a/legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/csess/PlayerSession.java
+++ b/legacyworlds-web/legacyworlds-web-beans/src/main/java/com/deepclone/lw/web/csess/PlayerSession.java
@@ -17,10 +17,11 @@ import com.deepclone.lw.cmd.player.elist.*;
 import com.deepclone.lw.cmd.player.fleets.*;
 import com.deepclone.lw.cmd.player.gdata.*;
 import com.deepclone.lw.cmd.player.planets.*;
-import com.deepclone.lw.cmd.player.tech.GetResearchCommand;
-import com.deepclone.lw.cmd.player.tech.GetResearchResponse;
-import com.deepclone.lw.cmd.player.tech.ImplementTechCommand;
-import com.deepclone.lw.cmd.player.tech.UpdateResearchPrioritiesCommand;
+import com.deepclone.lw.cmd.player.research.ImplementTechCommand;
+import com.deepclone.lw.cmd.player.research.ResearchOperationResponse;
+import com.deepclone.lw.cmd.player.research.SetResearchPrioritiesCommand;
+import com.deepclone.lw.cmd.player.research.ViewResearchCommand;
+import com.deepclone.lw.cmd.player.research.ViewResearchResponse;
 import com.deepclone.lw.cmd.player.msgs.*;
 import com.deepclone.lw.session.Command;
 import com.deepclone.lw.session.SessionException;
@@ -73,7 +74,7 @@ public class PlayerSession
 	}
 
 
-	/* Empire commands */
+	/* Overview */
 
 	public EmpireResponse getOverview( )
 			throws SessionException , SessionServerException , SessionMaintenanceException
@@ -82,54 +83,26 @@ public class PlayerSession
 	}
 
 
-	/**
-	 * Request research information
-	 * 
-	 * @return the research information response
-	 */
-	public GetResearchResponse getResearch( )
+	/* Technologies */
+
+	public ViewResearchResponse viewResearch( )
 			throws SessionException , SessionServerException , SessionMaintenanceException
 	{
-		return (GetResearchResponse) this.execute( new GetResearchCommand( ) );
+		return (ViewResearchResponse) this.execute( new ViewResearchCommand( ) );
 	}
 
 
-	/**
-	 * Update research priorities
-	 * 
-	 * @param priorities
-	 *            the map of research identifiers to priority values
-	 */
-	public void updateResearchPriorities( Map< String , Integer > priorities )
+	public ResearchOperationResponse implementTechnology( String technology )
 			throws SessionException , SessionServerException , SessionMaintenanceException
 	{
-		this.execute( new UpdateResearchPrioritiesCommand( priorities ) );
+		return (ResearchOperationResponse) this.execute( new ImplementTechCommand( technology ) );
 	}
 
 
-	/**
-	 * Implement a technology
-	 * 
-	 * @param technology
-	 *            the technology's identifier
-	 */
-	public void implementTechnology( String technology )
+	public ResearchOperationResponse setResearchPriorities( Map< String , Integer > priorities )
 			throws SessionException , SessionServerException , SessionMaintenanceException
 	{
-		this.execute( new ImplementTechCommand( technology ) );
-	}
-
-
-	/**
-	 * Send an {@link UpdateEmpireMiningSettingsCommand} to the server
-	 * 
-	 * @param miningSettings
-	 *            the mining settings
-	 */
-	public void updateEmpireMiningSettings( Map< String , Integer > miningSettings )
-			throws SessionException , SessionServerException , SessionMaintenanceException
-	{
-		this.execute( new UpdateEmpireMiningSettingsCommand( miningSettings ) );
+		return (ResearchOperationResponse) this.execute( new SetResearchPrioritiesCommand( priorities ) );
 	}
 
 
@@ -199,36 +172,6 @@ public class PlayerSession
 	}
 
 
-	/**
-	 * Send a {@link ToggleMiningSettingsCommand} to the server
-	 * 
-	 * @param pId
-	 *            the planet whose mining settings are to be switched between empire-wide and
-	 *            planet-specific
-	 */
-	public void toggleMiningSettingsFor( int pId )
-			throws SessionException , SessionServerException , SessionMaintenanceException
-	{
-		this.execute( new ToggleMiningSettingsCommand( pId ) );
-	}
-
-
-	/**
-	 * Send a {@link UpdatePlanetMiningSettingsCommand} to the server
-	 * 
-	 * @param pId
-	 *            the identifier of the planet to udpate
-	 * @param settings
-	 *            the map of settings, as associations between resource identifiers and priority
-	 *            values
-	 */
-	public void updatePlanetMiningSettings( int pId , Map< String , Integer > settings )
-			throws SessionException , SessionServerException , SessionMaintenanceException
-	{
-		this.execute( new UpdatePlanetMiningSettingsCommand( pId , settings ) );
-	}
-
-
 	public ViewPlanetResponse rename( int planetId , String name )
 			throws SessionException , SessionServerException , SessionMaintenanceException
 	{
@@ -653,5 +596,4 @@ public class PlayerSession
 	{
 		return (PostCommentResponse) this.execute( new PostCommentCommand( bugId , comment ) );
 	}
-
 }
diff --git a/legacyworlds-web/legacyworlds-web-main/.classpath b/legacyworlds-web/legacyworlds-web-main/.classpath
new file mode 100644
index 0000000..3f554db
--- /dev/null
+++ b/legacyworlds-web/legacyworlds-web-main/.classpath
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" output="target/classes" path="src/main/java"/>
+	<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources"/>
+	<classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
+	<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+	<classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER">
+		<attributes>
+			<attribute name="org.eclipse.jst.component.dependency" value="/WEB-INF/lib"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="con" path="org.eclipse.jst.server.core.container/org.eclipse.jst.server.tomcat.runtimeTarget/Apache Tomcat v6.0">
+		<attributes>
+			<attribute name="owner.project.facets" value="jst.web"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="con" path="org.eclipse.jst.j2ee.internal.web.container"/>
+	<classpathentry kind="con" path="org.eclipse.jst.j2ee.internal.module.container"/>
+	<classpathentry kind="output" path="target/classes"/>
+</classpath>
diff --git a/legacyworlds-web/legacyworlds-web-main/.project b/legacyworlds-web/legacyworlds-web-main/.project
new file mode 100644
index 0000000..348118f
--- /dev/null
+++ b/legacyworlds-web/legacyworlds-web-main/.project
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>legacyworlds-web-main</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.wst.jsdt.core.javascriptValidator</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.maven.ide.eclipse.maven2Builder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.wst.validation.validationbuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jem.workbench.JavaEMFNature</nature>
+		<nature>org.eclipse.wst.common.modulecore.ModuleCoreNature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.maven.ide.eclipse.maven2Nature</nature>
+		<nature>org.eclipse.wst.common.project.facet.core.nature</nature>
+		<nature>org.eclipse.wst.jsdt.core.jsNature</nature>
+	</natures>
+</projectDescription>
diff --git a/legacyworlds-web/legacyworlds-web-main/.settings/.jsdtscope b/legacyworlds-web/legacyworlds-web-main/.settings/.jsdtscope
new file mode 100644
index 0000000..bbb8e68
--- /dev/null
+++ b/legacyworlds-web/legacyworlds-web-main/.settings/.jsdtscope
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="con" path="org.eclipse.wst.jsdt.launching.JRE_CONTAINER"/>
+	<classpathentry kind="con" path="org.eclipse.wst.jsdt.launching.WebProject">
+		<attributes>
+			<attribute name="hide" value="true"/>
+		</attributes>
+	</classpathentry>
+	<classpathentry kind="con" path="org.eclipse.wst.jsdt.launching.baseBrowserLibrary"/>
+	<classpathentry kind="output" path=""/>
+</classpath>
diff --git a/legacyworlds-web/legacyworlds-web-main/.settings/org.eclipse.jdt.core.prefs b/legacyworlds-web/legacyworlds-web-main/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..30a3c16
--- /dev/null
+++ b/legacyworlds-web/legacyworlds-web-main/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,8 @@
+#Thu Apr 15 19:50:22 CEST 2010
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.source=1.6
diff --git a/legacyworlds-web/legacyworlds-web-main/.settings/org.eclipse.wst.common.component b/legacyworlds-web/legacyworlds-web-main/.settings/org.eclipse.wst.common.component
new file mode 100644
index 0000000..9c506c0
--- /dev/null
+++ b/legacyworlds-web/legacyworlds-web-main/.settings/org.eclipse.wst.common.component
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project-modules id="moduleCoreId" project-version="1.5.0">
+    <wb-module deploy-name="legacyworlds-web-main">
+        <wb-resource deploy-path="/" source-path="/WebContent"/>
+        <wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/java"/>
+        <wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/resources"/>
+        <wb-resource deploy-path="/WEB-INF/classes" source-path="/src/test/java"/>
+        <wb-resource deploy-path="/WEB-INF/classes" source-path="/src/test/resources"/>
+        <property name="context-root" value="legacyworlds-web-main"/>
+        <property name="java-output-path" value="/legacyworlds-web-main/target/classes"/>
+    </wb-module>
+</project-modules>
diff --git a/legacyworlds-web/legacyworlds-web-main/.settings/org.eclipse.wst.common.project.facet.core.xml b/legacyworlds-web/legacyworlds-web-main/.settings/org.eclipse.wst.common.project.facet.core.xml
new file mode 100644
index 0000000..9680654
--- /dev/null
+++ b/legacyworlds-web/legacyworlds-web-main/.settings/org.eclipse.wst.common.project.facet.core.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<faceted-project>
+  <runtime name="Apache Tomcat v6.0"/>
+  <installed facet="jst.java" version="6.0"/>
+  <installed facet="jst.web" version="2.4"/>
+</faceted-project>
diff --git a/legacyworlds-web/legacyworlds-web-main/.settings/org.eclipse.wst.jsdt.ui.superType.container b/legacyworlds-web/legacyworlds-web-main/.settings/org.eclipse.wst.jsdt.ui.superType.container
new file mode 100644
index 0000000..3bd5d0a
--- /dev/null
+++ b/legacyworlds-web/legacyworlds-web-main/.settings/org.eclipse.wst.jsdt.ui.superType.container
@@ -0,0 +1 @@
+org.eclipse.wst.jsdt.launching.baseBrowserLibrary
\ No newline at end of file
diff --git a/legacyworlds-web/legacyworlds-web-main/.settings/org.eclipse.wst.jsdt.ui.superType.name b/legacyworlds-web/legacyworlds-web-main/.settings/org.eclipse.wst.jsdt.ui.superType.name
new file mode 100644
index 0000000..05bd71b
--- /dev/null
+++ b/legacyworlds-web/legacyworlds-web-main/.settings/org.eclipse.wst.jsdt.ui.superType.name
@@ -0,0 +1 @@
+Window
\ No newline at end of file
diff --git a/legacyworlds-web/legacyworlds-web-main/.settings/org.maven.ide.eclipse.prefs b/legacyworlds-web/legacyworlds-web-main/.settings/org.maven.ide.eclipse.prefs
new file mode 100644
index 0000000..a40fb0f
--- /dev/null
+++ b/legacyworlds-web/legacyworlds-web-main/.settings/org.maven.ide.eclipse.prefs
@@ -0,0 +1,9 @@
+#Thu Apr 15 18:52:28 CEST 2010
+activeProfiles=
+eclipse.preferences.version=1
+fullBuildGoals=process-test-resources
+includeModules=false
+resolveWorkspaceProjects=true
+resourceFilterGoals=process-resources resources\:testResources
+skipCompilerPlugin=true
+version=1
diff --git a/legacyworlds-web-main/Content/Raw/META-INF/MANIFEST.MF b/legacyworlds-web/legacyworlds-web-main/WebContent/META-INF/MANIFEST.MF
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/META-INF/MANIFEST.MF
rename to legacyworlds-web/legacyworlds-web-main/WebContent/META-INF/MANIFEST.MF
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/ROOT.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/ROOT.ftl
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/ROOT.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/ROOT.ftl
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/containers/chat.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/containers/chat.ftl
similarity index 51%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/containers/chat.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/containers/chat.ftl
index 18eb983..28deee5 100644
--- a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/containers/chat.ftl
+++ b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/containers/chat.ftl
@@ -6,29 +6,22 @@
 	<head>
 		<title>Legacy Worlds Beta 6 <@version/> - ${title?xhtml}</title>
 		<link rel="stylesheet" type="text/css" href="css/main.css" />
-		<script type="text/javascript" charset="utf-8" src="js/jquery-1.7.1.min.js"></script>
+		<script type="text/javascript" charset="utf-8" src="js/jquery-1.4.2.min.js"></script>
 		<script type="text/javascript" charset="utf-8" src="js/main.js"></script>
 	</head>
 	<body>
-		<!-- Header -->
-		<div id="hd-top">
-			<div id="hd-logo">
-				<a href="#" title="Legacy Worlds home page"><span>Legacy Worlds Beta 6 <@version/></span></a>
-			</div>
-			<div id="hd-bar">
-				<div id="hd-summary" />
-				<div id="hd-page">
-					<h1>${title?xhtml}</h1>
+		<div id="extframe">
+			<div class="internal" id="intframe">
+				<!-- Title and planet list -->
+				<div class="top-centered">
+					<p style="padding: 22px 0px 0px 0px" id="tc-title">${title?xhtml}</p>
 				</div>
+				
+				<div class="cframe full-width"><#nested></div>
+			</div>
+			<div class="internal" id="footer">
+				Copyright (C) 2004-2010, <a title="DeepClone Development" href="http://www.deepclone.com">DeepClone Development</a>
 			</div>
-			<div id="hd-text">current version: <@full_version/></div>
-		</div>
-
-		<div id="page-contents" class="chat-page"><#nested></div>
-
-		<div id="footer">
-			Copyright (C) 2004-2012,
-			<a title="DeepClone Development" href="http://www.deepclone.com">DeepClone Development</a>
 		</div>
 	</body>
 </html>
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/containers/external.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/containers/external.ftl
similarity index 51%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/containers/external.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/containers/external.ftl
index 011f210..5f9e1ef 100644
--- a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/containers/external.ftl
+++ b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/containers/external.ftl
@@ -5,19 +5,19 @@
 	<head>
 		<title>Legacy Worlds Beta 6 <@version/> - ${title?xhtml}</title>
 		<link rel="stylesheet" type="text/css" href="css/main.css" />
-		<script type="text/javascript" charset="utf-8" src="js/jquery-1.7.1.min.js"></script>
+		<script type="text/javascript" charset="utf-8" src="js/jquery-1.4.2.min.js"></script>
 		<script type="text/javascript" charset="utf-8" src="js/main.js"></script>
 	</head>
 	<body>
-		<!-- Header -->
-		<div id="hd-top">
-			<div id="hd-logo">
-				<a href="home" title="Legacy Worlds home page"><span>Legacy Worlds Beta 6 <@version/></span></a>
-			</div>
-			
-			<!-- Title / login bar -->
-			<div id="hd-bar">
-				<div id="hd-summary">
+		<div id="extframe">
+			<div class="internal" id="intframe">
+				<!-- Header -->
+				<a id="hbutton" href="home" title="Legacy Worlds home page"><span>Legacy Worlds Beta 6 <@version/></span></a>
+				<div id="version">current version: <@full_version/></div>
+				<div class="top-centered" id="tc-title">${title?xhtml}</div>
+
+				<!-- Log-in box -->
+				<div id="lbox">
 					<form method="post" action="login.action">
 						<div>
 							E-mail address: <input type="text" name="mail" value="" size="15" maxlength="128" class='input' /><br/>
@@ -27,34 +27,17 @@
 						</div>
 					</form>
 				</div>
-				<div id="hd-page">
-					<h1>${title?xhtml}</h1>
-				</div>
-			</div>
-			<div id="hd-text">current version: <@full_version/></div>
-		</div>
 
-		<!-- Menu
-		   -
-		   - FIXME: set "current" style on button for the current page
-		  -->
-		<div id="menu-left">
-			<div class="button">
-				<a href="scope" title="Scope of this milestone">Scope</a>
-			</div>
-			<div class="button">
-				<a href="rules" title="Game rules">Rules</a>
-			</div>
-			<div class="button">
-				<a href="register" title="Register">Register</a>
-			</div>
-		</div>
+				<!-- Menu -->
+				<a class="mbutton" id="b0" href="scope" title="Scope of this milestone">Scope</a>
+				<a class="mbutton" id="b1" href="rules" title="Game rules">Rules</a>
+				<a class="mbutton" id="b2" href="register" title="Register">Register</a>
 
-		<div id="page-contents"><#nested></div>
-
-		<div id="footer">
-			Copyright (C) 2004-2012,
-			<a title="DeepClone Development" href="http://www.deepclone.com">DeepClone Development</a>
+				<div class="cframe"><#nested></div>
+			</div>
+			<div class="internal" id="footer">
+				Copyright (C) 2004-2010, <a title="DeepClone Development" href="http://www.deepclone.com">DeepClone Development</a>
+			</div>
 		</div>
 	</body>
 </html>
diff --git a/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/containers/game.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/containers/game.ftl
new file mode 100644
index 0000000..3d07f3f
--- /dev/null
+++ b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/containers/game.ftl
@@ -0,0 +1,70 @@
+<#include "../game.ftl">
+<#macro page title hidePlanets=false>
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
+	<head>
+		<title>Legacy Worlds Beta 6 <@version/> - ${title?xhtml}</title>
+		<link rel="stylesheet" type="text/css" href="css/main.css" />
+		<script type="text/javascript" charset="utf-8" src="js/jquery-1.4.2.min.js"></script>
+		<script type="text/javascript" charset="utf-8" src="js/main.js"></script>
+	</head>
+	<body>
+		<div id="extframe">
+			<div class="internal" id="intframe">
+				<a id="hbutton" href="overview" title="Overview page"><span>Legacy Worlds Beta 6 <@version/></span></a>
+				<div id="version"><@abbr_gt/>: <@game_time record=data.page.gameTime /> / <@abbr_st/>: ${data.page.serverTime?string("yyyy-MM-dd HH:mm:ss ZZZZZ")}</div>
+				
+				<!-- Title and planet list -->
+				<div class="top-centered">
+					<p id="tc-title">${title?xhtml}</p>
+					<p>&nbsp;</p>
+					<#if !hidePlanets>
+						<#if data.page.planets?size == 0>
+							<p id="get-new-planet"><a href="get-planet">Get new planet</a></p>
+						<#else>
+							<p id="jump-to-planet"><span class="jtp-text">Jump to planet</span>: <span>
+								<#list data.page.planets as planet>
+									<a href="planet-${planet.id}">${planet.name?xhtml}</a>
+								</#list>
+							</span></p> 
+						</#if>
+					</#if>
+				</div>
+				
+				<div id="lbox" class="game-info">
+					<strong>${data.page.empire}</strong>
+					<#if data.page.alliance?has_content>
+						[<strong>${data.page.alliance}</strong>]
+					</#if><br/>
+					<span id="gi-cash">${data.page.cash?string(",##0")}</span> <@abbr_bgc/><br/>
+					<#if data.page.special?has_content>
+						<span class="special-info">
+							<#switch data.page.special>
+								<#case 'v'>ON VACATION<#break>
+								<#case 's'>ENTERING VACATION<#break>
+								<#case 'q'>QUITTING<#break>
+							</#switch>
+						</span>
+					</#if>
+					<br/>
+					<a href="account">Account</a> - <a href="logout.action">Log out</a>
+				</div>
+
+				<a class="mbutton" id="b0" href="planets" title="Planets">Planets</a>
+				<a class="mbutton" id="b1" href="fleets" title="Fleets">Fleets</a>
+				<a class="mbutton" id="b2" href="map" title="Map of the universe">Map</a>
+				<a class="mbutton" id="b3" href="alliance" title="Alliance">Alliance</a>
+				<a class="mbutton" id="b4" href="enemies" title="Manage enemy players and alliances">Enemy list</a>
+				<a class="mbutton" id="b5" href="messages" title="Messages">Messages</a>
+				<a class="mbutton" id="b6" href="bugtrack" title="Bug tracking application">Bug tracker</a>
+
+				<div class="cframe"><#nested></div>
+			</div>
+			<div class="internal" id="footer">
+				Copyright (C) 2004-2010, <a title="DeepClone Development" href="http://www.deepclone.com">DeepClone Development</a>
+			</div>
+		</div>
+	</body>
+</html>
+</#macro>
\ No newline at end of file
diff --git a/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/containers/offline.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/containers/offline.ftl
new file mode 100644
index 0000000..37af005
--- /dev/null
+++ b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/containers/offline.ftl
@@ -0,0 +1,27 @@
+<#macro page title>
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
+	<head>
+		<title>Legacy Worlds Beta 6 <@version/> - ${title?xhtml}</title>
+		<link rel="stylesheet" type="text/css" href="css/main.css" />
+		<script type="text/javascript" charset="utf-8" src="js/jquery-1.4.2.min.js"></script>
+		<script type="text/javascript" charset="utf-8" src="js/main.js"></script>
+	</head>
+	<body>
+		<div id="extframe">
+			<div class="internal" id="intframe">
+				<!-- Header -->
+				<a id="hbutton" href="player-session" title="Legacy Worlds home page"><span>Legacy Worlds Beta 6 <@version/></span></a>
+				<div id="version">current version: <@full_version/></div>
+				<div class="top-centered" id="tc-title">${title?xhtml}</div>
+
+				<div class="cframe full-width offline"><#nested></div>
+			</div>
+			<div class="internal" id="footer">
+				Copyright (C) 2004-2010, <a title="DeepClone Development" href="http://www.deepclone.com">DeepClone Development</a>
+			</div>
+		</div>
+	</body>
+</html>
+</#macro>
\ No newline at end of file
diff --git a/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/containers/restricted.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/containers/restricted.ftl
new file mode 100644
index 0000000..6f5efb8
--- /dev/null
+++ b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/containers/restricted.ftl
@@ -0,0 +1,33 @@
+<#macro page title>
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
+	<head>
+		<title>Legacy Worlds Beta 6 <@version/> - ${title?xhtml}</title>
+		<link rel="stylesheet" type="text/css" href="css/main.css" />
+		<script type="text/javascript" charset="utf-8" src="js/jquery-1.4.2.min.js"></script>
+		<script type="text/javascript" charset="utf-8" src="js/main.js"></script>
+	</head>
+	<body>
+		<div id="extframe">
+			<div class="internal" id="intframe">
+				<!-- Header -->
+				<a id="hbutton" href="home" title="Legacy Worlds home page"><span>Legacy Worlds Beta 6 <@version/></span></a>
+				<div id="version">current version: <@full_version/></div>
+				<div class="top-centered" id="tc-title">${title?xhtml}</div>
+
+				<!-- Log-in box -->
+				<div id="lbox">
+					<br/><br/><br/>
+					<a href="logout.action">Log out</a>
+				</div>
+
+				<div class="cframe full-width"><#nested></div>
+			</div>
+			<div class="internal" id="footer">
+				Copyright (C) 2004-2010, <a title="DeepClone Development" href="http://www.deepclone.com">DeepClone Development</a>
+			</div>
+		</div>
+	</body>
+</html>
+</#macro>
\ No newline at end of file
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/game.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/game.ftl
similarity index 92%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/game.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/game.ftl
index 122c93a..f9518eb 100644
--- a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/game.ftl
+++ b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/game.ftl
@@ -63,11 +63,4 @@
 </#macro>
 <#macro abbr_bgc><abbr title="billion galactic credits">bgc</abbr></#macro>
 <#macro abbr_st><abbr title="Server time">ST</abbr></#macro>
-<#macro abbr_gt><abbr title="Time in the game universe">GT</abbr></#macro>
-<#macro over_time title>
-	<#if data.page.useRLTime>
-		${title?xhtml} (for 12h)
-	<#else>
-		Monthly ${title?xhtml}
-	</#if>
-</#macro>
\ No newline at end of file
+<#macro abbr_gt><abbr title="Time in the game universe">GT</abbr></#macro>
\ No newline at end of file
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/static/home.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/static/home.ftl
similarity index 94%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/static/home.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/static/home.ftl
index a9dedfb..cc4a22b 100644
--- a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/static/home.ftl
+++ b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/static/home.ftl
@@ -1,4 +1,4 @@
-<@page title="Legacy Worlds Beta 6 - Milestone 1">
+<@page title="Legacy Worlds Beta 6 - Milestone 2">
 	<p>
 		Welcome to the first milestone release for Legacy Worlds' Beta 6.
 	</p>
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/static/loggedOut.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/static/loggedOut.ftl
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/static/loggedOut.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/static/loggedOut.ftl
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/static/loginFailed.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/static/loginFailed.ftl
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/static/loginFailed.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/static/loginFailed.ftl
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/static/noSession.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/static/noSession.ftl
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/static/noSession.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/static/noSession.ftl
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/static/passwordRecoveryOk.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/static/passwordRecoveryOk.ftl
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/static/passwordRecoveryOk.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/static/passwordRecoveryOk.ftl
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/static/reactivate.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/static/reactivate.ftl
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/static/reactivate.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/static/reactivate.ftl
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/static/rules.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/static/rules.ftl
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/static/rules.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/static/rules.ftl
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/static/scope.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/static/scope.ftl
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/static/scope.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/static/scope.ftl
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/account.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/types/account.ftl
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/account.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/types/account.ftl
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/alliance.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/types/alliance.ftl
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/alliance.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/types/alliance.ftl
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/banned.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/types/banned.ftl
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/banned.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/types/banned.ftl
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/battle.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/types/battle.ftl
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/battle.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/types/battle.ftl
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/battles.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/types/battles.ftl
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/battles.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/types/battles.ftl
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/bugsList.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/types/bugsList.ftl
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/bugsList.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/types/bugsList.ftl
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/bugsReport.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/types/bugsReport.ftl
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/bugsReport.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/types/bugsReport.ftl
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/bugsTabs.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/types/bugsTabs.ftl
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/bugsTabs.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/types/bugsTabs.ftl
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/bugsView.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/types/bugsView.ftl
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/bugsView.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/types/bugsView.ftl
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/chat.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/types/chat.ftl
similarity index 95%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/chat.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/types/chat.ftl
index 8bbd44a..f62c595 100644
--- a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/chat.ftl
+++ b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/types/chat.ftl
@@ -1,6 +1,6 @@
 <#macro render>
 <@page title="Legacy Worlds chat">
-	<applet code="IRCApplet.class" archive="irc.jar,pixx.jar" codebase="pjirc" width="100%" height="400px">
+	<applet code="IRCApplet.class" archive="irc.jar,pixx.jar" codebase="pjirc" width="100%" height="100%">
 		<param name="CABINETS" value="irc.cab,securedirc.cab,pixx.cab" />
 		<param name="nick" value="${(data.page.empire?replace(' ' , '_'))?xhtml}" />
 		<param name="alternatenick" value="LW-Player-???" />
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/enemies.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/types/enemies.ftl
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/enemies.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/types/enemies.ftl
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/fleets.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/types/fleets.ftl
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/fleets.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/types/fleets.ftl
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/fleetsCommand.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/types/fleetsCommand.ftl
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/fleetsCommand.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/types/fleetsCommand.ftl
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/getNewPlanet.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/types/getNewPlanet.ftl
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/getNewPlanet.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/types/getNewPlanet.ftl
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/maintenance.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/types/maintenance.ftl
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/maintenance.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/types/maintenance.ftl
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/map.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/types/map.ftl
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/map.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/types/map.ftl
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/message.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/types/message.ftl
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/message.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/types/message.ftl
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/messageBox.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/types/messageBox.ftl
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/messageBox.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/types/messageBox.ftl
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/messageTabs.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/types/messageTabs.ftl
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/messageTabs.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/types/messageTabs.ftl
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/messageTargets.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/types/messageTargets.ftl
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/messageTargets.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/types/messageTargets.ftl
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/messageWriter.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/types/messageWriter.ftl
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/messageWriter.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/types/messageWriter.ftl
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/offline.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/types/offline.ftl
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/offline.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/types/offline.ftl
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/overview.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/types/overview.ftl
similarity index 94%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/overview.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/types/overview.ftl
index b0a711d..b923794 100644
--- a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/overview.ftl
+++ b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/types/overview.ftl
@@ -61,11 +61,6 @@
 			</@right_column>
 		</@tab>
 
-		<@tab id="economy" title="Economy">
-			<#include "overview/resources.ftl" />
-			<@overviewResources />
-		</@tab>
-
 	</@tabs>
 
 </@page>
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/passwordRecovery.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/types/passwordRecovery.ftl
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/passwordRecovery.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/types/passwordRecovery.ftl
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/planet.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/types/planet.ftl
similarity index 87%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/planet.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/types/planet.ftl
index e6b735c..f32d709 100644
--- a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/planet.ftl
+++ b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/types/planet.ftl
@@ -108,55 +108,6 @@
 			</#if>
 
 		</@tab>
-
-		<#if data.own?has_content && data.own.resources?size gt 0>
-		
-			<@tab id="resources" title="Economy">
-			
-				<@listview>
-					<#local previousCategory="">
-
-					<@lv_line headers=true>
-						<@lv_column width=30>&nbsp;</@lv_column>
-						<@lv_column width="x">Resource</@lv_column>
-						<@lv_column width=100 centered=true><@over_time "Income" /></@lv_column>
-						<@lv_column width=100 centered=true><@over_time "Upkeep" /></@lv_column>
-						<@lv_column width=100 centered=true>Invested</@lv_column>
-					</@lv_line>
-					
-					<#list data.own.resources as resource>
-
-						<#if previousCategory?has_content && !resource.category?has_content
-								|| resource.category?has_content && !previousCategory?has_content
-								|| resource.category?has_content && previousCategory?has_content
-									&& resource.category != previousCategory>
-							<@lv_line>
-								<#if resource.category?has_content>
-									<td colspan="5"><strong>${resource.category?xhtml}</strong></td>
-								<#else>
-									<td colspan="5"><hr /></td>
-								</#if>
-							</@lv_line>
-							<#local previousCategory=resource.category>
-						</#if>
-						
-						<@lv_line>
-							<@lv_column>&nbsp;</@lv_column>
-							<@lv_column>${resource.title?xhtml}
-								<div class="auto-hide">${resource.description?xhtml}</div>
-							</@lv_column>
-							<@lv_column centered=true>${resource.income?string(",##0")}</@lv_column>
-							<@lv_column centered=true>${resource.upkeep?string(",##0")}</@lv_column>
-							<@lv_column centered=true>${resource.invested?string(",##0")}</@lv_column>
-						</@lv_line>
-
-					</#list>
-
-				</@listview>
-			
-			</@tab>
-
-		</#if>
 	
 		<#if data.orbit?has_content>
 		
@@ -192,7 +143,6 @@
 												<#case "DEF">defence<#break>
 												<#case "WORK">mil. output<#break>
 												<#case "POP">growth<#break>
-												<#case "MINE">res. extraction<#break>
 											</#switch>
 										</@lv_column>
 										<@lv_column centered=true>${building.jobs?string(",##0")}</@lv_column>
@@ -239,7 +189,6 @@
 														<#case "DEF">defence<#break>
 														<#case "WORK">mil. output<#break>
 														<#case "POP">growth<#break>
-														<#case "MINE">res. extraction<#break>
 													</#switch>
 												</@dt_entry>
 											</@dt_main>
@@ -302,7 +251,6 @@
 			</#if>
 
 			<#if data.own?has_content>
-
 				<@tab id="ships" title="Shipyards">
 					<#if data.page.special! != 'v'>
 						<#if data.own.milQueue.appendPossible>
@@ -373,13 +321,9 @@
 						</@listview>
 					</#if>
 				</@tab>
-
 			</#if>
-			
-			<#include "planet/natres.ftl" />
-			<@RenderNaturalResources />
 		</#if>
-		
+
 	</@tabs>
 </@page>
 </#macro>
\ No newline at end of file
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/planets.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/types/planets.ftl
similarity index 98%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/planets.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/types/planets.ftl
index c8bc9cb..0321889 100644
--- a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/planets.ftl
+++ b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/types/planets.ftl
@@ -28,7 +28,7 @@
 				</@listview>
 			</@tab>
 
-			<@tab id="eco" title="Economy (OLD)"> 
+			<@tab id="eco" title="Economy"> 
 				<@listview>
 					<@lv_line headers=true>
 						<@lv_column width="x">Name</@lv_column>
@@ -56,9 +56,6 @@
 				</@listview>
 			</@tab>
 
-			<#include "planets/economy.ftl" />
-			<@RenderEconomy />
-
 			<@tab id="prod" title="Production"> 
 				<@listview>
 					<@lv_line headers=true>
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/reactivation.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/types/reactivation.ftl
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/reactivation.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/types/reactivation.ftl
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/register.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/types/register.ftl
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/register.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/types/register.ftl
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/registered.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/types/registered.ftl
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/registered.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/types/registered.ftl
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/splitFleet.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/types/splitFleet.ftl
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/splitFleet.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/types/splitFleet.ftl
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/static.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/types/static.ftl
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/static.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/types/static.ftl
diff --git a/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/types/technologies.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/types/technologies.ftl
new file mode 100644
index 0000000..954dfe8
--- /dev/null
+++ b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/types/technologies.ftl
@@ -0,0 +1,171 @@
+<#macro render_entry identifier title category description>
+	<div class="research-entry" id="research-${identifier?xhtml}">
+		<div class="title">${title?xhtml}</div>
+		<div class="category">Category: <b>${category?xhtml}</b></div>
+		<div class="description">${description?xhtml}</div>
+		<#nested>
+	</div>
+</#macro>
+<#macro render_implementable entry>
+	<@render_entry entry.identifier entry.name entry.category entry.description>
+		<div class="cost">Cost: <b>${entry.cost?string(",##0")}</b> <@abbr_bgc/></div>
+		<#if data.page.cash &gt;= entry.cost>
+			<form class="implement" name="implement-${entry.identifier?xhtml}" action="implement-tech.action" method="POST">
+				<input type="hidden" name="technology" value="${entry.identifier?xhtml}" />
+				<input type="submit" class="input" value="Implement technology" />
+			</form>
+		</#if> 
+	</@render_entry>
+</#macro>
+<#macro render_research entry title description display_priority_form>
+	<@render_entry entry.identifier title entry.category description>
+		<div class="progress">Progress: <span class="progress">${entry.completion}%</span></div>
+		<#if display_priority_form>
+			<div class="priority">
+				Priority:
+				<span class="priority">
+					<input type="text" maxlength="3" size="4" class="input priority-field" name="priority-${entry.identifier?xhtml}" id="priority-${entry.identifier?xhtml}" value="${entry.priority}" />%
+				</span> 
+			</div>
+		</#if>
+	</@render_entry>
+</#macro>
+<#macro render_unidentified entry display_priority_form>
+	<@render_research entry "Unidentified technology" "Our researchers are working on something new, but they have no clue where it will lead at this time." display_priority_form />
+</#macro>
+<#macro render_research_list entries>
+	<#local priority_form_started = false>
+	<#local priority_form_checked = false>
+	<#local display_priority_form = false>
+	<#local counter = 0>
+	<#-- List of in-progress research topics as well as implementable technologies -->
+	<#list entries as entry>
+		<#if entry.cost?has_content>
+			<#-- Technology that can be implemented -->
+			<#local counter = counter + 1>
+			<@render_implementable entry />
+		<#else>
+			<#if ! priority_form_checked>
+				<#-- Check whether we need to display the priority form -->
+				<#if entries?size - counter &gt; 1>
+					<#local display_priority_form = true>
+				</#if>
+				<#local priority_form_checked = true>
+			</#if>
+			<#-- Start of the research priority form, if necessary -->
+			<#if display_priority_form && ! priority_form_started>
+				<#local priority_form_started = true>
+				<form name="priority" action="set-research-priority.action" method="POST">
+			</#if>
+			<#if entry.name?has_content>
+				<#-- Identified technology being researched -->
+				<@render_research entry entry.name entry.description display_priority_form />
+			<#else>
+				<#-- Unidentified technology -->
+				<@render_unidentified entry display_priority_form />
+			</#if>
+		</#if>
+	</#list>
+	<#-- End of the research priority form, if necessary -->
+	<#if priority_form_started>
+			<div class="submit-priorities">
+				<input type="submit" class="input" value="Update research priorities" />
+			</div>
+		</form>
+	</#if>
+</#macro>
+<#macro find_tech_name id lists>
+	<#local found=false>
+	<#list lists as cat>
+		<#list cat.technologies as tech>
+			<#if tech.identifier == id><#local found=true>${tech.name?xhtml}<#break></#if>
+		</#list>
+		<#if found><#break></#if>
+	</#list>
+</#macro>
+<#macro render_tech_dependencies deps fullLists>
+	<ul>
+		<#list deps as dependency>
+			<li><a href="#tech-${dependency?xhtml}"><@find_tech_name dependency fullLists /></a></li>
+		</#list>
+	</ul>
+</#macro>
+<#macro render_technology tech fullList>
+	<div class="technology" id="tech-${tech.identifier?xhtml}">
+		<div class="title">${tech.name?xhtml}</div>
+		<div class="description">
+			<p>${tech.description?xhtml}</p>
+		</div>
+		
+		<#if tech.dependsOn?size != 0>
+			<div class="dependencies">
+				<b>Depends on:</b>
+				<@render_tech_dependencies tech.dependsOn fullList />
+			</div>
+		</#if>
+		
+		<#if tech.dependencyOf?size != 0>
+			<div class="rev-deps">
+				<b>Required by:</b>
+				<@render_tech_dependencies tech.dependencyOf fullList />
+			</div>
+		</#if>
+
+	</div>
+</#macro>
+<#macro render_tech_list categories>
+	<#-- List categories -->
+	<#list categories as category>
+		<div class="tech-category">
+			<h2>${category.name?xhtml}</h2>
+			<p>${category.description?xhtml}</p>
+			<#-- List technologies in the category -->
+			<#list category.technologies as technology>
+				<@render_technology technology categories />
+			</#list>
+		</div>
+	</#list>
+</#macro>
+<#macro render>
+<@page title="Technologies">
+
+	<#if data.research?size == 0 && data.implementedTechnologies?size == 0>
+		<p>Our scientists are still settling in, please come back in a little while...</p>
+		<#return>
+	</#if>
+	
+	<@tabs>
+	
+		<#if data.research?size != 0>
+			<@tab id="research" title="Research">
+				<#if data.result?exists>
+					<#switch data.result>
+						<#case "ERR_RESOURCES">
+							<@standalone_error>We do not possess the necessary resources anymore.</@standalone_error>
+							<#break>
+						<#case "ERR_STATE_CHANGED">
+							<@standalone_error>Something changed... Please try again.</@standalone_error>
+							<#break>
+						<#case "ERR_INVALID">
+							<@standalone_error>Invalid priorities.</@standalone_error>
+							<#break>
+						<#default>
+							<#-- Ignore other error codes -->
+							<#break>
+					</#switch>
+				</#if>
+				<#-- Render the list -->
+				<@render_research_list data.research />
+			</@tab>
+		</#if>
+
+		<#if data.implementedTechnologies?size != 0>
+			<@tab id="implemented" title="Implemented technologies">
+				<@render_tech_list data.implementedTechnologies />
+			</@tab>
+		</#if>
+
+	</@tabs>
+
+</@page>
+</#macro>
\ No newline at end of file
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/validation.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/types/validation.ftl
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/validation.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/en/types/validation.ftl
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/containers/chat.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/containers/chat.ftl
similarity index 51%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/containers/chat.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/containers/chat.ftl
index 48a47f3..28deee5 100644
--- a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/containers/chat.ftl
+++ b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/containers/chat.ftl
@@ -6,29 +6,22 @@
 	<head>
 		<title>Legacy Worlds Beta 6 <@version/> - ${title?xhtml}</title>
 		<link rel="stylesheet" type="text/css" href="css/main.css" />
-		<script type="text/javascript" charset="utf-8" src="js/jquery-1.7.1.min.js"></script>
+		<script type="text/javascript" charset="utf-8" src="js/jquery-1.4.2.min.js"></script>
 		<script type="text/javascript" charset="utf-8" src="js/main.js"></script>
 	</head>
 	<body>
-		<!-- Header -->
-		<div id="hd-top">
-			<div id="hd-logo">
-				<a href="#" title="Page d'accueil de Legacy Worlds"><span>Legacy Worlds Beta 6 <@version/></span></a>
-			</div>
-			<div id="hd-bar">
-				<div id="hd-summary" />
-				<div id="hd-page">
-					<h1>${title?xhtml}</h1>
+		<div id="extframe">
+			<div class="internal" id="intframe">
+				<!-- Title and planet list -->
+				<div class="top-centered">
+					<p style="padding: 22px 0px 0px 0px" id="tc-title">${title?xhtml}</p>
 				</div>
+				
+				<div class="cframe full-width"><#nested></div>
+			</div>
+			<div class="internal" id="footer">
+				Copyright (C) 2004-2010, <a title="DeepClone Development" href="http://www.deepclone.com">DeepClone Development</a>
 			</div>
-			<div id="hd-text">version courante : <@full_version/></div>
-		</div>
-
-		<div id="page-contents" class="chat-page"><#nested></div>
-
-		<div id="footer">
-			Copyright (C) 2004-2012,
-			<a title="DeepClone Development" href="http://www.deepclone.com">DeepClone Development</a>
 		</div>
 	</body>
 </html>
diff --git a/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/containers/external.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/containers/external.ftl
new file mode 100644
index 0000000..040e9d7
--- /dev/null
+++ b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/containers/external.ftl
@@ -0,0 +1,44 @@
+<#macro page title>
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
+	<head>
+		<title>Legacy Worlds Beta 6 <@version/> - ${title?xhtml}</title>
+		<link rel="stylesheet" type="text/css" href="css/main.css" />
+		<script type="text/javascript" charset="utf-8" src="js/jquery-1.4.2.min.js"></script>
+		<script type="text/javascript" charset="utf-8" src="js/main.js"></script>
+	</head>
+	<body>
+		<div id="extframe">
+			<div class="internal" id="intframe">
+				<!-- Header -->
+				<a id="hbutton" href="home" title="Page d'accueil de Legacy Worlds"><span>Legacy Worlds Beta 6 <@version/></span></a>
+				<div id="version">version courante : <@full_version/></div>
+				<div class="top-centered" id="tc-title">${title?xhtml}</div>
+
+				<!-- Log-in box -->
+				<div id="lbox">
+					<form method="post" action="login.action">
+						<div>
+							Adresse e-mail : <input type="text" name="mail" value="" size="15" maxlength="128" class='input' /><br/>
+							Mot de passe : <input type="password" name="password" value='' size="15" maxlength="128" class='input' /><br/>
+							<a title="Récupération de mot de passe" href="password-recovery">Mot de passe oublié ?</a>
+							<input type="submit" value='Connexion' class='input' />
+						</div>
+					</form>
+				</div>
+
+				<!-- Menu -->
+				<a class="mbutton" id="b0" href="scope" title="Portée de ce jalon">Portée</a>
+				<a class="mbutton" id="b1" href="rules" title="Règles du jeu">Règles</a>
+				<a class="mbutton" id="b2" href="register" title="Inscription">Inscription</a>
+
+				<div class="cframe"><#nested></div>
+			</div>
+			<div class="internal" id="footer">
+				Copyright (C) 2004-2010, <a title="DeepClone Development" href="http://www.deepclone.com">DeepClone Development</a>
+			</div>
+		</div>
+	</body>
+</html>
+</#macro>
\ No newline at end of file
diff --git a/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/containers/game.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/containers/game.ftl
new file mode 100644
index 0000000..2f8e922
--- /dev/null
+++ b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/containers/game.ftl
@@ -0,0 +1,70 @@
+<#include "../game.ftl">
+<#macro page title hidePlanets=false>
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
+	<head>
+		<title>Legacy Worlds Beta 6 <@version/> - ${title?xhtml}</title>
+		<link rel="stylesheet" type="text/css" href="css/main.css" />
+		<script type="text/javascript" charset="utf-8" src="js/jquery-1.4.2.min.js"></script>
+		<script type="text/javascript" charset="utf-8" src="js/main.js"></script>
+	</head>
+	<body>
+		<div id="extframe">
+			<div class="internal" id="intframe">
+				<a id="hbutton" href="overview" title="Page Empire"><span>Legacy Worlds Beta 6 <@version/></span></a>
+				<div id="version"><@abbr_gt/>: <@game_time record=data.page.gameTime /> / <@abbr_st/>: ${data.page.serverTime?string("yyyy-MM-dd HH:mm:ss ZZZZZ")}</div>
+				
+				<!-- Title and planet list -->
+				<div class="top-centered">
+					<p id="tc-title">${title?xhtml}</p>
+					<#if !hidePlanets>
+						<p>&nbsp;</p>
+						<#if data.page.planets?size == 0>
+							<p id="get-new-planet"><a href="get-planet">Obtenir une nouvelle planète</a></p>
+						<#else>
+							<p id="jump-to-planet"><span class="jtp-text">Aller à la planète</span>: <span>
+								<#list data.page.planets as planet>
+									<a href="planet-${planet.id}">${planet.name?xhtml}</a>
+								</#list>
+							</span></p> 
+						</#if>
+					</#if>
+				</div>
+				
+				<div id="lbox" class="game-info">
+					<strong>${data.page.empire}</strong>
+					<#if data.page.alliance?has_content>
+						[<strong>${data.page.alliance}</strong>]
+					</#if><br/>
+					<span id="gi-cash">${data.page.cash?string(",##0")}</span> <@abbr_bgc/><br/>
+					<#if data.page.special?has_content>
+						<span class="special-info">
+							<#switch data.page.special>
+								<#case 'v'>EN VACANCES<#break>
+								<#case 's'>PRELIMINAIRES AUX VACANCES<#break>
+								<#case 'q'>EN TRAIN D'ABANDONNER<#break>
+							</#switch>
+						</span>
+					</#if>
+					<br/>
+					<a href="account">Compte</a> - <a href="logout.action">Déconnexion</a>
+				</div>
+
+				<a class="mbutton" id="b0" href="planets" title="Planètes">Planètes</a>
+				<a class="mbutton" id="b1" href="fleets" title="Flottes">Flottes</a>
+				<a class="mbutton" id="b2" href="map" title="Carte de l'univers">Carte</a>
+				<a class="mbutton" id="b3" href="alliance" title="Alliance">Alliance</a>
+				<a class="mbutton" id="b4" href="enemies" title="Gèstion des listes de joueurs et alliances ennemis">Listes d'ennemis</a>
+				<a class="mbutton" id="b5" href="messages" title="Messages">Messages</a>
+				<a class="mbutton" id="b6" href="bugtrack" title="Application de suivi des bugs">Suivi des bugs</a>
+
+				<div class="cframe"><#nested></div>
+			</div>
+			<div class="internal" id="footer">
+				Copyright (C) 2004-2010, <a title="DeepClone Development" href="http://www.deepclone.com">DeepClone Development</a>
+			</div>
+		</div>
+	</body>
+</html>
+</#macro>
\ No newline at end of file
diff --git a/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/containers/offline.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/containers/offline.ftl
new file mode 100644
index 0000000..9261f58
--- /dev/null
+++ b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/containers/offline.ftl
@@ -0,0 +1,27 @@
+<#macro page title>
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
+	<head>
+		<title>Legacy Worlds Beta 6 <@version/> - ${title?xhtml}</title>
+		<link rel="stylesheet" type="text/css" href="css/main.css" />
+		<script type="text/javascript" charset="utf-8" src="js/jquery-1.4.2.min.js"></script>
+		<script type="text/javascript" charset="utf-8" src="js/main.js"></script>
+	</head>
+	<body>
+		<div id="extframe">
+			<div class="internal" id="intframe">
+				<!-- Header -->
+				<a id="hbutton" href="player-session" title="Page d'accueil de Legacy Worlds"><span>Legacy Worlds Beta 6 <@version/></span></a>
+				<div id="version">Version courante : <@full_version/></div>
+				<div class="top-centered" id="tc-title">${title?xhtml}</div>
+
+				<div class="cframe full-width offline"><#nested></div>
+			</div>
+			<div class="internal" id="footer">
+				Copyright (C) 2004-2010, <a title="DeepClone Development" href="http://www.deepclone.com">DeepClone Development</a>
+			</div>
+		</div>
+	</body>
+</html>
+</#macro>
\ No newline at end of file
diff --git a/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/containers/restricted.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/containers/restricted.ftl
new file mode 100644
index 0000000..7f1db1a
--- /dev/null
+++ b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/containers/restricted.ftl
@@ -0,0 +1,33 @@
+<#macro page title>
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
+	<head>
+		<title>Legacy Worlds Beta 6 <@version/> - ${title?xhtml}</title>
+		<link rel="stylesheet" type="text/css" href="css/main.css" />
+		<script type="text/javascript" charset="utf-8" src="js/jquery-1.4.2.min.js"></script>
+		<script type="text/javascript" charset="utf-8" src="js/main.js"></script>
+	</head>
+	<body>
+		<div id="extframe">
+			<div class="internal" id="intframe">
+				<!-- Header -->
+				<a id="hbutton" href="home" title="Page d'accueil de Legacy Worlds"><span>Legacy Worlds Beta 6 <@version/></span></a>
+				<div id="version">Version courante : <@full_version/></div>
+				<div class="top-centered" id="tc-title">${title?xhtml}</div>
+
+				<!-- Log-in box -->
+				<div id="lbox">
+					<br/><br/><br/>
+					<a href="logout.action">Déconnexion</a>
+				</div>
+
+				<div class="cframe full-width"><#nested></div>
+			</div>
+			<div class="internal" id="footer">
+				Copyright (C) 2004-2010, <a title="DeepClone Development" href="http://www.deepclone.com">DeepClone Development</a>
+			</div>
+		</div>
+	</body>
+</html>
+</#macro>
\ No newline at end of file
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/game.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/game.ftl
similarity index 89%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/game.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/game.ftl
index b0c8a1a..81e8aa9 100644
--- a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/game.ftl
+++ b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/game.ftl
@@ -63,11 +63,4 @@
 </#macro>
 <#macro abbr_bgc><abbr title="milliards de crédits galactiques">mcg</abbr></#macro>
 <#macro abbr_st><abbr title="Temps Serveur">TS </abbr></#macro>
-<#macro abbr_gt><abbr title="Temps dans l'univers du jeu">TJ </abbr></#macro>
-<#macro over_time title feminin=false pluriel=false>
-	<#if data.page.useRLTime>
-		${title?xhtml} (pour 12h)
-	<#else>
-		 ${title?xhtml} mensuel<#if feminin>le</#if><#if pluriel>s</#if>
-	</#if>
-</#macro>
\ No newline at end of file
+<#macro abbr_gt><abbr title="Temps dans l'univers du jeu">TJ </abbr></#macro>
\ No newline at end of file
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/static/home.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/static/home.ftl
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/static/home.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/static/home.ftl
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/static/loggedOut.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/static/loggedOut.ftl
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/static/loggedOut.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/static/loggedOut.ftl
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/static/loginFailed.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/static/loginFailed.ftl
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/static/loginFailed.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/static/loginFailed.ftl
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/static/noSession.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/static/noSession.ftl
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/static/noSession.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/static/noSession.ftl
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/static/passwordRecoveryOk.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/static/passwordRecoveryOk.ftl
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/static/passwordRecoveryOk.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/static/passwordRecoveryOk.ftl
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/static/reactivate.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/static/reactivate.ftl
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/static/reactivate.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/static/reactivate.ftl
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/static/rules.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/static/rules.ftl
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/static/rules.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/static/rules.ftl
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/static/scope.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/static/scope.ftl
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/static/scope.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/static/scope.ftl
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/account.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/types/account.ftl
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/account.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/types/account.ftl
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/alliance.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/types/alliance.ftl
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/alliance.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/types/alliance.ftl
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/banned.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/types/banned.ftl
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/banned.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/types/banned.ftl
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/battle.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/types/battle.ftl
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/battle.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/types/battle.ftl
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/battles.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/types/battles.ftl
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/battles.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/types/battles.ftl
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/bugsList.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/types/bugsList.ftl
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/bugsList.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/types/bugsList.ftl
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/bugsReport.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/types/bugsReport.ftl
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/bugsReport.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/types/bugsReport.ftl
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/bugsTabs.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/types/bugsTabs.ftl
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/bugsTabs.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/types/bugsTabs.ftl
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/bugsView.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/types/bugsView.ftl
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/bugsView.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/types/bugsView.ftl
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/chat.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/types/chat.ftl
similarity index 95%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/chat.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/types/chat.ftl
index d2e827a..52708bf 100644
--- a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/chat.ftl
+++ b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/types/chat.ftl
@@ -1,6 +1,6 @@
 <#macro render>
 <@page title="Legacy Worlds - Discussion">
-	<applet code="IRCApplet.class" archive="irc.jar,pixx.jar" codebase="pjirc" width="100%" height="400px">
+	<applet code="IRCApplet.class" archive="irc.jar,pixx.jar" codebase="pjirc" width="100%" height="100%">
 		<param name="CABINETS" value="irc.cab,securedirc.cab,pixx.cab" />
 		<param name="nick" value="${(data.page.empire?replace(' ' , '_'))?xhtml}" />
 		<param name="alternatenick" value="LW-Player-???" />
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/enemies.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/types/enemies.ftl
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/enemies.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/types/enemies.ftl
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/fleets.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/types/fleets.ftl
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/fleets.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/types/fleets.ftl
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/fleetsCommand.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/types/fleetsCommand.ftl
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/fleetsCommand.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/types/fleetsCommand.ftl
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/getNewPlanet.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/types/getNewPlanet.ftl
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/getNewPlanet.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/types/getNewPlanet.ftl
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/maintenance.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/types/maintenance.ftl
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/maintenance.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/types/maintenance.ftl
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/map.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/types/map.ftl
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/map.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/types/map.ftl
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/message.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/types/message.ftl
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/message.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/types/message.ftl
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/messageBox.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/types/messageBox.ftl
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/messageBox.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/types/messageBox.ftl
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/messageTabs.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/types/messageTabs.ftl
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/messageTabs.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/types/messageTabs.ftl
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/messageTargets.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/types/messageTargets.ftl
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/messageTargets.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/types/messageTargets.ftl
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/messageWriter.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/types/messageWriter.ftl
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/messageWriter.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/types/messageWriter.ftl
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/offline.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/types/offline.ftl
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/offline.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/types/offline.ftl
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/overview.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/types/overview.ftl
similarity index 94%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/overview.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/types/overview.ftl
index c679530..61bdda4 100644
--- a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/overview.ftl
+++ b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/types/overview.ftl
@@ -60,11 +60,6 @@
 		
 			</@right_column>
 		</@tab>
-		
-		<@tab id="economy" title="Économie">
-			<#include "overview/resources.ftl" />
-			<@overviewResources />
-		</@tab>
 
 	</@tabs>
 
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/passwordRecovery.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/types/passwordRecovery.ftl
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/passwordRecovery.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/types/passwordRecovery.ftl
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/planet.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/types/planet.ftl
similarity index 87%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/planet.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/types/planet.ftl
index 9c69b05..1aed9bf 100644
--- a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/planet.ftl
+++ b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/types/planet.ftl
@@ -108,55 +108,6 @@
 			</#if>
 
 		</@tab>
-
-		<#if data.own?has_content && data.own.resources?size gt 0>
-		
-			<@tab id="resources" title="Économie">
-			
-				<@listview>
-					<#local previousCategory="">
-
-					<@lv_line headers=true>
-						<@lv_column width=30>&nbsp;</@lv_column>
-						<@lv_column width="x">Ressource</@lv_column>
-						<@lv_column width=100 centered=true><@over_time "Bénéfice" /></@lv_column>
-						<@lv_column width=100 centered=true><@over_time title="Charges" feminin=true pluriel=true /></@lv_column>
-						<@lv_column width=100 centered=true>Investissement</@lv_column>
-					</@lv_line>
-					
-					<#list data.own.resources as resource>
-
-						<#if previousCategory?has_content && !resource.category?has_content
-								|| resource.category?has_content && !previousCategory?has_content
-								|| resource.category?has_content && previousCategory?has_content
-									&& resource.category != previousCategory>
-							<@lv_line>
-								<#if resource.category?has_content>
-									<td colspan="5"><strong>${resource.category?xhtml}</strong></td>
-								<#else>
-									<td colspan="5"><hr /></td>
-								</#if>
-							</@lv_line>
-							<#local previousCategory=resource.category>
-						</#if>
-						
-						<@lv_line>
-							<@lv_column>&nbsp;</@lv_column>
-							<@lv_column>${resource.title?xhtml}
-								<div class="auto-hide">${resource.description?xhtml}</div>
-							</@lv_column>
-							<@lv_column centered=true>${resource.income?string(",##0")}</@lv_column>
-							<@lv_column centered=true>${resource.upkeep?string(",##0")}</@lv_column>
-							<@lv_column centered=true>${resource.invested?string(",##0")}</@lv_column>
-						</@lv_line>
-
-					</#list>
-
-				</@listview>
-			
-			</@tab>
-
-		</#if>
 	
 		<#if data.orbit?has_content>
 		
@@ -192,7 +143,6 @@
 												<#case "DEF">défense<#break>
 												<#case "WORK">production mil.<#break>
 												<#case "POP">croissance<#break>
-												<#case "MINE">extraction<#break>
 											</#switch>
 										</@lv_column>
 										<@lv_column centered=true>${building.jobs?string(",##0")}</@lv_column>
@@ -239,7 +189,6 @@
 														<#case "DEF">défense<#break>
 														<#case "WORK">production mil.<#break>
 														<#case "POP">croissance<#break>
-														<#case "MINE">extraction<#break>
 													</#switch>
 												</@dt_entry>
 											</@dt_main>
@@ -373,10 +322,6 @@
 					</#if>
 				</@tab>
 			</#if>
-
-			<#include "planet/natres.ftl" />
-			<@RenderNaturalResources />
-
 		</#if>
 
 	</@tabs>
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/planets.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/types/planets.ftl
similarity index 98%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/planets.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/types/planets.ftl
index 51760fb..e8fb997 100644
--- a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/planets.ftl
+++ b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/types/planets.ftl
@@ -28,7 +28,7 @@
 				</@listview>
 			</@tab>
 
-			<@tab id="eco" title="Économie (VIEUX)"> 
+			<@tab id="eco" title="Économie"> 
 				<@listview>
 					<@lv_line headers=true>
 						<@lv_column width="x">Nom</@lv_column>
@@ -56,9 +56,6 @@
 				</@listview>
 			</@tab>
 
-			<#include "planets/economy.ftl" />
-			<@RenderEconomy />
-
 			<@tab id="prod" title="Production"> 
 				<@listview>
 					<@lv_line headers=true>
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/reactivation.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/types/reactivation.ftl
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/reactivation.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/types/reactivation.ftl
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/register.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/types/register.ftl
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/register.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/types/register.ftl
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/registered.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/types/registered.ftl
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/registered.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/types/registered.ftl
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/splitFleet.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/types/splitFleet.ftl
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/splitFleet.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/types/splitFleet.ftl
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/static.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/types/static.ftl
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/static.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/types/static.ftl
diff --git a/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/types/technologies.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/types/technologies.ftl
new file mode 100644
index 0000000..5ae9fc6
--- /dev/null
+++ b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/types/technologies.ftl
@@ -0,0 +1,171 @@
+<#macro render_entry identifier title category description>
+	<div class="research-entry" id="research-${identifier?xhtml}">
+		<div class="title">${title?xhtml}</div>
+		<div class="category">Catégorie: <b>${category?xhtml}</b></div>
+		<div class="description">${description?xhtml}</div>
+		<#nested>
+	</div>
+</#macro>
+<#macro render_implementable entry>
+	<@render_entry entry.identifier entry.name entry.category entry.description>
+		<div class="cost">Coût: <b>${entry.cost?string(",##0")}</b> <@abbr_bgc/></div>
+		<#if data.page.cash &gt;= entry.cost>
+			<form class="implement" name="implement-${entry.identifier?xhtml}" action="implement-tech.action" method="POST">
+				<input type="hidden" name="technology" value="${entry.identifier?xhtml}" />
+				<input type="submit" class="input" value="Appliquer la technologie" />
+			</form>
+		</#if> 
+	</@render_entry>
+</#macro>
+<#macro render_research entry title description display_priority_form>
+	<@render_entry entry.identifier title entry.category description>
+		<div class="progress">Progrès: <span class="progress">${entry.completion}%</span></div>
+		<#if display_priority_form>
+			<div class="priority">
+				Priorité:
+				<span class="priority">
+					<input type="text" maxlength="3" size="4" class="input priority-field" name="priority-${entry.identifier?xhtml}" id="priority-${entry.identifier?xhtml}" value="${entry.priority}" />%
+				</span> 
+			</div>
+		</#if>
+	</@render_entry>
+</#macro>
+<#macro render_unidentified entry display_priority_form>
+	<@render_research entry "Technologie non identifiée" "Nos chercheurs travaillent sur une nouvelle technologie, mais ne savent pas encore où leurs travaux les mèneront." display_priority_form />
+</#macro>
+<#macro render_research_list entries>
+	<#local priority_form_started = false>
+	<#local priority_form_checked = false>
+	<#local display_priority_form = false>
+	<#local counter = 0>
+	<#-- List of in-progress research topics as well as implementable technologies -->
+	<#list entries as entry>
+		<#if entry.cost?has_content>
+			<#-- Technology that can be implemented -->
+			<#local counter = counter + 1>
+			<@render_implementable entry />
+		<#else>
+			<#if ! priority_form_checked>
+				<#-- Check whether we need to display the priority form -->
+				<#if entries?size - counter &gt; 1>
+					<#local display_priority_form = true>
+				</#if>
+				<#local priority_form_checked = true>
+			</#if>
+			<#-- Start of the research priority form, if necessary -->
+			<#if display_priority_form && ! priority_form_started>
+				<#local priority_form_started = true>
+				<form name="priority" action="set-research-priority.action" method="POST">
+			</#if>
+			<#if entry.name?has_content>
+				<#-- Identified technology being researched -->
+				<@render_research entry entry.name entry.description display_priority_form />
+			<#else>
+				<#-- Unidentified technology -->
+				<@render_unidentified entry display_priority_form />
+			</#if>
+		</#if>
+	</#list>
+	<#-- End of the research priority form, if necessary -->
+	<#if priority_form_started>
+			<div class="submit-priorities">
+				<input type="submit" class="input" value="Modifier les priorités" />
+			</div>
+		</form>
+	</#if>
+</#macro>
+<#macro find_tech_name id lists>
+	<#local found=false>
+	<#list lists as cat>
+		<#list cat.technologies as tech>
+			<#if tech.identifier == id><#local found=true>${tech.name?xhtml}<#break></#if>
+		</#list>
+		<#if found><#break></#if>
+	</#list>
+</#macro>
+<#macro render_tech_dependencies deps fullLists>
+	<ul>
+		<#list deps as dependency>
+			<li><a href="#tech-${dependency?xhtml}"><@find_tech_name dependency fullLists /></a></li>
+		</#list>
+	</ul>
+</#macro>
+<#macro render_technology tech fullList>
+	<div class="technology" id="tech-${tech.identifier?xhtml}">
+		<div class="title">${tech.name?xhtml}</div>
+		<div class="description">
+			<p>${tech.description?xhtml}</p>
+		</div>
+		
+		<#if tech.dependsOn?size != 0>
+			<div class="dependencies">
+				<b>Dépend de:</b>
+				<@render_tech_dependencies tech.dependsOn fullList />
+			</div>
+		</#if>
+		
+		<#if tech.dependencyOf?size != 0>
+			<div class="rev-deps">
+				<b>Requise par:</b>
+				<@render_tech_dependencies tech.dependencyOf fullList />
+			</div>
+		</#if>
+
+	</div>
+</#macro>
+<#macro render_tech_list categories>
+	<#-- List categories -->
+	<#list categories as category>
+		<div class="tech-category">
+			<h2>${category.name?xhtml}</h2>
+			<p>${category.description?xhtml}</p>
+			<#-- List technologies in the category -->
+			<#list category.technologies as technology>
+				<@render_technology technology categories />
+			</#list>
+		</div>
+	</#list>
+</#macro>
+<#macro render>
+<@page title="Technologies">
+
+	<#if data.research?size == 0 && data.implementedTechnologies?size == 0>
+		<p>Nos chercheurs sont encore en train de s'installer, revenez dans un petit moment...</p>
+		<#return>
+	</#if>
+	
+	<@tabs>
+	
+		<#if data.research?size != 0>
+			<@tab id="research" title="Recherche">
+				<#if data.result?exists>
+					<#switch data.result>
+						<#case "ERR_RESOURCES">
+							<@standalone_error>Nous ne possédons plus les ressources nécessaires.</@standalone_error>
+							<#break>
+						<#case "ERR_STATE_CHANGED">
+							<@standalone_error>Quelque chose a changé... Veuillez réessayer.</@standalone_error>
+							<#break>
+						<#case "ERR_INVALID">
+							<@standalone_error>Priorités invalides.</@standalone_error>
+							<#break>
+						<#default>
+							<#-- Ignore other error codes -->
+							<#break>
+					</#switch>
+				</#if>
+				<#-- Render the list -->
+				<@render_research_list data.research />
+			</@tab>
+		</#if>
+
+		<#if data.implementedTechnologies?size != 0>
+			<@tab id="implemented" title="Technologies maîtrisées">
+				<@render_tech_list data.implementedTechnologies />
+			</@tab>
+		</#if>
+
+	</@tabs>
+
+</@page>
+</#macro>
\ No newline at end of file
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/validation.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/types/validation.ftl
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/validation.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/fr/types/validation.ftl
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/layout/columns.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/layout/columns.ftl
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/layout/columns.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/layout/columns.ftl
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/layout/datatable.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/layout/datatable.ftl
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/layout/datatable.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/layout/datatable.ftl
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/layout/fields.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/layout/fields.ftl
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/layout/fields.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/layout/fields.ftl
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/layout/form.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/layout/form.ftl
similarity index 87%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/layout/form.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/layout/form.ftl
index 1fc8448..4544473 100644
--- a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/layout/form.ftl
+++ b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/layout/form.ftl
@@ -1,21 +1,12 @@
-<#macro rawFormStart action name="" hash="">
-	<form action="${action?url}.action<#if hash != "">#${hash?url}</#if>" method="post">
-</#macro>
-<#macro formStart action name="" hash="">
+<#macro form action name="" hash="">
 	<div class="form-container">
-		<@rawFormStart action name hash />
+		<form action="${action?url}.action<#if hash != "">#${hash?url}</#if>" method="post">
 			<table>
-</#macro>
-<#macro formEnd>
+				<#nested>
 			</table>
 		</form>
 	</div>
 </#macro>
-<#macro form action name="" hash="">
-	<@formStart action name hash />
-		<#nested>
-	<@formEnd />
-</#macro>
 <#macro form_field_line label id>
 	<tr class="form-field">
 		<th><label for="ff-${id?xhtml}">${label?xhtml}:</label></th>
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/layout/happiness.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/layout/happiness.ftl
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/layout/happiness.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/layout/happiness.ftl
diff --git a/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/layout/lists.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/layout/lists.ftl
new file mode 100644
index 0000000..798342a
--- /dev/null
+++ b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/layout/lists.ftl
@@ -0,0 +1,25 @@
+<#macro listview>
+	<table class="list-view">
+		<#nested>
+	</table>
+</#macro>
+<#macro lv_line headers=false class="">
+	<tr<#if class != ""> class="${class}<#if headers>headers</#if>"<#elseif headers> class="headers"</#if>>
+		<#nested>
+	</tr>
+</#macro>
+<#macro lv_column width=0 centered=false right=false>
+	<#if width?is_string>
+		<th style="text-align: <#if centered>center<#elseif right>right<#else>left</#if>">
+			<#nested>
+		</th>
+	<#elseif width gt 0>
+		<th style="width: ${width}px; text-align: <#if centered>center<#elseif right>right<#else>left</#if>">
+			<#nested>
+		</th>
+	<#else>
+		<td style="text-align: <#if centered>center<#elseif right>right<#else>left</#if>">
+			<#nested>
+		</td>
+	</#if>
+</#macro>
\ No newline at end of file
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/layout/tabs.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/layout/tabs.ftl
similarity index 61%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/fm/layout/tabs.ftl
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/layout/tabs.ftl
index 599fcfb..b1ab861 100644
--- a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/layout/tabs.ftl
+++ b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/layout/tabs.ftl
@@ -3,17 +3,11 @@
 		<#nested>
 	</div>
 </#macro>
-<#macro tabStart id title>
+<#macro tab id title>
 	<div class="tab" id="${id?xhtml}">
 		<h3>${title?xhtml}</h3>
 		<div class="tab-contents">
-</#macro>
-<#macro tabEnd>
+			<#nested>
 		</div>
 	</div>
-</#macro>
-<#macro tab id title>
-	<@tabStart id title />
-		<#nested>
-	<@tabEnd />
 </#macro>
\ No newline at end of file
diff --git a/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/version.ftl b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/version.ftl
new file mode 100644
index 0000000..e4abdb7
--- /dev/null
+++ b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/fm/version.ftl
@@ -0,0 +1,2 @@
+<#macro version>Milestone 2</#macro>
+<#macro full_version>Beta 6 milestone 2 (5.99.2)</#macro>
\ No newline at end of file
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/main-servlet.xml b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/main-servlet.xml
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/main-servlet.xml
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/main-servlet.xml
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/web.xml b/legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/web.xml
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/WEB-INF/web.xml
rename to legacyworlds-web/legacyworlds-web-main/WebContent/WEB-INF/web.xml
diff --git a/legacyworlds-web-main/Content/Raw/css/main.css b/legacyworlds-web/legacyworlds-web-main/WebContent/css/main.css
similarity index 66%
rename from legacyworlds-web-main/Content/Raw/css/main.css
rename to legacyworlds-web/legacyworlds-web-main/WebContent/css/main.css
index 2fabe1c..40af4ab 100644
--- a/legacyworlds-web-main/Content/Raw/css/main.css
+++ b/legacyworlds-web/legacyworlds-web-main/WebContent/css/main.css
@@ -5,6 +5,13 @@
 	padding: 0px;
 	margin: 0px;
 	color: white;
+	scrollbar-face-color: #1f1f1f;
+	scrollbar-highlight-color: #1f1f1f;
+	scrollbar-3dlight-color: #3f3f3f;
+	scrollbar-darkshadow-color: #3f3f3f;
+	scrollbar-shadow-color: #1f1f1f;
+	scrollbar-arrow-color: #afafaf;
+	scrollbar-track-color: #1f1f1f;
 }
 
 h1 {
@@ -31,259 +38,304 @@ h6 {
 	font-size: 10pt
 }
 
-a {
-	text-decoration: none;
-}
-
-a:hover {
-	text-decoration: underline;
+body {
+	background-color: #000;
+	color: #888;
+	overflow: auto;
 }
 
 /* Page layout */
-body {
-	background: black;
+#extframe {
+	position: absolute;
+	top: 50%;
+	left: 0px;
+	width: 100%;
+	height: 1px
+}
+
+.internal {
+	margin-left: -475px;
+	position: absolute;
+	left: 50%;
+	width: 950px;
+}
+
+#intframe {
+	top: -280px;
+	height: 560px;
 	background-image: url(../img/background.jpg);
-	background-position: right bottom;
-	background-attachment: fixed;
 	background-repeat: no-repeat;
-	background-size: cover;
-	min-width: 960px;
-}
-
-#hd-logo {
-	float: left;
-	position: relative;
-	background: url(../img/rust.png) repeat;
-	border-radius: 0 0 30px 0;
-	box-shadow: inset -2px -2px 10px #bfbfbf, 2px 2px 30px black;
-	margin: 0;
-	padding: 0;
-	z-index: 1;
-}
-
-#hd-logo>a {
-	display: block;
-	width: 260px;
-	height: 96px;
-	background: url(../img/logo.png) no-repeat;
-	margin: 0;
-	padding: 0;
-}
-
-#hd-logo>a>span {
-	display: none;
-}
-
-#hd-summary {
-	float: right;
-	font-size: 10pt;
-	text-align: right;
-	padding: 3px 10px 0 0;
-}
-
-#hd-page {
-	padding: 5px;
-}
-
-#hd-page h1 {
-	padding: 0;
-	margin: 0 0 5px 0;
-	font-size: 18pt;
-	font-variant: small-caps;
-	text-shadow: 0 0 1px white, 2px 2px 4px black;
-}
-
-#hd-page ul {
-	padding: 0;
-	margin: 0;
-}
-
-#hd-page li {
-	display: inline-block;
-}
-
-#hd-page li a {
-	font-size: 12px;
-	font-variant: small-caps;
-	display: block;
-	margin: 0 10px;
-	padding: 4px 8px;
-	background-color: rgba(127, 127, 127, 0.2);
-	border-radius: 10px;
-	border-style: solid;
-	border-width: 1px;
-	border-color: rgba(255, 255, 255, 0.3);
-	color: #bfbfbf;
-	text-shadow: 1px 1px 1px black;
-}
-
-#hd-page li.selected a {
-	color: white;
-	background-color: rgba(127, 127, 127, 0.8);
-}
-
-#hd-page li a:hover {
-	text-decoration: none;
-	border-color: rgba(255, 255, 255, 1);
-	color: white;
-}
-
-#hd-bar {
-	background: url(../img/rust.png) repeat;
-	height: 76px;
-	box-shadow: inset 0 -2px 10px #bfbfbf, 2px 2px 30px black;
-	z-index: 0;
-	padding: 0 0 0 260px;
-	margin: 0 10px 0 0;
-	border-radius: 0 0 20px 0;
-}
-
-#hd-text {
-	color: white;
-	height: 12px;
-	font-size: 12px;
-	text-align: right;
-	font-weight: bold;
-	font-style: italic;
-	padding: 4px 20px 4px 0px;
-}
-
-/* Menu */
-#menu-left {
-	float: left;
-	position: relative;
-	width: 200px;
-	background: url(../img/rust.png) repeat;
-	background-position: 0 -96px;
-	border-radius: 0 0 20px 0;
-	margin: -20px 0 0 -20px;
-	padding: 20px 0 0 20px;
-	box-shadow: inset -2px -2px 5px #bfbfbf, 2px 2px 30px black;
-	z-index: 0;
-}
-
-#menu-left div.button {
-	margin: 10px 9px;
-}
-
-#menu-left div.button.sub-menu {
-	margin: 5px 9px 5px 30px;
-}
-
-div.button a {
-	display: block;
-	color: #bfbfbf;
-	text-decoration: none;
-	font-weight: bold;
-	font-size: 16px;
-	text-align: center;
-	padding: 5px;
-	box-shadow: inset -2px -2px 5px #7f7f7f, 0px 0px 5px #3f3f3f;
-	border-radius: 15px;
-	border: 1px solid transparent;
-	text-shadow: 2px 2px 2px black;
-}
-
-div.button.sub-menu a {
-	font-size: 11px;
-	font-weight: normal;
-	text-align: right;
-	padding: 3px 10px 3px 3px;
-}
-
-div.button.current a {
-	border-color: white;
-	color: white;
-}
-
-div.button a:focus,div.button a:hover {
-	color: white;
-	box-shadow: inset -2px -2px 5px white, 0px 0px 10px black;
 }
 
 /* Footer (DCD link) */
 #footer {
+	top: 280px;
 	text-align: center;
-	margin: 0 0 10px 0;
+	font-size: 8pt;
+	font-style: italic;
+	padding: 2px 0 0 0;
 }
 
-#footer,#footer a {
+#footer a,#footer a:visited {
 	font-size: 8pt;
+	text-decoration: none;
+	color: white;
+}
+
+#footer a:hover {
+	text-decoration: underline;
+}
+
+/* "Home" button */
+#hbutton {
+	display: block;
+	position: absolute;
+	top: 12px;
+	left: 10px;
+	width: 272px;
+	height: 90px;
+	background-color: transparent;
+}
+
+#hbutton span {
+	display: none;
+}
+
+/* Current version text */
+#version {
+	position: absolute;
+	top: 89px;
+	left: 299px;
+	width: 640px;
+	height: 22px;
+	font-size: 10pt;
+	text-align: center;
+	font-style: italic;
+	font-weight: bold;
+}
+
+/* Log-in/player info box */
+#lbox {
+	position: absolute;
+	top: 9px;
+	left: 699px;
+	width: 230px;
+	height: 60px;
+	text-align: right;
+	font-size: 10pt;
+}
+
+#lbox a {
+	color: white;
+	text-decoration: none;
+	font-style: italic;
+}
+
+#lbox a:hover {
+	text-decoration: underline;
+}
+
+/* Menu and buttons */
+a.mbutton {
+	display: block;
+	position: absolute;
+	height: 21px;
+	width: 250px;
+	left: 14px;
+	padding: 18px 0px;
+	background-repeat: no-repeat;
+	border-style: none;
+	border-width: 0px;
+	font-weight: bold;
+	text-align: center;
+	text-decoration: none;
+	color: #ddd;
+	background-position: 0px 0px;
+	font-size: 12pt;
+}
+
+a.mbutton:hover {
+	color: white;
+	background-position: 0px -57px;
+}
+
+a#b0 {
+	top: 136px;
+	background-image: url(../img/button-0.png);
+}
+
+a#b1 {
+	top: 193px;
+	background-image: url(../img/button-1.png);
+}
+
+a#b2 {
+	top: 250px;
+	background-image: url(../img/button-2.png);
+}
+
+a#b3 {
+	top: 307px;
+	background-image: url(../img/button-3.png);
+}
+
+a#b4 {
+	top: 364px;
+	background-image: url(../img/button-4.png);
+}
+
+a#b5 {
+	top: 421px;
+	background-image: url(../img/button-5.png);
+}
+
+a#b6 {
+	top: 478px;
+	background-image: url(../img/button-6.png);
 }
 
 /* Content frame */
-#page-contents {
-	margin: 0 20px 10px -40px;
-	padding: 20px 40px 20px 260px;
-	border-radius: 40px;
-	background-color: rgba(0, 0, 0, 0.7);
-	min-height: 400px;
+.cframe {
+	position: absolute;
+	left: 299px;
+	top: 117px;
+	width: 637px;
+	height: 426px;
+	overflow: auto;
+	background-color: transparent;
+	color: white;
 }
 
-.chat-page#page-contents {
-	padding: 20px 40px 20px 60px;
+.cframe.full-width {
+	left: 15px;
+	width: 921px;
 }
 
-#page-contents p {
+.cframe.offline {
+	height: 279px;
+	top: 264px;
+	overflow: hidden;
+}
+
+.cframe p {
 	color: #CCCCCC;
 }
 
-#page-contents ul,#page-contents ol {
+.cframe ul,.cframe ol {
 	margin: 0px 0px 0px 20px;
 	padding: 0px 0px 0px 10px;
 }
 
-#page-contents li {
+.cframe li {
 	margin: 0px 0px 0px 20px;
 	padding: 0px 0px 0px 0px;
 }
 
 /* Text in the content frame */
-#page-contents ul {
+.cframe ul {
 	list-style-type: square;
 }
 
-#page-contents li {
+.cframe li {
 	font-size: 10pt;
 }
 
-#page-contents li:first-letter {
+.cframe li:first-letter {
 	font-size: 11pt;
 	font-weight: bold;
 }
 
-#page-contents p {
+.cframe p {
 	margin: 5px 10px 5px 30px;
 	text-align: justify;
 	text-indent: 10px;
 	font-size: 10pt;
 }
 
-#page-contents p:first-letter {
+.cframe p:first-letter {
 	font-size: 11pt;
 	font-weight: bold;
 }
 
+/* Tabs */
+.tab-buttons {
+	width: 100%;
+	text-align: center;
+	margin: 0 0 5px 0;
+	padding: 5px 0 0 0;
+	height: 20px;
+}
+
+a.tab-button {
+	padding: 4px;
+	margin: 1px 0 0 5px;
+	background-color: #3f3f3f;
+	border: 1px solid #7f7f7f;
+	text-decoration: none;
+	font-style: normal;
+}
+
+a.tab-button:hover {
+	background-color: #4f4f4f;
+	border-color: #8f8f8f;
+}
+
+a.tab-button.selected-tab,a.tab-button.selected-tab:hover {
+	background-color: #7f7f7f;
+	border-color: white;
+}
+
+/* Top/centered layer (title, planet links) */
+div.top-centered {
+	position: absolute;
+	left: 330px;
+	width: 320px;
+	top: 10px;
+	height: 50px;
+	text-align: center;
+}
+
+#tc-title {
+	font-weight: bold;
+	font-size: 13pt;
+	text-align: center;
+}
+
+div#tc-title {
+	top: 30px;
+	height: 30px;
+}
+
+span.special-info {
+	color: red;
+	font-weight: bold;
+}
+
 /* Forms */
 .form-container {
-	width: -moz-calc(100% -   128px);
-	width: -webkit-calc(100% -   128px);
-	width: -o-calc(100% -   128px);
-	width: calc(100% -   128px);
+	width: 509px;
+	margin: 0 64px;
+}
+
+.full-width .form-container {
+	width: 793px;
 	margin: 0 64px;
 }
 
 .form-container table {
-	width: 100%;
+	width: 509px;
 	table-layout: fixed;
 }
 
+.full-width .form-container table {
+	width: 793px;
+}
+
 .form-field th,.form-submit th {
 	text-align: right;
 	vertical-align: middle;
 	height: 16px;
-	min-width: 200px;
-	width: 25%;
+	width: 200px;
 	padding: 4px;
 	font-weight: normal;
 }
@@ -304,10 +356,10 @@ div.button a:focus,div.button a:hover {
 	padding: 5px 20px;
 }
 
-.form-submit .input:hover,.form-submit .input:focus {
+.form-submit .input:hover {
 	padding: 5px 20px;
 	border-color: #dfdfdf;
-	background-color: rgba(127, 127, 127, 0.6);
+	background-color: #7f7f7f;
 }
 
 .form-extra td {
@@ -323,23 +375,20 @@ div.button a:focus,div.button a:hover {
 .form-error td {
 	font-size: 11pt;
 	color: white;
-	background-color: rgba(255, 0, 0, 0.4);
+	background-color: red;
 	font-weight: bold;
 	margin: 2px 0px;
-	padding: 5px 10px;
-	border-radius: 10px;
+	padding: 5px;
 }
 
 .input {
 	border-style: solid;
 	border-width: 1px;
 	border-color: #afafaf;
-	background-color: rgba(63, 63, 63, 0.6);
+	background-color: #3f3f3f;
 	color: white;
 	font-size: 10pt;
-	margin: 1px 0px;
-	border-radius: 8px;
-	padding: 0 4px;
+	margin: 1px 0px
 }
 
 /* Data display */
@@ -371,10 +420,7 @@ div.button a:focus,div.button a:hover {
 
 /* List display */
 .list-view {
-	width: -moz-calc(100% -   64px);
-	width: -webkit-calc(100% -   64px);
-	width: -o-calc(100% -   64px);
-	width: calc(100% -   64px);
+	width: 573px;
 	margin: 0 32px 20px 32px;
 	border-collapse: collapse;
 }
@@ -397,7 +443,7 @@ div.button a:focus,div.button a:hover {
 
 /* Column layout */
 .column {
-	width: 50%
+	width: 310px
 }
 
 .left-column {
@@ -405,7 +451,7 @@ div.button a:focus,div.button a:hover {
 }
 
 .right-column {
-	padding: 0 0 0 50%;
+	padding: 0 0 0 310px;
 }
 
 /* Misc */
@@ -604,20 +650,14 @@ table.fleets-planet,table.fleets-moving {
 	border: 1px solid white;
 	border-collapse: collapse;
 	margin: 0 0 20px 5px;
-	width: -moz-calc(100% -   20px);
-	width: -webkit-calc(100% -   20px);
-	width: -o-calc(100% -   20px);
-	width: calc(100% -   20px);
+	width: 610px;
 }
 
 table.selected-fleets {
 	border: 1px solid white;
 	border-collapse: collapse;
 	margin: 10px 0 20px 15px;
-	width: -moz-calc(100% -   30px);
-	width: -webkit-calc(100% -   30px);
-	width: -o-calc(100% -   30px);
-	width: calc(100% -   30px);
+	width: 600px;
 }
 
 table.fleets-planet td {
@@ -801,18 +841,59 @@ tr.empire-msg * {
 	color: #afafaf;
 }
 
-/*
- * Research page
- */
-.tech-line {
-	height: 22px;
+/* Research and technologies */
+div.research-entry {
+	padding: 0 0 15px 0;
 }
-.tech-view h4 {
-	margin-bottom: 15px;
+
+div.research-entry div {
+	padding: 0 0 0 20px;
 }
-.tech-view .tech-info {
-	margin-bottom: 7px;
+
+div.research-entry div.title {
+	color: white;
+	font-size: 110%;
+	font-weight: bold;
+	padding: 0;
 }
-.tech-line.selected, .tech-line.selected td {
-	background-color: rgba(127, 127, 127, 0.25);
+
+div.research-entry div.description {
+	padding: 0 0 5px 20px;
+	font-style: italic;
+}
+
+div.research-entry div.progress {
+	padding: 0 0 5px 20px;
+}
+
+div.research-entry span.progress {
+	font-weight: bold;
+	color: white;
+}
+
+div.research-entry form.implement {
+	padding: 5px 0 0 40px;
+}
+
+div.tech-category {
+	padding: 0 0 15px 0;
+}
+
+div.technology {
+	padding: 15px 0 0 20px;
+}
+
+div.technology div {
+	padding: 0 0 0 20px;
+}
+
+div.technology div.title {
+	color: white;
+	font-size: 105%;
+	font-weight: bold;
+	padding: 0;
+}
+
+div.technology div.description {
+	padding: 0;
 }
\ No newline at end of file
diff --git a/legacyworlds-web/legacyworlds-web-main/WebContent/img/background.jpg b/legacyworlds-web/legacyworlds-web-main/WebContent/img/background.jpg
new file mode 100644
index 0000000..b5bd6df
Binary files /dev/null and b/legacyworlds-web/legacyworlds-web-main/WebContent/img/background.jpg differ
diff --git a/legacyworlds-web/legacyworlds-web-main/WebContent/img/button-0.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/button-0.png
new file mode 100644
index 0000000..ed18c52
Binary files /dev/null and b/legacyworlds-web/legacyworlds-web-main/WebContent/img/button-0.png differ
diff --git a/legacyworlds-web/legacyworlds-web-main/WebContent/img/button-1.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/button-1.png
new file mode 100644
index 0000000..c62487e
Binary files /dev/null and b/legacyworlds-web/legacyworlds-web-main/WebContent/img/button-1.png differ
diff --git a/legacyworlds-web/legacyworlds-web-main/WebContent/img/button-2.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/button-2.png
new file mode 100644
index 0000000..2ffec4f
Binary files /dev/null and b/legacyworlds-web/legacyworlds-web-main/WebContent/img/button-2.png differ
diff --git a/legacyworlds-web/legacyworlds-web-main/WebContent/img/button-3.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/button-3.png
new file mode 100644
index 0000000..f35a722
Binary files /dev/null and b/legacyworlds-web/legacyworlds-web-main/WebContent/img/button-3.png differ
diff --git a/legacyworlds-web/legacyworlds-web-main/WebContent/img/button-4.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/button-4.png
new file mode 100644
index 0000000..e2c9548
Binary files /dev/null and b/legacyworlds-web/legacyworlds-web-main/WebContent/img/button-4.png differ
diff --git a/legacyworlds-web/legacyworlds-web-main/WebContent/img/button-5.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/button-5.png
new file mode 100644
index 0000000..92560ea
Binary files /dev/null and b/legacyworlds-web/legacyworlds-web-main/WebContent/img/button-5.png differ
diff --git a/legacyworlds-web/legacyworlds-web-main/WebContent/img/button-6.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/button-6.png
new file mode 100644
index 0000000..81a8a92
Binary files /dev/null and b/legacyworlds-web/legacyworlds-web-main/WebContent/img/button-6.png differ
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/1.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/1.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/1.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/1.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/10.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/10.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/10.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/10.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/100.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/100.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/100.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/100.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/101.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/101.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/101.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/101.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/102.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/102.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/102.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/102.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/103.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/103.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/103.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/103.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/104.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/104.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/104.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/104.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/105.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/105.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/105.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/105.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/106.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/106.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/106.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/106.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/107.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/107.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/107.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/107.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/108.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/108.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/108.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/108.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/109.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/109.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/109.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/109.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/11.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/11.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/11.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/11.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/110.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/110.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/110.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/110.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/111.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/111.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/111.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/111.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/112.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/112.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/112.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/112.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/113.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/113.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/113.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/113.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/114.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/114.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/114.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/114.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/115.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/115.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/115.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/115.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/116.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/116.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/116.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/116.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/117.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/117.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/117.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/117.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/118.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/118.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/118.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/118.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/119.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/119.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/119.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/119.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/12.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/12.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/12.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/12.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/120.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/120.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/120.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/120.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/121.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/121.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/121.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/121.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/122.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/122.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/122.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/122.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/123.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/123.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/123.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/123.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/124.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/124.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/124.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/124.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/125.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/125.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/125.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/125.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/126.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/126.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/126.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/126.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/127.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/127.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/127.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/127.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/128.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/128.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/128.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/128.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/129.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/129.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/129.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/129.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/13.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/13.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/13.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/13.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/130.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/130.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/130.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/130.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/131.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/131.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/131.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/131.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/132.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/132.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/132.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/132.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/133.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/133.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/133.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/133.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/134.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/134.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/134.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/134.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/135.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/135.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/135.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/135.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/136.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/136.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/136.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/136.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/137.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/137.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/137.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/137.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/138.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/138.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/138.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/138.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/139.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/139.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/139.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/139.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/14.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/14.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/14.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/14.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/140.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/140.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/140.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/140.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/141.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/141.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/141.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/141.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/142.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/142.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/142.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/142.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/143.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/143.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/143.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/143.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/144.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/144.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/144.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/144.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/145.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/145.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/145.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/145.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/146.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/146.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/146.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/146.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/147.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/147.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/147.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/147.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/148.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/148.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/148.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/148.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/149.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/149.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/149.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/149.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/15.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/15.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/15.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/15.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/150.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/150.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/150.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/150.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/151.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/151.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/151.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/151.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/152.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/152.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/152.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/152.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/153.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/153.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/153.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/153.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/154.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/154.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/154.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/154.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/155.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/155.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/155.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/155.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/156.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/156.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/156.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/156.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/157.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/157.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/157.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/157.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/158.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/158.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/158.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/158.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/159.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/159.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/159.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/159.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/16.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/16.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/16.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/16.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/160.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/160.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/160.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/160.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/161.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/161.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/161.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/161.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/162.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/162.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/162.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/162.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/163.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/163.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/163.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/163.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/164.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/164.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/164.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/164.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/165.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/165.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/165.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/165.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/166.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/166.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/166.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/166.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/167.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/167.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/167.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/167.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/168.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/168.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/168.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/168.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/169.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/169.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/169.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/169.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/17.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/17.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/17.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/17.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/170.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/170.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/170.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/170.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/171.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/171.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/171.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/171.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/172.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/172.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/172.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/172.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/173.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/173.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/173.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/173.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/174.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/174.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/174.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/174.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/175.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/175.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/175.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/175.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/176.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/176.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/176.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/176.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/177.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/177.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/177.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/177.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/178.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/178.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/178.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/178.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/179.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/179.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/179.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/179.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/18.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/18.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/18.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/18.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/180.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/180.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/180.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/180.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/181.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/181.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/181.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/181.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/182.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/182.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/182.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/182.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/183.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/183.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/183.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/183.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/184.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/184.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/184.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/184.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/185.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/185.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/185.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/185.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/186.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/186.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/186.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/186.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/187.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/187.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/187.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/187.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/188.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/188.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/188.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/188.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/189.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/189.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/189.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/189.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/19.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/19.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/19.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/19.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/190.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/190.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/190.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/190.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/191.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/191.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/191.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/191.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/192.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/192.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/192.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/192.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/193.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/193.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/193.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/193.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/194.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/194.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/194.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/194.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/195.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/195.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/195.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/195.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/196.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/196.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/196.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/196.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/197.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/197.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/197.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/197.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/198.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/198.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/198.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/198.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/199.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/199.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/199.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/199.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/2.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/2.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/2.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/2.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/20.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/20.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/20.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/20.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/200.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/200.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/200.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/200.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/21.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/21.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/21.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/21.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/22.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/22.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/22.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/22.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/23.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/23.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/23.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/23.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/24.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/24.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/24.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/24.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/25.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/25.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/25.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/25.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/26.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/26.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/26.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/26.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/27.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/27.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/27.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/27.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/28.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/28.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/28.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/28.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/29.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/29.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/29.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/29.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/3.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/3.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/3.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/3.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/30.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/30.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/30.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/30.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/31.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/31.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/31.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/31.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/32.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/32.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/32.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/32.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/33.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/33.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/33.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/33.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/34.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/34.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/34.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/34.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/35.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/35.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/35.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/35.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/36.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/36.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/36.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/36.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/37.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/37.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/37.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/37.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/38.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/38.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/38.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/38.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/39.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/39.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/39.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/39.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/4.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/4.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/4.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/4.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/40.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/40.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/40.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/40.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/41.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/41.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/41.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/41.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/42.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/42.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/42.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/42.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/43.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/43.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/43.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/43.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/44.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/44.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/44.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/44.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/45.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/45.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/45.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/45.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/46.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/46.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/46.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/46.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/47.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/47.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/47.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/47.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/48.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/48.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/48.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/48.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/49.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/49.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/49.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/49.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/5.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/5.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/5.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/5.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/50.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/50.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/50.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/50.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/51.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/51.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/51.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/51.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/52.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/52.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/52.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/52.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/53.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/53.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/53.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/53.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/54.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/54.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/54.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/54.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/55.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/55.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/55.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/55.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/56.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/56.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/56.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/56.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/57.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/57.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/57.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/57.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/58.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/58.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/58.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/58.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/59.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/59.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/59.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/59.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/6.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/6.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/6.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/6.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/60.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/60.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/60.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/60.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/61.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/61.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/61.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/61.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/62.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/62.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/62.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/62.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/63.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/63.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/63.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/63.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/64.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/64.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/64.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/64.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/65.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/65.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/65.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/65.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/66.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/66.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/66.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/66.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/67.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/67.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/67.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/67.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/68.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/68.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/68.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/68.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/69.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/69.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/69.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/69.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/7.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/7.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/7.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/7.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/70.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/70.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/70.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/70.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/71.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/71.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/71.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/71.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/72.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/72.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/72.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/72.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/73.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/73.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/73.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/73.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/74.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/74.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/74.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/74.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/75.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/75.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/75.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/75.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/76.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/76.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/76.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/76.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/77.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/77.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/77.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/77.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/78.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/78.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/78.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/78.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/79.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/79.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/79.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/79.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/8.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/8.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/8.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/8.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/80.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/80.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/80.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/80.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/81.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/81.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/81.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/81.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/82.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/82.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/82.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/82.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/83.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/83.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/83.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/83.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/84.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/84.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/84.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/84.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/85.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/85.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/85.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/85.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/86.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/86.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/86.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/86.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/87.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/87.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/87.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/87.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/88.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/88.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/88.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/88.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/89.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/89.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/89.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/89.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/9.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/9.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/9.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/9.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/90.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/90.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/90.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/90.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/91.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/91.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/91.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/91.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/92.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/92.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/92.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/92.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/93.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/93.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/93.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/93.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/94.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/94.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/94.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/94.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/95.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/95.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/95.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/95.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/96.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/96.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/96.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/96.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/97.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/97.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/97.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/97.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/98.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/98.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/98.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/98.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/l/99.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/99.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/l/99.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/l/99.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/1.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/1.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/1.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/1.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/10.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/10.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/10.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/10.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/100.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/100.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/100.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/100.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/101.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/101.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/101.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/101.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/102.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/102.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/102.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/102.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/103.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/103.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/103.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/103.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/104.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/104.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/104.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/104.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/105.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/105.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/105.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/105.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/106.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/106.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/106.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/106.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/107.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/107.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/107.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/107.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/108.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/108.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/108.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/108.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/109.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/109.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/109.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/109.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/11.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/11.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/11.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/11.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/110.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/110.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/110.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/110.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/111.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/111.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/111.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/111.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/112.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/112.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/112.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/112.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/113.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/113.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/113.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/113.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/114.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/114.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/114.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/114.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/115.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/115.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/115.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/115.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/116.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/116.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/116.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/116.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/117.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/117.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/117.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/117.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/118.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/118.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/118.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/118.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/119.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/119.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/119.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/119.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/12.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/12.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/12.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/12.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/120.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/120.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/120.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/120.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/121.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/121.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/121.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/121.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/122.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/122.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/122.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/122.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/123.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/123.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/123.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/123.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/124.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/124.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/124.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/124.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/125.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/125.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/125.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/125.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/126.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/126.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/126.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/126.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/127.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/127.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/127.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/127.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/128.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/128.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/128.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/128.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/129.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/129.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/129.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/129.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/13.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/13.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/13.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/13.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/130.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/130.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/130.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/130.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/131.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/131.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/131.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/131.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/132.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/132.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/132.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/132.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/133.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/133.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/133.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/133.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/134.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/134.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/134.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/134.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/135.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/135.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/135.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/135.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/136.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/136.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/136.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/136.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/137.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/137.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/137.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/137.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/138.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/138.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/138.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/138.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/139.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/139.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/139.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/139.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/14.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/14.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/14.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/14.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/140.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/140.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/140.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/140.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/141.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/141.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/141.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/141.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/142.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/142.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/142.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/142.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/143.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/143.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/143.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/143.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/144.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/144.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/144.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/144.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/145.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/145.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/145.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/145.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/146.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/146.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/146.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/146.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/147.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/147.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/147.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/147.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/148.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/148.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/148.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/148.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/149.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/149.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/149.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/149.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/15.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/15.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/15.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/15.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/150.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/150.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/150.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/150.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/151.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/151.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/151.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/151.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/152.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/152.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/152.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/152.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/153.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/153.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/153.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/153.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/154.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/154.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/154.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/154.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/155.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/155.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/155.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/155.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/156.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/156.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/156.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/156.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/157.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/157.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/157.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/157.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/158.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/158.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/158.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/158.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/159.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/159.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/159.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/159.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/16.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/16.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/16.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/16.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/160.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/160.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/160.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/160.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/161.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/161.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/161.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/161.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/162.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/162.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/162.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/162.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/163.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/163.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/163.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/163.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/164.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/164.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/164.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/164.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/165.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/165.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/165.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/165.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/166.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/166.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/166.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/166.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/167.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/167.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/167.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/167.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/168.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/168.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/168.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/168.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/169.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/169.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/169.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/169.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/17.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/17.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/17.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/17.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/170.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/170.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/170.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/170.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/171.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/171.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/171.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/171.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/172.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/172.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/172.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/172.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/173.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/173.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/173.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/173.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/174.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/174.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/174.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/174.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/175.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/175.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/175.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/175.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/176.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/176.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/176.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/176.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/177.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/177.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/177.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/177.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/178.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/178.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/178.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/178.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/179.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/179.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/179.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/179.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/18.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/18.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/18.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/18.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/180.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/180.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/180.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/180.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/181.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/181.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/181.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/181.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/182.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/182.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/182.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/182.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/183.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/183.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/183.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/183.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/184.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/184.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/184.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/184.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/185.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/185.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/185.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/185.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/186.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/186.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/186.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/186.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/187.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/187.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/187.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/187.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/188.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/188.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/188.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/188.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/189.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/189.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/189.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/189.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/19.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/19.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/19.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/19.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/190.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/190.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/190.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/190.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/191.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/191.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/191.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/191.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/192.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/192.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/192.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/192.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/193.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/193.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/193.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/193.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/194.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/194.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/194.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/194.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/195.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/195.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/195.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/195.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/196.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/196.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/196.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/196.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/197.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/197.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/197.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/197.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/198.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/198.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/198.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/198.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/199.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/199.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/199.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/199.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/2.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/2.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/2.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/2.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/20.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/20.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/20.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/20.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/200.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/200.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/200.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/200.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/21.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/21.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/21.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/21.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/22.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/22.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/22.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/22.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/23.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/23.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/23.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/23.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/24.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/24.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/24.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/24.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/25.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/25.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/25.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/25.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/26.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/26.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/26.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/26.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/27.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/27.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/27.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/27.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/28.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/28.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/28.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/28.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/29.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/29.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/29.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/29.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/3.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/3.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/3.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/3.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/30.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/30.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/30.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/30.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/31.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/31.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/31.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/31.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/32.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/32.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/32.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/32.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/33.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/33.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/33.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/33.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/34.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/34.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/34.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/34.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/35.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/35.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/35.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/35.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/36.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/36.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/36.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/36.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/37.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/37.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/37.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/37.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/38.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/38.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/38.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/38.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/39.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/39.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/39.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/39.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/4.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/4.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/4.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/4.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/40.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/40.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/40.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/40.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/41.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/41.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/41.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/41.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/42.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/42.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/42.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/42.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/43.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/43.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/43.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/43.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/44.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/44.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/44.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/44.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/45.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/45.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/45.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/45.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/46.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/46.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/46.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/46.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/47.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/47.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/47.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/47.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/48.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/48.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/48.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/48.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/49.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/49.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/49.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/49.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/5.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/5.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/5.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/5.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/50.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/50.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/50.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/50.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/51.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/51.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/51.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/51.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/52.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/52.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/52.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/52.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/53.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/53.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/53.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/53.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/54.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/54.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/54.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/54.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/55.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/55.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/55.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/55.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/56.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/56.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/56.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/56.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/57.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/57.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/57.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/57.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/58.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/58.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/58.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/58.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/59.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/59.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/59.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/59.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/6.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/6.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/6.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/6.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/60.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/60.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/60.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/60.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/61.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/61.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/61.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/61.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/62.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/62.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/62.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/62.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/63.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/63.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/63.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/63.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/64.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/64.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/64.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/64.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/65.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/65.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/65.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/65.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/66.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/66.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/66.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/66.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/67.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/67.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/67.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/67.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/68.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/68.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/68.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/68.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/69.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/69.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/69.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/69.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/7.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/7.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/7.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/7.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/70.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/70.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/70.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/70.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/71.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/71.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/71.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/71.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/72.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/72.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/72.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/72.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/73.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/73.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/73.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/73.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/74.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/74.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/74.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/74.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/75.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/75.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/75.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/75.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/76.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/76.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/76.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/76.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/77.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/77.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/77.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/77.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/78.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/78.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/78.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/78.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/79.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/79.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/79.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/79.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/8.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/8.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/8.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/8.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/80.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/80.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/80.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/80.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/81.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/81.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/81.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/81.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/82.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/82.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/82.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/82.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/83.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/83.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/83.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/83.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/84.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/84.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/84.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/84.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/85.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/85.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/85.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/85.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/86.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/86.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/86.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/86.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/87.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/87.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/87.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/87.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/88.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/88.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/88.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/88.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/89.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/89.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/89.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/89.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/9.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/9.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/9.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/9.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/90.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/90.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/90.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/90.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/91.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/91.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/91.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/91.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/92.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/92.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/92.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/92.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/93.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/93.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/93.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/93.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/94.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/94.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/94.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/94.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/95.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/95.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/95.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/95.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/96.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/96.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/96.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/96.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/97.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/97.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/97.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/97.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/98.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/98.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/98.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/98.png
diff --git a/legacyworlds-web-main/Content/Raw/img/pp/s/99.png b/legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/99.png
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/img/pp/s/99.png
rename to legacyworlds-web/legacyworlds-web-main/WebContent/img/pp/s/99.png
diff --git a/legacyworlds-web/legacyworlds-web-main/WebContent/js/jquery-1.4.2.min.js b/legacyworlds-web/legacyworlds-web-main/WebContent/js/jquery-1.4.2.min.js
new file mode 100644
index 0000000..7c24308
--- /dev/null
+++ b/legacyworlds-web/legacyworlds-web-main/WebContent/js/jquery-1.4.2.min.js
@@ -0,0 +1,154 @@
+/*!
+ * jQuery JavaScript Library v1.4.2
+ * http://jquery.com/
+ *
+ * Copyright 2010, John Resig
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
+ *
+ * Includes Sizzle.js
+ * http://sizzlejs.com/
+ * Copyright 2010, The Dojo Foundation
+ * Released under the MIT, BSD, and GPL Licenses.
+ *
+ * Date: Sat Feb 13 22:33:48 2010 -0500
+ */
+(function(A,w){function ma(){if(!c.isReady){try{s.documentElement.doScroll("left")}catch(a){setTimeout(ma,1);return}c.ready()}}function Qa(a,b){b.src?c.ajax({url:b.src,async:false,dataType:"script"}):c.globalEval(b.text||b.textContent||b.innerHTML||"");b.parentNode&&b.parentNode.removeChild(b)}function X(a,b,d,f,e,j){var i=a.length;if(typeof b==="object"){for(var o in b)X(a,o,b[o],f,e,d);return a}if(d!==w){f=!j&&f&&c.isFunction(d);for(o=0;o<i;o++)e(a[o],b,f?d.call(a[o],o,e(a[o],b)):d,j);return a}return i?
+e(a[0],b):w}function J(){return(new Date).getTime()}function Y(){return false}function Z(){return true}function na(a,b,d){d[0].type=a;return c.event.handle.apply(b,d)}function oa(a){var b,d=[],f=[],e=arguments,j,i,o,k,n,r;i=c.data(this,"events");if(!(a.liveFired===this||!i||!i.live||a.button&&a.type==="click")){a.liveFired=this;var u=i.live.slice(0);for(k=0;k<u.length;k++){i=u[k];i.origType.replace(O,"")===a.type?f.push(i.selector):u.splice(k--,1)}j=c(a.target).closest(f,a.currentTarget);n=0;for(r=
+j.length;n<r;n++)for(k=0;k<u.length;k++){i=u[k];if(j[n].selector===i.selector){o=j[n].elem;f=null;if(i.preType==="mouseenter"||i.preType==="mouseleave")f=c(a.relatedTarget).closest(i.selector)[0];if(!f||f!==o)d.push({elem:o,handleObj:i})}}n=0;for(r=d.length;n<r;n++){j=d[n];a.currentTarget=j.elem;a.data=j.handleObj.data;a.handleObj=j.handleObj;if(j.handleObj.origHandler.apply(j.elem,e)===false){b=false;break}}return b}}function pa(a,b){return"live."+(a&&a!=="*"?a+".":"")+b.replace(/\./g,"`").replace(/ /g,
+"&")}function qa(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function ra(a,b){var d=0;b.each(function(){if(this.nodeName===(a[d]&&a[d].nodeName)){var f=c.data(a[d++]),e=c.data(this,f);if(f=f&&f.events){delete e.handle;e.events={};for(var j in f)for(var i in f[j])c.event.add(this,j,f[j][i],f[j][i].data)}}})}function sa(a,b,d){var f,e,j;b=b&&b[0]?b[0].ownerDocument||b[0]:s;if(a.length===1&&typeof a[0]==="string"&&a[0].length<512&&b===s&&!ta.test(a[0])&&(c.support.checkClone||!ua.test(a[0]))){e=
+true;if(j=c.fragments[a[0]])if(j!==1)f=j}if(!f){f=b.createDocumentFragment();c.clean(a,b,f,d)}if(e)c.fragments[a[0]]=j?f:1;return{fragment:f,cacheable:e}}function K(a,b){var d={};c.each(va.concat.apply([],va.slice(0,b)),function(){d[this]=a});return d}function wa(a){return"scrollTo"in a&&a.document?a:a.nodeType===9?a.defaultView||a.parentWindow:false}var c=function(a,b){return new c.fn.init(a,b)},Ra=A.jQuery,Sa=A.$,s=A.document,T,Ta=/^[^<]*(<[\w\W]+>)[^>]*$|^#([\w-]+)$/,Ua=/^.[^:#\[\.,]*$/,Va=/\S/,
+Wa=/^(\s|\u00A0)+|(\s|\u00A0)+$/g,Xa=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,P=navigator.userAgent,xa=false,Q=[],L,$=Object.prototype.toString,aa=Object.prototype.hasOwnProperty,ba=Array.prototype.push,R=Array.prototype.slice,ya=Array.prototype.indexOf;c.fn=c.prototype={init:function(a,b){var d,f;if(!a)return this;if(a.nodeType){this.context=this[0]=a;this.length=1;return this}if(a==="body"&&!b){this.context=s;this[0]=s.body;this.selector="body";this.length=1;return this}if(typeof a==="string")if((d=Ta.exec(a))&&
+(d[1]||!b))if(d[1]){f=b?b.ownerDocument||b:s;if(a=Xa.exec(a))if(c.isPlainObject(b)){a=[s.createElement(a[1])];c.fn.attr.call(a,b,true)}else a=[f.createElement(a[1])];else{a=sa([d[1]],[f]);a=(a.cacheable?a.fragment.cloneNode(true):a.fragment).childNodes}return c.merge(this,a)}else{if(b=s.getElementById(d[2])){if(b.id!==d[2])return T.find(a);this.length=1;this[0]=b}this.context=s;this.selector=a;return this}else if(!b&&/^\w+$/.test(a)){this.selector=a;this.context=s;a=s.getElementsByTagName(a);return c.merge(this,
+a)}else return!b||b.jquery?(b||T).find(a):c(b).find(a);else if(c.isFunction(a))return T.ready(a);if(a.selector!==w){this.selector=a.selector;this.context=a.context}return c.makeArray(a,this)},selector:"",jquery:"1.4.2",length:0,size:function(){return this.length},toArray:function(){return R.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this.slice(a)[0]:this[a]},pushStack:function(a,b,d){var f=c();c.isArray(a)?ba.apply(f,a):c.merge(f,a);f.prevObject=this;f.context=this.context;if(b===
+"find")f.selector=this.selector+(this.selector?" ":"")+d;else if(b)f.selector=this.selector+"."+b+"("+d+")";return f},each:function(a,b){return c.each(this,a,b)},ready:function(a){c.bindReady();if(c.isReady)a.call(s,c);else Q&&Q.push(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(R.apply(this,arguments),"slice",R.call(arguments).join(","))},map:function(a){return this.pushStack(c.map(this,
+function(b,d){return a.call(b,d,b)}))},end:function(){return this.prevObject||c(null)},push:ba,sort:[].sort,splice:[].splice};c.fn.init.prototype=c.fn;c.extend=c.fn.extend=function(){var a=arguments[0]||{},b=1,d=arguments.length,f=false,e,j,i,o;if(typeof a==="boolean"){f=a;a=arguments[1]||{};b=2}if(typeof a!=="object"&&!c.isFunction(a))a={};if(d===b){a=this;--b}for(;b<d;b++)if((e=arguments[b])!=null)for(j in e){i=a[j];o=e[j];if(a!==o)if(f&&o&&(c.isPlainObject(o)||c.isArray(o))){i=i&&(c.isPlainObject(i)||
+c.isArray(i))?i:c.isArray(o)?[]:{};a[j]=c.extend(f,i,o)}else if(o!==w)a[j]=o}return a};c.extend({noConflict:function(a){A.$=Sa;if(a)A.jQuery=Ra;return c},isReady:false,ready:function(){if(!c.isReady){if(!s.body)return setTimeout(c.ready,13);c.isReady=true;if(Q){for(var a,b=0;a=Q[b++];)a.call(s,c);Q=null}c.fn.triggerHandler&&c(s).triggerHandler("ready")}},bindReady:function(){if(!xa){xa=true;if(s.readyState==="complete")return c.ready();if(s.addEventListener){s.addEventListener("DOMContentLoaded",
+L,false);A.addEventListener("load",c.ready,false)}else if(s.attachEvent){s.attachEvent("onreadystatechange",L);A.attachEvent("onload",c.ready);var a=false;try{a=A.frameElement==null}catch(b){}s.documentElement.doScroll&&a&&ma()}}},isFunction:function(a){return $.call(a)==="[object Function]"},isArray:function(a){return $.call(a)==="[object Array]"},isPlainObject:function(a){if(!a||$.call(a)!=="[object Object]"||a.nodeType||a.setInterval)return false;if(a.constructor&&!aa.call(a,"constructor")&&!aa.call(a.constructor.prototype,
+"isPrototypeOf"))return false;var b;for(b in a);return b===w||aa.call(a,b)},isEmptyObject:function(a){for(var b in a)return false;return true},error:function(a){throw a;},parseJSON:function(a){if(typeof a!=="string"||!a)return null;a=c.trim(a);if(/^[\],:{}\s]*$/.test(a.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,"")))return A.JSON&&A.JSON.parse?A.JSON.parse(a):(new Function("return "+
+a))();else c.error("Invalid JSON: "+a)},noop:function(){},globalEval:function(a){if(a&&Va.test(a)){var b=s.getElementsByTagName("head")[0]||s.documentElement,d=s.createElement("script");d.type="text/javascript";if(c.support.scriptEval)d.appendChild(s.createTextNode(a));else d.text=a;b.insertBefore(d,b.firstChild);b.removeChild(d)}},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,b,d){var f,e=0,j=a.length,i=j===w||c.isFunction(a);if(d)if(i)for(f in a){if(b.apply(a[f],
+d)===false)break}else for(;e<j;){if(b.apply(a[e++],d)===false)break}else if(i)for(f in a){if(b.call(a[f],f,a[f])===false)break}else for(d=a[0];e<j&&b.call(d,e,d)!==false;d=a[++e]);return a},trim:function(a){return(a||"").replace(Wa,"")},makeArray:function(a,b){b=b||[];if(a!=null)a.length==null||typeof a==="string"||c.isFunction(a)||typeof a!=="function"&&a.setInterval?ba.call(b,a):c.merge(b,a);return b},inArray:function(a,b){if(b.indexOf)return b.indexOf(a);for(var d=0,f=b.length;d<f;d++)if(b[d]===
+a)return d;return-1},merge:function(a,b){var d=a.length,f=0;if(typeof b.length==="number")for(var e=b.length;f<e;f++)a[d++]=b[f];else for(;b[f]!==w;)a[d++]=b[f++];a.length=d;return a},grep:function(a,b,d){for(var f=[],e=0,j=a.length;e<j;e++)!d!==!b(a[e],e)&&f.push(a[e]);return f},map:function(a,b,d){for(var f=[],e,j=0,i=a.length;j<i;j++){e=b(a[j],j,d);if(e!=null)f[f.length]=e}return f.concat.apply([],f)},guid:1,proxy:function(a,b,d){if(arguments.length===2)if(typeof b==="string"){d=a;a=d[b];b=w}else if(b&&
+!c.isFunction(b)){d=b;b=w}if(!b&&a)b=function(){return a.apply(d||this,arguments)};if(a)b.guid=a.guid=a.guid||b.guid||c.guid++;return b},uaMatch:function(a){a=a.toLowerCase();a=/(webkit)[ \/]([\w.]+)/.exec(a)||/(opera)(?:.*version)?[ \/]([\w.]+)/.exec(a)||/(msie) ([\w.]+)/.exec(a)||!/compatible/.test(a)&&/(mozilla)(?:.*? rv:([\w.]+))?/.exec(a)||[];return{browser:a[1]||"",version:a[2]||"0"}},browser:{}});P=c.uaMatch(P);if(P.browser){c.browser[P.browser]=true;c.browser.version=P.version}if(c.browser.webkit)c.browser.safari=
+true;if(ya)c.inArray=function(a,b){return ya.call(b,a)};T=c(s);if(s.addEventListener)L=function(){s.removeEventListener("DOMContentLoaded",L,false);c.ready()};else if(s.attachEvent)L=function(){if(s.readyState==="complete"){s.detachEvent("onreadystatechange",L);c.ready()}};(function(){c.support={};var a=s.documentElement,b=s.createElement("script"),d=s.createElement("div"),f="script"+J();d.style.display="none";d.innerHTML="   <link/><table></table><a href='/a' style='color:red;float:left;opacity:.55;'>a</a><input type='checkbox'/>";
+var e=d.getElementsByTagName("*"),j=d.getElementsByTagName("a")[0];if(!(!e||!e.length||!j)){c.support={leadingWhitespace:d.firstChild.nodeType===3,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/red/.test(j.getAttribute("style")),hrefNormalized:j.getAttribute("href")==="/a",opacity:/^0.55$/.test(j.style.opacity),cssFloat:!!j.style.cssFloat,checkOn:d.getElementsByTagName("input")[0].value==="on",optSelected:s.createElement("select").appendChild(s.createElement("option")).selected,
+parentNode:d.removeChild(d.appendChild(s.createElement("div"))).parentNode===null,deleteExpando:true,checkClone:false,scriptEval:false,noCloneEvent:true,boxModel:null};b.type="text/javascript";try{b.appendChild(s.createTextNode("window."+f+"=1;"))}catch(i){}a.insertBefore(b,a.firstChild);if(A[f]){c.support.scriptEval=true;delete A[f]}try{delete b.test}catch(o){c.support.deleteExpando=false}a.removeChild(b);if(d.attachEvent&&d.fireEvent){d.attachEvent("onclick",function k(){c.support.noCloneEvent=
+false;d.detachEvent("onclick",k)});d.cloneNode(true).fireEvent("onclick")}d=s.createElement("div");d.innerHTML="<input type='radio' name='radiotest' checked='checked'/>";a=s.createDocumentFragment();a.appendChild(d.firstChild);c.support.checkClone=a.cloneNode(true).cloneNode(true).lastChild.checked;c(function(){var k=s.createElement("div");k.style.width=k.style.paddingLeft="1px";s.body.appendChild(k);c.boxModel=c.support.boxModel=k.offsetWidth===2;s.body.removeChild(k).style.display="none"});a=function(k){var n=
+s.createElement("div");k="on"+k;var r=k in n;if(!r){n.setAttribute(k,"return;");r=typeof n[k]==="function"}return r};c.support.submitBubbles=a("submit");c.support.changeBubbles=a("change");a=b=d=e=j=null}})();c.props={"for":"htmlFor","class":"className",readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",colspan:"colSpan",tabindex:"tabIndex",usemap:"useMap",frameborder:"frameBorder"};var G="jQuery"+J(),Ya=0,za={};c.extend({cache:{},expando:G,noData:{embed:true,object:true,
+applet:true},data:function(a,b,d){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var f=a[G],e=c.cache;if(!f&&typeof b==="string"&&d===w)return null;f||(f=++Ya);if(typeof b==="object"){a[G]=f;e[f]=c.extend(true,{},b)}else if(!e[f]){a[G]=f;e[f]={}}a=e[f];if(d!==w)a[b]=d;return typeof b==="string"?a[b]:a}},removeData:function(a,b){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var d=a[G],f=c.cache,e=f[d];if(b){if(e){delete e[b];c.isEmptyObject(e)&&c.removeData(a)}}else{if(c.support.deleteExpando)delete a[c.expando];
+else a.removeAttribute&&a.removeAttribute(c.expando);delete f[d]}}}});c.fn.extend({data:function(a,b){if(typeof a==="undefined"&&this.length)return c.data(this[0]);else if(typeof a==="object")return this.each(function(){c.data(this,a)});var d=a.split(".");d[1]=d[1]?"."+d[1]:"";if(b===w){var f=this.triggerHandler("getData"+d[1]+"!",[d[0]]);if(f===w&&this.length)f=c.data(this[0],a);return f===w&&d[1]?this.data(d[0]):f}else return this.trigger("setData"+d[1]+"!",[d[0],b]).each(function(){c.data(this,
+a,b)})},removeData:function(a){return this.each(function(){c.removeData(this,a)})}});c.extend({queue:function(a,b,d){if(a){b=(b||"fx")+"queue";var f=c.data(a,b);if(!d)return f||[];if(!f||c.isArray(d))f=c.data(a,b,c.makeArray(d));else f.push(d);return f}},dequeue:function(a,b){b=b||"fx";var d=c.queue(a,b),f=d.shift();if(f==="inprogress")f=d.shift();if(f){b==="fx"&&d.unshift("inprogress");f.call(a,function(){c.dequeue(a,b)})}}});c.fn.extend({queue:function(a,b){if(typeof a!=="string"){b=a;a="fx"}if(b===
+w)return c.queue(this[0],a);return this.each(function(){var d=c.queue(this,a,b);a==="fx"&&d[0]!=="inprogress"&&c.dequeue(this,a)})},dequeue:function(a){return this.each(function(){c.dequeue(this,a)})},delay:function(a,b){a=c.fx?c.fx.speeds[a]||a:a;b=b||"fx";return this.queue(b,function(){var d=this;setTimeout(function(){c.dequeue(d,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])}});var Aa=/[\n\t]/g,ca=/\s+/,Za=/\r/g,$a=/href|src|style/,ab=/(button|input)/i,bb=/(button|input|object|select|textarea)/i,
+cb=/^(a|area)$/i,Ba=/radio|checkbox/;c.fn.extend({attr:function(a,b){return X(this,a,b,true,c.attr)},removeAttr:function(a){return this.each(function(){c.attr(this,a,"");this.nodeType===1&&this.removeAttribute(a)})},addClass:function(a){if(c.isFunction(a))return this.each(function(n){var r=c(this);r.addClass(a.call(this,n,r.attr("class")))});if(a&&typeof a==="string")for(var b=(a||"").split(ca),d=0,f=this.length;d<f;d++){var e=this[d];if(e.nodeType===1)if(e.className){for(var j=" "+e.className+" ",
+i=e.className,o=0,k=b.length;o<k;o++)if(j.indexOf(" "+b[o]+" ")<0)i+=" "+b[o];e.className=c.trim(i)}else e.className=a}return this},removeClass:function(a){if(c.isFunction(a))return this.each(function(k){var n=c(this);n.removeClass(a.call(this,k,n.attr("class")))});if(a&&typeof a==="string"||a===w)for(var b=(a||"").split(ca),d=0,f=this.length;d<f;d++){var e=this[d];if(e.nodeType===1&&e.className)if(a){for(var j=(" "+e.className+" ").replace(Aa," "),i=0,o=b.length;i<o;i++)j=j.replace(" "+b[i]+" ",
+" ");e.className=c.trim(j)}else e.className=""}return this},toggleClass:function(a,b){var d=typeof a,f=typeof b==="boolean";if(c.isFunction(a))return this.each(function(e){var j=c(this);j.toggleClass(a.call(this,e,j.attr("class"),b),b)});return this.each(function(){if(d==="string")for(var e,j=0,i=c(this),o=b,k=a.split(ca);e=k[j++];){o=f?o:!i.hasClass(e);i[o?"addClass":"removeClass"](e)}else if(d==="undefined"||d==="boolean"){this.className&&c.data(this,"__className__",this.className);this.className=
+this.className||a===false?"":c.data(this,"__className__")||""}})},hasClass:function(a){a=" "+a+" ";for(var b=0,d=this.length;b<d;b++)if((" "+this[b].className+" ").replace(Aa," ").indexOf(a)>-1)return true;return false},val:function(a){if(a===w){var b=this[0];if(b){if(c.nodeName(b,"option"))return(b.attributes.value||{}).specified?b.value:b.text;if(c.nodeName(b,"select")){var d=b.selectedIndex,f=[],e=b.options;b=b.type==="select-one";if(d<0)return null;var j=b?d:0;for(d=b?d+1:e.length;j<d;j++){var i=
+e[j];if(i.selected){a=c(i).val();if(b)return a;f.push(a)}}return f}if(Ba.test(b.type)&&!c.support.checkOn)return b.getAttribute("value")===null?"on":b.value;return(b.value||"").replace(Za,"")}return w}var o=c.isFunction(a);return this.each(function(k){var n=c(this),r=a;if(this.nodeType===1){if(o)r=a.call(this,k,n.val());if(typeof r==="number")r+="";if(c.isArray(r)&&Ba.test(this.type))this.checked=c.inArray(n.val(),r)>=0;else if(c.nodeName(this,"select")){var u=c.makeArray(r);c("option",this).each(function(){this.selected=
+c.inArray(c(this).val(),u)>=0});if(!u.length)this.selectedIndex=-1}else this.value=r}})}});c.extend({attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(a,b,d,f){if(!a||a.nodeType===3||a.nodeType===8)return w;if(f&&b in c.attrFn)return c(a)[b](d);f=a.nodeType!==1||!c.isXMLDoc(a);var e=d!==w;b=f&&c.props[b]||b;if(a.nodeType===1){var j=$a.test(b);if(b in a&&f&&!j){if(e){b==="type"&&ab.test(a.nodeName)&&a.parentNode&&c.error("type property can't be changed");
+a[b]=d}if(c.nodeName(a,"form")&&a.getAttributeNode(b))return a.getAttributeNode(b).nodeValue;if(b==="tabIndex")return(b=a.getAttributeNode("tabIndex"))&&b.specified?b.value:bb.test(a.nodeName)||cb.test(a.nodeName)&&a.href?0:w;return a[b]}if(!c.support.style&&f&&b==="style"){if(e)a.style.cssText=""+d;return a.style.cssText}e&&a.setAttribute(b,""+d);a=!c.support.hrefNormalized&&f&&j?a.getAttribute(b,2):a.getAttribute(b);return a===null?w:a}return c.style(a,b,d)}});var O=/\.(.*)$/,db=function(a){return a.replace(/[^\w\s\.\|`]/g,
+function(b){return"\\"+b})};c.event={add:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){if(a.setInterval&&a!==A&&!a.frameElement)a=A;var e,j;if(d.handler){e=d;d=e.handler}if(!d.guid)d.guid=c.guid++;if(j=c.data(a)){var i=j.events=j.events||{},o=j.handle;if(!o)j.handle=o=function(){return typeof c!=="undefined"&&!c.event.triggered?c.event.handle.apply(o.elem,arguments):w};o.elem=a;b=b.split(" ");for(var k,n=0,r;k=b[n++];){j=e?c.extend({},e):{handler:d,data:f};if(k.indexOf(".")>-1){r=k.split(".");
+k=r.shift();j.namespace=r.slice(0).sort().join(".")}else{r=[];j.namespace=""}j.type=k;j.guid=d.guid;var u=i[k],z=c.event.special[k]||{};if(!u){u=i[k]=[];if(!z.setup||z.setup.call(a,f,r,o)===false)if(a.addEventListener)a.addEventListener(k,o,false);else a.attachEvent&&a.attachEvent("on"+k,o)}if(z.add){z.add.call(a,j);if(!j.handler.guid)j.handler.guid=d.guid}u.push(j);c.event.global[k]=true}a=null}}},global:{},remove:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){var e,j=0,i,o,k,n,r,u,z=c.data(a),
+C=z&&z.events;if(z&&C){if(b&&b.type){d=b.handler;b=b.type}if(!b||typeof b==="string"&&b.charAt(0)==="."){b=b||"";for(e in C)c.event.remove(a,e+b)}else{for(b=b.split(" ");e=b[j++];){n=e;i=e.indexOf(".")<0;o=[];if(!i){o=e.split(".");e=o.shift();k=new RegExp("(^|\\.)"+c.map(o.slice(0).sort(),db).join("\\.(?:.*\\.)?")+"(\\.|$)")}if(r=C[e])if(d){n=c.event.special[e]||{};for(B=f||0;B<r.length;B++){u=r[B];if(d.guid===u.guid){if(i||k.test(u.namespace)){f==null&&r.splice(B--,1);n.remove&&n.remove.call(a,u)}if(f!=
+null)break}}if(r.length===0||f!=null&&r.length===1){if(!n.teardown||n.teardown.call(a,o)===false)Ca(a,e,z.handle);delete C[e]}}else for(var B=0;B<r.length;B++){u=r[B];if(i||k.test(u.namespace)){c.event.remove(a,n,u.handler,B);r.splice(B--,1)}}}if(c.isEmptyObject(C)){if(b=z.handle)b.elem=null;delete z.events;delete z.handle;c.isEmptyObject(z)&&c.removeData(a)}}}}},trigger:function(a,b,d,f){var e=a.type||a;if(!f){a=typeof a==="object"?a[G]?a:c.extend(c.Event(e),a):c.Event(e);if(e.indexOf("!")>=0){a.type=
+e=e.slice(0,-1);a.exclusive=true}if(!d){a.stopPropagation();c.event.global[e]&&c.each(c.cache,function(){this.events&&this.events[e]&&c.event.trigger(a,b,this.handle.elem)})}if(!d||d.nodeType===3||d.nodeType===8)return w;a.result=w;a.target=d;b=c.makeArray(b);b.unshift(a)}a.currentTarget=d;(f=c.data(d,"handle"))&&f.apply(d,b);f=d.parentNode||d.ownerDocument;try{if(!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()]))if(d["on"+e]&&d["on"+e].apply(d,b)===false)a.result=false}catch(j){}if(!a.isPropagationStopped()&&
+f)c.event.trigger(a,b,f,true);else if(!a.isDefaultPrevented()){f=a.target;var i,o=c.nodeName(f,"a")&&e==="click",k=c.event.special[e]||{};if((!k._default||k._default.call(d,a)===false)&&!o&&!(f&&f.nodeName&&c.noData[f.nodeName.toLowerCase()])){try{if(f[e]){if(i=f["on"+e])f["on"+e]=null;c.event.triggered=true;f[e]()}}catch(n){}if(i)f["on"+e]=i;c.event.triggered=false}}},handle:function(a){var b,d,f,e;a=arguments[0]=c.event.fix(a||A.event);a.currentTarget=this;b=a.type.indexOf(".")<0&&!a.exclusive;
+if(!b){d=a.type.split(".");a.type=d.shift();f=new RegExp("(^|\\.)"+d.slice(0).sort().join("\\.(?:.*\\.)?")+"(\\.|$)")}e=c.data(this,"events");d=e[a.type];if(e&&d){d=d.slice(0);e=0;for(var j=d.length;e<j;e++){var i=d[e];if(b||f.test(i.namespace)){a.handler=i.handler;a.data=i.data;a.handleObj=i;i=i.handler.apply(this,arguments);if(i!==w){a.result=i;if(i===false){a.preventDefault();a.stopPropagation()}}if(a.isImmediatePropagationStopped())break}}}return a.result},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),
+fix:function(a){if(a[G])return a;var b=a;a=c.Event(b);for(var d=this.props.length,f;d;){f=this.props[--d];a[f]=b[f]}if(!a.target)a.target=a.srcElement||s;if(a.target.nodeType===3)a.target=a.target.parentNode;if(!a.relatedTarget&&a.fromElement)a.relatedTarget=a.fromElement===a.target?a.toElement:a.fromElement;if(a.pageX==null&&a.clientX!=null){b=s.documentElement;d=s.body;a.pageX=a.clientX+(b&&b.scrollLeft||d&&d.scrollLeft||0)-(b&&b.clientLeft||d&&d.clientLeft||0);a.pageY=a.clientY+(b&&b.scrollTop||
+d&&d.scrollTop||0)-(b&&b.clientTop||d&&d.clientTop||0)}if(!a.which&&(a.charCode||a.charCode===0?a.charCode:a.keyCode))a.which=a.charCode||a.keyCode;if(!a.metaKey&&a.ctrlKey)a.metaKey=a.ctrlKey;if(!a.which&&a.button!==w)a.which=a.button&1?1:a.button&2?3:a.button&4?2:0;return a},guid:1E8,proxy:c.proxy,special:{ready:{setup:c.bindReady,teardown:c.noop},live:{add:function(a){c.event.add(this,a.origType,c.extend({},a,{handler:oa}))},remove:function(a){var b=true,d=a.origType.replace(O,"");c.each(c.data(this,
+"events").live||[],function(){if(d===this.origType.replace(O,""))return b=false});b&&c.event.remove(this,a.origType,oa)}},beforeunload:{setup:function(a,b,d){if(this.setInterval)this.onbeforeunload=d;return false},teardown:function(a,b){if(this.onbeforeunload===b)this.onbeforeunload=null}}}};var Ca=s.removeEventListener?function(a,b,d){a.removeEventListener(b,d,false)}:function(a,b,d){a.detachEvent("on"+b,d)};c.Event=function(a){if(!this.preventDefault)return new c.Event(a);if(a&&a.type){this.originalEvent=
+a;this.type=a.type}else this.type=a;this.timeStamp=J();this[G]=true};c.Event.prototype={preventDefault:function(){this.isDefaultPrevented=Z;var a=this.originalEvent;if(a){a.preventDefault&&a.preventDefault();a.returnValue=false}},stopPropagation:function(){this.isPropagationStopped=Z;var a=this.originalEvent;if(a){a.stopPropagation&&a.stopPropagation();a.cancelBubble=true}},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=Z;this.stopPropagation()},isDefaultPrevented:Y,isPropagationStopped:Y,
+isImmediatePropagationStopped:Y};var Da=function(a){var b=a.relatedTarget;try{for(;b&&b!==this;)b=b.parentNode;if(b!==this){a.type=a.data;c.event.handle.apply(this,arguments)}}catch(d){}},Ea=function(a){a.type=a.data;c.event.handle.apply(this,arguments)};c.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){c.event.special[a]={setup:function(d){c.event.add(this,b,d&&d.selector?Ea:Da,a)},teardown:function(d){c.event.remove(this,b,d&&d.selector?Ea:Da)}}});if(!c.support.submitBubbles)c.event.special.submit=
+{setup:function(){if(this.nodeName.toLowerCase()!=="form"){c.event.add(this,"click.specialSubmit",function(a){var b=a.target,d=b.type;if((d==="submit"||d==="image")&&c(b).closest("form").length)return na("submit",this,arguments)});c.event.add(this,"keypress.specialSubmit",function(a){var b=a.target,d=b.type;if((d==="text"||d==="password")&&c(b).closest("form").length&&a.keyCode===13)return na("submit",this,arguments)})}else return false},teardown:function(){c.event.remove(this,".specialSubmit")}};
+if(!c.support.changeBubbles){var da=/textarea|input|select/i,ea,Fa=function(a){var b=a.type,d=a.value;if(b==="radio"||b==="checkbox")d=a.checked;else if(b==="select-multiple")d=a.selectedIndex>-1?c.map(a.options,function(f){return f.selected}).join("-"):"";else if(a.nodeName.toLowerCase()==="select")d=a.selectedIndex;return d},fa=function(a,b){var d=a.target,f,e;if(!(!da.test(d.nodeName)||d.readOnly)){f=c.data(d,"_change_data");e=Fa(d);if(a.type!=="focusout"||d.type!=="radio")c.data(d,"_change_data",
+e);if(!(f===w||e===f))if(f!=null||e){a.type="change";return c.event.trigger(a,b,d)}}};c.event.special.change={filters:{focusout:fa,click:function(a){var b=a.target,d=b.type;if(d==="radio"||d==="checkbox"||b.nodeName.toLowerCase()==="select")return fa.call(this,a)},keydown:function(a){var b=a.target,d=b.type;if(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(d==="checkbox"||d==="radio")||d==="select-multiple")return fa.call(this,a)},beforeactivate:function(a){a=a.target;c.data(a,
+"_change_data",Fa(a))}},setup:function(){if(this.type==="file")return false;for(var a in ea)c.event.add(this,a+".specialChange",ea[a]);return da.test(this.nodeName)},teardown:function(){c.event.remove(this,".specialChange");return da.test(this.nodeName)}};ea=c.event.special.change.filters}s.addEventListener&&c.each({focus:"focusin",blur:"focusout"},function(a,b){function d(f){f=c.event.fix(f);f.type=b;return c.event.handle.call(this,f)}c.event.special[b]={setup:function(){this.addEventListener(a,
+d,true)},teardown:function(){this.removeEventListener(a,d,true)}}});c.each(["bind","one"],function(a,b){c.fn[b]=function(d,f,e){if(typeof d==="object"){for(var j in d)this[b](j,f,d[j],e);return this}if(c.isFunction(f)){e=f;f=w}var i=b==="one"?c.proxy(e,function(k){c(this).unbind(k,i);return e.apply(this,arguments)}):e;if(d==="unload"&&b!=="one")this.one(d,f,e);else{j=0;for(var o=this.length;j<o;j++)c.event.add(this[j],d,i,f)}return this}});c.fn.extend({unbind:function(a,b){if(typeof a==="object"&&
+!a.preventDefault)for(var d in a)this.unbind(d,a[d]);else{d=0;for(var f=this.length;d<f;d++)c.event.remove(this[d],a,b)}return this},delegate:function(a,b,d,f){return this.live(b,d,f,a)},undelegate:function(a,b,d){return arguments.length===0?this.unbind("live"):this.die(b,null,d,a)},trigger:function(a,b){return this.each(function(){c.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0]){a=c.Event(a);a.preventDefault();a.stopPropagation();c.event.trigger(a,b,this[0]);return a.result}},
+toggle:function(a){for(var b=arguments,d=1;d<b.length;)c.proxy(a,b[d++]);return this.click(c.proxy(a,function(f){var e=(c.data(this,"lastToggle"+a.guid)||0)%d;c.data(this,"lastToggle"+a.guid,e+1);f.preventDefault();return b[e].apply(this,arguments)||false}))},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}});var Ga={focus:"focusin",blur:"focusout",mouseenter:"mouseover",mouseleave:"mouseout"};c.each(["live","die"],function(a,b){c.fn[b]=function(d,f,e,j){var i,o=0,k,n,r=j||this.selector,
+u=j?this:c(this.context);if(c.isFunction(f)){e=f;f=w}for(d=(d||"").split(" ");(i=d[o++])!=null;){j=O.exec(i);k="";if(j){k=j[0];i=i.replace(O,"")}if(i==="hover")d.push("mouseenter"+k,"mouseleave"+k);else{n=i;if(i==="focus"||i==="blur"){d.push(Ga[i]+k);i+=k}else i=(Ga[i]||i)+k;b==="live"?u.each(function(){c.event.add(this,pa(i,r),{data:f,selector:r,handler:e,origType:i,origHandler:e,preType:n})}):u.unbind(pa(i,r),e)}}return this}});c.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error".split(" "),
+function(a,b){c.fn[b]=function(d){return d?this.bind(b,d):this.trigger(b)};if(c.attrFn)c.attrFn[b]=true});A.attachEvent&&!A.addEventListener&&A.attachEvent("onunload",function(){for(var a in c.cache)if(c.cache[a].handle)try{c.event.remove(c.cache[a].handle.elem)}catch(b){}});(function(){function a(g){for(var h="",l,m=0;g[m];m++){l=g[m];if(l.nodeType===3||l.nodeType===4)h+=l.nodeValue;else if(l.nodeType!==8)h+=a(l.childNodes)}return h}function b(g,h,l,m,q,p){q=0;for(var v=m.length;q<v;q++){var t=m[q];
+if(t){t=t[g];for(var y=false;t;){if(t.sizcache===l){y=m[t.sizset];break}if(t.nodeType===1&&!p){t.sizcache=l;t.sizset=q}if(t.nodeName.toLowerCase()===h){y=t;break}t=t[g]}m[q]=y}}}function d(g,h,l,m,q,p){q=0;for(var v=m.length;q<v;q++){var t=m[q];if(t){t=t[g];for(var y=false;t;){if(t.sizcache===l){y=m[t.sizset];break}if(t.nodeType===1){if(!p){t.sizcache=l;t.sizset=q}if(typeof h!=="string"){if(t===h){y=true;break}}else if(k.filter(h,[t]).length>0){y=t;break}}t=t[g]}m[q]=y}}}var f=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
+e=0,j=Object.prototype.toString,i=false,o=true;[0,0].sort(function(){o=false;return 0});var k=function(g,h,l,m){l=l||[];var q=h=h||s;if(h.nodeType!==1&&h.nodeType!==9)return[];if(!g||typeof g!=="string")return l;for(var p=[],v,t,y,S,H=true,M=x(h),I=g;(f.exec(""),v=f.exec(I))!==null;){I=v[3];p.push(v[1]);if(v[2]){S=v[3];break}}if(p.length>1&&r.exec(g))if(p.length===2&&n.relative[p[0]])t=ga(p[0]+p[1],h);else for(t=n.relative[p[0]]?[h]:k(p.shift(),h);p.length;){g=p.shift();if(n.relative[g])g+=p.shift();
+t=ga(g,t)}else{if(!m&&p.length>1&&h.nodeType===9&&!M&&n.match.ID.test(p[0])&&!n.match.ID.test(p[p.length-1])){v=k.find(p.shift(),h,M);h=v.expr?k.filter(v.expr,v.set)[0]:v.set[0]}if(h){v=m?{expr:p.pop(),set:z(m)}:k.find(p.pop(),p.length===1&&(p[0]==="~"||p[0]==="+")&&h.parentNode?h.parentNode:h,M);t=v.expr?k.filter(v.expr,v.set):v.set;if(p.length>0)y=z(t);else H=false;for(;p.length;){var D=p.pop();v=D;if(n.relative[D])v=p.pop();else D="";if(v==null)v=h;n.relative[D](y,v,M)}}else y=[]}y||(y=t);y||k.error(D||
+g);if(j.call(y)==="[object Array]")if(H)if(h&&h.nodeType===1)for(g=0;y[g]!=null;g++){if(y[g]&&(y[g]===true||y[g].nodeType===1&&E(h,y[g])))l.push(t[g])}else for(g=0;y[g]!=null;g++)y[g]&&y[g].nodeType===1&&l.push(t[g]);else l.push.apply(l,y);else z(y,l);if(S){k(S,q,l,m);k.uniqueSort(l)}return l};k.uniqueSort=function(g){if(B){i=o;g.sort(B);if(i)for(var h=1;h<g.length;h++)g[h]===g[h-1]&&g.splice(h--,1)}return g};k.matches=function(g,h){return k(g,null,null,h)};k.find=function(g,h,l){var m,q;if(!g)return[];
+for(var p=0,v=n.order.length;p<v;p++){var t=n.order[p];if(q=n.leftMatch[t].exec(g)){var y=q[1];q.splice(1,1);if(y.substr(y.length-1)!=="\\"){q[1]=(q[1]||"").replace(/\\/g,"");m=n.find[t](q,h,l);if(m!=null){g=g.replace(n.match[t],"");break}}}}m||(m=h.getElementsByTagName("*"));return{set:m,expr:g}};k.filter=function(g,h,l,m){for(var q=g,p=[],v=h,t,y,S=h&&h[0]&&x(h[0]);g&&h.length;){for(var H in n.filter)if((t=n.leftMatch[H].exec(g))!=null&&t[2]){var M=n.filter[H],I,D;D=t[1];y=false;t.splice(1,1);if(D.substr(D.length-
+1)!=="\\"){if(v===p)p=[];if(n.preFilter[H])if(t=n.preFilter[H](t,v,l,p,m,S)){if(t===true)continue}else y=I=true;if(t)for(var U=0;(D=v[U])!=null;U++)if(D){I=M(D,t,U,v);var Ha=m^!!I;if(l&&I!=null)if(Ha)y=true;else v[U]=false;else if(Ha){p.push(D);y=true}}if(I!==w){l||(v=p);g=g.replace(n.match[H],"");if(!y)return[];break}}}if(g===q)if(y==null)k.error(g);else break;q=g}return v};k.error=function(g){throw"Syntax error, unrecognized expression: "+g;};var n=k.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF-]|\\.)+)/,
+CLASS:/\.((?:[\w\u00c0-\uFFFF-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(g){return g.getAttribute("href")}},
+relative:{"+":function(g,h){var l=typeof h==="string",m=l&&!/\W/.test(h);l=l&&!m;if(m)h=h.toLowerCase();m=0;for(var q=g.length,p;m<q;m++)if(p=g[m]){for(;(p=p.previousSibling)&&p.nodeType!==1;);g[m]=l||p&&p.nodeName.toLowerCase()===h?p||false:p===h}l&&k.filter(h,g,true)},">":function(g,h){var l=typeof h==="string";if(l&&!/\W/.test(h)){h=h.toLowerCase();for(var m=0,q=g.length;m<q;m++){var p=g[m];if(p){l=p.parentNode;g[m]=l.nodeName.toLowerCase()===h?l:false}}}else{m=0;for(q=g.length;m<q;m++)if(p=g[m])g[m]=
+l?p.parentNode:p.parentNode===h;l&&k.filter(h,g,true)}},"":function(g,h,l){var m=e++,q=d;if(typeof h==="string"&&!/\W/.test(h)){var p=h=h.toLowerCase();q=b}q("parentNode",h,m,g,p,l)},"~":function(g,h,l){var m=e++,q=d;if(typeof h==="string"&&!/\W/.test(h)){var p=h=h.toLowerCase();q=b}q("previousSibling",h,m,g,p,l)}},find:{ID:function(g,h,l){if(typeof h.getElementById!=="undefined"&&!l)return(g=h.getElementById(g[1]))?[g]:[]},NAME:function(g,h){if(typeof h.getElementsByName!=="undefined"){var l=[];
+h=h.getElementsByName(g[1]);for(var m=0,q=h.length;m<q;m++)h[m].getAttribute("name")===g[1]&&l.push(h[m]);return l.length===0?null:l}},TAG:function(g,h){return h.getElementsByTagName(g[1])}},preFilter:{CLASS:function(g,h,l,m,q,p){g=" "+g[1].replace(/\\/g,"")+" ";if(p)return g;p=0;for(var v;(v=h[p])!=null;p++)if(v)if(q^(v.className&&(" "+v.className+" ").replace(/[\t\n]/g," ").indexOf(g)>=0))l||m.push(v);else if(l)h[p]=false;return false},ID:function(g){return g[1].replace(/\\/g,"")},TAG:function(g){return g[1].toLowerCase()},
+CHILD:function(g){if(g[1]==="nth"){var h=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(g[2]==="even"&&"2n"||g[2]==="odd"&&"2n+1"||!/\D/.test(g[2])&&"0n+"+g[2]||g[2]);g[2]=h[1]+(h[2]||1)-0;g[3]=h[3]-0}g[0]=e++;return g},ATTR:function(g,h,l,m,q,p){h=g[1].replace(/\\/g,"");if(!p&&n.attrMap[h])g[1]=n.attrMap[h];if(g[2]==="~=")g[4]=" "+g[4]+" ";return g},PSEUDO:function(g,h,l,m,q){if(g[1]==="not")if((f.exec(g[3])||"").length>1||/^\w/.test(g[3]))g[3]=k(g[3],null,null,h);else{g=k.filter(g[3],h,l,true^q);l||m.push.apply(m,
+g);return false}else if(n.match.POS.test(g[0])||n.match.CHILD.test(g[0]))return true;return g},POS:function(g){g.unshift(true);return g}},filters:{enabled:function(g){return g.disabled===false&&g.type!=="hidden"},disabled:function(g){return g.disabled===true},checked:function(g){return g.checked===true},selected:function(g){return g.selected===true},parent:function(g){return!!g.firstChild},empty:function(g){return!g.firstChild},has:function(g,h,l){return!!k(l[3],g).length},header:function(g){return/h\d/i.test(g.nodeName)},
+text:function(g){return"text"===g.type},radio:function(g){return"radio"===g.type},checkbox:function(g){return"checkbox"===g.type},file:function(g){return"file"===g.type},password:function(g){return"password"===g.type},submit:function(g){return"submit"===g.type},image:function(g){return"image"===g.type},reset:function(g){return"reset"===g.type},button:function(g){return"button"===g.type||g.nodeName.toLowerCase()==="button"},input:function(g){return/input|select|textarea|button/i.test(g.nodeName)}},
+setFilters:{first:function(g,h){return h===0},last:function(g,h,l,m){return h===m.length-1},even:function(g,h){return h%2===0},odd:function(g,h){return h%2===1},lt:function(g,h,l){return h<l[3]-0},gt:function(g,h,l){return h>l[3]-0},nth:function(g,h,l){return l[3]-0===h},eq:function(g,h,l){return l[3]-0===h}},filter:{PSEUDO:function(g,h,l,m){var q=h[1],p=n.filters[q];if(p)return p(g,l,h,m);else if(q==="contains")return(g.textContent||g.innerText||a([g])||"").indexOf(h[3])>=0;else if(q==="not"){h=
+h[3];l=0;for(m=h.length;l<m;l++)if(h[l]===g)return false;return true}else k.error("Syntax error, unrecognized expression: "+q)},CHILD:function(g,h){var l=h[1],m=g;switch(l){case "only":case "first":for(;m=m.previousSibling;)if(m.nodeType===1)return false;if(l==="first")return true;m=g;case "last":for(;m=m.nextSibling;)if(m.nodeType===1)return false;return true;case "nth":l=h[2];var q=h[3];if(l===1&&q===0)return true;h=h[0];var p=g.parentNode;if(p&&(p.sizcache!==h||!g.nodeIndex)){var v=0;for(m=p.firstChild;m;m=
+m.nextSibling)if(m.nodeType===1)m.nodeIndex=++v;p.sizcache=h}g=g.nodeIndex-q;return l===0?g===0:g%l===0&&g/l>=0}},ID:function(g,h){return g.nodeType===1&&g.getAttribute("id")===h},TAG:function(g,h){return h==="*"&&g.nodeType===1||g.nodeName.toLowerCase()===h},CLASS:function(g,h){return(" "+(g.className||g.getAttribute("class"))+" ").indexOf(h)>-1},ATTR:function(g,h){var l=h[1];g=n.attrHandle[l]?n.attrHandle[l](g):g[l]!=null?g[l]:g.getAttribute(l);l=g+"";var m=h[2];h=h[4];return g==null?m==="!=":m===
+"="?l===h:m==="*="?l.indexOf(h)>=0:m==="~="?(" "+l+" ").indexOf(h)>=0:!h?l&&g!==false:m==="!="?l!==h:m==="^="?l.indexOf(h)===0:m==="$="?l.substr(l.length-h.length)===h:m==="|="?l===h||l.substr(0,h.length+1)===h+"-":false},POS:function(g,h,l,m){var q=n.setFilters[h[2]];if(q)return q(g,l,h,m)}}},r=n.match.POS;for(var u in n.match){n.match[u]=new RegExp(n.match[u].source+/(?![^\[]*\])(?![^\(]*\))/.source);n.leftMatch[u]=new RegExp(/(^(?:.|\r|\n)*?)/.source+n.match[u].source.replace(/\\(\d+)/g,function(g,
+h){return"\\"+(h-0+1)}))}var z=function(g,h){g=Array.prototype.slice.call(g,0);if(h){h.push.apply(h,g);return h}return g};try{Array.prototype.slice.call(s.documentElement.childNodes,0)}catch(C){z=function(g,h){h=h||[];if(j.call(g)==="[object Array]")Array.prototype.push.apply(h,g);else if(typeof g.length==="number")for(var l=0,m=g.length;l<m;l++)h.push(g[l]);else for(l=0;g[l];l++)h.push(g[l]);return h}}var B;if(s.documentElement.compareDocumentPosition)B=function(g,h){if(!g.compareDocumentPosition||
+!h.compareDocumentPosition){if(g==h)i=true;return g.compareDocumentPosition?-1:1}g=g.compareDocumentPosition(h)&4?-1:g===h?0:1;if(g===0)i=true;return g};else if("sourceIndex"in s.documentElement)B=function(g,h){if(!g.sourceIndex||!h.sourceIndex){if(g==h)i=true;return g.sourceIndex?-1:1}g=g.sourceIndex-h.sourceIndex;if(g===0)i=true;return g};else if(s.createRange)B=function(g,h){if(!g.ownerDocument||!h.ownerDocument){if(g==h)i=true;return g.ownerDocument?-1:1}var l=g.ownerDocument.createRange(),m=
+h.ownerDocument.createRange();l.setStart(g,0);l.setEnd(g,0);m.setStart(h,0);m.setEnd(h,0);g=l.compareBoundaryPoints(Range.START_TO_END,m);if(g===0)i=true;return g};(function(){var g=s.createElement("div"),h="script"+(new Date).getTime();g.innerHTML="<a name='"+h+"'/>";var l=s.documentElement;l.insertBefore(g,l.firstChild);if(s.getElementById(h)){n.find.ID=function(m,q,p){if(typeof q.getElementById!=="undefined"&&!p)return(q=q.getElementById(m[1]))?q.id===m[1]||typeof q.getAttributeNode!=="undefined"&&
+q.getAttributeNode("id").nodeValue===m[1]?[q]:w:[]};n.filter.ID=function(m,q){var p=typeof m.getAttributeNode!=="undefined"&&m.getAttributeNode("id");return m.nodeType===1&&p&&p.nodeValue===q}}l.removeChild(g);l=g=null})();(function(){var g=s.createElement("div");g.appendChild(s.createComment(""));if(g.getElementsByTagName("*").length>0)n.find.TAG=function(h,l){l=l.getElementsByTagName(h[1]);if(h[1]==="*"){h=[];for(var m=0;l[m];m++)l[m].nodeType===1&&h.push(l[m]);l=h}return l};g.innerHTML="<a href='#'></a>";
+if(g.firstChild&&typeof g.firstChild.getAttribute!=="undefined"&&g.firstChild.getAttribute("href")!=="#")n.attrHandle.href=function(h){return h.getAttribute("href",2)};g=null})();s.querySelectorAll&&function(){var g=k,h=s.createElement("div");h.innerHTML="<p class='TEST'></p>";if(!(h.querySelectorAll&&h.querySelectorAll(".TEST").length===0)){k=function(m,q,p,v){q=q||s;if(!v&&q.nodeType===9&&!x(q))try{return z(q.querySelectorAll(m),p)}catch(t){}return g(m,q,p,v)};for(var l in g)k[l]=g[l];h=null}}();
+(function(){var g=s.createElement("div");g.innerHTML="<div class='test e'></div><div class='test'></div>";if(!(!g.getElementsByClassName||g.getElementsByClassName("e").length===0)){g.lastChild.className="e";if(g.getElementsByClassName("e").length!==1){n.order.splice(1,0,"CLASS");n.find.CLASS=function(h,l,m){if(typeof l.getElementsByClassName!=="undefined"&&!m)return l.getElementsByClassName(h[1])};g=null}}})();var E=s.compareDocumentPosition?function(g,h){return!!(g.compareDocumentPosition(h)&16)}:
+function(g,h){return g!==h&&(g.contains?g.contains(h):true)},x=function(g){return(g=(g?g.ownerDocument||g:0).documentElement)?g.nodeName!=="HTML":false},ga=function(g,h){var l=[],m="",q;for(h=h.nodeType?[h]:h;q=n.match.PSEUDO.exec(g);){m+=q[0];g=g.replace(n.match.PSEUDO,"")}g=n.relative[g]?g+"*":g;q=0;for(var p=h.length;q<p;q++)k(g,h[q],l);return k.filter(m,l)};c.find=k;c.expr=k.selectors;c.expr[":"]=c.expr.filters;c.unique=k.uniqueSort;c.text=a;c.isXMLDoc=x;c.contains=E})();var eb=/Until$/,fb=/^(?:parents|prevUntil|prevAll)/,
+gb=/,/;R=Array.prototype.slice;var Ia=function(a,b,d){if(c.isFunction(b))return c.grep(a,function(e,j){return!!b.call(e,j,e)===d});else if(b.nodeType)return c.grep(a,function(e){return e===b===d});else if(typeof b==="string"){var f=c.grep(a,function(e){return e.nodeType===1});if(Ua.test(b))return c.filter(b,f,!d);else b=c.filter(b,f)}return c.grep(a,function(e){return c.inArray(e,b)>=0===d})};c.fn.extend({find:function(a){for(var b=this.pushStack("","find",a),d=0,f=0,e=this.length;f<e;f++){d=b.length;
+c.find(a,this[f],b);if(f>0)for(var j=d;j<b.length;j++)for(var i=0;i<d;i++)if(b[i]===b[j]){b.splice(j--,1);break}}return b},has:function(a){var b=c(a);return this.filter(function(){for(var d=0,f=b.length;d<f;d++)if(c.contains(this,b[d]))return true})},not:function(a){return this.pushStack(Ia(this,a,false),"not",a)},filter:function(a){return this.pushStack(Ia(this,a,true),"filter",a)},is:function(a){return!!a&&c.filter(a,this).length>0},closest:function(a,b){if(c.isArray(a)){var d=[],f=this[0],e,j=
+{},i;if(f&&a.length){e=0;for(var o=a.length;e<o;e++){i=a[e];j[i]||(j[i]=c.expr.match.POS.test(i)?c(i,b||this.context):i)}for(;f&&f.ownerDocument&&f!==b;){for(i in j){e=j[i];if(e.jquery?e.index(f)>-1:c(f).is(e)){d.push({selector:i,elem:f});delete j[i]}}f=f.parentNode}}return d}var k=c.expr.match.POS.test(a)?c(a,b||this.context):null;return this.map(function(n,r){for(;r&&r.ownerDocument&&r!==b;){if(k?k.index(r)>-1:c(r).is(a))return r;r=r.parentNode}return null})},index:function(a){if(!a||typeof a===
+"string")return c.inArray(this[0],a?c(a):this.parent().children());return c.inArray(a.jquery?a[0]:a,this)},add:function(a,b){a=typeof a==="string"?c(a,b||this.context):c.makeArray(a);b=c.merge(this.get(),a);return this.pushStack(qa(a[0])||qa(b[0])?b:c.unique(b))},andSelf:function(){return this.add(this.prevObject)}});c.each({parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},parents:function(a){return c.dir(a,"parentNode")},parentsUntil:function(a,b,d){return c.dir(a,"parentNode",
+d)},next:function(a){return c.nth(a,2,"nextSibling")},prev:function(a){return c.nth(a,2,"previousSibling")},nextAll:function(a){return c.dir(a,"nextSibling")},prevAll:function(a){return c.dir(a,"previousSibling")},nextUntil:function(a,b,d){return c.dir(a,"nextSibling",d)},prevUntil:function(a,b,d){return c.dir(a,"previousSibling",d)},siblings:function(a){return c.sibling(a.parentNode.firstChild,a)},children:function(a){return c.sibling(a.firstChild)},contents:function(a){return c.nodeName(a,"iframe")?
+a.contentDocument||a.contentWindow.document:c.makeArray(a.childNodes)}},function(a,b){c.fn[a]=function(d,f){var e=c.map(this,b,d);eb.test(a)||(f=d);if(f&&typeof f==="string")e=c.filter(f,e);e=this.length>1?c.unique(e):e;if((this.length>1||gb.test(f))&&fb.test(a))e=e.reverse();return this.pushStack(e,a,R.call(arguments).join(","))}});c.extend({filter:function(a,b,d){if(d)a=":not("+a+")";return c.find.matches(a,b)},dir:function(a,b,d){var f=[];for(a=a[b];a&&a.nodeType!==9&&(d===w||a.nodeType!==1||!c(a).is(d));){a.nodeType===
+1&&f.push(a);a=a[b]}return f},nth:function(a,b,d){b=b||1;for(var f=0;a;a=a[d])if(a.nodeType===1&&++f===b)break;return a},sibling:function(a,b){for(var d=[];a;a=a.nextSibling)a.nodeType===1&&a!==b&&d.push(a);return d}});var Ja=/ jQuery\d+="(?:\d+|null)"/g,V=/^\s+/,Ka=/(<([\w:]+)[^>]*?)\/>/g,hb=/^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i,La=/<([\w:]+)/,ib=/<tbody/i,jb=/<|&#?\w+;/,ta=/<script|<object|<embed|<option|<style/i,ua=/checked\s*(?:[^=]|=\s*.checked.)/i,Ma=function(a,b,d){return hb.test(d)?
+a:b+"></"+d+">"},F={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]};F.optgroup=F.option;F.tbody=F.tfoot=F.colgroup=F.caption=F.thead;F.th=F.td;if(!c.support.htmlSerialize)F._default=[1,"div<div>","</div>"];c.fn.extend({text:function(a){if(c.isFunction(a))return this.each(function(b){var d=
+c(this);d.text(a.call(this,b,d.text()))});if(typeof a!=="object"&&a!==w)return this.empty().append((this[0]&&this[0].ownerDocument||s).createTextNode(a));return c.text(this)},wrapAll:function(a){if(c.isFunction(a))return this.each(function(d){c(this).wrapAll(a.call(this,d))});if(this[0]){var b=c(a,this[0].ownerDocument).eq(0).clone(true);this[0].parentNode&&b.insertBefore(this[0]);b.map(function(){for(var d=this;d.firstChild&&d.firstChild.nodeType===1;)d=d.firstChild;return d}).append(this)}return this},
+wrapInner:function(a){if(c.isFunction(a))return this.each(function(b){c(this).wrapInner(a.call(this,b))});return this.each(function(){var b=c(this),d=b.contents();d.length?d.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){c(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){c.nodeName(this,"body")||c(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.appendChild(a)})},
+prepend:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this)});else if(arguments.length){var a=c(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,
+this.nextSibling)});else if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,c(arguments[0]).toArray());return a}},remove:function(a,b){for(var d=0,f;(f=this[d])!=null;d++)if(!a||c.filter(a,[f]).length){if(!b&&f.nodeType===1){c.cleanData(f.getElementsByTagName("*"));c.cleanData([f])}f.parentNode&&f.parentNode.removeChild(f)}return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++)for(b.nodeType===1&&c.cleanData(b.getElementsByTagName("*"));b.firstChild;)b.removeChild(b.firstChild);
+return this},clone:function(a){var b=this.map(function(){if(!c.support.noCloneEvent&&!c.isXMLDoc(this)){var d=this.outerHTML,f=this.ownerDocument;if(!d){d=f.createElement("div");d.appendChild(this.cloneNode(true));d=d.innerHTML}return c.clean([d.replace(Ja,"").replace(/=([^="'>\s]+\/)>/g,'="$1">').replace(V,"")],f)[0]}else return this.cloneNode(true)});if(a===true){ra(this,b);ra(this.find("*"),b.find("*"))}return b},html:function(a){if(a===w)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(Ja,
+""):null;else if(typeof a==="string"&&!ta.test(a)&&(c.support.leadingWhitespace||!V.test(a))&&!F[(La.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Ka,Ma);try{for(var b=0,d=this.length;b<d;b++)if(this[b].nodeType===1){c.cleanData(this[b].getElementsByTagName("*"));this[b].innerHTML=a}}catch(f){this.empty().append(a)}}else c.isFunction(a)?this.each(function(e){var j=c(this),i=j.html();j.empty().append(function(){return a.call(this,e,i)})}):this.empty().append(a);return this},replaceWith:function(a){if(this[0]&&
+this[0].parentNode){if(c.isFunction(a))return this.each(function(b){var d=c(this),f=d.html();d.replaceWith(a.call(this,b,f))});if(typeof a!=="string")a=c(a).detach();return this.each(function(){var b=this.nextSibling,d=this.parentNode;c(this).remove();b?c(b).before(a):c(d).append(a)})}else return this.pushStack(c(c.isFunction(a)?a():a),"replaceWith",a)},detach:function(a){return this.remove(a,true)},domManip:function(a,b,d){function f(u){return c.nodeName(u,"table")?u.getElementsByTagName("tbody")[0]||
+u.appendChild(u.ownerDocument.createElement("tbody")):u}var e,j,i=a[0],o=[],k;if(!c.support.checkClone&&arguments.length===3&&typeof i==="string"&&ua.test(i))return this.each(function(){c(this).domManip(a,b,d,true)});if(c.isFunction(i))return this.each(function(u){var z=c(this);a[0]=i.call(this,u,b?z.html():w);z.domManip(a,b,d)});if(this[0]){e=i&&i.parentNode;e=c.support.parentNode&&e&&e.nodeType===11&&e.childNodes.length===this.length?{fragment:e}:sa(a,this,o);k=e.fragment;if(j=k.childNodes.length===
+1?(k=k.firstChild):k.firstChild){b=b&&c.nodeName(j,"tr");for(var n=0,r=this.length;n<r;n++)d.call(b?f(this[n],j):this[n],n>0||e.cacheable||this.length>1?k.cloneNode(true):k)}o.length&&c.each(o,Qa)}return this}});c.fragments={};c.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){c.fn[a]=function(d){var f=[];d=c(d);var e=this.length===1&&this[0].parentNode;if(e&&e.nodeType===11&&e.childNodes.length===1&&d.length===1){d[b](this[0]);
+return this}else{e=0;for(var j=d.length;e<j;e++){var i=(e>0?this.clone(true):this).get();c.fn[b].apply(c(d[e]),i);f=f.concat(i)}return this.pushStack(f,a,d.selector)}}});c.extend({clean:function(a,b,d,f){b=b||s;if(typeof b.createElement==="undefined")b=b.ownerDocument||b[0]&&b[0].ownerDocument||s;for(var e=[],j=0,i;(i=a[j])!=null;j++){if(typeof i==="number")i+="";if(i){if(typeof i==="string"&&!jb.test(i))i=b.createTextNode(i);else if(typeof i==="string"){i=i.replace(Ka,Ma);var o=(La.exec(i)||["",
+""])[1].toLowerCase(),k=F[o]||F._default,n=k[0],r=b.createElement("div");for(r.innerHTML=k[1]+i+k[2];n--;)r=r.lastChild;if(!c.support.tbody){n=ib.test(i);o=o==="table"&&!n?r.firstChild&&r.firstChild.childNodes:k[1]==="<table>"&&!n?r.childNodes:[];for(k=o.length-1;k>=0;--k)c.nodeName(o[k],"tbody")&&!o[k].childNodes.length&&o[k].parentNode.removeChild(o[k])}!c.support.leadingWhitespace&&V.test(i)&&r.insertBefore(b.createTextNode(V.exec(i)[0]),r.firstChild);i=r.childNodes}if(i.nodeType)e.push(i);else e=
+c.merge(e,i)}}if(d)for(j=0;e[j];j++)if(f&&c.nodeName(e[j],"script")&&(!e[j].type||e[j].type.toLowerCase()==="text/javascript"))f.push(e[j].parentNode?e[j].parentNode.removeChild(e[j]):e[j]);else{e[j].nodeType===1&&e.splice.apply(e,[j+1,0].concat(c.makeArray(e[j].getElementsByTagName("script"))));d.appendChild(e[j])}return e},cleanData:function(a){for(var b,d,f=c.cache,e=c.event.special,j=c.support.deleteExpando,i=0,o;(o=a[i])!=null;i++)if(d=o[c.expando]){b=f[d];if(b.events)for(var k in b.events)e[k]?
+c.event.remove(o,k):Ca(o,k,b.handle);if(j)delete o[c.expando];else o.removeAttribute&&o.removeAttribute(c.expando);delete f[d]}}});var kb=/z-?index|font-?weight|opacity|zoom|line-?height/i,Na=/alpha\([^)]*\)/,Oa=/opacity=([^)]*)/,ha=/float/i,ia=/-([a-z])/ig,lb=/([A-Z])/g,mb=/^-?\d+(?:px)?$/i,nb=/^-?\d/,ob={position:"absolute",visibility:"hidden",display:"block"},pb=["Left","Right"],qb=["Top","Bottom"],rb=s.defaultView&&s.defaultView.getComputedStyle,Pa=c.support.cssFloat?"cssFloat":"styleFloat",ja=
+function(a,b){return b.toUpperCase()};c.fn.css=function(a,b){return X(this,a,b,true,function(d,f,e){if(e===w)return c.curCSS(d,f);if(typeof e==="number"&&!kb.test(f))e+="px";c.style(d,f,e)})};c.extend({style:function(a,b,d){if(!a||a.nodeType===3||a.nodeType===8)return w;if((b==="width"||b==="height")&&parseFloat(d)<0)d=w;var f=a.style||a,e=d!==w;if(!c.support.opacity&&b==="opacity"){if(e){f.zoom=1;b=parseInt(d,10)+""==="NaN"?"":"alpha(opacity="+d*100+")";a=f.filter||c.curCSS(a,"filter")||"";f.filter=
+Na.test(a)?a.replace(Na,b):b}return f.filter&&f.filter.indexOf("opacity=")>=0?parseFloat(Oa.exec(f.filter)[1])/100+"":""}if(ha.test(b))b=Pa;b=b.replace(ia,ja);if(e)f[b]=d;return f[b]},css:function(a,b,d,f){if(b==="width"||b==="height"){var e,j=b==="width"?pb:qb;function i(){e=b==="width"?a.offsetWidth:a.offsetHeight;f!=="border"&&c.each(j,function(){f||(e-=parseFloat(c.curCSS(a,"padding"+this,true))||0);if(f==="margin")e+=parseFloat(c.curCSS(a,"margin"+this,true))||0;else e-=parseFloat(c.curCSS(a,
+"border"+this+"Width",true))||0})}a.offsetWidth!==0?i():c.swap(a,ob,i);return Math.max(0,Math.round(e))}return c.curCSS(a,b,d)},curCSS:function(a,b,d){var f,e=a.style;if(!c.support.opacity&&b==="opacity"&&a.currentStyle){f=Oa.test(a.currentStyle.filter||"")?parseFloat(RegExp.$1)/100+"":"";return f===""?"1":f}if(ha.test(b))b=Pa;if(!d&&e&&e[b])f=e[b];else if(rb){if(ha.test(b))b="float";b=b.replace(lb,"-$1").toLowerCase();e=a.ownerDocument.defaultView;if(!e)return null;if(a=e.getComputedStyle(a,null))f=
+a.getPropertyValue(b);if(b==="opacity"&&f==="")f="1"}else if(a.currentStyle){d=b.replace(ia,ja);f=a.currentStyle[b]||a.currentStyle[d];if(!mb.test(f)&&nb.test(f)){b=e.left;var j=a.runtimeStyle.left;a.runtimeStyle.left=a.currentStyle.left;e.left=d==="fontSize"?"1em":f||0;f=e.pixelLeft+"px";e.left=b;a.runtimeStyle.left=j}}return f},swap:function(a,b,d){var f={};for(var e in b){f[e]=a.style[e];a.style[e]=b[e]}d.call(a);for(e in b)a.style[e]=f[e]}});if(c.expr&&c.expr.filters){c.expr.filters.hidden=function(a){var b=
+a.offsetWidth,d=a.offsetHeight,f=a.nodeName.toLowerCase()==="tr";return b===0&&d===0&&!f?true:b>0&&d>0&&!f?false:c.curCSS(a,"display")==="none"};c.expr.filters.visible=function(a){return!c.expr.filters.hidden(a)}}var sb=J(),tb=/<script(.|\s)*?\/script>/gi,ub=/select|textarea/i,vb=/color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week/i,N=/=\?(&|$)/,ka=/\?/,wb=/(\?|&)_=.*?(&|$)/,xb=/^(\w+:)?\/\/([^\/?#]+)/,yb=/%20/g,zb=c.fn.load;c.fn.extend({load:function(a,b,d){if(typeof a!==
+"string")return zb.call(this,a);else if(!this.length)return this;var f=a.indexOf(" ");if(f>=0){var e=a.slice(f,a.length);a=a.slice(0,f)}f="GET";if(b)if(c.isFunction(b)){d=b;b=null}else if(typeof b==="object"){b=c.param(b,c.ajaxSettings.traditional);f="POST"}var j=this;c.ajax({url:a,type:f,dataType:"html",data:b,complete:function(i,o){if(o==="success"||o==="notmodified")j.html(e?c("<div />").append(i.responseText.replace(tb,"")).find(e):i.responseText);d&&j.each(d,[i.responseText,o,i])}});return this},
+serialize:function(){return c.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?c.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||ub.test(this.nodeName)||vb.test(this.type))}).map(function(a,b){a=c(this).val();return a==null?null:c.isArray(a)?c.map(a,function(d){return{name:b.name,value:d}}):{name:b.name,value:a}}).get()}});c.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),
+function(a,b){c.fn[b]=function(d){return this.bind(b,d)}});c.extend({get:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b=null}return c.ajax({type:"GET",url:a,data:b,success:d,dataType:f})},getScript:function(a,b){return c.get(a,null,b,"script")},getJSON:function(a,b,d){return c.get(a,b,d,"json")},post:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b={}}return c.ajax({type:"POST",url:a,data:b,success:d,dataType:f})},ajaxSetup:function(a){c.extend(c.ajaxSettings,a)},ajaxSettings:{url:location.href,
+global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:A.XMLHttpRequest&&(A.location.protocol!=="file:"||!A.ActiveXObject)?function(){return new A.XMLHttpRequest}:function(){try{return new A.ActiveXObject("Microsoft.XMLHTTP")}catch(a){}},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},etag:{},ajax:function(a){function b(){e.success&&
+e.success.call(k,o,i,x);e.global&&f("ajaxSuccess",[x,e])}function d(){e.complete&&e.complete.call(k,x,i);e.global&&f("ajaxComplete",[x,e]);e.global&&!--c.active&&c.event.trigger("ajaxStop")}function f(q,p){(e.context?c(e.context):c.event).trigger(q,p)}var e=c.extend(true,{},c.ajaxSettings,a),j,i,o,k=a&&a.context||e,n=e.type.toUpperCase();if(e.data&&e.processData&&typeof e.data!=="string")e.data=c.param(e.data,e.traditional);if(e.dataType==="jsonp"){if(n==="GET")N.test(e.url)||(e.url+=(ka.test(e.url)?
+"&":"?")+(e.jsonp||"callback")+"=?");else if(!e.data||!N.test(e.data))e.data=(e.data?e.data+"&":"")+(e.jsonp||"callback")+"=?";e.dataType="json"}if(e.dataType==="json"&&(e.data&&N.test(e.data)||N.test(e.url))){j=e.jsonpCallback||"jsonp"+sb++;if(e.data)e.data=(e.data+"").replace(N,"="+j+"$1");e.url=e.url.replace(N,"="+j+"$1");e.dataType="script";A[j]=A[j]||function(q){o=q;b();d();A[j]=w;try{delete A[j]}catch(p){}z&&z.removeChild(C)}}if(e.dataType==="script"&&e.cache===null)e.cache=false;if(e.cache===
+false&&n==="GET"){var r=J(),u=e.url.replace(wb,"$1_="+r+"$2");e.url=u+(u===e.url?(ka.test(e.url)?"&":"?")+"_="+r:"")}if(e.data&&n==="GET")e.url+=(ka.test(e.url)?"&":"?")+e.data;e.global&&!c.active++&&c.event.trigger("ajaxStart");r=(r=xb.exec(e.url))&&(r[1]&&r[1]!==location.protocol||r[2]!==location.host);if(e.dataType==="script"&&n==="GET"&&r){var z=s.getElementsByTagName("head")[0]||s.documentElement,C=s.createElement("script");C.src=e.url;if(e.scriptCharset)C.charset=e.scriptCharset;if(!j){var B=
+false;C.onload=C.onreadystatechange=function(){if(!B&&(!this.readyState||this.readyState==="loaded"||this.readyState==="complete")){B=true;b();d();C.onload=C.onreadystatechange=null;z&&C.parentNode&&z.removeChild(C)}}}z.insertBefore(C,z.firstChild);return w}var E=false,x=e.xhr();if(x){e.username?x.open(n,e.url,e.async,e.username,e.password):x.open(n,e.url,e.async);try{if(e.data||a&&a.contentType)x.setRequestHeader("Content-Type",e.contentType);if(e.ifModified){c.lastModified[e.url]&&x.setRequestHeader("If-Modified-Since",
+c.lastModified[e.url]);c.etag[e.url]&&x.setRequestHeader("If-None-Match",c.etag[e.url])}r||x.setRequestHeader("X-Requested-With","XMLHttpRequest");x.setRequestHeader("Accept",e.dataType&&e.accepts[e.dataType]?e.accepts[e.dataType]+", */*":e.accepts._default)}catch(ga){}if(e.beforeSend&&e.beforeSend.call(k,x,e)===false){e.global&&!--c.active&&c.event.trigger("ajaxStop");x.abort();return false}e.global&&f("ajaxSend",[x,e]);var g=x.onreadystatechange=function(q){if(!x||x.readyState===0||q==="abort"){E||
+d();E=true;if(x)x.onreadystatechange=c.noop}else if(!E&&x&&(x.readyState===4||q==="timeout")){E=true;x.onreadystatechange=c.noop;i=q==="timeout"?"timeout":!c.httpSuccess(x)?"error":e.ifModified&&c.httpNotModified(x,e.url)?"notmodified":"success";var p;if(i==="success")try{o=c.httpData(x,e.dataType,e)}catch(v){i="parsererror";p=v}if(i==="success"||i==="notmodified")j||b();else c.handleError(e,x,i,p);d();q==="timeout"&&x.abort();if(e.async)x=null}};try{var h=x.abort;x.abort=function(){x&&h.call(x);
+g("abort")}}catch(l){}e.async&&e.timeout>0&&setTimeout(function(){x&&!E&&g("timeout")},e.timeout);try{x.send(n==="POST"||n==="PUT"||n==="DELETE"?e.data:null)}catch(m){c.handleError(e,x,null,m);d()}e.async||g();return x}},handleError:function(a,b,d,f){if(a.error)a.error.call(a.context||a,b,d,f);if(a.global)(a.context?c(a.context):c.event).trigger("ajaxError",[b,a,f])},active:0,httpSuccess:function(a){try{return!a.status&&location.protocol==="file:"||a.status>=200&&a.status<300||a.status===304||a.status===
+1223||a.status===0}catch(b){}return false},httpNotModified:function(a,b){var d=a.getResponseHeader("Last-Modified"),f=a.getResponseHeader("Etag");if(d)c.lastModified[b]=d;if(f)c.etag[b]=f;return a.status===304||a.status===0},httpData:function(a,b,d){var f=a.getResponseHeader("content-type")||"",e=b==="xml"||!b&&f.indexOf("xml")>=0;a=e?a.responseXML:a.responseText;e&&a.documentElement.nodeName==="parsererror"&&c.error("parsererror");if(d&&d.dataFilter)a=d.dataFilter(a,b);if(typeof a==="string")if(b===
+"json"||!b&&f.indexOf("json")>=0)a=c.parseJSON(a);else if(b==="script"||!b&&f.indexOf("javascript")>=0)c.globalEval(a);return a},param:function(a,b){function d(i,o){if(c.isArray(o))c.each(o,function(k,n){b||/\[\]$/.test(i)?f(i,n):d(i+"["+(typeof n==="object"||c.isArray(n)?k:"")+"]",n)});else!b&&o!=null&&typeof o==="object"?c.each(o,function(k,n){d(i+"["+k+"]",n)}):f(i,o)}function f(i,o){o=c.isFunction(o)?o():o;e[e.length]=encodeURIComponent(i)+"="+encodeURIComponent(o)}var e=[];if(b===w)b=c.ajaxSettings.traditional;
+if(c.isArray(a)||a.jquery)c.each(a,function(){f(this.name,this.value)});else for(var j in a)d(j,a[j]);return e.join("&").replace(yb,"+")}});var la={},Ab=/toggle|show|hide/,Bb=/^([+-]=)?([\d+-.]+)(.*)$/,W,va=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];c.fn.extend({show:function(a,b){if(a||a===0)return this.animate(K("show",3),a,b);else{a=0;for(b=this.length;a<b;a++){var d=c.data(this[a],"olddisplay");
+this[a].style.display=d||"";if(c.css(this[a],"display")==="none"){d=this[a].nodeName;var f;if(la[d])f=la[d];else{var e=c("<"+d+" />").appendTo("body");f=e.css("display");if(f==="none")f="block";e.remove();la[d]=f}c.data(this[a],"olddisplay",f)}}a=0;for(b=this.length;a<b;a++)this[a].style.display=c.data(this[a],"olddisplay")||"";return this}},hide:function(a,b){if(a||a===0)return this.animate(K("hide",3),a,b);else{a=0;for(b=this.length;a<b;a++){var d=c.data(this[a],"olddisplay");!d&&d!=="none"&&c.data(this[a],
+"olddisplay",c.css(this[a],"display"))}a=0;for(b=this.length;a<b;a++)this[a].style.display="none";return this}},_toggle:c.fn.toggle,toggle:function(a,b){var d=typeof a==="boolean";if(c.isFunction(a)&&c.isFunction(b))this._toggle.apply(this,arguments);else a==null||d?this.each(function(){var f=d?a:c(this).is(":hidden");c(this)[f?"show":"hide"]()}):this.animate(K("toggle",3),a,b);return this},fadeTo:function(a,b,d){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,d)},
+animate:function(a,b,d,f){var e=c.speed(b,d,f);if(c.isEmptyObject(a))return this.each(e.complete);return this[e.queue===false?"each":"queue"](function(){var j=c.extend({},e),i,o=this.nodeType===1&&c(this).is(":hidden"),k=this;for(i in a){var n=i.replace(ia,ja);if(i!==n){a[n]=a[i];delete a[i];i=n}if(a[i]==="hide"&&o||a[i]==="show"&&!o)return j.complete.call(this);if((i==="height"||i==="width")&&this.style){j.display=c.css(this,"display");j.overflow=this.style.overflow}if(c.isArray(a[i])){(j.specialEasing=
+j.specialEasing||{})[i]=a[i][1];a[i]=a[i][0]}}if(j.overflow!=null)this.style.overflow="hidden";j.curAnim=c.extend({},a);c.each(a,function(r,u){var z=new c.fx(k,j,r);if(Ab.test(u))z[u==="toggle"?o?"show":"hide":u](a);else{var C=Bb.exec(u),B=z.cur(true)||0;if(C){u=parseFloat(C[2]);var E=C[3]||"px";if(E!=="px"){k.style[r]=(u||1)+E;B=(u||1)/z.cur(true)*B;k.style[r]=B+E}if(C[1])u=(C[1]==="-="?-1:1)*u+B;z.custom(B,u,E)}else z.custom(B,u,"")}});return true})},stop:function(a,b){var d=c.timers;a&&this.queue([]);
+this.each(function(){for(var f=d.length-1;f>=0;f--)if(d[f].elem===this){b&&d[f](true);d.splice(f,1)}});b||this.dequeue();return this}});c.each({slideDown:K("show",1),slideUp:K("hide",1),slideToggle:K("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(a,b){c.fn[a]=function(d,f){return this.animate(b,d,f)}});c.extend({speed:function(a,b,d){var f=a&&typeof a==="object"?a:{complete:d||!d&&b||c.isFunction(a)&&a,duration:a,easing:d&&b||b&&!c.isFunction(b)&&b};f.duration=c.fx.off?0:typeof f.duration===
+"number"?f.duration:c.fx.speeds[f.duration]||c.fx.speeds._default;f.old=f.complete;f.complete=function(){f.queue!==false&&c(this).dequeue();c.isFunction(f.old)&&f.old.call(this)};return f},easing:{linear:function(a,b,d,f){return d+f*a},swing:function(a,b,d,f){return(-Math.cos(a*Math.PI)/2+0.5)*f+d}},timers:[],fx:function(a,b,d){this.options=b;this.elem=a;this.prop=d;if(!b.orig)b.orig={}}});c.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this);(c.fx.step[this.prop]||
+c.fx.step._default)(this);if((this.prop==="height"||this.prop==="width")&&this.elem.style)this.elem.style.display="block"},cur:function(a){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];return(a=parseFloat(c.css(this.elem,this.prop,a)))&&a>-10000?a:parseFloat(c.curCSS(this.elem,this.prop))||0},custom:function(a,b,d){function f(j){return e.step(j)}this.startTime=J();this.start=a;this.end=b;this.unit=d||this.unit||"px";this.now=this.start;
+this.pos=this.state=0;var e=this;f.elem=this.elem;if(f()&&c.timers.push(f)&&!W)W=setInterval(c.fx.tick,13)},show:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.show=true;this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur());c(this.elem).show()},hide:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.hide=true;this.custom(this.cur(),0)},step:function(a){var b=J(),d=true;if(a||b>=this.options.duration+this.startTime){this.now=
+this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;for(var f in this.options.curAnim)if(this.options.curAnim[f]!==true)d=false;if(d){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;a=c.data(this.elem,"olddisplay");this.elem.style.display=a?a:this.options.display;if(c.css(this.elem,"display")==="none")this.elem.style.display="block"}this.options.hide&&c(this.elem).hide();if(this.options.hide||this.options.show)for(var e in this.options.curAnim)c.style(this.elem,
+e,this.options.orig[e]);this.options.complete.call(this.elem)}return false}else{e=b-this.startTime;this.state=e/this.options.duration;a=this.options.easing||(c.easing.swing?"swing":"linear");this.pos=c.easing[this.options.specialEasing&&this.options.specialEasing[this.prop]||a](this.state,e,0,1,this.options.duration);this.now=this.start+(this.end-this.start)*this.pos;this.update()}return true}};c.extend(c.fx,{tick:function(){for(var a=c.timers,b=0;b<a.length;b++)a[b]()||a.splice(b--,1);a.length||
+c.fx.stop()},stop:function(){clearInterval(W);W=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){c.style(a.elem,"opacity",a.now)},_default:function(a){if(a.elem.style&&a.elem.style[a.prop]!=null)a.elem.style[a.prop]=(a.prop==="width"||a.prop==="height"?Math.max(0,a.now):a.now)+a.unit;else a.elem[a.prop]=a.now}}});if(c.expr&&c.expr.filters)c.expr.filters.animated=function(a){return c.grep(c.timers,function(b){return a===b.elem}).length};c.fn.offset="getBoundingClientRect"in s.documentElement?
+function(a){var b=this[0];if(a)return this.each(function(e){c.offset.setOffset(this,a,e)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return c.offset.bodyOffset(b);var d=b.getBoundingClientRect(),f=b.ownerDocument;b=f.body;f=f.documentElement;return{top:d.top+(self.pageYOffset||c.support.boxModel&&f.scrollTop||b.scrollTop)-(f.clientTop||b.clientTop||0),left:d.left+(self.pageXOffset||c.support.boxModel&&f.scrollLeft||b.scrollLeft)-(f.clientLeft||b.clientLeft||0)}}:function(a){var b=
+this[0];if(a)return this.each(function(r){c.offset.setOffset(this,a,r)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return c.offset.bodyOffset(b);c.offset.initialize();var d=b.offsetParent,f=b,e=b.ownerDocument,j,i=e.documentElement,o=e.body;f=(e=e.defaultView)?e.getComputedStyle(b,null):b.currentStyle;for(var k=b.offsetTop,n=b.offsetLeft;(b=b.parentNode)&&b!==o&&b!==i;){if(c.offset.supportsFixedPosition&&f.position==="fixed")break;j=e?e.getComputedStyle(b,null):b.currentStyle;
+k-=b.scrollTop;n-=b.scrollLeft;if(b===d){k+=b.offsetTop;n+=b.offsetLeft;if(c.offset.doesNotAddBorder&&!(c.offset.doesAddBorderForTableAndCells&&/^t(able|d|h)$/i.test(b.nodeName))){k+=parseFloat(j.borderTopWidth)||0;n+=parseFloat(j.borderLeftWidth)||0}f=d;d=b.offsetParent}if(c.offset.subtractsBorderForOverflowNotVisible&&j.overflow!=="visible"){k+=parseFloat(j.borderTopWidth)||0;n+=parseFloat(j.borderLeftWidth)||0}f=j}if(f.position==="relative"||f.position==="static"){k+=o.offsetTop;n+=o.offsetLeft}if(c.offset.supportsFixedPosition&&
+f.position==="fixed"){k+=Math.max(i.scrollTop,o.scrollTop);n+=Math.max(i.scrollLeft,o.scrollLeft)}return{top:k,left:n}};c.offset={initialize:function(){var a=s.body,b=s.createElement("div"),d,f,e,j=parseFloat(c.curCSS(a,"marginTop",true))||0;c.extend(b.style,{position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"});b.innerHTML="<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>";
+a.insertBefore(b,a.firstChild);d=b.firstChild;f=d.firstChild;e=d.nextSibling.firstChild.firstChild;this.doesNotAddBorder=f.offsetTop!==5;this.doesAddBorderForTableAndCells=e.offsetTop===5;f.style.position="fixed";f.style.top="20px";this.supportsFixedPosition=f.offsetTop===20||f.offsetTop===15;f.style.position=f.style.top="";d.style.overflow="hidden";d.style.position="relative";this.subtractsBorderForOverflowNotVisible=f.offsetTop===-5;this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==j;a.removeChild(b);
+c.offset.initialize=c.noop},bodyOffset:function(a){var b=a.offsetTop,d=a.offsetLeft;c.offset.initialize();if(c.offset.doesNotIncludeMarginInBodyOffset){b+=parseFloat(c.curCSS(a,"marginTop",true))||0;d+=parseFloat(c.curCSS(a,"marginLeft",true))||0}return{top:b,left:d}},setOffset:function(a,b,d){if(/static/.test(c.curCSS(a,"position")))a.style.position="relative";var f=c(a),e=f.offset(),j=parseInt(c.curCSS(a,"top",true),10)||0,i=parseInt(c.curCSS(a,"left",true),10)||0;if(c.isFunction(b))b=b.call(a,
+d,e);d={top:b.top-e.top+j,left:b.left-e.left+i};"using"in b?b.using.call(a,d):f.css(d)}};c.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),d=this.offset(),f=/^body|html$/i.test(b[0].nodeName)?{top:0,left:0}:b.offset();d.top-=parseFloat(c.curCSS(a,"marginTop",true))||0;d.left-=parseFloat(c.curCSS(a,"marginLeft",true))||0;f.top+=parseFloat(c.curCSS(b[0],"borderTopWidth",true))||0;f.left+=parseFloat(c.curCSS(b[0],"borderLeftWidth",true))||0;return{top:d.top-
+f.top,left:d.left-f.left}},offsetParent:function(){return this.map(function(){for(var a=this.offsetParent||s.body;a&&!/^body|html$/i.test(a.nodeName)&&c.css(a,"position")==="static";)a=a.offsetParent;return a})}});c.each(["Left","Top"],function(a,b){var d="scroll"+b;c.fn[d]=function(f){var e=this[0],j;if(!e)return null;if(f!==w)return this.each(function(){if(j=wa(this))j.scrollTo(!a?f:c(j).scrollLeft(),a?f:c(j).scrollTop());else this[d]=f});else return(j=wa(e))?"pageXOffset"in j?j[a?"pageYOffset":
+"pageXOffset"]:c.support.boxModel&&j.document.documentElement[d]||j.document.body[d]:e[d]}});c.each(["Height","Width"],function(a,b){var d=b.toLowerCase();c.fn["inner"+b]=function(){return this[0]?c.css(this[0],d,false,"padding"):null};c.fn["outer"+b]=function(f){return this[0]?c.css(this[0],d,false,f?"margin":"border"):null};c.fn[d]=function(f){var e=this[0];if(!e)return f==null?null:this;if(c.isFunction(f))return this.each(function(j){var i=c(this);i[d](f.call(this,j,i[d]()))});return"scrollTo"in
+e&&e.document?e.document.compatMode==="CSS1Compat"&&e.document.documentElement["client"+b]||e.document.body["client"+b]:e.nodeType===9?Math.max(e.documentElement["client"+b],e.body["scroll"+b],e.documentElement["scroll"+b],e.body["offset"+b],e.documentElement["offset"+b]):f===w?c.css(e,d):this.css(d,typeof f==="string"?f:f+"px")}});A.jQuery=A.$=c})(window);
diff --git a/legacyworlds-web-main/Content/Raw/js/main.js b/legacyworlds-web/legacyworlds-web-main/WebContent/js/main.js
similarity index 83%
rename from legacyworlds-web-main/Content/Raw/js/main.js
rename to legacyworlds-web/legacyworlds-web-main/WebContent/js/main.js
index 85cc697..545e799 100644
--- a/legacyworlds-web-main/Content/Raw/js/main.js
+++ b/legacyworlds-web/legacyworlds-web-main/WebContent/js/main.js
@@ -1,4 +1,37 @@
 $(function() {
+	/*
+	 * Main layer location
+	 */
+	var _viewportHeight = function() {
+		return self.innerHeight || jQuery.boxModel
+				&& document.documentElement.clientHeight
+				|| document.body.clientHeight;
+	};
+	var _viewportWidth = function() {
+		return self.innerWidth || jQuery.boxModel
+				&& document.documentElement.clientWidth
+				|| document.body.clientWidth;
+	};
+
+	var _handleSize = function() {
+		var _h = _viewportHeight();
+		if (_h < 560) {
+			$("#extframe").css('top', '280px');
+		} else {
+			$("#extframe").css('top', '50%');
+		}
+
+		var _w = _viewportWidth();
+		if (_w < 950) {
+			$(".internal").css('left', '475px');
+		} else {
+			$(".internal").css('left', '50%');
+		}
+	};
+
+	$(window).resize(_handleSize);
+	_handleSize();
+
 	/*
 	 * Tabs
 	 */
@@ -25,20 +58,20 @@ $(function() {
 	};
 
 	var _hideTab = function(_id) {
-		$('#tabl-' + _id).removeClass('selected');
+		$('#tabb-' + _id).removeClass('selected-tab');
 		$('#tabc-' + _id).css('display', 'none');
 	};
 
 	var _showTab = function(_id) {
-		$('#tabl-' + _id).addClass('selected');
+		$('#tabb-' + _id).addClass('selected-tab');
 		$('#tabc-' + _id).css('display', 'block');
 	};
 
 	var _prepareTabContainer = function(_root) {
 		_root.container.empty();
 
-		var _titles = $('<ul/>').addClass('tab-buttons');
-		_titles.appendTo( $('#hd-page') );
+		var _titles = $('<div/>').addClass('tab-buttons');
+		_titles.appendTo(_root.container);
 
 		for ( var j in _root.tabs) {
 			var _theTab = _root.tabs[j];
@@ -46,17 +79,15 @@ $(function() {
 				_root.selected = _theTab.id;
 			}
 
-			var _link = $('<a/>').attr('id', 'tabb-' + _theTab.id)
-					.attr('href', '#' + _theTab.id).text(_theTab.title);
-			$('<li/>').attr('id' , 'tabl-' + _theTab.id )
-				.appendTo(_titles).append(_link);
-			_link.click(
-					function() {
-						_hideTab(_root.selected);
-						_root.selected = $(this).attr('id').replace(
-								/^tabb-/, '');
-						_showTab(_root.selected);
-					});
+			$('<a/>').addClass('tab-button').attr('id', 'tabb-' + _theTab.id)
+					.attr('href', '#' + _theTab.id).text(_theTab.title)
+					.appendTo(_titles).click(
+							function() {
+								_hideTab(_root.selected);
+								_root.selected = $(this).attr('id').replace(
+										/^tabb-/, '');
+								_showTab(_root.selected);
+							});
 			_theTab.contents.css('display', 'none').attr('id',
 					'tabc-' + _theTab.id).appendTo(_root.container);
 		}
@@ -68,37 +99,9 @@ $(function() {
 			_prepareTabContainer(_tabs[i]);
 		}
 	};
-	
-	var _handleFakeTabs = function( ) {
-		var _buttons = [];
-		$('.tab-buttons a').each( function( _button ) {
-			$(this).remove( );
-			_buttons.push( $(this) );
-		});
-		if ( _buttons.length == 0 ) {
-			return false;
-		}
-
-		var _titles = $('<ul/>').addClass('tab-buttons');
-		_titles.appendTo( $('#hd-page') );
-		for ( var i in _buttons ) {
-			var _button = _buttons[ i ];
-			var _content = $('<li/>').appendTo(_titles).append(_button);
-			if ( _button.hasClass( 'selected-tab' ) ) {
-				_content.addClass( 'selected' );
-			}
-		}
-		
-		return true;
-	};
 
 	var _tabs = _findTabs();
-	if ( _handleFakeTabs() && _tabs.length != 0 ) {
-		// FIXME: we should display "sub-tabs" somehow
-		// For now we simply ignore the JS tabs
-	} else if ( _tabs.length != 0 ) {
-		_prepareTabs(_tabs);
-	}
+	_prepareTabs(_tabs);
 
 	/*
 	 * Hidden descriptions
diff --git a/legacyworlds-web-main/Content/Raw/pjirc/IRCApplet.class b/legacyworlds-web/legacyworlds-web-main/WebContent/pjirc/IRCApplet.class
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/pjirc/IRCApplet.class
rename to legacyworlds-web/legacyworlds-web-main/WebContent/pjirc/IRCApplet.class
diff --git a/legacyworlds-web-main/Content/Raw/pjirc/background.gif b/legacyworlds-web/legacyworlds-web-main/WebContent/pjirc/background.gif
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/pjirc/background.gif
rename to legacyworlds-web/legacyworlds-web-main/WebContent/pjirc/background.gif
diff --git a/legacyworlds-web-main/Content/Raw/pjirc/english.lng b/legacyworlds-web/legacyworlds-web-main/WebContent/pjirc/english.lng
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/pjirc/english.lng
rename to legacyworlds-web/legacyworlds-web-main/WebContent/pjirc/english.lng
diff --git a/legacyworlds-web-main/Content/Raw/pjirc/french.lng b/legacyworlds-web/legacyworlds-web-main/WebContent/pjirc/french.lng
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/pjirc/french.lng
rename to legacyworlds-web/legacyworlds-web-main/WebContent/pjirc/french.lng
diff --git a/legacyworlds-web-main/Content/Raw/pjirc/irc.cab b/legacyworlds-web/legacyworlds-web-main/WebContent/pjirc/irc.cab
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/pjirc/irc.cab
rename to legacyworlds-web/legacyworlds-web-main/WebContent/pjirc/irc.cab
diff --git a/legacyworlds-web-main/Content/Raw/pjirc/irc.jar b/legacyworlds-web/legacyworlds-web-main/WebContent/pjirc/irc.jar
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/pjirc/irc.jar
rename to legacyworlds-web/legacyworlds-web-main/WebContent/pjirc/irc.jar
diff --git a/legacyworlds-web-main/Content/Raw/pjirc/pixx-english.lng b/legacyworlds-web/legacyworlds-web-main/WebContent/pjirc/pixx-english.lng
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/pjirc/pixx-english.lng
rename to legacyworlds-web/legacyworlds-web-main/WebContent/pjirc/pixx-english.lng
diff --git a/legacyworlds-web-main/Content/Raw/pjirc/pixx-french.lng b/legacyworlds-web/legacyworlds-web-main/WebContent/pjirc/pixx-french.lng
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/pjirc/pixx-french.lng
rename to legacyworlds-web/legacyworlds-web-main/WebContent/pjirc/pixx-french.lng
diff --git a/legacyworlds-web-main/Content/Raw/pjirc/pixx.cab b/legacyworlds-web/legacyworlds-web-main/WebContent/pjirc/pixx.cab
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/pjirc/pixx.cab
rename to legacyworlds-web/legacyworlds-web-main/WebContent/pjirc/pixx.cab
diff --git a/legacyworlds-web-main/Content/Raw/pjirc/pixx.jar b/legacyworlds-web/legacyworlds-web-main/WebContent/pjirc/pixx.jar
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/pjirc/pixx.jar
rename to legacyworlds-web/legacyworlds-web-main/WebContent/pjirc/pixx.jar
diff --git a/legacyworlds-web-main/Content/Raw/pjirc/securedirc.cab b/legacyworlds-web/legacyworlds-web-main/WebContent/pjirc/securedirc.cab
similarity index 100%
rename from legacyworlds-web-main/Content/Raw/pjirc/securedirc.cab
rename to legacyworlds-web/legacyworlds-web-main/WebContent/pjirc/securedirc.cab
diff --git a/legacyworlds-web/legacyworlds-web-main/pom.xml b/legacyworlds-web/legacyworlds-web-main/pom.xml
new file mode 100644
index 0000000..577b5ee
--- /dev/null
+++ b/legacyworlds-web/legacyworlds-web-main/pom.xml
@@ -0,0 +1,89 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+	<parent>
+		<artifactId>legacyworlds-web</artifactId>
+		<groupId>com.deepclone.lw</groupId>
+		<version>5.99.2</version>
+	</parent>
+
+	<groupId>com.deepclone.lw</groupId>
+	<artifactId>legacyworlds-web-main</artifactId>
+	<version>5.99.2</version>
+	<packaging>war</packaging>
+	<name>Legacy Worlds main site</name>
+
+	<dependencies>
+		<dependency>
+			<groupId>com.deepclone.lw</groupId>
+			<artifactId>legacyworlds-web-beans</artifactId>
+			<version>${project.version}</version>
+		</dependency>
+
+		<dependency>
+			<groupId>javax.servlet</groupId>
+			<artifactId>servlet-api</artifactId>
+			<version>2.5</version>
+			<scope>provided</scope>
+		</dependency>
+
+		<dependency>
+			<groupId>org.freemarker</groupId>
+			<artifactId>freemarker</artifactId>
+			<version>${org.freemarker.version}</version>
+			<scope>runtime</scope>
+		</dependency>
+	</dependencies>
+
+	<build>
+		<plugins>
+			<!-- 
+			<plugin>
+				<groupId>org.codehaus.mojo</groupId>
+				<artifactId>tomcat-maven-plugin</artifactId>
+				<version>1.0-beta-1</version>
+				<configuration>
+					<url>http://localhost:8080/manager</url>
+					<path>/lwmain</path>
+					<update>true</update>
+				</configuration>
+				<executions>
+					<execution>
+						<id>deploy-main-site</id>
+						<phase>package</phase>
+						<goals>
+							<goal>deploy</goal>
+						</goals>
+					</execution>
+				</executions>
+			</plugin>
+			 -->
+
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-war-plugin</artifactId>
+				<version>2.0</version>
+				<configuration>
+					<attachClasses>true</attachClasses>
+					<archiveClasses>true</archiveClasses>
+					<webResources>
+						<resource>
+							<directory>legacyworlds-web/legacyworlds-web-main/WebContent</directory>
+						</resource>
+					</webResources>
+				</configuration>
+				<executions>
+					<execution>
+						<id>build-main-war</id>
+						<phase>package</phase>
+						<goals>
+							<goal>war</goal>
+						</goals>
+					</execution>
+				</executions>
+			</plugin>
+
+		</plugins>
+	</build>
+
+</project>
\ No newline at end of file
diff --git a/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/BannedPage.java b/legacyworlds-web/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/BannedPage.java
similarity index 100%
rename from legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/BannedPage.java
rename to legacyworlds-web/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/BannedPage.java
diff --git a/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/CommonPages.java b/legacyworlds-web/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/CommonPages.java
similarity index 100%
rename from legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/CommonPages.java
rename to legacyworlds-web/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/CommonPages.java
diff --git a/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/ErrorHandlerBean.java b/legacyworlds-web/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/ErrorHandlerBean.java
similarity index 100%
rename from legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/ErrorHandlerBean.java
rename to legacyworlds-web/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/ErrorHandlerBean.java
diff --git a/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/ExternalPages.java b/legacyworlds-web/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/ExternalPages.java
similarity index 100%
rename from legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/ExternalPages.java
rename to legacyworlds-web/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/ExternalPages.java
diff --git a/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/LoginPages.java b/legacyworlds-web/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/LoginPages.java
similarity index 100%
rename from legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/LoginPages.java
rename to legacyworlds-web/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/LoginPages.java
diff --git a/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/LogoutPages.java b/legacyworlds-web/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/LogoutPages.java
similarity index 100%
rename from legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/LogoutPages.java
rename to legacyworlds-web/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/LogoutPages.java
diff --git a/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/PasswordRecoveryPages.java b/legacyworlds-web/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/PasswordRecoveryPages.java
similarity index 100%
rename from legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/PasswordRecoveryPages.java
rename to legacyworlds-web/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/PasswordRecoveryPages.java
diff --git a/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/PlayerSessionRedirector.java b/legacyworlds-web/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/PlayerSessionRedirector.java
similarity index 100%
rename from legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/PlayerSessionRedirector.java
rename to legacyworlds-web/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/PlayerSessionRedirector.java
diff --git a/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/ReactivationPages.java b/legacyworlds-web/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/ReactivationPages.java
similarity index 100%
rename from legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/ReactivationPages.java
rename to legacyworlds-web/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/ReactivationPages.java
diff --git a/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/RegistrationPages.java b/legacyworlds-web/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/RegistrationPages.java
similarity index 100%
rename from legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/RegistrationPages.java
rename to legacyworlds-web/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/RegistrationPages.java
diff --git a/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/ValidationPages.java b/legacyworlds-web/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/ValidationPages.java
similarity index 100%
rename from legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/ValidationPages.java
rename to legacyworlds-web/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/ValidationPages.java
diff --git a/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/game/AccountPage.java b/legacyworlds-web/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/game/AccountPage.java
similarity index 100%
rename from legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/game/AccountPage.java
rename to legacyworlds-web/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/game/AccountPage.java
diff --git a/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/game/AlliancePage.java b/legacyworlds-web/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/game/AlliancePage.java
similarity index 100%
rename from legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/game/AlliancePage.java
rename to legacyworlds-web/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/game/AlliancePage.java
diff --git a/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/game/BattlePages.java b/legacyworlds-web/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/game/BattlePages.java
similarity index 100%
rename from legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/game/BattlePages.java
rename to legacyworlds-web/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/game/BattlePages.java
diff --git a/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/game/BugTrackerPages.java b/legacyworlds-web/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/game/BugTrackerPages.java
similarity index 100%
rename from legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/game/BugTrackerPages.java
rename to legacyworlds-web/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/game/BugTrackerPages.java
diff --git a/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/game/ChatPage.java b/legacyworlds-web/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/game/ChatPage.java
similarity index 100%
rename from legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/game/ChatPage.java
rename to legacyworlds-web/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/game/ChatPage.java
diff --git a/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/game/EnemiesPage.java b/legacyworlds-web/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/game/EnemiesPage.java
similarity index 100%
rename from legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/game/EnemiesPage.java
rename to legacyworlds-web/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/game/EnemiesPage.java
diff --git a/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/game/FleetsPage.java b/legacyworlds-web/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/game/FleetsPage.java
similarity index 100%
rename from legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/game/FleetsPage.java
rename to legacyworlds-web/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/game/FleetsPage.java
diff --git a/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/game/GetPlanetPage.java b/legacyworlds-web/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/game/GetPlanetPage.java
similarity index 100%
rename from legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/game/GetPlanetPage.java
rename to legacyworlds-web/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/game/GetPlanetPage.java
diff --git a/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/game/MapPage.java b/legacyworlds-web/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/game/MapPage.java
similarity index 100%
rename from legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/game/MapPage.java
rename to legacyworlds-web/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/game/MapPage.java
diff --git a/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/game/MessageBoxView.java b/legacyworlds-web/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/game/MessageBoxView.java
similarity index 100%
rename from legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/game/MessageBoxView.java
rename to legacyworlds-web/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/game/MessageBoxView.java
diff --git a/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/game/MessagePages.java b/legacyworlds-web/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/game/MessagePages.java
similarity index 100%
rename from legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/game/MessagePages.java
rename to legacyworlds-web/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/game/MessagePages.java
diff --git a/legacyworlds-web/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/game/OverviewPage.java b/legacyworlds-web/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/game/OverviewPage.java
new file mode 100644
index 0000000..e8f4831
--- /dev/null
+++ b/legacyworlds-web/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/game/OverviewPage.java
@@ -0,0 +1,36 @@
+package com.deepclone.lw.web.main.game;
+
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.ModelAttribute;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.SessionAttributes;
+
+import com.deepclone.lw.session.SessionException;
+import com.deepclone.lw.web.beans.intercept.SessionRequirement;
+import com.deepclone.lw.web.beans.session.SessionMaintenanceException;
+import com.deepclone.lw.web.beans.session.SessionServerException;
+import com.deepclone.lw.web.beans.view.PageControllerBase;
+import com.deepclone.lw.web.csess.PlayerSession;
+
+
+
+@Controller
+@SessionRequirement( value = true , redirectTo = "player-session" , subType = "game" )
+@SessionAttributes( "language" )
+public class OverviewPage
+		extends PageControllerBase
+{
+
+	@RequestMapping( "/overview" )
+	public String overview( HttpServletRequest request , @ModelAttribute( "language" ) String language , Model model )
+			throws SessionException , SessionServerException , SessionMaintenanceException
+	{
+		PlayerSession pSession = this.getSession( PlayerSession.class , request );
+		return this.render( model , "game" , language , "overview" , pSession.getOverview( ) );
+	}
+
+}
diff --git a/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/game/PlanetListPage.java b/legacyworlds-web/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/game/PlanetListPage.java
similarity index 100%
rename from legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/game/PlanetListPage.java
rename to legacyworlds-web/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/game/PlanetListPage.java
diff --git a/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/game/PlanetPage.java b/legacyworlds-web/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/game/PlanetPage.java
similarity index 70%
rename from legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/game/PlanetPage.java
rename to legacyworlds-web/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/game/PlanetPage.java
index 2bbb419..e0afc3c 100644
--- a/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/game/PlanetPage.java
+++ b/legacyworlds-web/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/game/PlanetPage.java
@@ -1,10 +1,6 @@
 package com.deepclone.lw.web.main.game;
 
 
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Map.Entry;
-
 import javax.servlet.http.HttpServletRequest;
 
 import org.springframework.stereotype.Controller;
@@ -84,8 +80,8 @@ public class PlanetPage
 
 
 	@RequestMapping( value = "/planet-{planetId}-cancel-abandon.action" , method = RequestMethod.POST )
-	public String cancelAbandon( HttpServletRequest request , @ModelAttribute( "language" ) String language ,
-			Model model , @PathVariable String planetId )
+	public String cancelAbandon( HttpServletRequest request , @ModelAttribute( "language" ) String language , Model model ,
+			@PathVariable String planetId )
 			throws SessionException , SessionServerException , SessionMaintenanceException
 	{
 		int pId;
@@ -237,108 +233,4 @@ public class PlanetPage
 		PlayerSession pSession = this.getSession( PlayerSession.class , request );
 		return this.render( model , "game" , language , "planet" , pSession.flushQueue( pId , true ) );
 	}
-
-
-	/**
-	 * Handler for commands that modify planet mining settings
-	 * 
-	 * <p>
-	 * This method handles all mining settings commands, including both switching between empire-
-	 * and planet-specific settings and updating all priorities.
-	 * 
-	 * @param request
-	 *            the HTTP request
-	 * @param model
-	 *            the model
-	 * @param planetId
-	 *            the planet's identifier string from the path
-	 * @param toggle
-	 *            this parameter from the form's <code>toggle-settings</code> value will be set if
-	 *            the "Switch to empire-wide/planet-specific settings" button was clicked.
-	 * 
-	 * @return a redirect to the overview page if the planet identifier was invalid, or a redirect
-	 *         to the planet page's natural resources tab otherwise.
-	 * 
-	 * @throws SessionException
-	 *             if some error occurs on the server
-	 * @throws SessionServerException
-	 *             if the server is unreachable
-	 * @throws SessionMaintenanceException
-	 *             if the game is under maintenance
-	 */
-	@RequestMapping( value = "/planet-{planetId}-update-mset.action" , method = RequestMethod.POST )
-	public String updateMiningSettings( HttpServletRequest request , Model model , @PathVariable String planetId ,
-			@RequestParam( value = "toggle-settings" , required = false ) String toggle )
-			throws SessionException , SessionServerException , SessionMaintenanceException
-	{
-		int pId;
-		try {
-			pId = Integer.parseInt( planetId );
-		} catch ( NumberFormatException e ) {
-			return this.redirect( "overview" );
-		}
-
-		PlayerSession session = this.getSession( PlayerSession.class , request );
-		if ( toggle == null ) {
-			Map< String , Integer > settings = this.getMiningSettings( request );
-			if ( settings != null ) {
-				session.updatePlanetMiningSettings( pId , settings );
-			}
-		} else {
-			session.toggleMiningSettingsFor( pId );
-		}
-
-		return this.redirect( "planet-" + Integer.toString( pId ) + "#natres" );
-	}
-
-
-	/**
-	 * Extract mining priorities from the HTTP request
-	 * 
-	 * <p>
-	 * Look for all submitted fields that begin with "pms-" then try to extract their values into a
-	 * map that associates resource identifiers to priorities.
-	 * 
-	 * @param request
-	 *            the HTTP request
-	 * 
-	 * @return the map containing the submitted mining settings, or <code>null</code> if one of the
-	 *         values was incorrect.
-	 */
-	private Map< String , Integer > getMiningSettings( HttpServletRequest request )
-	{
-		Map< String , Object > input = this.getInput( request );
-		Map< String , Integer > miningSettings = new HashMap< String , Integer >( );
-		for ( Entry< String , Object > entry : input.entrySet( ) ) {
-			// Ignore items which are not mining settings
-			String name = entry.getKey( );
-			if ( !name.startsWith( "pms-" ) ) {
-				continue;
-			}
-			name = name.substring( 4 );
-
-			// Get values
-			if ( ! ( entry.getValue( ) instanceof String[] ) ) {
-				continue;
-			}
-			String[] values = (String[]) entry.getValue( );
-			if ( values.length < 1 ) {
-				continue;
-			}
-
-			// Pre-validate them
-			int value;
-			try {
-				value = Integer.parseInt( values[ 0 ] );
-			} catch ( NumberFormatException e ) {
-				value = -1;
-			}
-			if ( value < 0 || value > 4 ) {
-				return null;
-			}
-
-			miningSettings.put( name , value );
-		}
-		return miningSettings;
-	}
 }
diff --git a/legacyworlds-web/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/game/TechnologyPages.java b/legacyworlds-web/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/game/TechnologyPages.java
new file mode 100644
index 0000000..1042912
--- /dev/null
+++ b/legacyworlds-web/legacyworlds-web-main/src/main/java/com/deepclone/lw/web/main/game/TechnologyPages.java
@@ -0,0 +1,143 @@
+package com.deepclone.lw.web.main.game;
+
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.ModelAttribute;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.SessionAttributes;
+
+import com.deepclone.lw.cmd.player.gdata.empire.ResearchData;
+import com.deepclone.lw.cmd.player.research.ResearchOperationResponse;
+import com.deepclone.lw.cmd.player.research.ViewResearchResponse;
+import com.deepclone.lw.cmd.player.research.ResearchOperationResponse.Result;
+import com.deepclone.lw.session.SessionException;
+import com.deepclone.lw.web.beans.intercept.SessionRequirement;
+import com.deepclone.lw.web.beans.session.SessionMaintenanceException;
+import com.deepclone.lw.web.beans.session.SessionServerException;
+import com.deepclone.lw.web.beans.view.PageControllerBase;
+import com.deepclone.lw.web.csess.PlayerSession;
+
+
+
+@Controller
+@SessionRequirement( value = true , redirectTo = "player-session" , subType = "game" )
+@SessionAttributes( "language" )
+public class TechnologyPages
+		extends PageControllerBase
+{
+
+	@RequestMapping( "/technologies" )
+	public String viewTechnologies( HttpServletRequest request , @ModelAttribute( "language" ) String language ,
+			Model model )
+			throws SessionException , SessionServerException , SessionMaintenanceException
+	{
+		PlayerSession pSession = this.getSession( PlayerSession.class , request );
+		return this.renderPage( model , language , pSession.viewResearch( ) );
+	}
+
+
+	@RequestMapping( value = "/implement-tech.action" , method = RequestMethod.POST )
+	public String implement( HttpServletRequest request , @ModelAttribute( "language" ) String language , Model model ,
+			@RequestParam( "technology" ) String tech )
+			throws SessionException , SessionServerException , SessionMaintenanceException
+	{
+		if ( tech == null || tech.equals( "" ) ) {
+			return this.redirect( "technologies" );
+		}
+
+		PlayerSession pSession = this.getSession( PlayerSession.class , request );
+		ResearchOperationResponse response = pSession.implementTechnology( tech );
+		if ( response.getResult( ) == Result.OK ) {
+			return this.redirect( "technologies" );
+		}
+		return this.renderPage( model , language , response );
+	}
+
+
+	@RequestMapping( value = "/set-research-priority.action" , method = RequestMethod.POST )
+	public String setPriorities( HttpServletRequest request , @ModelAttribute( "language" ) String language ,
+			Model model )
+			throws SessionException , SessionServerException , SessionMaintenanceException
+	{
+		PlayerSession pSession = this.getSession( PlayerSession.class , request );
+		ResearchOperationResponse response;
+
+		Map< String , Integer > priorities = new HashMap< String , Integer >( );
+		if ( this.getPriorityValues( priorities , request ) ) {
+			response = pSession.setResearchPriorities( priorities );
+			if ( response.getResult( ) == Result.OK ) {
+				return this.redirect( "technologies" );
+			}
+		} else {
+			response = this.createInvalidResponse( pSession , priorities );
+		}
+
+		return this.renderPage( model , language , response );
+	}
+
+
+	private String renderPage( Model model , String language , ViewResearchResponse data )
+	{
+		return this.render( model , "game" , language , "technologies" , data );
+	}
+
+
+	private ResearchOperationResponse createInvalidResponse( PlayerSession pSession , Map< String , Integer > priorities )
+			throws SessionException , SessionServerException , SessionMaintenanceException
+	{
+		ViewResearchResponse view = pSession.viewResearch( );
+		for ( ResearchData research : view.getResearch( ) ) {
+			Integer nPrio = priorities.get( research.getIdentifier( ) );
+			if ( nPrio != null && research.getPriority( ) != null ) {
+				research.setPriority( nPrio );
+			}
+		}
+		return new ResearchOperationResponse( view.getPage( ) , view.getResearch( ) ,
+				view.getImplementedTechnologies( ) , Result.ERR_INVALID );
+	}
+
+
+	@SuppressWarnings( "unchecked" )
+	private boolean getPriorityValues( Map< String , Integer > priorities , HttpServletRequest request )
+	{
+		Map< String , String[] > parameters = request.getParameterMap( );
+		int total = 0;
+		boolean ok = true;
+
+		for ( String pName : parameters.keySet( ) ) {
+			if ( !pName.matches( "^priority-[A-Za-z0-9\\-]+" ) ) {
+				continue;
+			}
+
+			String tName = pName.substring( "priority-".length( ) );
+			String pValues[] = parameters.get( pName );
+			if ( pValues.length != 1 || pValues[ 0 ] == null ) {
+				ok = false;
+				continue;
+			}
+
+			int value;
+			try {
+				value = Integer.parseInt( pValues[ 0 ] );
+			} catch ( NumberFormatException e ) {
+				ok = false;
+				continue;
+			}
+
+			priorities.put( tName , value );
+			total += value;
+
+			ok = ok && ! ( value < 0 || value > 100 );
+		}
+
+		return ok && total == 100 && priorities.size( ) >= 2;
+	}
+}
diff --git a/legacyworlds-web-main/src/main/resources/log4j.properties b/legacyworlds-web/legacyworlds-web-main/src/main/resources/log4j.properties
similarity index 100%
rename from legacyworlds-web-main/src/main/resources/log4j.properties
rename to legacyworlds-web/legacyworlds-web-main/src/main/resources/log4j.properties
diff --git a/legacyworlds-web/pom.xml b/legacyworlds-web/pom.xml
index 26517d6..24fa5cb 100644
--- a/legacyworlds-web/pom.xml
+++ b/legacyworlds-web/pom.xml
@@ -4,62 +4,19 @@
 	<parent>
 		<artifactId>legacyworlds</artifactId>
 		<groupId>com.deepclone.lw</groupId>
-		<version>1.0.0</version>
-		<relativePath>../legacyworlds/pom.xml</relativePath>
+		<version>5.99.2</version>
 	</parent>
 
+	<groupId>com.deepclone.lw</groupId>
 	<artifactId>legacyworlds-web</artifactId>
+	<version>5.99.2</version>
 	<packaging>pom</packaging>
-	<name>Legacy Worlds - Web</name>
+	<name>Legacy Worlds web sites</name>
 	<description>Root module for Legacy Worlds web sites</description>
 
 	<modules>
-		<module>../legacyworlds-web-admin</module>
-		<module>../legacyworlds-web-beans</module>
-		<module>../legacyworlds-web-DIST</module>
-		<module>../legacyworlds-web-main</module>
-		<module>../legacyworlds-web-tests</module>
+		<module>legacyworlds-web-main</module>
+		<module>legacyworlds-web-admin</module>
+		<module>legacyworlds-web-beans</module>
 	</modules>
-
-
-	<build>
-		<pluginManagement>
-			<plugins>
-			
-				<!--
-				   - Default configuration for the WAR plug-in
-				  -->
-				<plugin>
-					<artifactId>maven-war-plugin</artifactId>
-					<configuration>
-						<attachClasses>true</attachClasses>
-						<archiveClasses>true</archiveClasses>
-						<webResources>
-							<!-- Copy resources that do not need filtering -->
-							<resource>
-								<directory>Content/Raw</directory>
-								<filtering>false</filtering>
-							</resource>
-							<!-- Copy resources that need filtering to WEB-INF/ -->
-							<resource>
-								<directory>Content/Filtered</directory>
-								<targetPath>WEB-INF</targetPath>
-								<filtering>true</filtering>
-							</resource>
-						</webResources>
-					</configuration>
-					<executions>
-						<execution>
-							<id>build-war</id>
-							<phase>package</phase>
-							<goals>
-								<goal>war</goal>
-							</goals>
-						</execution>
-					</executions>
-				</plugin>
-
-			</plugins>
-		</pluginManagement>
-	</build>
-</project>
+</project>
\ No newline at end of file
diff --git a/legacyworlds/.gitignore b/legacyworlds/.gitignore
deleted file mode 100644
index 2fd5b12..0000000
--- a/legacyworlds/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-legacyworlds.tar.bz2
diff --git a/legacyworlds/dev-tools/run-database-tests.sh b/legacyworlds/dev-tools/run-database-tests.sh
deleted file mode 100755
index b1956f8..0000000
--- a/legacyworlds/dev-tools/run-database-tests.sh
+++ /dev/null
@@ -1,65 +0,0 @@
-#!/bin/sh
-
-[ -z "$3" ] && {
-	echo "Syntax: $0 test-database admin-user test-user [misc]" >&2
-	echo
-	echo "Where misc is:"
-	echo "       --no-create	don't create the DB"
-	echo "       --run-name name	run tests matching '*name*'"
-	echo
-	exit 1
-}
-
-test_db="$1"
-admin_user="$2"
-test_user="$3"
-
-create_db=1
-run_name=""
-while ! [ -z "$4" ]; do
-	if [ "x$4" = "x--no-create" ]; then
-		create_db=0
-	elif [ "x$4" = "x--run-name" ]; then
-		shift
-		run_name="$4"
-	fi
-
-	shift
-done
-
-scriptdir="`dirname $0`"
-tempdir="`mktemp -d`"
-cp -Rap $scriptdir/../../legacyworlds-server-data/db-structure/* $tempdir/
-cat > $tempdir/db-config.txt <<EOF
-admin=$admin_user
-db=$test_db
-user=$test_user
-password=$test_user
-EOF
-
-(
-	cd $tempdir
-
-	if [ $create_db -eq 1 ]; then
-		echo "Creating DB..."
-		psql -vQUIET=1 -vON_ERROR_STOP=1 --file database.sql || exit 1
-		psql -vQUIET=1 -f tests/pgtap.sql $test_db || exit 1
-	fi
-
-	cd tests
-	if [ "x$run_name" = "x" ]; then
-		run_name='*.sql'
-	else
-		run_name='*'"$run_name"'*.sql'
-	fi
-	if ! [ -z "`find admin/ -type f -name "$run_name"`" ]; then
-		pg_prove -d $test_db `find admin/ -type f -name "$run_name" | sort` || exit 1
-	fi
-	if ! [ -z "`find user/ -type f -name "$run_name"`" ]; then
-		pg_prove -U $test_user -d $test_db `find user/ -type f -name "$run_name" | sort` || exit 1
-	fi
-)
-result=$?
-
-rm -rf $tempdir
-exit $result
diff --git a/legacyworlds/doc/Eclipse-import.txt b/legacyworlds/doc/Eclipse-import.txt
deleted file mode 100644
index 5948161..0000000
--- a/legacyworlds/doc/Eclipse-import.txt
+++ /dev/null
@@ -1,58 +0,0 @@
-Legacy Worlds Eclipse projects import
-======================================
-
-While it is not strictly necessary, it is recommended to import the Legacy
-Worlds code into a separate workspace, as it will be easier to use e.g. the LW
-code formatting configuration without interfering with other projects.
-
-Before you start, make sure the following Eclipse plug-ins are active:
-* M2E (the Maven integration plug-in)
-* EGit or equivalent
-
-This guide assumes that you've already cloned the source code from the
-server's Git repositories.
-
-
-Importing the projects
------------------------
-
-1) Select the Java perspective (the Java EE perspective tries to be clever and
-fails).
-2) In the Package Explorer, right-click then select Import.
-3) Select Maven > Existing Maven projects.
-4) Select the root directory of your local Git repository. It will list all
-parts of the Legacy Worlds code. Make sure they're all selected, then click the
-Finish button.
-
-The projects should be imported, and after a while, they should all build
-successfully. This may take a few minutes, as Maven will download all
-dependencies and plug-ins.
-
-At this point, Eclipse knows of the projects, but has no clue they're in a Git
-repository.
-
-
-Git support
-------------
-
-1) Open the Git Repositories perspective, and add the local repository to the
-list.
-2) Go back to the Java perspective, select all projects, right-click then select
-Team > Share Project
-3) Select the Git repository type,
-4) Select the local repository then click Finish.
-
-Eclipse will proceed to "link" the local repository with the projects in the
-workspace.
-
-
-Editor set-up
---------------
-
-1) Select Window > Preferences in the main menu
-2) Select Java > Code Style > Formatter
-3) Click the Import button and select the eclipse-code-format.xml file found in
-the legacyworlds/ directory.
-4) Select Java > Code Style > Clean Up
-5) Click the Import button and select the eclipse-code-cleanup.xml file found
-in the legacyworlds/ directory.
diff --git a/legacyworlds/doc/communications.txt b/legacyworlds/doc/communications.txt
deleted file mode 100644
index b295a15..0000000
--- a/legacyworlds/doc/communications.txt
+++ /dev/null
@@ -1,134 +0,0 @@
-Communications between the server and its clients
-==================================================
-
-This file contains a few notes about the implementation of the client/server
-system, as well as a (purely speculative) section about changes that ought to
-be made.
-
-
-Definitions
-------------
-
-The Legacy Worlds "server" has nothing to do with the web interfaces. It is a
-standalone application which handles most aspects of the game itself, but does
-not provide any kind of human-readable interface.
-
-Legay Worlds "clients", on the other hand, are applications (whether they are
-standalone or depend on some container is a detail) which connect to the
-server and provide either some user interface or an intermediary layer for
-an user interface application.
-
-At this time, the two clients in existence are:
- -> the main web site,
- -> the administration web site.
- 
-This architecture was designed to keep any access to the game completely
-separate from the game's logic. The only exception to that principle is the
-email notifications system (see discussion).
-
-
-Protocol implementation
-------------------------
-
-All client/server communications go through a RMI interface, SessionAccessor.
-This interface can be used by clients to initiate, authenticate and terminate
-sessions and to execute commands on the server. The general type of a session
-(i.e. whether it is an administrative session, a game session, or an
-"external" session which serves for user registration) is determined when the
-session is created.
-
-Commands are classes that extend the Command abstract class. They carry all
-the information required for their specific purpose.
-
-In response to a Command, the server will reply with either an exception or
-a response. The following exceptions can be thrown by the server:
-
- -> SessionInternalException means that some internal error occurred while
-    manipulating the session or executing the command. It can in theory be
-    thrown by all parts of the session access interface, but shouldn't
-    occur too often in practice, as it indicates a bug or server problem.
-
- -> SessionIdentifierException means that the session identifier sent by
-    the client doesn't match any known session. This may indicate a timeout
-    on the client's part.
-
- -> SessionStateException is thrown when the client tries to re-authenticate
-    a session or to execute a command before the session has been
-    authenticated.
-
- -> SessionCommandException is thrown when the command that was sent is not
-    supported by the server.
-
-When everything is fine, a command's execution will cause the server to return
-an object of some class that inherits the CommandResponse class. If no data is
-to be transmitted in response to the command, the response may be a
-NullResponse instance.
-
-
-Server implementation
-----------------------
-
-The server supports various types of session. Each type of session may have
-different parameters (for example, its timeout) or behaviours (for example,
-the way the session's authentication request is verified). In addition, each
-type of session will implement a different set of commands.
-
-The internals of the session and command routing system are somewhat outside
-the scope of this document. The various classes which implement that system
-can be found in com.deepclone.lw.beans.user.abst for the most basic elements,
-while the com.deepclone.lw.beans.user.admin,
-com.deepclone.lw.beans.user.player and com.deepclone.lw.beans.user.ext
-packages all contain parts specific to session types.
-
-Actual command handling is defined through classes which implement the
-AutowiredCommandDelegate interface.
- -> The getCommandHandler() method must return the class which defines the
-    type of session in which the command handler is to be included. For
-    example it will return GameSubTypeBean.class for game session commands or
-    AdminCommandsBean.class for administration commands.
- -> The getType() method must return the class of commands handled. For
-    example, a handler for commands of the WhateverCommand class would have
-    this method returning WhateverCommand.class
- -> Finally, the execute() method implements the command itself.
-
-All command handlers, once defined, must be listed to one of the Spring XML
-configuration files in the legacyworlds-server-beans-user project's resources.
-
-
-Discussion
------------
-
-While the current implementation is successful in that it defines a clear line
-between the game and whatever is used to display it and access it, it has a
-few drawbacks.
-
-Firstly, the use of RMI associated with dozens of Command / CommandResponse
-classes, while easy to use, is definitely very heavy, specific to Java and
-causes a proliferation of mostly-useless classes.
-
-The protocol's weight is not too problematic at this time, since all
-communications occur either on the same system or between virtual machines
-running on the same system. However, the unbelievable amount of classes
-makes the implementation of new commands or the modification of existing
-commands somewhat tedious. Finally, the Java specificity would prevent the
-implementation of clients connecting directly to the server in any other
-language.
-
-However the main problem with this implementation lies elsewhere. As a matter
-of fact, communications between client and server only go one way: the clients
-may request the execution of commands, but the server cannot send the clients
-data independently. It is not possible to "poll" the server either: sessions
-are exclusive and can only be used to execute one command at a time, so having
-one session running a blocking command is not a possibility. The only way a
-client application could request updates would be by running a command every
-few seconds. This is not a problem at all with the current clients, as they
-are based on user-triggered HTTP requests.
-
-However, trying to implement anything more interactive would be difficult. As
-a matter of fact, the email notifications system should *be* a separate
-client, but the current architecture does not support it. 
-
-In the long run, the existing communications protocol should be replaced with
-something more flexible. For example, it is entirely conceivable to replace it
-with a custom TCP- or even UDP-based protocol which could be used by both
-"local" clients (such as the web sites) and remote applications.  
\ No newline at end of file
diff --git a/legacyworlds/doc/database.txt b/legacyworlds/doc/database.txt
deleted file mode 100644
index 15ae48e..0000000
--- a/legacyworlds/doc/database.txt
+++ /dev/null
@@ -1,130 +0,0 @@
-Database structure and development
-===================================
-
-The database used by the Legacy Worlds server can be found in the db-structure
-directory of the legacyworlds-server-data package.
-
-
-Database configuration
------------------------
-
-The configuration used by the various SQL scripts must be placed in the
-db-config.txt file, at the root of the directory. This file is ignored by Git,
-which allows each developer to set up her or his own copy of the database
-without hassle. A sample is included in the repository in the
-db-config.sample.txt file.
-
-The configuration file contains a few fields, which are defined using a simple
-"<key>=<value>" syntax (warning: there should be no spaces before or after the
-'=' sign).
-
-The following fields must be defined:
-
-* admin - the name of the administrative user,
-* db - the name of the database,
-* user - the name of the user through which the server connects to the
-database,
-* password - the password used by the server to authenticate when accessing
-the database.
-
-
-Code structure
----------------
-
-The root directory includes a "database.sql" script, which can be launched in
-psql to create the database and associated user.
-
-The parts/ sub-directory contains the various elements of the database's
-definition.
-
-All SQL files contained in this directory, as well as all sub-directories and
-their contents, are prefixed with some number which serves as an indication of
-the order in which the scripts are to be loaded. Numbering in a directory
-should start with 010 and increase by 10 for each file in the sequence.
-However, when adding new code, it is possible to add new files with
-intermediary values.
-
-The parts/ sub-directory contains the following elements:
- * schema and extension loaders,
- * the xxx-data/ sub-directory which contains most data structure definitions
-   (types, tables, indexes, constraints and some of the views).
- * the xxx-functions/ sub-directory which contains all general function
-   definitions; this includes both functions that are called internally and
-   functions which are called by the server. It also includes view definitions
-   that depend on functions or are used only by functions, as well as type
-   definitions used to pass values between functions or as return values.
- * the xxx-updates/ sub-directory which contains all functions that implement
-   the game's updates.
-
-The tests/ sub-directory contains the SQL source code for the pgTAP testing
-framework as well as the tests themselves. See below for more information.
- 
- 
-Unit tests
-----------
- 
-There are four sub-directories in the tests/ directory. The admin/ directory
-contains tests that require administrative permissions on the database
-(therefore most functionality checks can be found there), while the user/
-sub-directory contains unit tests that must be executed as the standard
-user (for example privileges checks).
-
-The dirty/ sub-directory contains tests which require actual changes to
-be committed to the database; while unit tests are not supposed to be executed
-on a loaded database anyway, these specific tests could cause problems with
-other tests, and therefore run on copies of the database.
-
-Finally, the utils/ sub-directory contains scripts used by tests from both the
-admin/ and dirty/ sub-directories to create test data.
- 
-In both the admin/ and user/ directories, files are organised in a manner that
-is parallel to the contents of the database creation scripts. For each actual
-SQL file, a sub-directory with the same name (minus the ".sql" extension) can
-be created, each sub-directory containing the test suites for the definitions
-and functions from the corresponding file.
-
-The dirty/ sub-directory contains a script which can be used to run the
-"dirty" test suites, as well as one directory per test suite. Each test suite
-directory may contain a "prepare.sql" script, to be executed before the actual
-tests, as well as a "run-test.sql" which runs the actual tests.
- 
-In order to run the database unit tests, the following steps must be taken:
- 
-1) pg_prove must be installed. This can be achieved by running the following
-   command as root:
- 
- 		 cpan TAP::Parser::SourceHandler::pgTAP
-
-2) It must be possible to log on to the database through the local socket as
-   both the administrative and the standard user, without password.
-
-3) The database itself must be loaded using the aforementioned database.sql
-   script.
-
-4) The tests/pgtap.sql script must be loaded into the database as the
-   administrative user.
-
-At this point, it becomes possible to launch the basic test suites by issuing a
-command similar to:
-
-		pg_prove -d $DATABASE -U $USER \
-				`find $DIR/ -type f -name '*.sql' | sort`
-
-where $DATABASE is the name of the database, $USER the name of the user that
-will execute the tests and $DIR being either admin or user. The "dirty" test
-suite can be launched by running:
-
-		TEST_DATABASE=$DATABASE ./run-dirty-tests.sh
-
-Note that the dirty tests will fail unless all existing connections to the
-main database are closed.
-
-
-Build system
--------------
-
-The build system will attempt to create the database using the scripts. It will
-stop at the first unsuccessful command. On success, it will proceed to loading
-pgTAP, then run all available unit tests: first it will execute tests from the
-admin/ sub-directory, then tests from the user/ sub-directory, and finally the
-dirty tests. A failure will cause the build to be aborted. 
diff --git a/legacyworlds/doc/local-deployment.txt b/legacyworlds/doc/local-deployment.txt
deleted file mode 100644
index 245e281..0000000
--- a/legacyworlds/doc/local-deployment.txt
+++ /dev/null
@@ -1,90 +0,0 @@
-Deploying a local Legacy Worlds server
-=======================================
-
-
-1) Before the server can be deployed, it is necessary to build the whole thing.
-Enter the legacyworlds/ directory, and run:
-
-	mvn package
-
-The server's distribution will be prepared in the
-legacyworlds-server-DIST/target/legacyworlds-server-1.0.0-0/ directory. It
-includes the server's main archive and libraries, the SQL scripts that
-initialise the database and the initial game data.
-
-
-
-2) The database needs to be created. In order to do that, you need to have a
-PostgreSQL instance onto which you can connect locally, without password, as an
-administrative user.
-
-In the server distribution's sql/ directory, copy the db-config.sample.txt file
-to db-config.txt, and edit it. The "admin" field should be the name of the
-administrative user, the "db" field the name of the database, the "user" field
-the name of the Legacy Worlds user, and the "password" field the Legacy Worlds
-user's password.
-
-Once this is done, connect to PostgreSQL and run:
-
-	\i database.sql
-
-
-3) Configure the server's data source by copying the data-source.sample.xml file
-to data-source.xml, and modifying the JDBC URL, user name and password to match
-the values used at step 2.  
-
-
-4) Load the game's base data. In order to do that, run the following commands
-from the root of the server's distribution: 
-
-	java -jar legacyworlds-server-main-1.0.0-0.jar \
-		--run-tool ImportText data/i18n-text.xml
-	java -jar legacyworlds-server-main-1.0.0-0.jar \
-		--run-tool ImportEvents data/event-definitions.xml
-	java -jar legacyworlds-server-main-1.0.0-0.jar \
-		--run-tool ImportTechGraph data/tech-graph.xml
-	java -jar legacyworlds-server-main-1.0.0-0.jar \
-		--run-tool ImportResources data/resources.xml
-	java -jar legacyworlds-server-main-1.0.0-0.jar \
-		--run-tool ImportBuildables data/buildables.xml 
-
-
-5) Run the server for a few seconds by typing:
-
-	java -jar legacyworlds-server-main-1.0.0-0.jar
-
-Stop it by running
-
-	java -jar legacyworlds-server-main-1.0.0-0.jar  --run-tool Stop
-
-in another terminal.
-
-
-6) Create the server's super user. First, create an inactive user account:
-
-	java -jar legacyworlds-server-main-1.0.0-0.jar --run-tool CreateUser
-	
-The tool will prompt for an email address, password (which /will/ appear on the
-console) and language identifier ('en' or 'fr' are supported). Please note that
-the usual password strength restrictions apply.
-
-Once this has been completed, make this user a superuser by running:
-
-	java -jar legacyworlds-server-main-1.0.0-0.jar \
-		--run-tool CreateSuperuser 'user@example.org VisibleName'
-
-Replace 'user@example.org' with the user's actual email address, and
-'VisibleName' with the name of the administrator as seen by the users.
-
-
-7) Web sites:
-	* Set up a local Tomcat instance.
-	* Make sure its manager application is enabled.
-	* Make sure there is a local, XML-based user database configured.
-	* Create an "admin" user with an empty password and the "manager" role.
-	* From the legacyworlds/ directory, run:
-		mvn package tomcat:deploy
-	This will deploy the main and administrative sites to /lwmain and /lwadmin,
-respectively.
-	* If you need to redeploy the sites later, you need to run
-		mvn package tomcat:redeploy
diff --git a/legacyworlds/doc/spring-configuration.txt b/legacyworlds/doc/spring-configuration.txt
deleted file mode 100644
index 2eda413..0000000
--- a/legacyworlds/doc/spring-configuration.txt
+++ /dev/null
@@ -1,77 +0,0 @@
-Spring configuration files
-===========================
-
-A lot of the game's code (whether on the server side or on the web clients)
-relies on the Spring framework. For most of the components, it is easier to
-use XML configuration files rather than in-code configuration. This file
-describes the common elements and guidelines to follow for the configuration
-files.
-
-
-Files in the main server package:
-
-	lw-server.xml					Main configuration file
-	
-		This file contains the server's top-level configuration. It enables
-		annotation-based component processing, adds the server termination
-		component, and loads the configuration files for all elements of the
-		server: transaction management, meta components, game components for
-		both the "real" game and the "simple" implementation written for
-		Milestone 1, session type definitions and commands.
-
-	configuration/game.xml			"Real" game components
-
-		This file acts as a loader for all configuration files the load
-		elements of the "real" game - that is, parts of the game which have
-		taken (or are taking) the form they should have in the final version.
-
-	configuration/meta.xml			Meta components
-
-		This file loads the configuration files for all "meta" components.
-		A "meta" component is any component which is not directly related to
-		the game itself, but it still necessary: for example account
-		management or the bug tracking system fall into this category.
-
-	configuration/transactions.xml	Transaction manager configuration
-
-		This file contains the configuration for Spring's transaction
-		management system. It defines the transaction manager and enables
-		annotation-based transaction processing.
-
-
-Files in general component definition packages:
-
-	Most of the component definition packages will include one single
-	configuration file which loads the components the package defines. This
-	file will be found in either configuration/meta/ or configuration/game/
-	depending on the purpose of the components. The file in question will
-	be loaded from the corresponding file in the main server package.
-
-
-Files in the legacyworlds-server-beans-simple package:
-
-	This package includes its own top-level configuration file, unsurprisingly
-	named configuration/simple.xml, which is included in the server's top-level
-	configuration and loads all files in the configuration/simple/
-	sub-directory. Since it corresponds to Milestone 1's "simple" game
-	implementation, it should only be modified to remove components as they
-	are moved or replaced.
-
-
-Files in the legacyworlds-server-beans-user package:
-
-	This package includes a "meta" components configuration file, which loads
-	low-level session management components. In addition, it features the
-	following configuration files:
-	
-		configuration/session-types.xml		Session types loader
-
-			This file loads the configuration files for each specific type of
-			session.
-
-		configuration/session-types/		Session types definitions
-
-			This directory contains configuration files which loads all
-			components for some type of session. Each file should therefore
-			load at least one session definer component, and a bunch of
-			command handling components.
\ No newline at end of file
diff --git a/legacyworlds/doc/workflow.txt b/legacyworlds/doc/workflow.txt
deleted file mode 100644
index 77a2d4d..0000000
--- a/legacyworlds/doc/workflow.txt
+++ /dev/null
@@ -1,53 +0,0 @@
-Legacy Worlds development work flow
-====================================
-
-Development is based off a set of Git repositories on the web-based repository
-server. All repositories can be found under https://svn.legacyworlds.com/git/
-
-
-Repositories
--------------
-
-* Developer repositories: each developer has access to a personal repository,
-  under dev/{developer name} on the server. All developers have read access to
-  the others' repositories.
-
-  Address: https://svn.legacyworlds.com/git/dev/{developer name}
-
-* Staging repository: this repository is meant to be used as the source for
-  all local repositories. All developers may read from it. However, only
-  TSeeker can push code to it.
-
-  Address: https://svn.legacyworlds.com/git/staging
-
-* Main repository: this repository contains the code that has been processed
-  by the build system, along with the binaries if the last build succeeded.
-  While all developers can read from it, it should not be used as the source
-  for local copies.
-
-  Address: https://svn.legacyworlds.com/git/main
-
-
-Branches
----------
-
-On the staging and main repositories, the following branches exist:
-
-* master - this is the main development branch. All code destined to end up
-  in the next version of Legacy Worlds lives there.
-
-* milestone1 - maintenance branch for Legacy Worlds Beta 6 milestone 1.
-
-
-Development process
---------------------
-
-Work on some branch on your local copy.
-	-> Don't hesitate to push to your developer repository on the server
-	   as a means of backup.
-	-> Rebase to the original branch whenever it changes.
-
-When you are done with your work on a branch:
- 1) push to some branch on your developer repository on the server,
- 2) notify TSeeker that the branch should be pulled to the staging repository.
-While this is easier to handle on IRC, a mail is fine as well.
diff --git a/legacyworlds/eclipse-code-cleanup.xml b/legacyworlds/eclipse-code-cleanup.xml
deleted file mode 100644
index 699d5f8..0000000
--- a/legacyworlds/eclipse-code-cleanup.xml
+++ /dev/null
@@ -1,56 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<profiles version="2">
-<profile kind="CleanUpProfile" name="Legacy Worlds" version="2">
-<setting id="cleanup.remove_unused_private_fields" value="true"/>
-<setting id="cleanup.always_use_parentheses_in_expressions" value="false"/>
-<setting id="cleanup.never_use_blocks" value="false"/>
-<setting id="cleanup.add_missing_deprecated_annotations" value="true"/>
-<setting id="cleanup.remove_unused_private_methods" value="true"/>
-<setting id="cleanup.convert_to_enhanced_for_loop" value="false"/>
-<setting id="cleanup.remove_unnecessary_nls_tags" value="true"/>
-<setting id="cleanup.sort_members" value="false"/>
-<setting id="cleanup.remove_unused_local_variables" value="false"/>
-<setting id="cleanup.remove_unused_private_members" value="false"/>
-<setting id="cleanup.never_use_parentheses_in_expressions" value="true"/>
-<setting id="cleanup.remove_unnecessary_casts" value="true"/>
-<setting id="cleanup.make_parameters_final" value="false"/>
-<setting id="cleanup.use_this_for_non_static_field_access" value="true"/>
-<setting id="cleanup.use_blocks" value="true"/>
-<setting id="cleanup.remove_private_constructors" value="true"/>
-<setting id="cleanup.always_use_this_for_non_static_method_access" value="true"/>
-<setting id="cleanup.remove_trailing_whitespaces_all" value="true"/>
-<setting id="cleanup.always_use_this_for_non_static_field_access" value="true"/>
-<setting id="cleanup.use_this_for_non_static_field_access_only_if_necessary" value="false"/>
-<setting id="cleanup.add_default_serial_version_id" value="true"/>
-<setting id="cleanup.make_type_abstract_if_missing_method" value="false"/>
-<setting id="cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class" value="true"/>
-<setting id="cleanup.make_variable_declarations_final" value="true"/>
-<setting id="cleanup.add_missing_nls_tags" value="false"/>
-<setting id="cleanup.format_source_code" value="true"/>
-<setting id="cleanup.add_missing_override_annotations" value="true"/>
-<setting id="cleanup.qualify_static_method_accesses_with_declaring_class" value="false"/>
-<setting id="cleanup.remove_unused_private_types" value="true"/>
-<setting id="cleanup.make_local_variable_final" value="false"/>
-<setting id="cleanup.add_missing_methods" value="false"/>
-<setting id="cleanup.add_missing_override_annotations_interface_methods" value="true"/>
-<setting id="cleanup.correct_indentation" value="false"/>
-<setting id="cleanup.remove_unused_imports" value="true"/>
-<setting id="cleanup.remove_trailing_whitespaces_ignore_empty" value="false"/>
-<setting id="cleanup.make_private_fields_final" value="true"/>
-<setting id="cleanup.add_generated_serial_version_id" value="false"/>
-<setting id="cleanup.organize_imports" value="true"/>
-<setting id="cleanup.sort_members_all" value="false"/>
-<setting id="cleanup.remove_trailing_whitespaces" value="true"/>
-<setting id="cleanup.use_blocks_only_for_return_and_throw" value="false"/>
-<setting id="cleanup.use_parentheses_in_expressions" value="false"/>
-<setting id="cleanup.add_missing_annotations" value="true"/>
-<setting id="cleanup.qualify_static_field_accesses_with_declaring_class" value="false"/>
-<setting id="cleanup.use_this_for_non_static_method_access_only_if_necessary" value="false"/>
-<setting id="cleanup.use_this_for_non_static_method_access" value="true"/>
-<setting id="cleanup.qualify_static_member_accesses_through_instances_with_declaring_class" value="true"/>
-<setting id="cleanup.add_serial_version_id" value="false"/>
-<setting id="cleanup.always_use_blocks" value="true"/>
-<setting id="cleanup.qualify_static_member_accesses_with_declaring_class" value="true"/>
-<setting id="cleanup.format_source_code_changes_only" value="false"/>
-</profile>
-</profiles>
diff --git a/legacyworlds/pom.xml b/legacyworlds/pom.xml
deleted file mode 100644
index 0cd04f8..0000000
--- a/legacyworlds/pom.xml
+++ /dev/null
@@ -1,371 +0,0 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-	<modelVersion>4.0.0</modelVersion>
-	<groupId>com.deepclone.lw</groupId>
-	<artifactId>legacyworlds</artifactId>
-	<version>1.0.0</version>
-	<packaging>pom</packaging>
-	<name>Legacy Worlds</name>
-	<description>Main Maven project for LW</description>
-
-	<!--
-	   - BUILD CONFIGURATION
-	   -
-	   - Make sure everything is built for and using Java 6, and declare all
-	   - other plug-ins to ease upgrades.
-	 -->
-	<build>
-		<plugins>
-			<plugin>
-				<groupId>org.apache.maven.plugins</groupId>
-				<artifactId>maven-compiler-plugin</artifactId>
-				<version>2.3.2</version>
-				<configuration>
-					<source>1.6</source>
-					<target>1.6</target>
-				</configuration>
-			</plugin>
-		</plugins>
-		
-		<pluginManagement>
-			<plugins>
-
-				<plugin>
-					<groupId>org.apache.maven.plugins</groupId>
-					<artifactId>maven-assembly-plugin</artifactId>
-					<version>2.2.2</version>
-				</plugin>
-
-				<plugin>
-					<groupId>org.apache.maven.plugins</groupId>
-					<artifactId>maven-jar-plugin</artifactId>
-					<version>2.3.2</version>
-				</plugin>
-
-				<plugin>
-					<groupId>org.apache.maven.plugins</groupId>
-					<artifactId>maven-war-plugin</artifactId>
-					<version>2.1.1</version>
-				</plugin>
-				
-				<plugin>
-					<groupId>org.codehaus.mojo</groupId>
-					<artifactId>tomcat-maven-plugin</artifactId>
-					<version>1.1</version>
-				</plugin>
-				
-				<plugin>
-					<groupId>org.apache.maven.plugins</groupId>
-					<artifactId>maven-clean-plugin</artifactId>
-					<version>2.4.1</version>
-				</plugin>
-
-			</plugins>
-		</pluginManagement>
-	</build>
-
-	<!--
-	   - REPOSITORIES
-	   -
-	   - We need the Spring framework's own repository
-	  -->
-	<repositories>
-
-		<repository>
-			<id>com.springsource.repository.bundles.release</id>
-			<name>Spring framework</name>
-			<url>http://repo.springsource.org/release</url>
-		</repository>
-
-	</repositories>
-
-
-	<properties>
-		<!-- Make sure the source is seen as UTF8 -->
-		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-
-		<!--
-		   - VERSION NUMBERS
-		   -
-		   - These properties are used in sub-modules to identify the
-		   - current version and build number of the files.
-		   -
-		   - They are set by the build system, and should NEVER be changed
-		   - manually.
-		  -->
-		<legacyworlds.version.main>1.0</legacyworlds.version.main>
-		<legacyworlds.version.release>0</legacyworlds.version.release>
-		<legacyworlds.version.build>0</legacyworlds.version.build>
-		<legacyworlds.version.string>DEV</legacyworlds.version.string>
-
-		<!--
-		   - DEPENDENCY VERSIONS
-		  -->
-		<dep.springframework>3.1.0.RELEASE</dep.springframework>
-		<dep.slf4j>1.6.4</dep.slf4j>
-		<dep.log4j>1.2.16</dep.log4j>
-		<dep.dbcp>1.4</dep.dbcp>
-		<dep.codecs>1.6</dep.codecs>
-		<dep.cglib>2.2.2</dep.cglib>
-		<dep.mail>1.4.4</dep.mail>
-		<dep.xstream>1.4.2</dep.xstream>
-		<dep.junit>4.10</dep.junit>
-		<dep.freemarker>2.3.18</dep.freemarker>
-		<dep.servlet>2.5</dep.servlet>
-		<dep.postgresql>9.1-901.jdbc4</dep.postgresql>
-	</properties>
-
-
-	<!--
-	   - DEPENDENCY MANAGEMENT
-	  -->
-	<dependencyManagement>
-		<dependencies>
-
-			<!-- INTERNAL DEPENDENCIES -->
-			<dependency>
-				<artifactId>legacyworlds-server-beans-accounts</artifactId>
-				<groupId>com.deepclone.lw</groupId>
-				<version>${legacyworlds.version.main}.${legacyworlds.version.release}-${legacyworlds.version.build}</version>
-			</dependency>
-			<dependency>
-				<artifactId>legacyworlds-server-beans-bt</artifactId>
-				<groupId>com.deepclone.lw</groupId>
-				<version>${legacyworlds.version.main}.${legacyworlds.version.release}-${legacyworlds.version.build}</version>
-			</dependency>
-			<dependency>
-				<artifactId>legacyworlds-server-beans-eventlog</artifactId>
-				<groupId>com.deepclone.lw</groupId>
-				<version>${legacyworlds.version.main}.${legacyworlds.version.release}-${legacyworlds.version.build}</version>
-			</dependency>
-			<dependency>
-				<artifactId>legacyworlds-server-beans-events</artifactId>
-				<groupId>com.deepclone.lw</groupId>
-				<version>${legacyworlds.version.main}.${legacyworlds.version.release}-${legacyworlds.version.build}</version>
-			</dependency>
-			<dependency>
-				<artifactId>legacyworlds-server-beans-i18n</artifactId>
-				<groupId>com.deepclone.lw</groupId>
-				<version>${legacyworlds.version.main}.${legacyworlds.version.release}-${legacyworlds.version.build}</version>
-			</dependency>
-			<dependency>
-				<artifactId>legacyworlds-server-beans-mailer</artifactId>
-				<groupId>com.deepclone.lw</groupId>
-				<version>${legacyworlds.version.main}.${legacyworlds.version.release}-${legacyworlds.version.build}</version>
-			</dependency>
-			<dependency>
-				<artifactId>legacyworlds-server-beans-naming</artifactId>
-				<groupId>com.deepclone.lw</groupId>
-				<version>${legacyworlds.version.main}.${legacyworlds.version.release}-${legacyworlds.version.build}</version>
-			</dependency>
-			<dependency>
-				<artifactId>legacyworlds-server-beans-resources</artifactId>
-				<groupId>com.deepclone.lw</groupId>
-				<version>${legacyworlds.version.main}.${legacyworlds.version.release}-${legacyworlds.version.build}</version>
-			</dependency>
-			<dependency>
-				<artifactId>legacyworlds-server-beans-simple</artifactId>
-				<groupId>com.deepclone.lw</groupId>
-				<version>${legacyworlds.version.main}.${legacyworlds.version.release}-${legacyworlds.version.build}</version>
-			</dependency>
-			<dependency>
-				<artifactId>legacyworlds-server-beans-system</artifactId>
-				<groupId>com.deepclone.lw</groupId>
-				<version>${legacyworlds.version.main}.${legacyworlds.version.release}-${legacyworlds.version.build}</version>
-			</dependency>
-			<dependency>
-				<artifactId>legacyworlds-server-beans-technologies</artifactId>
-				<groupId>com.deepclone.lw</groupId>
-				<version>${legacyworlds.version.main}.${legacyworlds.version.release}-${legacyworlds.version.build}</version>
-			</dependency>
-			<dependency>
-				<artifactId>legacyworlds-server-beans-updates</artifactId>
-				<groupId>com.deepclone.lw</groupId>
-				<version>${legacyworlds.version.main}.${legacyworlds.version.release}-${legacyworlds.version.build}</version>
-			</dependency>
-			<dependency>
-				<artifactId>legacyworlds-server-beans-user</artifactId>
-				<groupId>com.deepclone.lw</groupId>
-				<version>${legacyworlds.version.main}.${legacyworlds.version.release}-${legacyworlds.version.build}</version>
-			</dependency>
-			<dependency>
-				<groupId>com.deepclone.lw</groupId>
-				<artifactId>legacyworlds-server-data</artifactId>
-				<version>${legacyworlds.version.main}.${legacyworlds.version.release}-${legacyworlds.version.build}</version>
-			</dependency>
-			<dependency>
-				<groupId>com.deepclone.lw</groupId>
-				<artifactId>legacyworlds-server-interfaces</artifactId>
-				<version>${legacyworlds.version.main}.${legacyworlds.version.release}-${legacyworlds.version.build}</version>
-			</dependency>
-			<dependency>
-				<groupId>com.deepclone.lw</groupId>
-				<artifactId>legacyworlds-server-main</artifactId>
-				<version>${legacyworlds.version.main}.${legacyworlds.version.release}-${legacyworlds.version.build}</version>
-			</dependency>
-			<dependency>
-				<groupId>com.deepclone.lw</groupId>
-				<artifactId>legacyworlds-session</artifactId>
-				<version>${legacyworlds.version.main}.${legacyworlds.version.release}-${legacyworlds.version.build}</version>
-			</dependency>
-			<dependency>
-				<groupId>com.deepclone.lw</groupId>
-				<artifactId>legacyworlds-server-utils</artifactId>
-				<version>${legacyworlds.version.main}.${legacyworlds.version.release}-${legacyworlds.version.build}</version>
-			</dependency>
-			<dependency>
-				<groupId>com.deepclone.lw</groupId>
-				<artifactId>legacyworlds-session</artifactId>
-				<version>${legacyworlds.version.main}.${legacyworlds.version.release}-${legacyworlds.version.build}</version>
-			</dependency>
-			<dependency>
-				<groupId>com.deepclone.lw</groupId>
-				<artifactId>legacyworlds-utils</artifactId>
-				<version>${legacyworlds.version.main}.${legacyworlds.version.release}-${legacyworlds.version.build}</version>
-			</dependency>
-			<dependency>
-				<groupId>com.deepclone.lw</groupId>
-				<artifactId>legacyworlds-web-beans</artifactId>
-				<version>${legacyworlds.version.main}.${legacyworlds.version.release}-${legacyworlds.version.build}</version>
-			</dependency>
-
-			<!-- EXTERNAL DEPENDENCIES -->
-
-			<!-- XStream -->
-			<dependency>
-				<groupId>com.thoughtworks.xstream</groupId>
-				<artifactId>xstream</artifactId>
-				<version>${dep.xstream}</version>
-			</dependency>
-
-			<!-- Spring framework -->
-			<dependency>
-				<groupId>org.springframework</groupId>
-				<artifactId>spring-core</artifactId>
-				<version>${dep.springframework}</version>
-			</dependency>
-			<dependency>
-				<groupId>org.springframework</groupId>
-				<artifactId>spring-context</artifactId>
-				<version>${dep.springframework}</version>
-				<exclusions>
-					<exclusion>
-						<groupId>commons-logging</groupId>
-						<artifactId>commons-logging</artifactId>
-					</exclusion>
-				</exclusions>
-			</dependency>
-			<dependency>
-				<groupId>org.springframework</groupId>
-				<artifactId>spring-jdbc</artifactId>
-				<version>${dep.springframework}</version>
-			</dependency>
-			<dependency>
-				<groupId>org.springframework</groupId>
-				<artifactId>spring-context-support</artifactId>
-				<version>${dep.springframework}</version>
-			</dependency>
-			<dependency>
-				<groupId>org.springframework</groupId>
-				<artifactId>spring-test</artifactId>
-				<version>${dep.springframework}</version>
-			</dependency>
-			<dependency>
-				<groupId>org.springframework</groupId>
-				<artifactId>spring-webmvc</artifactId>
-				<version>${dep.springframework}</version>
-			</dependency>
-
-			<!-- Logging (SLF4J + Log4J) -->
-			<dependency>
-				<groupId>org.slf4j</groupId>
-				<artifactId>jcl-over-slf4j</artifactId>
-				<version>${dep.slf4j}</version>
-			</dependency>
-			<dependency>
-				<groupId>org.slf4j</groupId>
-				<artifactId>slf4j-api</artifactId>
-				<version>${dep.slf4j}</version>
-			</dependency>
-			<dependency>
-				<groupId>org.slf4j</groupId>
-				<artifactId>slf4j-log4j12</artifactId>
-				<version>${dep.slf4j}</version>
-			</dependency>
-
-			<dependency>
-				<groupId>log4j</groupId>
-				<artifactId>log4j</artifactId>
-				<version>${dep.log4j}</version>
-			</dependency>
-
-			<!-- Apache commons -->
-			<dependency>
-				<groupId>commons-codec</groupId>
-				<artifactId>commons-codec</artifactId>
-				<version>${dep.codecs}</version>
-			</dependency>
-			<dependency>
-				<groupId>commons-dbcp</groupId>
-				<artifactId>commons-dbcp</artifactId>
-				<version>${dep.dbcp}</version>
-			</dependency>
-
-			<!-- Code generation library -->
-			<dependency>
-				<groupId>cglib</groupId>
-				<artifactId>cglib</artifactId>
-				<version>${dep.cglib}</version>
-			</dependency>
-
-			<!-- Java Mail extension -->
-			<dependency>
-				<groupId>javax.mail</groupId>
-				<artifactId>mail</artifactId>
-				<version>${dep.mail}</version>
-			</dependency>
-
-			<!-- PostgreSQL -->
-			<dependency>
-				<groupId>postgresql</groupId>
-				<artifactId>postgresql</artifactId>
-				<version>${dep.postgresql}</version>
-			</dependency>
-
-
-			<!-- JUnit -->
-			<dependency>
-				<groupId>junit</groupId>
-				<artifactId>junit</artifactId>
-				<version>${dep.junit}</version>
-			</dependency>
-
-
-			<!-- Web stuff (FreeMarker, servlet specs, etc...) -->
-			<dependency>
-				<groupId>javax.servlet</groupId>
-				<artifactId>servlet-api</artifactId>
-				<version>${dep.servlet}</version>
-			</dependency>
-			<dependency>
-				<groupId>org.freemarker</groupId>
-				<artifactId>freemarker</artifactId>
-				<version>${dep.freemarker}</version>
-			</dependency>
-
-		</dependencies>
-	</dependencyManagement>
-
-
-	<!--
-	   - MODULES
-	  -->
-	<modules>
-		<module>../legacyworlds-server</module>
-		<module>../legacyworlds-session</module>
-		<module>../legacyworlds-tests</module>
-		<module>../legacyworlds-utils</module>
-		<module>../legacyworlds-web</module>
-	</modules>
-
-</project>
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..e1ad570
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,72 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+	<groupId>com.deepclone.lw</groupId>
+	<artifactId>legacyworlds</artifactId>
+	<version>5.99.2</version>
+	<packaging>pom</packaging>
+	<name>Legacy Worlds</name>
+	<description>Main Maven project for LW</description>
+
+	<build>
+		<plugins>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-compiler-plugin</artifactId>
+				<version>2.2</version>
+				<configuration>
+					<source>1.6</source>
+					<target>1.6</target>
+				</configuration>
+			</plugin>
+		</plugins>
+	</build>
+
+	<repositories>
+
+		<repository>
+			<id>com.springsource.repository.bundles.release</id>
+			<name>Spring framework</name>
+			<url>http://repository.springsource.com/maven/bundles/release</url>
+		</repository>
+		<repository>
+			<id>com.springsource.repository.bundles.external</id>
+			<name>Spring framework - external</name>
+			<url>http://repository.springsource.com/maven/bundles/external</url>
+		</repository>
+
+		<repository>
+			<id>jboss</id>
+			<url>http://repository.jboss.com/maven2</url>
+			<releases>
+				<enabled>true</enabled>
+			</releases>
+			<snapshots>
+				<enabled>false</enabled>
+			</snapshots>
+		</repository>
+
+	</repositories>
+
+	<properties>
+		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+		<org.springframework.version>3.0.5.RELEASE</org.springframework.version>
+		<log4j.version>1.2.16</log4j.version>
+		<org.slf4j.version>1.6.1</org.slf4j.version>
+		<commons.dbcp.version>1.4</commons.dbcp.version>
+		<commons.codec.version>1.4</commons.codec.version>
+		<cglib.version>2.2</cglib.version>
+		<javax.mail.version>1.4.1</javax.mail.version>
+		<com.thoughtworks.xstream.version>1.3.1</com.thoughtworks.xstream.version>
+		<junit.version>4.8.2</junit.version>
+		<org.freemarker.version>2.3.16</org.freemarker.version>
+	</properties>
+
+	<modules>
+		<module>legacyworlds-server</module>
+		<module>legacyworlds-session</module>
+		<module>legacyworlds-web</module>
+		<module>legacyworlds-utils</module>
+	</modules>
+
+</project>
\ No newline at end of file
diff --git a/runsrv.sh b/runsrv.sh
new file mode 100755
index 0000000..226099d
--- /dev/null
+++ b/runsrv.sh
@@ -0,0 +1,4 @@
+#!/bin/sh
+BASE="`dirname $0`"
+cd "$BASE/legacyworlds-server/legacyworlds-server-main"
+java -Djava.rmi.server.hostname=localhost -jar target/legacyworlds-server-main-5.99.2.jar
diff --git a/runtool.sh b/runtool.sh
new file mode 100755
index 0000000..037ac04
--- /dev/null
+++ b/runtool.sh
@@ -0,0 +1,4 @@
+#!/bin/sh
+BASE="`dirname $0`"
+cd "$BASE/legacyworlds-server/legacyworlds-server-main"
+java -Djava.rmi.server.hostname=localhost -jar target/legacyworlds-server-main-5.99.2.jar --run-tool $1 "$2"