diff --git a/Projects/Server/Commands.cs b/Projects/Server/Commands.cs index 6819dfe91..41547f63e 100644 --- a/Projects/Server/Commands.cs +++ b/Projects/Server/Commands.cs @@ -41,6 +41,8 @@ public class CommandEventArgs public string[] Arguments { get; } + private Dictionary _context; + public int Length => Arguments.Length; public string GetString(int index) => index < 0 || index >= Arguments.Length ? "" : Arguments[index]; @@ -57,6 +59,25 @@ public class CommandEventArgs public TimeSpan GetTimeSpan(int index) => index < 0 || index >= Arguments.Length ? TimeSpan.Zero : Utility.ToTimeSpan(Arguments[index]); + + public bool GetContext(string key, out T t) + { + if (_context != null && _context.TryGetValue(key, out var value) && value is T tValue) + { + t = tValue; + return true; + } + + t = default; + return false; + } + + public T SetContext(string key, T value) + { + _context ??= new Dictionary(); + _context[key] = value; + return value; + } } public static partial class EventSink diff --git a/Projects/UOContent/Commands/DragEffects.cs b/Projects/UOContent/Commands/DragEffects.cs index dac60f8d0..4f4d2b96f 100644 --- a/Projects/UOContent/Commands/DragEffects.cs +++ b/Projects/UOContent/Commands/DragEffects.cs @@ -15,11 +15,11 @@ namespace Server.Commands { if (Mobile.DragEffects) { - e.Mobile.SendMessage($"Drag effects are currently enabled."); + e.Mobile.SendMessage("Drag effects are currently enabled."); } else { - e.Mobile.SendMessage($"Drag effects are currently disabled."); + e.Mobile.SendMessage("Drag effects are currently disabled."); } } else @@ -28,11 +28,11 @@ namespace Server.Commands if (Mobile.DragEffects) { - e.Mobile.SendMessage($"Drag effects have been enabled."); + e.Mobile.SendMessage("Drag effects have been enabled."); } else { - e.Mobile.SendMessage($"Drag effects have been disabled."); + e.Mobile.SendMessage("Drag effects have been disabled."); } } } diff --git a/Projects/UOContent/Commands/Generic/Commands/Commands.cs b/Projects/UOContent/Commands/Generic/Commands/Commands.cs index 865699db1..81d85fc0a 100644 --- a/Projects/UOContent/Commands/Generic/Commands/Commands.cs +++ b/Projects/UOContent/Commands/Generic/Commands/Commands.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Reflection; using Server.Accounting; using Server.Engines.Help; using Server.Factions; @@ -511,36 +512,39 @@ namespace Server.Commands.Generic public override bool ValidateArgs(BaseCommandImplementor impl, CommandEventArgs e) { - if (e.Length >= 1) - { - var t = AssemblyHandler.FindTypeByName(e.GetString(0)); - - if (t == null) - { - e.Mobile.SendMessage("No type with that name was found."); - - var match = e.GetString(0).Trim(); - - if (match.Length < 3) - { - e.Mobile.SendMessage("Invalid search string."); - e.Mobile.SendGump(new AddGump(match, 0, Type.EmptyTypes, false)); - } - else - { - e.Mobile.SendGump(new AddGump(match, 0, AddGump.Match(match), true)); - } - } - else - { - return true; - } - } - else + if (e.Length < 1) { e.Mobile.SendGump(new CategorizedAddGump(e.Mobile)); + return false; } + var match = e.GetString(0).Trim(); + if (e.GetContext("exactMatch", out var exactMatch)) + { + return true; + } + + exactMatch = AddGump.ExactMatch(match); + if (exactMatch != null) + { + e.SetContext("exactMatch", exactMatch); + return true; + } + + if (match.Length < 3) + { + e.Mobile.SendMessage("Invalid search string."); + e.Mobile.SendGump(new AddGump(match, 0, [], false)); + return false; + } + + if (!e.GetContext("matches", out var matches)) + { + matches = e.SetContext("matches", AddGump.MatchEmptyCtor(match)); + } + + e.Mobile.SendMessage("No type with that name was found."); + e.Mobile.SendGump(new AddGump(match, 0, matches, true)); return false; } @@ -558,7 +562,13 @@ namespace Server.Commands.Generic _ => new Point3D(ip) }; - Add.Invoke(e.Mobile, p, p, e.Arguments); + if (e.GetContext("exactMatch", out var exactMatch)) + { + Add.Invoke(e.Mobile, p, p, exactMatch, e.Arguments.AsSpan(1)); + return; + } + + e.Mobile.SendMessage("No type with that name was found."); } } diff --git a/Projects/UOContent/Commands/Generic/Implementors/BaseCommandImplementor.cs b/Projects/UOContent/Commands/Generic/Implementors/BaseCommandImplementor.cs index bce4737a3..a8cae3741 100644 --- a/Projects/UOContent/Commands/Generic/Implementors/BaseCommandImplementor.cs +++ b/Projects/UOContent/Commands/Generic/Implementors/BaseCommandImplementor.cs @@ -213,8 +213,6 @@ namespace Server.Commands.Generic public void RunCommand(Mobile from, object obj, BaseCommand command, string[] args) { - // try - // { var e = new CommandEventArgs(from, command.Commands[0], GenerateArgString(args), args); if (!command.ValidateArgs(this, e)) @@ -256,11 +254,6 @@ namespace Server.Commands.Generic } command.Flush(from, flushToLog); - // } - // catch ( Exception ex ) - // { - // from.SendMessage( ex.Message ); - // } } public virtual void Process(Mobile from, BaseCommand command, string[] args) diff --git a/Projects/UOContent/Commands/Generic/Implementors/SingleCommandImplementor.cs b/Projects/UOContent/Commands/Generic/Implementors/SingleCommandImplementor.cs index 3220cd28b..033cb73f5 100644 --- a/Projects/UOContent/Commands/Generic/Implementors/SingleCommandImplementor.cs +++ b/Projects/UOContent/Commands/Generic/Implementors/SingleCommandImplementor.cs @@ -36,7 +36,7 @@ namespace Server.Commands.Generic { e.Mobile.SendMessage("You do not have access to that command."); } - else if (command.ValidateArgs(this, e)) + else { Process(e.Mobile, command, e.Arguments); } diff --git a/Projects/UOContent/Commands/Handlers.cs b/Projects/UOContent/Commands/Handlers.cs index e98ab1084..cfeb8bd5a 100644 --- a/Projects/UOContent/Commands/Handlers.cs +++ b/Projects/UOContent/Commands/Handlers.cs @@ -665,11 +665,11 @@ namespace Server.Commands if (m.AutoPageNotify) { - m.SendMessage($"Your auto-page-notify has been turned on."); + m.SendMessage("Your auto-page-notify has been turned on."); } else { - m.SendMessage($"Your auto-page-notify has been turned off."); + m.SendMessage("Your auto-page-notify has been turned off."); } } diff --git a/Projects/UOContent/Commands/Object Creation/Add.cs b/Projects/UOContent/Commands/Object Creation/Add.cs index 240d8dbd4..b34af5bac 100644 --- a/Projects/UOContent/Commands/Object Creation/Add.cs +++ b/Projects/UOContent/Commands/Object Creation/Add.cs @@ -3,697 +3,761 @@ using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Text; +using Server.Gumps; using Server.Items; +using Server.Text; using static Server.Attributes; using static Server.Types; -namespace Server.Commands -{ - public static class Add - { - public static void Configure() - { - CommandSystem.Register("Tile", AccessLevel.GameMaster, Tile_OnCommand); - CommandSystem.Register("TileRXYZ", AccessLevel.GameMaster, TileRXYZ_OnCommand); - CommandSystem.Register("TileXYZ", AccessLevel.GameMaster, TileXYZ_OnCommand); - CommandSystem.Register("TileZ", AccessLevel.GameMaster, TileZ_OnCommand); - CommandSystem.Register("TileAvg", AccessLevel.GameMaster, TileAvg_OnCommand); +namespace Server.Commands; - CommandSystem.Register("Outline", AccessLevel.GameMaster, Outline_OnCommand); - CommandSystem.Register("OutlineRXYZ", AccessLevel.GameMaster, OutlineRXYZ_OnCommand); - CommandSystem.Register("OutlineXYZ", AccessLevel.GameMaster, OutlineXYZ_OnCommand); - CommandSystem.Register("OutlineZ", AccessLevel.GameMaster, OutlineZ_OnCommand); - CommandSystem.Register("OutlineAvg", AccessLevel.GameMaster, OutlineAvg_OnCommand); +public static class Add +{ + public static void Configure() + { + CommandSystem.Register("Tile", AccessLevel.GameMaster, Tile_OnCommand); + CommandSystem.Register("TileRXYZ", AccessLevel.GameMaster, TileRXYZ_OnCommand); + CommandSystem.Register("TileXYZ", AccessLevel.GameMaster, TileXYZ_OnCommand); + CommandSystem.Register("TileZ", AccessLevel.GameMaster, TileZ_OnCommand); + CommandSystem.Register("TileAvg", AccessLevel.GameMaster, TileAvg_OnCommand); + + CommandSystem.Register("Outline", AccessLevel.GameMaster, Outline_OnCommand); + CommandSystem.Register("OutlineRXYZ", AccessLevel.GameMaster, OutlineRXYZ_OnCommand); + CommandSystem.Register("OutlineXYZ", AccessLevel.GameMaster, OutlineXYZ_OnCommand); + CommandSystem.Register("OutlineZ", AccessLevel.GameMaster, OutlineZ_OnCommand); + CommandSystem.Register("OutlineAvg", AccessLevel.GameMaster, OutlineAvg_OnCommand); + } + + public static void Invoke( + Mobile from, Point3D start, Point3D end, string[] args, List packs = null, + bool outline = false, bool mapAvg = false + ) + { + var type = AddGump.ExactMatch(args[0]); + + if (type == null) + { + from.SendMessage("No type with that name was found."); + return; } - public static void Invoke( - Mobile from, Point3D start, Point3D end, string[] args, List packs = null, - bool outline = false, bool mapAvg = false - ) + Invoke(from, start, end, type, args.AsSpan(1), packs, outline, mapAvg); + } + + public static void Invoke(Mobile from, Point3D start, Point3D end, ConstructorInfo ctor) + { + using var sb = ValueStringBuilder.Create(); + + sb.Append($"{from.AccessLevel} {CommandLogging.Format(from)} building "); + + if (start == end) { - var sb = new StringBuilder(); + sb.Append($"at {start} in {from.Map}"); + } + else + { + sb.Append($"from {start} to {end} in {from.Map}"); + } - sb.Append($"{from.AccessLevel} {CommandLogging.Format(from)} building "); + sb.Append($": {ctor.DeclaringType!.Name}"); - if (start == end) + CommandLogging.WriteLine(from, sb.ToString()); + + var watch = new Stopwatch(); + watch.Start(); + + Utility.FixPoints(ref start, ref end); + + // Handle optional parameters + var paramList = ctor.GetParameters(); + var parms = paramList.Length == 0 ? Array.Empty() : new object[paramList.Length]; + for (var i = 0; i < parms.Length; i++) + { + parms[i] = Type.Missing; + } + + var built = Build(from, start, end, ctor, parms, null, null, null); + + if (built <= 0) + { + SendUsage(ctor, from); + return; + } + + watch.Stop(); + + if (built == 1) + { + from.SendMessage($"{built} object generated in {watch.Elapsed.TotalSeconds:F2} seconds."); + } + else + { + from.SendMessage($"{built} objects generated in {watch.Elapsed.TotalSeconds:F2} seconds."); + } + } + + public static void Invoke( + Mobile from, Point3D start, Point3D end, Type type, + ReadOnlySpan args = default, List packs = null, bool outline = false, bool mapAvg = false + ) + { + using var sb = ValueStringBuilder.Create(); + + sb.Append($"{from.AccessLevel} {CommandLogging.Format(from)} building "); + + if (start == end) + { + sb.Append($"at {start} in {from.Map}"); + } + else + { + sb.Append($"from {start} to {end} in {from.Map}"); + } + + sb.Append($": {type.Name}"); + + string[,] props = null; + + var setArgsIndex = -1; + for (var i = 0; i < args.Length; ++i) + { + sb.Append($" \"{args[i]}\""); + + if (setArgsIndex != -1 || !args[i].InsensitiveEquals("set")) { - sb.Append($"at {start} in {from.Map}"); - } - else - { - sb.Append($"from {start} to {end} in {from.Map}"); + continue; } - sb.Append(':'); + setArgsIndex = i; + var remains = args.Length - i - 1; - for (var i = 0; i < args.Length; ++i) + if (remains < 2) { - sb.Append($" \"{args[i]}\""); + continue; } - CommandLogging.WriteLine(from, sb.ToString()); + props = new string[remains / 2, 2]; - var name = args[0]; + remains /= 2; - FixArgs(ref args); - - string[,] props = null; - - for (var i = 0; i < args.Length; ++i) + for (var j = 0; j < remains; ++j) { - if (args[i].InsensitiveEquals("set")) + props[j, 0] = args[i + j * 2 + 1]; + props[j, 1] = args[i + j * 2 + 2]; + } + } + + CommandLogging.WriteLine(from, sb.ToString()); + + ReadOnlySpan ctorArgs = setArgsIndex != -1 ? args[..setArgsIndex] : args; + + var watch = new Stopwatch(); + watch.Start(); + + var built = BuildObjects(from, type, start, end, ctorArgs, props, packs, outline, mapAvg); + + if (built <= 0) + { + SendUsage(type, from); + return; + } + + watch.Stop(); + + if (built == 1) + { + from.SendMessage($"{built} object generated in {watch.Elapsed.TotalSeconds:F2} seconds."); + } + else + { + from.SendMessage($"{built} objects generated in {watch.Elapsed.TotalSeconds:F2} seconds."); + } + } + + public static int BuildObjects( + Mobile from, Type type, Point3D start, Point3D end, ReadOnlySpan args, string[,] props, + List packs, bool outline = false, bool mapAvg = false + ) + { + Utility.FixPoints(ref start, ref end); + + PropertyInfo[] realProps = null; + + if (props != null) + { + realProps = new PropertyInfo[props.GetLength(0)]; + + var allProps = + type.GetProperties(BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public); + + for (var i = 0; i < realProps.Length; ++i) + { + var propName = props[i, 0]; + var thisProp = Properties.GetPropertyInfoByName(from, allProps, propName, PropertyAccess.Write, out var failReason); + + if (failReason == null) { - var remains = args.Length - i - 1; - - if (remains >= 2) - { - props = new string[remains / 2, 2]; - - remains /= 2; - - for (var j = 0; j < remains; ++j) - { - props[j, 0] = args[i + j * 2 + 1]; - props[j, 1] = args[i + j * 2 + 2]; - } - - FixSetString(ref args, i); - } - - break; - } - } - - var type = AssemblyHandler.FindTypeByName(name); - - if (!IsEntity(type)) - { - from.SendMessage("No type with that name was found."); - return; - } - - var watch = new Stopwatch(); - watch.Start(); - - var built = BuildObjects(from, type, start, end, args, props, packs, outline, mapAvg); - - if (built > 0) - { - watch.Stop(); - if (built == 1) - { - from.SendMessage($"{built} object generated in {watch.Elapsed.TotalSeconds:F2} seconds."); + realProps[i] = thisProp; } else { - from.SendMessage($"{built} objects generated in {watch.Elapsed.TotalSeconds:F2} seconds."); + from.SendMessage(failReason); } } - else + } + + var ctors = type.GetConstructors(); + + for (var i = 0; i < ctors.Length; ++i) + { + var ctor = ctors[i]; + + if (!IsConstructible(ctor, from.AccessLevel)) { - SendUsage(type, from); + continue; } - } - public static void FixSetString(ref string[] args, int index) - { - var old = args; - args = GC.AllocateUninitializedArray(index); - - Array.Copy(old, 0, args, 0, index); - } - - public static void FixArgs(ref string[] args) - { - var old = args; - args = GC.AllocateUninitializedArray(args.Length - 1); - - Array.Copy(old, 1, args, 0, args.Length); - } - - public static int BuildObjects( - Mobile from, Type type, Point3D start, Point3D end, string[] args, string[,] props, - List packs, bool outline = false, bool mapAvg = false - ) - { - Utility.FixPoints(ref start, ref end); - - PropertyInfo[] realProps = null; - - if (props != null) + // Handle optional constructors + var paramList = ctor.GetParameters(); + var totalParams = 0; + for (var j = 0; j < paramList.Length; j++) { - realProps = new PropertyInfo[props.GetLength(0)]; - - var allProps = - type.GetProperties(BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public); - - for (var i = 0; i < realProps.Length; ++i) + if (!paramList[j].HasDefaultValue) { - var propName = props[i, 0]; - var thisProp = Properties.GetPropertyInfoByName(from, allProps, propName, PropertyAccess.Write, out var failReason); - - if (failReason == null) - { - realProps[i] = thisProp; - } - else - { - from.SendMessage(failReason); - } + totalParams++; } } - var ctors = type.GetConstructors(); - - for (var i = 0; i < ctors.Length; ++i) + if (args.Length >= totalParams && args.Length <= paramList.Length) { - var ctor = ctors[i]; + var paramValues = ParseValues(paramList, args); - if (!IsConstructible(ctor, from.AccessLevel)) + if (paramValues == null) { continue; } - // Handle optional constructors - var paramList = ctor.GetParameters(); - var totalParams = 0; - for (var j = 0; j < paramList.Length; j++) + var built = Build(from, start, end, ctor, paramValues, props, realProps, packs, outline, mapAvg); + + if (built > 0) { - if (!paramList[j].HasDefaultValue) - { - totalParams++; - } + return built; + } + } + } + + return 0; + } + + public static object[] ParseValues(ParameterInfo[] paramList, ReadOnlySpan args) + { + var values = new object[paramList.Length]; + + for (int i = 0, a = 0; i < paramList.Length; i++) + { + var param = paramList[i]; + TryParse(param.ParameterType, a < args.Length ? args[a++] : null, out var value); + + if (value != null) + { + values[i] = value; + } + else if (param.HasDefaultValue) + { + values[i] = Type.Missing; + } + else + { + return null; + } + } + + return values; + } + + public static IEntity Build( + Mobile from, ConstructorInfo ctor, object[] values, string[,] props, + PropertyInfo[] realProps, ref bool sendError + ) + { + var built = ctor.Invoke(values); + + if (realProps != null) + { + var hadError = false; + + for (var i = 0; i < realProps.Length; ++i) + { + if (realProps[i] == null) + { + continue; } - if (args.Length >= totalParams && args.Length <= paramList.Length) + var result = + Properties.InternalSetValue(from, built, built, realProps[i], props[i, 1], props[i, 1], false); + + if (result != "Property has been set.") { - var paramValues = ParseValues(paramList, args); - - if (paramValues == null) + if (sendError) { - continue; + from.SendMessage(result); } - var built = Build(from, start, end, ctor, paramValues, props, realProps, packs, outline, mapAvg); - - if (built > 0) - { - return built; - } + hadError = true; } } - return 0; + if (hadError) + { + sendError = false; + } } - public static object[] ParseValues(ParameterInfo[] paramList, string[] args) + return (IEntity)built; + } + + public static int Build( + Mobile from, Point3D start, Point3D end, ConstructorInfo ctor, object[] values, + string[,] props, PropertyInfo[] realProps, List packs, bool outline = false, bool mapAvg = false + ) + { + try { - var values = new object[paramList.Length]; + var map = from.Map; - for (int i = 0, a = 0; i < paramList.Length; i++) + var width = end.X - start.X + 1; + var height = end.Y - start.Y + 1; + + if (outline && (width < 3 || height < 3)) { - var param = paramList[i]; - TryParse(param.ParameterType, a < args.Length ? args[a++] : null, out var value); - - if (value != null) - { - values[i] = value; - } - else if (param.HasDefaultValue) - { - values[i] = Type.Missing; - } - else - { - return null; - } + outline = false; } - return values; - } + int objectCount; - public static IEntity Build( - Mobile from, ConstructorInfo ctor, object[] values, string[,] props, - PropertyInfo[] realProps, ref bool sendError - ) - { - var built = ctor.Invoke(values); - - if (realProps != null) + if (packs != null) { - var hadError = false; + objectCount = packs.Count; + } + else if (outline) + { + objectCount = (width + height - 2) * 2; + } + else + { + objectCount = width * height; + } - for (var i = 0; i < realProps.Length; ++i) + if (objectCount >= 20) + { + from.SendMessage($"Constructing {objectCount} objects, please wait."); + } + + var sendError = true; + + var sb = new StringBuilder(); + sb.Append("Serials: "); + + if (packs != null) + { + for (var i = 0; i < packs.Count; ++i) { - if (realProps[i] == null) + var built = Build(from, ctor, values, props, realProps, ref sendError); + + sb.Append($"{built.Serial}; "); + + if (built is Item item) { - continue; + packs[i].DropItem(item); } - - var result = - Properties.InternalSetValue(from, built, built, realProps[i], props[i, 1], props[i, 1], false); - - if (result != "Property has been set.") + else if (built is Mobile m) { - if (sendError) + m.MoveToWorld(new Point3D(start.X, start.Y, start.Z), map); + } + } + } + else + { + var z = start.Z; + + for (var x = start.X; x <= end.X; ++x) + { + for (var y = start.Y; y <= end.Y; ++y) + { + if (outline && x != start.X && x != end.X && y != start.Y && y != end.Y) { - from.SendMessage(result); + continue; } - hadError = true; - } - } + if (mapAvg) + { + z = map.GetAverageZ(x, y); + } - if (hadError) - { - sendError = false; - } - } - - return (IEntity)built; - } - - public static int Build( - Mobile from, Point3D start, Point3D end, ConstructorInfo ctor, object[] values, - string[,] props, PropertyInfo[] realProps, List packs, bool outline = false, bool mapAvg = false - ) - { - try - { - var map = from.Map; - - var width = end.X - start.X + 1; - var height = end.Y - start.Y + 1; - - if (outline && (width < 3 || height < 3)) - { - outline = false; - } - - int objectCount; - - if (packs != null) - { - objectCount = packs.Count; - } - else if (outline) - { - objectCount = (width + height - 2) * 2; - } - else - { - objectCount = width * height; - } - - if (objectCount >= 20) - { - from.SendMessage($"Constructing {objectCount} objects, please wait."); - } - - var sendError = true; - - var sb = new StringBuilder(); - sb.Append("Serials: "); - - if (packs != null) - { - for (var i = 0; i < packs.Count; ++i) - { var built = Build(from, ctor, values, props, realProps, ref sendError); sb.Append($"{built.Serial}; "); if (built is Item item) { - packs[i].DropItem(item); + item.MoveToWorld(new Point3D(x, y, z), map); } else if (built is Mobile m) { - m.MoveToWorld(new Point3D(start.X, start.Y, start.Z), map); + m.MoveToWorld(new Point3D(x, y, z), map); } } } - else - { - var z = start.Z; - - for (var x = start.X; x <= end.X; ++x) - { - for (var y = start.Y; y <= end.Y; ++y) - { - if (outline && x != start.X && x != end.X && y != start.Y && y != end.Y) - { - continue; - } - - if (mapAvg) - { - z = map.GetAverageZ(x, y); - } - - var built = Build(from, ctor, values, props, realProps, ref sendError); - - sb.Append($"{built.Serial}; "); - - if (built is Item item) - { - item.MoveToWorld(new Point3D(x, y, z), map); - } - else if (built is Mobile m) - { - m.MoveToWorld(new Point3D(x, y, z), map); - } - } - } - } - - CommandLogging.WriteLine(from, sb.ToString()); - - return objectCount; - } - catch (Exception ex) - { - Console.WriteLine(ex); - return 0; } + + CommandLogging.WriteLine(from, sb.ToString()); + + return objectCount; } - - public static void SendUsage(Type type, Mobile from) + catch (Exception ex) { - var ctors = type.GetConstructors(); - var foundCtor = false; + Console.WriteLine(ex); + return 0; + } + } - for (var i = 0; i < ctors.Length; ++i) + public static void SendUsage(Type type, Mobile from) + { + var ctors = type.GetConstructors(); + var foundCtor = false; + + for (var i = 0; i < ctors.Length; ++i) + { + var ctor = ctors[i]; + + if (!IsConstructible(ctor, from.AccessLevel)) { - var ctor = ctors[i]; - - if (!IsConstructible(ctor, from.AccessLevel)) - { - continue; - } - - if (!foundCtor) - { - foundCtor = true; - from.SendMessage("Usage:"); - } - - SendCtor(type, ctor, from); + continue; } if (!foundCtor) { - from.SendMessage("That type is not marked constructible."); + foundCtor = true; + from.SendMessage("Usage:"); } + + SendCtor(ctor, from); } - public static void SendCtor(Type type, ConstructorInfo ctor, Mobile from) + if (!foundCtor) { - var paramList = ctor.GetParameters(); + from.SendMessage("That type is not marked constructible."); + } + } - var sb = new StringBuilder(); + public static void SendUsage(ConstructorInfo ctor, Mobile from) + { + if (!IsConstructible(ctor, from.AccessLevel)) + { + from.SendMessage("That type is not marked constructible."); + return; + } - sb.Append(type.Name); + from.SendMessage("Usage:"); + SendCtor(ctor, from); + } - for (var i = 0; i < paramList.Length; ++i) + public static void SendCtor(ConstructorInfo ctor, Mobile from) + { + var paramList = ctor.GetParameters(); + + using var sb = ValueStringBuilder.Create(); + + sb.Append(ctor.DeclaringType!.Name); + + for (var i = 0; i < paramList.Length; ++i) + { + if (i != 0) { - if (i != 0) + sb.Append(','); + } + + sb.Append(' '); + + sb.Append(paramList[i].ParameterType.Name); + sb.Append(' '); + sb.Append(paramList[i].Name); + } + + from.SendMessage(sb.ToString()); + } + + private static void TileBox_Callback(Mobile from, Point3D start, Point3D end, TileState ts) + { + var mapAvg = false; + + switch (ts.m_ZType) + { + case TileZType.Fixed: { - sb.Append(','); + start.Z = end.Z = ts.m_FixedZ; + break; + } + case TileZType.MapAverage: + { + mapAvg = true; + break; } - - sb.Append(' '); - - sb.Append(paramList[i].ParameterType.Name); - sb.Append(' '); - sb.Append(paramList[i].Name); - } - - from.SendMessage(sb.ToString()); } - private static void TileBox_Callback(Mobile from, Point3D start, Point3D end, TileState ts) + Invoke(from, start, end, ts.m_Args, null, ts.m_Outline, mapAvg); + } + + private static void Internal_OnCommand(CommandEventArgs e, bool outline) + { + var from = e.Mobile; + + if (e.Length >= 1) { - var mapAvg = false; - - switch (ts.m_ZType) - { - case TileZType.Fixed: - { - start.Z = end.Z = ts.m_FixedZ; - break; - } - case TileZType.MapAverage: - { - mapAvg = true; - break; - } - } - - Invoke(from, start, end, ts.m_Args, null, ts.m_Outline, mapAvg); + BoundingBoxPicker.Begin( + from, + (_, start, end) => + TileBox_Callback(from, start, end, new TileState(TileZType.Start, 0, e.Arguments, outline)) + ); } - - private static void Internal_OnCommand(CommandEventArgs e, bool outline) + else { - var from = e.Mobile; - - if (e.Length >= 1) + if (outline) { - BoundingBoxPicker.Begin( - from, - (map, start, end) => - TileBox_Callback(from, start, end, new TileState(TileZType.Start, 0, e.Arguments, outline)) - ); + from.SendMessage("Format: Outline [params] [set { ...}]"); } else { - if (outline) - { - from.SendMessage($"Format: Outline [params] [set {{ ...}}]"); - } - else - { - from.SendMessage($"Format: Tile [params] [set {{ ...}}]"); - } - } - } - - private static void InternalRXYZ_OnCommand(CommandEventArgs e, bool outline) - { - if (e.Length >= 6) - { - var p = new Point3D(e.Mobile.X + e.GetInt32(0), e.Mobile.Y + e.GetInt32(1), e.Mobile.Z + e.GetInt32(4)); - var p2 = new Point3D(p.X + e.GetInt32(2) - 1, p.Y + e.GetInt32(3) - 1, p.Z); - - var subArgs = new string[e.Length - 5]; - - for (var i = 0; i < subArgs.Length; ++i) - { - subArgs[i] = e.Arguments[i + 5]; - } - - Invoke(e.Mobile, p, p2, subArgs, null, outline); - } - else - { - if (outline) - { - e.Mobile.SendMessage($"Format: OutlineRXYZ [params] [set {{ ...}}]"); - } - else - { - e.Mobile.SendMessage($"Format: TileRXYZ [params] [set {{ ...}}]"); - } - } - } - - private static void InternalXYZ_OnCommand(CommandEventArgs e, bool outline) - { - if (e.Length >= 6) - { - var p = new Point3D(e.GetInt32(0), e.GetInt32(1), e.GetInt32(4)); - var p2 = new Point3D(p.X + e.GetInt32(2) - 1, p.Y + e.GetInt32(3) - 1, e.GetInt32(4)); - - var subArgs = new string[e.Length - 5]; - - for (var i = 0; i < subArgs.Length; ++i) - { - subArgs[i] = e.Arguments[i + 5]; - } - - Invoke(e.Mobile, p, p2, subArgs, null, outline); - } - else - { - if (outline) - { - e.Mobile.SendMessage($"Format: OutlineXYZ [params] [set {{ ...}}]" ); - } - else - { - e.Mobile.SendMessage($"Format: TileXYZ [params] [set {{ ...}}]"); - } - } - } - - private static void InternalZ_OnCommand(CommandEventArgs e, bool outline) - { - var from = e.Mobile; - - if (e.Length >= 2) - { - var subArgs = new string[e.Length - 1]; - - for (var i = 0; i < subArgs.Length; ++i) - { - subArgs[i] = e.Arguments[i + 1]; - } - - BoundingBoxPicker.Begin( - from, - (map, start, end) => - TileBox_Callback(from, start, end, new TileState(TileZType.Fixed, e.GetInt32(0), subArgs, outline)) - ); - } - else - { - if (outline) - { - from.SendMessage($"Format: OutlineZ [params] [set {{ ...}}]"); - } - else - { - from.SendMessage($"Format: TileZ [params] [set {{ ...}}]"); - } - } - } - - private static void InternalAvg_OnCommand(CommandEventArgs e, bool outline) - { - var from = e.Mobile; - - if (e.Length >= 1) - { - BoundingBoxPicker.Begin( - from, - (map, start, end) => - TileBox_Callback(from, start, end, new TileState(TileZType.MapAverage, 0, e.Arguments, outline)) - ); - } - else - { - if (outline) - { - from.SendMessage($"Format: OutlineAvg [params] [set {{ ...}}]"); - } - else - { - from.SendMessage($"Format: TileAvg [params] [set {{ ...}}]"); - } - } - } - - [Usage("Tile [params] [set { ...}]"), Description( - "Tiles an item or npc by name into a targeted bounding box. Optional constructor parameters. Optional set property list." - )] - public static void Tile_OnCommand(CommandEventArgs e) - { - Internal_OnCommand(e, false); - } - - [Usage("TileRXYZ [params] [set { ...}]"), Description( - "Tiles an item or npc by name into a given bounding box, (x, y) parameters are relative to your characters position. Optional constructor parameters. Optional set property list." - )] - public static void TileRXYZ_OnCommand(CommandEventArgs e) - { - InternalRXYZ_OnCommand(e, false); - } - - [Usage("TileXYZ [params] [set { ...}]"), Description( - "Tiles an item or npc by name into a given bounding box. Optional constructor parameters. Optional set property list." - )] - public static void TileXYZ_OnCommand(CommandEventArgs e) - { - InternalXYZ_OnCommand(e, false); - } - - [Usage("TileZ [params] [set { ...}]"), Description( - "Tiles an item or npc by name into a targeted bounding box at a fixed Z location. Optional constructor parameters. Optional set property list." - )] - public static void TileZ_OnCommand(CommandEventArgs e) - { - InternalZ_OnCommand(e, false); - } - - [Usage("TileAvg [params] [set { ...}]"), Description( - "Tiles an item or npc by name into a targeted bounding box on the map's average Z elevation. Optional constructor parameters. Optional set property list." - )] - public static void TileAvg_OnCommand(CommandEventArgs e) - { - InternalAvg_OnCommand(e, false); - } - - [Usage("Outline [params] [set { ...}]"), Description( - "Tiles an item or npc by name around a targeted bounding box. Optional constructor parameters. Optional set property list." - )] - public static void Outline_OnCommand(CommandEventArgs e) - { - Internal_OnCommand(e, true); - } - - [Usage("OutlineRXYZ [params] [set { ...}]"), Description( - "Tiles an item or npc by name around a given bounding box, (x, y) parameters are relative to your characters position. Optional constructor parameters. Optional set property list." - )] - public static void OutlineRXYZ_OnCommand(CommandEventArgs e) - { - InternalRXYZ_OnCommand(e, true); - } - - [Usage("OutlineXYZ [params] [set { ...}]"), Description( - "Tiles an item or npc by name around a given bounding box. Optional constructor parameters. Optional set property list." - )] - public static void OutlineXYZ_OnCommand(CommandEventArgs e) - { - InternalXYZ_OnCommand(e, true); - } - - [Usage("OutlineZ [params] [set { ...}]"), Description( - "Tiles an item or npc by name around a targeted bounding box at a fixed Z location. Optional constructor parameters. Optional set property list." - )] - public static void OutlineZ_OnCommand(CommandEventArgs e) - { - InternalZ_OnCommand(e, true); - } - - [Usage("OutlineAvg [params] [set { ...}]"), Description( - "Tiles an item or npc by name around a targeted bounding box on the map's average Z elevation. Optional constructor parameters. Optional set property list." - )] - public static void OutlineAvg_OnCommand(CommandEventArgs e) - { - InternalAvg_OnCommand(e, true); - } - - private enum TileZType - { - Start, - Fixed, - MapAverage - } - - private class TileState - { - public readonly string[] m_Args; - public readonly int m_FixedZ; - public readonly bool m_Outline; - public readonly TileZType m_ZType; - - public TileState(TileZType zType, int fixedZ, string[] args, bool outline) - { - m_ZType = zType; - m_FixedZ = fixedZ; - m_Args = args; - m_Outline = outline; + from.SendMessage("Format: Tile [params] [set { ...}]"); } } } + + private static void InternalRXYZ_OnCommand(CommandEventArgs e, bool outline) + { + if (e.Length >= 6) + { + var p = new Point3D(e.Mobile.X + e.GetInt32(0), e.Mobile.Y + e.GetInt32(1), e.Mobile.Z + e.GetInt32(4)); + var p2 = new Point3D(p.X + e.GetInt32(2) - 1, p.Y + e.GetInt32(3) - 1, p.Z); + + var subArgs = new string[e.Length - 5]; + + for (var i = 0; i < subArgs.Length; ++i) + { + subArgs[i] = e.Arguments[i + 5]; + } + + Invoke(e.Mobile, p, p2, subArgs, null, outline); + } + else + { + if (outline) + { + e.Mobile.SendMessage("Format: OutlineRXYZ [params] [set { ...}]"); + } + else + { + e.Mobile.SendMessage("Format: TileRXYZ [params] [set { ...}]"); + } + } + } + + private static void InternalXYZ_OnCommand(CommandEventArgs e, bool outline) + { + if (e.Length >= 6) + { + var p = new Point3D(e.GetInt32(0), e.GetInt32(1), e.GetInt32(4)); + var p2 = new Point3D(p.X + e.GetInt32(2) - 1, p.Y + e.GetInt32(3) - 1, e.GetInt32(4)); + + var subArgs = new string[e.Length - 5]; + + for (var i = 0; i < subArgs.Length; ++i) + { + subArgs[i] = e.Arguments[i + 5]; + } + + Invoke(e.Mobile, p, p2, subArgs, null, outline); + } + else + { + if (outline) + { + e.Mobile.SendMessage("Format: OutlineXYZ [params] [set { ...}]" ); + } + else + { + e.Mobile.SendMessage("Format: TileXYZ [params] [set { ...}]"); + } + } + } + + private static void InternalZ_OnCommand(CommandEventArgs e, bool outline) + { + var from = e.Mobile; + + if (e.Length >= 2) + { + var subArgs = new string[e.Length - 1]; + + for (var i = 0; i < subArgs.Length; ++i) + { + subArgs[i] = e.Arguments[i + 1]; + } + + BoundingBoxPicker.Begin( + from, + (_, start, end) => + TileBox_Callback(from, start, end, new TileState(TileZType.Fixed, e.GetInt32(0), subArgs, outline)) + ); + } + else + { + if (outline) + { + from.SendMessage("Format: OutlineZ [params] [set { ...}]"); + } + else + { + from.SendMessage("Format: TileZ [params] [set { ...}]"); + } + } + } + + private static void InternalAvg_OnCommand(CommandEventArgs e, bool outline) + { + var from = e.Mobile; + + if (e.Length >= 1) + { + BoundingBoxPicker.Begin( + from, + (_, start, end) => + TileBox_Callback(from, start, end, new TileState(TileZType.MapAverage, 0, e.Arguments, outline)) + ); + } + else + { + if (outline) + { + from.SendMessage("Format: OutlineAvg [params] [set { ...}]"); + } + else + { + from.SendMessage("Format: TileAvg [params] [set { ...}]"); + } + } + } + + [Usage("Tile [params] [set { ...}]")] + [Description( + "Tiles an item or npc by name into a targeted bounding box. Optional constructor parameters. Optional set property list." + )] + public static void Tile_OnCommand(CommandEventArgs e) + { + Internal_OnCommand(e, false); + } + + [Usage("TileRXYZ [params] [set { ...}]")] + [Description( + "Tiles an item or npc by name into a given bounding box, (x, y) parameters are relative to your characters position. Optional constructor parameters. Optional set property list." + )] + public static void TileRXYZ_OnCommand(CommandEventArgs e) + { + InternalRXYZ_OnCommand(e, false); + } + + [Usage("TileXYZ [params] [set { ...}]")] + [Description( + "Tiles an item or npc by name into a given bounding box. Optional constructor parameters. Optional set property list." + )] + public static void TileXYZ_OnCommand(CommandEventArgs e) + { + InternalXYZ_OnCommand(e, false); + } + + [Usage("TileZ [params] [set { ...}]")] + [Description( + "Tiles an item or npc by name into a targeted bounding box at a fixed Z location. Optional constructor parameters. Optional set property list." + )] + public static void TileZ_OnCommand(CommandEventArgs e) + { + InternalZ_OnCommand(e, false); + } + + [Usage("TileAvg [params] [set { ...}]")] + [Description( + "Tiles an item or npc by name into a targeted bounding box on the map's average Z elevation. Optional constructor parameters. Optional set property list." + )] + public static void TileAvg_OnCommand(CommandEventArgs e) + { + InternalAvg_OnCommand(e, false); + } + + [Usage("Outline [params] [set { ...}]")] + [Description( + "Tiles an item or npc by name around a targeted bounding box. Optional constructor parameters. Optional set property list." + )] + public static void Outline_OnCommand(CommandEventArgs e) + { + Internal_OnCommand(e, true); + } + + [Usage("OutlineRXYZ [params] [set { ...}]")] + [Description( + "Tiles an item or npc by name around a given bounding box, (x, y) parameters are relative to your characters position. Optional constructor parameters. Optional set property list." + )] + public static void OutlineRXYZ_OnCommand(CommandEventArgs e) + { + InternalRXYZ_OnCommand(e, true); + } + + [Usage("OutlineXYZ [params] [set { ...}]")] + [Description( + "Tiles an item or npc by name around a given bounding box. Optional constructor parameters. Optional set property list." + )] + public static void OutlineXYZ_OnCommand(CommandEventArgs e) + { + InternalXYZ_OnCommand(e, true); + } + + [Usage("OutlineZ [params] [set { ...}]")] + [Description( + "Tiles an item or npc by name around a targeted bounding box at a fixed Z location. Optional constructor parameters. Optional set property list." + )] + public static void OutlineZ_OnCommand(CommandEventArgs e) + { + InternalZ_OnCommand(e, true); + } + + [Usage("OutlineAvg [params] [set { ...}]")] + [Description( + "Tiles an item or npc by name around a targeted bounding box on the map's average Z elevation. Optional constructor parameters. Optional set property list." + )] + public static void OutlineAvg_OnCommand(CommandEventArgs e) + { + InternalAvg_OnCommand(e, true); + } + + private enum TileZType + { + Start, + Fixed, + MapAverage + } + + private class TileState + { + public readonly string[] m_Args; + public readonly int m_FixedZ; + public readonly bool m_Outline; + public readonly TileZType m_ZType; + + public TileState(TileZType zType, int fixedZ, string[] args, bool outline) + { + m_ZType = zType; + m_FixedZ = fixedZ; + m_Args = args; + m_Outline = outline; + } + } } diff --git a/Projects/UOContent/Commands/Object Creation/AddGump.cs b/Projects/UOContent/Commands/Object Creation/AddGump.cs index 22a832f22..fc38b9ad1 100644 --- a/Projects/UOContent/Commands/Object Creation/AddGump.cs +++ b/Projects/UOContent/Commands/Object Creation/AddGump.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Reflection; using Server.Network; using Server.Targeting; @@ -10,13 +11,13 @@ public class AddGump : DynamicGump private static readonly Type _typeofItem = typeof(Item); private static readonly Type _typeofMobile = typeof(Mobile); private readonly int _page; - private readonly Type[] _searchResults; + private readonly ConstructorInfo[] _searchResults; private readonly string _searchString; private readonly bool _explicitSearch; public override bool Singleton => true; - public AddGump(string searchString, int page, Type[] searchResults, bool explicitSearch) : base(50, 50) + public AddGump(string searchString, int page, ConstructorInfo[] searchResults, bool explicitSearch) : base(50, 50) { _searchString = searchString; _searchResults = searchResults; @@ -50,7 +51,7 @@ public class AddGump : DynamicGump { var index = i % 10; - builder.AddLabel(44, 39 + index * 20, 0x480, _searchResults[i].Name); + builder.AddLabel(44, 39 + index * 20, 0x480, _searchResults[i].DeclaringType!.Name); builder.AddButton(10, 39 + index * 20, 4023, 4025, 4 + i); } } @@ -102,42 +103,83 @@ public class AddGump : DynamicGump private static void AddMenu_OnCommand(CommandEventArgs e) { var val = e.ArgString.Trim(); - Type[] types; + ConstructorInfo[] ctors; var explicitSearch = false; if (val.Length == 0) { - types = Type.EmptyTypes; + ctors = []; } else if (val.Length < 3) { e.Mobile.SendMessage("Invalid search string."); - types = Type.EmptyTypes; + ctors = []; } else { - types = Match(val); + ctors = MatchEmptyCtor(val); explicitSearch = true; } - e.Mobile.SendGump(new AddGump(val, 0, types, explicitSearch)); + e.Mobile.SendGump(new AddGump(val, 0, ctors, explicitSearch)); } - private static void Match(string match, Type[] types, HashSet results) + private static bool ExactMatch(string match, Assembly assembly, out Type type) { - if (match.Length == 0) + if (!_mobileItemTypes.TryGetValue(assembly, out var mobileItemTypes)) { - return; + List typeList = []; + var types = AssemblyHandler.GetTypeCache(assembly).Types; + for (var i = 0; i < types.Length; i++) + { + var t = types[i]; + if (_typeofMobile.IsAssignableFrom(t) || _typeofItem.IsAssignableFrom(t)) + { + typeList.Add(t); + } + } + + _mobileItemTypes[assembly] = mobileItemTypes = typeList.ToArray(); } - match = match.ToLower(); - - for (var i = 0; i < types.Length; i++) + for (var i = 0; i < mobileItemTypes.Length; i++) { - var t = types[i]; + var t = mobileItemTypes[i]; - if (!(_typeofMobile.IsAssignableFrom(t) || _typeofItem.IsAssignableFrom(t)) || - !t.Name.InsensitiveContains(match) || results.Contains(t)) + if (t.Name.InsensitiveEquals(match)) + { + type = t; + return true; + } + } + + type = null; + return false; + } + + private static void MatchEmptyCtor(string match, Assembly assembly, List results) + { + if (!_mobileItemTypes.TryGetValue(assembly, out var mobileItemTypes)) + { + List typeList = []; + var types = AssemblyHandler.GetTypeCache(assembly).Types; + for (var i = 0; i < types.Length; i++) + { + var t = types[i]; + if (_typeofMobile.IsAssignableFrom(t) || _typeofItem.IsAssignableFrom(t)) + { + typeList.Add(t); + } + } + + _mobileItemTypes[assembly] = mobileItemTypes = typeList.ToArray(); + } + + for (var i = 0; i < mobileItemTypes.Length; i++) + { + var t = mobileItemTypes[i]; + + if (!t.Name.InsensitiveContains(match)) { continue; } @@ -158,47 +200,70 @@ public class AddGump : DynamicGump } } - if (isEmptyCtor && ctors[j].IsDefined(typeof(ConstructibleAttribute), false)) + if (isEmptyCtor && ctor.GetCustomAttributes(Types.OfConstructible, false).Length > 0) { - results.Add(t); + results.Add(ctor); break; } } } } - public static Type[] Match(string match) + private static readonly Dictionary _mobileItemTypes = []; + + public static ConstructorInfo[] MatchEmptyCtor(string match) { - var results = new HashSet(); - Type[] types; - - var asms = AssemblyHandler.Assemblies; - - for (var i = 0; i < asms.Length; ++i) + if (string.IsNullOrWhiteSpace(match)) { - types = AssemblyHandler.GetTypeCache(asms[i]).Types; - Match(match, types, results); + return []; } - types = AssemblyHandler.GetTypeCache(Core.Assembly).Types; - Match(match, types, results); + match = match.ToLower(); + + List results = []; + MatchEmptyCtor(match, Core.Assembly, results); + + for (var i = 0; i < AssemblyHandler.Assemblies.Length; ++i) + { + MatchEmptyCtor(match, AssemblyHandler.Assemblies[i], results); + } if (results.Count == 0) { - return Array.Empty(); + return []; } - var finalResults = new Type[results.Count]; - var index = 0; - foreach (var t in results) - { - finalResults[index++] = t; - } + var finalResults = results.ToArray(); + Array.Sort(finalResults, ConstructorNameComparer.Instance); - Array.Sort(finalResults, TypeNameComparer.Instance); return finalResults; } + public static Type ExactMatch(string match) + { + if (string.IsNullOrWhiteSpace(match)) + { + return null; + } + + match = match.ToLower(); + + if (ExactMatch(match, Core.Assembly, out var type)) + { + return type; + } + + for (var i = 0; i < AssemblyHandler.Assemblies.Length; ++i) + { + if (ExactMatch(match, AssemblyHandler.Assemblies[i], out type)) + { + return type; + } + } + + return null; + } + public override void OnResponse(NetState sender, in RelayInfo info) { var from = sender.Mobile; @@ -216,7 +281,7 @@ public class AddGump : DynamicGump } else { - from.SendGump(new AddGump(match, 0, Match(match), true)); + from.SendGump(new AddGump(match, 0, MatchEmptyCtor(match), true)); } break; @@ -259,29 +324,30 @@ public class AddGump : DynamicGump } } - private class TypeNameComparer : IComparer + private class ConstructorNameComparer : IComparer { - public static readonly TypeNameComparer Instance = new(); - public int Compare(Type x, Type y) => string.CompareOrdinal(x?.Name, y?.Name); + public static readonly ConstructorNameComparer Instance = new(); + public int Compare(ConstructorInfo x, ConstructorInfo y) => + x?.DeclaringType!.Name.CompareOrdinal(y?.DeclaringType!.Name) ?? 0; } public class InternalTarget : Target { - private readonly int m_Page; - private readonly Type[] m_SearchResults; - private readonly string m_SearchString; - private readonly Type m_Type; + private readonly int _page; + private readonly ConstructorInfo[] _searchResults; + private readonly string _searchString; + private readonly ConstructorInfo _ctor; - public InternalTarget(Type type, Type[] searchResults, string searchString, int page) : base( + public InternalTarget(ConstructorInfo ctor, ConstructorInfo[] searchResults, string searchString, int page) : base( -1, true, TargetFlags.None ) { - m_Type = type; - m_SearchResults = searchResults; - m_SearchString = searchString; - m_Page = page; + _ctor = ctor; + _searchResults = searchResults; + _searchString = searchString; + _page = page; } protected override void OnTarget(Mobile from, object o) @@ -298,16 +364,15 @@ public class AddGump : DynamicGump _ => 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); + Commands.Add.Invoke(from, new Point3D(p), new Point3D(p), _ctor); + from.Target = new InternalTarget(_ctor, _searchResults, _searchString, _page); } protected override void OnTargetCancel(Mobile from, TargetCancelType cancelType) { if (cancelType == TargetCancelType.Canceled) { - from.SendGump(new AddGump(m_SearchString, m_Page, m_SearchResults, true)); + from.SendGump(new AddGump(_searchString, _page, _searchResults, true)); } } } diff --git a/Projects/UOContent/Engines/ConPVP/DuelContext.cs b/Projects/UOContent/Engines/ConPVP/DuelContext.cs index a01e24058..ef7fb5b89 100644 --- a/Projects/UOContent/Engines/ConPVP/DuelContext.cs +++ b/Projects/UOContent/Engines/ConPVP/DuelContext.cs @@ -1764,7 +1764,7 @@ namespace Server.Engines.ConPVP { if (Rematch) { - mob.SendMessage(0x22, $"You have rejected the rematch."); + mob.SendMessage(0x22, "You have rejected the rematch."); } else { diff --git a/Projects/UOContent/Engines/ML Quests/MLQuestSystem.cs b/Projects/UOContent/Engines/ML Quests/MLQuestSystem.cs index cfe129675..7ad4aa937 100644 --- a/Projects/UOContent/Engines/ML Quests/MLQuestSystem.cs +++ b/Projects/UOContent/Engines/ML Quests/MLQuestSystem.cs @@ -263,11 +263,11 @@ namespace Server.Engines.MLQuests if (enable) { - m.SendMessage($"Serialization for all quests is now enabled."); + m.SendMessage("Serialization for all quests is now enabled."); } else { - m.SendMessage($"Serialization for all quests is now disabled."); + m.SendMessage("Serialization for all quests is now disabled."); } if (AutoGenerateNew && !enable) diff --git a/Projects/UOContent/Special Systems/Items/Stones/GamblingStone.cs b/Projects/UOContent/Special Systems/Items/Stones/GamblingStone.cs index dc3898e39..c949b0cbc 100644 --- a/Projects/UOContent/Special Systems/Items/Stones/GamblingStone.cs +++ b/Projects/UOContent/Special Systems/Items/Stones/GamblingStone.cs @@ -82,7 +82,7 @@ public partial class GamblingStone : Item } else { - from.SendMessage(0x22, $"You need at least 250gp in your backpack to use this."); + from.SendMessage(0x22, "You need at least 250gp in your backpack to use this."); } } } diff --git a/Projects/UOContent/World Saves/SaveCommands.cs b/Projects/UOContent/World Saves/SaveCommands.cs index 21da36a1f..29882bc4e 100644 --- a/Projects/UOContent/World Saves/SaveCommands.cs +++ b/Projects/UOContent/World Saves/SaveCommands.cs @@ -35,11 +35,11 @@ namespace Server.Commands if (enabled) { - e.Mobile.SendMessage($"Saves have been enabled."); + e.Mobile.SendMessage("Saves have been enabled."); } else { - e.Mobile.SendMessage($"Saves have been disabled."); + e.Mobile.SendMessage("Saves have been disabled."); } } else