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
new file mode 100644
index 0000000..39e7847
--- /dev/null
+++ b/legacyworlds-server-beans-resources/src/main/java/com/deepclone/lw/beans/game/resources/AbstractResourceMapper.java
@@ -0,0 +1,61 @@
+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
new file mode 100644
index 0000000..71e6b7c
--- /dev/null
+++ b/legacyworlds-server-beans-resources/src/main/java/com/deepclone/lw/beans/game/resources/EmpireResourceMapper.java
@@ -0,0 +1,72 @@
+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/PlanetResourceMapper.java b/legacyworlds-server-beans-resources/src/main/java/com/deepclone/lw/beans/game/resources/PlanetResourceMapper.java
new file mode 100644
index 0000000..f35426d
--- /dev/null
+++ b/legacyworlds-server-beans-resources/src/main/java/com/deepclone/lw/beans/game/resources/PlanetResourceMapper.java
@@ -0,0 +1,105 @@
+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/ResourcesInformationDAOBean.java b/legacyworlds-server-beans-resources/src/main/java/com/deepclone/lw/beans/game/resources/ResourcesInformationDAOBean.java
new file mode 100644
index 0000000..651d4e5
--- /dev/null
+++ b/legacyworlds-server-beans-resources/src/main/java/com/deepclone/lw/beans/game/resources/ResourcesInformationDAOBean.java
@@ -0,0 +1,99 @@
+package com.deepclone.lw.beans.game.resources;
+
+
+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.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 = ?";
+
+	/** Row mapper for planet resources */
+	private final PlanetResourceMapper mPlanetResource;
+
+	/** Row mapper for empire resources */
+	private final EmpireResourceMapper mEmpireResource;
+
+	/** Spring JDBC interface */
+	private JdbcTemplate dTemplate;
+
+
+	/** Initialise the necessary row mappers */
+	public ResourcesInformationDAOBean( )
+	{
+		this.mPlanetResource = new PlanetResourceMapper( );
+		this.mEmpireResource = new EmpireResourceMapper( );
+	}
+
+
+	/**
+	 * 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 );
+	}
+
+}
diff --git a/legacyworlds-server-beans-resources/src/main/resources/configuration/game/resources-beans.xml b/legacyworlds-server-beans-resources/src/main/resources/configuration/game/resources-beans.xml
new file mode 100644
index 0000000..2c36ed9
--- /dev/null
+++ b/legacyworlds-server-beans-resources/src/main/resources/configuration/game/resources-beans.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.1.xsd">
+
+	<bean id="resourcesInformationDAO" class="com.deepclone.lw.beans.game.resources.ResourcesInformationDAOBean" />
+
+</beans>
diff --git a/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/empire/EmpireManagementBean.java b/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/empire/EmpireManagementBean.java
index 18a9571..2d769f3 100644
--- a/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/empire/EmpireManagementBean.java
+++ b/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/empire/EmpireManagementBean.java
@@ -25,6 +25,7 @@ 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.naming.NamingDAO;
 import com.deepclone.lw.interfaces.prefs.AccountPreferences;
 import com.deepclone.lw.interfaces.prefs.PreferencesDAO;
@@ -46,6 +47,7 @@ public class EmpireManagementBean
 	private EmpireDAO empireDao;
 	private PreferencesDAO prefsDao;
 	private BattlesDAO battlesDao;
+	private ResourcesInformationDAO resourcesInformationDao;
 
 
 	@Autowired( required = true )
@@ -83,6 +85,13 @@ public class EmpireManagementBean
 	}
 
 
+	@Autowired( required = true )
+	public void setResourcesInformationDao( ResourcesInformationDAO resourcesInformationDao )
+	{
+		this.resourcesInformationDao = resourcesInformationDao;
+	}
+
+
 	@Override
 	public Integer getEmpireId( EmailAddress address )
 	{
@@ -103,8 +112,9 @@ 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 );
+		return new GamePageData( generalInformation.getName( ) , generalInformation.getStatus( ) ,
+				generalInformation.getTag( ) , generalInformation.getCash( ) , generalInformation.getNextTick( ) ,
+				planets , rlTime );
 	}
 
 
@@ -150,6 +160,8 @@ public class EmpireManagementBean
 			battles.add( entry );
 		}
 
+		overview.setEconomy( this.resourcesInformationDao.getEmpireInformation( empireId ) );
+
 		return new EmpireResponse( this.getGeneralInformation( empireId ) , overview , research , battles );
 	}
 
diff --git a/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/map/PlanetsManagementBean.java b/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/map/PlanetsManagementBean.java
index 709fe4b..0e364ca 100644
--- a/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/map/PlanetsManagementBean.java
+++ b/legacyworlds-server-beans-simple/src/main/java/com/deepclone/lw/beans/map/PlanetsManagementBean.java
@@ -19,6 +19,7 @@ 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;
@@ -36,6 +37,7 @@ public class PlanetsManagementBean
 	private EmpireManagement empireManagement;
 	private PlanetDAO planetDao;
 	private NamingDAO namingDao;
+	private ResourcesInformationDAO resourcesInformationDao;
 
 
 	@Autowired( required = true )
@@ -59,6 +61,13 @@ 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 ) {
@@ -107,6 +116,8 @@ public class PlanetsManagementBean
 		view.setbBuildings( this.planetDao.getAvailableBuildings( planetId ) );
 		view.setbShips( this.planetDao.getAvailableShips( planetId ) );
 
+		view.setResources( this.resourcesInformationDao.getPlanetInformation( planetId ) );
+
 		return view;
 	}
 
@@ -199,8 +210,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/resources/configuration/game.xml b/legacyworlds-server-beans-simple/src/main/resources/configuration/game.xml
new file mode 100644
index 0000000..952f3f6
--- /dev/null
+++ b/legacyworlds-server-beans-simple/src/main/resources/configuration/game.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.1.xsd">
+
+	<import resource="game/resources-beans.xml" />
+
+</beans>
\ 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
index 3a47212..4a7fa06 100644
--- a/legacyworlds-server-data/db-structure/parts/040-functions/025-resources.sql
+++ b/legacyworlds-server-data/db-structure/parts/040-functions/025-resources.sql
@@ -505,3 +505,59 @@ GRANT EXECUTE
 			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/040-empire.sql b/legacyworlds-server-data/db-structure/parts/040-functions/040-empire.sql
index 63ac90e..cb30603 100644
--- a/legacyworlds-server-data/db-structure/parts/040-functions/040-empire.sql
+++ b/legacyworlds-server-data/db-structure/parts/040-functions/040-empire.sql
@@ -668,4 +668,112 @@ 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;
\ No newline at end of file
+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;
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
index 0dfccb2..74b758b 100644
--- 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
@@ -139,3 +139,139 @@ REVOKE EXECUTE
 		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;
+
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
new file mode 100644
index 0000000..f5a59ba
--- /dev/null
+++ b/legacyworlds-server-data/db-structure/tests/admin/040-functions/025-resources/050-resource-category-weight-view.sql
@@ -0,0 +1,47 @@
+/*
+ * 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
new file mode 100644
index 0000000..aecee23
--- /dev/null
+++ b/legacyworlds-server-data/db-structure/tests/admin/040-functions/025-resources/060-ordered-resources-view.sql
@@ -0,0 +1,57 @@
+/*
+ * 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/040-empire/020-planet-resources-view.sql b/legacyworlds-server-data/db-structure/tests/admin/040-functions/040-empire/020-planet-resources-view.sql
new file mode 100644
index 0000000..3130b92
--- /dev/null
+++ b/legacyworlds-server-data/db-structure/tests/admin/040-functions/040-empire/020-planet-resources-view.sql
@@ -0,0 +1,56 @@
+/*
+ * 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
new file mode 100644
index 0000000..8a38970
--- /dev/null
+++ b/legacyworlds-server-data/db-structure/tests/admin/040-functions/040-empire/030-resources-view.sql
@@ -0,0 +1,169 @@
+/*
+ * 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/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
new file mode 100644
index 0000000..39a081b
--- /dev/null
+++ b/legacyworlds-server-data/db-structure/tests/admin/040-functions/145-resource-providers/040-get-planet-resources.sql
@@ -0,0 +1,187 @@
+/*
+ * 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/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
new file mode 100644
index 0000000..17df905
--- /dev/null
+++ b/legacyworlds-server-data/db-structure/tests/user/040-functions/025-resources/050-resource-category-weight-view.sql
@@ -0,0 +1,11 @@
+/*
+ * 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
new file mode 100644
index 0000000..a632f1f
--- /dev/null
+++ b/legacyworlds-server-data/db-structure/tests/user/040-functions/025-resources/060-ordered-resources-view.sql
@@ -0,0 +1,11 @@
+/*
+ * 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/040-empire/020-planet-resources-view.sql b/legacyworlds-server-data/db-structure/tests/user/040-functions/040-empire/020-planet-resources-view.sql
new file mode 100644
index 0000000..619ad96
--- /dev/null
+++ b/legacyworlds-server-data/db-structure/tests/user/040-functions/040-empire/020-planet-resources-view.sql
@@ -0,0 +1,11 @@
+/*
+ * 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
new file mode 100644
index 0000000..817d0e1
--- /dev/null
+++ b/legacyworlds-server-data/db-structure/tests/user/040-functions/040-empire/030-resources-view.sql
@@ -0,0 +1,11 @@
+/*
+ * 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/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
new file mode 100644
index 0000000..e2ed935
--- /dev/null
+++ b/legacyworlds-server-data/db-structure/tests/user/040-functions/145-resource-providers/040-get-planet-resources.sql
@@ -0,0 +1,13 @@
+/*
+ * 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/utils/strings.sql b/legacyworlds-server-data/db-structure/tests/utils/strings.sql
index 33ead96..3303ae3 100644
--- a/legacyworlds-server-data/db-structure/tests/utils/strings.sql
+++ b/legacyworlds-server-data/db-structure/tests/utils/strings.sql
@@ -29,24 +29,11 @@ CREATE FUNCTION _get_string( TEXT ) RETURNS INT AS $$
 $$ LANGUAGE SQL;
 
 
-/*
- * Function that creates some quantity of test strings
- */
-CREATE FUNCTION _create_test_strings( _quantity INT )
-		RETURNS VOID
-	AS $$
-DECLARE
-	i	INT;
-BEGIN
-	PERFORM _create_test_strings( _quantity , 'test' );
-END;
-$$ LANGUAGE PLPGSQL;
-
-
 /*
  * Function that creates some quantity of test strings using a specific prefix
+ * and translation prefix.
  */
-CREATE FUNCTION _create_test_strings( _quantity INT , _prefix TEXT )
+CREATE FUNCTION _create_test_strings( _quantity INT , _prefix TEXT , _trans TEXT )
 		RETURNS VOID
 	AS $$
 DECLARE
@@ -59,7 +46,27 @@ BEGIN
 	LOOP
 		i := i + 1;
 		PERFORM defs.uoc_translation( 't' , _prefix || i::TEXT ,
-			'Test string #' || 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-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
new file mode 100644
index 0000000..5c88115
--- /dev/null
+++ b/legacyworlds-server-interfaces/src/main/java/com/deepclone/lw/interfaces/game/resources/ResourcesInformationDAO.java
@@ -0,0 +1,43 @@
+package com.deepclone.lw.interfaces.game.resources;
+
+
+import java.util.List;
+
+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 );
+}
diff --git a/legacyworlds-server-main/src/main/resources/lw-server.xml b/legacyworlds-server-main/src/main/resources/lw-server.xml
index cf7c8ea..081b882 100644
--- a/legacyworlds-server-main/src/main/resources/lw-server.xml
+++ b/legacyworlds-server-main/src/main/resources/lw-server.xml
@@ -13,14 +13,13 @@
 	<!-- Load transaction manager -->
 	<import resource="configuration/transaction-bean.xml" />
 
-	<!-- Load all server beans -->
+	<!-- Load all system and low-level 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/user-beans.xml" />
 
@@ -29,5 +28,4 @@
 	<import resource="configuration/game.xml" />
 	<import resource="configuration/simple-beans.xml" />
 
-
 </beans>
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
new file mode 100644
index 0000000..4a0cd03
--- /dev/null
+++ b/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/game/resources/TestAbstractResourceMapper.java
@@ -0,0 +1,126 @@
+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
new file mode 100644
index 0000000..f9966ab
--- /dev/null
+++ b/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/game/resources/TestEmpireResourceMapper.java
@@ -0,0 +1,104 @@
+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/TestPlanetResourceMapper.java b/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/game/resources/TestPlanetResourceMapper.java
new file mode 100644
index 0000000..5f2990f
--- /dev/null
+++ b/legacyworlds-server-tests/src/test/java/com/deepclone/lw/beans/game/resources/TestPlanetResourceMapper.java
@@ -0,0 +1,131 @@
+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/testing/MockResultSet.java b/legacyworlds-server-tests/src/test/java/com/deepclone/lw/testing/MockResultSet.java
index da5bd52..fc92bed 100644
--- 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
@@ -225,6 +225,28 @@ public class MockResultSet
 	}
 
 
+	/**
+	 * 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
 	 * 
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
new file mode 100644
index 0000000..605a4ac
--- /dev/null
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/AbstractResourceRecord.java
@@ -0,0 +1,109 @@
+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/empire/EmpireResourceRecord.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/empire/EmpireResourceRecord.java
new file mode 100644
index 0000000..9a9bd64
--- /dev/null
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/empire/EmpireResourceRecord.java
@@ -0,0 +1,152 @@
+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 d82cc66..9858969 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,6 +2,7 @@ package com.deepclone.lw.cmd.player.gdata.empire;
 
 
 import java.io.Serializable;
+import java.util.List;
 
 
 
@@ -9,124 +10,234 @@ public class OverviewData
 		implements Serializable
 {
 
-	private static final long serialVersionUID = 1L;
+	/**
+	 * 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;
 
+	/** 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 planets;
+		return this.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 newMessages;
+		return this.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 population;
+		return this.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 avgHappiness;
+		return this.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 fleetPower;
+		return this.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 planetIncome;
+		return this.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 planetUpkeep;
+		return this.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 fleetUpkeep;
+		return this.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 investment;
+		return this.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/planets/PlanetOwnView.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/planets/PlanetOwnView.java
index a567a8e..9dfc71f 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
@@ -6,128 +6,283 @@ import java.util.List;
 
 
 
+/**
+ * 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
 {
 
-	private static final long serialVersionUID = 1L;
+	/**
+	 * 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;
 
+	/** 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 happiness;
+		return this.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 hChange;
+		return this.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 income;
+		return this.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 upkeep;
+		return this.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 status;
+		return this.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 civQueue;
+		return this.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 milQueue;
+		return this.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 bShips;
+		return this.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 bBuildings;
+		return this.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
new file mode 100644
index 0000000..704e422
--- /dev/null
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/planets/PlanetResourceRecord.java
@@ -0,0 +1,125 @@
+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/ResourceProviderRecord.java b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/planets/ResourceProviderRecord.java
new file mode 100644
index 0000000..dee594d
--- /dev/null
+++ b/legacyworlds-session/src/main/java/com/deepclone/lw/cmd/player/gdata/planets/ResourceProviderRecord.java
@@ -0,0 +1,117 @@
+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-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
new file mode 100644
index 0000000..e4a0e5c
--- /dev/null
+++ b/legacyworlds-tests/src/test/java/com/deepclone/lw/cmd/player/gdata/TestAbstractResourceRecord.java
@@ -0,0 +1,88 @@
+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
new file mode 100644
index 0000000..02f3ea7
--- /dev/null
+++ b/legacyworlds-tests/src/test/java/com/deepclone/lw/cmd/player/gdata/empire/TestEmpireResourceRecord.java
@@ -0,0 +1,125 @@
+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
new file mode 100644
index 0000000..30818de
--- /dev/null
+++ b/legacyworlds-tests/src/test/java/com/deepclone/lw/cmd/player/gdata/planets/TestPlanetResourceRecord.java
@@ -0,0 +1,82 @@
+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
new file mode 100644
index 0000000..cac3037
--- /dev/null
+++ b/legacyworlds-tests/src/test/java/com/deepclone/lw/cmd/player/gdata/planets/TestResourceProviderRecord.java
@@ -0,0 +1,83 @@
+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-web-main/Content/Raw/WEB-INF/fm/en/game.ftl b/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/game.ftl
index f9518eb..122c93a 100644
--- a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/game.ftl
+++ b/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/game.ftl
@@ -63,4 +63,11 @@
 </#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>
\ No newline at end of file
+<#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
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/overview.ftl b/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/overview.ftl
index af04b79..639de56 100644
--- a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/overview.ftl
+++ b/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/overview.ftl
@@ -61,7 +61,64 @@
 		
 			</@right_column>
 		</@tab>
+
+		<@tab id="economy" title="Economy">
 		
+			<@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>
+								<#switch resource.miningPriority>
+									<#case 0>lowest<#break>
+									<#case 1>low<#break>
+									<#case 2>normal<#break>
+									<#case 3>high<#break>
+									<#case 4>highest<#break>
+								</#switch>
+							<#else>
+								N/A
+							</#if>
+						</@lv_column>
+					</@lv_line>
+
+				</#list>
+
+			</@listview>
+
+		</@tab>
+
 		<@tab id="research" title="Research">
 			<#if rs?size == 0>
 				<p>Our scientists are still settling in.</p>
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/planet.ftl b/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/planet.ftl
index f32d709..7f3649c 100644
--- a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/planet.ftl
+++ b/legacyworlds-web-main/Content/Raw/WEB-INF/fm/en/types/planet.ftl
@@ -108,6 +108,55 @@
 			</#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>
 		
@@ -143,6 +192,7 @@
 												<#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>
@@ -189,6 +239,7 @@
 														<#case "DEF">defence<#break>
 														<#case "WORK">mil. output<#break>
 														<#case "POP">growth<#break>
+														<#case "MINE">res. extraction<#break>
 													</#switch>
 												</@dt_entry>
 											</@dt_main>
@@ -251,6 +302,7 @@
 			</#if>
 
 			<#if data.own?has_content>
+
 				<@tab id="ships" title="Shipyards">
 					<#if data.page.special! != 'v'>
 						<#if data.own.milQueue.appendPossible>
@@ -321,9 +373,60 @@
 						</@listview>
 					</#if>
 				</@tab>
-			</#if>
-		</#if>
 
+			</#if>
+			
+			<#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">
+				
+					<@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>
+										<#switch resProv.priority>
+											<#case 0>lowest<#break>
+											<#case 1>low<#break>
+											<#case 2>normal<#break>
+											<#case 3>high<#break>
+											<#case 4>highest<#break>
+										</#switch>
+									</@lv_column>
+								</@lv_line>
+
+							</#if>
+						</#list>
+					</@listview>
+
+				</@tab>
+			</#if>
+
+		</#if>
+		
 	</@tabs>
 </@page>
 </#macro>
\ No newline at end of file
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/game.ftl b/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/game.ftl
index 81e8aa9..b0c8a1a 100644
--- a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/game.ftl
+++ b/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/game.ftl
@@ -63,4 +63,11 @@
 </#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>
\ No newline at end of file
+<#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
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/overview.ftl b/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/overview.ftl
index 919f8e9..5bf71e8 100644
--- a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/overview.ftl
+++ b/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/overview.ftl
@@ -62,6 +62,63 @@
 			</@right_column>
 		</@tab>
 		
+		<@tab id="economy" title="Économie">
+		
+			<@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>
+								<#switch resource.miningPriority>
+									<#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>
+							<#else>
+								N/A
+							</#if>
+						</@lv_column>
+					</@lv_line>
+
+				</#list>
+
+			</@listview>
+
+		</@tab>
+		
 		<@tab id="research" title="Recherche">
 			<#if rs?size == 0>
 				<p>Nos scientifiques sont encore en train de s'installer.</p>
diff --git a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/planet.ftl b/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/planet.ftl
index 1aed9bf..5f6fadd 100644
--- a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/planet.ftl
+++ b/legacyworlds-web-main/Content/Raw/WEB-INF/fm/fr/types/planet.ftl
@@ -108,6 +108,55 @@
 			</#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>
 		
@@ -143,6 +192,7 @@
 												<#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>
@@ -189,6 +239,7 @@
 														<#case "DEF">défense<#break>
 														<#case "WORK">production mil.<#break>
 														<#case "POP">croissance<#break>
+														<#case "MINE">extraction<#break>
 													</#switch>
 												</@dt_entry>
 											</@dt_main>
@@ -322,6 +373,56 @@
 					</#if>
 				</@tab>
 			</#if>
+
+			<#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">
+				
+					<@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>
+										<#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>
+									</@lv_column>
+								</@lv_line>
+
+							</#if>
+						</#list>
+					</@listview>
+
+				</@tab>
+			</#if>
+
 		</#if>
 
 	</@tabs>
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
index 798342a..3e196b7 100644
--- a/legacyworlds-web-main/Content/Raw/WEB-INF/fm/layout/lists.ftl
+++ b/legacyworlds-web-main/Content/Raw/WEB-INF/fm/layout/lists.ftl
@@ -8,17 +8,17 @@
 		<#nested>
 	</tr>
 </#macro>
-<#macro lv_column width=0 centered=false right=false>
+<#macro lv_column width=0 centered=false right=false colspan=0>
 	<#if width?is_string>
-		<th style="text-align: <#if centered>center<#elseif right>right<#else>left</#if>">
+		<th style="text-align: <#if centered>center<#elseif right>right<#else>left</#if>"<#if colspan gt 1>colspan="${colspan}"</#if>>
 			<#nested>
 		</th>
 	<#elseif width gt 0>
-		<th style="width: ${width}px; text-align: <#if centered>center<#elseif right>right<#else>left</#if>">
+		<th style="width: ${width}px; text-align: <#if centered>center<#elseif right>right<#else>left</#if>"<#if colspan gt 1>colspan="${colspan}"</#if>>
 			<#nested>
 		</th>
 	<#else>
-		<td style="text-align: <#if centered>center<#elseif right>right<#else>left</#if>">
+		<td style="text-align: <#if centered>center<#elseif right>right<#else>left</#if>" <#if colspan gt 1>colspan="${colspan}"</#if>>
 			<#nested>
 		</td>
 	</#if>