Files
OpenRA/OpenRA.Mods.Common/Traits/Immobile.cs
RoosterDragon 1bc3a7395f Prevent items without size from being added to SpatiallyPartitioned.
Items with no size act unexpectedly as they can fail to be returned when querying partition bins as they do not intersect along the top or left edges of the bin. We prevent such items being added in the first place to avoid this scenario.

As a side effect - we must now prevent any Immobile items that do not have size from being added to the screen map.
2016-01-09 16:51:13 +00:00

73 lines
2.1 KiB
C#

#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.Primitives;
using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits
{
class ImmobileInfo : ITraitInfo, IOccupySpaceInfo
{
public readonly bool OccupiesSpace = true;
public object Create(ActorInitializer init) { return new Immobile(init, this); }
public IReadOnlyDictionary<CPos, SubCell> OccupiedCells(ActorInfo info, CPos location, SubCell subCell = SubCell.Any)
{
var occupied = OccupiesSpace ? new Dictionary<CPos, SubCell>() { { location, SubCell.FullCell } } :
new Dictionary<CPos, SubCell>();
return new ReadOnlyDictionary<CPos, SubCell>(occupied);
}
bool IOccupySpaceInfo.SharesCell { get { return false; } }
}
class Immobile : IOccupySpace, ISync, INotifyAddedToWorld, INotifyRemovedFromWorld
{
[Sync] readonly CPos location;
[Sync] readonly WPos position;
readonly IEnumerable<Pair<CPos, SubCell>> occupied;
public Immobile(ActorInitializer init, ImmobileInfo info)
{
location = init.Get<LocationInit, CPos>();
position = init.World.Map.CenterOfCell(location);
if (info.OccupiesSpace)
occupied = new[] { Pair.New(TopLeft, SubCell.FullCell) };
else
occupied = new Pair<CPos, SubCell>[0];
}
public CPos TopLeft { get { return location; } }
public WPos CenterPosition { get { return position; } }
public IEnumerable<Pair<CPos, SubCell>> OccupiedCells() { return occupied; }
public void AddedToWorld(Actor self)
{
self.World.ActorMap.AddInfluence(self, this);
self.World.ActorMap.AddPosition(self, this);
if (!self.Bounds.Size.IsEmpty)
self.World.ScreenMap.Add(self);
}
public void RemovedFromWorld(Actor self)
{
self.World.ActorMap.RemoveInfluence(self, this);
self.World.ActorMap.RemovePosition(self, this);
if (!self.Bounds.Size.IsEmpty)
self.World.ScreenMap.Remove(self);
}
}
}