Created
October 1, 2019 17:53
-
-
Save copygirl/b0c7309d7495f00c56e76de971df222c to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Text; | |
using Vintagestory.API.MathTools; | |
namespace Vintagestory.Essentials | |
{ | |
[Flags] | |
public enum ProperNeighbor : byte | |
{ | |
None = 0, | |
// FACINGS | |
East = 0b110000, // +X | |
West = 0b100000, // -X | |
Up = 0b001100, // +Y | |
Down = 0b001000, // -Y | |
South = 0b000011, // +Z | |
North = 0b000010, // -Z | |
// CARDINALS | |
SouthEast = South | East, // +X +Z | |
SouthWest = South | West, // -X +Z | |
NorthEast = North | East, // +X -Z | |
NorthWest = North | West, // -X -Z | |
// ALL_AXIS_PLANES | |
UpEast = Up | East , // +X +Y | |
UpWest = Up | West , // -X +Y | |
UpSouth = Up | South, // +Z +Y | |
UpNorth = Up | North, // -Z +Y | |
DownEast = Down | East , // +X -Y | |
DownWest = Down | West , // -X -Y | |
DownSouth = Down | South, // +Z -Y | |
DownNorth = Down | North, // -Z -Y | |
// ALL | |
UpSouthEast = Up | South | East, // +X +Y +Z | |
UpSouthWest = Up | South | West, // -X +Y +Z | |
UpNorthEast = Up | North | East, // +X +Y -Z | |
UpNorthWest = Up | North | West, // -X +Y -Z | |
DownSouthEast = Down | South | East, // +X -Y +Z | |
DownSouthWest = Down | South | West, // -X -Y +Z | |
DownNorthEast = Down | North | East, // +X -Y -Z | |
DownNorthWest = Down | North | West, // -X -Y -Z | |
} | |
public static class ProperNeighborHelper | |
{ | |
public static readonly ImmutableSet<ProperNeighbor> HORIZONTALS = | |
new ImmutableSet<ProperNeighbor>( | |
ProperNeighbor.East, ProperNeighbor.West, | |
ProperNeighbor.South, ProperNeighbor.North); | |
public static readonly ImmutableSet<ProperNeighbor> VERTICALS = | |
new ImmutableSet<ProperNeighbor>(ProperNeighbor.Up, ProperNeighbor.Down); | |
public static readonly ImmutableSet<ProperNeighbor> FACINGS = | |
new ImmutableSet<ProperNeighbor>(HORIZONTALS, VERTICALS); | |
public static readonly ImmutableSet<ProperNeighbor> CARDINALS = | |
new ImmutableSet<ProperNeighbor>(HORIZONTALS, | |
ProperNeighbor.SouthEast, ProperNeighbor.SouthWest, | |
ProperNeighbor.NorthEast, ProperNeighbor.NorthWest); | |
public static readonly ImmutableSet<ProperNeighbor> ALL_AXIS_PLANES = | |
new ImmutableSet<ProperNeighbor>(FACINGS, | |
ProperNeighbor.SouthEast, ProperNeighbor.SouthWest, | |
ProperNeighbor.NorthEast, ProperNeighbor.NorthWest, | |
ProperNeighbor.UpEast , ProperNeighbor.UpWest , | |
ProperNeighbor.UpSouth , ProperNeighbor.UpNorth , | |
ProperNeighbor.DownEast , ProperNeighbor.DownWest , | |
ProperNeighbor.DownSouth, ProperNeighbor.DownNorth); | |
public static readonly ImmutableSet<ProperNeighbor> ALL = | |
new ImmutableSet<ProperNeighbor>(ALL_AXIS_PLANES, | |
ProperNeighbor.UpSouthEast, ProperNeighbor.UpSouthWest, | |
ProperNeighbor.UpNorthEast, ProperNeighbor.UpNorthWest, | |
ProperNeighbor.DownSouthEast, ProperNeighbor.DownSouthWest, | |
ProperNeighbor.DownNorthEast, ProperNeighbor.DownNorthWest); | |
public static ProperNeighbor fromAxis(EnumAxis axis, int v) | |
{ | |
if ((v < -1) || (v > 1)) | |
throw new ArgumentOutOfRangeException(nameof(v), $"v must be within (-1, 1), is {v}"); | |
switch (axis) { | |
case EnumAxis.X: return (v > 0) ? ProperNeighbor.East : ProperNeighbor.West; | |
case EnumAxis.Y: return (v > 0) ? ProperNeighbor.Up : ProperNeighbor.Down; | |
case EnumAxis.Z: return (v > 0) ? ProperNeighbor.South : ProperNeighbor.North; | |
default: return ProperNeighbor.None; | |
} | |
} | |
public static EnumAxis getAxis(this ProperNeighbor self) | |
{ | |
switch (self) { | |
case ProperNeighbor.East : return EnumAxis.X; | |
case ProperNeighbor.West : return EnumAxis.X; | |
case ProperNeighbor.Up : return EnumAxis.Y; | |
case ProperNeighbor.Down : return EnumAxis.Y; | |
case ProperNeighbor.South : return EnumAxis.Z; | |
case ProperNeighbor.North : return EnumAxis.Z; | |
default: throw new ArgumentException(nameof(self), $"{self} is not one of FACINGS"); | |
} | |
} | |
public static ProperNeighbor fromOffset(int x, int y, int z) | |
{ | |
ProperNeighbor neighbor = ProperNeighbor.None; | |
if (x != 0) { | |
if (x == 1) neighbor |= ProperNeighbor.East; | |
else if (x == -1) neighbor |= ProperNeighbor.West; | |
else throw new ArgumentOutOfRangeException(nameof(x), $"x must be within (-1, 1), is {x}"); | |
} | |
if (y != 0) { | |
if (y == 1) neighbor |= ProperNeighbor.Up; | |
else if (y == -1) neighbor |= ProperNeighbor.Down; | |
else throw new ArgumentOutOfRangeException(nameof(y), $"y must be within (-1, 1), is {y}"); | |
} | |
if (z != 0) { | |
if (z == 1) neighbor |= ProperNeighbor.South; | |
else if (z == -1) neighbor |= ProperNeighbor.North; | |
else throw new ArgumentOutOfRangeException(nameof(z), $"z must be within (-1, 1), is {z}"); | |
} | |
return neighbor; | |
// Alternative implementation: | |
// if ((x < -1) || (x > 1)) throw new ArgumentOutOfRangeException(nameof(x), "x must be within (-1, 1)"); | |
// if ((y < -1) || (y > 1)) throw new ArgumentOutOfRangeException(nameof(y), "y must be within (-1, 1)"); | |
// if ((z < -1) || (z > 1)) throw new ArgumentOutOfRangeException(nameof(z), "z must be within (-1, 1)"); | |
// return ((x != 0) ? ((x > 0) ? ProperNeighbor.East : ProperNeighbor.West ) : 0) | |
// | ((y != 0) ? ((y > 0) ? ProperNeighbor.Up : ProperNeighbor.Down ) : 0) | |
// | ((z != 0) ? ((z > 0) ? ProperNeighbor.South : ProperNeighbor.North) : 0); | |
} | |
private const int X_SET_BIT = 0b100000, X_VALUE_BIT = 0b010000; | |
private const int Y_SET_BIT = 0b001000, Y_VALUE_BIT = 0b000100; | |
private const int Z_SET_BIT = 0b000010, Z_VALUE_BIT = 0b000001; | |
public static void getOffset(this ProperNeighbor self, | |
out int x, out int y, out int z) | |
{ | |
x = (((int)self & X_SET_BIT) != 0) ? ((((int)self & X_VALUE_BIT) != 0) ? 1 : -1) : 0; | |
y = (((int)self & Y_SET_BIT) != 0) ? ((((int)self & Y_VALUE_BIT) != 0) ? 1 : -1) : 0; | |
z = (((int)self & Z_SET_BIT) != 0) ? ((((int)self & Z_VALUE_BIT) != 0) ? 1 : -1) : 0; | |
} | |
public static ProperPos toProperPos(this ProperNeighbor self) | |
{ | |
self.getOffset(out var x, out var y, out var z); | |
return new ProperPos(x, y, z); | |
} | |
public static Vec3i toVec3i(this ProperNeighbor self) | |
{ | |
self.getOffset(out var x, out var y, out var z); | |
return new Vec3i(x, y, z); | |
} | |
public static bool isNone(this ProperNeighbor self) | |
=> (self == ProperNeighbor.None); | |
public static bool isHorizontal(this ProperNeighbor self) | |
=> HORIZONTALS.Contains(self); | |
public static bool isVertical(this ProperNeighbor self) | |
=> VERTICALS.Contains(self); | |
public static bool isCardinal(this ProperNeighbor self) | |
=> CARDINALS.Contains(self); | |
public static bool isFacing(this ProperNeighbor self) | |
=> FACINGS.Contains(self); | |
public static bool isValid(this ProperNeighbor self) | |
=> ALL.Contains(self); | |
public static string ToShortString(this ProperNeighbor self) | |
{ | |
if (!self.isValid()) return "-"; | |
var sb = new StringBuilder(3); | |
foreach (var chr in self.ToString()) | |
if ((chr >= 'A') && (chr <= 'Z')) // ASCII IsUpper | |
sb.Append(chr + 0x20); // ASCII ToUpper | |
return sb.ToString(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment