Index: binaries/data/mods/public/gui/session_new/input.js
===================================================================
--- binaries/data/mods/public/gui/session_new/input.js	(revision 7942)
+++ binaries/data/mods/public/gui/session_new/input.js	(working copy)
@@ -128,6 +128,10 @@
 			{
 				return {"type": "build", "cursor": "action-build", "target": targets[0]};
 			}
+			else if (entState.buildEntities && targetState.needsRepair && playerOwned)
+			{
+				return {"type": "build", "cursor": "action-build", "target": targets[0]};
+			}
 			else if (entState.attack && enemyOwned)
 			{
 				return {"type": "attack", "cursor": "action-attack", "target": targets[0]};
Index: binaries/data/mods/public/simulation/components/Health.js
===================================================================
--- binaries/data/mods/public/simulation/components/Health.js	(revision 7942)
+++ binaries/data/mods/public/simulation/components/Health.js	(working copy)
@@ -42,6 +42,7 @@
 	// Default to <Initial>, but use <Max> if it's undefined or zero
 	// (Allowing 0 initial HP would break our death detection code)
 	this.hitpoints = +(this.template.Initial || this.GetMaxHitpoints());
+	this.repairProgress = this.hitpoints / this.GetMaxHitpoints();
 };
 
 //// Interface functions ////
@@ -65,6 +66,14 @@
 	this.hitpoints = Math.max(1, Math.min(this.GetMaxHitpoints(), value));
 };
 
+Health.prototype.IsRepairable = function()
+{
+	if (this.template.Repairable)
+		return this.template.Repairable;
+	else
+		return false;
+};
+
 Health.prototype.Kill = function()
 {
 	this.Reduce(this.hitpoints);
@@ -132,5 +141,39 @@
 	cmpCorpseVisual.SelectAnimation("death", true, 1.0, "");
 };
 
+Health.prototype.Repair = function(builderEnt, work)
+{
+	// Do nothing if we've already finished building
+	this.repairProgress = this.GetHitpoints() / this.GetMaxHitpoints();
 
+	if (this.repairProgress == 1.0)
+		return;
+
+	// Calculate the amount of progress that will be added (where 1.0 = completion)
+	var cmpCost = Engine.QueryInterface(this.entity, IID_Cost);
+	var amount = work / cmpCost.GetBuildTime();
+
+	// TODO: implement some kind of diminishing returns for multiple repairmen.
+	// e.g. record the set of entities that build this, then every ~2 seconds
+	// count them (and reset the list), and apply some function to the count to get
+	// a factor, and apply that factor here.
+	this.repairProgress += amount;
+	if (this.repairProgress > 1.0)
+		this.repairProgress = 1.0;
+
+	// Add an appropriate proportion of hitpoints
+	var targetHP = Math.max(0, Math.min(this.GetMaxHitpoints(), Math.floor(this.GetMaxHitpoints() * this.repairProgress)));
+	var deltaHP = targetHP - this.hitpoints;
+	if (deltaHP > 0)
+	{
+		var cmpHealth = Engine.QueryInterface(this.entity, IID_Health);
+		cmpHealth.Increase(deltaHP);
+	}
+
+	if (this.repairProgress >= 1.0)
+	{
+		Engine.PostMessage(this.entity, MT_ConstructionFinished,
+				{ "entity": this.entity, "newentity": this.entity });
+	}
+};
 Engine.RegisterComponentType(IID_Health, "Health", Health);
Index: binaries/data/mods/public/simulation/components/GuiInterface.js
===================================================================
--- binaries/data/mods/public/simulation/components/GuiInterface.js	(revision 7942)
+++ binaries/data/mods/public/simulation/components/GuiInterface.js	(working copy)
@@ -76,6 +76,7 @@
 	{
 		ret.hitpoints = cmpHealth.GetHitpoints();
 		ret.maxHitpoints = cmpHealth.GetMaxHitpoints();
+		ret.needsRepair = cmpHealth.IsRepairable() && (cmpHealth.GetHitpoints() < cmpHealth.GetMaxHitpoints());
 	}
 
 	var cmpAttack = Engine.QueryInterface(ent, IID_Attack);
Index: binaries/data/mods/public/simulation/components/Player.js
===================================================================
--- binaries/data/mods/public/simulation/components/Player.js	(revision 7942)
+++ binaries/data/mods/public/simulation/components/Player.js	(working copy)
@@ -10,7 +10,8 @@
 	this.civ = "gaia";
 	this.colour = { "r": 0.0, "g": 0.0, "b": 0.0, "a": 1.0 };
 	this.popCount = 0;
-	this.popLimit = 50;
+	this.popLimit = 0;
+	this.popReserve = 0;
 	this.resourceCount = {
 		"food": 2000,	
 		"wood": 1500,	
@@ -54,9 +55,19 @@
 	return this.colour;
 };
 
+Player.prototype.ReservePopulationSlots = function(num)
+{
+	this.popReserve += num;
+};
+
+Player.prototype.UnReservePopulationSlots = function(num)
+{
+	this.popReserve -= Math.min(num, this.popReserve);
+}
+
 Player.prototype.GetPopulationCount = function()
 {
-	return this.popCount;
+	return this.popCount + this.popReserve;
 };
 
 Player.prototype.GetPopulationLimit = function()
Index: binaries/data/mods/public/simulation/components/Builder.js
===================================================================
--- binaries/data/mods/public/simulation/components/Builder.js	(revision 7942)
+++ binaries/data/mods/public/simulation/components/Builder.js	(working copy)
@@ -51,17 +51,18 @@
 
 	// If it's a foundation, then build it
 	var cmpFoundation = Engine.QueryInterface(target, IID_Foundation);
+	var cmpHealth = Engine.QueryInterface(target, IID_Health)
 	if (cmpFoundation)
 	{
 		cmpFoundation.Build(this.entity, rate);
 		return { "finished": false };
 	}
-	else
+	else if (cmpHealth)
 	{
- 		// TODO: do some kind of repairing
-
-		return { "finished": true };
+		return { "finished": cmpHealth.Repair(this.entity, rate) };
 	}
+	return { "finished": false };
 };
 
 Engine.RegisterComponentType(IID_Builder, "Builder", Builder);
