This commit is contained in:
mischa 2024-11-11 04:55:00 +02:00 committed by GitHub
commit f6954b55e1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 294 additions and 0 deletions

View File

@ -63,6 +63,13 @@ public static class NetworkReaderExtensions
public static decimal? ReadDecimalNullable(this NetworkReader reader) => reader.ReadBlittableNullable<decimal>();
public static Half ReadHalf(this NetworkReader reader) => new Half(reader.ReadUShort());
public static Vector3Half ReadVector3Half(this NetworkReader reader)
{
Half x = reader.ReadHalf();
Half y = reader.ReadHalf();
Half z = reader.ReadHalf();
return new Vector3Half(x, y, z);
}
/// <exception cref="T:System.ArgumentException">if an invalid utf8 string is sent</exception>
public static string ReadString(this NetworkReader reader)

View File

@ -58,6 +58,12 @@ public static class NetworkWriterExtensions
public static void WriteDecimalNullable(this NetworkWriter writer, decimal? value) => writer.WriteBlittableNullable(value);
public static void WriteHalf(this NetworkWriter writer, Half value) => writer.WriteUShort(value._value);
public static void WriteVector3Half(this NetworkWriter writer, Vector3Half value)
{
writer.WriteHalf(value.x);
writer.WriteHalf(value.y);
writer.WriteHalf(value.z);
}
public static void WriteString(this NetworkWriter writer, string value)
{

View File

@ -0,0 +1,125 @@
#pragma warning disable CS0659 // 'Vector3Half' overrides Object.Equals(object o) but does not override Object.GetHashCode()
#pragma warning disable CS0661 // 'Vector3Half' defines operator == or operator != but does not override Object.GetHashCode()
// Vector3Half by mischa (based on game engine project)
using System;
using System.Runtime.CompilerServices;
namespace Mirror
{
public struct Vector3Half
{
public Half x;
public Half y;
public Half z;
public static readonly Vector3Half zero = new Vector3Half((Half)0, (Half)0, (Half)0);
public static readonly Vector3Half one = new Vector3Half((Half)1, (Half)1, (Half)1);
public static readonly Vector3Half forward = new Vector3Half((Half)0, (Half)0, (Half)1);
public static readonly Vector3Half back = new Vector3Half((Half)0, (Half)0, (Half)(-1));
public static readonly Vector3Half left = new Vector3Half((Half)(-1), (Half)0, (Half)0);
public static readonly Vector3Half right = new Vector3Half((Half)1, (Half)0, (Half)0);
public static readonly Vector3Half up = new Vector3Half((Half)0, (Half)1, (Half)0);
public static readonly Vector3Half down = new Vector3Half((Half)0, (Half)(-1), (Half)0);
// constructor /////////////////////////////////////////////////////////
public Vector3Half(Half x, Half y, Half z)
{
this.x = x;
this.y = y;
this.z = z;
}
// operators ///////////////////////////////////////////////////////////
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector3Half operator +(Vector3Half a, Vector3Half b) =>
new Vector3Half(a.x + b.x, a.y + b.y, a.z + b.z);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector3Half operator -(Vector3Half a, Vector3Half b) =>
new Vector3Half(a.x - b.x, a.y - b.y, a.z - b.z);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector3Half operator -(Vector3Half v) =>
new Vector3Half(-v.x, -v.y, -v.z);
// [MethodImpl(MethodImplOptions.AggressiveInlining)]
// public static Vector3Half operator *(Vector3Half a, long n) =>
// new Vector3Half(a.x * n, a.y * n, a.z * n);
// [MethodImpl(MethodImplOptions.AggressiveInlining)]
// public static Vector3Half operator *(long n, Vector3Half a) =>
// new Vector3Half(a.x * n, a.y * n, a.z * n);
// == returns true if approximately equal (with epsilon).
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator ==(Vector3Half a, Vector3Half b) =>
a.x == b.x &&
a.y == b.y &&
a.z == b.z;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool operator !=(Vector3Half a, Vector3Half b) => !(a == b);
// NO IMPLICIT System.Numerics.Vector3Half conversion because double<->float
// would silently lose precision in large worlds.
// [i] component index. useful for iterating all components etc.
public Half this[int index]
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
switch (index)
{
case 0: return x;
case 1: return y;
case 2: return z;
default: throw new IndexOutOfRangeException($"Vector3Half[{index}] out of range.");
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
set
{
switch (index)
{
case 0:
x = value;
break;
case 1:
y = value;
break;
case 2:
z = value;
break;
default: throw new IndexOutOfRangeException($"Vector3Half[{index}] out of range.");
}
}
}
// instance functions //////////////////////////////////////////////////
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override string ToString() => $"({x} {y} {z})";
// equality ////////////////////////////////////////////////////////////
// implement Equals & HashCode explicitly for performance.
// calling .Equals (instead of "==") checks for exact equality.
// (API compatibility)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Equals(Vector3Half other) =>
x == other.x && y == other.y && z == other.z;
// Equals(object) can reuse Equals(Vector4)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override bool Equals(object other) =>
other is Vector3Half vector4 && Equals(vector4);
#if UNITY_2021_3_OR_NEWER
// Unity 2019/2020 don't have HashCode.Combine yet.
// this is only to avoid reflection. without defining, it works too.
// default generated by rider
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public override int GetHashCode() => HashCode.Combine(x, y, z);
#endif
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: b70bf28681a14c65a37793a87c8df33e
timeCreated: 1730890316

View File

@ -0,0 +1,150 @@
using System;
using NUnit.Framework;
namespace Mirror.Tests.Tools
{
public class Vector3HalfTests
{
[Test]
public void Constructor()
{
Vector3Half v = new Vector3Half();
Assert.That(v.x, Is.EqualTo((Half)0));
Assert.That(v.y, Is.EqualTo((Half)0));
Assert.That(v.z, Is.EqualTo((Half)0));
}
[Test]
public void ConstructorXYZ()
{
Vector3Half v = new Vector3Half((Half)1, (Half)2, (Half)3);
Assert.That(v.x, Is.EqualTo((Half)1));
Assert.That(v.y, Is.EqualTo((Half)2));
Assert.That(v.z, Is.EqualTo((Half)3));
}
[Test]
public void OperatorAdd()
{
Vector3Half a = new Vector3Half((Half)1, (Half)2, (Half)3);
Vector3Half b = new Vector3Half((Half)2, (Half)3, (Half)4);
Assert.That(a + b, Is.EqualTo(new Vector3Half((Half)3, (Half)5, (Half)7)));
}
[Test]
public void OperatorSubtract()
{
Vector3Half a = new Vector3Half((Half)1, (Half)2, (Half)3);
Vector3Half b = new Vector3Half((Half)(-2), (Half)(-3), (Half)(-4));
Assert.That(a - b, Is.EqualTo(new Vector3Half((Half)3, (Half)5, (Half)7)));
}
[Test]
public void OperatorInverse()
{
Vector3Half v = new Vector3Half((Half)1, (Half)2, (Half)3);
Assert.That(-v, Is.EqualTo(new Vector3Half((Half)(-1), (Half)(-2), (Half)(-3))));
}
// [Test]
// public void OperatorMultiply()
// {
// Vector3Half a = new Vector3Half((Half)1, (Half)2, (Half)3);
// // a * n, n * a are two different operators. test both.
// Assert.That(a * (Half)2, Is.EqualTo(new Vector3Half((Half)2, (Half)4, (Half)6)));
// Assert.That((Half)2 * a, Is.EqualTo(new Vector3Half((Half)2, (Half)4, (Half)6)));
// }
#if UNITY_2021_3_OR_NEWER
[Test]
public void OperatorEquals()
{
// two vectors which are approximately the same
Vector3Half a = new Vector3Half((Half)1, (Half)2, (Half)3);
Vector3Half b = new Vector3Half((Half)1, (Half)2, (Half)3);
Assert.That(a == b, Is.True);
// two vectors which are definitely not the same
Assert.That(a == Vector3Half.one, Is.False);
}
[Test]
public void OperatorNotEquals()
{
// two vectors which are approximately the same
Vector3Half a = new Vector3Half((Half)1, (Half)2, (Half)3);
Vector3Half b = new Vector3Half((Half)1, (Half)2, (Half)3);
Assert.That(a != b, Is.False);
// two vectors which are definitely not the same
Assert.That(a != Vector3Half.one, Is.True);
}
#endif
[Test]
public void OperatorIndexer()
{
Vector3Half a = new Vector3Half((Half)1, (Half)2, (Half)3);
// get
Assert.That(a[0], Is.EqualTo((Half)1));
Assert.That(a[1], Is.EqualTo((Half)2));
Assert.That(a[2], Is.EqualTo((Half)3));
Assert.Throws<IndexOutOfRangeException>(() =>
{
Half _ = a[-1];
});
Assert.Throws<IndexOutOfRangeException>(() =>
{
Half _ = a[3];
});
// set
a[0] = -1;
a[1] = -2;
a[2] = -3;
Assert.Throws<IndexOutOfRangeException>(() => { a[-1] = (Half)0; });
Assert.Throws<IndexOutOfRangeException>(() => { a[3] = (Half)0; });
Assert.That(a, Is.EqualTo(new Vector3Half((Half)(-1), (Half)(-2), (Half)(-3))));
}
[Test]
public void ToStringTest()
{
// should be rounded to :F2
Vector3Half v = new Vector3Half((Half)(-10), (Half)0, (Half)42);
Assert.That(v.ToString(), Is.EqualTo("(-10 0 42)"));
}
#if UNITY_2021_3_OR_NEWER
[Test]
public void EqualsVector3Half()
{
Assert.That(Vector3Half.one.Equals(Vector3Half.one), Is.True);
Assert.That(Vector3Half.one.Equals(Vector3Half.zero), Is.False);
}
[Test]
public void EqualsObject()
{
Assert.That(Vector3Half.one.Equals((object)42), Is.False);
Assert.That(Vector3Half.one.Equals((object)Vector3Half.one), Is.True);
Assert.That(Vector3Half.one.Equals((object)Vector3Half.zero), Is.False);
}
[Test]
public void GetHashCodeTest()
{
// shouldn't be 0
Assert.That(Vector3Half.zero.GetHashCode(), !Is.EqualTo(0));
Assert.That(Vector3Half.one.GetHashCode(), !Is.EqualTo(0));
// should be same for same vector
Assert.That(Vector3Half.zero.GetHashCode(), Is.EqualTo(Vector3Half.zero.GetHashCode()));
// should be different for different vectors
Assert.That(Vector3Half.zero.GetHashCode(), !Is.EqualTo(Vector3Half.one.GetHashCode()));
}
#endif
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: bc5f32db47ab4ffb92433050cc1b6e9f
timeCreated: 1730890719