Index: binaries/data/mods/public/gui/common/settings.js
===================================================================
--- binaries/data/mods/public/gui/common/settings.js	(revision 17014)
+++ binaries/data/mods/public/gui/common/settings.js	(working copy)
@@ -31,6 +31,7 @@
 {
 	var settings = {
 		"Ceasefire": loadCeasefire(),
+		"PlayerColors": loadPlayerColors(),
 		"PopulationCapacities": loadPopulationCapacities(),
 		"StartingResources": loadSettingValuesFile("starting_resources.json")
 	};
@@ -88,6 +89,24 @@
 }
 
 /**
+* Loads available colors settings.
+*
+* @returns {Array|undefined}
+*/
+function loadPlayerColors()
+{
+	var json = Engine.ReadJSONFile("simulation/data/player_defaults.json");
+
+	if (!json || !json.PlayerData || !Array.isArray(json.PlayerData))
+ 	{
+		error("Could not load player_defaults.json"); 
+		return undefined;
+	}
+
+	return json.PlayerData.map(player => player.Color);
+}
+
+/**
  * Loads available population capacities.
  *
  * @returns {Array|undefined}
Index: binaries/data/mods/public/gui/gamesetup/gamesetup.js
===================================================================
--- binaries/data/mods/public/gui/gamesetup/gamesetup.js	(revision 17014)
+++ binaries/data/mods/public/gui/gamesetup/gamesetup.js	(working copy)
@@ -6,6 +6,7 @@
 const VICTORY_DEFAULTIDX = 1;
 
 const g_Ceasefire = prepareForDropdown(g_Settings ? g_Settings.Ceasefire : undefined);
+const g_PlayerColors = prepareForDropdown(g_Settings ? g_Settings.PlayerColors : undefined);
 const g_PopulationCapacities = prepareForDropdown(g_Settings ? g_Settings.PopulationCapacities : undefined);
 const g_StartingResources = prepareForDropdown(g_Settings ? g_Settings.StartingResources : undefined);
 
@@ -50,6 +51,10 @@
 
 var g_AIs = [];
 
+var g_PlayerColorsSorted = [];
+var g_PlayerColorIdsSorted = [];
+var g_PlayerColorDisplayNamesSorted = [];
+
 var g_ChatMessages = [];
 
 // Data caches
@@ -381,6 +386,37 @@
 			updateGameAttributes();
 		};
 
+		// Populate color drop-down lists.
+		var colorPicker = Engine.GetGUIObjectByName("playerColorPicker["+i+"]");
+		colorPicker.list = getPlayerColorLabelsSorted();
+		colorPicker.list_data = getPlayerColorIdsSorted();
+		colorPicker.selected = -1;
+		colorPicker.onSelectionChange = function()
+		{       // Update color
+			if (this.selected !== -1)
+			{
+				var numPlayers = g_GameAttributes.settings.PlayerData.length;
+				var used = 0;
+				var playerColorsSorted = getPlayerColorsSorted();
+				for (var o = 0; o < numPlayers; o++)
+				{
+					if (rgbValuesMatch(playerColorsSorted[this.list_data[this.selected]], g_GameAttributes.settings.PlayerData[o].Color))
+					{
+						++used;
+						break;
+					}
+				}
+				if (!used)
+				{
+					copyRgbValuesFromColorIntoColor(playerColorsSorted[this.list_data[this.selected]], g_GameAttributes.settings.PlayerData[playerSlot].Color);
+				}
+			}
+			if (!g_IsInGuiUpdate)
+			{
+				updateGameAttributes();
+			}
+		};
+
 		// Set events
 		var civ = Engine.GetGUIObjectByName("playerCiv["+i+"]");
 		civ.onSelectionChange = function() {
@@ -414,6 +450,122 @@
 	}
 }
 
+// Returns the index of the specified color.
+function getIndexOfColor(color)
+{
+    for (var i = 0; i < g_PlayerColors.length; ++i)
+    {
+        var playerColorsSorted = getPlayerColorsSorted();
+        if (rgbValuesMatch(playerColorsSorted[i], color))
+        {
+            return i;
+        }
+    }
+    return -1;
+}
+
+function rgbToHsl(color){
+        var r = color.r/255, g = color.g/255, b = color.b/255;
+        var max = Math.max(r, g, b), min = Math.min(r, g, b);
+        var h, s, l = (max + min) / 2;
+        if (max === min)
+        {
+                h = s = 0; // achromatic
+        }
+        else
+        {
+                var d = max - min;
+                s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
+                switch(max)
+                {
+                        case r: h = (g - b) / d + (g < b ? 6 : 0); break;
+                        case g: h = (b - r) / d + 2; break;
+                        case b: h = (r - g) / d + 4; break;
+                }
+                h /= 6;
+        }
+        return [h * 360, s * 100, l * 100];
+}
+
+// Get list of player colors sorted by color value.
+// See http://stackoverflow.com/a/11923973/939364
+function getPlayerColorsSorted()
+{
+    if (g_PlayerColorsSorted.length === 0)
+    {
+        var hslArray = [];
+        for (var i = 0; i < g_PlayerColors.length; ++i)
+        {
+            //Transforming rgb to hsl
+            //`hslArray[i][1]` (`i`) is a reference to the rgb color, in order to retrieve it later
+            hslArray[i] = [rgbToHsl(g_PlayerColors[i]),i];
+        }
+
+        var sortedHslArray = [];
+        outerloop:
+        for (var i = 0; i < hslArray.length; ++i)
+        {
+            for (var j = 0; j < sortedHslArray.length; ++j)
+            {
+                if (sortedHslArray[j][0][0] > hslArray[i][0][0])
+                {
+                    sortedHslArray.splice(j, 0, hslArray[i]);
+                    continue outerloop;
+                }
+            }
+            sortedHslArray.push(hslArray[i]);
+        }
+
+        for (var i = 0; i < sortedHslArray.length; ++i)
+        {
+            g_PlayerColorsSorted[i] = g_PlayerColors[sortedHslArray[i][1]];
+        }
+    }
+    return g_PlayerColorsSorted;
+}
+
+// Get a list of player color display names.
+function getPlayerColorLabelsSorted()
+{
+    if (g_PlayerColorDisplayNamesSorted.length === 0)
+    {
+        var playerColorsSorted = getPlayerColorsSorted();
+        for (var i = 0; i < playerColorsSorted.length; ++i)
+        {
+            g_PlayerColorDisplayNamesSorted[i] = "[color=\"" + playerColorsSorted[i].r + " " + playerColorsSorted[i].g + " " + playerColorsSorted[i].b + " 255\"]" + "█";
+        }
+    }
+    return g_PlayerColorDisplayNamesSorted;
+}
+
+// Get a simple list of color IDs, basically a list of indexes that has as many members as colors there are.
+function getPlayerColorIdsSorted()
+{
+    if (g_PlayerColorIdsSorted.length === 0)
+    {
+        var playerColorsSorted = getPlayerColorsSorted();
+        for (var i = 0; i < playerColorsSorted.length; ++i)
+        {
+          g_PlayerColorIdsSorted[i] = i;
+        }
+    }
+    return g_PlayerColorIdsSorted;
+}
+
+// Determine whether two specified variables contain the same RGB data.
+function rgbValuesMatch(color1, color2)
+{
+    return color1.r === color2.r && color1.g === color2.g && color1.b === color2.b;
+}
+
+// Copy the RGB data from the first color into the second color.
+function copyRgbValuesFromColorIntoColor(color1, color2)
+{
+    color2.r = color1.r;
+    color2.g = color1.g;
+    color2.b = color1.b;
+}
+
 function handleNetMessage(message)
 {
 	log("Net message: " + uneval(message));
@@ -1422,6 +1574,7 @@
 		var pTeam = Engine.GetGUIObjectByName("playerTeam["+i+"]");
 		var pTeamText = Engine.GetGUIObjectByName("playerTeamText["+i+"]");
 		var pColor = Engine.GetGUIObjectByName("playerColor["+i+"]");
+		var pColorPicker = Engine.GetGUIObjectByName("playerColorPicker["+i+"]")
 
 		// Player data / defaults
 		var pData = mapSettings.PlayerData ? mapSettings.PlayerData[i] : {};
@@ -1428,8 +1581,8 @@
 		var pDefs = g_DefaultPlayerData ? g_DefaultPlayerData[i] : {};
 
 		// Common to all game types
-		var color = rgbToGuiColor(getSetting(pData, pDefs, "Color"));
-		pColor.sprite = "color:" + color + " 100";
+		var color = getSetting(pData, pDefs, "Color");
+		pColor.sprite = "color:" + rgbToGuiColor(color) + " 100";
 		pName.caption = translate(getSetting(pData, pDefs, "Name"));
 
 		var team = getSetting(pData, pDefs, "Team");
@@ -1449,6 +1602,7 @@
 		{
 			pCivText.hidden = false;
 			pCiv.hidden = true;
+			pColorPicker.hidden = true;
 			pTeamText.hidden = false;
 			pTeam.hidden = true;
 			// Set text values
@@ -1462,10 +1616,12 @@
 		{
 			pCivText.hidden = true;
 			pCiv.hidden = false;
+			pColorPicker.hidden = false;
 			pTeamText.hidden = true;
 			pTeam.hidden = false;
 			// Set dropdown values
 			pCiv.selected = (civ ? pCiv.list_data.indexOf(civ) : 0);
+			pColorPicker.selected = getIndexOfColor(color);
 			pTeam.selected = (team !== undefined && team >= 0) ? team+1 : 0;
 		}
 	}
Index: binaries/data/mods/public/gui/gamesetup/gamesetup.xml
===================================================================
--- binaries/data/mods/public/gui/gamesetup/gamesetup.xml	(revision 17014)
+++ binaries/data/mods/public/gui/gamesetup/gamesetup.xml	(working copy)
@@ -72,6 +72,9 @@
 						<object name="playerBox[n]" size="0 0 100% 32" hidden="true">
 							<object name="playerColor[n]" type="image" size="0 0 100% 100%"/>
 							<object name="playerName[n]" type="text" style="ModernLabelText" size="0 2 22% 30"/>
+							<object name="playerColorPicker[n]" type="dropdown" style="ModernDropDown" size="16%+5 2 20%+5 30" tooltip_style="onscreenToolTip">
+								<translatableAttribute id="tooltip">Pick Color.</translatableAttribute>
+							</object>
 							<object name="playerAssignment[n]" type="dropdown" style="ModernDropDown" size="22%+5 2 50%+35 30" tooltip_style="onscreenToolTip">
 								<translatableAttribute id="tooltip">Select player.</translatableAttribute>
 							</object>
@@ -152,7 +155,7 @@
 					tooltip_style="onscreenToolTip">
 					<translatableAttribute id="tooltip">Select a map to play on.</translatableAttribute>
 					<action on="SelectionChange">
-						if (this.list_data[this.selected]) 
+						if (this.list_data[this.selected])
 							selectMap(this.list_data[this.selected]);
 					</action>
 				</object>
@@ -179,7 +182,7 @@
 
 			<!-- Map Description -->
 			<object size="100%-425 529 100%-25 100%-60">
-				<object name="mapInfoName" type="text" style="ModernLeftLabelText" size="0 0 100%-120 30"/> 
+				<object name="mapInfoName" type="text" style="ModernLeftLabelText" size="0 0 100%-120 30"/>
 				<object type="image" sprite="ModernDarkBoxGold" size="0 30 100% 100%">
 					<object name="mapInfoDescription" type="text" style="MapDescription" size="0 0 100% 100%"/>
 				</object>
