diff --git a/src/MHServerEmu.Games/GameData/Calligraphy/PrototypePropertyCollection.cs b/src/MHServerEmu.Games/GameData/Calligraphy/PrototypePropertyCollection.cs index a7a6ebbf..b60255fd 100644 --- a/src/MHServerEmu.Games/GameData/Calligraphy/PrototypePropertyCollection.cs +++ b/src/MHServerEmu.Games/GameData/Calligraphy/PrototypePropertyCollection.cs @@ -196,8 +196,10 @@ namespace MHServerEmu.Games.GameData.Calligraphy { if (paramsSetMask == 0xff) return left == right; - var leftParams = left.GetParams(); - var rightParams = right.GetParams(); + Span leftParams = stackalloc PropertyParam[Property.MaxParamCount]; + Span rightParams = stackalloc PropertyParam[Property.MaxParamCount]; + left.GetParams(ref leftParams); + right.GetParams(ref rightParams); for (int i = 0; i < Property.MaxParamCount; i++) { @@ -218,8 +220,10 @@ namespace MHServerEmu.Games.GameData.Calligraphy { if (paramsSetMask == 0xff) return; - PropertyParam[] destParams = destId.GetParams(); - PropertyParam[] sourceParams = sourceId.GetParams(); + Span destParams = stackalloc PropertyParam[Property.MaxParamCount]; + Span sourceParams = stackalloc PropertyParam[Property.MaxParamCount]; + destId.GetParams(ref destParams); + sourceId.GetParams(ref sourceParams); for (int i = 0; i < Property.MaxParamCount; i++) { diff --git a/src/MHServerEmu.Games/Properties/Evals/Eval.cs b/src/MHServerEmu.Games/Properties/Evals/Eval.cs index bd5a9a35..f3f4255c 100644 --- a/src/MHServerEmu.Games/Properties/Evals/Eval.cs +++ b/src/MHServerEmu.Games/Properties/Evals/Eval.cs @@ -2425,7 +2425,10 @@ namespace MHServerEmu.Games.Properties.Evals PropertyInfoTable propInfoTable = GameDatabase.PropertyInfoTable; PropertyEnum propEnum = propInfoTable.GetPropertyEnumFromPrototype(assignPropEvalParamsProto.Prop); PropertyInfo propInfo = propInfoTable.LookupPropertyInfo(propEnum); - PropertyParam[] paramValues = propInfo.DefaultParamValues; + + Span paramValues = stackalloc PropertyParam[Property.MaxParamCount]; + propInfo.DefaultParamValues.CopyTo(paramValues); + for (int i = 0; i < propInfo.ParamCount; i++) { if (i >= 4) break; @@ -2462,7 +2465,7 @@ namespace MHServerEmu.Games.Properties.Evals } } - PropertyId propId = new (propEnum, paramValues); + PropertyId propId = new(propEnum, paramValues); switch (propInfo.DataType) { @@ -2629,7 +2632,7 @@ namespace MHServerEmu.Games.Properties.Evals if (propInfoParams.ParamCount != propInfoValue.ParamCount) return evalVar; - PropertyParam[] paramValues = new PropertyParam[propInfoParams.ParamCount]; + Span paramValues = stackalloc PropertyParam[propInfoParams.ParamCount]; for (int i = 0; i < propInfoParams.ParamCount; ++i) { if (propInfoParams.GetParamType(i) != propInfoValue.GetParamType(i)) return evalVar; @@ -2653,7 +2656,7 @@ namespace MHServerEmu.Games.Properties.Evals } } - PropertyId propIdValue = new (propEnum, paramValues); + PropertyId propIdValue = new(propEnum, paramValues); switch (propInfoValue.DataType) { @@ -2704,7 +2707,9 @@ namespace MHServerEmu.Games.Properties.Evals PropertyInfoTable propInfoTable = GameDatabase.PropertyInfoTable; PropertyEnum propEnum = propInfoTable.GetPropertyEnumFromPrototype(loadPropEvalParamsProto.Prop); PropertyInfo propInfo = propInfoTable.LookupPropertyInfo(propEnum); - PropertyParam[] paramValues = propInfo.DefaultParamValues; + + Span paramValues = stackalloc PropertyParam[Property.MaxParamCount]; + propInfo.DefaultParamValues.CopyTo(paramValues); for (int i = 0; i < propInfo.ParamCount; ++i) { @@ -2742,7 +2747,7 @@ namespace MHServerEmu.Games.Properties.Evals } } - PropertyId propId = new (propEnum, paramValues); + PropertyId propId = new(propEnum, paramValues); switch (propInfo.DataType) { diff --git a/src/MHServerEmu.Games/Properties/PropertyId.cs b/src/MHServerEmu.Games/Properties/PropertyId.cs index c5b9e537..81dd95ef 100644 --- a/src/MHServerEmu.Games/Properties/PropertyId.cs +++ b/src/MHServerEmu.Games/Properties/PropertyId.cs @@ -40,13 +40,13 @@ namespace MHServerEmu.Games.Properties public PropertyId(PropertyEnum propertyEnum, PropertyParam[] @params) { PropertyInfo info = GameDatabase.PropertyInfoTable.LookupPropertyInfo(propertyEnum); - Raw = info.EncodeParameters(propertyEnum, @params).Raw; + Raw = info.EncodeParameters(propertyEnum, @params.AsSpan()).Raw; } /// /// Constructs a with the provided params /// - public PropertyId(PropertyEnum propertyEnum, ReadOnlySpan @params) + public PropertyId(PropertyEnum propertyEnum, in ReadOnlySpan @params) { PropertyInfo info = GameDatabase.PropertyInfoTable.LookupPropertyInfo(propertyEnum); Raw = info.EncodeParameters(propertyEnum, @params).Raw; @@ -189,16 +189,18 @@ namespace MHServerEmu.Games.Properties /// public PropertyParam GetParam(int index) { - return GetParams()[index]; + Span @params = stackalloc PropertyParam[Property.MaxParamCount]; + GetParams(ref @params); + return @params[index]; } /// - /// Decodes and returns encoded param values. + /// Decodes encoded param values to a . /// - public PropertyParam[] GetParams() + public void GetParams(ref Span @params) { PropertyInfo info = GameDatabase.PropertyInfoTable.LookupPropertyInfo(Enum); - return info.DecodeParameters(this); + info.DecodeParameters(this, ref @params); } } } diff --git a/src/MHServerEmu.Games/Properties/PropertyInfo.cs b/src/MHServerEmu.Games/Properties/PropertyInfo.cs index c9f68322..9f729eb3 100644 --- a/src/MHServerEmu.Games/Properties/PropertyInfo.cs +++ b/src/MHServerEmu.Games/Properties/PropertyInfo.cs @@ -68,36 +68,27 @@ namespace MHServerEmu.Games.Properties } } - public PropertyParam[] DecodeParameters(PropertyId propertyId) + public void DecodeParameters(PropertyId propertyId, ref Span @params) { - if (ParamCount == 0) return new PropertyParam[Property.MaxParamCount]; + if (ParamCount == 0) + { + @params.Clear(); + return; + } ulong encodedParams = propertyId.Raw & Property.ParamMask; - PropertyParam[] decodedParams = new PropertyParam[Property.MaxParamCount]; for (int i = 0; i < ParamCount; i++) - decodedParams[i] = (PropertyParam)(int)((encodedParams >> _paramOffsets[i]) & ((1ul << _paramBitCounts[i]) - 1)); + @params[i] = (PropertyParam)(int)((encodedParams >> _paramOffsets[i]) & ((1ul << _paramBitCounts[i]) - 1)); - return decodedParams; + for (int i = ParamCount; i < Property.MaxParamCount; i++) + @params[i] = 0; } // There's a bunch of (client-accurate) copypasted code here for encoding that allows us to avoid allocating param arrays in some cases. // Feel free to make this more DRY if there is a smarter way of doing this without losing performance. - public PropertyId EncodeParameters(PropertyEnum propertyEnum, PropertyParam[] @params) - { - switch (ParamCount) - { - case 0: return new(propertyEnum); - case 1: return EncodeParameters(propertyEnum, @params[0]); - case 2: return EncodeParameters(propertyEnum, @params[0], @params[1]); - case 3: return EncodeParameters(propertyEnum, @params[0], @params[1], @params[2]); - case 4: return EncodeParameters(propertyEnum, @params[0], @params[1], @params[2], @params[3]); - default: return Logger.WarnReturn(new PropertyId(propertyEnum), $"EncodeParameters(): Invalid param count {ParamCount}"); - } - } - - public PropertyId EncodeParameters(PropertyEnum propertyEnum, ReadOnlySpan @params) + public PropertyId EncodeParameters(PropertyEnum propertyEnum, in ReadOnlySpan @params) { switch (ParamCount) { @@ -166,7 +157,9 @@ namespace MHServerEmu.Games.Properties { StringBuilder sb = new(); sb.Append(PropertyName); - var @params = id.GetParams(); + + Span @params = stackalloc PropertyParam[Property.MaxParamCount]; + id.GetParams(ref @params); for (int i = 0; i < ParamCount; i++) {