Index: binaries/data/mods/public/simulation/components/BuildingAI.js
===================================================================
--- binaries/data/mods/public/simulation/components/BuildingAI.js	(revision 18140)
+++ binaries/data/mods/public/simulation/components/BuildingAI.js	(working copy)
@@ -32,25 +32,30 @@
 
 BuildingAI.prototype.OnGarrisonedUnitsChanged = function(msg)
 {
-	let classes = this.template.GarrisonArrowClasses;
+	for (let IsVisible of message.visible){
+		if (!IsVisible)
+			return;
+		else{
+			for (let ent of msg.added)
+			{
+				let cmpIdentity = Engine.QueryInterface(ent, IID_Identity);
+				if (!cmpIdentity)
+					continue;
+				if (MatchesClassList(cmpIdentity.GetClassesList(), classes))
+					++this.archersGarrisoned;
+			}
 
-	for (let ent of msg.added)
-	{
-		let cmpIdentity = Engine.QueryInterface(ent, IID_Identity);
-		if (!cmpIdentity)
-			continue;
-		if (MatchesClassList(cmpIdentity.GetClassesList(), classes))
-			++this.archersGarrisoned;
+			for (let ent of msg.removed)
+			{
+				let cmpIdentity = Engine.QueryInterface(ent, IID_Identity);
+				if (!cmpIdentity)
+					continue;
+				if (MatchesClassList(cmpIdentity.GetClassesList(), classes))
+					--this.archersGarrisoned;
+			}
+		}
 	}
-
-	for (let ent of msg.removed)
-	{
-		let cmpIdentity = Engine.QueryInterface(ent, IID_Identity);
-		if (!cmpIdentity)
-			continue;
-		if (MatchesClassList(cmpIdentity.GetClassesList(), classes))
-			--this.archersGarrisoned;
-	}
+	let classes = this.template.GarrisonArrowClasses;
 };
 
 BuildingAI.prototype.OnOwnershipChanged = function(msg)
Index: binaries/data/mods/public/simulation/components/GarrisonHolder.js
===================================================================
--- binaries/data/mods/public/simulation/components/GarrisonHolder.js	(revision 18140)
+++ binaries/data/mods/public/simulation/components/GarrisonHolder.js	(working copy)
@@ -1,3 +1,6 @@
+/**
+ * @class Defines an entity's ability to garrison units.
+ */
 function GarrisonHolder() {}
 
 GarrisonHolder.prototype.Schema =
@@ -45,6 +48,14 @@
 						"<element name='Z'>" +
 							"<data type='decimal'/>" +
 						"</element>" +
+						"<optional>" +
+							"<element name='VisibleGarrisonAllowedClasses'>" +
+								"<attribute name='datatype'>" +
+									"<value>tokens</value>" +
+								"</attribute>" +
+								"<text/>" +
+							"</element>" +
+						"</optional>" +
 					"</interleave>" +
 				"</element>" +
 			"</zeroOrMore>" +
@@ -72,7 +83,7 @@
 			o.x = +offset.X;
 			o.y = +offset.Y;
 			o.z = +offset.Z;
-			this.visibleGarrisonPoints.push({"offset":o, "entity": null});
+			this.visibleGarrisonPoints.push({ "offset": o, "entity": null, "allowedClass": offset.VisibleGarrisonAllowedClasses });
 		}
 	}
 };
@@ -100,7 +111,6 @@
 	return IsOwnedByPlayer(player, ent);
 };
 
-
 /**
  * Return the list of entities garrisoned inside
  */
@@ -204,6 +214,19 @@
 };
 
 /**
+ * Returns true if the unit is allowed be visible on that garrison point, false otherwise.
+ */
+GarrisonHolder.prototype.AllowedToVisibleGarrisoning = function(visibleGarrisonPoint, entity)
+{
+	let allowedClassesList = visibleGarrisonPoint.allowedClass._string; 
+	// If classlist is empty, everybody can garrison.
+	if (!allowedClassesList) 
+		return true; 
+	
+	return MatchesClassList(Engine.QueryInterface(entity, IID_Identity).GetClassesList(), allowedClassesList);
+};
+
+/**
  * Garrison a unit inside.
  * Returns true if successful, false if not
  * The timer for AutoHeal is started here
@@ -229,8 +252,7 @@
 			break;
 		}
 	}
-
-	if (visibleGarrisonPoint)
+	if (visibleGarrisonPoint && this.AllowedToVisibleGarrisoning(visibleGarrisonPoint, entity))
 	{
 		visibleGarrisonPoint.entity = entity;
 		cmpPosition.SetTurretParent(this.entity, visibleGarrisonPoint.offset);
@@ -240,10 +262,19 @@
 	}
 	else
 		cmpPosition.MoveOutOfWorld();
-
+	// Should only be called after the garrison has been performed else the visible Garrison Points are not updated yet.
+	Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, {
+		"added": [entity],
+		"visible": [this.IsVisiblyGarrisoned(entity)],
+		"removed": []
+		});
 	return true;
 };
 
+/**
+ * Garrison units inside the entity
+ * @return true if successful, false if not
+ */
 GarrisonHolder.prototype.PerformGarrison = function(entity)
 {
 	if (!this.HasEnoughHealth())
@@ -250,10 +281,10 @@
 		return false;
 
 	// Check if the unit is allowed to be garrisoned inside the building
-	if(!this.AllowedToGarrison(entity))
+	if (!this.AllowedToGarrison(entity))
 		return false;
 
-	// check the capacity
+	// Check the capacity
 	var extraCount = 0;
 	var cmpGarrisonHolder = Engine.QueryInterface(entity, IID_GarrisonHolder);
 	if (cmpGarrisonHolder)
@@ -278,8 +309,6 @@
 	if (cmpAura && cmpAura.HasGarrisonAura())
 		cmpAura.ApplyGarrisonBonus(this.entity);
 
-	Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, { "added" : [entity], "removed": [] });
-
 	var cmpUnitAI = Engine.QueryInterface(entity, IID_UnitAI);
 	if (cmpUnitAI && cmpUnitAI.IsUnderAlert())
 		Engine.PostMessage(cmpUnitAI.GetAlertRaiser(), MT_UnitGarrisonedAfterAlert, {"holder": this.entity, "unit": entity});
@@ -326,7 +355,12 @@
 
 	var cmpNewPosition = Engine.QueryInterface(entity, IID_Position);
 	this.entities.splice(entityIndex, 1);
-
+	// Should only be called before the ejection has been performed else the visible Garrison Points will be empty.
+	Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, {
+		"added": [],
+		"visible": [this.IsVisiblyGarrisoned(entity)],
+		"removed": [entity]
+		});
 	for (var vgp of this.visibleGarrisonPoints)
 	{
 		if (vgp.entity != entity)
@@ -356,7 +390,6 @@
 	cmpNewPosition.SetHeightOffset(0);
 	// TODO: what direction should they face in?
 
-	Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, { "added" : [], "removed": [entity] });
 
 	return true;
 };
@@ -620,7 +653,11 @@
 		if (cmpHealth && cmpHealth.GetHitpoints() == 0)
 		{
 			this.entities.splice(entityIndex, 1);
-			Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, { "added" : [], "removed": [msg.entity] });
+			Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, {
+				"added": [],
+				"visible": [this.IsVisiblyGarrisoned(entity)],
+				"removed": [msg.entity]
+				});
 			this.UpdateGarrisonFlag();
 
 			for (var pt of this.visibleGarrisonPoints)
@@ -634,6 +671,8 @@
 
 /**
  * Update list of garrisoned entities if one gets renamed (e.g. by promotion)
+ * vgpEntity is only defined in some peculiar case where we want to reuse the same visibleGarrisonPoint,
+ * in case of promotion for example, and thus should always be allowed. 
  */
 GarrisonHolder.prototype.OnGlobalEntityRenamed = function(msg)
 {
@@ -670,7 +709,6 @@
 	}
 };
 
-
 /**
  * Eject all foreign garrisoned entities which are no more allied
  */
@@ -710,13 +748,35 @@
 		this.entities.splice(entityIndex, 1);
 		killedEntities.push(entity);
 	}
-
-	if (killedEntities.length > 0)
-		Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, { "added" : [], "removed" : killedEntities });
+	let killedEntitiesVisibility = [];
+	if  (killedEntities.length > 0)
+	{
+	 let i = 0;
+	 for (let ent of killedEntities)
+	 {
+		killedEntitiesVisibility[i] = this.IsVisiblyGarrisoned(entity) ;
+		++i =;
+	 }
+	Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, {
+		"added": [],
+		"visible": killedEntitiesVisibility,
+		"removed" : killedEntities;
+		});
+	}
 	this.UpdateGarrisonFlag();
 };
 
 /**
+ * Gives insight about the unit type of garrisoning.
+ * @return{bool} returns true if the unit is visible on the structure
+ * @param {int} the entity's id
+ */
+GarrisonHolder.prototype.IsVisiblyGarrisoned = function(entity)
+{
+	return this.visibleGarrisonPoints.some(point => point.entity === entity);
+};
+
+/**
  * Checks if an entity is ejectable on destroy if possible
  */
 GarrisonHolder.prototype.IsEjectable = function(entity)
