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.
This commit is contained in:
parent
23532db603
commit
0925a2d435
18 changed files with 184 additions and 958 deletions
|
|
@ -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)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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 <u>will be removed from the world</u> and placed into the server data files. " +
|
||||
"Other players <u>will not see the changes</u> unless you distribute your data files to them.<br><br>" +
|
||||
"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.<br><br>" +
|
||||
"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 <u>will be removed from the static files</u> and exchanged with unmovable dynamic items. " +
|
||||
"Other players <u>will not see the changes</u> unless you distribute your data files to them.<br><br>" +
|
||||
"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.<br><br>" +
|
||||
"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 <u>all items in {0}</u>.",
|
||||
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 <u>every item on every map</u>.",
|
||||
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<Map, Dictionary<Point2D, DeltaState>>();
|
||||
|
||||
if (start3d == NullP3D && end3d == NullP3D)
|
||||
{
|
||||
if (targetMap == null)
|
||||
{
|
||||
CommandLogging.WriteLine(
|
||||
from,
|
||||
"{0} {1} invoking freeze for every item in every map",
|
||||
from.AccessLevel,
|
||||
CommandLogging.Format(from)
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
CommandLogging.WriteLine(
|
||||
from,
|
||||
"{0} {1} invoking freeze for every item in {0}",
|
||||
from.AccessLevel,
|
||||
CommandLogging.Format(from),
|
||||
targetMap
|
||||
);
|
||||
}
|
||||
|
||||
foreach (var item in World.Items.Values)
|
||||
{
|
||||
if (targetMap != null && item.Map != targetMap)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (item.Parent != null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (item is Static or BaseFloor or BaseWall)
|
||||
{
|
||||
var itemMap = item.Map;
|
||||
|
||||
if (itemMap == null || itemMap == Map.Internal)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!mapTable.TryGetValue(itemMap, out var table))
|
||||
{
|
||||
mapTable[itemMap] = table = new Dictionary<Point2D, DeltaState>();
|
||||
}
|
||||
|
||||
var p = new Point2D(item.X >> 3, item.Y >> 3);
|
||||
|
||||
if (!table.TryGetValue(p, out var state))
|
||||
{
|
||||
table[p] = state = new DeltaState(p);
|
||||
}
|
||||
|
||||
state.m_List.Add(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (targetMap != null)
|
||||
{
|
||||
Point2D start = targetMap.Bound(new Point2D(start3d)), end = targetMap.Bound(new Point2D(end3d));
|
||||
|
||||
CommandLogging.WriteLine(
|
||||
from,
|
||||
"{0} {1} invoking freeze from {2} to {3} in {4}",
|
||||
from.AccessLevel,
|
||||
CommandLogging.Format(from),
|
||||
start,
|
||||
end,
|
||||
targetMap
|
||||
);
|
||||
|
||||
var eable =
|
||||
targetMap.GetItemsInBounds(new Rectangle2D(start.X, start.Y, end.X - start.X + 1, end.Y - start.Y + 1));
|
||||
|
||||
foreach (var item in eable)
|
||||
{
|
||||
if (item is Static or BaseFloor or BaseWall)
|
||||
{
|
||||
var itemMap = item.Map;
|
||||
|
||||
if (itemMap == null || itemMap == Map.Internal)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!mapTable.TryGetValue(itemMap, out var table))
|
||||
{
|
||||
mapTable[itemMap] = table = new Dictionary<Point2D, DeltaState>();
|
||||
}
|
||||
|
||||
var p = new Point2D(item.X >> 3, item.Y >> 3);
|
||||
|
||||
if (!table.TryGetValue(p, out var state))
|
||||
{
|
||||
table[p] = state = new DeltaState(p);
|
||||
}
|
||||
|
||||
state.m_List.Add(item);
|
||||
}
|
||||
}
|
||||
|
||||
eable.Free();
|
||||
}
|
||||
|
||||
if (mapTable.Count == 0)
|
||||
{
|
||||
from.SendGump(
|
||||
new NoticeGump(
|
||||
1060637,
|
||||
30720,
|
||||
"No freezable items were found. Only the following item types are frozen:<br> - Static<br> - BaseFloor<br> - BaseWall",
|
||||
0xFFC000,
|
||||
320,
|
||||
240
|
||||
)
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
var badDataFile = false;
|
||||
|
||||
var totalFrozen = 0;
|
||||
|
||||
foreach (var de in mapTable)
|
||||
{
|
||||
var map = de.Key;
|
||||
var table = de.Value;
|
||||
|
||||
var matrix = map.Tiles;
|
||||
|
||||
using var idxStream = OpenWrite(matrix.IndexStream);
|
||||
using var mulStream = OpenWrite(matrix.DataStream);
|
||||
if (idxStream == null || mulStream == null)
|
||||
{
|
||||
badDataFile = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
var idxReader = new BinaryReader(idxStream);
|
||||
|
||||
var idxWriter = new BinaryWriter(idxStream);
|
||||
var mulWriter = new BinaryWriter(mulStream);
|
||||
|
||||
foreach (var state in table.Values)
|
||||
{
|
||||
var oldTiles = ReadStaticBlock(
|
||||
idxReader,
|
||||
mulStream,
|
||||
state.m_X,
|
||||
state.m_Y,
|
||||
matrix.BlockWidth,
|
||||
matrix.BlockHeight,
|
||||
out var oldTileCount
|
||||
);
|
||||
|
||||
if (oldTileCount < 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var newTileCount = 0;
|
||||
var newTiles = new StaticTile[state.m_List.Count];
|
||||
|
||||
for (var i = 0; i < state.m_List.Count; ++i)
|
||||
{
|
||||
var item = state.m_List[i];
|
||||
|
||||
var xOffset = item.X - state.m_X * 8;
|
||||
var yOffset = item.Y - state.m_Y * 8;
|
||||
|
||||
if (xOffset is < 0 or >= 8 || yOffset is < 0 or >= 8)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var newTile = new StaticTile(
|
||||
(ushort)item.ItemID,
|
||||
(byte)xOffset,
|
||||
(byte)yOffset,
|
||||
(sbyte)item.Z,
|
||||
(short)item.Hue
|
||||
);
|
||||
|
||||
newTiles[newTileCount++] = newTile;
|
||||
|
||||
item.Delete();
|
||||
|
||||
++totalFrozen;
|
||||
}
|
||||
|
||||
var mulPos = -1;
|
||||
var length = -1;
|
||||
var extra = 0;
|
||||
|
||||
if (oldTileCount + newTileCount > 0)
|
||||
{
|
||||
mulWriter.Seek(0, SeekOrigin.End);
|
||||
|
||||
mulPos = (int)mulWriter.BaseStream.Position;
|
||||
length = (oldTileCount + newTileCount) * 7;
|
||||
extra = 1;
|
||||
|
||||
for (var i = 0; i < oldTileCount; ++i)
|
||||
{
|
||||
var toWrite = oldTiles[i];
|
||||
|
||||
mulWriter.Write((ushort)toWrite.ID);
|
||||
mulWriter.Write((byte)toWrite.X);
|
||||
mulWriter.Write((byte)toWrite.Y);
|
||||
mulWriter.Write((sbyte)toWrite.Z);
|
||||
mulWriter.Write((short)toWrite.Hue);
|
||||
}
|
||||
|
||||
for (var i = 0; i < newTileCount; ++i)
|
||||
{
|
||||
var toWrite = newTiles[i];
|
||||
|
||||
mulWriter.Write((ushort)toWrite.ID);
|
||||
mulWriter.Write((byte)toWrite.X);
|
||||
mulWriter.Write((byte)toWrite.Y);
|
||||
mulWriter.Write((sbyte)toWrite.Z);
|
||||
mulWriter.Write((short)toWrite.Hue);
|
||||
}
|
||||
|
||||
mulWriter.Flush();
|
||||
}
|
||||
|
||||
var idxPos = (state.m_X * matrix.BlockHeight + state.m_Y) * 12;
|
||||
|
||||
idxWriter.Seek(idxPos, SeekOrigin.Begin);
|
||||
idxWriter.Write(mulPos);
|
||||
idxWriter.Write(length);
|
||||
idxWriter.Write(extra);
|
||||
|
||||
idxWriter.Flush();
|
||||
|
||||
matrix.SetStaticBlock(state.m_X, state.m_Y, null);
|
||||
}
|
||||
}
|
||||
|
||||
if (totalFrozen == 0 && badDataFile)
|
||||
{
|
||||
from.SendGump(
|
||||
new NoticeGump(
|
||||
1060637,
|
||||
30720,
|
||||
"Output data files could not be opened and the freeze operation has been aborted.<br><br>This probably means your server and client are using the same data files. Instructions on how to resolve this can be found in the first warning window.",
|
||||
0xFFC000,
|
||||
320,
|
||||
240
|
||||
)
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
from.SendGump(
|
||||
new NoticeGump(
|
||||
1060637,
|
||||
30720,
|
||||
$"Freeze operation completed successfully.<br><br>{totalFrozen} item{(totalFrozen != 1 ? "s were" : " was")} frozen.<br><br>You must restart your client and update it's data files to see the changes.",
|
||||
0xFFC000,
|
||||
320,
|
||||
240
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
[Usage("Unfreeze")]
|
||||
[Description("Makes a targeted area of static items dynamic.")]
|
||||
public static void Unfreeze_OnCommand(CommandEventArgs e)
|
||||
{
|
||||
var from = e.Mobile;
|
||||
BoundingBoxPicker.Begin(from, (map, start, end) => UnfreezeBox_Callback(from, map, start, end));
|
||||
}
|
||||
|
||||
[Usage("UnfreezeMap")]
|
||||
[Description("Makes every static item in your map dynamic.")]
|
||||
public static void UnfreezeMap_OnCommand(CommandEventArgs e)
|
||||
{
|
||||
var map = e.Mobile.Map;
|
||||
|
||||
if (map != null && map != Map.Internal)
|
||||
{
|
||||
SendWarning(
|
||||
e.Mobile,
|
||||
"You are about to unfreeze <u>all items in {0}</u>.",
|
||||
BaseUnfreezeWarning,
|
||||
map,
|
||||
NullP3D,
|
||||
NullP3D,
|
||||
UnfreezeWarning_Callback
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
[Usage("UnfreezeWorld")]
|
||||
[Description("Makes every static item on all maps dynamic.")]
|
||||
public static void UnfreezeWorld_OnCommand(CommandEventArgs e)
|
||||
{
|
||||
SendWarning(
|
||||
e.Mobile,
|
||||
"You are about to unfreeze <u>every item on every map</u>.",
|
||||
BaseUnfreezeWarning,
|
||||
null,
|
||||
NullP3D,
|
||||
NullP3D,
|
||||
UnfreezeWarning_Callback
|
||||
);
|
||||
}
|
||||
|
||||
private static void UnfreezeBox_Callback(Mobile from, Map map, Point3D start, Point3D end)
|
||||
{
|
||||
SendWarning(
|
||||
from,
|
||||
"You are about to unfreeze a section of items.",
|
||||
BaseUnfreezeWarning,
|
||||
map,
|
||||
start,
|
||||
end,
|
||||
UnfreezeWarning_Callback
|
||||
);
|
||||
}
|
||||
|
||||
private static void UnfreezeWarning_Callback(Mobile from, bool okay, StateInfo si)
|
||||
{
|
||||
if (!okay)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Unfreeze(from, si.m_Map, si.m_Start, si.m_End);
|
||||
}
|
||||
|
||||
private static void DoUnfreeze(Map map, Point2D start, Point2D end, ref bool badDataFile, ref int totalUnfrozen)
|
||||
{
|
||||
start = map.Bound(start);
|
||||
end = map.Bound(end);
|
||||
|
||||
var xStartBlock = start.X >> 3;
|
||||
var yStartBlock = start.Y >> 3;
|
||||
var xEndBlock = end.X >> 3;
|
||||
var yEndBlock = end.Y >> 3;
|
||||
|
||||
int xTileStart = start.X, yTileStart = start.Y;
|
||||
int xTileWidth = end.X - start.X + 1, yTileHeight = end.Y - start.Y + 1;
|
||||
|
||||
var matrix = map.Tiles;
|
||||
|
||||
using var idxStream = OpenWrite(matrix.IndexStream);
|
||||
using var mulStream = OpenWrite(matrix.DataStream);
|
||||
if (idxStream == null || mulStream == null)
|
||||
{
|
||||
badDataFile = true;
|
||||
return;
|
||||
}
|
||||
|
||||
var idxReader = new BinaryReader(idxStream);
|
||||
|
||||
var idxWriter = new BinaryWriter(idxStream);
|
||||
var mulWriter = new BinaryWriter(mulStream);
|
||||
|
||||
for (var x = xStartBlock; x <= xEndBlock; ++x)
|
||||
{
|
||||
for (var y = yStartBlock; y <= yEndBlock; ++y)
|
||||
{
|
||||
var oldTiles = ReadStaticBlock(
|
||||
idxReader,
|
||||
mulStream,
|
||||
x,
|
||||
y,
|
||||
matrix.BlockWidth,
|
||||
matrix.BlockHeight,
|
||||
out var oldTileCount
|
||||
);
|
||||
|
||||
if (oldTileCount < 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var newTileCount = 0;
|
||||
var newTiles = new StaticTile[oldTileCount];
|
||||
|
||||
int baseX = (x << 3) - xTileStart, baseY = (y << 3) - yTileStart;
|
||||
|
||||
for (var i = 0; i < oldTileCount; ++i)
|
||||
{
|
||||
var oldTile = oldTiles[i];
|
||||
|
||||
var px = baseX + oldTile.X;
|
||||
var py = baseY + oldTile.Y;
|
||||
|
||||
if (px < 0 || px >= xTileWidth || py < 0 || py >= yTileHeight)
|
||||
{
|
||||
newTiles[newTileCount++] = oldTile;
|
||||
}
|
||||
else
|
||||
{
|
||||
++totalUnfrozen;
|
||||
|
||||
Item item = new Static(oldTile.ID);
|
||||
|
||||
item.Hue = oldTile.Hue;
|
||||
|
||||
item.MoveToWorld(new Point3D(px + xTileStart, py + yTileStart, oldTile.Z), map);
|
||||
}
|
||||
}
|
||||
|
||||
var mulPos = -1;
|
||||
var length = -1;
|
||||
var extra = 0;
|
||||
|
||||
if (newTileCount > 0)
|
||||
{
|
||||
mulWriter.Seek(0, SeekOrigin.End);
|
||||
|
||||
mulPos = (int)mulWriter.BaseStream.Position;
|
||||
length = newTileCount * 7;
|
||||
extra = 1;
|
||||
|
||||
for (var i = 0; i < newTileCount; ++i)
|
||||
{
|
||||
var toWrite = newTiles[i];
|
||||
|
||||
mulWriter.Write((ushort)toWrite.ID);
|
||||
mulWriter.Write((byte)toWrite.X);
|
||||
mulWriter.Write((byte)toWrite.Y);
|
||||
mulWriter.Write((sbyte)toWrite.Z);
|
||||
mulWriter.Write((short)toWrite.Hue);
|
||||
}
|
||||
|
||||
mulWriter.Flush();
|
||||
}
|
||||
|
||||
var idxPos = (x * matrix.BlockHeight + y) * 12;
|
||||
|
||||
idxWriter.Seek(idxPos, SeekOrigin.Begin);
|
||||
idxWriter.Write(mulPos);
|
||||
idxWriter.Write(length);
|
||||
idxWriter.Write(extra);
|
||||
|
||||
idxWriter.Flush();
|
||||
|
||||
matrix.SetStaticBlock(x, y, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void DoUnfreeze(Map map, ref bool badDataFile, ref int totalUnfrozen)
|
||||
{
|
||||
DoUnfreeze(map, Point2D.Zero, new Point2D(map.Width - 1, map.Height - 1), ref badDataFile, ref totalUnfrozen);
|
||||
}
|
||||
|
||||
public static void Unfreeze(Mobile from, Map map, Point3D start, Point3D end)
|
||||
{
|
||||
var totalUnfrozen = 0;
|
||||
var badDataFile = false;
|
||||
|
||||
if (map == null)
|
||||
{
|
||||
CommandLogging.WriteLine(
|
||||
from,
|
||||
"{0} {1} invoking unfreeze for every item in every map",
|
||||
from.AccessLevel,
|
||||
CommandLogging.Format(from)
|
||||
);
|
||||
|
||||
DoUnfreeze(Map.Felucca, ref badDataFile, ref totalUnfrozen);
|
||||
DoUnfreeze(Map.Trammel, ref badDataFile, ref totalUnfrozen);
|
||||
DoUnfreeze(Map.Ilshenar, ref badDataFile, ref totalUnfrozen);
|
||||
DoUnfreeze(Map.Malas, ref badDataFile, ref totalUnfrozen);
|
||||
DoUnfreeze(Map.Tokuno, ref badDataFile, ref totalUnfrozen);
|
||||
}
|
||||
else if (start == NullP3D && end == NullP3D)
|
||||
{
|
||||
CommandLogging.WriteLine(
|
||||
from,
|
||||
"{0} {1} invoking unfreeze for every item in {2}",
|
||||
from.AccessLevel,
|
||||
CommandLogging.Format(from),
|
||||
map
|
||||
);
|
||||
|
||||
DoUnfreeze(map, ref badDataFile, ref totalUnfrozen);
|
||||
}
|
||||
else
|
||||
{
|
||||
CommandLogging.WriteLine(
|
||||
from,
|
||||
"{0} {1} invoking unfreeze from {2} to {3} in {4}",
|
||||
from.AccessLevel,
|
||||
CommandLogging.Format(from),
|
||||
new Point2D(start),
|
||||
new Point2D(end),
|
||||
map
|
||||
);
|
||||
|
||||
DoUnfreeze(map, new Point2D(start), new Point2D(end), ref badDataFile, ref totalUnfrozen);
|
||||
}
|
||||
|
||||
if (totalUnfrozen == 0 && badDataFile)
|
||||
{
|
||||
from.SendGump(
|
||||
new NoticeGump(
|
||||
1060637,
|
||||
30720,
|
||||
"Output data files could not be opened and the unfreeze operation has been aborted.<br><br>This probably means your server and client are using the same data files. Instructions on how to resolve this can be found in the first warning window.",
|
||||
0xFFC000,
|
||||
320,
|
||||
240
|
||||
)
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
from.SendGump(
|
||||
new NoticeGump(
|
||||
1060637,
|
||||
30720,
|
||||
$"Unfreeze operation completed successfully.<br><br>{totalUnfrozen} item{(totalUnfrozen != 1 ? "s were" : " was")} unfrozen.<br><br>You must restart your client and update it's data files to see the changes.",
|
||||
0xFFC000,
|
||||
320,
|
||||
240
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private static FileStream OpenWrite(FileStream orig)
|
||||
{
|
||||
if (orig == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
return new FileStream(orig.Name, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static StaticTile[] ReadStaticBlock(
|
||||
BinaryReader idxReader, FileStream mulStream, int x, int y, int width,
|
||||
int height, out int count
|
||||
)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (x < 0 || x >= width || y < 0 || y >= height)
|
||||
{
|
||||
count = -1;
|
||||
return m_TileBuffer;
|
||||
}
|
||||
|
||||
idxReader.BaseStream.Seek((x * height + y) * 12, SeekOrigin.Begin);
|
||||
|
||||
var lookup = idxReader.ReadInt32();
|
||||
var length = idxReader.ReadInt32();
|
||||
|
||||
if (lookup < 0 || length <= 0)
|
||||
{
|
||||
count = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
count = length / 7;
|
||||
|
||||
mulStream.Seek(lookup, SeekOrigin.Begin);
|
||||
|
||||
if (m_TileBuffer.Length < count)
|
||||
{
|
||||
m_TileBuffer = new StaticTile[count];
|
||||
}
|
||||
|
||||
var staTiles = m_TileBuffer;
|
||||
|
||||
if (m_Buffer == null || length > m_Buffer.Length)
|
||||
{
|
||||
m_Buffer = GC.AllocateUninitializedArray<byte>(length);
|
||||
}
|
||||
|
||||
mulStream.Read(m_Buffer, 0, length);
|
||||
|
||||
var index = 0;
|
||||
|
||||
for (var i = 0; i < count; ++i)
|
||||
{
|
||||
staTiles[i]
|
||||
.Set(
|
||||
(ushort)(m_Buffer[index++] | (m_Buffer[index++] << 8)),
|
||||
m_Buffer[index++],
|
||||
m_Buffer[index++],
|
||||
(sbyte)m_Buffer[index++],
|
||||
(short)(m_Buffer[index++] | (m_Buffer[index++] << 8))
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
count = -1;
|
||||
}
|
||||
|
||||
return m_TileBuffer;
|
||||
}
|
||||
|
||||
private class DeltaState
|
||||
{
|
||||
public readonly List<Item> m_List;
|
||||
public readonly int m_X;
|
||||
public readonly int m_Y;
|
||||
|
||||
public DeltaState(Point2D p)
|
||||
{
|
||||
m_X = p.X;
|
||||
m_Y = p.Y;
|
||||
m_List = new List<Item>();
|
||||
}
|
||||
}
|
||||
|
||||
public class StateInfo
|
||||
{
|
||||
public Map m_Map;
|
||||
public Point3D m_Start, m_End;
|
||||
|
||||
public StateInfo(Map map, Point3D start, Point3D end)
|
||||
{
|
||||
m_Map = map;
|
||||
m_Start = start;
|
||||
m_End = end;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -95,7 +95,7 @@ namespace Server
|
|||
foreach (var m in eable)
|
||||
{
|
||||
if (from.CanBeHarmful(m, false) &&
|
||||
m.InLOS(new Point3D(origin, origin.Z + 1)) &&
|
||||
m.InLOS(new Point3D(origin.X, origin.Y, origin.Z + 1)) &&
|
||||
Faction.Find(m) != null)
|
||||
{
|
||||
targets.Add(from);
|
||||
|
|
@ -118,7 +118,7 @@ namespace Server
|
|||
}
|
||||
|
||||
Effects.SendMovingEffect(
|
||||
new Entity(Serial.Zero, new Point3D(origin, origin.Z + 4), facet),
|
||||
new Entity(Serial.Zero, new Point3D(origin.X, origin.Y, origin.Z + 4), facet),
|
||||
mob,
|
||||
14068,
|
||||
1,
|
||||
|
|
|
|||
|
|
@ -261,16 +261,6 @@ namespace Server.Gumps
|
|||
AddButtonLabeled(20, 225, GetButtonID(3, 104), "Doors");
|
||||
AddButtonLabeled(220, 225, GetButtonID(3, 105), "Signs");
|
||||
|
||||
AddHtml(20, 275, 400, 30, Color(Center("Statics"), LabelColor32));
|
||||
|
||||
AddButtonLabeled(20, 300, GetButtonID(3, 110), "Freeze (Target)");
|
||||
AddButtonLabeled(20, 325, GetButtonID(3, 111), "Freeze (World)");
|
||||
AddButtonLabeled(20, 350, GetButtonID(3, 112), "Freeze (Map)");
|
||||
|
||||
AddButtonLabeled(220, 300, GetButtonID(3, 120), "Unfreeze (Target)");
|
||||
AddButtonLabeled(220, 325, GetButtonID(3, 121), "Unfreeze (World)");
|
||||
AddButtonLabeled(220, 350, GetButtonID(3, 122), "Unfreeze (Map)");
|
||||
|
||||
goto case AdminGumpPage.Administer;
|
||||
}
|
||||
case AdminGumpPage.Administer_Server:
|
||||
|
|
|
|||
|
|
@ -115,7 +115,7 @@ namespace Server.Gumps
|
|||
{
|
||||
case 1: // Current location
|
||||
{
|
||||
toSet = new Point2D(m_Mobile.Location);
|
||||
toSet = new Point2D(m_Mobile.Location.X, m_Mobile.Location.Y);
|
||||
shouldSet = true;
|
||||
shouldSend = true;
|
||||
|
||||
|
|
@ -194,12 +194,13 @@ namespace Server.Gumps
|
|||
|
||||
protected override void OnTarget(Mobile from, object targeted)
|
||||
{
|
||||
if (targeted is IPoint3D p)
|
||||
if (targeted is IPoint3D point3D)
|
||||
{
|
||||
try
|
||||
{
|
||||
CommandLogging.LogChangeProperty(m_Mobile, m_Object, m_Property.Name, new Point2D(p).ToString());
|
||||
m_Property.SetValue(m_Object, new Point2D(p), null);
|
||||
var p = new Point2D(point3D.X, point3D.Y);
|
||||
CommandLogging.LogChangeProperty(m_Mobile, m_Object, m_Property.Name, p.ToString());
|
||||
m_Property.SetValue(m_Object, p, null);
|
||||
m_PropertiesGump.OnValueChanged(m_Object, m_Property);
|
||||
}
|
||||
catch
|
||||
|
|
|
|||
|
|
@ -320,7 +320,7 @@ namespace Server.Items
|
|||
|
||||
if (floorZ > int.MinValue && item.Z < floorZ + 15) // Confirmed : no height checks here
|
||||
{
|
||||
item.Location = new Point3D(item.Location, item.Z + 1);
|
||||
item.Location = new Point3D(item.Location.X, item.Location.Y, item.Z + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -334,7 +334,7 @@ namespace Server.Items
|
|||
|
||||
if (floorZ > int.MinValue && item.Z > GetFloorZ(item))
|
||||
{
|
||||
item.Location = new Point3D(item.Location, item.Z - 1);
|
||||
item.Location = new Point3D(item.Location.X, item.Location.Y, item.Z - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
|
|
@ -176,7 +176,7 @@ namespace Server.Multis
|
|||
{
|
||||
if (ip is Item item)
|
||||
{
|
||||
ip = item.GetWorldTop();
|
||||
ip = from;
|
||||
}
|
||||
|
||||
var p = new Point3D(ip);
|
||||
|
|
|
|||
|
|
@ -194,29 +194,31 @@ namespace Server.Multis
|
|||
|
||||
protected override void OnTarget(Mobile from, object o)
|
||||
{
|
||||
if (o is IPoint3D ip)
|
||||
if (o is not IPoint3D ip)
|
||||
{
|
||||
if (ip is Item item)
|
||||
{
|
||||
ip = item.GetWorldTop();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
var p = new Point3D(ip);
|
||||
Point3D p = ip switch
|
||||
{
|
||||
Item item => item.GetWorldTop(),
|
||||
Mobile m => m.Location,
|
||||
_ => new Point3D(ip)
|
||||
};
|
||||
|
||||
var region = Region.Find(p, from.Map);
|
||||
var region = Region.Find(p, from.Map);
|
||||
|
||||
if (region.IsPartOf<DungeonRegion>())
|
||||
{
|
||||
from.SendLocalizedMessage(502488); // You can not place a ship inside a dungeon.
|
||||
}
|
||||
else if (region.IsPartOf<HouseRegion>() || region.IsPartOf<ChampionSpawnRegion>())
|
||||
{
|
||||
from.SendLocalizedMessage(1042549); // A boat may not be placed in this area.
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Model.OnPlacement(from, p);
|
||||
}
|
||||
if (region.IsPartOf<DungeonRegion>())
|
||||
{
|
||||
from.SendLocalizedMessage(502488); // You can not place a ship inside a dungeon.
|
||||
}
|
||||
else if (region.IsPartOf<HouseRegion>() || region.IsPartOf<ChampionSpawnRegion>())
|
||||
{
|
||||
from.SendLocalizedMessage(1042549); // A boat may not be placed in this area.
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Model.OnPlacement(from, p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,41 +11,41 @@ namespace Server.Multis.Deeds
|
|||
|
||||
protected override void OnTarget(Mobile from, object o)
|
||||
{
|
||||
if (o is IPoint3D ip)
|
||||
if (o is not IPoint3D ip)
|
||||
{
|
||||
if (ip is Item item)
|
||||
{
|
||||
ip = item.GetWorldTop();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
var p = new Point3D(ip);
|
||||
Point3D p = ip switch
|
||||
{
|
||||
Item item => item.GetWorldTop(),
|
||||
Mobile m => m.Location,
|
||||
_ => new Point3D(ip)
|
||||
};
|
||||
|
||||
var reg = Region.Find(new Point3D(p), from.Map);
|
||||
var reg = Region.Find(p, from.Map);
|
||||
|
||||
if (from.AccessLevel >= AccessLevel.GameMaster || reg.AllowHousing(from, p))
|
||||
{
|
||||
m_Deed.OnPlacement(from, p);
|
||||
}
|
||||
else if (reg.IsPartOf<TempNoHousingRegion>())
|
||||
{
|
||||
from.SendLocalizedMessage(
|
||||
501270
|
||||
); // Lord British has decreed a 'no build' period, thus you cannot build this house at this time.
|
||||
}
|
||||
else if (reg.IsPartOf<TreasureRegion>() || reg.IsPartOf<HouseRegion>())
|
||||
{
|
||||
from.SendLocalizedMessage(
|
||||
1043287
|
||||
); // The house could not be created here. Either something is blocking the house, or the house would not be on valid terrain.
|
||||
}
|
||||
else if (reg.IsPartOf<HouseRaffleRegion>())
|
||||
{
|
||||
from.SendLocalizedMessage(1150493); // You must have a deed for this plot of land in order to build here.
|
||||
}
|
||||
else
|
||||
{
|
||||
from.SendLocalizedMessage(501265); // Housing can not be created in this area.
|
||||
}
|
||||
if (from.AccessLevel >= AccessLevel.GameMaster || reg.AllowHousing(from, p))
|
||||
{
|
||||
m_Deed.OnPlacement(from, p);
|
||||
}
|
||||
else if (reg.IsPartOf<TempNoHousingRegion>())
|
||||
{
|
||||
// Lord British has decreed a 'no build' period, thus you cannot build this house at this time.
|
||||
from.SendLocalizedMessage(501270);
|
||||
}
|
||||
else if (reg.IsPartOf<TreasureRegion>() || reg.IsPartOf<HouseRegion>())
|
||||
{
|
||||
// The house could not be created here. Either something is blocking the house, or the house would not be on valid terrain.
|
||||
from.SendLocalizedMessage(1043287);
|
||||
}
|
||||
else if (reg.IsPartOf<HouseRaffleRegion>())
|
||||
{
|
||||
from.SendLocalizedMessage(1150493); // You must have a deed for this plot of land in order to build here.
|
||||
}
|
||||
else
|
||||
{
|
||||
from.SendLocalizedMessage(501265); // Housing can not be created in this area.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -184,9 +184,8 @@ namespace Server.Multis.Deeds
|
|||
case HousePlacementResult.BadStatic:
|
||||
case HousePlacementResult.BadRegionHidden:
|
||||
{
|
||||
from.SendLocalizedMessage(
|
||||
1043287
|
||||
); // The house could not be created here. Either something is blocking the house, or the house would not be on valid terrain.
|
||||
// The house could not be created here. Either something is blocking the house, or the house would not be on valid terrain.
|
||||
from.SendLocalizedMessage(1043287);
|
||||
break;
|
||||
}
|
||||
case HousePlacementResult.NoSurface:
|
||||
|
|
@ -203,16 +202,14 @@ namespace Server.Multis.Deeds
|
|||
}
|
||||
case HousePlacementResult.BadRegionTemp:
|
||||
{
|
||||
from.SendLocalizedMessage(
|
||||
501270
|
||||
); // Lord British has decreed a 'no build' period, thus you cannot build this house at this time.
|
||||
// Lord British has decreed a 'no build' period, thus you cannot build this house at this time.
|
||||
from.SendLocalizedMessage(501270);
|
||||
break;
|
||||
}
|
||||
case HousePlacementResult.BadRegionRaffle:
|
||||
{
|
||||
from.SendLocalizedMessage(
|
||||
1150493
|
||||
); // You must have a deed for this plot of land in order to build here.
|
||||
// You must have a deed for this plot of land in order to build here.
|
||||
from.SendLocalizedMessage(1150493);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -250,46 +250,46 @@ namespace Server.Items
|
|||
|
||||
protected override void OnTarget(Mobile from, object o)
|
||||
{
|
||||
if (o is not IPoint3D ip)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!from.CheckAlive() || from.Backpack?.FindItemByType<HousePlacementTool>() == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (o is IPoint3D ip)
|
||||
Point3D p = ip switch
|
||||
{
|
||||
if (ip is Item item)
|
||||
{
|
||||
ip = item.GetWorldTop();
|
||||
}
|
||||
Item item => item.GetWorldTop(),
|
||||
Mobile m => m.Location,
|
||||
_ => new Point3D(ip)
|
||||
};
|
||||
|
||||
var p = new Point3D(ip);
|
||||
var reg = Region.Find(p, from.Map);
|
||||
|
||||
var reg = Region.Find(new Point3D(p), from.Map);
|
||||
|
||||
if (from.AccessLevel >= AccessLevel.GameMaster || reg.AllowHousing(from, p))
|
||||
{
|
||||
m_Placed = m_Entry.OnPlacement(from, p);
|
||||
}
|
||||
else if (reg.IsPartOf<TempNoHousingRegion>())
|
||||
{
|
||||
from.SendLocalizedMessage(
|
||||
501270
|
||||
); // Lord British has decreed a 'no build' period, thus you cannot build this house at this time.
|
||||
}
|
||||
else if (reg.IsPartOf<TreasureRegion>() || reg.IsPartOf<HouseRegion>())
|
||||
{
|
||||
from.SendLocalizedMessage(
|
||||
1043287
|
||||
); // The house could not be created here. Either something is blocking the house, or the house would not be on valid terrain.
|
||||
}
|
||||
else if (reg.IsPartOf<HouseRaffleRegion>())
|
||||
{
|
||||
from.SendLocalizedMessage(1150493); // You must have a deed for this plot of land in order to build here.
|
||||
}
|
||||
else
|
||||
{
|
||||
from.SendLocalizedMessage(501265); // Housing can not be created in this area.
|
||||
}
|
||||
if (from.AccessLevel >= AccessLevel.GameMaster || reg.AllowHousing(from, p))
|
||||
{
|
||||
m_Placed = m_Entry.OnPlacement(from, p);
|
||||
}
|
||||
else if (reg.IsPartOf<TempNoHousingRegion>())
|
||||
{
|
||||
// Lord British has decreed a 'no build' period, thus you cannot build this house at this time.
|
||||
from.SendLocalizedMessage(501270);
|
||||
}
|
||||
else if (reg.IsPartOf<TreasureRegion>() || reg.IsPartOf<HouseRegion>())
|
||||
{
|
||||
// The house could not be created here. Either something is blocking the house, or the house would not be on valid terrain.
|
||||
from.SendLocalizedMessage(1043287);
|
||||
}
|
||||
else if (reg.IsPartOf<HouseRaffleRegion>())
|
||||
{
|
||||
from.SendLocalizedMessage(1150493); // You must have a deed for this plot of land in order to build here.
|
||||
}
|
||||
else
|
||||
{
|
||||
from.SendLocalizedMessage(501265); // Housing can not be created in this area.
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -155,9 +155,7 @@ namespace Server.Items
|
|||
return;
|
||||
}
|
||||
|
||||
var m = m_Mobile;
|
||||
|
||||
if (m.Location != m_Teleporter.Location || m.Map != m_Teleporter.Map)
|
||||
if (m_Mobile.Location != m_Teleporter.Location || m_Mobile.Map != m_Teleporter.Map)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
@ -165,11 +163,11 @@ namespace Server.Items
|
|||
var p = target.GetWorldTop();
|
||||
var map = target.Map;
|
||||
|
||||
BaseCreature.TeleportPets(m, p, map);
|
||||
BaseCreature.TeleportPets(m_Mobile, p, map);
|
||||
|
||||
m.MoveToWorld(p, map);
|
||||
m_Mobile.MoveToWorld(p, map);
|
||||
|
||||
if (m.Hidden && m.AccessLevel != AccessLevel.Player)
|
||||
if (m_Mobile.Hidden && m_Mobile.AccessLevel != AccessLevel.Player)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,41 +12,45 @@ namespace Server.Targets
|
|||
|
||||
protected override void OnTarget(Mobile from, object o)
|
||||
{
|
||||
if (o is IPoint3D p)
|
||||
if (o is not IPoint3D ip)
|
||||
{
|
||||
if (!BaseCommand.IsAccessible(from, m_Object))
|
||||
{
|
||||
from.SendLocalizedMessage(500447); // That is not accessible.
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (p is Item pItem)
|
||||
{
|
||||
p = pItem.GetWorldTop();
|
||||
}
|
||||
if (!BaseCommand.IsAccessible(from, m_Object))
|
||||
{
|
||||
from.SendLocalizedMessage(500447); // That is not accessible.
|
||||
return;
|
||||
}
|
||||
|
||||
CommandLogging.WriteLine(
|
||||
from,
|
||||
"{0} {1} moving {2} to {3}",
|
||||
from.AccessLevel,
|
||||
CommandLogging.Format(from),
|
||||
CommandLogging.Format(m_Object),
|
||||
new Point3D(p)
|
||||
);
|
||||
Point3D p = ip switch
|
||||
{
|
||||
Item i => i.GetWorldTop(),
|
||||
Mobile m => m.Location,
|
||||
_ => new Point3D(ip)
|
||||
};
|
||||
|
||||
if (m_Object is Item item)
|
||||
CommandLogging.WriteLine(
|
||||
from,
|
||||
"{0} {1} moving {2} to {3}",
|
||||
from.AccessLevel,
|
||||
CommandLogging.Format(from),
|
||||
CommandLogging.Format(m_Object),
|
||||
p
|
||||
);
|
||||
|
||||
if (m_Object is Item item)
|
||||
{
|
||||
if (!item.Deleted)
|
||||
{
|
||||
if (!item.Deleted)
|
||||
{
|
||||
item.MoveToWorld(new Point3D(p), from.Map);
|
||||
}
|
||||
item.MoveToWorld(p, from.Map);
|
||||
}
|
||||
else if (m_Object is Mobile m)
|
||||
}
|
||||
else if (m_Object is Mobile m)
|
||||
{
|
||||
if (!m.Deleted)
|
||||
{
|
||||
if (!m.Deleted)
|
||||
{
|
||||
m.MoveToWorld(new Point3D(p), from.Map);
|
||||
}
|
||||
m.MoveToWorld(p, from.Map);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue