Updated CPos struct to use a bit field for all properties.

This commit is contained in:
teinarss
2018-10-01 17:57:28 +02:00
committed by Paul Chote
parent 9f82ef999f
commit cfaf5a6467
7 changed files with 61 additions and 14 deletions

View File

@@ -18,11 +18,28 @@ namespace OpenRA
{ {
public struct CPos : IScriptBindable, ILuaAdditionBinding, ILuaSubtractionBinding, ILuaEqualityBinding, ILuaTableBinding, IEquatable<CPos> public struct CPos : IScriptBindable, ILuaAdditionBinding, ILuaSubtractionBinding, ILuaEqualityBinding, ILuaTableBinding, IEquatable<CPos>
{ {
public readonly int X, Y; // Coordinates are packed in a 32 bit signed int
public readonly byte Layer; // X and Y are 12 bits (signed): -2048...2047
// Layer is an unsigned byte
// Packing is XXXX XXXX XXXX YYYY YYYY YYYY LLLL LLLL
public readonly int Bits;
// X is padded to MSB, so bit shift does the correct sign extension
public int X { get { return Bits >> 20; } }
// Align Y with a short, cast, then shift the rest of the way
// The signed short bit shift does the correct sign extension
public int Y { get { return ((short)(Bits >> 4)) >> 4; } }
public byte Layer { get { return (byte)Bits; } }
public CPos(int bits) { Bits = bits; }
public CPos(int x, int y) : this(x, y, 0) { }
public CPos(int x, int y, byte layer)
{
Bits = (x & 0xFFF) << 20 | (y & 0xFFF) << 8 | layer;
}
public CPos(int x, int y) { X = x; Y = y; Layer = 0; }
public CPos(int x, int y, byte layer) { X = x; Y = y; Layer = layer; }
public static readonly CPos Zero = new CPos(0, 0, 0); public static readonly CPos Zero = new CPos(0, 0, 0);
public static explicit operator CPos(int2 a) { return new CPos(a.X, a.Y); } public static explicit operator CPos(int2 a) { return new CPos(a.X, a.Y); }
@@ -32,12 +49,12 @@ namespace OpenRA
public static CPos operator -(CPos a, CVec b) { return new CPos(a.X - b.X, a.Y - b.Y, a.Layer); } public static CPos operator -(CPos a, CVec b) { return new CPos(a.X - b.X, a.Y - b.Y, a.Layer); }
public static CVec operator -(CPos a, CPos b) { return new CVec(a.X - b.X, a.Y - b.Y); } public static CVec operator -(CPos a, CPos b) { return new CVec(a.X - b.X, a.Y - b.Y); }
public static bool operator ==(CPos me, CPos other) { return me.X == other.X && me.Y == other.Y && me.Layer == other.Layer; } public static bool operator ==(CPos me, CPos other) { return me.Bits == other.Bits; }
public static bool operator !=(CPos me, CPos other) { return !(me == other); } public static bool operator !=(CPos me, CPos other) { return !(me == other); }
public override int GetHashCode() { return X.GetHashCode() ^ Y.GetHashCode() ^ Layer.GetHashCode(); } public override int GetHashCode() { return Bits.GetHashCode(); }
public bool Equals(CPos other) { return X == other.X && Y == other.Y && Layer == other.Layer; } public bool Equals(CPos other) { return Bits == other.Bits; }
public override bool Equals(object obj) { return obj is CPos && Equals((CPos)obj); } public override bool Equals(object obj) { return obj is CPos && Equals((CPos)obj); }
public override string ToString() { return X + "," + Y; } public override string ToString() { return X + "," + Y; }

View File

@@ -56,7 +56,7 @@ namespace OpenRA
public readonly string[] categories; public readonly string[] categories;
public readonly int players; public readonly int players;
public readonly Rectangle bounds; public readonly Rectangle bounds;
public readonly int[] spawnpoints = { }; public readonly short[] spawnpoints = { };
public readonly MapGridType map_grid_type; public readonly MapGridType map_grid_type;
public readonly string minimap; public readonly string minimap;
public readonly bool downloading; public readonly bool downloading;

View File

@@ -128,7 +128,7 @@ namespace OpenRA
{ {
if (flags.HasField(OrderFields.TargetIsCell)) if (flags.HasField(OrderFields.TargetIsCell))
{ {
var cell = new CPos(r.ReadInt32(), r.ReadInt32(), r.ReadByte()); var cell = new CPos(r.ReadInt32());
var subCell = (SubCell)r.ReadByte(); var subCell = (SubCell)r.ReadByte();
if (world != null) if (world != null)
target = Target.FromCell(world, cell, subCell); target = Target.FromCell(world, cell, subCell);
@@ -146,7 +146,7 @@ namespace OpenRA
var targetString = flags.HasField(OrderFields.TargetString) ? r.ReadString() : null; var targetString = flags.HasField(OrderFields.TargetString) ? r.ReadString() : null;
var queued = flags.HasField(OrderFields.Queued); var queued = flags.HasField(OrderFields.Queued);
var extraLocation = flags.HasField(OrderFields.ExtraLocation) ? new CPos(r.ReadInt32(), r.ReadInt32(), r.ReadByte()) : CPos.Zero; var extraLocation = flags.HasField(OrderFields.ExtraLocation) ? new CPos(r.ReadInt32()) : CPos.Zero;
var extraData = flags.HasField(OrderFields.ExtraData) ? r.ReadUInt32() : 0; var extraData = flags.HasField(OrderFields.ExtraData) ? r.ReadUInt32() : 0;
if (world == null) if (world == null)

View File

@@ -58,9 +58,7 @@ namespace OpenRA.Network
public static void Write(this BinaryWriter w, CPos cell) public static void Write(this BinaryWriter w, CPos cell)
{ {
w.Write(cell.X); w.Write(cell.Bits);
w.Write(cell.Y);
w.Write(cell.Layer);
} }
public static void Write(this BinaryWriter w, WPos pos) public static void Write(this BinaryWriter w, WPos pos)

View File

@@ -0,0 +1,31 @@
using System.Runtime.Remoting.Metadata;
using NUnit.Framework;
namespace OpenRA.Test
{
[TestFixture]
public class CPosTest
{
[TestCase(TestName = "Packing x,y and layer into int")]
public void PackUnpackBits()
{
var values = new int[] { -2048, -1024, 0, 1024, 2047 };
var layerValues = new byte[] { 0, 128, 255 };
foreach (var x in values)
{
foreach (var y in values)
{
foreach (var layer in layerValues)
{
var cell = new CPos(x, y, layer);
Assert.AreEqual(x, cell.X);
Assert.AreEqual(y, cell.Y);
Assert.AreEqual(layer, cell.Layer);
}
}
}
}
}
}

View File

@@ -64,7 +64,7 @@ namespace OpenRA.Test
var o = new Order("Test", null, Target.Invalid, true) var o = new Order("Test", null, Target.Invalid, true)
{ {
TargetString = "TargetString", TargetString = "TargetString",
ExtraLocation = new CPos(int.MinValue, int.MaxValue, 128), ExtraLocation = new CPos(2047, 2047, 128),
ExtraData = uint.MaxValue, ExtraData = uint.MaxValue,
IsImmediate = true, IsImmediate = true,
}.Serialize(); }.Serialize();

View File

@@ -46,6 +46,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="OpenRA.Game\ActionQueueTest.cs" /> <Compile Include="OpenRA.Game\ActionQueueTest.cs" />
<Compile Include="OpenRA.Game\CPosTest.cs" />
<Compile Include="OpenRA.Game\MiniYamlTest.cs" /> <Compile Include="OpenRA.Game\MiniYamlTest.cs" />
<Compile Include="OpenRA.Game\ActorInfoTest.cs" /> <Compile Include="OpenRA.Game\ActorInfoTest.cs" />
<Compile Include="OpenRA.Game\CoordinateTest.cs" /> <Compile Include="OpenRA.Game\CoordinateTest.cs" />