Updates Data to JSON (#159)

This commit is contained in:
Kamron Batman 2020-06-19 13:53:18 -07:00 committed by GitHub
parent d2f7e08de4
commit 1246a135f7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
61 changed files with 18005 additions and 9152 deletions

View file

@ -17,7 +17,7 @@ namespace Server.Tests
public static void Equal(ReadOnlySpan<byte> actual, ReadOnlySpan<byte> expected) =>
Xunit.Assert.True(
MemoryExtensions.SequenceEqual(expected, actual),
expected.SequenceEqual(actual),
$"Expected does not match actual.\nExpected:\t{SpanToString(expected)}\nActual:\t\t{SpanToString(actual)}"
);
}

View file

@ -5,8 +5,8 @@
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.6.1" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1" />
<PackageReference Include="coverlet.collector" Version="1.2.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.2" />
<PackageReference Include="coverlet.collector" Version="1.3.0" />
<ProjectReference Include="..\Server\Server.csproj" />
</ItemGroup>
</Project>

File diff suppressed because it is too large Load diff

View file

@ -1,391 +0,0 @@
/***************************************************************************
* Geometry.cs
* -------------------
* begin : May 1, 2002
* copyright : (C) The RunUO Software Team
* email : info@runuo.com
*
* $Id$
*
***************************************************************************/
/***************************************************************************
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
***************************************************************************/
using System;
namespace Server
{
[Parsable]
public struct Point2D : IPoint2D, IComparable<Point2D>, IEquatable<object>, IEquatable<Point2D>
{
internal int m_X;
internal int m_Y;
public static readonly Point2D Zero = new Point2D(0, 0);
public Point2D(int x, int y)
{
m_X = x;
m_Y = y;
}
public Point2D(IPoint2D p) : this(p.X, p.Y)
{
}
[CommandProperty(AccessLevel.Counselor)]
public int X
{
get => m_X;
set => m_X = value;
}
[CommandProperty(AccessLevel.Counselor)]
public int Y
{
get => m_Y;
set => m_Y = value;
}
public override string ToString() => $"({m_X}, {m_Y})";
public static Point2D Parse(string value)
{
var start = value.IndexOf('(');
var end = value.IndexOf(',', start + 1);
var param1 = value.Substring(start + 1, end - (start + 1)).Trim();
start = end;
end = value.IndexOf(')', start + 1);
var param2 = value.Substring(start + 1, end - (start + 1)).Trim();
return new Point2D(Convert.ToInt32(param1), Convert.ToInt32(param2));
}
public int CompareTo(Point2D other)
{
var v = m_X.CompareTo(other.m_X);
if (v == 0)
v = m_Y.CompareTo(other.m_Y);
return v;
}
public override bool Equals(object o) => o is IPoint2D p && m_X == p.X && m_Y == p.Y;
public bool Equals(Point2D p) => m_X == p.X && m_Y == p.Y;
public override int GetHashCode() => m_X ^ m_Y;
public static bool operator ==(Point2D l, Point2D r) => l.m_X == r.m_X && l.m_Y == r.m_Y;
public static bool operator !=(Point2D l, Point2D r) => l.m_X != r.m_X || l.m_Y != r.m_Y;
public static bool operator ==(Point2D l, IPoint2D r) => !ReferenceEquals(r, null) && l.m_X == r.X && l.m_Y == r.Y;
public static bool operator !=(Point2D l, IPoint2D r) => !ReferenceEquals(r, null) && (l.m_X != r.X || l.m_Y != r.Y);
public static bool operator >(Point2D l, Point2D r) => l.m_X > r.m_X && l.m_Y > r.m_Y;
public static bool operator >(Point2D l, Point3D r) => l.m_X > r.m_X && l.m_Y > r.m_Y;
public static bool operator >(Point2D l, IPoint2D r) => !ReferenceEquals(r, null) && l.m_X > r.X && l.m_Y > r.Y;
public static bool operator <(Point2D l, Point2D r) => l.m_X < r.m_X && l.m_Y < r.m_Y;
public static bool operator <(Point2D l, Point3D r) => l.m_X < r.m_X && l.m_Y < r.m_Y;
public static bool operator <(Point2D l, IPoint2D r) => !ReferenceEquals(r, null) && l.m_X < r.X && l.m_Y < r.Y;
public static bool operator >=(Point2D l, Point2D r) => l.m_X >= r.m_X && l.m_Y >= r.m_Y;
public static bool operator >=(Point2D l, Point3D r) => l.m_X >= r.m_X && l.m_Y >= r.m_Y;
public static bool operator >=(Point2D l, IPoint2D r) => !ReferenceEquals(r, null) && l.m_X >= r.X && l.m_Y >= r.Y;
public static bool operator <=(Point2D l, Point2D r) => l.m_X <= r.m_X && l.m_Y <= r.m_Y;
public static bool operator <=(Point2D l, Point3D r) => l.m_X <= r.m_X && l.m_Y <= r.m_Y;
public static bool operator <=(Point2D l, IPoint2D r) => !ReferenceEquals(r, null) && l.m_X <= r.X && l.m_Y <= r.Y;
}
[Parsable]
public struct Point3D : IPoint3D, IComparable<Point3D>, IEquatable<object>, IEquatable<Point3D>
{
internal int m_X;
internal int m_Y;
internal int m_Z;
public static readonly Point3D Zero = new Point3D(0, 0, 0);
public Point3D(int x, int y, int z)
{
m_X = x;
m_Y = y;
m_Z = z;
}
public Point3D(IPoint3D p)
: this(p.X, p.Y, p.Z)
{
}
public Point3D(IPoint2D p, int z)
: this(p.X, p.Y, z)
{
}
[CommandProperty(AccessLevel.Counselor)]
public int X
{
get => m_X;
set => m_X = value;
}
[CommandProperty(AccessLevel.Counselor)]
public int Y
{
get => m_Y;
set => m_Y = value;
}
[CommandProperty(AccessLevel.Counselor)]
public int Z
{
get => m_Z;
set => m_Z = value;
}
public override string ToString() => $"({m_X}, {m_Y}, {m_Z})";
public override bool Equals(object o) => o is IPoint3D p && m_X == p.X && m_Y == p.Y && m_Z == p.Z;
public bool Equals(Point3D p) => m_X == p.X && m_Y == p.Y && m_Z == p.Z;
public override int GetHashCode() => m_X ^ m_Y ^ m_Z;
public static Point3D Parse(string value)
{
var start = value.IndexOf('(');
var end = value.IndexOf(',', start + 1);
var param1 = value.Substring(start + 1, end - (start + 1)).Trim();
start = end;
end = value.IndexOf(',', start + 1);
var param2 = value.Substring(start + 1, end - (start + 1)).Trim();
start = end;
end = value.IndexOf(')', start + 1);
var param3 = value.Substring(start + 1, end - (start + 1)).Trim();
return new Point3D(Convert.ToInt32(param1), Convert.ToInt32(param2), Convert.ToInt32(param3));
}
public static bool operator ==(Point3D l, Point3D r) => l.m_X == r.m_X && l.m_Y == r.m_Y && l.m_Z == r.m_Z;
public static bool operator !=(Point3D l, Point3D r) => l.m_X != r.m_X || l.m_Y != r.m_Y || l.m_Z != r.m_Z;
public static bool operator ==(Point3D l, IPoint3D r) =>
!ReferenceEquals(r, null) && l.m_X == r.X && l.m_Y == r.Y && l.m_Z == r.Z;
public static bool operator !=(Point3D l, IPoint3D r) =>
!ReferenceEquals(r, null) && (l.m_X != r.X || l.m_Y != r.Y || l.m_Z != r.Z);
public int CompareTo(Point3D other)
{
var v = m_X.CompareTo(other.m_X);
if (v == 0)
{
v = m_Y.CompareTo(other.m_Y);
if (v == 0)
v = m_Z.CompareTo(other.m_Z);
}
return v;
}
}
[NoSort]
[Parsable]
[PropertyObject]
public struct Rectangle2D
{
private Point2D m_Start;
private Point2D m_End;
public Rectangle2D(IPoint2D start, IPoint2D end)
{
m_Start = new Point2D(start);
m_End = new Point2D(end);
}
public Rectangle2D(int x, int y, int width, int height)
{
m_Start = new Point2D(x, y);
m_End = new Point2D(x + width, y + height);
}
public void Set(int x, int y, int width, int height)
{
m_Start = new Point2D(x, y);
m_End = new Point2D(x + width, y + height);
}
public static Rectangle2D Parse(string value)
{
var start = value.IndexOf('(');
var end = value.IndexOf(',', start + 1);
var param1 = value.Substring(start + 1, end - (start + 1)).Trim();
start = end;
end = value.IndexOf(',', start + 1);
var param2 = value.Substring(start + 1, end - (start + 1)).Trim();
start = end;
end = value.IndexOf(',', start + 1);
var param3 = value.Substring(start + 1, end - (start + 1)).Trim();
start = end;
end = value.IndexOf(')', start + 1);
var param4 = value.Substring(start + 1, end - (start + 1)).Trim();
return new Rectangle2D(Convert.ToInt32(param1), Convert.ToInt32(param2), Convert.ToInt32(param3),
Convert.ToInt32(param4));
}
[CommandProperty(AccessLevel.Counselor)]
public Point2D Start
{
get => m_Start;
set => m_Start = value;
}
[CommandProperty(AccessLevel.Counselor)]
public Point2D End
{
get => m_End;
set => m_End = value;
}
[CommandProperty(AccessLevel.Counselor)]
public int X
{
get => m_Start.m_X;
set => m_Start.m_X = value;
}
[CommandProperty(AccessLevel.Counselor)]
public int Y
{
get => m_Start.m_Y;
set => m_Start.m_Y = value;
}
[CommandProperty(AccessLevel.Counselor)]
public int Width
{
get => m_End.m_X - m_Start.m_X;
set => m_End.m_X = m_Start.m_X + value;
}
[CommandProperty(AccessLevel.Counselor)]
public int Height
{
get => m_End.m_Y - m_Start.m_Y;
set => m_End.m_Y = m_Start.m_Y + value;
}
public void MakeHold(Rectangle2D r)
{
if (r.m_Start.m_X < m_Start.m_X)
m_Start.m_X = r.m_Start.m_X;
if (r.m_Start.m_Y < m_Start.m_Y)
m_Start.m_Y = r.m_Start.m_Y;
if (r.m_End.m_X > m_End.m_X)
m_End.m_X = r.m_End.m_X;
if (r.m_End.m_Y > m_End.m_Y)
m_End.m_Y = r.m_End.m_Y;
}
public bool Contains(Point3D p) =>
m_Start.m_X <= p.m_X && m_Start.m_Y <= p.m_Y && m_End.m_X > p.m_X && m_End.m_Y > p.m_Y;
public bool Contains(Point2D p) =>
m_Start.m_X <= p.m_X && m_Start.m_Y <= p.m_Y && m_End.m_X > p.m_X && m_End.m_Y > p.m_Y;
public bool Contains(IPoint2D p) => m_Start <= p && m_End > p;
public override string ToString() => $"({X}, {Y})+({Width}, {Height})";
}
[NoSort]
[PropertyObject]
public struct Rectangle3D
{
public Rectangle3D(Point3D start, Point3D end)
{
Start = start;
End = end;
}
public Rectangle3D(int x, int y, int z, int width, int height, int depth)
{
Start = new Point3D(x, y, z);
End = new Point3D(x + width, y + height, z + depth);
}
[CommandProperty(AccessLevel.Counselor)]
public Point3D Start { get; set; }
[CommandProperty(AccessLevel.Counselor)]
public Point3D End { get; set; }
[CommandProperty(AccessLevel.Counselor)]
public int Width => End.X - Start.X;
[CommandProperty(AccessLevel.Counselor)]
public int Height => End.Y - Start.Y;
[CommandProperty(AccessLevel.Counselor)]
public int Depth => End.Z - Start.Z;
public bool Contains(Point3D p) =>
p.m_X >= Start.m_X
&& p.m_X < End.m_X
&& p.m_Y >= Start.m_Y
&& p.m_Y < End.m_Y
&& p.m_Z >= Start.m_Z
&& p.m_Z < End.m_Z;
public bool Contains(IPoint3D p) =>
p.X >= Start.m_X
&& p.X < End.m_X
&& p.Y >= Start.m_Y
&& p.Y < End.m_Y
&& p.Z >= Start.m_Z
&& p.Z < End.m_Z;
}
}

View file

@ -0,0 +1,122 @@
/*************************************************************************
* ModernUO *
* Copyright (C) 2019-2020 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: Point2D.cs - Created: 2020/05/31 - Updated: 2020/05/31 *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
*************************************************************************/
using System;
namespace Server
{
[Parsable]
public struct Point2D :
IPoint2D, IComparable<Point2D>, IComparable<IPoint2D>, IEquatable<object>, IEquatable<Point2D>, IEquatable<IPoint2D>
{
internal int m_X;
internal int m_Y;
public static readonly Point2D Zero = new Point2D(0, 0);
[CommandProperty(AccessLevel.Counselor)]
public int X
{
get => m_X;
set => m_X = value;
}
[CommandProperty(AccessLevel.Counselor)]
public int Y
{
get => m_Y;
set => m_Y = value;
}
public Point2D(int x, int y)
{
m_X = x;
m_Y = y;
}
public Point2D(IPoint2D p) : this(p.X, p.Y)
{
}
public override string ToString() => $"({m_X}, {m_Y})";
public static Point2D Parse(string value)
{
var start = value.IndexOf('(');
var end = value.IndexOf(',', start + 1);
Utility.ToInt32(value.Substring(start + 1, end - (start + 1)).Trim(), out int x);
start = end;
end = value.IndexOf(')', start + 1);
Utility.ToInt32(value.Substring(start + 1, end - (start + 1)).Trim(), out int y);
return new Point2D(x, y);
}
public bool Equals(Point2D other) => m_X == other.m_X && m_Y == other.m_Y;
public bool Equals(IPoint2D other) =>
!ReferenceEquals(other, null) && m_X == other.X && m_Y == other.Y;
public override bool Equals(object obj) => obj is Point2D other && Equals(other);
public override int GetHashCode() => HashCode.Combine(m_X, m_Y);
public static bool operator ==(Point2D l, Point2D r) => l.m_X == r.m_X && l.m_Y == r.m_Y;
public static bool operator !=(Point2D l, Point2D r) => l.m_X != r.m_X || l.m_Y != r.m_Y;
public static bool operator ==(Point2D l, IPoint2D r) => !ReferenceEquals(r, null) && l.m_X == r.X && l.m_Y == r.Y;
public static bool operator !=(Point2D l, IPoint2D r) => !ReferenceEquals(r, null) && (l.m_X != r.X || l.m_Y != r.Y);
public static bool operator >(Point2D l, Point2D r) => l.m_X > r.m_X && l.m_Y > r.m_Y;
public static bool operator >(Point2D l, IPoint2D r) => !ReferenceEquals(r, null) && l.m_X > r.X && l.m_Y > r.Y;
public static bool operator <(Point2D l, Point2D r) => l.m_X < r.m_X && l.m_Y < r.m_Y;
public static bool operator <(Point2D l, IPoint2D r) => !ReferenceEquals(r, null) && l.m_X < r.X && l.m_Y < r.Y;
public static bool operator >=(Point2D l, Point2D r) => l.m_X >= r.m_X && l.m_Y >= r.m_Y;
public static bool operator >=(Point2D l, IPoint2D r) => !ReferenceEquals(r, null) && l.m_X >= r.X && l.m_Y >= r.Y;
public static bool operator <=(Point2D l, Point2D r) => l.m_X <= r.m_X && l.m_Y <= r.m_Y;
public static bool operator <=(Point2D l, IPoint2D r) => !ReferenceEquals(r, null) && l.m_X <= r.X && l.m_Y <= r.Y;
public int CompareTo(Point2D other)
{
var xComparison = m_X.CompareTo(other.m_X);
if (xComparison != 0) return xComparison;
return m_Y.CompareTo(other.m_Y);
}
public int CompareTo(IPoint2D other)
{
var xComparison = m_X.CompareTo(other.X);
if (xComparison != 0) return xComparison;
return m_Y.CompareTo(other.Y);
}
}
}

View file

@ -0,0 +1,150 @@
/*************************************************************************
* ModernUO *
* Copyright (C) 2019-2020 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: Point3D.cs - Created: 2020/05/31 - Updated: 2020/05/31 *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
*************************************************************************/
using System;
namespace Server
{
[Parsable]
public struct Point3D :
IPoint3D, IComparable<Point3D>, IComparable<IPoint3D>, IEquatable<object>, IEquatable<Point3D>, IEquatable<IPoint3D>
{
internal int m_X;
internal int m_Y;
internal int m_Z;
public static readonly Point3D Zero = new Point3D(0, 0, 0);
[CommandProperty(AccessLevel.Counselor)]
public int X
{
get => m_X;
set => m_X = value;
}
[CommandProperty(AccessLevel.Counselor)]
public int Y
{
get => m_Y;
set => m_Y = value;
}
[CommandProperty(AccessLevel.Counselor)]
public int Z
{
get => m_Z;
set => m_Z = value;
}
public Point3D(IPoint3D p) : this(p.X, p.Y, p.Z)
{
}
public Point3D(IPoint2D p, int z) : this(p.X, p.Y, z)
{
}
public Point3D(int x, int y, int z)
{
m_X = x;
m_Y = y;
m_Z = z;
}
public override string ToString() => $"({m_X}, {m_Y}, {m_Z})";
public bool Equals(Point3D other) => m_X == other.m_X && m_Y == other.m_Y && m_Z == other.m_Z;
public bool Equals(IPoint3D other) =>
!ReferenceEquals(other, null) && m_X == other.X && m_Y == other.Y && m_Z == other.Z;
public override bool Equals(object obj) => obj is Point3D other && Equals(other);
public override int GetHashCode() => HashCode.Combine(m_X, m_Y, m_Z);
public static Point3D Parse(string value)
{
var start = value.IndexOf('(');
var end = value.IndexOf(',', start + 1);
Utility.ToInt32(value.Substring(start + 1, end - (start + 1)).Trim(), out int x);
start = end;
end = value.IndexOf(',', start + 1);
Utility.ToInt32(value.Substring(start + 1, end - (start + 1)).Trim(), out int y);
start = end;
end = value.IndexOf(')', start + 1);
Utility.ToInt32(value.Substring(start + 1, end - (start + 1)).Trim(), out int z);
return new Point3D(x, y, z);
}
public static bool operator ==(Point3D l, Point3D r) => l.m_X == r.m_X && l.m_Y == r.m_Y && l.m_Z == r.m_Z;
public static bool operator ==(Point3D l, IPoint3D r) =>
!ReferenceEquals(r, null) && l.m_X == r.X && l.m_Y == r.Y && l.m_Z == r.Z;
public static bool operator !=(Point3D l, Point3D r) => l.m_X != r.m_X || l.m_Y != r.m_Y || l.m_Z != r.m_Z;
public static bool operator !=(Point3D l, IPoint3D r) =>
!ReferenceEquals(r, null) && (l.m_X != r.X || l.m_Y != r.Y || l.m_Z != r.Z);
public static bool operator >(Point3D l, Point3D r) => l.m_X > r.m_X && l.m_Y > r.m_Y && l.m_Z > r.m_Z;
public static bool operator >(Point3D l, IPoint3D r) =>
!ReferenceEquals(r, null) && l.m_X > r.X && l.m_Y > r.Y && l.m_Z > r.Z;
public static bool operator <(Point3D l, Point3D r) => l.m_X < r.m_X && l.m_Y < r.m_Y && l.m_Z > r.m_Z;
public static bool operator <(Point3D l, IPoint3D r) =>
!ReferenceEquals(r, null) && l.m_X < r.X && l.m_Y < r.Y && l.m_Z > r.Z;
public static bool operator >=(Point3D l, Point3D r) => l.m_X >= r.m_X && l.m_Y >= r.m_Y && l.m_Z > r.m_Z;
public static bool operator >=(Point3D l, IPoint3D r) =>
!ReferenceEquals(r, null) && l.m_X >= r.X && l.m_Y >= r.Y && l.m_Z > r.Z;
public static bool operator <=(Point3D l, Point3D r) => l.m_X <= r.m_X && l.m_Y <= r.m_Y && l.m_Z > r.m_Z;
public static bool operator <=(Point3D l, IPoint3D r) =>
!ReferenceEquals(r, null) && l.m_X <= r.X && l.m_Y <= r.Y && l.m_Z > r.Z;
public int CompareTo(Point3D other)
{
var xComparison = m_X.CompareTo(other.m_X);
if (xComparison != 0) return xComparison;
var yComparison = m_Y.CompareTo(other.m_Y);
if (yComparison != 0) return yComparison;
return m_Z.CompareTo(other.m_Z);
}
public int CompareTo(IPoint3D other)
{
var xComparison = m_X.CompareTo(other.X);
if (xComparison != 0) return xComparison;
var yComparison = m_Y.CompareTo(other.Y);
if (yComparison != 0) return yComparison;
return m_Z.CompareTo(other.Z);
}
}
}

View file

@ -0,0 +1,141 @@
/*************************************************************************
* ModernUO *
* Copyright (C) 2019-2020 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: Rectangle2D.cs - Created: 2020/05/31 - Updated: 2020/05/31 *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
*************************************************************************/
namespace Server
{
[NoSort]
[Parsable]
[PropertyObject]
public struct Rectangle2D
{
private Point2D m_Start;
private Point2D m_End;
public Rectangle2D(IPoint2D start, IPoint2D end)
{
m_Start = new Point2D(start);
m_End = new Point2D(end);
}
public Rectangle2D(int x, int y, int width, int height)
{
m_Start = new Point2D(x, y);
m_End = new Point2D(x + width, y + height);
}
public void Set(int x, int y, int width, int height)
{
m_Start = new Point2D(x, y);
m_End = new Point2D(x + width, y + height);
}
public static Rectangle2D Parse(string value)
{
var start = value.IndexOf('(');
var end = value.IndexOf(',', start + 1);
Utility.ToInt32(value.Substring(start + 1, end - (start + 1)).Trim(), out int x);
start = end;
end = value.IndexOf(',', start + 1);
Utility.ToInt32(value.Substring(start + 1, end - (start + 1)).Trim(), out int y);
start = end;
end = value.IndexOf(',', start + 1);
Utility.ToInt32(value.Substring(start + 1, end - (start + 1)).Trim(), out int w);
start = end;
end = value.IndexOf(')', start + 1);
Utility.ToInt32(value.Substring(start + 1, end - (start + 1)).Trim(), out int h);
return new Rectangle2D(x, y, w, h);
}
[CommandProperty(AccessLevel.Counselor)]
public Point2D Start
{
get => m_Start;
set => m_Start = value;
}
[CommandProperty(AccessLevel.Counselor)]
public Point2D End
{
get => m_End;
set => m_End = value;
}
[CommandProperty(AccessLevel.Counselor)]
public int X
{
get => m_Start.m_X;
set => m_Start.m_X = value;
}
[CommandProperty(AccessLevel.Counselor)]
public int Y
{
get => m_Start.m_Y;
set => m_Start.m_Y = value;
}
[CommandProperty(AccessLevel.Counselor)]
public int Width
{
get => m_End.m_X - m_Start.m_X;
set => m_End.m_X = m_Start.m_X + value;
}
[CommandProperty(AccessLevel.Counselor)]
public int Height
{
get => m_End.m_Y - m_Start.m_Y;
set => m_End.m_Y = m_Start.m_Y + value;
}
public void MakeHold(Rectangle2D r)
{
if (r.m_Start.m_X < m_Start.m_X)
m_Start.m_X = r.m_Start.m_X;
if (r.m_Start.m_Y < m_Start.m_Y)
m_Start.m_Y = r.m_Start.m_Y;
if (r.m_End.m_X > m_End.m_X)
m_End.m_X = r.m_End.m_X;
if (r.m_End.m_Y > m_End.m_Y)
m_End.m_Y = r.m_End.m_Y;
}
public bool Contains(Point3D p) =>
m_Start.m_X <= p.m_X && m_Start.m_Y <= p.m_Y && m_End.m_X > p.m_X && m_End.m_Y > p.m_Y;
public bool Contains(Point2D p) =>
m_Start.m_X <= p.m_X && m_Start.m_Y <= p.m_Y && m_End.m_X > p.m_X && m_End.m_Y > p.m_Y;
public bool Contains(IPoint2D p) => m_Start <= p && m_End > p;
public override string ToString() => $"({X}, {Y})+({Width}, {Height})";
}
}

View file

@ -0,0 +1,123 @@
/*************************************************************************
* ModernUO *
* Copyright (C) 2019-2020 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: Rectangle3D.cs - Created: 2020/05/31 - Updated: 2020/05/31 *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
*************************************************************************/
namespace Server
{
[NoSort]
[PropertyObject]
public struct Rectangle3D
{
private Point3D m_Start;
private Point3D m_End;
public Rectangle3D(Point3D start, Point3D end)
{
m_Start = start;
m_End = end;
}
public Rectangle3D(int x, int y, int z, int width, int height, int depth)
{
m_Start = new Point3D(x, y, z);
m_End = new Point3D(x + width, y + height, z + depth);
}
[CommandProperty(AccessLevel.Counselor)]
public Point3D Start
{
get => m_Start;
set => m_Start = value;
}
[CommandProperty(AccessLevel.Counselor)]
public Point3D End
{
get => m_End;
set => m_End = value;
}
[CommandProperty(AccessLevel.Counselor)]
public int X
{
get => m_Start.m_X;
set => m_Start.m_X = value;
}
[CommandProperty(AccessLevel.Counselor)]
public int Y
{
get => m_Start.m_Y;
set => m_Start.m_Y = value;
}
[CommandProperty(AccessLevel.Counselor)]
public int Z
{
get => m_Start.m_Z;
set => m_Start.m_Z = value;
}
[CommandProperty(AccessLevel.Counselor)]
public int Width => m_End.X - m_Start.X;
[CommandProperty(AccessLevel.Counselor)]
public int Height => m_End.Y - m_Start.Y;
[CommandProperty(AccessLevel.Counselor)]
public int Depth => m_End.Z - m_Start.Z;
public void MakeHold(Rectangle3D r)
{
if (r.m_Start.m_X < m_Start.m_X)
m_Start.m_X = r.m_Start.m_X;
if (r.m_Start.m_Y < m_Start.m_Y)
m_Start.m_Y = r.m_Start.m_Y;
if (r.m_Start.m_Z < m_Start.m_Z)
m_Start.m_Z = r.m_Start.m_Z;
if (r.m_End.m_X > m_End.m_X)
m_End.m_X = r.m_End.m_X;
if (r.m_End.m_Y > m_End.m_Y)
m_End.m_Y = r.m_End.m_Y;
if (r.m_End.m_Z < m_End.m_Z)
m_End.m_Z = r.m_End.m_Z;
}
public bool Contains(Point3D p) =>
p.m_X >= m_Start.m_X
&& p.m_X < m_End.m_X
&& p.m_Y >= m_Start.m_Y
&& p.m_Y < m_End.m_Y
&& p.m_Z >= m_Start.m_Z
&& p.m_Z < m_End.m_Z;
public bool Contains(IPoint3D p) =>
p.X >= m_Start.m_X
&& p.X < m_End.m_X
&& p.Y >= m_Start.m_Y
&& p.Y < m_End.m_Y
&& p.Z >= m_Start.m_Z
&& p.Z < m_End.m_Z;
}
}

View file

@ -0,0 +1,173 @@
/*************************************************************************
* ModernUO *
* Copyright (C) 2019-2020 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: WorldLocation.cs - Created: 2020/05/31 - Updated: 2020/05/31 *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
*************************************************************************/
using System;
using System.Collections.Generic;
namespace Server
{
[Parsable]
public struct WorldLocation : IPoint3D, IComparable<WorldLocation>, IEquatable<object>, IEquatable<WorldLocation>, IEquatable<IEntity>
{
internal Point3D m_Loc;
internal Map m_Map;
public static readonly WorldLocation Zero = new WorldLocation(0, 0, 0, Map.Internal);
[CommandProperty(AccessLevel.Counselor)]
public Point3D Location
{
get => m_Loc;
set => m_Loc = value;
}
[CommandProperty(AccessLevel.Counselor)]
public int X
{
get => m_Loc.m_X;
set => m_Loc.m_X = value;
}
[CommandProperty(AccessLevel.Counselor)]
public int Y
{
get => m_Loc.m_Y;
set => m_Loc.m_Y = value;
}
[CommandProperty(AccessLevel.Counselor)]
public int Z
{
get => m_Loc.m_Z;
set => m_Loc.m_Z = value;
}
[CommandProperty(AccessLevel.Counselor)]
public Map Map
{
get => m_Map;
set => m_Map = value;
}
public WorldLocation(IEntity e) : this(e.Location.X, e.Location.Y, e.Location.Z, e.Map)
{
}
public WorldLocation(IPoint2D p, Map map) : this(p.X, p.Y, 0, map)
{
}
public WorldLocation(int x, int y, Map map) : this(x, y, 0, map)
{
}
public WorldLocation(IPoint3D p, Map map) : this(p.X, p.Y, p.Z, map)
{
}
public WorldLocation(int x, int y, int z, Map map)
{
m_Loc.m_X = x;
m_Loc.m_Y = y;
m_Loc.m_Z = z;
m_Map = map;
}
public override string ToString() =>
$"({m_Loc.m_X}, {m_Loc.m_Y}, {m_Loc.m_Z}, {m_Map?.ToString() ?? "(-null-)"})";
public bool Equals(WorldLocation other) =>
m_Loc.Equals(other.m_Loc) && m_Map.MapID == other.m_Map.MapID;
public bool Equals(IEntity other) =>
!ReferenceEquals(other, null) && m_Loc == other.Location &&
m_Map.MapID == other.Map.MapID;
public override bool Equals(object obj) =>
obj is WorldLocation other && Equals(other);
public override int GetHashCode() => HashCode.Combine(m_Loc, m_Map);
public int CompareTo(WorldLocation other)
{
var locComparison = m_Loc.CompareTo(other.m_Loc);
if (locComparison != 0) return locComparison;
return Comparer<Map>.Default.Compare(m_Map, other.m_Map);
}
public static implicit operator Point3D(WorldLocation worldLocation) => worldLocation.Location;
public static bool operator ==(WorldLocation l, WorldLocation r) =>
l.m_Loc == r.m_Loc && l.m_Map == r.m_Map;
public static bool operator ==(WorldLocation l, IEntity r) =>
!ReferenceEquals(r, null) && l.m_Loc == r.Location && l.m_Map == r.Map;
public static bool operator !=(WorldLocation l, WorldLocation r) => l.m_Loc != r.m_Loc && l.m_Map != r.m_Map;
public static bool operator !=(WorldLocation l, IEntity r) =>
!ReferenceEquals(r, null) && l.m_Loc != r.Location && l.m_Map != r.Map;
public static bool operator >(WorldLocation l, WorldLocation r) => l.m_Loc > r.m_Loc && l.m_Map == r.m_Map;
public static bool operator >(WorldLocation l, IEntity r) =>
!ReferenceEquals(r, null) && l.m_Loc > r.Location && l.m_Map == r.Map;
public static bool operator <(WorldLocation l, WorldLocation r) => l.m_Loc < r.m_Loc && l.m_Map == r.m_Map;
public static bool operator <(WorldLocation l, IEntity r) =>
!ReferenceEquals(r, null) && l.m_Loc < r.Location && l.m_Map == r.Map;
public static bool operator >=(WorldLocation l, WorldLocation r) => l.m_Loc >= r.m_Loc && l.m_Map == r.m_Map;
public static bool operator >=(WorldLocation l, IEntity r) =>
!ReferenceEquals(r, null) && l.m_Loc >= r.Location && l.m_Map == r.Map;
public static bool operator <=(WorldLocation l, WorldLocation r) => l.m_Loc <= r.m_Loc && l.m_Map == r.m_Map;
public static bool operator <=(WorldLocation l, IEntity r) =>
!ReferenceEquals(r, null) && l.m_Loc <= r.Location && l.m_Map == r.Map;
public static WorldLocation Parse(string value)
{
var start = value.IndexOf('(');
var end = value.IndexOf(',', start + 1);
Utility.ToInt32(value.Substring(start + 1, end - (start + 1)).Trim(), out int x);
start = end;
end = value.IndexOf(',', start + 1);
Utility.ToInt32(value.Substring(start + 1, end - (start + 1)).Trim(), out int y);
start = end;
end = value.IndexOf(',', start + 1);
Utility.ToInt32(value.Substring(start + 1, end - (start + 1)).Trim(), out int z);
start = end;
end = value.IndexOf(')', start + 1);
var map = Map.Parse(value.Substring(start + 1, end - (start + 1)).Trim());
return new WorldLocation(x, y, z, map);
}
}
}

View file

@ -0,0 +1,160 @@
/*************************************************************************
* ModernUO *
* Copyright (C) 2019-2020 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: WorldLocationConverter.cs *
* Created: 2020/05/31 - Updated: 2020/05/31 *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
*************************************************************************/
using System;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace Server.Json
{
public class WorldLocationConverter : JsonConverter<WorldLocation>
{
private WorldLocation DeserializeArray(ref Utf8JsonReader reader)
{
Span<int> data = stackalloc int[3];
var count = 0;
bool hasMap = false;
Map map = null;
while (true)
{
reader.Read();
if (reader.TokenType == JsonTokenType.EndArray)
break;
if (reader.TokenType == JsonTokenType.Number)
{
if (count < 3)
data[count] = reader.GetInt32();
else if (count == 3)
map = Map.Maps[reader.GetInt32()];
count++;
}
if (reader.TokenType == JsonTokenType.String)
{
map = Map.Parse(reader.GetString());
break;
}
}
if (!hasMap || count < 3 || count > 4)
throw new JsonException("WorldLocation must be an array of x, y, z, and map");
return new WorldLocation(data[0], data[1], data[2], map);
}
private WorldLocation DeserializeObj(ref Utf8JsonReader reader, JsonSerializerOptions options)
{
Span<int> data = stackalloc int[3];
int count = 0;
bool hasLoc = false;
bool hasXYZ = false;
bool hasMap = false;
Map map = null;
while (true)
{
reader.Read();
if (reader.TokenType == JsonTokenType.EndObject)
break;
if (reader.TokenType != JsonTokenType.PropertyName)
throw new JsonException("Invalid Json structure for WorldLocation object");
var key = reader.GetString();
var i = key switch
{
"x" => 0,
"y" => 1,
"z" => 2,
"loc" => 3,
"map" => 4,
_ => 5
};
if (i == 5)
continue;
reader.Read();
if (i < 3)
{
if (hasLoc)
throw new JsonException("WorldLocation must have loc or x, y, z, but not both");
if (reader.TokenType != JsonTokenType.Number)
throw new JsonException($"Value for {key} must be a number");
hasXYZ = true;
data[i] = reader.GetInt32();
continue;
}
if (i == 3)
{
if (hasXYZ)
throw new JsonException("WorldLocation must have loc or x, y, z, but not both");
hasLoc = true;
Point3D loc = new Point3DConverter().Read(ref reader, typeof(Point3D), options);
data[0] = loc.X;
data[1] = loc.Y;
data[2] = loc.Z;
count = 3;
continue;
}
map = reader.TokenType switch
{
JsonTokenType.String => Map.Parse(reader.GetString()),
JsonTokenType.Number => Map.Maps[reader.GetInt32()],
_ => throw new JsonException($"Value for {key} must be a number or string")
};
}
if (!hasMap || count < 2)
throw new JsonException("WorldLocation must have an x, y, z, and map properties");
return new WorldLocation(data[0], data[1], data[2], map);
}
public override WorldLocation Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) =>
reader.TokenType switch
{
JsonTokenType.StartArray => DeserializeArray(ref reader),
JsonTokenType.StartObject => DeserializeObj(ref reader, options),
_ => throw new JsonException("Invalid Json for Point3D")
};
public override void Write(Utf8JsonWriter writer, WorldLocation value, JsonSerializerOptions options)
{
writer.WriteStartArray();
writer.WriteNumberValue(value.X);
writer.WriteNumberValue(value.Y);
writer.WriteNumberValue(value.Z);
writer.WriteStringValue(value.Map.ToString());
writer.WriteEndArray();
}
}
}

View file

@ -0,0 +1,34 @@
/*************************************************************************
* ModernUO *
* Copyright (C) 2019-2020 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: WorldLocationConverterFactory.cs *
* Created: 2020/05/31 - Updated: 2020/05/31 *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
*************************************************************************/
using System;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace Server.Json
{
public class WorldLocationConverterFactory : JsonConverterFactory
{
public override bool CanConvert(Type typeToConvert) => typeToConvert == typeof(WorldLocation);
public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options) => new WorldLocationConverter();
}
}

View file

@ -20,33 +20,50 @@
using System;
using System.Buffers;
using System.Collections.Generic;
using System.IO;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace Server.Json
{
public static class JsonConfig
{
public static readonly JsonSerializerOptions Options = new JsonSerializerOptions
public static readonly JsonSerializerOptions DefaultOptions = GetOptions();
public static JsonSerializerOptions GetOptions(params JsonConverterFactory[] converters)
{
ReadCommentHandling = JsonCommentHandling.Skip,
WriteIndented = true,
AllowTrailingCommas = true,
IgnoreNullValues = true
};
// In the future this should be optimized by cloning DefaultOptions
var options = new JsonSerializerOptions
{
ReadCommentHandling = JsonCommentHandling.Skip,
WriteIndented = true,
AllowTrailingCommas = true,
IgnoreNullValues = true
};
options.Converters.Add(new MapConverterFactory());
options.Converters.Add(new Point3DConverterFactory());
options.Converters.Add(new Rectangle3DConverterFactory());
options.Converters.Add(new TimeSpanConverterFactory());
for (int i = 0; i < converters.Length; i++) options.Converters.Add(converters[i]);
return options;
}
public static T Deserialize<T>(string filePath, JsonSerializerOptions options = null)
{
if (!File.Exists(filePath)) return default;
string text = File.ReadAllText(filePath, Utility.UTF8);
return JsonSerializer.Deserialize<T>(text, options ?? Options);
return JsonSerializer.Deserialize<T>(text, options ?? DefaultOptions);
}
public static void Serialize(string filePath, object value, JsonSerializerOptions options = null)
{
if (File.Exists(filePath)) File.Delete(filePath);
File.WriteAllText(filePath, JsonSerializer.Serialize(value, options ?? Options));
File.WriteAllText(filePath, JsonSerializer.Serialize(value, options ?? DefaultOptions));
}
public static T ToObject<T>(this ref Utf8JsonReader reader, JsonSerializerOptions options = null) =>

View file

@ -14,12 +14,6 @@ namespace Server
{
var path = Path.Join(Core.BaseDirectory, "Data/regions.json");
// Json Deserialization options for custom objects
JsonSerializerOptions options = new JsonSerializerOptions();
options.Converters.Add(new MapConverterFactory());
options.Converters.Add(new Point3DConverterFactory());
options.Converters.Add(new Rectangle3DConverterFactory());
List<string> failures = new List<string>();
int count = 0;
@ -38,7 +32,7 @@ namespace Server
continue;
}
var region = ActivatorUtil.CreateInstance(type, json, options) as Region;
var region = ActivatorUtil.CreateInstance(type, json, JsonConfig.DefaultOptions) as Region;
region?.Register();
count++;
}

View file

@ -6,7 +6,7 @@
<StartupObject>Server.Core</StartupObject>
<AssemblyName>ModernUO</AssemblyName>
<Win32Resource />
<Version>0.4.0</Version>
<Version>0.5.0</Version>
<Product>ModernUO Server</Product>
<PublishDir>..\..\Distribution</PublishDir>
<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
@ -25,6 +25,7 @@
<Delete Files="..\..\Distribution\zlib.dll" ContinueOnError="true" />
<Delete Files="..\..\Distribution\libz.dylib" ContinueOnError="true" />
<Delete Files="..\..\Distribution\libz.so" ContinueOnError="true" />
<Delete Files="..\..\Distribution\ZLib.Bindings.dll" ContinueOnError="true" />
<Delete Files="..\..\Distribution\Microsoft.AspNetCore.Connections.Abstractions.dll" ContinueOnError="true" />
<Delete Files="..\..\Distribution\Microsoft.AspNetCore.Http.Features.dll" ContinueOnError="true" />
<Delete Files="..\..\Distribution\Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.dll" ContinueOnError="true" />
@ -64,9 +65,9 @@
<AdditionalFiles Include="..\..\stylecop.json">
<Link>stylecop.json</Link>
</AdditionalFiles>
<PackageReference Include="Microsoft.AspNetCore.Connections.Abstractions" Version="3.1.4" />
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv" Version="3.1.4" />
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="3.1.4" />
<PackageReference Include="Microsoft.AspNetCore.Connections.Abstractions" Version="3.1.5" />
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv" Version="3.1.5" />
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="3.1.5" />
<PackageReference Include="System.IO.Pipelines" Version="4.7.2" />
<PackageReference Include="ZLib.Bindings" Version="1.0.2" />
</ItemGroup>

View file

@ -4,36 +4,36 @@
".NETCoreApp,Version=v3.1": {
"Microsoft.AspNetCore.Connections.Abstractions": {
"type": "Direct",
"requested": "[3.1.4, )",
"resolved": "3.1.4",
"contentHash": "3F5O9gkTfK8lp9qiLkKBacNlTIKb6dGv8W7noHGb6QVw8Kt0OvSXH/hCI08Ao7GCehciI7wNA9c6lUqarLV92A==",
"requested": "[3.1.5, )",
"resolved": "3.1.5",
"contentHash": "d9QNKLjOIb+O8fW+Xolhw0ZpOP1nzJi822qthXUhZqzb1PpL/xD4tmZfeE6IRXlRmQOAKDKg38mDEDTaMPGy1w==",
"dependencies": {
"Microsoft.AspNetCore.Http.Features": "3.1.4",
"Microsoft.AspNetCore.Http.Features": "3.1.5",
"System.IO.Pipelines": "4.7.1"
}
},
"Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv": {
"type": "Direct",
"requested": "[3.1.4, )",
"resolved": "3.1.4",
"contentHash": "htKi6bBU13AxI3qsM21K0s82J43JAGPmPG/KTAvMHoFgba8/U32j2Y/4olWkFw8vRAGv302F6FnOOfe2eObfNA==",
"requested": "[3.1.5, )",
"resolved": "3.1.5",
"contentHash": "RmWkwrdmpquJa3Tvui4AhNEy+LeqeDgd85RPNjamwKNjVSUW+Yaz8n1pKPz4IiqDJ+3XfdmaLjP9TSVnXSDNuA==",
"dependencies": {
"Libuv": "1.10.0",
"Microsoft.AspNetCore.Connections.Abstractions": "3.1.4",
"Microsoft.Extensions.Logging.Abstractions": "3.1.4",
"Microsoft.Extensions.Options": "3.1.4"
"Microsoft.AspNetCore.Connections.Abstractions": "3.1.5",
"Microsoft.Extensions.Logging.Abstractions": "3.1.5",
"Microsoft.Extensions.Options": "3.1.5"
}
},
"Microsoft.Extensions.Hosting.Abstractions": {
"type": "Direct",
"requested": "[3.1.4, )",
"resolved": "3.1.4",
"contentHash": "w1Zildlb70fJ8qqysyt6HaueWBQ89qQmcSCsh/6+1TKmipU0AOjwduqY72eqHZ39j4jZYaXaoXQ/zqXZ1nYgCg==",
"requested": "[3.1.5, )",
"resolved": "3.1.5",
"contentHash": "e57iK9spITqHE7qNgC3IowzK+PK5NC2rmVY4Sz+ZoDNO24nIsgllIRbanSbt2wQz7Iy/N8Jm3C1sXqKc8zEOMQ==",
"dependencies": {
"Microsoft.Extensions.Configuration.Abstractions": "3.1.4",
"Microsoft.Extensions.DependencyInjection.Abstractions": "3.1.4",
"Microsoft.Extensions.FileProviders.Abstractions": "3.1.4",
"Microsoft.Extensions.Logging.Abstractions": "3.1.4"
"Microsoft.Extensions.Configuration.Abstractions": "3.1.5",
"Microsoft.Extensions.DependencyInjection.Abstractions": "3.1.5",
"Microsoft.Extensions.FileProviders.Abstractions": "3.1.5",
"Microsoft.Extensions.Logging.Abstractions": "3.1.5"
}
},
"System.IO.Pipelines": {
@ -46,7 +46,7 @@
"type": "Direct",
"requested": "[1.0.2, )",
"resolved": "1.0.2",
"contentHash": "rd7gUFhwKb9Pd5ehhsUUdZiGS/AQQ1v0UItP2J+EYIfKzq7H54yDQ509qcBmbNtr6zTz7AAax4zRUcg3j9mfyQ=="
"contentHash": "oMnRfnRHzfboCS/SXUrrqbDVtM/9h5LkHkB8GuyUq70BYkJRza7CNZxLR+F6IKOTNDcDO68VVCID4DA5Sj8c4Q=="
},
"Libuv": {
"type": "Transitive",
@ -58,58 +58,106 @@
},
"Microsoft.AspNetCore.Http.Features": {
"type": "Transitive",
"resolved": "3.1.4",
"contentHash": "HroyqnPK+g/GF+W3oLFQ2CfKS7BO/vzKhcgRAz3bovf3F/c3vR5Qw8AJEi0c+UVxyIhbFp00CdNR53Ghj+qckA==",
"resolved": "3.1.5",
"contentHash": "I+G1L5363H2oCdMxHv2vtbluRgb4e33Gv6zJd8Uj93bBRFbE4MZlb3cB9PvRAYpSB0xbK216/qRtHmQJBzWIcg==",
"dependencies": {
"Microsoft.Extensions.Primitives": "3.1.4",
"Microsoft.Extensions.Primitives": "3.1.5",
"System.IO.Pipelines": "4.7.1"
}
},
"Microsoft.Extensions.Configuration.Abstractions": {
"type": "Transitive",
"resolved": "3.1.4",
"contentHash": "k7IJME4US5S5JFOGYaei5TLwutp8IqUvcBWtliKXETGn/JScmCgfej21xq5+ttxi0qZhiyJY06y9dw+cLh3kiQ==",
"resolved": "3.1.5",
"contentHash": "VBcAk6s9izZr04WCzNqOh1Sxz2RbVSh0G79MfpHSDv16cUJtSEYEHody9ZnF71LBEktzdu6cvDFBOFMh43q0iA==",
"dependencies": {
"Microsoft.Extensions.Primitives": "3.1.4"
"Microsoft.Extensions.Primitives": "3.1.5"
}
},
"Microsoft.Extensions.DependencyInjection.Abstractions": {
"type": "Transitive",
"resolved": "3.1.4",
"contentHash": "AceHamXNKDMDwIoZqEoApLp8s3935wSC3VXrPaRWa0wWOaEcYdDlo1nWQ1zLiezoDmpJzV7FqDm53E0Ty/hEMg=="
"resolved": "3.1.5",
"contentHash": "2VSCj2TZPMdeEi279Lawi6qJQu4+sEWizSOYrhY6hapyS1jxn1jVUZT1Ugv68bya+x8+3lD4+RqhUZql9PhISQ=="
},
"Microsoft.Extensions.FileProviders.Abstractions": {
"type": "Transitive",
"resolved": "3.1.4",
"contentHash": "NNJA8JAoIaxlnb/bdQ8N0kA4T9ZaBAaUFM79pnT7j/x61Wne6K4lznU9u+NDgSAB3wrSx94mz169jNtle7KrSA==",
"resolved": "3.1.5",
"contentHash": "LrEQ97jhSWw84Y1m+CJfvh9qTUUswt27au54QYn2x5PCMPPgR+yAv/4VTJKMGSSI9T4scSLBXZ/fVhT4fPTCtA==",
"dependencies": {
"Microsoft.Extensions.Primitives": "3.1.4"
"Microsoft.Extensions.Primitives": "3.1.5"
}
},
"Microsoft.Extensions.Logging.Abstractions": {
"type": "Transitive",
"resolved": "3.1.4",
"contentHash": "JNPxhw2XwhjfGFyIkA5eBfzUDPNpa6Q50HJ2F6lCAMoSa1GquAktTrl4PhEyTYFNmu09B0E90WhYsUb3kmSkOA=="
"resolved": "3.1.5",
"contentHash": "ZvwowjRSWXewdPI+whPFXgwF4Qme6Q9KV9SCPEITSGiqHLArct7q5hTBtTzj3GPsVLjTqehvTg6Bd/EQk9JS0A=="
},
"Microsoft.Extensions.Options": {
"type": "Transitive",
"resolved": "3.1.4",
"contentHash": "ntWmD8i6UmAo0nn5MiCXIVl3+75aybVHgP/NxL9B16zwsbGkSfs+66BullsGEDNvrimgIFVDO+iB/h0yWfATWg==",
"resolved": "3.1.5",
"contentHash": "f+JT/7lkKBMp/Ak2tVjO+TD7o+UoCfjnExkZNn0PZIso8kIXrqNy6x42Lrxf4Q0pW3JMf9ExmL2EQlvk2XnFAg==",
"dependencies": {
"Microsoft.Extensions.DependencyInjection.Abstractions": "3.1.4",
"Microsoft.Extensions.Primitives": "3.1.4"
"Microsoft.Extensions.DependencyInjection.Abstractions": "3.1.5",
"Microsoft.Extensions.Primitives": "3.1.5"
}
},
"Microsoft.Extensions.Primitives": {
"type": "Transitive",
"resolved": "3.1.4",
"contentHash": "tLR9n5ltwA56nr1t5M6q5IBfGLXtMS+XgumtqVENmtPQOWUD+m0Kgo1U6GWr06Y875WUN3sOGnmqkvW4an7fYA=="
"resolved": "3.1.5",
"contentHash": "6bLdjSAQix82oP2tsuX9MM2yjgUFFOkSZYyRSKoUULilw2cg0Y0H+dnugwYlfj8Jd7yjd/+QSdNBqEyYhTYv0w=="
},
"Microsoft.NETCore.Platforms": {
"type": "Transitive",
"resolved": "1.0.1",
"contentHash": "2G6OjjJzwBfNOO8myRV/nFrbTw5iA+DEm0N+qUqhrOmaVtn4pC77h38I1jsXGw5VH55+dPfQsqHD0We9sCl9FQ=="
}
},
".NETCoreApp,Version=v3.1/linux-x64": {
"ZLib.Bindings": {
"type": "Direct",
"requested": "[1.0.2, )",
"resolved": "1.0.2",
"contentHash": "oMnRfnRHzfboCS/SXUrrqbDVtM/9h5LkHkB8GuyUq70BYkJRza7CNZxLR+F6IKOTNDcDO68VVCID4DA5Sj8c4Q=="
},
"Libuv": {
"type": "Transitive",
"resolved": "1.10.0",
"contentHash": "GsCf4q+eyaI49rCPlgYxdxa1SQCysXFFdSJWdstrwxytg4+VPYLYrXD4AT2rjHVJ+UF7SSWX9CapWEYaU4ejVQ==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.0.1"
}
}
},
".NETCoreApp,Version=v3.1/osx-x64": {
"ZLib.Bindings": {
"type": "Direct",
"requested": "[1.0.2, )",
"resolved": "1.0.2",
"contentHash": "oMnRfnRHzfboCS/SXUrrqbDVtM/9h5LkHkB8GuyUq70BYkJRza7CNZxLR+F6IKOTNDcDO68VVCID4DA5Sj8c4Q=="
},
"Libuv": {
"type": "Transitive",
"resolved": "1.10.0",
"contentHash": "GsCf4q+eyaI49rCPlgYxdxa1SQCysXFFdSJWdstrwxytg4+VPYLYrXD4AT2rjHVJ+UF7SSWX9CapWEYaU4ejVQ==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.0.1"
}
}
},
".NETCoreApp,Version=v3.1/win-x64": {
"ZLib.Bindings": {
"type": "Direct",
"requested": "[1.0.2, )",
"resolved": "1.0.2",
"contentHash": "oMnRfnRHzfboCS/SXUrrqbDVtM/9h5LkHkB8GuyUq70BYkJRza7CNZxLR+F6IKOTNDcDO68VVCID4DA5Sj8c4Q=="
},
"Libuv": {
"type": "Transitive",
"resolved": "1.10.0",
"contentHash": "GsCf4q+eyaI49rCPlgYxdxa1SQCysXFFdSJWdstrwxytg4+VPYLYrXD4AT2rjHVJ+UF7SSWX9CapWEYaU4ejVQ==",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.0.1"
}
}
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,28 @@
using Server.Gumps;
namespace Server.Commands
{
public class CAGCategory : CAGNode
{
private static CAGCategory m_Root;
public CAGCategory(string title, CAGCategory parent = null)
{
Title = title;
Parent = parent;
}
public override string Title { get; }
public CAGNode[] Nodes { get; set; }
public CAGCategory Parent { get; }
public static CAGCategory Root => m_Root ??= CAGLoader.Load();
public override void OnClick(Mobile from, int page)
{
from.SendGump(new CategorizedAddGump(from, this));
}
}
}

View file

@ -0,0 +1,68 @@
using System.Collections.Generic;
using System.IO;
using System.Text.Json.Serialization;
using Server.Json;
namespace Server.Commands
{
public static class CAGLoader
{
public static CAGCategory Load()
{
var root = new CAGCategory("Add Menu");
var path = Path.Combine(Core.BaseDirectory, "Data/objects.json");
List<CAGJson> list = JsonConfig.Deserialize<List<CAGJson>>(path);
// Not an optimized solution
foreach (var cag in list)
{
var parent = root;
// Navigate through the dot notation categories until we find the last one
var categories = cag.Category.Split(".");
for (int i = 0; i < categories.Length; i++)
{
var category = categories[i];
var oldParent = parent;
for (int j = 0; j < parent.Nodes.Length; j++)
{
var node = parent.Nodes[i];
if (category == node.Title && node is CAGCategory cat)
{
parent = cat;
break;
}
}
if (parent == oldParent)
parent = new CAGCategory(category, parent);
}
// Set the objects associated with the child most node
parent.Nodes = new CAGNode[cag.Objects.Length];
for (int i = 0; i < cag.Objects.Length; i++)
{
var obj = cag.Objects[i];
obj.Parent = parent;
parent.Nodes[i] = obj;
}
}
return root;
}
}
public class CAGJson
{
public CAGJson()
{
}
[JsonPropertyName("category")]
public string Category { get; set; }
[JsonPropertyName("objects")]
public CAGObject[] Objects { get; set; }
}
}

View file

@ -0,0 +1,8 @@
namespace Server.Commands
{
public abstract class CAGNode
{
public abstract string Title { get; }
public abstract void OnClick(Mobile from, int page);
}
}

View file

@ -0,0 +1,40 @@
using System;
using System.Text.Json.Serialization;
using Server.Gumps;
namespace Server.Commands
{
public class CAGObject : CAGNode
{
public CAGObject()
{
}
[JsonPropertyName("type")]
public Type Type { get; set; }
[JsonPropertyName("gfx")]
public int ItemID { get; set; }
[JsonPropertyName("hue")]
public int? Hue { get; set; }
public CAGCategory Parent { get; set; }
public override string Title => Type == null ? "bad type" : Type.Name;
public override void OnClick(Mobile from, int page)
{
if (Type == null)
{
from.SendMessage("That is an invalid type name.");
}
else
{
CommandSystem.Handle(from, $"{CommandSystem.Prefix}Add {Type.Name}");
from.SendGump(new CategorizedAddGump(from, Parent, page));
}
}
}
}

View file

@ -1,15 +1,15 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Xml;
using Server.Items;
using Server.Json;
using Server.Utilities;
namespace Server.Commands
{
public class Categorization
public static class Categorization
{
private static CategoryEntry m_RootItems, m_RootMobiles;
@ -50,95 +50,87 @@ namespace Server.Commands
{
CategoryEntry root = new CategoryEntry(null, "Add Menu", new[] { Items, Mobiles });
Export(root, "Data/objects.xml", "Objects");
List<CategoryEntry> ceList = new List<CategoryEntry>();
ceList.AddRange(root.SubCategories);
Export(ceList, "Data/objects.json");
e.Mobile.SendMessage("Categorization menu rebuilt.");
}
public static void Export(CategoryEntry ce, string fileName, string title)
public static void Export(List<CategoryEntry> ceList, string fileName)
{
XmlTextWriter xml = new XmlTextWriter(fileName, Encoding.UTF8);
List<CAGJson> list = new List<CAGJson>();
foreach (var ce in ceList)
RecurseExport(list, ce, null);
xml.Indentation = 1;
xml.IndentChar = '\t';
xml.Formatting = Formatting.Indented;
xml.WriteStartDocument(true);
RecurseExport(xml, ce);
xml.Flush();
xml.Close();
JsonConfig.Serialize(fileName, list);
}
public static void RecurseExport(XmlTextWriter xml, CategoryEntry ce)
public static void RecurseExport(List<CAGJson> list, CategoryEntry ce, string category)
{
xml.WriteStartElement("category");
category = string.IsNullOrWhiteSpace(category) ? ce.Title : $"{category}{ce.Title}";
xml.WriteAttributeString("title", ce.Title);
if (ce.Matched.Count > 0)
list.Add(new CAGJson
{
Category = category,
Objects = ce.Matched.Select(cte =>
{
if (cte.Object is Item item)
{
int itemID = item.ItemID;
if (item is BaseAddon addon && addon.Components.Count == 1)
itemID = addon.Components[0].ItemID;
if (itemID > TileData.MaxItemValue)
itemID = 1;
int? hue = item.Hue & 0x7FFF;
if ((hue & 0x4000) != 0)
hue = 0;
return new CAGObject
{
Type = cte.Type,
ItemID = itemID,
Hue = hue == 0 ? null : hue
};
}
if (cte.Object is Mobile m)
{
int itemID = ShrinkTable.Lookup(m, 1);
int? hue = m.Hue & 0x7FFF;
if ((hue & 0x4000) != 0)
hue = 0;
return new CAGObject
{
Type = cte.Type,
ItemID = itemID,
Hue = hue == 0 ? null : hue
};
}
throw new InvalidCastException($"Categorization Type Entry: {cte.Type.Name} is not a valid type.");
}).ToArray()
});
List<CategoryEntry> subCats = new List<CategoryEntry>(ce.SubCategories);
subCats.Sort(new CategorySorter());
for (int i = 0; i < subCats.Count; ++i)
RecurseExport(xml, subCats[i]);
ce.Matched.Sort(new CategoryTypeSorter());
for (int i = 0; i < ce.Matched.Count; ++i)
for (int i = 0; i < subCats.Count; i++)
{
CategoryTypeEntry cte = ce.Matched[i];
xml.WriteStartElement("object");
xml.WriteAttributeString("type", cte.Type.ToString());
if (cte.Object is Item item)
{
int itemID = item.ItemID;
if (item is BaseAddon addon && addon.Components.Count == 1)
itemID = addon.Components[0].ItemID;
if (itemID > TileData.MaxItemValue)
itemID = 1;
xml.WriteAttributeString("gfx", XmlConvert.ToString(itemID));
int hue = item.Hue & 0x7FFF;
if ((hue & 0x4000) != 0)
hue = 0;
if (hue != 0)
xml.WriteAttributeString("hue", XmlConvert.ToString(hue));
item.Delete();
}
else if (cte.Object is Mobile mob)
{
int itemID = ShrinkTable.Lookup(mob, 1);
xml.WriteAttributeString("gfx", XmlConvert.ToString(itemID));
int hue = mob.Hue & 0x7FFF;
if ((hue & 0x4000) != 0)
hue = 0;
if (hue != 0)
xml.WriteAttributeString("hue", XmlConvert.ToString(hue));
mob.Delete();
}
xml.WriteEndElement();
var subCat = subCats[i];
RecurseExport(list, subCat, category);
}
xml.WriteEndElement();
}
public static void Load()
{
List<Type> types = new List<Type>();
@ -156,17 +148,15 @@ namespace Server.Commands
{
CategoryLine[] lines = CategoryLine.Load(config);
if (lines.Length > 0)
{
int index = 0;
CategoryEntry root = new CategoryEntry(null, lines, ref index);
if (lines.Length <= 0) return new CategoryEntry();
Fill(root, types);
int index = 0;
CategoryEntry root = new CategoryEntry(null, lines, ref index);
return root;
}
Fill(root, types);
return root;
return new CategoryEntry();
}
private static bool IsConstructible(Type type)
@ -240,13 +230,12 @@ namespace Server.Commands
string a = x?.Title;
string b = y?.Title;
if (a == null && b == null)
return 0;
if (a == null)
return 1;
return a.CompareTo(b);
return a switch
{
null when b == null => 0,
null => 1,
_ => a.CompareTo(b)
};
}
}
@ -257,13 +246,12 @@ namespace Server.Commands
string a = x?.Type.Name;
string b = y?.Type.Name;
if (a == null && b == null)
return 0;
if (a == null)
return 1;
return a.CompareTo(b);
return a switch
{
null when b == null => 0,
null => 1,
_ => a.CompareTo(b)
};
}
}

View file

@ -1,143 +1,9 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Xml;
using Server.Commands;
using Server.Network;
namespace Server.Gumps
{
public abstract class CAGNode
{
public abstract string Caption { get; }
public abstract void OnClick(Mobile from, int page);
}
public class CAGObject : CAGNode
{
public CAGObject(CAGCategory parent, XmlTextReader xml)
{
Parent = parent;
if (xml.MoveToAttribute("type"))
Type = AssemblyHandler.FindFirstTypeForName(xml.Value, false);
if (xml.MoveToAttribute("gfx"))
ItemID = XmlConvert.ToInt32(xml.Value);
if (xml.MoveToAttribute("hue"))
Hue = XmlConvert.ToInt32(xml.Value);
}
public Type Type { get; }
public int ItemID { get; }
public int Hue { get; }
public CAGCategory Parent { get; }
public override string Caption => Type == null ? "bad type" : Type.Name;
public override void OnClick(Mobile from, int page)
{
if (Type == null)
{
from.SendMessage("That is an invalid type name.");
}
else
{
CommandSystem.Handle(from, $"{CommandSystem.Prefix}Add {Type.Name}");
from.SendGump(new CategorizedAddGump(from, Parent, page));
}
}
}
public class CAGCategory : CAGNode
{
private static CAGCategory m_Root;
private CAGCategory()
{
Title = "no data";
Nodes = Array.Empty<CAGNode>();
}
public CAGCategory(CAGCategory parent, XmlTextReader xml)
{
Parent = parent;
if (xml.MoveToAttribute("title"))
Title = xml.Value;
else
Title = "empty";
if (Title == "Docked")
Title = "Docked 2";
if (xml.IsEmptyElement)
{
Nodes = Array.Empty<CAGNode>();
}
else
{
List<CAGNode> nodes = new List<CAGNode>();
while (xml.Read() && xml.NodeType != XmlNodeType.EndElement)
if (xml.NodeType == XmlNodeType.Element && xml.Name == "object")
{
nodes.Add(new CAGObject(this, xml));
}
else if (xml.NodeType == XmlNodeType.Element && xml.Name == "category")
{
if (!xml.IsEmptyElement)
nodes.Add(new CAGCategory(this, xml));
}
else
{
xml.Skip();
}
Nodes = nodes.ToArray();
}
}
public string Title { get; }
public CAGNode[] Nodes { get; }
public CAGCategory Parent { get; }
public override string Caption => Title;
public static CAGCategory Root => m_Root ?? (m_Root = Load("Data/objects.xml"));
public override void OnClick(Mobile from, int page)
{
from.SendGump(new CategorizedAddGump(from, this));
}
public static CAGCategory Load(string path)
{
if (File.Exists(path))
{
XmlTextReader xml = new XmlTextReader(path) { WhitespaceHandling = WhitespaceHandling.None };
while (xml.Read())
if (xml.Name == "category" && xml.NodeType == XmlNodeType.Element)
{
CAGCategory cat = new CAGCategory(null, xml);
xml.Close();
return cat;
}
}
return new CAGCategory();
}
}
public class CategorizedAddGump : Gump
{
public static bool OldStyle = PropsConfig.OldStyle;
@ -266,7 +132,7 @@ namespace Server.Gumps
EntryGumpID);
AddHtml(x + TextOffsetX, y + (EntryHeight - 20) / 2, emptyWidth - TextOffsetX, EntryHeight,
$"<center>{m_Category.Caption}</center>");
$"<center>{m_Category.Title}</center>");
x += emptyWidth + OffsetSize;
@ -305,7 +171,7 @@ namespace Server.Gumps
AddImageTiled(x, y, EntryWidth, EntryHeight, EntryGumpID);
AddLabelCropped(x + TextOffsetX, y + (EntryHeight - 20) / 2, EntryWidth - TextOffsetX, EntryHeight, TextHue,
node.Caption);
node.Title);
x += EntryWidth + OffsetSize;

View file

@ -11,7 +11,7 @@ using Server.Utilities;
namespace Server.Commands
{
public class DecorateMag
public static class DecorateMag
{
private static Mobile m_Mobile;
private static int m_Count;

View file

@ -5,30 +5,28 @@ using System.Linq;
using System.Text.Json;
using System.Text.Json.Serialization;
using Server.Items;
using Server.Json;
namespace Server.Commands
{
public struct Location
{
[JsonPropertyName("point"), JsonConverter(typeof(Point3DConverter))]
public Point3D Pos { get; set; }
[JsonPropertyName("map"), JsonConverter(typeof(MapConverter))]
public Map Map { get; set; }
public override string ToString() => $"({Map.Name}:{Pos.X},{Pos.Y},{Pos.Z})";
public override int GetHashCode() => ToString().GetHashCode();
}
public struct TeleporterDefinition
{
[JsonPropertyName("source")]
public Location Source { get; set; }
[JsonPropertyName("destination")]
public Location Destination { get; set; }
[JsonPropertyName("src")]
public WorldLocation Source { get; set; }
[JsonPropertyName("dst")]
public WorldLocation Destination { get; set; }
[JsonPropertyName("back")]
public bool Back { get; set; }
public override string ToString() => $"{{{Source},{Destination},{Back}}}";
public override int GetHashCode() => ToString().GetHashCode();
public bool Equals(TeleporterDefinition other) =>
Source.Equals(other.Source) && Destination.Equals(other.Destination) && Back == other.Back;
public override bool Equals(object obj) => obj is TeleporterDefinition other && Equals(other);
public override int GetHashCode() => HashCode.Combine(Source, Destination, Back);
}
public static class GenTeleporter
@ -124,11 +122,11 @@ namespace Server.Commands
private static bool IsWithinZ(int delta) => delta >= -12 && delta <= 12;
public static int DeleteTeleporters(Location location)
public static int DeleteTeleporters(WorldLocation worldLocation)
{
IPooledEnumerable<Teleporter> eable = location.Map.GetItemsInRange<Teleporter>(location.Pos, 0);
IPooledEnumerable<Teleporter> eable = worldLocation.Map.GetItemsInRange<Teleporter>(worldLocation, 0);
var items = eable
.Where(x => !(x is KeywordTeleporter || x is SkillTeleporter) && IsWithinZ(x.Z - location.Pos.Z));
.Where(x => !(x is KeywordTeleporter || x is SkillTeleporter) && IsWithinZ(x.Z - worldLocation.Z));
int count = 0;
foreach (var item in items)
{
@ -143,11 +141,11 @@ namespace Server.Commands
{
DelCount += DeleteTeleporters(telDef.Source);
Count++;
new Teleporter(telDef.Destination.Pos, telDef.Destination.Map).MoveToWorld(telDef.Source.Pos, telDef.Source.Map);
new Teleporter(telDef.Destination, telDef.Destination.Map).MoveToWorld(telDef.Source, telDef.Source.Map);
if (!telDef.Back) return;
DelCount += DeleteTeleporters(telDef.Destination);
Count++;
new Teleporter(telDef.Source.Pos, telDef.Source.Map).MoveToWorld(telDef.Destination.Pos, telDef.Destination.Map);
new Teleporter(telDef.Source, telDef.Source.Map).MoveToWorld(telDef.Destination, telDef.Destination.Map);
}
}
}

View file

@ -36,11 +36,7 @@ namespace Server.Engines.Spawners
return;
}
JsonSerializerOptions options = new JsonSerializerOptions();
options.Converters.Add(new MapConverterFactory());
options.Converters.Add(new Point3DConverterFactory());
options.Converters.Add(new TimeSpanConverterFactory());
options.Converters.Add(new TextDefinitionConverterFactory());
JsonSerializerOptions options = JsonConfig.GetOptions(new TextDefinitionConverterFactory());
for (int i = 0; i < files.Length; i++)
{

View file

@ -1,38 +0,0 @@
using System.Xml;
namespace Server.Gumps
{
public class ChildNode : IGoNode
{
public ChildNode(XmlTextReader xml, ParentNode parent)
{
Parent = parent;
Parse(xml);
}
public ParentNode Parent { get; }
public string Name { get; private set; }
public Point3D Location { get; private set; }
private void Parse(XmlTextReader xml)
{
Name = xml.MoveToAttribute("name") ? xml.Value : "empty";
int x = 0, y = 0, z = 0;
if (xml.MoveToAttribute("x"))
x = Utility.ToInt32(xml.Value);
if (xml.MoveToAttribute("y"))
y = Utility.ToInt32(xml.Value);
if (xml.MoveToAttribute("z"))
z = Utility.ToInt32(xml.Value);
Location = new Point3D(x, y, z);
}
}
}

View file

@ -0,0 +1,18 @@
using System.Text.Json.Serialization;
namespace Server.Gumps
{
public class GoCategory
{
public GoCategory Parent { get; set; }
[JsonPropertyName("locations")]
public GoLocation[] Locations { get; set; }
[JsonPropertyName("categories")]
public GoCategory[] Categories { get; set; }
[JsonPropertyName("name")]
public string Name { get; set; }
}
}

View file

@ -4,11 +4,12 @@ namespace Server.Gumps
{
public class GoGump : Gump
{
public static readonly LocationTree Felucca = new LocationTree("felucca.xml", Map.Felucca);
public static readonly LocationTree Trammel = new LocationTree("trammel.xml", Map.Trammel);
public static readonly LocationTree Ilshenar = new LocationTree("ilshenar.xml", Map.Ilshenar);
public static readonly LocationTree Malas = new LocationTree("malas.xml", Map.Malas);
public static readonly LocationTree Tokuno = new LocationTree("tokuno.xml", Map.Tokuno);
private static LocationTree Felucca;
private static LocationTree Trammel;
private static LocationTree Ilshenar;
private static LocationTree Malas;
private static LocationTree Tokuno;
private static LocationTree TerMur;
public static bool OldStyle = PropsConfig.OldStyle;
@ -61,16 +62,43 @@ namespace Server.Gumps
private static readonly int BackWidth = BorderSize + TotalWidth + BorderSize;
private static readonly int BackHeight = BorderSize + TotalHeight + BorderSize;
private readonly ParentNode m_Node;
private readonly GoCategory m_Node;
private readonly int m_Page;
private readonly LocationTree m_Tree;
private GoGump(int page, Mobile from, LocationTree tree, ParentNode node) : base(50, 50)
public static void DisplayTo(Mobile from)
{
LocationTree tree;
if (from.Map == Map.Ilshenar)
tree = Ilshenar ??= new LocationTree("ilshenar", Map.Ilshenar);
else if (from.Map == Map.Felucca)
tree = Felucca ??= new LocationTree("felucca", Map.Felucca);
else if (from.Map == Map.Trammel)
tree = Trammel ??= new LocationTree("trammel", Map.Trammel);
else if (from.Map == Map.Malas)
tree = Malas ??= new LocationTree("malas", Map.Malas);
else if (from.Map == Map.Tokuno)
tree = Tokuno ??= new LocationTree("tokuno", Map.Tokuno);
else
tree = TerMur ??= new LocationTree("termur", Map.TerMur);
if (!tree.LastBranch.TryGetValue(from, out GoCategory branch))
branch = tree.Root;
if (branch != null)
from.SendGump(new GoGump(0, from, tree, branch));
}
private GoGump(int page, Mobile from, LocationTree tree, GoCategory node) : base(50, 50)
{
from.CloseGump<GoGump>();
tree.LastBranch[from] = node;
if (node == tree.Root)
tree.LastBranch.Remove(from);
else
tree.LastBranch[from] = node;
m_Page = page;
m_Tree = tree;
@ -79,7 +107,7 @@ namespace Server.Gumps
int x = BorderSize + OffsetSize;
int y = BorderSize + OffsetSize;
int count = node.Children.Length - page * EntryCount;
int count = node.Categories.Length + node.Locations.Length - page * EntryCount;
if (count < 0)
count = 0;
@ -138,7 +166,7 @@ namespace Server.Gumps
if (!OldStyle)
AddImageTiled(x, y, NextWidth, EntryHeight, HeaderGumpID);
if ((page + 1) * EntryCount < node.Children.Length)
if ((page + 1) * EntryCount < node.Categories.Length + node.Locations.Length)
{
AddButton(x + NextOffsetX, y + NextOffsetY, NextButtonID1, NextButtonID2, 3, GumpButtonType.Reply, 1);
@ -146,13 +174,14 @@ namespace Server.Gumps
AddLabel(x + NextLabelOffsetX, y + NextLabelOffsetY, TextHue, "Next");
}
for (int i = 0, index = page * EntryCount; i < EntryCount && index < node.Children.Length; ++i, ++index)
int totalEntryCount = node.Categories.Length + node.Locations.Length;
for (int i = 0, index = page * EntryCount; i < EntryCount && index < totalEntryCount; ++i, ++index)
{
x = BorderSize + OffsetSize;
y += EntryHeight + OffsetSize;
IGoNode child = node.Children[index];
string name = child.Name;
string name = index >= node.Categories.Length ? node.Locations[index].Name : node.Categories[index].Name;
AddImageTiled(x, y, EntryWidth, EntryHeight, EntryGumpID);
AddLabelCropped(x + TextOffsetX, y, EntryWidth - TextOffsetX, EntryHeight, TextHue, name);
@ -166,28 +195,6 @@ namespace Server.Gumps
}
}
public static void DisplayTo(Mobile from)
{
LocationTree tree;
if (from.Map == Map.Ilshenar)
tree = Ilshenar;
else if (from.Map == Map.Felucca)
tree = Felucca;
else if (from.Map == Map.Trammel)
tree = Trammel;
else if (from.Map == Map.Malas)
tree = Malas;
else
tree = Tokuno;
if (!tree.LastBranch.TryGetValue(from, out ParentNode branch))
branch = tree.Root;
if (branch != null)
from.SendGump(new GoGump(0, from, tree, branch));
}
public override void OnResponse(NetState state, RelayInfo info)
{
Mobile from = state.Mobile;
@ -210,7 +217,7 @@ namespace Server.Gumps
}
case 3:
{
if ((m_Page + 1) * EntryCount < m_Node.Children.Length)
if ((m_Page + 1) * EntryCount < m_Node.Categories.Length + m_Node.Locations.Length)
from.SendGump(new GoGump(m_Page + 1, from, m_Tree, m_Node));
break;
@ -219,14 +226,18 @@ namespace Server.Gumps
{
int index = info.ButtonID - 4;
if (index >= 0 && index < m_Node.Children.Length)
{
IGoNode o = m_Node.Children[index];
if (index < 0)
break;
if (o is ParentNode node)
from.SendGump(new GoGump(0, from, m_Tree, node));
else
from.MoveToWorld(((ChildNode)o).Location, m_Tree.Map);
if (index < m_Node.Categories.Length)
{
from.SendGump(new GoGump(0, from, m_Tree, m_Node.Categories[index]));
}
else
{
index -= m_Node.Categories.Length;
if (index < m_Node.Locations.Length)
from.MoveToWorld(m_Node.Locations[index].Location, m_Tree.Map);
}
break;

View file

@ -0,0 +1,15 @@
using System.Text.Json.Serialization;
namespace Server.Gumps
{
public class GoLocation
{
public GoCategory Parent { get; set; }
[JsonPropertyName("name")]
public string Name { get; set; }
[JsonPropertyName("location")]
public Point3D Location { get; set; }
}
}

View file

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Xml;
using Server.Json;
namespace Server.Gumps
{
@ -8,34 +9,50 @@ namespace Server.Gumps
{
public LocationTree(string fileName, Map map)
{
LastBranch = new Dictionary<Mobile, ParentNode>();
LastBranch = new Dictionary<Mobile, GoCategory>();
Map = map;
string path = Path.Combine("Data/Locations/", fileName);
string path = Path.Combine($"Data/Locations/{fileName}.json");
if (File.Exists(path))
if (!File.Exists(path))
{
XmlTextReader xml = new XmlTextReader(new StreamReader(path)) { WhitespaceHandling = WhitespaceHandling.None };
Console.WriteLine("Go Locations: {0} does not exist", path);
return;
}
Root = Parse(xml);
xml.Close();
try
{
Root = JsonConfig.Deserialize<GoCategory>(path);
SetParents(Root);
}
catch (Exception e)
{
Console.WriteLine("Go Locations: Error in deserializing {0}", path);
Console.WriteLine(e);
}
}
public Dictionary<Mobile, ParentNode> LastBranch { get; }
public Dictionary<Mobile, GoCategory> LastBranch { get; }
public Map Map { get; }
public ParentNode Root { get; }
public GoCategory Root { get; }
private ParentNode Parse(XmlTextReader xml)
private static void SetParents(GoCategory parent)
{
xml.Read();
xml.Read();
xml.Read();
// Deserialization may leave these null
parent.Categories ??= Array.Empty<GoCategory>();
parent.Locations ??= Array.Empty<GoLocation>();
return new ParentNode(xml, null);
for (int i = 0; i < parent.Categories.Length; i++)
{
GoCategory category = parent.Categories[i];
category.Parent = parent;
SetParents(category);
}
for (int j = 0; j < parent.Locations.Length; j++)
parent.Locations[j].Parent = parent;
}
}
}

View file

@ -1,53 +0,0 @@
using System;
using System.Collections.Generic;
using System.Xml;
namespace Server.Gumps
{
public interface IGoNode
{
ParentNode Parent { get; }
string Name { get; }
}
public class ParentNode : IGoNode
{
public ParentNode(XmlTextReader xml, ParentNode parent)
{
Parent = parent;
Parse(xml);
}
public ParentNode Parent { get; }
public IGoNode[] Children { get; private set; }
public string Name { get; private set; }
private void Parse(XmlTextReader xml)
{
Name = xml.MoveToAttribute("name") ? xml.Value : "empty";
if (xml.IsEmptyElement)
Children = Array.Empty<IGoNode>();
else
{
List<IGoNode> children = new List<IGoNode>();
while (xml.Read() && (xml.NodeType == XmlNodeType.Element || xml.NodeType == XmlNodeType.Comment))
{
if (xml.NodeType == XmlNodeType.Comment)
continue;
if (xml.Name == "child")
children.Add(new ChildNode(xml, this));
else
children.Add(new ParentNode(xml, this));
}
Children = children.ToArray();
}
}
}
}

View file

@ -1,4 +1,5 @@
using System;
using System.Diagnostics;
using Server.Engines.VeteranRewards;
using Server.Gumps;
using Server.Multis;

View file

@ -1,15 +1,18 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Xml;
using System.Text.Json.Serialization;
using Server.Json;
namespace Server
{
public class NameList
{
public string Type { get; }
[JsonPropertyName("type")]
public string Type { get; set; }
public string[] List { get; }
[JsonPropertyName("names")]
public string[] List { get; set; }
public bool ContainsName(string name)
{
@ -20,22 +23,7 @@ namespace Server
return false;
}
public NameList(string type, XmlElement xml)
{
Type = type;
List = xml.InnerText.Split(',');
for (int i = 0; i < List.Length; ++i)
List[i] = Utility.Intern(List[i].Trim());
}
public string GetRandomName()
{
if (List.Length > 0)
return List[Utility.Random(List.Length)];
return "";
}
public string GetRandomName() => List.Length > 0 ? List[Utility.Random(List.Length)] : "";
public static NameList GetNameList(string type)
{
@ -45,53 +33,25 @@ namespace Server
public static string RandomName(string type) => GetNameList(type)?.GetRandomName() ?? "";
private static readonly Dictionary<string, NameList> m_Table;
private static readonly Dictionary<string, NameList> m_Table = new Dictionary<string, NameList>(StringComparer.OrdinalIgnoreCase);
static NameList()
public static void Configure()
{
m_Table = new Dictionary<string, NameList>(StringComparer.OrdinalIgnoreCase);
// TODO: Turn this into a command so it can be updated in-game
string filePath = Path.Combine(Core.BaseDirectory, "Data/names.json");
string filePath = Path.Combine(Core.BaseDirectory, "Data/names.xml");
if (!File.Exists(filePath))
return;
try
List<NameList> nameLists = JsonConfig.Deserialize<List<NameList>>(filePath);
foreach (var nameList in nameLists)
{
Load(filePath);
}
catch (Exception e)
{
Console.WriteLine("Warning: Exception caught loading name lists:");
Console.WriteLine(e);
nameList.FixNames();
m_Table.Add(nameList.Type, nameList);
}
}
private static void Load(string filePath)
private void FixNames()
{
XmlDocument doc = new XmlDocument();
doc.Load(filePath);
XmlElement root = doc["names"];
foreach (XmlElement element in root.GetElementsByTagName("namelist"))
{
string type = element.GetAttribute("type");
if (string.IsNullOrEmpty(type))
continue;
try
{
NameList list = new NameList(type, element);
m_Table[type] = list;
}
catch
{
// ignored
}
}
for (int i = 0; i < List.Length; i++)
List[i] = Utility.Intern(List[i].Trim());
}
}
}

View file

@ -4,7 +4,6 @@ using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using Microsoft.AspNetCore.Connections;
using Server.Network;
namespace Server.Misc
@ -70,16 +69,15 @@ namespace Server.Misc
try
{
NetState ns = e.State;
ConnectionContext s = ns.Connection;
IPEndPoint ipep = (IPEndPoint)s.LocalEndPoint;
IPEndPoint ipep = (IPEndPoint)ns.Connection.LocalEndPoint;
IPAddress localAddress = ipep.Address;
int localPort = ipep.Port;
if (IsPrivateNetwork(localAddress))
{
ipep = (IPEndPoint)s.RemoteEndPoint;
ipep = (IPEndPoint)ns.Connection.RemoteEndPoint;
if (!IsPrivateNetwork(ipep.Address) && m_PublicAddress != null)
localAddress = m_PublicAddress;
}

View file

@ -61,10 +61,12 @@
<ProjectReference Include="..\Server\Server.csproj" Private="false" PrivateAssets="All" IncludeAssets="None">
<IncludeInPackage>false</IncludeInPackage>
</ProjectReference>
<PackageReference Include="MailKit" Version="2.6.0" />
<PackageReference Include="Microsoft.AspNetCore.Connections.Abstractions" Version="3.1.4" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="3.1.4" />
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="3.1.4" />
<!-- Transient package version resolution -->
<PackageReference Include="Microsoft.AspNetCore.Connections.Abstractions" Version="3.1.5" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="3.1.5" />
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="3.1.5" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="3.1.5" />
<PackageReference Include="MailKit" Version="2.7.0" />
<PackageReference Include="Argon2.Bindings" Version="1.2.7" />
<PackageReference Include="Zlib.Bindings" Version="1.0.2" />
</ItemGroup>

File diff suppressed because it is too large Load diff