From 0925a2d435fbd793b9f681fbcd9ff9e1a3d4a46c Mon Sep 17 00:00:00 2001
From: Kamron Batman <3953314+kamronbatman@users.noreply.github.com>
Date: Sun, 20 Mar 2022 23:15:59 -0700
Subject: [PATCH] fix: Cleans up Point checks and removes statics (#966)
- [X] Removes static freezing/unfreezing. Use other tools for this.
- [X] Cleans up IPoint3D allocations
- [X] Removes IPoint3D constructors since the compiler may not optimize the constructor path and allow allocations.
Note: Instead of `new Point3D(m)`, do something like `new Point3D(m.Location)`. Sorry for the inconvenience. In the long run this will prevent abuse of hot paths that will cause performance issues.
---
Projects/Server/Geometry/Point2D.cs | 2 +-
Projects/Server/Geometry/Point3D.cs | 8 +-
Projects/Server/Maps/Map.cs | 14 +-
Projects/Server/Regions/Region.cs | 4 +-
.../UOContent/Commands/BoundingBoxPicker.cs | 14 +-
.../Commands/Generic/Commands/Commands.cs | 16 +-
.../Commands/Object Creation/AddGump.cs | 24 +-
Projects/UOContent/Commands/Statics.cs | 780 ------------------
.../Items/Power Faction Items/StormsEye.cs | 4 +-
Projects/UOContent/Gumps/AdminGump.cs | 10 -
.../UOContent/Gumps/Props/SetPoint2DGump.cs | 9 +-
.../UOContent/Items/Misc/InteriorDecorator.cs | 4 +-
.../UOContent/Multis/Boats/BaseBoatDeed.cs | 2 +-
.../UOContent/Multis/Boats/BaseDockedBoat.cs | 40 +-
Projects/UOContent/Multis/Deeds.cs | 77 +-
.../Multis/Houses/HousePlacementTool.cs | 64 +-
.../Multis/Houses/HouseTeleporter.cs | 10 +-
Projects/UOContent/Targets/MoveTarget.cs | 60 +-
18 files changed, 184 insertions(+), 958 deletions(-)
delete mode 100644 Projects/UOContent/Commands/Statics.cs
diff --git a/Projects/Server/Geometry/Point2D.cs b/Projects/Server/Geometry/Point2D.cs
index 8e42236d3..0f1dba7d2 100644
--- a/Projects/Server/Geometry/Point2D.cs
+++ b/Projects/Server/Geometry/Point2D.cs
@@ -47,7 +47,7 @@ namespace Server
m_Y = y;
}
- public Point2D(IPoint2D p) : this(p.X, p.Y)
+ public Point2D(Point2D p) : this(p.X, p.Y)
{
}
diff --git a/Projects/Server/Geometry/Point3D.cs b/Projects/Server/Geometry/Point3D.cs
index 80588ef6d..6a65b7c26 100644
--- a/Projects/Server/Geometry/Point3D.cs
+++ b/Projects/Server/Geometry/Point3D.cs
@@ -14,6 +14,7 @@
*************************************************************************/
using System;
+using System.Runtime.CompilerServices;
namespace Server
{
@@ -49,11 +50,16 @@ namespace Server
set => m_Z = value;
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
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(Point3D p) : this(p.X, p.Y, p.Z)
+ {
+ }
+
+ public Point3D(Point2D p, int z) : this(p.X, p.Y, z)
{
}
diff --git a/Projects/Server/Maps/Map.cs b/Projects/Server/Maps/Map.cs
index 7f5e87d1f..a6fcad289 100644
--- a/Projects/Server/Maps/Map.cs
+++ b/Projects/Server/Maps/Map.cs
@@ -4,6 +4,7 @@ using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
+using System.Runtime.CompilerServices;
using Server.Items;
using Server.Logging;
using Server.Network;
@@ -809,17 +810,22 @@ namespace Server
return surface;
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Bound(int x, int y, out int newX, out int newY)
{
newX = Math.Clamp(x, 0, Width - 1);
newY = Math.Clamp(y, 0, Height - 1);
}
+ public Point2D Bound(Point3D p)
+ {
+ Bound(p.m_X, p.m_Y, out var x, out var y);
+ return new Point2D(x, y);
+ }
+
public Point2D Bound(Point2D p)
{
- var x = Math.Clamp(p.m_X, 0, Width - 1);
- var y = Math.Clamp(p.m_Y, 0, Height - 1);
-
+ Bound(p.m_X, p.m_Y, out var x, out var y);
return new Point2D(x, y);
}
@@ -1086,7 +1092,7 @@ namespace Server
}
else if (o is IPoint3D d)
{
- p = new Point3D(d);
+ p = new Point3D(d.X, d.Y, d.Z);
}
else
{
diff --git a/Projects/Server/Regions/Region.cs b/Projects/Server/Regions/Region.cs
index f6a9a1ae5..01054532d 100644
--- a/Projects/Server/Regions/Region.cs
+++ b/Projects/Server/Regions/Region.cs
@@ -330,8 +330,8 @@ namespace Server
{
var rect = Area[i];
- var start = Map.Bound(new Point2D(rect.Start));
- var end = Map.Bound(new Point2D(rect.End));
+ var start = Map.Bound(new Point2D(rect.Start.X, rect.Start.Y));
+ var end = Map.Bound(new Point2D(rect.End.X, rect.Start.Y));
var startSector = Map.GetSector(start);
var endSector = Map.GetSector(end);
diff --git a/Projects/UOContent/Commands/BoundingBoxPicker.cs b/Projects/UOContent/Commands/BoundingBoxPicker.cs
index fa6c1028b..4212c87fa 100644
--- a/Projects/UOContent/Commands/BoundingBoxPicker.cs
+++ b/Projects/UOContent/Commands/BoundingBoxPicker.cs
@@ -37,20 +37,22 @@ namespace Server
protected override void OnTarget(Mobile from, object targeted)
{
- if (targeted is not IPoint3D p)
+ if (targeted is not IPoint3D ip)
{
return;
}
- if (p is Item item)
+ Point3D p = ip switch
{
- p = item.GetWorldTop();
- }
+ Item item => item.GetWorldTop(),
+ Mobile m => m.Location,
+ _ => new Point3D(ip)
+ };
if (m_First)
{
from.SendMessage("Target another location to complete the bounding box.");
- from.Target = new PickTarget(new Point3D(p), false, from.Map, m_Callback);
+ from.Target = new PickTarget(p, false, from.Map, m_Callback);
}
else if (from.Map != m_Map)
{
@@ -59,7 +61,7 @@ namespace Server
else if (m_Map != null && m_Map != Map.Internal && m_Callback != null)
{
var start = m_Store;
- var end = new Point3D(p);
+ var end = p;
Utility.FixPoints(ref start, ref end);
diff --git a/Projects/UOContent/Commands/Generic/Commands/Commands.cs b/Projects/UOContent/Commands/Generic/Commands/Commands.cs
index 944b267b1..6d8630976 100644
--- a/Projects/UOContent/Commands/Generic/Commands/Commands.cs
+++ b/Projects/UOContent/Commands/Generic/Commands/Commands.cs
@@ -554,21 +554,19 @@ namespace Server.Commands.Generic
public override void Execute(CommandEventArgs e, object obj)
{
- if (obj is not IPoint3D p)
+ if (obj is not IPoint3D ip)
{
return;
}
- if (p is Item item)
+ Point3D p = ip switch
{
- p = item.GetWorldTop();
- }
- else if (p is Mobile m)
- {
- p = m.Location;
- }
+ Item item => item.GetWorldTop(),
+ Mobile m => m.Location,
+ _ => new Point3D(ip)
+ };
- Add.Invoke(e.Mobile, new Point3D(p), new Point3D(p), e.Arguments);
+ Add.Invoke(e.Mobile, p, p, e.Arguments);
}
}
diff --git a/Projects/UOContent/Commands/Object Creation/AddGump.cs b/Projects/UOContent/Commands/Object Creation/AddGump.cs
index bf7890052..2c093052f 100644
--- a/Projects/UOContent/Commands/Object Creation/AddGump.cs
+++ b/Projects/UOContent/Commands/Object Creation/AddGump.cs
@@ -282,19 +282,21 @@ namespace Server.Gumps
protected override void OnTarget(Mobile from, object o)
{
- if (o is IPoint3D p)
+ if (o is not IPoint3D ip)
{
- p = p switch
- {
- Item item => item.GetWorldTop(),
- Mobile m => m.Location,
- _ => p
- };
-
- Commands.Add.Invoke(from, new Point3D(p), new Point3D(p), new[] { m_Type.Name });
-
- from.Target = new InternalTarget(m_Type, m_SearchResults, m_SearchString, m_Page);
+ return;
}
+
+ Point3D p = ip switch
+ {
+ Item item => item.GetWorldTop(),
+ Mobile m => m.Location,
+ _ => new Point3D(ip)
+ };
+
+ Commands.Add.Invoke(from, new Point3D(p), new Point3D(p), new[] { m_Type.Name });
+
+ from.Target = new InternalTarget(m_Type, m_SearchResults, m_SearchString, m_Page);
}
protected override void OnTargetCancel(Mobile from, TargetCancelType cancelType)
diff --git a/Projects/UOContent/Commands/Statics.cs b/Projects/UOContent/Commands/Statics.cs
deleted file mode 100644
index 8a64c3021..000000000
--- a/Projects/UOContent/Commands/Statics.cs
+++ /dev/null
@@ -1,780 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.IO;
-using Server.Commands;
-using Server.Gumps;
-using Server.Items;
-
-namespace Server
-{
- public static class Statics
- {
- public delegate void FreezeCallback(Mobile from, bool okay, StateInfo si);
-
- private const string BaseFreezeWarning = "{0} " +
- "Those items will be removed from the world and placed into the server data files. " +
- "Other players will not see the changes unless you distribute your data files to them.
" +
- "This operation may not complete unless the server and client are using different data files. " +
- "If you receive a message stating 'output data files could not be opened,' then you are probably sharing data files. " +
- "Create a new directory for the world data files (statics*.mul and staidx*.mul) and add that to Scritps/Misc/DataPath.cs.
" +
- "The change will be in effect immediately on the server, however, you must restart your client and update it's data files for the changes to become visible. " +
- "It is strongly recommended that you make backup of the data files mentioned above. " +
- "Do you wish to proceed?";
-
- private const string BaseUnfreezeWarning = "{0} " +
- "Those items will be removed from the static files and exchanged with unmovable dynamic items. " +
- "Other players will not see the changes unless you distribute your data files to them.
" +
- "This operation may not complete unless the server and client are using different data files. " +
- "If you receive a message stating 'output data files could not be opened,' then you are probably sharing data files. " +
- "Create a new directory for the world data files (statics*.mul and staidx*.mul) and add that to Scritps/Misc/DataPath.cs.
" +
- "The change will be in effect immediately on the server, however, you must restart your client and update it's data files for the changes to become visible. " +
- "It is strongly recommended that you make backup of the data files mentioned above. " +
- "Do you wish to proceed?";
-
- private static readonly Point3D NullP3D = new(int.MinValue, int.MinValue, int.MinValue);
-
- private static byte[] m_Buffer;
-
- private static StaticTile[] m_TileBuffer = new StaticTile[128];
-
- public static void Initialize()
- {
- CommandSystem.Register("Freeze", AccessLevel.Administrator, Freeze_OnCommand);
- CommandSystem.Register("FreezeMap", AccessLevel.Administrator, FreezeMap_OnCommand);
- CommandSystem.Register("FreezeWorld", AccessLevel.Administrator, FreezeWorld_OnCommand);
-
- CommandSystem.Register("Unfreeze", AccessLevel.Administrator, Unfreeze_OnCommand);
- CommandSystem.Register("UnfreezeMap", AccessLevel.Administrator, UnfreezeMap_OnCommand);
- CommandSystem.Register("UnfreezeWorld", AccessLevel.Administrator, UnfreezeWorld_OnCommand);
- }
-
- [Usage("Freeze")]
- [Description("Makes a targeted area of dynamic items static.")]
- public static void Freeze_OnCommand(CommandEventArgs e)
- {
- var from = e.Mobile;
- BoundingBoxPicker.Begin(from, (map, start, end) => FreezeBox_Callback(from, map, start, end));
- }
-
- [Usage("FreezeMap")]
- [Description("Makes every dynamic item in your map static.")]
- public static void FreezeMap_OnCommand(CommandEventArgs e)
- {
- var from = e.Mobile;
- var map = from.Map;
-
- if (map != null && map != Map.Internal)
- {
- SendWarning(
- from,
- "You are about to freeze all items in {0}.",
- BaseFreezeWarning,
- map,
- NullP3D,
- NullP3D,
- FreezeWarning_Callback
- );
- }
- }
-
- [Usage("FreezeWorld")]
- [Description("Makes every dynamic item on all maps static.")]
- public static void FreezeWorld_OnCommand(CommandEventArgs e)
- {
- SendWarning(
- e.Mobile,
- "You are about to freeze every item on every map.",
- BaseFreezeWarning,
- null,
- NullP3D,
- NullP3D,
- FreezeWarning_Callback
- );
- }
-
- public static void SendWarning(
- Mobile m, string header, string baseWarning, Map map, Point3D start, Point3D end,
- FreezeCallback callback
- )
- {
- m.SendGump(
- new WarningGump(
- 1060635,
- 30720,
- string.Format(baseWarning, string.Format(header, map)),
- 0xFFC000,
- 420,
- 400,
- okay => callback(m, okay, new StateInfo(map, start, end))
- )
- );
- }
-
- private static void FreezeBox_Callback(Mobile from, Map map, Point3D start, Point3D end)
- {
- SendWarning(
- from,
- "You are about to freeze a section of items.",
- BaseFreezeWarning,
- map,
- start,
- end,
- FreezeWarning_Callback
- );
- }
-
- private static void FreezeWarning_Callback(Mobile from, bool okay, StateInfo si)
- {
- if (!okay)
- {
- return;
- }
-
- Freeze(from, si.m_Map, si.m_Start, si.m_End);
- }
-
- public static void Freeze(Mobile from, Map targetMap, Point3D start3d, Point3D end3d)
- {
- var mapTable = new Dictionary