mirror of
https://github.com/oliverbooth/VpSharp
synced 2024-11-22 23:58:47 +00:00
Add Coordinates struct
This commit is contained in:
parent
a064328418
commit
027ce96ed3
58
VpSharp.Tests/src/CoordinateTests.cs
Normal file
58
VpSharp.Tests/src/CoordinateTests.cs
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
|
namespace VpSharp.Tests;
|
||||||
|
|
||||||
|
[TestClass]
|
||||||
|
public sealed class CoordinateTests
|
||||||
|
{
|
||||||
|
[TestMethod]
|
||||||
|
public void TestAbsolute()
|
||||||
|
{
|
||||||
|
TestCoordinates("asdf", 0.0, 0.0, 0.0, 0.0, world: "asdf");
|
||||||
|
TestCoordinates("1n 1w", 1.0, 0.0, 1.0);
|
||||||
|
TestCoordinates("test 10n 5e 1a 123", -5, 1, 10, 123, world: "test");
|
||||||
|
TestCoordinates("4s 6w -10a 45", 6, -10, -4, 45);
|
||||||
|
TestCoordinates(" 100n 100w 1.5a 180", 100, 1.5, 100, 180);
|
||||||
|
TestCoordinates("2355.71S 3429.68E -0.37a 0", -3429.68, -0.37, -2355.71);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void TestRelative()
|
||||||
|
{
|
||||||
|
TestCoordinates("-1.1 +0 -1.2a", 0.0, -1.2, -1.1, 0.0, true);
|
||||||
|
TestCoordinates("+0 +0 +5a", 0.0, 5.0, 0.0, 0.0, true);
|
||||||
|
TestCoordinates("+1 +1 +1a", 1.0, 1.0, 1.0, 0.0, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void TestCoordinates(
|
||||||
|
string input,
|
||||||
|
double x,
|
||||||
|
double y,
|
||||||
|
double z,
|
||||||
|
double yaw = 0.0,
|
||||||
|
bool isRelative = false,
|
||||||
|
string? world = null
|
||||||
|
)
|
||||||
|
{
|
||||||
|
Coordinates coordinates = Coordinates.Parse(input);
|
||||||
|
|
||||||
|
Trace.WriteLine("----");
|
||||||
|
Trace.WriteLine($"Input: {input}");
|
||||||
|
Trace.WriteLine($"Parsed: {coordinates}");
|
||||||
|
Trace.WriteLine("----");
|
||||||
|
|
||||||
|
Assert.AreEqual(x, coordinates.X);
|
||||||
|
Assert.AreEqual(y, coordinates.Y);
|
||||||
|
Assert.AreEqual(z, coordinates.Z);
|
||||||
|
Assert.AreEqual(yaw, coordinates.Yaw);
|
||||||
|
Assert.AreEqual(isRelative, coordinates.IsRelative);
|
||||||
|
if (string.IsNullOrWhiteSpace(world))
|
||||||
|
{
|
||||||
|
Assert.IsTrue(string.IsNullOrWhiteSpace(coordinates.World));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Assert.AreEqual(world, coordinates.World);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
304
VpSharp/src/Coordinates.Serialization.cs
Normal file
304
VpSharp/src/Coordinates.Serialization.cs
Normal file
@ -0,0 +1,304 @@
|
|||||||
|
using System.Globalization;
|
||||||
|
using System.Text;
|
||||||
|
using Cysharp.Text;
|
||||||
|
using X10D.Linq;
|
||||||
|
using X10D.Text;
|
||||||
|
|
||||||
|
namespace VpSharp;
|
||||||
|
|
||||||
|
public readonly partial struct Coordinates
|
||||||
|
{
|
||||||
|
private static class Serializer
|
||||||
|
{
|
||||||
|
public static string Serialize(in Coordinates coordinates, string format)
|
||||||
|
{
|
||||||
|
int count = Serialize(coordinates, format, Span<char>.Empty);
|
||||||
|
Span<char> chars = stackalloc char[count];
|
||||||
|
Serialize(coordinates, format, chars);
|
||||||
|
return chars.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int Serialize(in Coordinates coordinates, string format, Span<char> destination)
|
||||||
|
{
|
||||||
|
using Utf8ValueStringBuilder builder = ZString.CreateUtf8StringBuilder();
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(coordinates.World))
|
||||||
|
{
|
||||||
|
builder.Append(coordinates.World);
|
||||||
|
builder.Append(' ');
|
||||||
|
}
|
||||||
|
|
||||||
|
bool north = coordinates.Z >= 0.0;
|
||||||
|
bool west = coordinates.X >= 0.0;
|
||||||
|
bool up = coordinates.Y >= 0.0;
|
||||||
|
bool dir = coordinates.Yaw >= 0.0;
|
||||||
|
|
||||||
|
if (coordinates.IsRelative)
|
||||||
|
{
|
||||||
|
if (north)
|
||||||
|
{
|
||||||
|
builder.Append('+');
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.Append(string.Format(CultureInfo.InvariantCulture, format, coordinates.Z));
|
||||||
|
builder.Append(' ');
|
||||||
|
|
||||||
|
if (west)
|
||||||
|
{
|
||||||
|
builder.Append('+');
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.Append(string.Format(CultureInfo.InvariantCulture, format, coordinates.X));
|
||||||
|
builder.Append(' ');
|
||||||
|
|
||||||
|
if (up)
|
||||||
|
{
|
||||||
|
builder.Append('+');
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.Append(string.Format(CultureInfo.InvariantCulture, format, coordinates.Y));
|
||||||
|
builder.Append("a ");
|
||||||
|
|
||||||
|
if (dir)
|
||||||
|
{
|
||||||
|
builder.Append('+');
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.Append(string.Format(CultureInfo.InvariantCulture, format, coordinates.Yaw));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
char zChar = north ? 'n' : 's';
|
||||||
|
char xChar = west ? 'w' : 'e';
|
||||||
|
|
||||||
|
builder.Append(string.Format(CultureInfo.InvariantCulture, format, Math.Abs(coordinates.Z)));
|
||||||
|
builder.Append(zChar);
|
||||||
|
builder.Append(' ');
|
||||||
|
|
||||||
|
builder.Append(string.Format(CultureInfo.InvariantCulture, format, Math.Abs(coordinates.X)));
|
||||||
|
builder.Append(xChar);
|
||||||
|
builder.Append(' ');
|
||||||
|
|
||||||
|
builder.Append(string.Format(CultureInfo.InvariantCulture, format, coordinates.Y));
|
||||||
|
builder.Append("a ");
|
||||||
|
|
||||||
|
builder.Append(string.Format(CultureInfo.InvariantCulture, format, coordinates.Yaw));
|
||||||
|
}
|
||||||
|
|
||||||
|
ReadOnlySpan<byte> bytes = builder.AsSpan();
|
||||||
|
Span<char> chars = stackalloc char[bytes.Length];
|
||||||
|
Encoding.UTF8.GetChars(bytes, chars);
|
||||||
|
|
||||||
|
for (var index = 0; index < destination.Length; index++)
|
||||||
|
{
|
||||||
|
destination[index] = chars[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder.Length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Coordinates Deserialize(ReadOnlySpan<char> value)
|
||||||
|
{
|
||||||
|
using Utf8ValueStringBuilder builder = ZString.CreateUtf8StringBuilder();
|
||||||
|
string? world = null;
|
||||||
|
var isRelative = false;
|
||||||
|
double x = 0.0, y = 0.0, z = 0.0, yaw = 0.0;
|
||||||
|
|
||||||
|
var word = 0;
|
||||||
|
for (var index = 0; index < value.Length; index++)
|
||||||
|
{
|
||||||
|
char current = value[index];
|
||||||
|
bool atEnd = index == value.Length - 1;
|
||||||
|
|
||||||
|
if (atEnd || char.IsWhiteSpace(current))
|
||||||
|
{
|
||||||
|
if (!builder.AsSpan().All(b => char.IsWhiteSpace((char)b)))
|
||||||
|
{
|
||||||
|
if (atEnd)
|
||||||
|
{
|
||||||
|
builder.Append(current);
|
||||||
|
}
|
||||||
|
|
||||||
|
ProcessBuffer();
|
||||||
|
word++;
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.Clear();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
builder.Append(current);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Coordinates(world, x, y, z, yaw, isRelative);
|
||||||
|
|
||||||
|
void ProcessBuffer()
|
||||||
|
{
|
||||||
|
ReadOnlySpan<byte> bytes = builder.AsSpan();
|
||||||
|
Span<char> chars = stackalloc char[bytes.Length];
|
||||||
|
Encoding.UTF8.GetChars(bytes, chars);
|
||||||
|
bool hasWorld = !string.IsNullOrWhiteSpace(world);
|
||||||
|
|
||||||
|
if (word == 0 && !IsUnitString(bytes))
|
||||||
|
{
|
||||||
|
world = chars.ToString().AsNullIfWhiteSpace();
|
||||||
|
}
|
||||||
|
else if (IsRelativeUnit(bytes))
|
||||||
|
{
|
||||||
|
isRelative = true;
|
||||||
|
|
||||||
|
switch (word)
|
||||||
|
{
|
||||||
|
case 0 when !hasWorld:
|
||||||
|
case 1 when hasWorld:
|
||||||
|
double.TryParse(chars, NumberStyles.Float, CultureInfo.InvariantCulture, out z);
|
||||||
|
break;
|
||||||
|
case 1 when !hasWorld:
|
||||||
|
case 2 when hasWorld:
|
||||||
|
double.TryParse(chars, NumberStyles.Float, CultureInfo.InvariantCulture, out x);
|
||||||
|
break;
|
||||||
|
case 2 when !hasWorld:
|
||||||
|
case 3 when hasWorld:
|
||||||
|
double.TryParse(chars, NumberStyles.Float, CultureInfo.InvariantCulture, out y);
|
||||||
|
break;
|
||||||
|
case 3 when !hasWorld:
|
||||||
|
case 4 when hasWorld:
|
||||||
|
double.TryParse(chars, NumberStyles.Float, CultureInfo.InvariantCulture, out yaw);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (((!hasWorld && word == 1) || (hasWorld && word == 2)) && chars[^1] is 'x' or 'X' or 'w' or 'W')
|
||||||
|
{
|
||||||
|
_ = double.TryParse(chars[..^1], NumberStyles.Float, CultureInfo.InvariantCulture, out x);
|
||||||
|
}
|
||||||
|
else if (((!hasWorld && word == 0) || (hasWorld && word == 1)) && chars[^1] is 'z' or 'Z' or 'n' or 'N')
|
||||||
|
{
|
||||||
|
_ = double.TryParse(chars[..^1], NumberStyles.Float, CultureInfo.InvariantCulture, out z);
|
||||||
|
}
|
||||||
|
else if (((!hasWorld && word == 1) || (hasWorld && word == 2)) && chars[^1] is 'e' or 'E')
|
||||||
|
{
|
||||||
|
_ = double.TryParse(chars[..^1], NumberStyles.Float, CultureInfo.InvariantCulture, out x);
|
||||||
|
x = -x;
|
||||||
|
}
|
||||||
|
else if (((!hasWorld && word == 0) || (hasWorld && word == 1)) && chars[^1] is 's' or 'S')
|
||||||
|
{
|
||||||
|
_ = double.TryParse(chars[..^1], NumberStyles.Float, CultureInfo.InvariantCulture, out z);
|
||||||
|
z = -z;
|
||||||
|
}
|
||||||
|
else if (((!hasWorld && word == 2) || (hasWorld && word == 3)) && chars[^1] is 'a' or 'A')
|
||||||
|
{
|
||||||
|
_ = double.TryParse(chars[..^1], NumberStyles.Float, CultureInfo.InvariantCulture, out y);
|
||||||
|
}
|
||||||
|
else if (((!hasWorld && word == 3) || (hasWorld && word == 4)) && double.TryParse(chars, NumberStyles.Float, CultureInfo.InvariantCulture, out double temp))
|
||||||
|
{
|
||||||
|
yaw = temp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a value indicating whether the specified span of characters represents a relative unit string.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="bytes">The span of characters to validate.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// <see langword="true" /> if <paramref name="bytes" /> represents a valid relative unit string; otherwise,
|
||||||
|
/// <see langword="false" />.
|
||||||
|
/// </returns>
|
||||||
|
public static bool IsAbsoluteUnit(ReadOnlySpan<byte> bytes)
|
||||||
|
{
|
||||||
|
Span<char> chars = stackalloc char[bytes.Length];
|
||||||
|
Encoding.UTF8.GetChars(bytes, chars);
|
||||||
|
return IsRelativeUnit(chars);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a value indicating whether the specified span of characters represents a relative unit string.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="chars">The span of characters to validate.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// <see langword="true" /> if <paramref name="chars" /> represents a valid relative unit string; otherwise,
|
||||||
|
/// <see langword="false" />.
|
||||||
|
/// </returns>
|
||||||
|
public static bool IsAbsoluteUnit(ReadOnlySpan<char> chars)
|
||||||
|
{
|
||||||
|
ReadOnlySpan<char> validChars = "nNeEwWsSaA";
|
||||||
|
return double.TryParse(chars, out _) ||
|
||||||
|
(validChars.Contains(chars[^1]) &&
|
||||||
|
double.TryParse(chars[..^1], NumberStyles.Float, CultureInfo.InvariantCulture, out _));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a value indicating whether the specified span of characters represents a relative unit string.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="bytes">The span of characters to validate.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// <see langword="true" /> if <paramref name="bytes" /> represents a valid relative unit string; otherwise,
|
||||||
|
/// <see langword="false" />.
|
||||||
|
/// </returns>
|
||||||
|
public static bool IsRelativeUnit(ReadOnlySpan<byte> bytes)
|
||||||
|
{
|
||||||
|
Span<char> chars = stackalloc char[bytes.Length];
|
||||||
|
Encoding.UTF8.GetChars(bytes, chars);
|
||||||
|
return IsRelativeUnit(chars);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a value indicating whether the specified span of characters represents a relative unit string.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="chars">The span of characters to validate.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// <see langword="true" /> if <paramref name="chars" /> represents a valid relative unit string; otherwise,
|
||||||
|
/// <see langword="false" />.
|
||||||
|
/// </returns>
|
||||||
|
public static bool IsRelativeUnit(ReadOnlySpan<char> chars)
|
||||||
|
{
|
||||||
|
return (chars[0] == '+' || chars[0] == '-') &&
|
||||||
|
double.TryParse(chars, NumberStyles.Float, CultureInfo.InvariantCulture, out _);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a value indicating whether the specified span of characters represents a valid coordinate unit string.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="bytes">The span of characters to validate.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// <see langword="true" /> if <paramref name="bytes" /> represents a valid coordinate unit string; otherwise,
|
||||||
|
/// <see langword="false" />.
|
||||||
|
/// </returns>
|
||||||
|
public static bool IsUnitString(ReadOnlySpan<byte> bytes)
|
||||||
|
{
|
||||||
|
Span<char> chars = stackalloc char[bytes.Length];
|
||||||
|
Encoding.UTF8.GetChars(bytes, chars);
|
||||||
|
return IsUnitString(chars);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a value indicating whether the specified span of characters represents a valid coordinate unit string.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="chars">The span of characters to validate.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// <see langword="true" /> if <paramref name="chars" /> represents a valid coordinate unit string; otherwise,
|
||||||
|
/// <see langword="false" />.
|
||||||
|
/// </returns>
|
||||||
|
public static bool IsUnitString(ReadOnlySpan<char> chars)
|
||||||
|
{
|
||||||
|
chars = chars.Trim();
|
||||||
|
|
||||||
|
if (chars.Length == 0)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!char.IsDigit(chars[0]) && chars[0] != '+' && chars[0] != '-')
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// thicc char span
|
||||||
|
return IsRelativeUnit(chars) || IsAbsoluteUnit(chars);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
146
VpSharp/src/Coordinates.cs
Normal file
146
VpSharp/src/Coordinates.cs
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
namespace VpSharp;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a set of coordinates.
|
||||||
|
/// </summary>
|
||||||
|
public readonly partial struct Coordinates
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="Coordinates" /> struct.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="x">The X coordinate.</param>
|
||||||
|
/// <param name="y">The Y coordinate.</param>
|
||||||
|
/// <param name="z">The Z coordinate.</param>
|
||||||
|
/// <param name="yaw">The yaw.</param>
|
||||||
|
/// <param name="isRelative">
|
||||||
|
/// <see langword="true" /> if these coordinates represent relative coordinates; <see langword="false" /> otherwise.
|
||||||
|
/// </param>
|
||||||
|
public Coordinates(double x, double y, double z, double yaw, bool isRelative = false)
|
||||||
|
: this(null, x, y, z, yaw, isRelative)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="Coordinates" /> struct.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="world">The world name.</param>
|
||||||
|
/// <param name="x">The X coordinate.</param>
|
||||||
|
/// <param name="y">The Y coordinate.</param>
|
||||||
|
/// <param name="z">The Z coordinate.</param>
|
||||||
|
/// <param name="yaw">The yaw.</param>
|
||||||
|
/// <param name="isRelative">
|
||||||
|
/// <see langword="true" /> if these coordinates represent relative coordinates; <see langword="false" /> otherwise.
|
||||||
|
/// </param>
|
||||||
|
public Coordinates(string? world, double x, double y, double z, double yaw, bool isRelative = false)
|
||||||
|
{
|
||||||
|
World = world;
|
||||||
|
X = x;
|
||||||
|
Y = y;
|
||||||
|
Z = z;
|
||||||
|
Yaw = yaw;
|
||||||
|
IsRelative = isRelative;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or initializes a value indicating whether this instance represents relative coordinates.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>
|
||||||
|
/// <see langword="true" /> if this instance represents relative coordinates; otherwise, <see langword="false" />.
|
||||||
|
/// </value>
|
||||||
|
public bool IsRelative { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or initializes the world.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The world.</value>
|
||||||
|
public string? World { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or initializes the X coordinate.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The X coordinate.</value>
|
||||||
|
public double X { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or initializes the Y coordinate.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The Y coordinate.</value>
|
||||||
|
public double Y { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or initializes the yaw.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The yaw.</value>
|
||||||
|
public double Yaw { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or initializes the Z coordinate.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The Z coordinate.</value>
|
||||||
|
public double Z { get; init; }
|
||||||
|
|
||||||
|
public static bool operator ==(Coordinates left, Coordinates right) =>
|
||||||
|
left.Equals(right);
|
||||||
|
|
||||||
|
public static bool operator !=(Coordinates left, Coordinates right) =>
|
||||||
|
!(left == right);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Parses a coordinate string.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="coordinates">The coordinates to parse.</param>
|
||||||
|
/// <returns>An instance of <see cref="Coordinates" />.</returns>
|
||||||
|
public static Coordinates Parse(string coordinates)
|
||||||
|
{
|
||||||
|
return Serializer.Deserialize(coordinates);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a value indicating whether this instance of <see cref="Coordinates" /> and another instance of
|
||||||
|
/// <see cref="Coordinates" /> are equal.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="other">The instance against which to compare.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// <see langword="true" /> if this instance is equal to <paramref name="other" />; otherwise, <see langword="false" />.
|
||||||
|
/// </returns>
|
||||||
|
public bool Equals(Coordinates other)
|
||||||
|
{
|
||||||
|
return X.Equals(other.X) &&
|
||||||
|
Y.Equals(other.Y) &&
|
||||||
|
Z.Equals(other.Z) &&
|
||||||
|
Yaw.Equals(other.Yaw) &&
|
||||||
|
IsRelative.Equals(other.IsRelative) &&
|
||||||
|
string.Equals(World, other.World);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override bool Equals(object? obj)
|
||||||
|
{
|
||||||
|
return obj is Coordinates other && Equals(other);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return HashCode.Combine(World, X, Y, Z, Yaw);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the string representation of these coordinates.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A <see cref="string" /> representation of these coordinates.</returns>
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return ToString("{0}");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the string representation of these coordinates.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="format">The format to apply to each component.</param>
|
||||||
|
/// <returns>A <see cref="string" /> representation of these coordinates.</returns>
|
||||||
|
public string ToString(string format)
|
||||||
|
{
|
||||||
|
return Serializer.Serialize(this, format);
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,7 @@
|
|||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using VpSharp.Entities;
|
using VpSharp.Entities;
|
||||||
|
using VpSharp.Extensions;
|
||||||
|
using X10D.Math;
|
||||||
|
|
||||||
namespace VpSharp;
|
namespace VpSharp;
|
||||||
|
|
||||||
@ -13,6 +15,23 @@ public readonly struct Location : IEquatable<Location>
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static readonly Location Nowhere = new(VirtualParadiseWorld.Nowhere);
|
public static readonly Location Nowhere = new(VirtualParadiseWorld.Nowhere);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="Location" /> struct.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="world">The world.</param>
|
||||||
|
/// <param name="coordinates">
|
||||||
|
/// The coordinates which contains the position and rotation. The <see cref="Coordinates.World" /> property in this value
|
||||||
|
/// is ignored. Fetch the world using <see cref="VirtualParadiseClient.GetWorldAsync" />, and pass that into the
|
||||||
|
/// <paramref name="world" /> parameter.
|
||||||
|
/// </param>
|
||||||
|
/// <exception cref="ArgumentNullException"><paramref name="world" /> is <see langword="null" />.</exception>
|
||||||
|
public Location(VirtualParadiseWorld world, in Coordinates coordinates)
|
||||||
|
{
|
||||||
|
World = world ?? throw new ArgumentNullException(nameof(world));
|
||||||
|
Position = new Vector3d(coordinates.X, coordinates.Y, coordinates.Z);
|
||||||
|
Rotation = Quaternion.CreateFromYawPitchRoll((float)coordinates.Yaw.DegreesToRadians(), 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="Location" /> struct.
|
/// Initializes a new instance of the <see cref="Location" /> struct.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -34,8 +53,8 @@ public readonly struct Location : IEquatable<Location>
|
|||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
var x = (int) Math.Floor(Position.X);
|
var x = (int)Math.Floor(Position.X);
|
||||||
var z = (int) Math.Floor(Position.Z);
|
var z = (int)Math.Floor(Position.Z);
|
||||||
return new Cell(x, z);
|
return new Cell(x, z);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -110,6 +129,17 @@ public readonly struct Location : IEquatable<Location>
|
|||||||
return HashCode.Combine(Position, Rotation, World);
|
return HashCode.Combine(Position, Rotation, World);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Converts this <see cref="Location" /> to an instance of <see cref="Coordinates" />.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The result of the conversion to <see cref="Coordinates" />.</returns>
|
||||||
|
public Coordinates ToCoordinates()
|
||||||
|
{
|
||||||
|
(double x, double y, double z) = Position;
|
||||||
|
(_, double yaw, _) = Rotation.ToEulerAngles();
|
||||||
|
return new Coordinates(World?.Name, x, y, z, yaw);
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user