Files
abysmal-isle/Scripts/SubSystem/VitaNex/Core/Geometry/Wireframe.cs
Unstable Kitsune b918192e4e Overwrite
Complete Overwrite of the Folder with the free shard. ServUO 57.3 has been added.
2023-11-28 23:20:26 -05:00

469 lines
9.0 KiB
C#

#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);
}
}
}