#region Copyright & License Information /* * Copyright 2007-2015 The OpenRA Developers (see AUTHORS) * This file is part of OpenRA, which is free software. It is made * available to you under the terms of the GNU General Public License * as published by the Free Software Foundation. For more information, * see COPYING. */ #endregion using System.Collections.Generic; using OpenRA.Graphics; using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { [Desc("Allows harvesters to coordinate their operations. Attach this to the world actor.")] public sealed class ResourceClaimLayerInfo : TraitInfo { } public sealed class ResourceClaimLayer : IWorldLoaded { Dictionary claimByCell; Dictionary claimByActor; private void MakeClaim(Actor claimer, CPos cell) { UnclaimByActor(claimer); UnclaimByCell(cell, claimer); claimByActor[claimer] = claimByCell[cell] = new ResourceClaim(claimer, cell); } private void Unclaim(ResourceClaim claim, Actor claimer) { if (claimByActor.Remove(claim.Claimer) & claimByCell.Remove(claim.Cell)) { if (claim.Claimer.Disposed) return; if (!claim.Claimer.IsInWorld) return; if (claim.Claimer.IsDead) return; claim.Claimer.Trait().OnNotifyResourceClaimLost(claim.Claimer, claim, claimer); } } public void WorldLoaded(World w, WorldRenderer wr) { // NOTE(jsd): 32 seems a sane default initial capacity for the total # of harvesters in a game. Purely a guesstimate. claimByCell = new Dictionary(32); claimByActor = new Dictionary(32); } /// /// Attempt to claim the resource at the cell for the given actor. /// /// /// /// public bool ClaimResource(Actor claimer, CPos cell) { // Has anyone else claimed this point? ResourceClaim claim; if (claimByCell.TryGetValue(cell, out claim)) { // Same claimer: if (claim.Claimer == claimer) return true; // This is to prevent in-fighting amongst friendly harvesters: if (claimer.Owner == claim.Claimer.Owner) return false; if (claimer.Owner.Stances[claim.Claimer.Owner] == Stance.Ally) return false; // If an enemy/neutral claimed this, don't respect that claim: } // Either nobody else claims this point or an enemy/neutral claims it: MakeClaim(claimer, cell); return true; } /// /// Release the last resource claim made on this cell. /// /// public void UnclaimByCell(CPos cell, Actor claimer) { ResourceClaim claim; if (claimByCell.TryGetValue(cell, out claim)) Unclaim(claim, claimer); } /// /// Release the last resource claim made by this actor. /// /// public void UnclaimByActor(Actor claimer) { ResourceClaim claim; if (claimByActor.TryGetValue(claimer, out claim)) Unclaim(claim, claimer); } /// /// Is the cell location claimed for harvesting by any other actor? /// /// /// /// true if already claimed by an ally that isn't ; false otherwise. public bool IsClaimedByAnyoneElse(Actor self, CPos cell, out ResourceClaim claim) { if (claimByCell.TryGetValue(cell, out claim)) { // Same claimer: if (claim.Claimer == self) return false; // This is to prevent in-fighting amongst friendly harvesters: if (self.Owner == claim.Claimer.Owner) return true; if (self.Owner.Stances[claim.Claimer.Owner] == Stance.Ally) return true; // If an enemy/neutral claimed this, don't respect that claim and fall through: } else { // No claim. claim = null; } return false; } } }