From bba5346a927a294c31bb45001c33216783a33d15 Mon Sep 17 00:00:00 2001 From: Kamron Batman <3953314+kamronbatman@users.noreply.github.com> Date: Wed, 15 Sep 2021 21:48:30 -0700 Subject: [PATCH] fix: Consolidates properties code (#785) * Consolidates the property logic between properties and add. * Fixes a bug with setting properties --- Projects/UOContent/Commands/Batch.cs | 96 +++++------ .../Commands/Generic/Commands/Interface.cs | 8 +- .../UOContent/Commands/Object Creation/Add.cs | 38 +---- Projects/UOContent/Commands/Properties.cs | 149 +++++++++--------- 4 files changed, 123 insertions(+), 168 deletions(-) diff --git a/Projects/UOContent/Commands/Batch.cs b/Projects/UOContent/Commands/Batch.cs index fcc5bdab6..84aeca315 100644 --- a/Projects/UOContent/Commands/Batch.cs +++ b/Projects/UOContent/Commands/Batch.cs @@ -76,67 +76,57 @@ namespace Server.Commands CommandLogging.Enabled = false; } - List usedList; + var propertyChains = new Dictionary(); + var usedList = new List(list.Count); - if (Utility.InsensitiveCompare(bc.Object, "Current") == 0) + for (var j = 0; j < list.Count; ++j) { - usedList = list; - } - else - { - var propertyChains = new Dictionary(); + var obj = list[j]; - usedList = new List(list.Count); - - for (var j = 0; j < list.Count; ++j) + if (obj == null) { - var obj = list[j]; + continue; + } - if (obj == null) + var type = obj.GetType(); + var failReason = ""; + + if (!propertyChains.TryGetValue(type, out var chain)) + { + propertyChains[type] = chain = Properties.GetPropertyInfoChain( + e.Mobile, + type, + bc.Object, + PropertyAccess.Read, + out failReason + ); + } + + if (chain == null) + { + continue; + } + + var endProp = Properties.GetPropertyInfo(ref obj, chain, out failReason); + + if (endProp == null) + { + continue; + } + + try + { + obj = endProp.GetValue(obj, null); + + if (obj != null) { - continue; - } - - var type = obj.GetType(); - var failReason = ""; - - if (!propertyChains.TryGetValue(type, out var chain)) - { - propertyChains[type] = chain = Properties.GetPropertyInfoChain( - e.Mobile, - type, - bc.Object, - PropertyAccess.Read, - ref failReason - ); - } - - if (chain == null) - { - continue; - } - - var endProp = Properties.GetPropertyInfo(ref obj, chain, ref failReason); - - if (endProp == null) - { - continue; - } - - try - { - obj = endProp.GetValue(obj, null); - - if (obj != null) - { - usedList.Add(obj); - } - } - catch - { - // ignored + usedList.Add(obj); } } + catch + { + // ignored + } } command.ExecuteList(eventArgs[i], usedList); diff --git a/Projects/UOContent/Commands/Generic/Commands/Interface.cs b/Projects/UOContent/Commands/Generic/Commands/Interface.cs index 6a343f554..b8c4b91e0 100644 --- a/Projects/UOContent/Commands/Generic/Commands/Interface.cs +++ b/Projects/UOContent/Commands/Generic/Commands/Interface.cs @@ -115,13 +115,12 @@ namespace Server.Commands.Generic if (obj != null) { - string failReason = null; var chain = Properties.GetPropertyInfoChain( m_From, obj.GetType(), m_Columns[i], PropertyAccess.Read, - ref failReason + out _ ); if (chain?.Length > 0) @@ -187,14 +186,13 @@ namespace Server.Commands.Generic var src = obj; string value; - var failReason = ""; var chain = Properties.GetPropertyInfoChain( m_From, src.GetType(), m_Columns[j], PropertyAccess.Read, - ref failReason + out _ ); if (chain == null || chain.Length == 0) @@ -203,7 +201,7 @@ namespace Server.Commands.Generic } else { - var p = Properties.GetPropertyInfo(ref src, chain, ref failReason); + var p = Properties.GetPropertyInfo(ref src, chain, out _); if (p == null) { diff --git a/Projects/UOContent/Commands/Object Creation/Add.cs b/Projects/UOContent/Commands/Object Creation/Add.cs index ae422c02e..a54c84e94 100644 --- a/Projects/UOContent/Commands/Object Creation/Add.cs +++ b/Projects/UOContent/Commands/Object Creation/Add.cs @@ -149,46 +149,16 @@ namespace Server.Commands for (var i = 0; i < realProps.Length; ++i) { - PropertyInfo thisProp = null; - var propName = props[i, 0]; + var thisProp = Properties.GetPropertyInfoByName(from, allProps, propName, PropertyAccess.Write, out var failReason); - for (var j = 0; thisProp == null && j < allProps.Length; ++j) + if (failReason == null) { - if (propName.InsensitiveEquals(allProps[j].Name)) - { - thisProp = allProps[j]; - } - } - - if (thisProp == null) - { - from.SendMessage("Property not found: {0}", propName); + realProps[i] = thisProp; } else { - var attr = GetCPA(thisProp); - - if (attr == null) - { - from.SendMessage("Property ({0}) not found.", propName); - } - else if (from.AccessLevel < attr.WriteLevel) - { - from.SendMessage( - "Setting this property ({0}) requires at least {1} access level.", - propName, - Mobile.GetAccessLevelName(attr.WriteLevel) - ); - } - else if (!thisProp.CanWrite || attr.ReadOnly) - { - from.SendMessage("Property ({0}) is read only.", propName); - } - else - { - realProps[i] = thisProp; - } + from.SendMessage(failReason); } } } diff --git a/Projects/UOContent/Commands/Properties.cs b/Projects/UOContent/Commands/Properties.cs index 61c6b20fb..683f9e042 100644 --- a/Projects/UOContent/Commands/Properties.cs +++ b/Projects/UOContent/Commands/Properties.cs @@ -55,13 +55,69 @@ namespace Server.Commands } } - private static bool CIEqual(string l, string r) => l.InsensitiveEquals(r); + public static PropertyInfo GetPropertyInfoByName( + Mobile from, PropertyInfo[] props, string propertyName, PropertyAccess access, out string failReason + ) + { + for (var i = 0; i < props.Length; i++) + { + var p = props[i]; + + if (!p.Name.InsensitiveEquals(propertyName)) + { + continue; + } + + var attr = GetCPA(p); + + if (attr == null) + { + failReason = $"Property '${propertyName}' not found."; + return null; + } + + if ((access & PropertyAccess.Read) != 0 && from.AccessLevel < attr.ReadLevel) + { + failReason = + $"You must be at least {Mobile.GetAccessLevelName(attr.ReadLevel)} to get the property '{propertyName}'."; + + return null; + } + + if ((access & PropertyAccess.Write) != 0 && from.AccessLevel < attr.WriteLevel) + { + failReason = + $"You must be at least {Mobile.GetAccessLevelName(attr.WriteLevel)} to set the property '{propertyName}'."; + + return null; + } + + if ((access & PropertyAccess.Read) != 0 && !p.CanRead) + { + failReason = $"Property '{propertyName}' is write only."; + return null; + } + + if ((access & PropertyAccess.Write) != 0 && (!p.CanWrite && !attr.CanModify || attr.ReadOnly)) + { + failReason = $"Property '{propertyName}' is read only."; + return null; + } + + failReason = null; + return p; + } + + failReason = null; + return null; + } public static PropertyInfo[] GetPropertyInfoChain( Mobile from, Type type, string propertyString, - PropertyAccess endAccess, ref string failReason + PropertyAccess access, out string failReason ) { + failReason = null; var split = propertyString.Split('.'); if (split.Length == 0) @@ -74,76 +130,18 @@ namespace Server.Commands for (var i = 0; i < info.Length; ++i) { var propertyName = split[i]; - - if (CIEqual(propertyName, "current")) - { - continue; - } - var props = type.GetProperties(BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public); - var isFinal = i == info.Length - 1; + var p = GetPropertyInfoByName(from, props, propertyName, access, out failReason); - var access = endAccess; - - if (!isFinal) + if (p == null) { - access |= PropertyAccess.Read; - } - - for (var j = 0; j < props.Length; ++j) - { - var p = props[j]; - - if (CIEqual(p.Name, propertyName)) - { - var attr = GetCPA(p); - - if (attr == null) - { - failReason = $"Property '{propertyName}' not found."; - return null; - } - - if ((access & PropertyAccess.Read) != 0 && from.AccessLevel < attr.ReadLevel) - { - failReason = - $"You must be at least {Mobile.GetAccessLevelName(attr.ReadLevel)} to get the property '{propertyName}'."; - - return null; - } - - if ((access & PropertyAccess.Write) != 0 && from.AccessLevel < attr.WriteLevel) - { - failReason = - $"You must be at least {Mobile.GetAccessLevelName(attr.WriteLevel)} to set the property '{propertyName}'."; - - return null; - } - - if ((access & PropertyAccess.Read) != 0 && !p.CanRead) - { - failReason = $"Property '{propertyName}' is write only."; - return null; - } - - if ((access & PropertyAccess.Write) != 0 && (!p.CanWrite || attr.ReadOnly) && isFinal) - { - failReason = $"Property '{propertyName}' is read only."; - return null; - } - - info[i] = p; - type = p.PropertyType; - break; - } - } - - if (info[i] == null) - { - failReason = $"Property '{propertyName}' not found."; + failReason ??= $"Property '{propertyName}' not found."; return null; } + + info[i] = p; + type = p.PropertyType; } return info; @@ -151,15 +149,15 @@ namespace Server.Commands public static PropertyInfo GetPropertyInfo( Mobile from, ref object obj, string propertyName, PropertyAccess access, - ref string failReason + out string failReason ) { - var chain = GetPropertyInfoChain(from, obj.GetType(), propertyName, access, ref failReason); + var chain = GetPropertyInfoChain(from, obj.GetType(), propertyName, access, out failReason); - return chain == null ? null : GetPropertyInfo(ref obj, chain, ref failReason); + return chain == null ? null : GetPropertyInfo(ref obj, chain, out failReason); } - public static PropertyInfo GetPropertyInfo(ref object obj, PropertyInfo[] chain, ref string failReason) + public static PropertyInfo GetPropertyInfo(ref object obj, PropertyInfo[] chain, out string failReason) { if (chain == null || chain.Length == 0) { @@ -183,6 +181,7 @@ namespace Server.Commands } } + failReason = null; return chain[^1]; } @@ -190,14 +189,14 @@ namespace Server.Commands { var failReason = ""; - var chain = GetPropertyInfoChain(from, o.GetType(), name, PropertyAccess.Read, ref failReason); + var chain = GetPropertyInfoChain(from, o.GetType(), name, PropertyAccess.Read, out failReason); if (chain == null || chain.Length == 0) { return failReason; } - var p = GetPropertyInfo(ref o, chain, ref failReason); + var p = GetPropertyInfo(ref o, chain, out failReason); return p == null ? failReason : InternalGetValue(o, p, chain); } @@ -246,9 +245,8 @@ namespace Server.Commands return "Zero is not a valid value to offset."; } - string failReason = null; realObjs[i] = o; - realProps[i] = GetPropertyInfo(from, ref realObjs[i], name, PropertyAccess.ReadWrite, ref failReason); + realProps[i] = GetPropertyInfo(from, ref realObjs[i], name, PropertyAccess.ReadWrite, out var failReason); if (failReason != null) { @@ -353,8 +351,7 @@ namespace Server.Commands { var logObject = o; - var failReason = ""; - var p = GetPropertyInfo(from, ref o, name, PropertyAccess.Write, ref failReason); + var p = GetPropertyInfo(from, ref o, name, PropertyAccess.Write, out var failReason); return p == null ? failReason : InternalSetValue(from, logObject, o, p, name, value, true); }