ModernUO/Projects/Server/Attributes.cs
Kamron Batman db02a6b6e9
fix(core): Fixes some properties that cannot be modified ingame (#604)
- [X] Adds a property to `CommandProperty` to allow modifying `PropertyObject` where there is no property setter that is accessible.
- [X] Updates AosAttributes and friends

Example of how to make this work:
```cs
        [CommandProperty(AccessLevel.GameMaster, canModify: true)]
        public AosWeaponAttributes WeaponAttributes { get; private set; }
```

This fix is necessary because in release mode the optimizer will sometimes _entirely remove the setter_ because it knows it can do something that is more efficient _when the property setter is private_. RunUO got around this by declaring a public setter explicitly that _was empty_.

### Screenshot
<img width="313" alt="Screen Shot 2021-05-15 at 11 34 01 PM" src="https://user-images.githubusercontent.com/3953314/118387955-49293c00-b5d6-11eb-8f31-a3b5e31bd18b.png">
2021-05-15 23:47:33 -07:00

146 lines
3.6 KiB
C#

using System;
using System.Collections.Generic;
using System.Reflection;
namespace Server
{
[AttributeUsage(AttributeTargets.Property)]
public class HueAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Property)]
public class BodyAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)]
public class PropertyObjectAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)]
public class NoSortAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Method)]
public class CallPriorityAttribute : Attribute
{
public CallPriorityAttribute(int priority) => Priority = priority;
public int Priority { get; set; }
}
public class CallPriorityComparer : IComparer<MethodInfo>
{
public int Compare(MethodInfo x, MethodInfo y)
{
if (x == null && y == null)
{
return 0;
}
if (x == null)
{
return 1;
}
if (y == null)
{
return -1;
}
var xPriority = GetPriority(x);
var yPriority = GetPriority(y);
if (xPriority > yPriority)
{
return 1;
}
if (xPriority < yPriority)
{
return -1;
}
return 0;
}
private int GetPriority(MethodInfo mi)
{
var objs = mi.GetCustomAttributes(typeof(CallPriorityAttribute), true);
if (objs.Length == 0)
{
return 50;
}
if (!(objs[0] is CallPriorityAttribute attr))
{
return 50;
}
return attr.Priority;
}
}
[AttributeUsage(AttributeTargets.Class)]
public class TypeAliasAttribute : Attribute
{
public TypeAliasAttribute(params string[] aliases) => Aliases = aliases;
public string[] Aliases { get; }
}
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)]
public class ParsableAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum)]
public class CustomEnumAttribute : Attribute
{
public CustomEnumAttribute(string[] names) => Names = names;
public string[] Names { get; }
}
[AttributeUsage(AttributeTargets.Constructor)]
public class ConstructibleAttribute : Attribute
{
public ConstructibleAttribute() :
this(AccessLevel.Player) // Lowest accesslevel for current functionality (Level determined by access to [add)
{
}
public ConstructibleAttribute(AccessLevel accessLevel) => AccessLevel = accessLevel;
public AccessLevel AccessLevel { get; set; }
}
[AttributeUsage(AttributeTargets.Property)]
public class CommandPropertyAttribute : Attribute
{
public CommandPropertyAttribute(
AccessLevel level,
bool readOnly = false,
bool canModify = false
) : this(level, level)
{
ReadOnly = readOnly;
CanModify = canModify;
}
public CommandPropertyAttribute(AccessLevel readLevel, AccessLevel writeLevel)
{
ReadLevel = readLevel;
WriteLevel = writeLevel;
}
public AccessLevel ReadLevel { get; }
public AccessLevel WriteLevel { get; }
public bool ReadOnly { get; }
public bool CanModify { get; }
}
}