Overwrite

Complete Overwrite of the Folder with the free shard. ServUO 57.3 has been added.
This commit is contained in:
Unstable Kitsune
2023-11-28 23:20:26 -05:00
parent 3cd54811de
commit b918192e4e
11608 changed files with 2644205 additions and 47 deletions

View File

@@ -0,0 +1,341 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using System.Collections.Generic;
#endregion
namespace Server
{
[Parsable, PropertyObject]
public struct Angle
: IEquatable<Angle>, IEquatable<int>, IEquatable<double>, IComparable<Angle>, IComparable<int>, IComparable<double>
{
public const double D2R = Math.PI / 180.0;
public const double R2D = 180.0 / Math.PI;
public static readonly Angle Zero = 0;
public static readonly Angle MinValue = -360;
public static readonly Angle MaxValue = 360;
public static Angle FromDirection(Direction dir)
{
int x = 0, y = 0;
Movement.Movement.Offset(dir & Direction.Mask, ref x, ref y);
return FromPoints(0, 0, x, y);
}
public static Angle FromPoints(IPoint2D p1, IPoint2D p2)
{
return FromPoints(p1.X, p1.Y, p2.X, p2.Y);
}
public static Angle FromPoints(IPoint2D p1, IPoint2D p2, IPoint2D p3)
{
return FromPoints(p1.X, p1.Y, p2.X, p2.Y, p3.X, p3.Y);
}
public static Angle FromPoints(int x1, int y1, int x2, int y2)
{
return Math.Atan2(y2, x2) - Math.Atan2(y1, x1);
}
public static Angle FromPoints(int x1, int y1, int x2, int y2, int x3, int y3)
{
return FromPoints(x2, y2, x1, y1) - FromPoints(x2, y2, x3, y3);
}
public static Angle FromDegrees(int degrees)
{
return degrees;
}
public static Angle FromRadians(double radians)
{
return radians;
}
public static Angle GetPitch(IPoint3D p1, IPoint3D p2)
{
int x = p2.X - p1.X, y = p2.Y - p1.Y, z = p2.Z - p1.Z;
return -Math.Atan2(z, Math.Sqrt((x * x) + (y * y)));
}
public static Angle GetYaw(IPoint2D p, IPoint2D left, IPoint2D right)
{
return Math.Abs(FromPoints(p, left) - FromPoints(p, right));
}
public static bool InLOS(IPoint2D p1, IPoint2D target, Direction d, Angle yaw, double distance)
{
return GetLOS(p1, d, yaw, distance).Contains(target);
}
public static Triangle2D GetLOS(IPoint2D p, Direction d, Angle yaw, double distance)
{
var a = FromDirection(d);
var p2 = GetPoint2D(p.X, p.Y, a - yaw, distance);
var p3 = GetPoint2D(p.X, p.Y, a + yaw, distance);
return new Triangle2D(p, p2, p3);
}
public static IEnumerable<Point2D> PlotLOS(IPoint2D p, Direction d, Angle yaw, double distance)
{
var a = FromDirection(d);
var p2 = GetPoint2D(p.X, p.Y, a - yaw, distance);
var p3 = GetPoint2D(p.X, p.Y, a + yaw, distance);
return Triangle2D.Plot(p, p2, p3);
}
public static void Transform(ref Point3D p, Angle angle, double offset)
{
int x = p.X, y = p.Y, z = p.Z;
Transform(ref x, ref y, angle, offset);
p = new Point3D(x, y, z);
}
public static void Transform(ref Point2D p, Angle angle, double offset)
{
int x = p.X, y = p.Y;
Transform(ref x, ref y, angle, offset);
p = new Point2D(x, y);
}
public static void Transform(ref int x, ref int y, Angle angle, double offset)
{
x += (int)(offset * Math.Cos(angle._Radians));
y += (int)(offset * Math.Sin(angle._Radians));
}
public static Point2D GetPoint2D(int x, int y, Angle angle, double distance)
{
return new Point2D(x + (int)(distance * Math.Cos(angle._Radians)), y + (int)(distance * Math.Sin(angle._Radians)));
}
public static Point3D GetPoint3D(int x, int y, int z, Angle angle, double distance)
{
return new Point3D(
x + (int)(distance * Math.Cos(angle._Radians)),
y + (int)(distance * Math.Sin(angle._Radians)),
z);
}
public static bool TryParse(string value, out Angle angle)
{
try
{
angle = Parse(value);
return true;
}
catch
{
angle = Zero;
return false;
}
}
public static Angle Parse(string value)
{
value = value ?? String.Empty;
value = value.Trim();
int d;
double r;
if (!value.Contains(","))
{
if (Int32.TryParse(value, out d))
{
return d;
}
if (Double.TryParse(value, out r))
{
return r;
}
}
else
{
value = value.Trim('(', ')', ' ');
var i = value.IndexOf(',');
if (Int32.TryParse(value.Substring(0, i).Trim(), out d))
{
return d;
}
if (Double.TryParse(value.Substring(i + 1).Trim(), out r))
{
return r;
}
}
throw new FormatException(
"The specified angle must be represented by Int32 (Degrees) or Double (Radians) using the format " + //
"'###', '#.##', or '(###, #.##)'");
}
private readonly int _Degrees;
private readonly double _Radians;
[CommandProperty(AccessLevel.Counselor)]
public int Degrees => _Degrees;
[CommandProperty(AccessLevel.Counselor)]
public double Radians => _Radians;
public Angle(Angle angle)
{
_Degrees = angle._Degrees;
_Radians = angle._Radians;
}
public Angle(int degrees)
{
_Degrees = degrees;
_Radians = _Degrees * D2R;
}
public Angle(double radians)
: this((int)(radians * R2D))
{ }
public Angle(int x1, int y1, int x2, int y2)
: this(Math.Atan2(y2, x2) - Math.Atan2(y1, x1))
{ }
public Angle(IPoint2D p1, IPoint2D p2)
: this(p1.X, p1.Y, p2.X, p2.Y)
{ }
public void Transform(ref Point3D p, double offset)
{
Transform(ref p, this, offset);
}
public void Transform(ref Point2D p, double offset)
{
Transform(ref p, this, offset);
}
public void Transform(ref int x, ref int y, double offset)
{
Transform(ref x, ref y, this, offset);
}
public Point2D GetPoint2D(int x, int y, double distance)
{
return GetPoint2D(x, y, this, distance);
}
public Point3D GetPoint3D(int x, int y, int z, double distance)
{
return GetPoint3D(x, y, z, this, distance);
}
public override int GetHashCode()
{
return _Degrees;
}
public override bool Equals(object obj)
{
return (obj is Angle && Equals((Angle)obj)) || (obj is int && Equals((int)obj)) ||
(obj is double && Equals((double)obj));
}
public bool Equals(Angle angle)
{
return _Degrees == angle._Degrees;
}
public bool Equals(int degrees)
{
return _Degrees == degrees;
}
public bool Equals(double radians)
{
return _Radians == radians;
}
public int CompareTo(Angle angle)
{
return _Degrees.CompareTo(angle._Degrees);
}
public int CompareTo(int degrees)
{
return _Degrees.CompareTo(degrees);
}
public int CompareTo(double radians)
{
return _Radians.CompareTo(radians);
}
public override string ToString()
{
return String.Format("({0}, {1})", _Degrees, _Radians);
}
public Angle Normalize()
{
return _Degrees % 360;
}
#region Operators
public static Angle operator --(Angle a)
{
return a._Degrees - 1;
}
public static Angle operator ++(Angle a)
{
return a._Degrees + 1;
}
public static implicit operator int(Angle a)
{
return a._Degrees;
}
public static implicit operator double(Angle a)
{
return a._Radians;
}
public static implicit operator Angle(int d)
{
return new Angle(d);
}
public static implicit operator Angle(double r)
{
return new Angle(r);
}
#endregion Operators
}
}

View File

@@ -0,0 +1,338 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using System.Collections;
using System.Collections.Generic;
using Server.Targeting;
#endregion
namespace Server
{
public interface IBlock3D : IPoint3D, IEquatable<IBlock3D>, IEnumerable<IPoint3D>
{
int H { get; set; }
bool Intersects(Item e);
bool Intersects(Mobile e);
bool Intersects(IEntity e);
bool Intersects(IPoint3D p);
bool Intersects(IBlock3D b);
bool Intersects(int z);
bool Intersects(int x, int y, int z);
bool Intersects(int x, int y, int z, int h);
IEnumerable<IPoint3D> Scan();
}
public struct Block3D : IBlock3D
{
public static readonly Block3D Empty = new Block3D(0, 0, 0, 0);
public static bool Intersects(IPoint3D a, IPoint3D b)
{
return Create(a).Intersects(Create(b));
}
public static Block3D Create(IPoint3D o)
{
if (o is Mobile)
{
return new Block3D(o, 18);
}
if (o is Item)
{
return new Block3D(o, Math.Max(1, ((Item)o).ItemData.CalcHeight));
}
if (o is LandTarget)
{
return new Block3D(o, 1);
}
if (o is StaticTarget)
{
return new Block3D(o, TileData.ItemTable[((StaticTarget)o).ItemID].CalcHeight);
}
return new Block3D(o, 5);
}
public int X { get; set; }
public int Y { get; set; }
public int Z { get; set; }
public int H { get; set; }
public Block3D(IBlock3D b)
: this(b.X, b.Y, b.Z, b.H)
{ }
public Block3D(IPoint3D p, int h)
: this(p.X, p.Y, p.Z, h)
{ }
public Block3D(int x, int y, int z, int h)
: this()
{
X = x;
Y = y;
Z = z;
H = h;
}
public bool Intersects(IEntity e)
{
if (e is Item)
{
return Intersects((Item)e);
}
if (e is Mobile)
{
return Intersects((Mobile)e);
}
return Intersects(e.X, e.Y, e.Z);
}
public bool Intersects(IPoint3D p)
{
if (p is Item)
{
return Intersects((Item)p);
}
if (p is Mobile)
{
return Intersects((Mobile)p);
}
if (p is LandTarget)
{
return Intersects((LandTarget)p);
}
if (p is StaticTarget)
{
return Intersects((StaticTarget)p);
}
return Intersects(p.X, p.Y, p.Z);
}
public bool Intersects(Point3D p, int h)
{
return Intersects(p.X, p.Y, p.Z, h);
}
public bool Intersects(LandTarget o)
{
return Intersects(o.X, o.Y, o.Z, 1);
}
public bool Intersects(StaticTarget o)
{
return Intersects(o.X, o.Y, o.Z, Math.Max(1, TileData.ItemTable[o.ItemID].CalcHeight));
}
public bool Intersects(Mobile m)
{
return Intersects(m.X, m.Y, m.Z, 18);
}
public bool Intersects(Item i)
{
return Intersects(i.X, i.Y, i.Z, Math.Max(1, i.ItemData.CalcHeight));
}
public bool Intersects(Block3D b)
{
return Intersects(b.X, b.Y, b.Z, b.H);
}
public bool Intersects(IBlock3D b)
{
return Intersects(b.X, b.Y, b.Z, b.H);
}
public bool Intersects(int z)
{
return Intersects(X, Y, z);
}
public bool Intersects(int z, int h)
{
return Intersects(X, Y, z, h);
}
public bool Intersects(int x, int y, int z)
{
return Intersects(x, y, z, 0);
}
public bool Intersects(Rectangle2D b, int z, int h)
{
return X >= b.Start.X && X < b.End.X && Y >= b.Start.Y && Y < b.End.Y && Intersects(X, Y, z, h);
}
public bool Intersects(Rectangle3D b)
{
var z = Math.Min(b.Start.Z, b.End.Z);
var h = Math.Abs(b.Depth);
return X >= b.Start.X && X < b.End.X && Y >= b.Start.Y && Y < b.End.Y && Intersects(X, Y, z, h);
}
public bool Intersects(int x, int y, int z, int h)
{
if (x != X || y != Y)
{
return false;
}
if (z == Z || z + h == Z + H)
{
return true;
}
if (z >= Z && z <= Z + H)
{
return true;
}
if (Z >= z && Z <= z + h)
{
return true;
}
if (z <= Z && z + h >= Z)
{
return true;
}
if (Z <= z && Z + H >= z)
{
return true;
}
return false;
}
public Block3D Offset(int x = 0, int y = 0, int z = 0, int h = 0)
{
X += x;
Y += y;
Z += z;
H += h;
return this;
}
public Block3D Delta(int x = 0, int y = 0, int z = 0, int h = 0)
{
X -= x;
Y -= y;
Z -= z;
H -= h;
return this;
}
public Block3D Normalize(int x = 0, int y = 0, int z = 0, int h = 0)
{
X = x - X;
Y = y - Y;
Z = z - Z;
H = h - H;
return this;
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public IEnumerator<IPoint3D> GetEnumerator()
{
return Scan().GetEnumerator();
}
public IEnumerable<IPoint3D> Scan()
{
for (var z = Z; z <= Z + H; z++)
{
yield return this.ToPoint3D(z);
}
}
public override string ToString()
{
return String.Format("{0}, {1}, {2}, {3}", X, Y, Z, H);
}
public override int GetHashCode()
{
unchecked
{
var hash = 0;
hash = (hash * 397) ^ X;
hash = (hash * 397) ^ Y;
hash = (hash * 397) ^ Z;
hash = (hash * 397) ^ H;
return hash;
}
}
public override bool Equals(object obj)
{
return obj is IBlock3D && Equals((IBlock3D)obj);
}
public bool Equals(IBlock3D b)
{
return !ReferenceEquals(b, null) && X == b.X && Y == b.Y && Z == b.Z && H == b.H;
}
public static bool operator ==(Block3D a, IBlock3D b)
{
return a.Equals(b);
}
public static bool operator !=(Block3D a, IBlock3D b)
{
return !a.Equals(b);
}
public static bool operator ==(IBlock3D a, Block3D b)
{
return b.Equals(a);
}
public static bool operator !=(IBlock3D a, Block3D b)
{
return !b.Equals(a);
}
public static implicit operator Block3D(Point3D p)
{
return new Block3D(p, 0);
}
public static implicit operator Point3D(Block3D p)
{
return new Point3D(p.X, p.Y, p.Z);
}
}
}

View File

@@ -0,0 +1,21 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
namespace Server
{
public enum Direction4
{
North = Direction.North,
East = Direction.East,
South = Direction.South,
West = Direction.West
}
}

View File

@@ -0,0 +1,21 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
namespace Server
{
public enum Direction45
{
Up = Direction.Up,
Right = Direction.Right,
Down = Direction.Down,
Left = Direction.Left
}
}

View File

@@ -0,0 +1,339 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using System.Collections.Generic;
using System.Linq;
#endregion
namespace Server
{
[NoSort, Parsable, PropertyObject]
public struct Line2D : IPoint2D
{
public static readonly Line2D Empty = new Line2D(0, 0, 0, 0);
private static void Swap<T>(ref T a, ref T b)
{
var t = a;
a = b;
b = t;
}
private static IEnumerable<Point2D> Plot(int x1, int y1, int x2, int y2)
{
var delta = Math.Abs(y2 - y1) > Math.Abs(x2 - x1);
if (delta)
{
Swap(ref x1, ref y1);
Swap(ref x2, ref y2);
}
if (x1 > x2)
{
Swap(ref x1, ref x2);
Swap(ref y1, ref y2);
}
var dX = x2 - x1;
var dY = Math.Abs(y2 - y1);
var eX = dX / 2;
var sY = y1 < y2 ? 1 : -1;
var y = y1;
for (var x = x1; x <= x2; x++)
{
if (delta)
{
yield return new Point2D(y, x);
}
else
{
yield return new Point2D(x, y);
}
eX -= dY;
if (eX < 0)
{
y += sY;
eX += dX;
}
}
}
public static IEnumerable<Point2D> Plot(IPoint2D start, IPoint2D end)
{
return Plot(start.X, start.Y, end.X, end.Y).OrderBy(p => GetLength(start, p));
}
public static double GetLength(IPoint2D start, IPoint2D end)
{
return Math.Abs(Math.Sqrt(Math.Pow(end.X - start.X, 2) + Math.Pow(end.Y - start.Y, 2)));
}
public static double GetLength(Line2D line)
{
return GetLength(line.Start, line.End);
}
public static IEnumerable<Point2D> Intersect(Line2D[] lines1, Line2D[] lines2)
{
return lines1.Ensure().SelectMany(l => Intersect(l, lines2));
}
public static IEnumerable<Point2D> Intersect(Line2D line, Line2D[] lines)
{
return lines.Ensure().Select(l => Intersect(line, l)).Where(p => p != null).Select(p => p.Value);
}
public static Point2D? Intersect(IPoint2D a1, IPoint2D b1, IPoint2D a2, IPoint2D b2)
{
if ((a1.X == a2.X && a1.Y == a2.Y) || (a1.X == b2.X && a1.Y == b2.Y))
{
return new Point2D(a1.X, a1.Y);
}
if ((b1.X == b2.X && b1.Y == b2.Y) || (b1.X == a2.X && b1.Y == a2.Y))
{
return new Point2D(b1.X, b1.Y);
}
var da1 = b1.Y - a1.Y;
var da2 = a1.X - b1.X;
var da3 = da1 * a1.X + da2 * a1.Y;
var db1 = b2.Y - a2.Y;
var db2 = a2.X - b2.X;
var db3 = db1 * a2.X + db2 * a2.Y;
var delta = da1 * db2 - db1 * da2;
if (delta != 0)
{
return new Point2D((db2 * da3 - da2 * db3) / delta, (da1 * db3 - db1 * da3) / delta);
}
return null;
}
public static Point2D? Intersect(Line2D line, IPoint2D a, IPoint2D b)
{
return Intersect(line._Start, line._End, a, b);
}
public static Point2D? Intersect(Line2D l1, Line2D l2)
{
return Intersect(l1._Start, l1._End, l2._Start, l2._End);
}
public static bool Intersects(Line2D[] lines1, Line2D[] lines2)
{
return Intersect(lines1, lines2).Any();
}
public static bool Intersects(Line2D line, Line2D[] lines)
{
return Intersect(line, lines).Any();
}
public static bool Intersects(Line2D line, IPoint2D a, IPoint2D b)
{
return Intersect(line, a, b) != null;
}
public static bool Intersects(IPoint2D a1, IPoint2D b1, IPoint2D a2, IPoint2D b2)
{
return Intersect(a1, b1, a2, b2) != null;
}
public static bool Intersects(Line2D l1, Line2D l2)
{
return Intersect(l1, l2) != null;
}
public static bool TryParse(string value, out Line2D l)
{
try
{
l = Parse(value);
return true;
}
catch
{
l = Empty;
return false;
}
}
public static Line2D Parse(string value)
{
var param = value.Split('+');
if (param.Length >= 2 && param.All(p => p.Contains(',')))
{
return new Line2D(Point2D.Parse(param[0]), Point2D.Parse(param[1]));
}
throw new FormatException(
"The specified line must be represented by two Point2D coords using the format " + //
"'(x1,y1)+(x2,y2)'");
}
private Point2D _Start, _End;
private Angle _Rotation;
private double _Length;
[CommandProperty(AccessLevel.Counselor)]
public int X
{
get => _Start.X;
set
{
_Start.X = value;
_Rotation = Angle.FromPoints(_Start, _End);
_Length = _Start.GetDistance(_End);
}
}
[CommandProperty(AccessLevel.Counselor)]
public int Y
{
get => _Start.Y;
set
{
_Start.Y = value;
_Rotation = Angle.FromPoints(_Start, _End);
_Length = _Start.GetDistance(_End);
}
}
[CommandProperty(AccessLevel.Counselor)]
public Point2D Start
{
get => _Start;
set
{
_Start = value;
_Rotation = Angle.FromPoints(_Start, _End);
_Length = _Start.GetDistance(_End);
}
}
[CommandProperty(AccessLevel.Counselor)]
public Point2D End
{
get => _End;
set
{
_End = value;
_Rotation = Angle.FromPoints(_Start, _End);
_Length = _Start.GetDistance(_End);
}
}
[CommandProperty(AccessLevel.Counselor)]
public Angle Rotation
{
get => _Rotation;
set
{
_Rotation = value;
_End = _Rotation.GetPoint2D(_Start.X, _Start.Y, _Length);
}
}
[CommandProperty(AccessLevel.Counselor)]
public double Length
{
get => _Length;
set
{
_Length = value;
_End = _Rotation.GetPoint2D(_Start.X, _Start.Y, _Length);
}
}
public Line2D(IPoint2D start, IPoint2D end)
{
_Start = new Point2D(start);
_End = new Point2D(end);
_Rotation = Angle.FromPoints(_Start, _End);
_Length = _Start.GetDistance(_End);
}
public Line2D(int xStart, int yStart, int xEnd, int yEnd)
{
_Start = new Point2D(xStart, yStart);
_End = new Point2D(xEnd, yEnd);
_Rotation = Angle.FromPoints(_Start, _End);
_Length = _Start.GetDistance(_End);
}
public Line2D(IPoint2D start, Angle angle, double length)
{
_Rotation = angle;
_Length = length;
_Start = new Point2D(start.X, start.Y);
_End = _Rotation.GetPoint2D(start.X, start.Y, _Length);
}
public Line2D(int xStart, int yStart, Angle angle, double length)
{
_Rotation = angle;
_Length = length;
_Start = new Point2D(xStart, yStart);
_End = _Rotation.GetPoint2D(xStart, yStart, _Length);
}
public IEnumerable<Point2D> Intersect(Line2D[] lines)
{
return Intersect(this, lines);
}
public Point2D? Intersect(Line2D line)
{
return Intersect(this, line);
}
public bool Intersects(Line2D line)
{
return Intersects(this, line);
}
public bool Intersects(Line2D[] lines)
{
return Intersects(this, lines);
}
public bool Intersects(IPoint2D a2, IPoint2D b2)
{
return Intersects(this, a2, b2);
}
public override string ToString()
{
return String.Format("{0}+{1}", _Start, _End);
}
}
}

View File

@@ -0,0 +1,113 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using Server;
#endregion
namespace VitaNex.Geometry
{
public class Cube3D : Shape3D
{
private int _Radius;
private bool _Hollow;
[CommandProperty(AccessLevel.Counselor, AccessLevel.GameMaster)]
public int Radius
{
get => _Radius;
set
{
if (_Radius == value)
{
return;
}
_Radius = value;
Render();
}
}
[CommandProperty(AccessLevel.Counselor, AccessLevel.GameMaster)]
public bool Hollow
{
get => _Hollow;
set
{
if (_Hollow == value)
{
return;
}
_Hollow = value;
Render();
}
}
public Cube3D(int radius)
: this(Point3D.Zero, radius)
{ }
public Cube3D(IPoint3D center, int radius)
: this(center, radius, false)
{ }
public Cube3D(IPoint3D center, int radius, bool hollow)
: base(center)
{
_Radius = radius;
_Hollow = hollow;
}
/// <summary>
/// This cube always has an odd width, height and depth, never even.
/// This preserves the center point.
/// </summary>
protected override void OnRender()
{
const int h = 5;
for (var z = -Radius; z <= Radius; z++)
{
for (var x = -Radius; x <= Radius; x++)
{
for (var y = -Radius; y <= Radius; y++)
{
if (!Hollow || (z == -Radius || z == Radius || x == -Radius || x == Radius || y == -Radius || y == Radius))
{
Add(new Block3D(Center.Clone3D(x, y, z * h), h));
}
}
}
}
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.SetVersion(0);
writer.Write(_Radius);
writer.Write(_Hollow);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
reader.GetVersion();
_Radius = reader.ReadInt();
_Hollow = reader.ReadBool();
}
}
}

View File

@@ -0,0 +1,148 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using Server;
#endregion
namespace VitaNex.Geometry
{
public class Cylinder3D : Shape3D
{
private int _Radius;
private bool _Hollow;
private bool _EndCaps;
[CommandProperty(AccessLevel.Counselor, AccessLevel.GameMaster)]
public int Radius
{
get => _Radius;
set
{
if (_Radius == value)
{
return;
}
_Radius = value;
Render();
}
}
[CommandProperty(AccessLevel.Counselor, AccessLevel.GameMaster)]
public bool Hollow
{
get => _Hollow;
set
{
if (_Hollow == value)
{
return;
}
_Hollow = value;
Render();
}
}
[CommandProperty(AccessLevel.Counselor, AccessLevel.GameMaster)]
public bool EndCaps
{
get => _EndCaps;
set
{
if (_EndCaps == value)
{
return;
}
_EndCaps = value;
Render();
}
}
public Cylinder3D(int radius)
: this(Point3D.Zero, radius)
{ }
public Cylinder3D(IPoint3D center, int radius)
: this(center, radius, false)
{ }
public Cylinder3D(IPoint3D center, int radius, bool hollow)
: this(center, radius, hollow, true)
{
Hollow = hollow;
}
public Cylinder3D(IPoint3D center, int radius, bool hollow, bool endCaps)
: base(center)
{
_Radius = radius;
_Hollow = hollow;
_EndCaps = endCaps;
}
public Cylinder3D(GenericReader reader)
: base(reader)
{ }
protected override void OnRender()
{
const int h = 5;
for (var z = -Radius; z <= Radius; z++)
{
if (Hollow && !EndCaps && (z == -Radius || z == Radius))
{
continue;
}
for (var x = -Radius; x <= Radius; x++)
{
for (var y = -Radius; y <= Radius; y++)
{
var dist = (int)Math.Sqrt(x * x + y * y);
if ((!Hollow || z == -Radius || z == Radius || dist >= Radius) && dist <= Radius)
{
Add(new Block3D(Center.Clone3D(x, y, z * h), h));
}
}
}
}
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.SetVersion(0);
writer.Write(_Radius);
writer.Write(_Hollow);
writer.Write(_EndCaps);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
reader.GetVersion();
_Radius = reader.ReadInt();
_Hollow = reader.ReadBool();
_EndCaps = reader.ReadBool();
}
}
}

View File

@@ -0,0 +1,114 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using Server;
#endregion
namespace VitaNex.Geometry
{
public class Disc3D : Shape3D
{
private int _Radius;
private bool _Hollow;
[CommandProperty(AccessLevel.Counselor, AccessLevel.GameMaster)]
public int Radius
{
get => _Radius;
set
{
if (_Radius == value)
{
return;
}
_Radius = value;
Render();
}
}
[CommandProperty(AccessLevel.Counselor, AccessLevel.GameMaster)]
public bool Hollow
{
get => _Hollow;
set
{
if (_Hollow == value)
{
return;
}
_Hollow = value;
Render();
}
}
public Disc3D(int radius)
: this(Point3D.Zero, radius)
{ }
public Disc3D(IPoint3D center, int radius)
: this(center, radius, false)
{ }
public Disc3D(IPoint3D center, int radius, bool hollow)
: base(center)
{
_Radius = radius;
_Hollow = hollow;
}
public Disc3D(GenericReader reader)
: base(reader)
{ }
protected override void OnRender()
{
const int h = 5;
for (var x = -Radius; x <= Radius; x++)
{
for (var y = -Radius; y <= Radius; y++)
{
var dist = (int)Math.Sqrt(x * x + y * y);
if ((!Hollow || dist >= Radius) && dist <= Radius)
{
Add(new Block3D(Center.Clone3D(x, y), h));
}
}
}
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.SetVersion(0);
writer.Write(_Radius);
writer.Write(_Hollow);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
reader.GetVersion();
_Radius = reader.ReadInt();
_Hollow = reader.ReadBool();
}
}
}

View File

@@ -0,0 +1,110 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using Server;
#endregion
namespace VitaNex.Geometry
{
public class Plane3D : Shape3D
{
private int _Radius;
private bool _Hollow;
[CommandProperty(AccessLevel.Counselor, AccessLevel.GameMaster)]
public int Radius
{
get => _Radius;
set
{
if (_Radius == value)
{
return;
}
_Radius = value;
Render();
}
}
[CommandProperty(AccessLevel.Counselor, AccessLevel.GameMaster)]
public bool Hollow
{
get => _Hollow;
set
{
if (_Hollow == value)
{
return;
}
_Hollow = value;
Render();
}
}
public Plane3D(int radius)
: this(Point3D.Zero, radius)
{ }
public Plane3D(IPoint3D center, int radius)
: this(center, radius, false)
{ }
public Plane3D(IPoint3D center, int radius, bool hollow)
: base(center)
{
_Radius = radius;
_Hollow = hollow;
}
/// <summary>
/// This plane always has an odd width, height and depth, never even.
/// This preserves the center point.
/// </summary>
protected override void OnRender()
{
const int h = 5;
for (var x = -Radius; x <= Radius; x++)
{
for (var y = -Radius; y <= Radius; y++)
{
if (!Hollow || (x == -Radius || x == Radius || y == -Radius || y == Radius))
{
Add(new Block3D(Center.Clone3D(x, y), h));
}
}
}
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.SetVersion(0);
writer.Write(_Radius);
writer.Write(_Hollow);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
reader.GetVersion();
_Radius = reader.ReadInt();
_Hollow = reader.ReadBool();
}
}
}

View File

@@ -0,0 +1,121 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using Server;
#endregion
namespace VitaNex.Geometry
{
public class Ring3D : Shape3D
{
private int _RadiusMin;
private int _RadiusMax;
[CommandProperty(AccessLevel.Counselor, AccessLevel.GameMaster)]
public int RadiusMin
{
get => _RadiusMin;
set
{
if (_RadiusMin == value)
{
return;
}
_RadiusMin = value;
Render();
}
}
[CommandProperty(AccessLevel.Counselor, AccessLevel.GameMaster)]
public int RadiusMax
{
get => _RadiusMax;
set
{
if (_RadiusMax == value)
{
return;
}
_RadiusMax = value;
Render();
}
}
public Ring3D(int radius)
: this(radius, radius)
{ }
public Ring3D(int radiusMin, int radiusMax)
: this(Point3D.Zero, radiusMin, radiusMax)
{ }
public Ring3D(IPoint3D center, int radius)
: this(center, radius, radius)
{ }
public Ring3D(IPoint3D center, int radiusMin, int radiusMax)
: base(center)
{
_RadiusMin = Math.Min(radiusMin, radiusMax);
_RadiusMax = Math.Max(radiusMin, radiusMax);
}
public Ring3D(GenericReader reader)
: base(reader)
{ }
protected override void OnRender()
{
var min = Math.Min(RadiusMin, RadiusMax);
var max = Math.Max(RadiusMin, RadiusMax);
const int h = 5;
for (var x = -max; x <= max; x++)
{
for (var y = -max; y <= max; y++)
{
var dist = (int)Math.Sqrt(x * x + y * y);
if (dist >= min && dist <= max)
{
Add(new Block3D(Center.Clone3D(x, y), h));
}
}
}
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.SetVersion(0);
writer.Write(_RadiusMin);
writer.Write(_RadiusMax);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
reader.GetVersion();
_RadiusMin = reader.ReadInt();
_RadiusMax = reader.ReadInt();
}
}
}

View File

@@ -0,0 +1,276 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using System.Collections.Generic;
using Server;
#endregion
namespace VitaNex.Geometry
{
[PropertyObject]
public abstract class Shape3D : DynamicWireframe, IPoint3D
{
private bool _InitialRender;
public override List<Block3D> Blocks
{
get
{
if (!_InitialRender)
{
Render();
}
return base.Blocks;
}
set => base.Blocks = value;
}
public override int Volume
{
get
{
if (!_InitialRender)
{
Render();
}
return base.Volume;
}
}
protected Point3D _Center;
[CommandProperty(AccessLevel.Counselor, AccessLevel.GameMaster)]
public Point3D Center
{
get => _Center;
set
{
if (_Center == value)
{
return;
}
_Center = value;
Render();
}
}
[CommandProperty(AccessLevel.Counselor, AccessLevel.GameMaster)]
public int X
{
get => _Center.X;
set
{
if (_Center.X == value)
{
return;
}
_Center.X = value;
Render();
}
}
[CommandProperty(AccessLevel.Counselor, AccessLevel.GameMaster)]
public int Y
{
get => _Center.Y;
set
{
if (_Center.Z == value)
{
return;
}
_Center.Y = value;
Render();
}
}
[CommandProperty(AccessLevel.Counselor, AccessLevel.GameMaster)]
public int Z
{
get => _Center.Z;
set
{
if (_Center.Z == value)
{
return;
}
_Center.Z = value;
Render();
}
}
public Shape3D()
: this(Point3D.Zero)
{ }
public Shape3D(IPoint3D center)
{
_Center = center.Clone3D();
}
public Shape3D(GenericReader reader)
: base(reader)
{ }
public void Render()
{
if (Rendering)
{
return;
}
_InitialRender = Rendering = true;
Clear();
OnRender();
Rendering = false;
}
protected abstract void OnRender();
public override void Add(Block3D item)
{
if (!_InitialRender)
{
Render();
}
base.Add(item);
}
public override void AddRange(IEnumerable<Block3D> collection)
{
if (!_InitialRender)
{
Render();
}
base.AddRange(collection);
}
public override bool Remove(Block3D item)
{
if (!_InitialRender)
{
Render();
}
return base.Remove(item);
}
public override int RemoveAll(Predicate<Block3D> match)
{
if (!_InitialRender)
{
Render();
}
return base.RemoveAll(match);
}
public override void RemoveAt(int index)
{
if (!_InitialRender)
{
Render();
}
base.RemoveAt(index);
}
public override void RemoveRange(int index, int count)
{
if (!_InitialRender)
{
Render();
}
base.RemoveRange(index, count);
}
public override void ForEach(Action<Block3D> action)
{
if (!_InitialRender)
{
Render();
}
base.ForEach(action);
}
public override IEnumerator<Block3D> GetEnumerator()
{
if (!_InitialRender)
{
Render();
}
return base.GetEnumerator();
}
public override Block3D this[int index]
{
get
{
if (!_InitialRender)
{
Render();
}
return base[index];
}
set
{
if (!_InitialRender)
{
Render();
}
base[index] = value;
}
}
public override void Serialize(GenericWriter writer)
{
if (!_InitialRender)
{
Render();
}
base.Serialize(writer);
writer.SetVersion(0);
writer.Write(_Center);
}
public override void Deserialize(GenericReader reader)
{
_InitialRender = true;
base.Deserialize(reader);
reader.GetVersion();
_Center = reader.ReadPoint3D();
}
}
}

View File

@@ -0,0 +1,136 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using Server;
#endregion
namespace VitaNex.Geometry
{
public class Sphere3D : Shape3D
{
private int _Radius;
private bool _Hollow;
[CommandProperty(AccessLevel.Counselor, AccessLevel.GameMaster)]
public int Radius
{
get => _Radius;
set
{
if (_Radius == value)
{
return;
}
_Radius = value;
Render();
}
}
[CommandProperty(AccessLevel.Counselor, AccessLevel.GameMaster)]
public bool Hollow
{
get => _Hollow;
set
{
if (_Hollow == value)
{
return;
}
_Hollow = value;
Render();
}
}
public Sphere3D(int radius)
: this(Point3D.Zero, radius)
{ }
public Sphere3D(IPoint3D center, int radius)
: this(center, radius, false)
{ }
public Sphere3D(IPoint3D center, int radius, bool hollow)
: base(center)
{
_Radius = radius;
_Hollow = hollow;
}
public Sphere3D(GenericReader reader)
: base(reader)
{ }
protected override void OnRender()
{
const int h = 5;
var layers = Radius * 2;
for (var z = -layers; z <= layers; z++)
{
var p = z / Math.Max(1.0, layers);
var r = 2 * Radius;
if (p < 0.5)
{
r = (int)Math.Ceiling(r * p);
}
else if (p > 0.5)
{
r = (int)Math.Ceiling(r - (r * p));
}
else
{
r = Radius;
}
for (var x = -r; x <= r; x++)
{
for (var y = -r; y <= r; y++)
{
var dist = (int)Math.Sqrt(x * x + y * y);
if ((!Hollow || z == -layers || z == layers || dist >= r) && dist <= r)
{
Add(new Block3D(Center.Clone3D(x, y, z * h), h));
}
}
}
}
}
public override void Serialize(GenericWriter writer)
{
base.Serialize(writer);
writer.SetVersion(0);
writer.Write(_Radius);
writer.Write(_Hollow);
}
public override void Deserialize(GenericReader reader)
{
base.Deserialize(reader);
reader.GetVersion();
_Radius = reader.ReadInt();
_Hollow = reader.ReadBool();
}
}
}

View File

@@ -0,0 +1,315 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using System.Collections.Generic;
using System.Linq;
#endregion
namespace Server
{
[NoSort, Parsable, PropertyObject]
public struct Triangle2D : IPoint2D
{
public static readonly Triangle2D Empty = new Triangle2D(0, 0, 0, 0, 0, 0);
public static IEnumerable<Point2D> Plot(IPoint2D a, IPoint2D b, IPoint2D c)
{
foreach (var p in Line2D.Plot(a, b).Skip(1))
{
yield return p;
}
foreach (var p in Line2D.Plot(b, c).Skip(1))
{
yield return p;
}
foreach (var p in Line2D.Plot(c, a).Skip(1))
{
yield return p;
}
}
public static bool Contains(IPoint2D p, IPoint2D a, IPoint2D b, IPoint2D c)
{
var x = p.X - a.X;
var y = p.Y - a.Y;
var delta = (b.X - a.X) * y - (b.Y - a.Y) * x > 0;
if ((c.X - a.X) * y - (c.Y - a.Y) * x > 0 == delta)
{
return false;
}
if ((c.X - b.X) * (p.Y - b.Y) - (c.Y - b.Y) * (p.X - b.X) > 0 != delta)
{
return false;
}
return true;
}
public static bool Contains(int x, int y, IPoint2D a, IPoint2D b, IPoint2D c)
{
return Contains(new Point2D(x, y), a, b, c);
}
public static IEnumerable<Point2D> Intersect(Triangle2D t1, Triangle2D t2)
{
return Line2D.Intersect(new[] { t1._AB, t1._BC, t1._CA }, new[] { t2._AB, t2._BC, t2._CA });
}
public static IEnumerable<Point2D> Intersect(Triangle2D t, Rectangle2D r)
{
return Line2D.Intersect(
new[] { t._AB, t._BC, t._CA },
new[]
{
new Line2D(r.X, r.Y, r.X + r.Width, r.Y), new Line2D(r.X + r.Width, r.Y, r.X + r.Width, r.Y + r.Height),
new Line2D(r.X, r.Y, r.X, r.Y + r.Height), new Line2D(r.X, r.Y + r.Height, r.X + r.Width, r.Y + r.Height)
});
}
public static bool Intersects(Triangle2D t1, Triangle2D t2)
{
return Intersect(t1, t2).Any();
}
public static bool Intersects(Triangle2D t, Rectangle2D r)
{
return Intersect(t, r).Any();
}
public static bool TryParse(string value, out Triangle2D t)
{
try
{
t = Parse(value);
return true;
}
catch
{
t = Empty;
return false;
}
}
public static Triangle2D Parse(string value)
{
var param = value.Split('+');
if (param.Length >= 3 && param.All(p => p.Contains(',')))
{
return new Triangle2D(Point2D.Parse(param[0]), Point2D.Parse(param[1]), Point2D.Parse(param[2]));
}
throw new FormatException(
"The specified triangle must be represented by three Point2D coords using the format " + //
"'(x1,y1)+(x2,y2)+(x3,y3)'");
}
private Point2D _A, _B, _C;
private Line2D _AB, _BC, _CA;
private Line2D _AC, _CB, _BA;
[CommandProperty(AccessLevel.Counselor)]
public int X
{
get => _A.X;
set
{
_A.X = value;
_AB.Start = _BA.End = _AC.Start = _CA.End = _A;
}
}
[CommandProperty(AccessLevel.Counselor)]
public int Y
{
get => _A.Y;
set
{
_A.Y = value;
_AB.Start = _BA.End = _AC.Start = _CA.End = _A;
}
}
[CommandProperty(AccessLevel.Counselor)]
public Point2D A { get => _A; set => _A = _AB.Start = _BA.End = _AC.Start = _CA.End = value; }
[CommandProperty(AccessLevel.Counselor)]
public Point2D B { get => _B; set => _B = _BC.Start = _CB.End = _BA.Start = _AB.End = value; }
[CommandProperty(AccessLevel.Counselor)]
public Point2D C { get => _C; set => _C = _CA.Start = _AC.End = _CB.Start = _BC.End = value; }
[CommandProperty(AccessLevel.Counselor)]
public Line2D AB
{
get => _AB;
set
{
_AB = value;
_A = _BA.End = _AB.Start;
_B = _BA.Start = _AB.End;
}
}
[CommandProperty(AccessLevel.Counselor)]
public Line2D BC
{
get => _BC;
set
{
_BC = value;
_B = _CB.End = _BC.Start;
_C = _CB.Start = _BC.End;
}
}
[CommandProperty(AccessLevel.Counselor)]
public Line2D CA
{
get => _CA;
set
{
_CA = value;
_C = _AC.End = _CA.Start;
_A = _AC.Start = _CA.End;
}
}
[CommandProperty(AccessLevel.Counselor)]
public Line2D AC
{
get => _AC;
set
{
_AC = value;
_A = _CA.End = _AC.Start;
_C = _CA.Start = _AC.End;
}
}
[CommandProperty(AccessLevel.Counselor)]
public Line2D CB
{
get => _CB;
set
{
_CB = value;
_C = _BC.End = _CB.Start;
_B = _BC.Start = _CB.End;
}
}
[CommandProperty(AccessLevel.Counselor)]
public Line2D BA
{
get => _BA;
set
{
_BA = value;
_B = _AB.End = _BA.Start;
_A = _AB.Start = _BA.End;
}
}
[CommandProperty(AccessLevel.Counselor)]
public Angle ABC => Angle.FromPoints(_A, _B, _C);
[CommandProperty(AccessLevel.Counselor)]
public Angle BCA => Angle.FromPoints(_B, _C, _A);
[CommandProperty(AccessLevel.Counselor)]
public Angle CAB => Angle.FromPoints(_C, _A, _B);
public Triangle2D(IPoint2D a, IPoint2D b, IPoint2D c)
{
_A = new Point2D(a);
_B = new Point2D(b);
_C = new Point2D(c);
_AB = new Line2D(_A, _B);
_BC = new Line2D(_B, _C);
_CA = new Line2D(_C, _A);
_AC = new Line2D(_A, _C);
_CB = new Line2D(_C, _B);
_BA = new Line2D(_B, _A);
}
public Triangle2D(int x1, int y1, int x2, int y2, int x3, int y3)
{
_A = new Point2D(x1, y1);
_B = new Point2D(x2, y2);
_C = new Point2D(x3, y3);
_AB = new Line2D(_A, _B);
_BC = new Line2D(_B, _C);
_CA = new Line2D(_C, _A);
_AC = new Line2D(_A, _C);
_CB = new Line2D(_C, _B);
_BA = new Line2D(_B, _A);
}
public bool Contains(IPoint2D p)
{
return Contains(p, _A, _B, _C);
}
public bool Contains(int x, int y)
{
return Contains(x, y, _A, _B, _C);
}
public IEnumerable<Point2D> Intersect(Triangle2D t)
{
return Intersect(this, t);
}
public IEnumerable<Point2D> Intersect(Rectangle2D r)
{
return Intersect(this, r);
}
public bool Intersects(Triangle2D t)
{
return Intersects(this, t);
}
public bool Intersects(Rectangle2D r)
{
return Intersects(this, r);
}
public IEnumerable<Point2D> Plot()
{
return Plot(_A, _B, _C);
}
public override string ToString()
{
return String.Format("{0}+{1}+{2}", _A, _B, _C);
}
}
}

View File

@@ -0,0 +1,469 @@
#region Header
// _,-'/-'/
// . __,-; ,'( '/
// \. `-.__`-._`:_,-._ _ , . ``
// `:-._,------' ` _,`--` -: `_ , ` ,' :
// `---..__,,--' (C) 2023 ` -'. -'
// # Vita-Nex [http://core.vita-nex.com] #
// {o)xxx|===============- # -===============|xxx(o}
// # #
#endregion
#region References
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using VitaNex.Collections;
#endregion
namespace Server
{
public interface IWireframe : IEnumerable<Block3D>
{
bool Intersects(IBlock3D b);
bool Intersects(int x, int y, int z);
bool Intersects(int x, int y, int z, int h);
bool Intersects(IWireframe frame);
Rectangle3D GetBounds();
IEnumerable<Block3D> Offset(int x = 0, int y = 0, int z = 0, int h = 0);
}
public sealed class Wireframe : IEquatable<Wireframe>, IWireframe
{
public static readonly Wireframe Empty = new Wireframe(0);
public Block3D[] Blocks { get; private set; }
public int Volume => Blocks.Length;
public int Length => Blocks.Length;
public Wireframe(params IBlock3D[] blocks)
: this(blocks.Ensure().Select(b => new Block3D(b)))
{ }
public Wireframe(IEnumerable<IBlock3D> blocks)
: this(blocks.Ensure().Select(b => new Block3D(b)))
{ }
public Wireframe(Wireframe frame)
: this(frame.Blocks)
{ }
public Wireframe(int capacity)
{
Blocks = new Block3D[capacity];
}
public Wireframe(params Block3D[] blocks)
{
Blocks = blocks.Ensure().ToArray();
}
public Wireframe(IEnumerable<Block3D> blocks)
{
Blocks = blocks.Ensure().ToArray();
}
public bool Intersects(IPoint3D p)
{
return Intersects(p.X, p.Y, p.Z);
}
public bool Intersects(IPoint3D p, int h)
{
return Intersects(p.X, p.Y, p.Z, h);
}
public bool Intersects(IBlock3D b)
{
return Intersects(b.X, b.Y, b.Z, b.H);
}
public bool Intersects(int x, int y, int z)
{
return Intersects(x, y, z, 0);
}
public bool Intersects(int x, int y, int z, int h)
{
return Blocks.Any(b => b.Intersects(x, y, z, h));
}
public bool Intersects(IWireframe frame)
{
return frame != null && Blocks.Any(b => frame.Intersects(b));
}
public Rectangle3D GetBounds()
{
Point3D min = Point3D.Zero, max = Point3D.Zero;
foreach (var b in Blocks)
{
min.X = Math.Min(min.X, b.X);
min.Y = Math.Min(min.Y, b.Y);
min.Z = Math.Min(min.Z, b.Z);
max.X = Math.Max(max.X, b.X);
max.Y = Math.Max(max.Y, b.Y);
max.Z = Math.Max(max.Z, b.Z + b.H);
}
return new Rectangle3D(min, max);
}
public IEnumerable<Block3D> Offset(int x = 0, int y = 0, int z = 0, int h = 0)
{
return Blocks.Select(b => b.Offset(x, y, z, h));
}
public IEnumerator<Block3D> GetEnumerator()
{
return Blocks.AsEnumerable().GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public Block3D this[int index]
{
get
{
if (index < 0 || index >= Blocks.Length)
{
return Block3D.Empty;
}
return Blocks[index];
}
set
{
if (index >= 0 && index < Blocks.Length)
{
Blocks[index] = value;
_Hash = null;
}
}
}
private int? _Hash;
public int HashCode => _Hash ?? (_Hash = Blocks.GetContentsHashCode(true)).Value;
public override int GetHashCode()
{
return HashCode;
}
public override bool Equals(object obj)
{
return obj is Wireframe && Equals((Wireframe)obj);
}
public bool Equals(Wireframe other)
{
return !ReferenceEquals(other, null) && (ReferenceEquals(this, other) || GetHashCode() == other.GetHashCode());
}
public override string ToString()
{
return String.Format("Wireframe ({0:#,0} blocks)", Length);
}
public static bool operator ==(Wireframe l, Wireframe r)
{
return ReferenceEquals(l, null) ? ReferenceEquals(r, null) : l.Equals(r);
}
public static bool operator !=(Wireframe l, Wireframe r)
{
return ReferenceEquals(l, null) ? !ReferenceEquals(r, null) : !l.Equals(r);
}
}
public class DynamicWireframe : IEquatable<DynamicWireframe>, IWireframe
{
public bool Rendering { get; protected set; }
public virtual List<Block3D> Blocks { get; set; }
public virtual int Volume => Blocks.Count;
public int Count => Blocks.Count;
public DynamicWireframe(params IBlock3D[] blocks)
: this(blocks.Ensure().Select(b => new Block3D(b)))
{ }
public DynamicWireframe(IEnumerable<IBlock3D> blocks)
: this(blocks.Ensure().Select(b => new Block3D(b)))
{ }
public DynamicWireframe(Wireframe frame)
: this(frame.Blocks)
{ }
public DynamicWireframe()
: this(0x100)
{ }
public DynamicWireframe(int capacity)
{
Blocks = new List<Block3D>(capacity);
}
public DynamicWireframe(params Block3D[] blocks)
{
Blocks = blocks.Ensure().ToList();
}
public DynamicWireframe(IEnumerable<Block3D> blocks)
{
Blocks = blocks.Ensure().ToList();
}
public DynamicWireframe(GenericReader reader)
{
Rendering = true;
Deserialize(reader);
Rendering = false;
}
public void Flatten()
{
var list = ListPool<Block3D>.AcquireObject();
list.AddRange(this);
Clear();
AddRange(list.Flatten());
ObjectPool.Free(ref list);
}
public bool Intersects(IPoint3D p)
{
return Intersects(p.X, p.Y, p.Z);
}
public bool Intersects(IBlock3D b)
{
return Intersects(b.X, b.Y, b.Z, b.H);
}
public bool Intersects(int x, int y, int z)
{
return Intersects(x, y, z, 0);
}
public bool Intersects(int x, int y, int z, int h)
{
return Blocks.Any(b => b.Intersects(x, y, z, h));
}
public bool Intersects(IWireframe frame)
{
return frame != null && Blocks.Any(b => frame.Intersects(b));
}
public Rectangle3D GetBounds()
{
Point3D min = Point3D.Zero, max = Point3D.Zero;
foreach (var b in Blocks)
{
min.X = Math.Min(min.X, b.X);
min.Y = Math.Min(min.Y, b.Y);
min.Z = Math.Min(min.Z, b.Z);
max.X = Math.Max(max.X, b.X);
max.Y = Math.Max(max.Y, b.Y);
max.Z = Math.Max(max.Z, b.Z + b.H);
}
return new Rectangle3D(min, max);
}
public IEnumerable<Block3D> Offset(int x = 0, int y = 0, int z = 0, int h = 0)
{
return Blocks.Select(b => b.Offset(x, y, z, h));
}
public virtual void Clear()
{
Blocks.Free(true);
_Hash = null;
}
public virtual void Add(Block3D item)
{
if (item != null)
{
Blocks.Add(item);
_Hash = null;
}
}
public virtual void AddRange(IEnumerable<Block3D> collection)
{
if (collection != null)
{
Blocks.AddRange(collection);
_Hash = null;
}
}
public virtual bool Remove(Block3D item)
{
if (item == null)
{
return false;
}
var success = Blocks.Remove(item);
Blocks.Free(false);
_Hash = null;
return success;
}
public virtual int RemoveAll(Predicate<Block3D> match)
{
if (match == null)
{
return 0;
}
var success = Blocks.RemoveAll(match);
Blocks.Free(false);
_Hash = null;
return success;
}
public virtual void RemoveAt(int index)
{
if (!Blocks.InBounds(index))
{
return;
}
Blocks.RemoveAt(index);
Blocks.Free(false);
_Hash = null;
}
public virtual void RemoveRange(int index, int count)
{
if (!Blocks.InBounds(index))
{
return;
}
Blocks.RemoveRange(index, count);
Blocks.Free(false);
_Hash = null;
}
public virtual void ForEach(Action<Block3D> action)
{
Blocks.ForEach(action);
}
public virtual IEnumerator<Block3D> GetEnumerator()
{
return Blocks.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public virtual Block3D this[int index]
{
get
{
if (index < 0 || index >= Blocks.Count)
{
return Block3D.Empty;
}
return Blocks[index];
}
set
{
if (index >= 0 && index < Blocks.Count)
{
Blocks[index] = value;
_Hash = null;
}
}
}
private int? _Hash;
public int HashCode => _Hash ?? (_Hash = Blocks.GetContentsHashCode(true)).Value;
public override int GetHashCode()
{
return HashCode;
}
public override bool Equals(object obj)
{
return obj is DynamicWireframe && Equals((DynamicWireframe)obj);
}
public bool Equals(DynamicWireframe other)
{
return !ReferenceEquals(other, null) && (ReferenceEquals(this, other) || GetHashCode() == other.GetHashCode());
}
public override string ToString()
{
return String.Format("DynamicWireframe ({0:#,0} blocks)", Count);
}
public virtual void Serialize(GenericWriter writer)
{
writer.SetVersion(0);
writer.WriteList(Blocks, (w, b) => w.WriteBlock3D(b));
}
public virtual void Deserialize(GenericReader reader)
{
reader.GetVersion();
Blocks = reader.ReadList(r => reader.ReadBlock3D());
}
public static bool operator ==(DynamicWireframe l, DynamicWireframe r)
{
return ReferenceEquals(l, null) ? ReferenceEquals(r, null) : l.Equals(r);
}
public static bool operator !=(DynamicWireframe l, DynamicWireframe r)
{
return ReferenceEquals(l, null) ? !ReferenceEquals(r, null) : !l.Equals(r);
}
}
}