Introduced the interfaces IActor, ICacheStorage, ILog, IMap, IWorld a
nd IMobileInfo to separate concrete implementations and abstractions
This commit is contained in:
@@ -22,14 +22,36 @@ using OpenRA.Traits;
|
|||||||
|
|
||||||
namespace OpenRA
|
namespace OpenRA
|
||||||
{
|
{
|
||||||
public class Actor : IScriptBindable, IScriptNotifyBind, ILuaTableBinding, ILuaEqualityBinding, ILuaToStringBinding, IEquatable<Actor>
|
public interface IActor
|
||||||
{
|
{
|
||||||
public readonly ActorInfo Info;
|
ActorInfo Info { get; }
|
||||||
|
IWorld World { get; }
|
||||||
|
uint ActorID { get; }
|
||||||
|
Player Owner { get; set; }
|
||||||
|
|
||||||
|
T TraitOrDefault<T>();
|
||||||
|
T Trait<T>();
|
||||||
|
IEnumerable<T> TraitsImplementing<T>();
|
||||||
|
|
||||||
|
T TraitInfo<T>();
|
||||||
|
|
||||||
|
IEnumerable<IRenderable> Render(WorldRenderer wr);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Actor : IScriptBindable, IScriptNotifyBind, ILuaTableBinding, ILuaEqualityBinding, ILuaToStringBinding, IEquatable<Actor>, IActor
|
||||||
|
{
|
||||||
|
public ActorInfo Info { get; private set; }
|
||||||
public readonly World World;
|
public readonly World World;
|
||||||
public readonly uint ActorID;
|
|
||||||
|
IWorld IActor.World
|
||||||
|
{
|
||||||
|
get { return World; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public uint ActorID { get; private set; }
|
||||||
|
|
||||||
[Sync]
|
[Sync]
|
||||||
public Player Owner;
|
public Player Owner { get; set; }
|
||||||
|
|
||||||
public bool IsInWorld { get; internal set; }
|
public bool IsInWorld { get; internal set; }
|
||||||
public bool Destroyed { get; private set; }
|
public bool Destroyed { get; private set; }
|
||||||
@@ -202,6 +224,11 @@ namespace OpenRA
|
|||||||
return World.TraitDict.WithInterface<T>(this);
|
return World.TraitDict.WithInterface<T>(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public T TraitInfo<T>()
|
||||||
|
{
|
||||||
|
return Info.Traits.Get<T>();
|
||||||
|
}
|
||||||
|
|
||||||
public bool HasTrait<T>()
|
public bool HasTrait<T>()
|
||||||
{
|
{
|
||||||
return World.TraitDict.Contains<T>(this);
|
return World.TraitDict.Contains<T>(this);
|
||||||
@@ -235,7 +262,7 @@ namespace OpenRA
|
|||||||
{
|
{
|
||||||
World.AddFrameEndTask(w =>
|
World.AddFrameEndTask(w =>
|
||||||
{
|
{
|
||||||
if (this.Destroyed)
|
if (Destroyed)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var oldOwner = Owner;
|
var oldOwner = Owner;
|
||||||
|
|||||||
19
OpenRA.Game/CacheStorage.cs
Normal file
19
OpenRA.Game/CacheStorage.cs
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
#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
|
||||||
|
|
||||||
|
namespace OpenRA
|
||||||
|
{
|
||||||
|
public interface ICacheStorage<T>
|
||||||
|
{
|
||||||
|
void Remove(string key);
|
||||||
|
void Store(string key, T data);
|
||||||
|
T Retrieve(string key);
|
||||||
|
}
|
||||||
|
}
|
||||||
25
OpenRA.Game/LogProxy.cs
Normal file
25
OpenRA.Game/LogProxy.cs
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
#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
|
||||||
|
|
||||||
|
namespace OpenRA
|
||||||
|
{
|
||||||
|
public interface ILog
|
||||||
|
{
|
||||||
|
void Write(string channel, string format, params object[] args);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class LogProxy : ILog
|
||||||
|
{
|
||||||
|
public void Write(string channel, string format, params object[] args)
|
||||||
|
{
|
||||||
|
Log.Write(channel, format, args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -111,15 +111,33 @@ namespace OpenRA
|
|||||||
MissionSelector = 4
|
MissionSelector = 4
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Map
|
public interface IMap
|
||||||
|
{
|
||||||
|
TileShape TileShape { get; }
|
||||||
|
|
||||||
|
int2 MapSize { get; set; }
|
||||||
|
bool Contains(CPos cell);
|
||||||
|
CPos CellContaining(WPos pos);
|
||||||
|
WVec OffsetOfSubCell(SubCell subCell);
|
||||||
|
IEnumerable<CPos> FindTilesInCircle(CPos center, int maxRange);
|
||||||
|
WPos CenterOfCell(CPos cell);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Map : IMap
|
||||||
{
|
{
|
||||||
public const int MaxTilesInCircleRange = 50;
|
public const int MaxTilesInCircleRange = 50;
|
||||||
public readonly TileShape TileShape;
|
public readonly TileShape TileShape;
|
||||||
|
TileShape IMap.TileShape
|
||||||
|
{
|
||||||
|
get { return TileShape; }
|
||||||
|
}
|
||||||
|
|
||||||
[FieldLoader.Ignore]
|
[FieldLoader.Ignore]
|
||||||
public readonly WVec[] SubCellOffsets;
|
public readonly WVec[] SubCellOffsets;
|
||||||
public readonly SubCell DefaultSubCell;
|
public readonly SubCell DefaultSubCell;
|
||||||
public readonly SubCell LastSubCell;
|
public readonly SubCell LastSubCell;
|
||||||
[FieldLoader.Ignore] public IFolder Container;
|
[FieldLoader.Ignore]
|
||||||
|
public IFolder Container;
|
||||||
public string Path { get; private set; }
|
public string Path { get; private set; }
|
||||||
|
|
||||||
// Yaml map data
|
// Yaml map data
|
||||||
@@ -165,41 +183,65 @@ namespace OpenRA
|
|||||||
return videos;
|
return videos;
|
||||||
}
|
}
|
||||||
|
|
||||||
[FieldLoader.Ignore] public Lazy<Dictionary<string, ActorReference>> Actors;
|
[FieldLoader.Ignore]
|
||||||
|
public Lazy<Dictionary<string, ActorReference>> Actors;
|
||||||
|
|
||||||
public int PlayerCount { get { return Players.Count(p => p.Value.Playable); } }
|
public int PlayerCount { get { return Players.Count(p => p.Value.Playable); } }
|
||||||
|
|
||||||
public Rectangle Bounds;
|
public Rectangle Bounds;
|
||||||
|
|
||||||
// Yaml map data
|
// Yaml map data
|
||||||
[FieldLoader.Ignore] public Dictionary<string, PlayerReference> Players = new Dictionary<string, PlayerReference>();
|
[FieldLoader.Ignore]
|
||||||
[FieldLoader.Ignore] public Lazy<List<SmudgeReference>> Smudges;
|
public Dictionary<string, PlayerReference> Players = new Dictionary<string, PlayerReference>();
|
||||||
|
[FieldLoader.Ignore]
|
||||||
|
public Lazy<List<SmudgeReference>> Smudges;
|
||||||
|
|
||||||
[FieldLoader.Ignore] public List<MiniYamlNode> RuleDefinitions = new List<MiniYamlNode>();
|
[FieldLoader.Ignore]
|
||||||
[FieldLoader.Ignore] public List<MiniYamlNode> SequenceDefinitions = new List<MiniYamlNode>();
|
public List<MiniYamlNode> RuleDefinitions = new List<MiniYamlNode>();
|
||||||
[FieldLoader.Ignore] public List<MiniYamlNode> VoxelSequenceDefinitions = new List<MiniYamlNode>();
|
[FieldLoader.Ignore]
|
||||||
[FieldLoader.Ignore] public List<MiniYamlNode> WeaponDefinitions = new List<MiniYamlNode>();
|
public List<MiniYamlNode> SequenceDefinitions = new List<MiniYamlNode>();
|
||||||
[FieldLoader.Ignore] public List<MiniYamlNode> VoiceDefinitions = new List<MiniYamlNode>();
|
[FieldLoader.Ignore]
|
||||||
[FieldLoader.Ignore] public List<MiniYamlNode> NotificationDefinitions = new List<MiniYamlNode>();
|
public List<MiniYamlNode> VoxelSequenceDefinitions = new List<MiniYamlNode>();
|
||||||
[FieldLoader.Ignore] public List<MiniYamlNode> TranslationDefinitions = new List<MiniYamlNode>();
|
[FieldLoader.Ignore]
|
||||||
|
public List<MiniYamlNode> WeaponDefinitions = new List<MiniYamlNode>();
|
||||||
|
[FieldLoader.Ignore]
|
||||||
|
public List<MiniYamlNode> VoiceDefinitions = new List<MiniYamlNode>();
|
||||||
|
[FieldLoader.Ignore]
|
||||||
|
public List<MiniYamlNode> NotificationDefinitions = new List<MiniYamlNode>();
|
||||||
|
[FieldLoader.Ignore]
|
||||||
|
public List<MiniYamlNode> TranslationDefinitions = new List<MiniYamlNode>();
|
||||||
|
|
||||||
// Binary map data
|
// Binary map data
|
||||||
[FieldLoader.Ignore] public byte TileFormat = 2;
|
[FieldLoader.Ignore]
|
||||||
|
public byte TileFormat = 2;
|
||||||
|
|
||||||
public int2 MapSize;
|
public int2 MapSize;
|
||||||
|
|
||||||
[FieldLoader.Ignore] public Lazy<CellLayer<TerrainTile>> MapTiles;
|
int2 IMap.MapSize
|
||||||
[FieldLoader.Ignore] public Lazy<CellLayer<ResourceTile>> MapResources;
|
{
|
||||||
[FieldLoader.Ignore] public Lazy<CellLayer<byte>> MapHeight;
|
get { return MapSize; }
|
||||||
|
set { MapSize = value; }
|
||||||
|
}
|
||||||
|
|
||||||
[FieldLoader.Ignore] public CellLayer<byte> CustomTerrain;
|
[FieldLoader.Ignore]
|
||||||
|
public Lazy<CellLayer<TerrainTile>> MapTiles;
|
||||||
|
[FieldLoader.Ignore]
|
||||||
|
public Lazy<CellLayer<ResourceTile>> MapResources;
|
||||||
|
[FieldLoader.Ignore]
|
||||||
|
public Lazy<CellLayer<byte>> MapHeight;
|
||||||
|
|
||||||
[FieldLoader.Ignore] Lazy<TileSet> cachedTileSet;
|
[FieldLoader.Ignore]
|
||||||
[FieldLoader.Ignore] Lazy<Ruleset> rules;
|
public CellLayer<byte> CustomTerrain;
|
||||||
|
|
||||||
|
[FieldLoader.Ignore]
|
||||||
|
Lazy<TileSet> cachedTileSet;
|
||||||
|
[FieldLoader.Ignore]
|
||||||
|
Lazy<Ruleset> rules;
|
||||||
public Ruleset Rules { get { return rules != null ? rules.Value : null; } }
|
public Ruleset Rules { get { return rules != null ? rules.Value : null; } }
|
||||||
public SequenceProvider SequenceProvider { get { return Rules.Sequences[Tileset]; } }
|
public SequenceProvider SequenceProvider { get { return Rules.Sequences[Tileset]; } }
|
||||||
|
|
||||||
[FieldLoader.Ignore] public CellRegion Cells;
|
[FieldLoader.Ignore]
|
||||||
|
public CellRegion Cells;
|
||||||
|
|
||||||
public static Map FromTileset(TileSet tileset)
|
public static Map FromTileset(TileSet tileset)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -84,6 +84,8 @@
|
|||||||
<Compile Include="Activities\Activity.cs" />
|
<Compile Include="Activities\Activity.cs" />
|
||||||
<Compile Include="Activities\CallFunc.cs" />
|
<Compile Include="Activities\CallFunc.cs" />
|
||||||
<Compile Include="Actor.cs" />
|
<Compile Include="Actor.cs" />
|
||||||
|
<Compile Include="CacheStorage.cs" />
|
||||||
|
<Compile Include="LogProxy.cs" />
|
||||||
<Compile Include="MPos.cs" />
|
<Compile Include="MPos.cs" />
|
||||||
<Compile Include="GameRules\Warhead.cs" />
|
<Compile Include="GameRules\Warhead.cs" />
|
||||||
<Compile Include="Graphics\QuadRenderer.cs" />
|
<Compile Include="Graphics\QuadRenderer.cs" />
|
||||||
|
|||||||
@@ -24,7 +24,15 @@ namespace OpenRA
|
|||||||
{
|
{
|
||||||
public enum WorldType { Regular, Shellmap }
|
public enum WorldType { Regular, Shellmap }
|
||||||
|
|
||||||
public class World
|
public interface IWorld
|
||||||
|
{
|
||||||
|
IActor WorldActor { get; }
|
||||||
|
int WorldTick { get; }
|
||||||
|
IMap Map { get; }
|
||||||
|
TileSet TileSet { get; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class World : IWorld
|
||||||
{
|
{
|
||||||
class ActorIDComparer : IComparer<Actor>
|
class ActorIDComparer : IComparer<Actor>
|
||||||
{
|
{
|
||||||
@@ -113,9 +121,13 @@ namespace OpenRA
|
|||||||
RenderPlayer = LocalPlayer;
|
RenderPlayer = LocalPlayer;
|
||||||
}
|
}
|
||||||
|
|
||||||
public readonly Actor WorldActor;
|
public Actor WorldActor { get; private set; }
|
||||||
public readonly Map Map;
|
IActor IWorld.WorldActor { get { return WorldActor; } }
|
||||||
public readonly TileSet TileSet;
|
|
||||||
|
public Map Map { get; private set; }
|
||||||
|
IMap IWorld.Map { get { return Map; } }
|
||||||
|
|
||||||
|
public TileSet TileSet { get; private set; }
|
||||||
public readonly ActorMap ActorMap;
|
public readonly ActorMap ActorMap;
|
||||||
public readonly ScreenMap ScreenMap;
|
public readonly ScreenMap ScreenMap;
|
||||||
public readonly WorldType Type;
|
public readonly WorldType Type;
|
||||||
|
|||||||
@@ -29,8 +29,17 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
All = TransientActors | BlockedByMovers
|
All = TransientActors | BlockedByMovers
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public interface IMobileInfo
|
||||||
|
{
|
||||||
|
int MovementCostForCell(World world, CPos cell);
|
||||||
|
bool CanEnterCell(World world, Actor self, CPos cell, out int movementCost, Actor ignoreActor = null, CellConditions check = CellConditions.All);
|
||||||
|
bool CanEnterCell(World world, Actor self, CPos cell, Actor ignoreActor = null, CellConditions check = CellConditions.All);
|
||||||
|
|
||||||
|
int GetMovementClass(TileSet tileset);
|
||||||
|
}
|
||||||
|
|
||||||
[Desc("Unit is able to move.")]
|
[Desc("Unit is able to move.")]
|
||||||
public class MobileInfo : ITraitInfo, IOccupySpaceInfo, IFacingInfo, IMoveInfo, UsesInit<FacingInit>, UsesInit<LocationInit>, UsesInit<SubCellInit>
|
public class MobileInfo : ITraitInfo, IOccupySpaceInfo, IFacingInfo, IMoveInfo, UsesInit<FacingInit>, UsesInit<LocationInit>, UsesInit<SubCellInit>, IMobileInfo
|
||||||
{
|
{
|
||||||
[FieldLoader.LoadUsing("LoadSpeeds")]
|
[FieldLoader.LoadUsing("LoadSpeeds")]
|
||||||
[Desc("Set Water: 0 for ground units and lower the value on rough terrain.")]
|
[Desc("Set Water: 0 for ground units and lower the value on rough terrain.")]
|
||||||
@@ -165,11 +174,61 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int TileSetMovementHash(TileSet tileSet)
|
||||||
|
{
|
||||||
|
var terrainInfos = TilesetTerrainInfo[tileSet];
|
||||||
|
|
||||||
|
// Compute and return the hash using aggregate
|
||||||
|
return terrainInfos.Aggregate(terrainInfos.Length,
|
||||||
|
(current, terrainInfo) => unchecked(current * 31 + terrainInfo.Cost));
|
||||||
|
}
|
||||||
|
|
||||||
public bool CanEnterCell(World world, Actor self, CPos cell, Actor ignoreActor = null, CellConditions check = CellConditions.All)
|
public bool CanEnterCell(World world, Actor self, CPos cell, Actor ignoreActor = null, CellConditions check = CellConditions.All)
|
||||||
{
|
{
|
||||||
if (MovementCostForCell(world, cell) == int.MaxValue)
|
if (MovementCostForCell(world, cell) == int.MaxValue)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
return CanMoveFreelyInto(world, self, cell, ignoreActor, check);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determines whether the actor is blocked by other Actors
|
||||||
|
public bool CanMoveFreelyInto(World world, Actor self, CPos cell, Actor ignoreActor, CellConditions check)
|
||||||
|
{
|
||||||
|
if (SharesCell && world.ActorMap.HasFreeSubCell(cell))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (check.HasFlag(CellConditions.TransientActors))
|
||||||
|
{
|
||||||
|
var canIgnoreMovingAllies = self != null && !check.HasFlag(CellConditions.BlockedByMovers);
|
||||||
|
var needsCellExclusively = self == null || Crushes == null || !Crushes.Any();
|
||||||
|
foreach (var a in world.ActorMap.GetUnitsAt(cell))
|
||||||
|
{
|
||||||
|
if (a == ignoreActor)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Neutral/enemy units are blockers. Allied units that are moving are not blockers.
|
||||||
|
if (canIgnoreMovingAllies && self.Owner.Stances[a.Owner] == Stance.Ally && IsMovingInMyDirection(self, a)) continue;
|
||||||
|
|
||||||
|
// Non-sharable unit can enter a cell with shareable units only if it can crush all of them.
|
||||||
|
if (needsCellExclusively)
|
||||||
|
return false;
|
||||||
|
var crushables = a.TraitsImplementing<ICrushable>();
|
||||||
|
if (!crushables.Any())
|
||||||
|
return false;
|
||||||
|
foreach (var crushable in crushables)
|
||||||
|
if (!crushable.CrushableBy(Crushes, self.Owner))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool CanEnterCell(World world, Actor self, CPos cell, out int movementCost, Actor ignoreActor = null, CellConditions check = CellConditions.All)
|
||||||
|
{
|
||||||
|
if ((movementCost = MovementCostForCell(world, cell)) == int.MaxValue)
|
||||||
|
return false;
|
||||||
|
|
||||||
if (SharesCell && world.ActorMap.HasFreeSubCell(cell))
|
if (SharesCell && world.ActorMap.HasFreeSubCell(cell))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
@@ -506,6 +565,11 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
return Info.CanEnterCell(self.World, self, cell, ignoreActor, checkTransientActors ? CellConditions.All : CellConditions.BlockedByMovers);
|
return Info.CanEnterCell(self.World, self, cell, ignoreActor, checkTransientActors ? CellConditions.All : CellConditions.BlockedByMovers);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool CanMoveFreely(CPos cell, Actor ignoreActor = null, bool checkTransientActors = true)
|
||||||
|
{
|
||||||
|
return Info.CanMoveFreelyInto(self.World, self, cell, ignoreActor, checkTransientActors ? CellConditions.All : CellConditions.BlockedByMovers);
|
||||||
|
}
|
||||||
|
|
||||||
public void EnteringCell(Actor self)
|
public void EnteringCell(Actor self)
|
||||||
{
|
{
|
||||||
var crushables = self.World.ActorMap.GetUnitsAt(ToCell).Where(a => a != self)
|
var crushables = self.World.ActorMap.GetUnitsAt(ToCell).Where(a => a != self)
|
||||||
|
|||||||
Reference in New Issue
Block a user