mirror of
https://github.com/modernuo/ModernUO
synced 2026-08-11 22:23:06 -04:00
## Summary ### Changes - Adds `[IgnoreDupe]` and `[SerializedIgnoreDupe]` - Updates all _known_ classes that need the attribute. Some might be missing, please helps us find them! - Adds `Item.Dupe()` command and encapsulates `CopyProperties` and `OnAfterDuped`. This is also overridable. - Updates Dupe command to use the new logic. - Fixes duping multiple kinds of objects that used to be outright broken. ### Bug Fixes - Fixes issue with durability after duping - Fixes issue with hue after duping > [!Note] > **Developer Note** > Customizing how duping an item works now requires two steps: > 1. Add `[IgnoreDupe]` or `[SerializedIgnoreDupe]` to the property/field > 2. Add custom logic in an `OnAfterDuped` override > > When do you need to do this? > *When the property being copied is not a primitive, and you need to manually deep-clone the contents of the property such as with Lists, Dictionaries, or sub classes.*
195 lines
5.5 KiB
C#
195 lines
5.5 KiB
C#
/*************************************************************************
|
|
* ModernUO *
|
|
* Copyright 2019-2023 - ModernUO Development Team *
|
|
* Email: hi@modernuo.com *
|
|
* File: Attributes.cs *
|
|
* *
|
|
* This program is free software: you can redistribute it and/or modify *
|
|
* it under the terms of the GNU General Public License as published by *
|
|
* the Free Software Foundation, either version 3 of the License, or *
|
|
* (at your option) any later version. *
|
|
* *
|
|
* You should have received a copy of the GNU General Public License *
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
|
*************************************************************************/
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Reflection;
|
|
using ModernUO.Serialization;
|
|
|
|
namespace Server;
|
|
|
|
[AttributeUsage(AttributeTargets.Property)]
|
|
public class HueAttribute : 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 static int GetPriority(MethodInfo mi)
|
|
{
|
|
var objs = mi.GetCustomAttributes(typeof(CallPriorityAttribute), true);
|
|
|
|
if (objs.Length == 0)
|
|
{
|
|
return 50;
|
|
}
|
|
|
|
return (objs[0] as CallPriorityAttribute)?.Priority ?? 50;
|
|
}
|
|
}
|
|
|
|
[AttributeUsage(AttributeTargets.Class)]
|
|
public class TypeAliasAttribute : Attribute
|
|
{
|
|
public TypeAliasAttribute(params string[] aliases) => Aliases = aliases;
|
|
|
|
public string[] Aliases { get; }
|
|
}
|
|
|
|
[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.Method)]
|
|
public class UsageAttribute : Attribute
|
|
{
|
|
public UsageAttribute(string usage) => Usage = usage;
|
|
|
|
public string Usage { get; }
|
|
}
|
|
|
|
[AttributeUsage(AttributeTargets.Method)]
|
|
public class DescriptionAttribute : Attribute
|
|
{
|
|
public DescriptionAttribute(string description) => Description = description;
|
|
|
|
public string Description { get; }
|
|
}
|
|
|
|
[AttributeUsage(AttributeTargets.Method)]
|
|
public class AliasesAttribute : Attribute
|
|
{
|
|
public AliasesAttribute(params string[] aliases) => Aliases = aliases;
|
|
|
|
public string[] Aliases { get; }
|
|
}
|
|
|
|
[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; }
|
|
}
|
|
|
|
[AttributeUsage(AttributeTargets.Field)]
|
|
public class SerializedCommandPropertyAttribute : SerializedPropertyAttrAttribute<CommandPropertyAttribute>
|
|
{
|
|
public SerializedCommandPropertyAttribute(
|
|
AccessLevel level,
|
|
bool readOnly = false,
|
|
bool canModify = false
|
|
) : this(level, level)
|
|
{
|
|
ReadOnly = readOnly;
|
|
CanModify = canModify;
|
|
}
|
|
|
|
public SerializedCommandPropertyAttribute(AccessLevel readLevel, AccessLevel writeLevel)
|
|
{
|
|
ReadLevel = readLevel;
|
|
WriteLevel = writeLevel;
|
|
}
|
|
|
|
public AccessLevel ReadLevel { get; }
|
|
public AccessLevel WriteLevel { get; }
|
|
public bool ReadOnly { get; }
|
|
public bool CanModify { get; }
|
|
}
|
|
|
|
[AttributeUsage(AttributeTargets.Property)]
|
|
public class IgnoreDupeAttribute : Attribute;
|
|
|
|
[AttributeUsage(AttributeTargets.Field)]
|
|
public class SerializedIgnoreDupeAttribute : SerializedPropertyAttrAttribute<IgnoreDupeAttribute>;
|