fix: Cleans up core code (#1187)

**Only one functional change**
* Fixes a bug in LogFactory where `Warning` is being logged as `Information`

Non-functional changes:
* Updates/Fixes copyright headers
* Removes namespace scopes for core files.

View with [whitespace off](https://github.com/modernuo/ModernUO/pull/1187/files?w=1).
This commit is contained in:
Kamron Batman 2022-10-10 21:47:08 -07:00 committed by GitHub
parent 0138d40bda
commit f268d5d4e2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
262 changed files with 28527 additions and 28646 deletions

View file

@ -26,7 +26,7 @@ jobs:
- name: Setup .NET 6
uses: actions/setup-dotnet@v1
with:
dotnet-version: 6.0.400
dotnet-version: 6.0.401
- name: Build
run: ./publish.cmd Release
- name: Test
@ -54,7 +54,7 @@ jobs:
- name: Setup .NET 6
uses: actions/setup-dotnet@v1
with:
dotnet-version: 6.0.400
dotnet-version: 6.0.401
- name: Build
run: ./publish.cmd Release
- name: Test

View file

@ -3,7 +3,7 @@
<PropertyGroup>
<Authors>Kamron Batman</Authors>
<Company>ModernUO</Company>
<Copyright>2019-2020</Copyright>
<Copyright>2019-2022</Copyright>
<TargetFramework>net6.0</TargetFramework>
<Platforms>x64</Platforms>
<PlatformTarget>x64</PlatformTarget>

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: VendorSellPackets.cs *
* *

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: AssemblyHandler.cs *
* *
@ -21,334 +21,333 @@ using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Loader;
namespace Server
namespace Server;
public static class AssemblyHandler
{
public static class AssemblyHandler
private static readonly Dictionary<Assembly, TypeCache> m_TypeCaches = new();
private static TypeCache m_NullCache;
public static Assembly[] Assemblies { get; set; }
internal static Assembly AssemblyResolver(object sender, ResolveEventArgs args)
{
private static readonly Dictionary<Assembly, TypeCache> m_TypeCaches = new();
private static TypeCache m_NullCache;
public static Assembly[] Assemblies { get; set; }
internal static Assembly AssemblyResolver(object sender, ResolveEventArgs args)
var assemblyName = new AssemblyName(args.Name);
var assembly = LoadAssemblyByAssemblyName(assemblyName);
if (assembly == null)
{
var assemblyName = new AssemblyName(args.Name);
var assembly = LoadAssemblyByAssemblyName(assemblyName);
if (assembly == null)
{
throw new FileNotFoundException(
$"Could not load file or assembly {assemblyName}. The system cannot find the file specified. Review the assemblyDirectories field in {ServerConfiguration.ConfigurationFilePath}",
$"{assemblyName.Name}.dll"
);
}
return assembly;
throw new FileNotFoundException(
$"Could not load file or assembly {assemblyName}. The system cannot find the file specified. Review the assemblyDirectories field in {ServerConfiguration.ConfigurationFilePath}",
$"{assemblyName.Name}.dll"
);
}
private static void EnsureAssemblyDirectories()
return assembly;
}
private static void EnsureAssemblyDirectories()
{
if (ServerConfiguration.AssemblyDirectories.Count == 0)
{
if (ServerConfiguration.AssemblyDirectories.Count == 0)
{
ServerConfiguration.AssemblyDirectories.Add("./Assemblies");
ServerConfiguration.Save();
}
ServerConfiguration.AssemblyDirectories.Add("./Assemblies");
ServerConfiguration.Save();
}
}
public static Assembly LoadAssemblyByAssemblyName(AssemblyName assemblyName)
public static Assembly LoadAssemblyByAssemblyName(AssemblyName assemblyName)
{
if (assemblyName?.Name == null)
{
if (assemblyName?.Name == null)
{
return null;
}
var fullName = assemblyName.FullName;
var fileName = $"{assemblyName.Name}.dll";
EnsureAssemblyDirectories();
var assemblyDirectories = ServerConfiguration.AssemblyDirectories;
foreach (var assemblyDir in assemblyDirectories)
{
var assemblyPath = PathUtility.GetFullPath(Path.Combine(assemblyDir, fileName), Core.BaseDirectory);
if (File.Exists(assemblyPath))
{
var assemblyNameCheck = AssemblyName.GetAssemblyName(assemblyPath);
if (assemblyNameCheck.FullName == fullName)
{
return AssemblyLoadContext.Default.LoadFromAssemblyPath(assemblyPath);
}
}
}
return null;
}
public static Assembly LoadAssemblyByFileName(string assemblyFile)
{
EnsureAssemblyDirectories();
var assemblyDirectories = ServerConfiguration.AssemblyDirectories;
var fullName = assemblyName.FullName;
var fileName = $"{assemblyName.Name}.dll";
foreach (var assemblyDir in assemblyDirectories)
EnsureAssemblyDirectories();
var assemblyDirectories = ServerConfiguration.AssemblyDirectories;
foreach (var assemblyDir in assemblyDirectories)
{
var assemblyPath = PathUtility.GetFullPath(Path.Combine(assemblyDir, fileName), Core.BaseDirectory);
if (File.Exists(assemblyPath))
{
var assemblyPath = Path.Combine(assemblyDir, assemblyFile);
if (File.Exists(assemblyPath))
var assemblyNameCheck = AssemblyName.GetAssemblyName(assemblyPath);
if (assemblyNameCheck.FullName == fullName)
{
return AssemblyLoadContext.Default.LoadFromAssemblyPath(assemblyPath);
}
}
}
return null;
}
public static Assembly LoadAssemblyByFileName(string assemblyFile)
{
EnsureAssemblyDirectories();
var assemblyDirectories = ServerConfiguration.AssemblyDirectories;
foreach (var assemblyDir in assemblyDirectories)
{
var assemblyPath = Path.Combine(assemblyDir, assemblyFile);
if (File.Exists(assemblyPath))
{
return AssemblyLoadContext.Default.LoadFromAssemblyPath(assemblyPath);
}
}
return null;
}
public static void LoadAssemblies(string[] files)
{
var assemblies = new Assembly[files.Length];
for (var i = 0; i < files.Length; i++)
{
var assemblyFile = files[i];
var assembly = LoadAssemblyByFileName(assemblyFile);
if (assembly == null)
{
throw new FileNotFoundException(
$"Could not load file or assembly {assemblyFile}. The system cannot find the file specified. Review the assemblyDirectories field in {ServerConfiguration.ConfigurationFilePath}",
assemblyFile
);
}
assemblies[i] = assembly;
}
Assemblies = assemblies;
}
public static void Invoke(string method)
{
var invoke = new List<MethodInfo>();
Core.Assembly.AddMethods(method, invoke);
for (var i = 0; i < Assemblies.Length; i++)
{
Assemblies[i].AddMethods(method, invoke);
}
invoke.Sort(new CallPriorityComparer());
for (var i = 0; i < invoke.Count; ++i)
{
invoke[i].Invoke(null, null);
}
}
private static void AddMethods(this Assembly assembly, string method, List<MethodInfo> list)
{
var types = assembly.GetTypes();
for (int i = 0; i < types.Length; i++)
{
var m = types[i].GetMethod(method, BindingFlags.Static | BindingFlags.Public);
if (m?.GetParameters().Length == 0)
{
list.Add(m);
}
}
}
public static TypeCache GetTypeCache(Assembly asm)
{
if (asm == null)
{
return m_NullCache ??= new TypeCache(null);
}
if (m_TypeCaches.TryGetValue(asm, out var c))
{
return c;
}
return m_TypeCaches[asm] = new TypeCache(asm);
}
public static Type FindTypeByFullName(string name, bool ignoreCase = true) =>
FindTypeByName(name, true, ignoreCase);
public static Type FindTypeByName(string name, bool fullName = false, bool ignoreCase = true)
{
if (string.IsNullOrWhiteSpace(name))
{
return null;
}
public static void LoadAssemblies(string[] files)
for (var i = 0; i < Assemblies.Length; i++)
{
var assemblies = new Assembly[files.Length];
for (var i = 0; i < files.Length; i++)
{
var assemblyFile = files[i];
var assembly = LoadAssemblyByFileName(assemblyFile);
if (assembly == null)
{
throw new FileNotFoundException(
$"Could not load file or assembly {assemblyFile}. The system cannot find the file specified. Review the assemblyDirectories field in {ServerConfiguration.ConfigurationFilePath}",
assemblyFile
);
}
assemblies[i] = assembly;
}
Assemblies = assemblies;
}
public static void Invoke(string method)
{
var invoke = new List<MethodInfo>();
Core.Assembly.AddMethods(method, invoke);
for (var i = 0; i < Assemblies.Length; i++)
{
Assemblies[i].AddMethods(method, invoke);
}
invoke.Sort(new CallPriorityComparer());
for (var i = 0; i < invoke.Count; ++i)
{
invoke[i].Invoke(null, null);
}
}
private static void AddMethods(this Assembly assembly, string method, List<MethodInfo> list)
{
var types = assembly.GetTypes();
for (int i = 0; i < types.Length; i++)
{
var m = types[i].GetMethod(method, BindingFlags.Static | BindingFlags.Public);
if (m?.GetParameters().Length == 0)
{
list.Add(m);
}
}
}
public static TypeCache GetTypeCache(Assembly asm)
{
if (asm == null)
{
return m_NullCache ??= new TypeCache(null);
}
if (m_TypeCaches.TryGetValue(asm, out var c))
{
return c;
}
return m_TypeCaches[asm] = new TypeCache(asm);
}
public static Type FindTypeByFullName(string name, bool ignoreCase = true) =>
FindTypeByName(name, true, ignoreCase);
public static Type FindTypeByName(string name, bool fullName = false, bool ignoreCase = true)
{
if (string.IsNullOrWhiteSpace(name))
{
return null;
}
for (var i = 0; i < Assemblies.Length; i++)
{
foreach (var type in GetTypeCache(Assemblies[i]).GetTypesByName(name, fullName, ignoreCase))
{
return type;
}
}
foreach(var type in GetTypeCache(Core.Assembly).GetTypesByName(name, fullName, ignoreCase))
foreach (var type in GetTypeCache(Assemblies[i]).GetTypesByName(name, fullName, ignoreCase))
{
return type;
}
}
return null;
foreach(var type in GetTypeCache(Core.Assembly).GetTypesByName(name, fullName, ignoreCase))
{
return type;
}
return null;
}
}
public class TypeCache
{
private readonly Dictionary<string, int[]> _nameMap = new();
private readonly Dictionary<string, int[]> _nameMapInsensitive = new();
private readonly Dictionary<string, int[]> _fullNameMap = new();
private readonly Dictionary<string, int[]> _fullNameMapInsensitive = new();
public TypeCache(Assembly asm)
{
Types = asm?.GetTypes() ?? Type.EmptyTypes;
var nameMap = new Dictionary<string, HashSet<int>>();
var nameMapInsensitive = new Dictionary<string, HashSet<int>>();
var fullNameMap = new Dictionary<string, HashSet<int>>();
var fullNameMapInsensitive = new Dictionary<string, HashSet<int>>();
[MethodImpl(MethodImplOptions.AggressiveInlining)]
void addTypeToRefs(int index, string fullTypeName)
{
var typeName = fullTypeName[(fullTypeName.LastIndexOf('.') + 1)..];
AddToRefs(index, typeName, nameMap);
AddToRefs(index, typeName.ToLower(), nameMapInsensitive);
AddToRefs(index, fullTypeName, fullNameMap);
AddToRefs(index, fullTypeName.ToLower(), fullNameMapInsensitive);
}
var aliasType = typeof(TypeAliasAttribute);
for (var i = 0; i < Types.Length; i++)
{
var current = Types[i];
addTypeToRefs(i, current.FullName);
if (current.GetCustomAttribute(aliasType, false) is TypeAliasAttribute alias)
{
for (var j = 0; j < alias.Aliases.Length; j++)
{
addTypeToRefs(i, alias.Aliases[j]);
}
}
}
foreach (var (key, value) in nameMap)
{
_nameMap[key] = value.ToArray();
}
foreach (var (key, value) in nameMapInsensitive)
{
_nameMapInsensitive[key] = value.ToArray();
}
foreach (var (key, value) in fullNameMap)
{
_fullNameMap[key] = value.ToArray();
}
foreach (var (key, value) in fullNameMapInsensitive)
{
_fullNameMapInsensitive[key] = value.ToArray();
}
}
public class TypeCache
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static void AddToRefs(int index, string key, Dictionary<string, HashSet<int>> map)
{
private readonly Dictionary<string, int[]> _nameMap = new();
private readonly Dictionary<string, int[]> _nameMapInsensitive = new();
private readonly Dictionary<string, int[]> _fullNameMap = new();
private readonly Dictionary<string, int[]> _fullNameMapInsensitive = new();
public TypeCache(Assembly asm)
if (key == null)
{
Types = asm?.GetTypes() ?? Type.EmptyTypes;
return;
}
var nameMap = new Dictionary<string, HashSet<int>>();
var nameMapInsensitive = new Dictionary<string, HashSet<int>>();
var fullNameMap = new Dictionary<string, HashSet<int>>();
var fullNameMapInsensitive = new Dictionary<string, HashSet<int>>();
if (map.TryGetValue(key, out var refs))
{
refs.Add(index);
}
else
{
refs = new HashSet<int> { index };
map.Add(key, refs);
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
void addTypeToRefs(int index, string fullTypeName)
{
var typeName = fullTypeName[(fullTypeName.LastIndexOf('.') + 1)..];
AddToRefs(index, typeName, nameMap);
AddToRefs(index, typeName.ToLower(), nameMapInsensitive);
AddToRefs(index, fullTypeName, fullNameMap);
AddToRefs(index, fullTypeName.ToLower(), fullNameMapInsensitive);
}
public Type[] Types { get; }
var aliasType = typeof(TypeAliasAttribute);
for (var i = 0; i < Types.Length; i++)
{
var current = Types[i];
addTypeToRefs(i, current.FullName);
if (current.GetCustomAttribute(aliasType, false) is TypeAliasAttribute alias)
{
for (var j = 0; j < alias.Aliases.Length; j++)
{
addTypeToRefs(i, alias.Aliases[j]);
}
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public TypeEnumerable GetTypesByName(string name, bool full, bool ignoreCase) => new(name, this, full, ignoreCase);
foreach (var (key, value) in nameMap)
{
_nameMap[key] = value.ToArray();
}
public ref struct TypeEnumerable
{
private readonly TypeCache _cache;
private readonly string _name;
private readonly bool _ignoreCase;
private readonly bool _full;
foreach (var (key, value) in nameMapInsensitive)
{
_nameMapInsensitive[key] = value.ToArray();
}
foreach (var (key, value) in fullNameMap)
{
_fullNameMap[key] = value.ToArray();
}
foreach (var (key, value) in fullNameMapInsensitive)
{
_fullNameMapInsensitive[key] = value.ToArray();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public TypeEnumerable(string name, TypeCache cache, bool full, bool ignoreCase)
{
_name = name;
_cache = cache;
_ignoreCase = ignoreCase;
_full = full;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static void AddToRefs(int index, string key, Dictionary<string, HashSet<int>> map)
{
if (key == null)
{
return;
}
public TypeEnumerator GetEnumerator() => new(_name, _cache, _full, _ignoreCase);
}
if (map.TryGetValue(key, out var refs))
public ref struct TypeEnumerator
{
private readonly TypeCache _cache;
private readonly int[] _values;
private int _index;
private Type _current;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal TypeEnumerator(string name, TypeCache cache, bool full, bool ignoreCase)
{
_cache = cache;
if (ignoreCase)
{
refs.Add(index);
var map = full ? _cache._fullNameMapInsensitive : _cache._nameMapInsensitive;
_values = map.TryGetValue(name.ToLower(), out var values) ? values : Array.Empty<int>();
}
else
{
refs = new HashSet<int> { index };
map.Add(key, refs);
var map = full ? _cache._fullNameMap : _cache._nameMap;
_values = map.TryGetValue(name, out var values) ? values : Array.Empty<int>();
}
}
public Type[] Types { get; }
_index = 0;
_current = default;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public TypeEnumerable GetTypesByName(string name, bool full, bool ignoreCase) => new(name, this, full, ignoreCase);
public ref struct TypeEnumerable
public bool MoveNext()
{
private readonly TypeCache _cache;
private readonly string _name;
private readonly bool _ignoreCase;
private readonly bool _full;
int[] localList = _values;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public TypeEnumerable(string name, TypeCache cache, bool full, bool ignoreCase)
if ((uint)_index < (uint)localList.Length)
{
_name = name;
_cache = cache;
_ignoreCase = ignoreCase;
_full = full;
_current = _cache.Types[_values[_index++]];
return true;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public TypeEnumerator GetEnumerator() => new(_name, _cache, _full, _ignoreCase);
return false;
}
public ref struct TypeEnumerator
public Type Current
{
private readonly TypeCache _cache;
private readonly int[] _values;
private int _index;
private Type _current;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal TypeEnumerator(string name, TypeCache cache, bool full, bool ignoreCase)
{
_cache = cache;
if (ignoreCase)
{
var map = full ? _cache._fullNameMapInsensitive : _cache._nameMapInsensitive;
_values = map.TryGetValue(name.ToLower(), out var values) ? values : Array.Empty<int>();
}
else
{
var map = full ? _cache._fullNameMap : _cache._nameMap;
_values = map.TryGetValue(name, out var values) ? values : Array.Empty<int>();
}
_index = 0;
_current = default;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool MoveNext()
{
int[] localList = _values;
if ((uint)_index < (uint)localList.Length)
{
_current = _cache.Types[_values[_index++]];
return true;
}
return false;
}
public Type Current
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => _current;
}
get => _current;
}
}
}

View file

@ -2,140 +2,139 @@ using System;
using System.Collections.Generic;
using System.Reflection;
namespace Server
namespace Server;
[AttributeUsage(AttributeTargets.Property)]
public class HueAttribute : Attribute
{
[AttributeUsage(AttributeTargets.Property)]
public class HueAttribute : Attribute
{
}
}
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)]
public class PropertyObjectAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)]
public class PropertyObjectAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)]
public class NoSortAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)]
public class NoSortAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Method)]
public class CallPriorityAttribute : Attribute
{
public CallPriorityAttribute(int priority) => Priority = priority;
[AttributeUsage(AttributeTargets.Method)]
public class CallPriorityAttribute : Attribute
{
public CallPriorityAttribute(int priority) => Priority = priority;
public int Priority { get; set; }
}
public int Priority { get; set; }
}
public class CallPriorityComparer : IComparer<MethodInfo>
public class CallPriorityComparer : IComparer<MethodInfo>
{
public int Compare(MethodInfo x, MethodInfo y)
{
public int Compare(MethodInfo x, MethodInfo y)
if (x == null && y == null)
{
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 not 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)
if (x == null)
{
return 1;
}
public ConstructibleAttribute(AccessLevel accessLevel) => AccessLevel = accessLevel;
if (y == null)
{
return -1;
}
public AccessLevel AccessLevel { get; set; }
var xPriority = GetPriority(x);
var yPriority = GetPriority(y);
if (xPriority > yPriority)
{
return 1;
}
if (xPriority < yPriority)
{
return -1;
}
return 0;
}
[AttributeUsage(AttributeTargets.Property)]
public class CommandPropertyAttribute : Attribute
private int GetPriority(MethodInfo mi)
{
public CommandPropertyAttribute(
AccessLevel level,
bool readOnly = false,
bool canModify = false
) : this(level, level)
var objs = mi.GetCustomAttributes(typeof(CallPriorityAttribute), true);
if (objs.Length == 0)
{
ReadOnly = readOnly;
CanModify = canModify;
return 50;
}
public CommandPropertyAttribute(AccessLevel readLevel, AccessLevel writeLevel)
if (objs[0] is not CallPriorityAttribute attr)
{
ReadLevel = readLevel;
WriteLevel = writeLevel;
return 50;
}
public AccessLevel ReadLevel { get; }
public AccessLevel WriteLevel { get; }
public bool ReadOnly { get; }
public bool CanModify { get; }
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; }
}

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: CircularBuffer.cs *
* *
@ -13,128 +13,127 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
*************************************************************************/
namespace System.Buffers
namespace System.Buffers;
public readonly ref struct CircularBuffer<T>
{
public readonly ref struct CircularBuffer<T>
private readonly Span<T> _first;
private readonly Span<T> _second;
public int Length { get; }
public CircularBuffer(ArraySegment<T>[] buffers) : this(buffers[0], buffers[1])
{
private readonly Span<T> _first;
private readonly Span<T> _second;
}
public int Length { get; }
public CircularBuffer(Span<T> first, Span<T> second)
{
_first = first;
_second = second;
Length = first.Length + second.Length;
}
public CircularBuffer(ArraySegment<T>[] buffers) : this(buffers[0], buffers[1])
public T this[int index]
{
get
{
}
public CircularBuffer(Span<T> first, Span<T> second)
{
_first = first;
_second = second;
Length = first.Length + second.Length;
}
public T this[int index]
{
get
if (index < 0 || index > Length)
{
if (index < 0 || index > Length)
{
throw new ArgumentOutOfRangeException(nameof(index));
}
return index < _first.Length ? _first[index] : _second[index - _first.Length];
throw new ArgumentOutOfRangeException(nameof(index));
}
set
{
if (index < 0 || index > Length)
{
throw new ArgumentOutOfRangeException(nameof(index));
}
if (index < _first.Length)
{
_first[index] = value;
}
else
{
_second[index - _first.Length] = value;
}
return index < _first.Length ? _first[index] : _second[index - _first.Length];
}
set
{
if (index < 0 || index > Length)
{
throw new ArgumentOutOfRangeException(nameof(index));
}
if (index < _first.Length)
{
_first[index] = value;
}
else
{
_second[index - _first.Length] = value;
}
}
}
public void CopyFrom(ReadOnlySpan<T> bytes)
public void CopyFrom(ReadOnlySpan<T> bytes)
{
var remaining = bytes.Length;
var offset = 0;
if (remaining == 0)
{
var remaining = bytes.Length;
var offset = 0;
return;
}
for (int i = 0; i < 2; i++)
{
var buffer = i == 0 ? _first : _second;
if (buffer.Length == 0)
{
continue;
}
var sz = Math.Min(remaining, buffer.Length);
bytes.Slice(offset, sz).CopyTo(buffer);
remaining -= sz;
offset += sz;
if (remaining == 0)
{
return;
}
for (int i = 0; i < 2; i++)
{
var buffer = i == 0 ? _first : _second;
if (buffer.Length == 0)
{
continue;
}
var sz = Math.Min(remaining, buffer.Length);
bytes.Slice(offset, sz).CopyTo(buffer);
remaining -= sz;
offset += sz;
if (remaining == 0)
{
return;
}
}
throw new OutOfMemoryException();
}
public void CopyTo(Span<T> bytes)
throw new OutOfMemoryException();
}
public void CopyTo(Span<T> bytes)
{
if (bytes.Length < Length)
{
if (bytes.Length < Length)
{
throw new ArgumentOutOfRangeException(nameof(bytes));
}
if (_first.Length > 0)
{
_first.CopyTo(bytes);
}
if (_second.Length > 0)
{
_second.CopyTo(bytes[_first.Length..]);
}
throw new ArgumentOutOfRangeException(nameof(bytes));
}
public CircularBuffer<T> Slice(int offset, int count)
if (_first.Length > 0)
{
var firstCount = Math.Min(count, _first.Length - offset);
var first = offset < _first.Length
? _first.Slice(offset, firstCount)
: Span<T>.Empty;
var secondCount = offset > _first.Length ? count : count - firstCount;
var second = secondCount > 0 ? _second.Slice(Math.Max(0, offset - _first.Length), secondCount) : Span<T>.Empty;
return new CircularBuffer<T>(first, second);
_first.CopyTo(bytes);
}
public Span<T> GetSpan(int index)
if (_second.Length > 0)
{
if (index is < 0 or > 1)
{
throw new ArgumentOutOfRangeException(nameof(index));
}
return index == 0 ? _first : _second;
_second.CopyTo(bytes[_first.Length..]);
}
}
public CircularBuffer<T> Slice(int offset, int count)
{
var firstCount = Math.Min(count, _first.Length - offset);
var first = offset < _first.Length
? _first.Slice(offset, firstCount)
: Span<T>.Empty;
var secondCount = offset > _first.Length ? count : count - firstCount;
var second = secondCount > 0 ? _second.Slice(Math.Max(0, offset - _first.Length), secondCount) : Span<T>.Empty;
return new CircularBuffer<T>(first, second);
}
public Span<T> GetSpan(int index)
{
if (index is < 0 or > 1)
{
throw new ArgumentOutOfRangeException(nameof(index));
}
return index == 0 ? _first : _second;
}
}

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: PacketReader.cs *
* *
@ -21,375 +21,374 @@ using System.Runtime.CompilerServices;
using System.Text;
using Server.Text;
namespace Server.Network
namespace Server.Network;
public ref struct CircularBufferReader
{
public ref struct CircularBufferReader
private readonly ReadOnlySpan<byte> _first;
private readonly ReadOnlySpan<byte> _second;
public int Length { get; }
public int Position { get; private set; }
public int Remaining => Length - Position;
// Only used for debugging!
public ReadOnlySpan<byte> First => _first;
public ReadOnlySpan<byte> Second => _second;
public CircularBufferReader(ref CircularBuffer<byte> buffer) : this(buffer.GetSpan(0), buffer.GetSpan(1))
{
private readonly ReadOnlySpan<byte> _first;
private readonly ReadOnlySpan<byte> _second;
}
public int Length { get; }
public int Position { get; private set; }
public int Remaining => Length - Position;
public CircularBufferReader(ArraySegment<byte>[] buffer) : this(buffer[0], buffer[1])
{
}
// Only used for debugging!
public ReadOnlySpan<byte> First => _first;
public ReadOnlySpan<byte> Second => _second;
public CircularBufferReader(ReadOnlySpan<byte> first, ReadOnlySpan<byte> second)
{
_first = first;
_second = second;
Position = 0;
Length = first.Length + second.Length;
}
public CircularBufferReader(ref CircularBuffer<byte> buffer) : this(buffer.GetSpan(0), buffer.GetSpan(1))
public void Trace(NetState state)
{
// We don't have data, so nothing to trace
if (_first.Length == 0)
{
return;
}
public CircularBufferReader(ArraySegment<byte>[] buffer) : this(buffer[0], buffer[1])
try
{
using var sw = new StreamWriter("unhandled-packets.log", true);
sw.WriteLine("Client: {0}: Unhandled packet 0x{1:X2}", state, _first[0]);
sw.FormatBuffer(_first, _second, Length);
sw.WriteLine();
sw.WriteLine();
}
catch
{
// ignored
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public byte ReadByte()
{
if (Position < _first.Length)
{
return _first[Position++];
}
public CircularBufferReader(ReadOnlySpan<byte> first, ReadOnlySpan<byte> second)
if (Position < Length)
{
_first = first;
_second = second;
Position = 0;
Length = first.Length + second.Length;
return _second[Position++ - _first.Length];
}
public void Trace(NetState state)
{
// We don't have data, so nothing to trace
if (_first.Length == 0)
{
return;
}
throw new OutOfMemoryException();
}
try
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool ReadBoolean() => ReadByte() > 0;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public sbyte ReadSByte() => (sbyte)ReadByte();
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public short ReadInt16()
{
short value;
if (Position < _first.Length)
{
if (!BinaryPrimitives.TryReadInt16BigEndian(_first[Position..], out value))
{
using var sw = new StreamWriter("unhandled-packets.log", true);
sw.WriteLine("Client: {0}: Unhandled packet 0x{1:X2}", state, _first[0]);
sw.FormatBuffer(_first, _second, Length);
sw.WriteLine();
sw.WriteLine();
}
catch
{
// ignored
// Not enough space. Split the spans
return (short)((ReadByte() >> 8) | ReadByte());
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public byte ReadByte()
else if (!BinaryPrimitives.TryReadInt16BigEndian(_second[(Position - _first.Length)..], out value))
{
if (Position < _first.Length)
{
return _first[Position++];
}
if (Position < Length)
{
return _second[Position++ - _first.Length];
}
throw new OutOfMemoryException();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool ReadBoolean() => ReadByte() > 0;
Position += 2;
return value;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public sbyte ReadSByte() => (sbyte)ReadByte();
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public ushort ReadUInt16()
{
ushort value;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public short ReadInt16()
if (Position < _first.Length)
{
short value;
if (Position < _first.Length)
if (!BinaryPrimitives.TryReadUInt16BigEndian(_first[Position..], out value))
{
if (!BinaryPrimitives.TryReadInt16BigEndian(_first[Position..], out value))
{
// Not enough space. Split the spans
return (short)((ReadByte() >> 8) | ReadByte());
}
// Not enough space. Split the spans
return (ushort)((ReadByte() >> 8) | ReadByte());
}
else if (!BinaryPrimitives.TryReadInt16BigEndian(_second[(Position - _first.Length)..], out value))
}
else if (!BinaryPrimitives.TryReadUInt16BigEndian(_second[(Position - _first.Length)..], out value))
{
throw new OutOfMemoryException();
}
Position += 2;
return value;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public int ReadInt32()
{
int value;
if (Position < _first.Length)
{
if (!BinaryPrimitives.TryReadInt32BigEndian(_first[Position..], out value))
{
// Not enough space. Split the spans
return (ReadByte() >> 24) | (ReadByte() >> 16) | (ReadByte() >> 8) | ReadByte();
}
}
else if (!BinaryPrimitives.TryReadInt32BigEndian(_second[(Position - _first.Length)..], out value))
{
throw new OutOfMemoryException();
}
Position += 4;
return value;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public uint ReadUInt32()
{
uint value;
if (Position < _first.Length)
{
if (!BinaryPrimitives.TryReadUInt32BigEndian(_first[Position..], out value))
{
// Not enough space. Split the spans
return (uint)((ReadByte() >> 24) | (ReadByte() >> 16) | (ReadByte() >> 8) | ReadByte());
}
}
else if (!BinaryPrimitives.TryReadUInt32BigEndian(_second[(Position - _first.Length)..], out value))
{
throw new OutOfMemoryException();
}
Position += 4;
return value;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public long ReadInt64()
{
long value;
if (Position < _first.Length)
{
if (!BinaryPrimitives.TryReadInt64BigEndian(_first[Position..], out value))
{
// Not enough space. Split the spans
return ((long)ReadByte() >> 56) |
((long)ReadByte() >> 48) |
((long)ReadByte() >> 40) |
((long)ReadByte() >> 32) |
((long)ReadByte() >> 24) |
((long)ReadByte() >> 16) |
((long)ReadByte() >> 8) |
ReadByte();
}
}
else if (!BinaryPrimitives.TryReadInt64BigEndian(_second[(Position - _first.Length)..], out value))
{
throw new OutOfMemoryException();
}
Position += 8;
return value;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public ulong ReadUInt64()
{
ulong value;
if (Position < _first.Length)
{
if (!BinaryPrimitives.TryReadUInt64BigEndian(_first[Position..], out value))
{
// Not enough space. Split the spans
return ((ulong)ReadByte() >> 56) |
((ulong)ReadByte() >> 48) |
((ulong)ReadByte() >> 40) |
((ulong)ReadByte() >> 32) |
((ulong)ReadByte() >> 24) |
((ulong)ReadByte() >> 16) |
((ulong)ReadByte() >> 8) |
ReadByte();
}
}
else if (!BinaryPrimitives.TryReadUInt64BigEndian(_second[(Position - _first.Length)..], out value))
{
throw new OutOfMemoryException();
}
Position += 8;
return value;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public string ReadString(Encoding encoding, bool safeString = false, int fixedLength = -1)
{
int byteLength = encoding.GetByteLengthForEncoding();
bool isFixedLength = fixedLength > -1;
var remaining = Remaining;
int size;
if (isFixedLength)
{
size = fixedLength * byteLength;
if (size > Remaining)
{
throw new OutOfMemoryException();
}
Position += 2;
return value;
}
else
{
size = remaining - (remaining & (byteLength - 1));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public ushort ReadUInt16()
ReadOnlySpan<byte> span;
int index;
if (Position < _first.Length)
{
ushort value;
var firstLength = Math.Min(_first.Length - Position, size);
if (Position < _first.Length)
// Find terminator
index = _first.Slice(Position, firstLength).IndexOfTerminator(byteLength);
if (index < 0)
{
if (!BinaryPrimitives.TryReadUInt16BigEndian(_first[Position..], out value))
remaining = size - firstLength;
// We don't have a terminator, but a fixed size to the end of the first span, so stop there
if (remaining <= 0)
{
// Not enough space. Split the spans
return (ushort)((ReadByte() >> 8) | ReadByte());
}
}
else if (!BinaryPrimitives.TryReadUInt16BigEndian(_second[(Position - _first.Length)..], out value))
{
throw new OutOfMemoryException();
}
Position += 2;
return value;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public int ReadInt32()
{
int value;
if (Position < _first.Length)
{
if (!BinaryPrimitives.TryReadInt32BigEndian(_first[Position..], out value))
{
// Not enough space. Split the spans
return (ReadByte() >> 24) | (ReadByte() >> 16) | (ReadByte() >> 8) | ReadByte();
}
}
else if (!BinaryPrimitives.TryReadInt32BigEndian(_second[(Position - _first.Length)..], out value))
{
throw new OutOfMemoryException();
}
Position += 4;
return value;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public uint ReadUInt32()
{
uint value;
if (Position < _first.Length)
{
if (!BinaryPrimitives.TryReadUInt32BigEndian(_first[Position..], out value))
{
// Not enough space. Split the spans
return (uint)((ReadByte() >> 24) | (ReadByte() >> 16) | (ReadByte() >> 8) | ReadByte());
}
}
else if (!BinaryPrimitives.TryReadUInt32BigEndian(_second[(Position - _first.Length)..], out value))
{
throw new OutOfMemoryException();
}
Position += 4;
return value;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public long ReadInt64()
{
long value;
if (Position < _first.Length)
{
if (!BinaryPrimitives.TryReadInt64BigEndian(_first[Position..], out value))
{
// Not enough space. Split the spans
return ((long)ReadByte() >> 56) |
((long)ReadByte() >> 48) |
((long)ReadByte() >> 40) |
((long)ReadByte() >> 32) |
((long)ReadByte() >> 24) |
((long)ReadByte() >> 16) |
((long)ReadByte() >> 8) |
ReadByte();
}
}
else if (!BinaryPrimitives.TryReadInt64BigEndian(_second[(Position - _first.Length)..], out value))
{
throw new OutOfMemoryException();
}
Position += 8;
return value;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public ulong ReadUInt64()
{
ulong value;
if (Position < _first.Length)
{
if (!BinaryPrimitives.TryReadUInt64BigEndian(_first[Position..], out value))
{
// Not enough space. Split the spans
return ((ulong)ReadByte() >> 56) |
((ulong)ReadByte() >> 48) |
((ulong)ReadByte() >> 40) |
((ulong)ReadByte() >> 32) |
((ulong)ReadByte() >> 24) |
((ulong)ReadByte() >> 16) |
((ulong)ReadByte() >> 8) |
ReadByte();
}
}
else if (!BinaryPrimitives.TryReadUInt64BigEndian(_second[(Position - _first.Length)..], out value))
{
throw new OutOfMemoryException();
}
Position += 8;
return value;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public string ReadString(Encoding encoding, bool safeString = false, int fixedLength = -1)
{
int byteLength = encoding.GetByteLengthForEncoding();
bool isFixedLength = fixedLength > -1;
var remaining = Remaining;
int size;
if (isFixedLength)
{
size = fixedLength * byteLength;
if (size > Remaining)
{
throw new OutOfMemoryException();
}
}
else
{
size = remaining - (remaining & (byteLength - 1));
}
ReadOnlySpan<byte> span;
int index;
if (Position < _first.Length)
{
var firstLength = Math.Min(_first.Length - Position, size);
// Find terminator
index = _first.Slice(Position, firstLength).IndexOfTerminator(byteLength);
if (index < 0)
{
remaining = size - firstLength;
// We don't have a terminator, but a fixed size to the end of the first span, so stop there
if (remaining <= 0)
{
index = firstLength;
}
else
{
index = _second[..remaining].IndexOfTerminator(byteLength);
int secondLength = index < 0 ? remaining : index;
int length = firstLength + secondLength;
// Assume no strings should be too long for the stack
Span<byte> bytes = stackalloc byte[length];
_first[Position..].CopyTo(bytes);
_second[..secondLength].CopyTo(bytes[firstLength..]);
Position += length + (index >= 0 ? byteLength : 0);
return TextEncoding.GetString(bytes, encoding, safeString);
}
}
span = _first.Slice(Position, index);
}
else
{
size = Math.Min(remaining, size);
span = _second.Slice( Position - _first.Length, size);
index = span.IndexOfTerminator(byteLength);
if (index >= 0)
{
span = span[..index];
index = firstLength;
}
else
{
index = size;
index = _second[..remaining].IndexOfTerminator(byteLength);
int secondLength = index < 0 ? remaining : index;
int length = firstLength + secondLength;
// Assume no strings should be too long for the stack
Span<byte> bytes = stackalloc byte[length];
_first[Position..].CopyTo(bytes);
_second[..secondLength].CopyTo(bytes[firstLength..]);
Position += length + (index >= 0 ? byteLength : 0);
return TextEncoding.GetString(bytes, encoding, safeString);
}
}
Position += isFixedLength ? size : index + byteLength;
return TextEncoding.GetString(span, encoding, safeString);
span = _first.Slice(Position, index);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public string ReadLittleUniSafe(int fixedLength) => ReadString(TextEncoding.UnicodeLE, true, fixedLength);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public string ReadLittleUniSafe() => ReadString(TextEncoding.UnicodeLE, true);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public string ReadLittleUni(int fixedLength) => ReadString(TextEncoding.UnicodeLE, false, fixedLength);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public string ReadLittleUni() => ReadString(TextEncoding.UnicodeLE);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public string ReadBigUniSafe(int fixedLength) => ReadString(TextEncoding.Unicode, true, fixedLength);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public string ReadBigUniSafe() => ReadString(TextEncoding.Unicode, true);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public string ReadBigUni(int fixedLength) => ReadString(TextEncoding.Unicode, false, fixedLength);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public string ReadBigUni() => ReadString(TextEncoding.Unicode);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public string ReadUTF8Safe(int fixedLength) => ReadString(TextEncoding.UTF8, true, fixedLength);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public string ReadUTF8Safe() => ReadString(TextEncoding.UTF8, true);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public string ReadUTF8() => ReadString(TextEncoding.UTF8);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public string ReadAsciiSafe(int fixedLength) => ReadString(Encoding.ASCII, true, fixedLength);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public string ReadAsciiSafe() => ReadString(Encoding.ASCII, true);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public string ReadAscii(int fixedLength) => ReadString(Encoding.ASCII, false, fixedLength);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public string ReadAscii() => ReadString(Encoding.ASCII);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public int Seek(int offset, SeekOrigin origin) =>
Position = origin switch
{
SeekOrigin.Begin => offset,
SeekOrigin.End => Length + offset,
_ => Position + offset // Current
};
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Read(Span<byte> bytes)
else
{
if (bytes.Length < Length)
{
throw new ArgumentOutOfRangeException(nameof(bytes));
}
size = Math.Min(remaining, size);
span = _second.Slice( Position - _first.Length, size);
index = span.IndexOfTerminator(byteLength);
if (_first.Length > 0 && !_first.TryCopyTo(bytes))
if (index >= 0)
{
return false;
span = span[..index];
}
else
{
index = size;
}
return _second.Length <= 0 || _second.TryCopyTo(bytes[_first.Length..]);
}
Position += isFixedLength ? size : index + byteLength;
return TextEncoding.GetString(span, encoding, safeString);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public string ReadLittleUniSafe(int fixedLength) => ReadString(TextEncoding.UnicodeLE, true, fixedLength);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public string ReadLittleUniSafe() => ReadString(TextEncoding.UnicodeLE, true);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public string ReadLittleUni(int fixedLength) => ReadString(TextEncoding.UnicodeLE, false, fixedLength);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public string ReadLittleUni() => ReadString(TextEncoding.UnicodeLE);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public string ReadBigUniSafe(int fixedLength) => ReadString(TextEncoding.Unicode, true, fixedLength);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public string ReadBigUniSafe() => ReadString(TextEncoding.Unicode, true);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public string ReadBigUni(int fixedLength) => ReadString(TextEncoding.Unicode, false, fixedLength);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public string ReadBigUni() => ReadString(TextEncoding.Unicode);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public string ReadUTF8Safe(int fixedLength) => ReadString(TextEncoding.UTF8, true, fixedLength);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public string ReadUTF8Safe() => ReadString(TextEncoding.UTF8, true);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public string ReadUTF8() => ReadString(TextEncoding.UTF8);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public string ReadAsciiSafe(int fixedLength) => ReadString(Encoding.ASCII, true, fixedLength);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public string ReadAsciiSafe() => ReadString(Encoding.ASCII, true);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public string ReadAscii(int fixedLength) => ReadString(Encoding.ASCII, false, fixedLength);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public string ReadAscii() => ReadString(Encoding.ASCII);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public int Seek(int offset, SeekOrigin origin) =>
Position = origin switch
{
SeekOrigin.Begin => offset,
SeekOrigin.End => Length + offset,
_ => Position + offset // Current
};
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Read(Span<byte> bytes)
{
if (bytes.Length < Length)
{
throw new ArgumentOutOfRangeException(nameof(bytes));
}
if (_first.Length > 0 && !_first.TryCopyTo(bytes))
{
return false;
}
return _second.Length <= 0 || _second.TryCopyTo(bytes[_first.Length..]);
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: SpanReader.cs *
* *
@ -21,273 +21,272 @@ using System.Text;
using Server;
using Server.Text;
namespace System.Buffers
namespace System.Buffers;
public ref struct SpanReader
{
public ref struct SpanReader
private readonly ReadOnlySpan<byte> _buffer;
public int Length { get; }
public int Position { get; private set; }
public int Remaining => Length - Position;
public SpanReader(ReadOnlySpan<byte> span)
{
private readonly ReadOnlySpan<byte> _buffer;
_buffer = span;
Position = 0;
Length = span.Length;
}
public int Length { get; }
public int Position { get; private set; }
public int Remaining => Length - Position;
public SpanReader(ReadOnlySpan<byte> span)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public byte ReadByte()
{
if (Position >= Length)
{
_buffer = span;
Position = 0;
Length = span.Length;
throw new OutOfMemoryException();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public byte ReadByte()
return _buffer[Position++];
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool ReadBoolean() => ReadByte() > 0;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public sbyte ReadSByte() => (sbyte)ReadByte();
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public short ReadInt16()
{
if (!BinaryPrimitives.TryReadInt16BigEndian(_buffer[Position..], out var value))
{
if (Position >= Length)
throw new OutOfMemoryException();
}
Position += 2;
return value;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public short ReadInt16LE()
{
if (!BinaryPrimitives.TryReadInt16LittleEndian(_buffer[Position..], out var value))
{
throw new OutOfMemoryException();
}
Position += 2;
return value;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public ushort ReadUInt16()
{
if (!BinaryPrimitives.TryReadUInt16BigEndian(_buffer[Position..], out var value))
{
throw new OutOfMemoryException();
}
Position += 2;
return value;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public ushort ReadUInt16LE()
{
if (!BinaryPrimitives.TryReadUInt16LittleEndian(_buffer[Position..], out var value))
{
throw new OutOfMemoryException();
}
Position += 2;
return value;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public int ReadInt32()
{
if (!BinaryPrimitives.TryReadInt32BigEndian(_buffer[Position..], out var value))
{
throw new OutOfMemoryException();
}
Position += 4;
return value;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public uint ReadUInt32()
{
if (!BinaryPrimitives.TryReadUInt32BigEndian(_buffer[Position..], out var value))
{
throw new OutOfMemoryException();
}
Position += 4;
return value;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public uint ReadUInt32LE()
{
if (!BinaryPrimitives.TryReadUInt32LittleEndian(_buffer[Position..], out var value))
{
throw new OutOfMemoryException();
}
Position += 4;
return value;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public long ReadInt64()
{
if (!BinaryPrimitives.TryReadInt64BigEndian(_buffer[Position..], out var value))
{
throw new OutOfMemoryException();
}
Position += 8;
return value;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public ulong ReadUInt64()
{
if (!BinaryPrimitives.TryReadUInt64BigEndian(_buffer[Position..], out var value))
{
throw new OutOfMemoryException();
}
Position += 8;
return value;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public string ReadString(Encoding encoding, bool safeString = false, int fixedLength = -1)
{
int byteLength = encoding.GetByteLengthForEncoding();
bool isFixedLength = fixedLength > -1;
var remaining = Remaining;
int size;
if (isFixedLength)
{
size = fixedLength * byteLength;
if (size > Remaining)
{
throw new OutOfMemoryException();
}
return _buffer[Position++];
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool ReadBoolean() => ReadByte() > 0;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public sbyte ReadSByte() => (sbyte)ReadByte();
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public short ReadInt16()
else
{
if (!BinaryPrimitives.TryReadInt16BigEndian(_buffer[Position..], out var value))
{
throw new OutOfMemoryException();
}
Position += 2;
return value;
// In case the remaining is not evenly divisible
size = remaining - (remaining & (byteLength - 1));
int index = _buffer.Slice(Position, size).IndexOfTerminator(byteLength);
size = index < 0 ? size : index;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public short ReadInt16LE()
var span = _buffer.Slice(Position, size);
Position += size;
return TextEncoding.GetString(span, encoding, safeString);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public string ReadLittleUniSafe(int fixedLength) => ReadString(TextEncoding.UnicodeLE, true, fixedLength);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public string ReadLittleUniSafe() => ReadString(TextEncoding.UnicodeLE, true);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public string ReadLittleUni(int fixedLength) => ReadString(TextEncoding.UnicodeLE, false, fixedLength);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public string ReadLittleUni() => ReadString(TextEncoding.UnicodeLE);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public string ReadBigUniSafe(int fixedLength) => ReadString(TextEncoding.Unicode, true, fixedLength);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public string ReadBigUniSafe() => ReadString(TextEncoding.Unicode, true);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public string ReadBigUni(int fixedLength) => ReadString(TextEncoding.Unicode, false, fixedLength);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public string ReadBigUni() => ReadString(TextEncoding.Unicode);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public string ReadUTF8Safe(int fixedLength) => ReadString(TextEncoding.UTF8, true, fixedLength);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public string ReadUTF8Safe() => ReadString(TextEncoding.UTF8, true);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public string ReadUTF8() => ReadString(TextEncoding.UTF8);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public string ReadAsciiSafe(int fixedLength) => ReadString(Encoding.ASCII, true, fixedLength);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public string ReadAsciiSafe() => ReadString(Encoding.ASCII, true);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public string ReadAscii(int fixedLength) => ReadString(Encoding.ASCII, false, fixedLength);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public string ReadAscii() => ReadString(Encoding.ASCII);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public int Seek(int offset, SeekOrigin origin)
{
Debug.Assert(
origin != SeekOrigin.End || offset <= 0,
"Attempting to seek to a position beyond capacity using SeekOrigin.End"
);
Debug.Assert(
origin != SeekOrigin.End || offset >= -_buffer.Length,
"Attempting to seek to a negative position using SeekOrigin.End"
);
Debug.Assert(
origin != SeekOrigin.Begin || offset >= 0,
"Attempting to seek to a negative position using SeekOrigin.Begin"
);
Debug.Assert(
origin != SeekOrigin.Begin || offset <= _buffer.Length,
"Attempting to seek to a position beyond the capacity using SeekOrigin.Begin"
);
Debug.Assert(
origin != SeekOrigin.Current || Position + offset >= 0,
"Attempting to seek to a negative position using SeekOrigin.Current"
);
Debug.Assert(
origin != SeekOrigin.Current || Position + offset <= _buffer.Length,
"Attempting to seek to a position beyond the capacity using SeekOrigin.Current"
);
return Position = Math.Max(0, origin switch
{
if (!BinaryPrimitives.TryReadInt16LittleEndian(_buffer[Position..], out var value))
{
throw new OutOfMemoryException();
}
SeekOrigin.Current => Position + offset,
SeekOrigin.End => _buffer.Length + offset,
_ => offset // Begin
});
}
Position += 2;
return value;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public ushort ReadUInt16()
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Read(Span<byte> bytes)
{
if (bytes.Length < Length)
{
if (!BinaryPrimitives.TryReadUInt16BigEndian(_buffer[Position..], out var value))
{
throw new OutOfMemoryException();
}
Position += 2;
return value;
throw new ArgumentOutOfRangeException(nameof(bytes));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public ushort ReadUInt16LE()
{
if (!BinaryPrimitives.TryReadUInt16LittleEndian(_buffer[Position..], out var value))
{
throw new OutOfMemoryException();
}
Position += 2;
return value;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public int ReadInt32()
{
if (!BinaryPrimitives.TryReadInt32BigEndian(_buffer[Position..], out var value))
{
throw new OutOfMemoryException();
}
Position += 4;
return value;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public uint ReadUInt32()
{
if (!BinaryPrimitives.TryReadUInt32BigEndian(_buffer[Position..], out var value))
{
throw new OutOfMemoryException();
}
Position += 4;
return value;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public uint ReadUInt32LE()
{
if (!BinaryPrimitives.TryReadUInt32LittleEndian(_buffer[Position..], out var value))
{
throw new OutOfMemoryException();
}
Position += 4;
return value;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public long ReadInt64()
{
if (!BinaryPrimitives.TryReadInt64BigEndian(_buffer[Position..], out var value))
{
throw new OutOfMemoryException();
}
Position += 8;
return value;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public ulong ReadUInt64()
{
if (!BinaryPrimitives.TryReadUInt64BigEndian(_buffer[Position..], out var value))
{
throw new OutOfMemoryException();
}
Position += 8;
return value;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public string ReadString(Encoding encoding, bool safeString = false, int fixedLength = -1)
{
int byteLength = encoding.GetByteLengthForEncoding();
bool isFixedLength = fixedLength > -1;
var remaining = Remaining;
int size;
if (isFixedLength)
{
size = fixedLength * byteLength;
if (size > Remaining)
{
throw new OutOfMemoryException();
}
}
else
{
// In case the remaining is not evenly divisible
size = remaining - (remaining & (byteLength - 1));
int index = _buffer.Slice(Position, size).IndexOfTerminator(byteLength);
size = index < 0 ? size : index;
}
var span = _buffer.Slice(Position, size);
Position += size;
return TextEncoding.GetString(span, encoding, safeString);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public string ReadLittleUniSafe(int fixedLength) => ReadString(TextEncoding.UnicodeLE, true, fixedLength);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public string ReadLittleUniSafe() => ReadString(TextEncoding.UnicodeLE, true);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public string ReadLittleUni(int fixedLength) => ReadString(TextEncoding.UnicodeLE, false, fixedLength);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public string ReadLittleUni() => ReadString(TextEncoding.UnicodeLE);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public string ReadBigUniSafe(int fixedLength) => ReadString(TextEncoding.Unicode, true, fixedLength);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public string ReadBigUniSafe() => ReadString(TextEncoding.Unicode, true);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public string ReadBigUni(int fixedLength) => ReadString(TextEncoding.Unicode, false, fixedLength);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public string ReadBigUni() => ReadString(TextEncoding.Unicode);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public string ReadUTF8Safe(int fixedLength) => ReadString(TextEncoding.UTF8, true, fixedLength);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public string ReadUTF8Safe() => ReadString(TextEncoding.UTF8, true);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public string ReadUTF8() => ReadString(TextEncoding.UTF8);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public string ReadAsciiSafe(int fixedLength) => ReadString(Encoding.ASCII, true, fixedLength);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public string ReadAsciiSafe() => ReadString(Encoding.ASCII, true);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public string ReadAscii(int fixedLength) => ReadString(Encoding.ASCII, false, fixedLength);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public string ReadAscii() => ReadString(Encoding.ASCII);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public int Seek(int offset, SeekOrigin origin)
{
Debug.Assert(
origin != SeekOrigin.End || offset <= 0,
"Attempting to seek to a position beyond capacity using SeekOrigin.End"
);
Debug.Assert(
origin != SeekOrigin.End || offset >= -_buffer.Length,
"Attempting to seek to a negative position using SeekOrigin.End"
);
Debug.Assert(
origin != SeekOrigin.Begin || offset >= 0,
"Attempting to seek to a negative position using SeekOrigin.Begin"
);
Debug.Assert(
origin != SeekOrigin.Begin || offset <= _buffer.Length,
"Attempting to seek to a position beyond the capacity using SeekOrigin.Begin"
);
Debug.Assert(
origin != SeekOrigin.Current || Position + offset >= 0,
"Attempting to seek to a negative position using SeekOrigin.Current"
);
Debug.Assert(
origin != SeekOrigin.Current || Position + offset <= _buffer.Length,
"Attempting to seek to a position beyond the capacity using SeekOrigin.Current"
);
return Position = Math.Max(0, origin switch
{
SeekOrigin.Current => Position + offset,
SeekOrigin.End => _buffer.Length + offset,
_ => offset // Begin
});
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Read(Span<byte> bytes)
{
if (bytes.Length < Length)
{
throw new ArgumentOutOfRangeException(nameof(bytes));
}
return _buffer.TryCopyTo(bytes);
}
return _buffer.TryCopyTo(bytes);
}
}

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: CityInfo.cs *
* *
@ -13,71 +13,70 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
*************************************************************************/
namespace Server
namespace Server;
public sealed class CityInfo
{
public sealed class CityInfo
private Point3D m_Location;
public CityInfo(string city, string building, int description, int x, int y, int z, Map m)
{
private Point3D m_Location;
public CityInfo(string city, string building, int description, int x, int y, int z, Map m)
{
City = city;
Building = building;
Description = description;
Location = new Point3D(x, y, z);
Map = m;
}
public CityInfo(string city, string building, int x, int y, int z, Map m) : this(city, building, 0, x, y, z, m)
{
}
public CityInfo(string city, string building, int description, int x, int y, int z) : this(
city,
building,
description,
x,
y,
z,
Map.Trammel
)
{
}
public CityInfo(string city, string building, int x, int y, int z) : this(city, building, 0, x, y, z, Map.Trammel)
{
}
public string City { get; set; }
public string Building { get; set; }
public int Description { get; set; }
public int X
{
get => m_Location.X;
set => m_Location.X = value;
}
public int Y
{
get => m_Location.Y;
set => m_Location.Y = value;
}
public int Z
{
get => m_Location.Z;
set => m_Location.Z = value;
}
public Point3D Location
{
get => m_Location;
set => m_Location = value;
}
public Map Map { get; set; }
City = city;
Building = building;
Description = description;
Location = new Point3D(x, y, z);
Map = m;
}
public CityInfo(string city, string building, int x, int y, int z, Map m) : this(city, building, 0, x, y, z, m)
{
}
public CityInfo(string city, string building, int description, int x, int y, int z) : this(
city,
building,
description,
x,
y,
z,
Map.Trammel
)
{
}
public CityInfo(string city, string building, int x, int y, int z) : this(city, building, 0, x, y, z, Map.Trammel)
{
}
public string City { get; set; }
public string Building { get; set; }
public int Description { get; set; }
public int X
{
get => m_Location.X;
set => m_Location.X = value;
}
public int Y
{
get => m_Location.Y;
set => m_Location.Y = value;
}
public int Z
{
get => m_Location.Z;
set => m_Location.Z = value;
}
public Point3D Location
{
get => m_Location;
set => m_Location = value;
}
public Map Map { get; set; }
}

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright (C) 2019-2021 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: ArrayEnumerator.cs *
* *
@ -17,63 +17,62 @@ using System;
using System.Collections;
using System.Collections.Generic;
namespace Server.Collections
namespace Server.Collections;
/// <summary>
/// Non-thread safe, non-guarded enumerator for classes that have internal arrays.
/// Recommended to copy this and use it as a nested struct.
/// Recommend adding version checking to properly guard against modification during enumeration.
/// </summary>
/// <typeparam name="T"></typeparam>
public struct ArrayEnumerator<T> : IEnumerator<T>
{
/// <summary>
/// Non-thread safe, non-guarded enumerator for classes that have internal arrays.
/// Recommended to copy this and use it as a nested struct.
/// Recommend adding version checking to properly guard against modification during enumeration.
/// </summary>
/// <typeparam name="T"></typeparam>
public struct ArrayEnumerator<T> : IEnumerator<T>
private readonly T[] _array;
private int _index;
private T? _current;
public ArrayEnumerator(T[] array)
{
private readonly T[] _array;
private int _index;
private T? _current;
_array = array;
_index = 0;
_current = default;
}
public ArrayEnumerator(T[] array)
public void Dispose()
{
}
public bool MoveNext()
{
T[] localList = _array;
if ((uint)_index < (uint)localList.Length)
{
_array = array;
_index = 0;
_current = default;
_current = _array[_index++];
return true;
}
public void Dispose()
{
}
return false;
}
public bool MoveNext()
{
T[] localList = _array;
public T? Current => _current!;
if ((uint)_index < (uint)localList.Length)
object IEnumerator.Current
{
get
{
if (_index == 0 || _index == _array.Length + 1)
{
_current = _array[_index++];
return true;
throw new InvalidOperationException(nameof(_index));
}
return false;
}
public T? Current => _current!;
object IEnumerator.Current
{
get
{
if (_index == 0 || _index == _array.Length + 1)
{
throw new InvalidOperationException(nameof(_index));
}
return _current;
}
}
void IEnumerator.Reset()
{
_index = 0;
_current = default;
return _current;
}
}
void IEnumerator.Reset()
{
_index = 0;
_current = default;
}
}

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright (C) 2019-2021 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: CollectionHelpers.cs *
* *
@ -16,17 +16,16 @@
using System.Collections.Generic;
using System.Runtime.CompilerServices;
namespace Server.Collections
namespace Server.Collections;
public static class CollectionHelpers
{
public static class CollectionHelpers
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void AddNotNull<T>(this ICollection<T> coll, T t) where T : class
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void AddNotNull<T>(this ICollection<T> coll, T t) where T : class
if (t != null)
{
if (t != null)
{
coll.Add(t);
}
coll.Add(t);
}
}
}

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2021 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: CollectionThrowStrings.cs *
* *

View file

@ -6,120 +6,119 @@ using System;
using System.Diagnostics;
using System.Runtime.CompilerServices;
namespace Microsoft.Collections.Extensions
namespace Microsoft.Collections.Extensions;
internal static class HashHelpers
{
internal static class HashHelpers
// must never be written to
internal static readonly int[] SizeOneIntArray = new int[1];
// This is the maximum prime smaller than Array.MaxArrayLength
public const int MaxPrimeArrayLength = 0x7FEFFFFD;
public const int HashPrime = 101;
// Table of prime numbers to use as hash table sizes.
// A typical resize algorithm would pick the smallest prime number in this array
// that is larger than twice the previous capacity.
// Suppose our Hashtable currently has capacity x and enough elements are added
// such that a resize needs to occur. Resizing first computes 2x then finds the
// first prime in the table greater than 2x, i.e. if primes are ordered
// p_1, p_2, ..., p_i, ..., it finds p_n such that p_n-1 < 2x < p_n.
// Doubling is important for preserving the asymptotic complexity of the
// hashtable operations such as add. Having a prime guarantees that double
// hashing does not lead to infinite loops. IE, your hash function will be
// h1(key) + i*h2(key), 0 <= i < size. h2 and the size must be relatively prime.
// We prefer the low computation costs of higher prime numbers over the increased
// memory allocation of a fixed prime number i.e. when right sizing a HashSet.
public static readonly int[] primes = {
3, 7, 11, 17, 23, 29, 37, 47, 59, 71, 89, 107, 131, 163, 197, 239, 293, 353, 431, 521, 631, 761, 919,
1103, 1327, 1597, 1931, 2333, 2801, 3371, 4049, 4861, 5839, 7013, 8419, 10103, 12143, 14591,
17519, 21023, 25229, 30293, 36353, 43627, 52361, 62851, 75431, 90523, 108631, 130363, 156437,
187751, 225307, 270371, 324449, 389357, 467237, 560689, 672827, 807403, 968897, 1162687, 1395263,
1674319, 2009191, 2411033, 2893249, 3471899, 4166287, 4999559, 5999471, 7199369 };
public static bool IsPrime(int candidate)
{
// must never be written to
internal static readonly int[] SizeOneIntArray = new int[1];
// This is the maximum prime smaller than Array.MaxArrayLength
public const int MaxPrimeArrayLength = 0x7FEFFFFD;
public const int HashPrime = 101;
// Table of prime numbers to use as hash table sizes.
// A typical resize algorithm would pick the smallest prime number in this array
// that is larger than twice the previous capacity.
// Suppose our Hashtable currently has capacity x and enough elements are added
// such that a resize needs to occur. Resizing first computes 2x then finds the
// first prime in the table greater than 2x, i.e. if primes are ordered
// p_1, p_2, ..., p_i, ..., it finds p_n such that p_n-1 < 2x < p_n.
// Doubling is important for preserving the asymptotic complexity of the
// hashtable operations such as add. Having a prime guarantees that double
// hashing does not lead to infinite loops. IE, your hash function will be
// h1(key) + i*h2(key), 0 <= i < size. h2 and the size must be relatively prime.
// We prefer the low computation costs of higher prime numbers over the increased
// memory allocation of a fixed prime number i.e. when right sizing a HashSet.
public static readonly int[] primes = {
3, 7, 11, 17, 23, 29, 37, 47, 59, 71, 89, 107, 131, 163, 197, 239, 293, 353, 431, 521, 631, 761, 919,
1103, 1327, 1597, 1931, 2333, 2801, 3371, 4049, 4861, 5839, 7013, 8419, 10103, 12143, 14591,
17519, 21023, 25229, 30293, 36353, 43627, 52361, 62851, 75431, 90523, 108631, 130363, 156437,
187751, 225307, 270371, 324449, 389357, 467237, 560689, 672827, 807403, 968897, 1162687, 1395263,
1674319, 2009191, 2411033, 2893249, 3471899, 4166287, 4999559, 5999471, 7199369 };
public static bool IsPrime(int candidate)
if ((candidate & 1) != 0)
{
if ((candidate & 1) != 0)
int limit = (int)Math.Sqrt(candidate);
for (int divisor = 3; divisor <= limit; divisor += 2)
{
int limit = (int)Math.Sqrt(candidate);
for (int divisor = 3; divisor <= limit; divisor += 2)
if (candidate % divisor == 0)
{
if (candidate % divisor == 0)
{
return false;
}
}
return true;
}
return candidate == 2;
}
public static int GetPrime(int min)
{
if (min < 0)
{
throw new ArgumentException("Hashtable's capacity overflowed and went negative. Check load factor, capacity and the current size of the table.");
}
for (int i = 0; i < primes.Length; i++)
{
int prime = primes[i];
if (prime >= min)
{
return prime;
return false;
}
}
//outside of our predefined table.
//compute the hard way.
for (int i = min | 1; i < int.MaxValue; i += 2)
{
if (IsPrime(i) && (i - 1) % HashPrime != 0)
{
return i;
}
}
return min;
return true;
}
return candidate == 2;
}
// Returns size of hashtable to grow to.
public static int ExpandPrime(int oldSize)
public static int GetPrime(int min)
{
if (min < 0)
{
int newSize = 2 * oldSize;
// Allow the hashtables to grow to maximum possible size (~2G elements) before encountering capacity overflow.
// Note that this check works even when _items.Length overflowed thanks to the (uint) cast
if ((uint)newSize > MaxPrimeArrayLength && MaxPrimeArrayLength > oldSize)
{
Debug.Assert(MaxPrimeArrayLength == GetPrime(MaxPrimeArrayLength), "Invalid MaxPrimeArrayLength");
return MaxPrimeArrayLength;
}
return GetPrime(newSize);
throw new ArgumentException("Hashtable's capacity overflowed and went negative. Check load factor, capacity and the current size of the table.");
}
/// <summary>Returns approximate reciprocal of the divisor: ceil(2**64 / divisor).</summary>
/// <remarks>This should only be used on 64-bit.</remarks>
public static ulong GetFastModMultiplier(uint divisor) =>
ulong.MaxValue / divisor + 1;
/// <summary>Performs a mod operation using the multiplier pre-computed with <see cref="GetFastModMultiplier"/>.</summary>
/// <remarks>This should only be used on 64-bit.</remarks>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static uint FastMod(uint value, uint divisor, ulong multiplier)
for (int i = 0; i < primes.Length; i++)
{
// We use modified Daniel Lemire's fastmod algorithm (https://github.com/dotnet/runtime/pull/406),
// which allows to avoid the long multiplication if the divisor is less than 2**31.
Debug.Assert(divisor <= int.MaxValue);
// This is equivalent of (uint)Math.BigMul(multiplier * value, divisor, out _). This version
// is faster than BigMul currently because we only need the high bits.
uint highbits = (uint)(((((multiplier * value) >> 32) + 1) * divisor) >> 32);
Debug.Assert(highbits == value % divisor);
return highbits;
int prime = primes[i];
if (prime >= min)
{
return prime;
}
}
//outside of our predefined table.
//compute the hard way.
for (int i = min | 1; i < int.MaxValue; i += 2)
{
if (IsPrime(i) && (i - 1) % HashPrime != 0)
{
return i;
}
}
return min;
}
// Returns size of hashtable to grow to.
public static int ExpandPrime(int oldSize)
{
int newSize = 2 * oldSize;
// Allow the hashtables to grow to maximum possible size (~2G elements) before encountering capacity overflow.
// Note that this check works even when _items.Length overflowed thanks to the (uint) cast
if ((uint)newSize > MaxPrimeArrayLength && MaxPrimeArrayLength > oldSize)
{
Debug.Assert(MaxPrimeArrayLength == GetPrime(MaxPrimeArrayLength), "Invalid MaxPrimeArrayLength");
return MaxPrimeArrayLength;
}
return GetPrime(newSize);
}
/// <summary>Returns approximate reciprocal of the divisor: ceil(2**64 / divisor).</summary>
/// <remarks>This should only be used on 64-bit.</remarks>
public static ulong GetFastModMultiplier(uint divisor) =>
ulong.MaxValue / divisor + 1;
/// <summary>Performs a mod operation using the multiplier pre-computed with <see cref="GetFastModMultiplier"/>.</summary>
/// <remarks>This should only be used on 64-bit.</remarks>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static uint FastMod(uint value, uint divisor, ulong multiplier)
{
// We use modified Daniel Lemire's fastmod algorithm (https://github.com/dotnet/runtime/pull/406),
// which allows to avoid the long multiplication if the divisor is less than 2**31.
Debug.Assert(divisor <= int.MaxValue);
// This is equivalent of (uint)Math.BigMul(multiplier * value, divisor, out _). This version
// is faster than BigMul currently because we only need the high bits.
uint highbits = (uint)(((((multiplier * value) >> 32) + 1) * divisor) >> 32);
Debug.Assert(highbits == value % divisor);
return highbits;
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2021 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: PooledOrderedHashSet.cs *
* *

View file

@ -2,240 +2,230 @@ using System;
using System.Collections.Generic;
using Server.Network;
namespace Server
namespace Server;
public delegate void CommandEventHandler(CommandEventArgs e);
public class CommandEventArgs
{
public delegate void CommandEventHandler(CommandEventArgs e);
public class CommandEventArgs
public CommandEventArgs(Mobile mobile, string command, string argString, string[] arguments)
{
public CommandEventArgs(Mobile mobile, string command, string argString, string[] arguments)
{
Mobile = mobile;
Command = command;
ArgString = argString;
Arguments = arguments;
}
public Mobile Mobile { get; }
public string Command { get; }
public string ArgString { get; }
public string[] Arguments { get; }
public int Length => Arguments.Length;
public string GetString(int index) => index < 0 || index >= Arguments.Length ? "" : Arguments[index];
public int GetInt32(int index) => index < 0 || index >= Arguments.Length ? 0 : Utility.ToInt32(Arguments[index]);
public uint GetUInt32(int index) =>
index < 0 || index >= Arguments.Length ? 0 : Utility.ToUInt32(Arguments[index]);
public bool GetBoolean(int index) => index >= 0 && index < Arguments.Length && Utility.ToBoolean(Arguments[index]);
public double GetDouble(int index) =>
index < 0 || index >= Arguments.Length ? 0.0 : Utility.ToDouble(Arguments[index]);
public TimeSpan GetTimeSpan(int index) =>
index < 0 || index >= Arguments.Length ? TimeSpan.Zero : Utility.ToTimeSpan(Arguments[index]);
Mobile = mobile;
Command = command;
ArgString = argString;
Arguments = arguments;
}
public static partial class EventSink
public Mobile Mobile { get; }
public string Command { get; }
public string ArgString { get; }
public string[] Arguments { get; }
public int Length => Arguments.Length;
public string GetString(int index) => index < 0 || index >= Arguments.Length ? "" : Arguments[index];
public int GetInt32(int index) => index < 0 || index >= Arguments.Length ? 0 : Utility.ToInt32(Arguments[index]);
public uint GetUInt32(int index) =>
index < 0 || index >= Arguments.Length ? 0 : Utility.ToUInt32(Arguments[index]);
public bool GetBoolean(int index) => index >= 0 && index < Arguments.Length && Utility.ToBoolean(Arguments[index]);
public double GetDouble(int index) =>
index < 0 || index >= Arguments.Length ? 0.0 : Utility.ToDouble(Arguments[index]);
public TimeSpan GetTimeSpan(int index) =>
index < 0 || index >= Arguments.Length ? TimeSpan.Zero : Utility.ToTimeSpan(Arguments[index]);
}
public static partial class EventSink
{
public static event Action<CommandEventArgs> Command;
public static void InvokeCommand(CommandEventArgs e) => Command?.Invoke(e);
}
public class CommandEntry : IComparable<CommandEntry>
{
public CommandEntry(string command, CommandEventHandler handler, AccessLevel accessLevel)
{
public static event Action<CommandEventArgs> Command;
public static void InvokeCommand(CommandEventArgs e) => Command?.Invoke(e);
Command = command;
Handler = handler;
AccessLevel = accessLevel;
}
public class CommandEntry : IComparable<CommandEntry>
public string Command { get; }
public CommandEventHandler Handler { get; }
public AccessLevel AccessLevel { get; }
public int CompareTo(CommandEntry e) => string.CompareOrdinal(Command, e?.Command);
public static List<CommandEntry> GetList()
{
public CommandEntry(string command, CommandEventHandler handler, AccessLevel accessLevel)
var commands = new List<CommandEntry>(CommandSystem.Entries.Values);
commands.Sort();
commands.Reverse();
for (var i = 0; i < commands.Count; ++i)
{
Command = command;
Handler = handler;
AccessLevel = accessLevel;
}
var e = commands[i];
public string Command { get; }
public CommandEventHandler Handler { get; }
public AccessLevel AccessLevel { get; }
public int CompareTo(CommandEntry e) => string.CompareOrdinal(Command, e?.Command);
public static List<CommandEntry> GetList()
{
var commands = new List<CommandEntry>(CommandSystem.Entries.Values);
commands.Sort();
commands.Reverse();
for (var i = 0; i < commands.Count; ++i)
for (var j = i + 1; j < commands.Count; ++j)
{
var e = commands[i];
var c = commands[j];
for (var j = i + 1; j < commands.Count; ++j)
if (e.Handler.Method == c.Handler.Method)
{
var c = commands[j];
commands.RemoveAt(j);
--j;
}
}
}
if (e.Handler.Method == c.Handler.Method)
return commands;
}
}
public record CommandInfo(AccessLevel AccessLevel, string Name, string[] Aliases, string Usage, string Description);
public class CommandInfoSorter : IComparer<CommandInfo>
{
public int Compare(CommandInfo a, CommandInfo b)
{
if (a == null && b == null)
{
return 0;
}
var v = b?.AccessLevel.CompareTo(a?.AccessLevel) ?? 1;
return v != 0 ? v : string.CompareOrdinal(a?.Name, b?.Name);
}
}
public static class CommandSystem
{
public static string Prefix { get; set; } = "[";
public static Dictionary<string, CommandEntry> Entries { get; } = new(StringComparer.OrdinalIgnoreCase);
public static AccessLevel BadCommandIgnoreLevel { get; set; } = AccessLevel.Player;
public static string[] Split(string value)
{
var array = value.ToCharArray();
var list = new List<string>();
var start = 0;
while (start < array.Length)
{
var c = array[start];
if (c == '"')
{
++start;
var end = start;
while (end < array.Length)
{
if (array[end] != '"' || array[end - 1] == '\\')
{
commands.RemoveAt(j);
--j;
++end;
}
else
{
break;
}
}
list.Add(value.Substring(start, end - start));
start = end + 2;
}
return commands;
}
}
public record CommandInfo(AccessLevel AccessLevel, string Name, string[] Aliases, string Usage, string Description);
public class CommandInfoSorter : IComparer<CommandInfo>
{
public int Compare(CommandInfo a, CommandInfo b)
{
if (a == null && b == null)
else if (c != ' ')
{
return 0;
}
var end = start;
var v = b?.AccessLevel.CompareTo(a?.AccessLevel) ?? 1;
return v != 0 ? v : string.CompareOrdinal(a?.Name, b?.Name);
}
}
public static class CommandSystem
{
public static string Prefix { get; set; } = "[";
public static Dictionary<string, CommandEntry> Entries { get; } = new(StringComparer.OrdinalIgnoreCase);
public static AccessLevel BadCommandIgnoreLevel { get; set; } = AccessLevel.Player;
public static string[] Split(string value)
{
var array = value.ToCharArray();
var list = new List<string>();
var start = 0;
while (start < array.Length)
{
var c = array[start];
if (c == '"')
while (end < array.Length)
{
++start;
var end = start;
while (end < array.Length)
if (array[end] != ' ')
{
if (array[end] != '"' || array[end - 1] == '\\')
{
++end;
}
else
{
break;
}
++end;
}
list.Add(value.Substring(start, end - start));
start = end + 2;
}
else if (c != ' ')
{
var end = start;
while (end < array.Length)
else
{
if (array[end] != ' ')
{
++end;
}
else
{
break;
}
break;
}
list.Add(value.Substring(start, end - start));
start = end + 1;
}
else
{
++start;
}
}
return list.ToArray();
}
list.Add(value.Substring(start, end - start));
public static void Register(string command, AccessLevel access, CommandEventHandler handler)
{
Entries[command] = new CommandEntry(command, handler, access);
}
public static bool Handle(Mobile from, string text, MessageType type = MessageType.Regular)
{
if (!text.StartsWithOrdinal(Prefix) && type != MessageType.Command)
{
return false;
}
if (type != MessageType.Command)
{
text = text[Prefix.Length..];
}
var indexOf = text.IndexOfOrdinal(' ');
string command;
string[] args;
string argString;
if (indexOf >= 0)
{
argString = text[(indexOf + 1)..];
command = text[..indexOf];
args = Split(argString);
start = end + 1;
}
else
{
argString = "";
command = text.ToLower();
args = Array.Empty<string>();
++start;
}
}
Entries.TryGetValue(command, out var entry);
return list.ToArray();
}
if (entry != null)
public static void Register(string command, AccessLevel access, CommandEventHandler handler)
{
Entries[command] = new CommandEntry(command, handler, access);
}
public static bool Handle(Mobile from, string text, MessageType type = MessageType.Regular)
{
if (!text.StartsWithOrdinal(Prefix) && type != MessageType.Command)
{
return false;
}
if (type != MessageType.Command)
{
text = text[Prefix.Length..];
}
var indexOf = text.IndexOfOrdinal(' ');
string command;
string[] args;
string argString;
if (indexOf >= 0)
{
argString = text[(indexOf + 1)..];
command = text[..indexOf];
args = Split(argString);
}
else
{
argString = "";
command = text.ToLower();
args = Array.Empty<string>();
}
Entries.TryGetValue(command, out var entry);
if (entry != null)
{
if (from.AccessLevel >= entry.AccessLevel)
{
if (from.AccessLevel >= entry.AccessLevel)
if (entry.Handler != null)
{
if (entry.Handler != null)
{
var e = new CommandEventArgs(from, command, argString, args);
entry.Handler(e);
EventSink.InvokeCommand(e);
}
}
else
{
if (from.AccessLevel <= BadCommandIgnoreLevel)
{
return false;
}
from.SendMessage("You do not have access to that command.");
var e = new CommandEventArgs(from, command, argString, args);
entry.Handler(e);
EventSink.InvokeCommand(e);
}
}
else
@ -245,10 +235,19 @@ namespace Server
return false;
}
from.SendMessage("That is not a valid command.");
from.SendMessage("You do not have access to that command.");
}
}
else
{
if (from.AccessLevel <= BadCommandIgnoreLevel)
{
return false;
}
return true;
from.SendMessage("That is not a valid command.");
}
return true;
}
}

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2021 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: DescendingComparer.cs *
* *
@ -16,9 +16,8 @@
using System;
using System.Collections.Generic;
namespace Server
{
public class DescendingComparer<T> : IComparer<T> where T : IComparable<T> {
public int Compare(T x, T y) => y?.CompareTo(x) ?? 1;
}
namespace Server;
public class DescendingComparer<T> : IComparer<T> where T : IComparable<T> {
public int Compare(T x, T y) => y?.CompareTo(x) ?? 1;
}

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: LocationComparer.cs *
* *
@ -15,42 +15,41 @@
using System.Collections.Generic;
namespace Server
namespace Server;
public class LocationComparer : IComparer<IPoint3D>
{
public class LocationComparer : IComparer<IPoint3D>
private static LocationComparer m_Instance;
public LocationComparer(IPoint3D relativeTo) => RelativeTo = relativeTo;
public IPoint3D RelativeTo { get; set; }
public int Compare(IPoint3D x, IPoint3D y) => GetDistance(x) - GetDistance(y);
public static LocationComparer GetInstance(IPoint3D relativeTo)
{
private static LocationComparer m_Instance;
public LocationComparer(IPoint3D relativeTo) => RelativeTo = relativeTo;
public IPoint3D RelativeTo { get; set; }
public int Compare(IPoint3D x, IPoint3D y) => GetDistance(x) - GetDistance(y);
public static LocationComparer GetInstance(IPoint3D relativeTo)
if (m_Instance == null)
{
if (m_Instance == null)
{
m_Instance = new LocationComparer(relativeTo);
}
else
{
m_Instance.RelativeTo = relativeTo;
}
return m_Instance;
m_Instance = new LocationComparer(relativeTo);
}
else
{
m_Instance.RelativeTo = relativeTo;
}
private int GetDistance(IPoint3D p)
{
var x = RelativeTo.X - p.X;
var y = RelativeTo.Y - p.Y;
var z = RelativeTo.Z - p.Z;
return m_Instance;
}
x *= 11;
y *= 11;
private int GetDistance(IPoint3D p)
{
var x = RelativeTo.X - p.X;
var y = RelativeTo.Y - p.Y;
var z = RelativeTo.Z - p.Z;
return x * x + y * y + z * z;
}
x *= 11;
y *= 11;
return x * x + y * y + z * z;
}
}

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: ServerConfiguration.cs *
* *

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2021 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: ServerSettings.cs *
* *
@ -17,23 +17,22 @@ using System.Collections.Generic;
using System.Net;
using System.Text.Json.Serialization;
namespace Server
namespace Server;
public class ServerSettings
{
public class ServerSettings
{
[JsonPropertyName("assemblyDirectories")]
public List<string> AssemblyDirectories { get; set; } = new();
[JsonPropertyName("assemblyDirectories")]
public List<string> AssemblyDirectories { get; set; } = new();
[JsonPropertyName("dataDirectories")]
public HashSet<string> DataDirectories { get; set; } = new();
[JsonPropertyName("dataDirectories")]
public HashSet<string> DataDirectories { get; set; } = new();
[JsonPropertyName("listeners")]
public List<IPEndPoint> Listeners { get; set; } = new();
[JsonPropertyName("listeners")]
public List<IPEndPoint> Listeners { get; set; } = new();
[JsonPropertyName("expansion")]
public Expansion? Expansion { get; set; }
[JsonPropertyName("expansion")]
public Expansion? Expansion { get; set; }
[JsonPropertyName("settings")]
public SortedDictionary<string, string> Settings { get; set; } = new();
}
[JsonPropertyName("settings")]
public SortedDictionary<string, string> Settings { get; set; } = new();
}

View file

@ -1,83 +1,82 @@
using System.Collections.Generic;
namespace Server.ContextMenus
namespace Server.ContextMenus;
/// <summary>
/// Represents the state of an active context menu. This includes who opened the menu, the menu's focus object, and a list
/// of
/// <see cref="ContextMenuEntry">entries</see> that the menu is composed of.
/// <seealso cref="ContextMenuEntry" />
/// </summary>
public class ContextMenu
{
/// <summary>
/// Represents the state of an active context menu. This includes who opened the menu, the menu's focus object, and a list
/// of
/// <see cref="ContextMenuEntry">entries</see> that the menu is composed of.
/// <seealso cref="ContextMenuEntry" />
/// Instantiates a new ContextMenu instance.
/// </summary>
public class ContextMenu
/// <param name="from">
/// The <see cref="Mobile" /> who opened this ContextMenu.
/// <seealso cref="From" />
/// </param>
/// <param name="target">
/// The <see cref="Mobile" /> or <see cref="Item" /> for which this ContextMenu is on.
/// <seealso cref="Target" />
/// </param>
public ContextMenu(Mobile from, IEntity target)
{
/// <summary>
/// Instantiates a new ContextMenu instance.
/// </summary>
/// <param name="from">
/// The <see cref="Mobile" /> who opened this ContextMenu.
/// <seealso cref="From" />
/// </param>
/// <param name="target">
/// The <see cref="Mobile" /> or <see cref="Item" /> for which this ContextMenu is on.
/// <seealso cref="Target" />
/// </param>
public ContextMenu(Mobile from, IEntity target)
From = from;
Target = target;
var list = new List<ContextMenuEntry>();
if (target is Mobile mobile)
{
From = from;
Target = target;
var list = new List<ContextMenuEntry>();
if (target is Mobile mobile)
{
mobile.GetContextMenuEntries(from, list);
}
else if (target is Item item)
{
item.GetContextMenuEntries(from, list);
}
Entries = list.ToArray();
for (var i = 0; i < Entries.Length; ++i)
{
Entries[i].Owner = this;
}
mobile.GetContextMenuEntries(from, list);
}
else if (target is Item item)
{
item.GetContextMenuEntries(from, list);
}
/// <summary>
/// Gets the <see cref="Mobile" /> who opened this ContextMenu.
/// </summary>
public Mobile From { get; }
Entries = list.ToArray();
/// <summary>
/// Gets an object of the <see cref="Mobile" /> or <see cref="Item" /> for which this ContextMenu is on.
/// </summary>
public IEntity Target { get; }
/// <summary>
/// Gets the list of <see cref="ContextMenuEntry">entries</see> contained in this ContextMenu.
/// </summary>
public ContextMenuEntry[] Entries { get; }
/// <summary>
/// Returns true if this ContextMenu requires packet version 2.
/// </summary>
public bool RequiresNewPacket
for (var i = 0; i < Entries.Length; ++i)
{
get
{
for (var i = 0; i < Entries.Length; ++i)
{
var number = Entries[i].Number;
if (number is < 3000000 or > 3032767)
{
return true;
}
}
Entries[i].Owner = this;
}
}
return false;
/// <summary>
/// Gets the <see cref="Mobile" /> who opened this ContextMenu.
/// </summary>
public Mobile From { get; }
/// <summary>
/// Gets an object of the <see cref="Mobile" /> or <see cref="Item" /> for which this ContextMenu is on.
/// </summary>
public IEntity Target { get; }
/// <summary>
/// Gets the list of <see cref="ContextMenuEntry">entries</see> contained in this ContextMenu.
/// </summary>
public ContextMenuEntry[] Entries { get; }
/// <summary>
/// Returns true if this ContextMenu requires packet version 2.
/// </summary>
public bool RequiresNewPacket
{
get
{
for (var i = 0; i < Entries.Length; ++i)
{
var number = Entries[i].Number;
if (number is < 3000000 or > 3032767)
{
return true;
}
}
return false;
}
}
}

View file

@ -1,83 +1,82 @@
using Server.Network;
namespace Server.ContextMenus
namespace Server.ContextMenus;
/// <summary>
/// Represents a single entry of a <see cref="ContextMenu">context menu</see>.
/// <seealso cref="ContextMenu" />
/// </summary>
public class ContextMenuEntry
{
/// <summary>
/// Represents a single entry of a <see cref="ContextMenu">context menu</see>.
/// <seealso cref="ContextMenu" />
/// Instantiates a new ContextMenuEntry with a given <see cref="Number">localization number</see> (
/// <paramref name="number" />)
/// and <see cref="Range">maximum range</see> (<paramref name="range" />).
/// </summary>
public class ContextMenuEntry
/// <param name="number">
/// The localization number containing the name of this entry.
/// <seealso cref="Number" />
/// </param>
/// <param name="range">
/// The maximum range at which this entry can be used.
/// <seealso cref="Range" />
/// </param>
public ContextMenuEntry(int number, int range = -1)
{
/// <summary>
/// Instantiates a new ContextMenuEntry with a given <see cref="Number">localization number</see> (
/// <paramref name="number" />)
/// and <see cref="Range">maximum range</see> (<paramref name="range" />).
/// </summary>
/// <param name="number">
/// The localization number containing the name of this entry.
/// <seealso cref="Number" />
/// </param>
/// <param name="range">
/// The maximum range at which this entry can be used.
/// <seealso cref="Range" />
/// </param>
public ContextMenuEntry(int number, int range = -1)
if (number <= 0x7FFF) // Legacy code support
{
if (number <= 0x7FFF) // Legacy code support
{
Number = 3000000 + number;
}
else
{
Number = number;
}
Range = range;
Enabled = true;
Color = 0xFFFF;
Number = 3000000 + number;
}
else
{
Number = number;
}
/// <summary>
/// Gets or sets additional <see cref="CMEFlags">flags</see> used in client communication.
/// </summary>
public CMEFlags Flags { get; set; }
Range = range;
Enabled = true;
Color = 0xFFFF;
}
/// <summary>
/// Gets or sets the <see cref="ContextMenu" /> that owns this entry.
/// </summary>
public ContextMenu Owner { get; set; }
/// <summary>
/// Gets or sets additional <see cref="CMEFlags">flags</see> used in client communication.
/// </summary>
public CMEFlags Flags { get; set; }
/// <summary>
/// Gets or sets the localization number containing the name of this entry.
/// </summary>
public int Number { get; set; }
/// <summary>
/// Gets or sets the <see cref="ContextMenu" /> that owns this entry.
/// </summary>
public ContextMenu Owner { get; set; }
/// <summary>
/// Gets or sets the maximum range at which this entry may be used, in tiles. A value of -1 signifies no maximum range.
/// </summary>
public int Range { get; set; }
/// <summary>
/// Gets or sets the localization number containing the name of this entry.
/// </summary>
public int Number { get; set; }
/// <summary>
/// Gets or sets the color for this entry. Format is A1-R5-G5-B5.
/// </summary>
public int Color { get; set; }
/// <summary>
/// Gets or sets the maximum range at which this entry may be used, in tiles. A value of -1 signifies no maximum range.
/// </summary>
public int Range { get; set; }
/// <summary>
/// Gets or sets whether this entry is enabled. When false, the entry will appear in a gray hue and <see cref="OnClick" />
/// will never be invoked.
/// </summary>
public bool Enabled { get; set; }
/// <summary>
/// Gets or sets the color for this entry. Format is A1-R5-G5-B5.
/// </summary>
public int Color { get; set; }
/// <summary>
/// Gets a value indicating if non local use of this entry is permitted.
/// </summary>
public virtual bool NonLocalUse => false;
/// <summary>
/// Gets or sets whether this entry is enabled. When false, the entry will appear in a gray hue and <see cref="OnClick" />
/// will never be invoked.
/// </summary>
public bool Enabled { get; set; }
/// <summary>
/// Overridable. Virtual event invoked when the entry is clicked.
/// </summary>
public virtual void OnClick()
{
}
/// <summary>
/// Gets a value indicating if non local use of this entry is permitted.
/// </summary>
public virtual bool NonLocalUse => false;
/// <summary>
/// Overridable. Virtual event invoked when the entry is clicked.
/// </summary>
public virtual void OnClick()
{
}
}

View file

@ -1,14 +1,13 @@
namespace Server.ContextMenus
namespace Server.ContextMenus;
public class OpenBackpackEntry : ContextMenuEntry
{
public class OpenBackpackEntry : ContextMenuEntry
private readonly Mobile m_Mobile;
public OpenBackpackEntry(Mobile m) : base(6145) => m_Mobile = m;
public override void OnClick()
{
private readonly Mobile m_Mobile;
public OpenBackpackEntry(Mobile m) : base(6145) => m_Mobile = m;
public override void OnClick()
{
m_Mobile.Use(m_Mobile.Backpack);
}
m_Mobile.Use(m_Mobile.Backpack);
}
}

View file

@ -1,17 +1,16 @@
namespace Server.ContextMenus
namespace Server.ContextMenus;
public class PaperdollEntry : ContextMenuEntry
{
public class PaperdollEntry : ContextMenuEntry
private readonly Mobile m_Mobile;
public PaperdollEntry(Mobile m) : base(6123, 18) => m_Mobile = m;
public override void OnClick()
{
private readonly Mobile m_Mobile;
public PaperdollEntry(Mobile m) : base(6123, 18) => m_Mobile = m;
public override void OnClick()
if (m_Mobile.CanPaperdollBeOpenedBy(Owner.From))
{
if (m_Mobile.CanPaperdollBeOpenedBy(Owner.From))
{
m_Mobile.DisplayPaperdollTo(Owner.From);
}
m_Mobile.DisplayPaperdollTo(Owner.From);
}
}
}

View file

@ -3,78 +3,77 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
namespace Server.Diagnostics
namespace Server.Diagnostics;
public abstract class BaseProfile
{
public abstract class BaseProfile
private readonly Stopwatch _stopwatch;
protected BaseProfile(string name)
{
private readonly Stopwatch _stopwatch;
Name = name;
protected BaseProfile(string name)
_stopwatch = new Stopwatch();
}
public string Name { get; }
public long Count { get; private set; }
public TimeSpan AverageTime => TimeSpan.FromTicks(TotalTime.Ticks / Math.Max(Count, 1));
public TimeSpan PeakTime { get; private set; }
public TimeSpan TotalTime { get; private set; }
public static void WriteAll<T>(TextWriter op, IEnumerable<T> profiles) where T : BaseProfile
{
var list = new List<T>(profiles);
list.Sort((a, b) => -a.TotalTime.CompareTo(b.TotalTime));
foreach (var prof in list)
{
Name = name;
_stopwatch = new Stopwatch();
prof.WriteTo(op);
op.WriteLine();
}
}
public string Name { get; }
public long Count { get; private set; }
public TimeSpan AverageTime => TimeSpan.FromTicks(TotalTime.Ticks / Math.Max(Count, 1));
public TimeSpan PeakTime { get; private set; }
public TimeSpan TotalTime { get; private set; }
public static void WriteAll<T>(TextWriter op, IEnumerable<T> profiles) where T : BaseProfile
public virtual void Start()
{
if (_stopwatch.IsRunning)
{
var list = new List<T>(profiles);
list.Sort((a, b) => -a.TotalTime.CompareTo(b.TotalTime));
foreach (var prof in list)
{
prof.WriteTo(op);
op.WriteLine();
}
}
public virtual void Start()
{
if (_stopwatch.IsRunning)
{
_stopwatch.Reset();
}
_stopwatch.Start();
}
public virtual void Finish()
{
var elapsed = _stopwatch.Elapsed;
TotalTime += elapsed;
if (elapsed > PeakTime)
{
PeakTime = elapsed;
}
Count++;
_stopwatch.Reset();
}
public virtual void WriteTo(TextWriter op)
_stopwatch.Start();
}
public virtual void Finish()
{
var elapsed = _stopwatch.Elapsed;
TotalTime += elapsed;
if (elapsed > PeakTime)
{
op.Write(
"{0,-100} {1,12:N0} {2,12:F5} {3,-12:F5} {4,12:F5}",
Name,
Count,
AverageTime.TotalSeconds,
PeakTime.TotalSeconds,
TotalTime.TotalSeconds
);
PeakTime = elapsed;
}
Count++;
_stopwatch.Reset();
}
public virtual void WriteTo(TextWriter op)
{
op.Write(
"{0,-100} {1,12:N0} {2,12:F5} {3,-12:F5} {4,12:F5}",
Name,
Count,
AverageTime.TotalSeconds,
PeakTime.TotalSeconds,
TotalTime.TotalSeconds
);
}
}

View file

@ -1,31 +1,30 @@
using System;
using System.Collections.Generic;
namespace Server.Diagnostics
namespace Server.Diagnostics;
public class GumpProfile : BaseProfile
{
public class GumpProfile : BaseProfile
private static readonly Dictionary<Type, GumpProfile> _profiles = new();
public GumpProfile(Type type) : base(type.FullName)
{
private static readonly Dictionary<Type, GumpProfile> _profiles = new();
}
public GumpProfile(Type type) : base(type.FullName)
public static IEnumerable<GumpProfile> Profiles => _profiles.Values;
public static GumpProfile Acquire(Type type)
{
if (!Core.Profiling)
{
return null;
}
public static IEnumerable<GumpProfile> Profiles => _profiles.Values;
public static GumpProfile Acquire(Type type)
if (!_profiles.TryGetValue(type, out var prof))
{
if (!Core.Profiling)
{
return null;
}
if (!_profiles.TryGetValue(type, out var prof))
{
_profiles.Add(type, prof = new GumpProfile(type));
}
return prof;
_profiles.Add(type, prof = new GumpProfile(type));
}
return prof;
}
}

View file

@ -4,89 +4,88 @@ using System.IO;
using System.Runtime.CompilerServices;
using System.Threading;
namespace Server.Diagnostics
namespace Server.Diagnostics;
public abstract class BasePacketProfile : BaseProfile
{
public abstract class BasePacketProfile : BaseProfile
protected BasePacketProfile(string name) : base(name)
{
protected BasePacketProfile(string name) : base(name)
{
}
public long TotalLength { get; private set; }
public double AverageLength => (double)TotalLength / Math.Max(Count, 1);
public void Finish(long length)
{
Finish();
TotalLength += length;
}
public override void WriteTo(TextWriter op)
{
base.WriteTo(op);
op.Write("\t{0,12:F2} {1,-12:N0}", AverageLength, TotalLength);
}
}
public class PacketSendProfile : BasePacketProfile
public long TotalLength { get; private set; }
public double AverageLength => (double)TotalLength / Math.Max(Count, 1);
public void Finish(long length)
{
private static readonly Dictionary<int, PacketSendProfile> _profiles = new();
Finish();
private long _created;
public PacketSendProfile(int packetId) : base($"0x{packetId:X2}")
{
}
public static IEnumerable<PacketSendProfile> Profiles => _profiles.Values;
[MethodImpl(MethodImplOptions.Synchronized)]
public static PacketSendProfile Acquire(int packetId)
{
if (!_profiles.TryGetValue(packetId, out var prof))
{
_profiles.Add(packetId, prof = new PacketSendProfile(packetId));
}
return prof;
}
public void Increment()
{
Interlocked.Increment(ref _created);
}
public override void WriteTo(TextWriter op)
{
base.WriteTo(op);
op.Write("\t{0,12:N0}", _created);
}
TotalLength += length;
}
public class PacketReceiveProfile : BasePacketProfile
public override void WriteTo(TextWriter op)
{
private static readonly Dictionary<int, PacketReceiveProfile>
_profiles = new();
base.WriteTo(op);
public PacketReceiveProfile(int packetId) : base($"0x{packetId:X2}")
{
}
public static IEnumerable<PacketReceiveProfile> Profiles => _profiles.Values;
[MethodImpl(MethodImplOptions.Synchronized)]
public static PacketReceiveProfile Acquire(int packetId)
{
if (!_profiles.TryGetValue(packetId, out var prof))
{
_profiles.Add(packetId, prof = new PacketReceiveProfile(packetId));
}
return prof;
}
op.Write("\t{0,12:F2} {1,-12:N0}", AverageLength, TotalLength);
}
}
public class PacketSendProfile : BasePacketProfile
{
private static readonly Dictionary<int, PacketSendProfile> _profiles = new();
private long _created;
public PacketSendProfile(int packetId) : base($"0x{packetId:X2}")
{
}
public static IEnumerable<PacketSendProfile> Profiles => _profiles.Values;
[MethodImpl(MethodImplOptions.Synchronized)]
public static PacketSendProfile Acquire(int packetId)
{
if (!_profiles.TryGetValue(packetId, out var prof))
{
_profiles.Add(packetId, prof = new PacketSendProfile(packetId));
}
return prof;
}
public void Increment()
{
Interlocked.Increment(ref _created);
}
public override void WriteTo(TextWriter op)
{
base.WriteTo(op);
op.Write("\t{0,12:N0}", _created);
}
}
public class PacketReceiveProfile : BasePacketProfile
{
private static readonly Dictionary<int, PacketReceiveProfile>
_profiles = new();
public PacketReceiveProfile(int packetId) : base($"0x{packetId:X2}")
{
}
public static IEnumerable<PacketReceiveProfile> Profiles => _profiles.Values;
[MethodImpl(MethodImplOptions.Synchronized)]
public static PacketReceiveProfile Acquire(int packetId)
{
if (!_profiles.TryGetValue(packetId, out var prof))
{
_profiles.Add(packetId, prof = new PacketReceiveProfile(packetId));
}
return prof;
}
}

View file

@ -1,32 +1,31 @@
using System;
using System.Collections.Generic;
namespace Server.Diagnostics
namespace Server.Diagnostics;
public class TargetProfile : BaseProfile
{
public class TargetProfile : BaseProfile
private static readonly Dictionary<Type, TargetProfile> _profiles = new();
public TargetProfile(Type type)
: base(type.FullName)
{
private static readonly Dictionary<Type, TargetProfile> _profiles = new();
}
public TargetProfile(Type type)
: base(type.FullName)
public static IEnumerable<TargetProfile> Profiles => _profiles.Values;
public static TargetProfile Acquire(Type type)
{
if (!Core.Profiling)
{
return null;
}
public static IEnumerable<TargetProfile> Profiles => _profiles.Values;
public static TargetProfile Acquire(Type type)
if (!_profiles.TryGetValue(type, out var prof))
{
if (!Core.Profiling)
{
return null;
}
if (!_profiles.TryGetValue(type, out var prof))
{
_profiles.Add(type, prof = new TargetProfile(type));
}
return prof;
_profiles.Add(type, prof = new TargetProfile(type));
}
return prof;
}
}

View file

@ -1,45 +1,44 @@
using System.Collections.Generic;
using System.IO;
namespace Server.Diagnostics
namespace Server.Diagnostics;
public class TimerProfile : BaseProfile
{
public class TimerProfile : BaseProfile
private static readonly Dictionary<string, TimerProfile> _profiles = new();
public TimerProfile(string name)
: base(name)
{
private static readonly Dictionary<string, TimerProfile> _profiles = new();
}
public TimerProfile(string name)
: base(name)
public static IEnumerable<TimerProfile> Profiles => _profiles.Values;
public long Created { get; set; }
public long Started { get; set; }
public long Stopped { get; set; }
public static TimerProfile Acquire(string name)
{
if (!Core.Profiling)
{
return null;
}
public static IEnumerable<TimerProfile> Profiles => _profiles.Values;
public long Created { get; set; }
public long Started { get; set; }
public long Stopped { get; set; }
public static TimerProfile Acquire(string name)
if (!_profiles.TryGetValue(name, out var prof))
{
if (!Core.Profiling)
{
return null;
}
if (!_profiles.TryGetValue(name, out var prof))
{
_profiles.Add(name, prof = new TimerProfile(name));
}
return prof;
_profiles.Add(name, prof = new TimerProfile(name));
}
public override void WriteTo(TextWriter op)
{
base.WriteTo(op);
return prof;
}
op.Write("\t{0,12:N0} {1,12:N0} {2,-12:N0}", Created, Started, Stopped);
}
public override void WriteTo(TextWriter op)
{
base.WriteTo(op);
op.Write("\t{0,12:N0} {1,12:N0} {2,-12:N0}", Created, Started, Stopped);
}
}

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: Effects.cs *
* *
@ -16,262 +16,304 @@
using System;
using Server.Network;
namespace Server
namespace Server;
public enum EffectType
{
public enum EffectType
Moving,
Lightning,
FixedXYZ,
FixedFrom
}
public enum ScreenEffectType
{
FadeOut = 0x00,
FadeIn = 0x01,
LightFlash = 0x02,
FadeInOut = 0x03,
DarkFlash = 0x04
}
public enum EffectLayer
{
Head = 0,
RightHand = 1,
LeftHand = 2,
Waist = 3,
LeftFoot = 4,
RightFoot = 5,
CenterFeet = 7
}
public enum ParticleSupportType
{
Full,
Detect,
None
}
public static class Effects
{
public static ParticleSupportType ParticleSupportType { get; set; } = ParticleSupportType.Detect;
public static bool SendParticlesTo(NetState state) =>
ParticleSupportType == ParticleSupportType.Full ||
ParticleSupportType == ParticleSupportType.Detect && state.IsUOTDClient;
public static void PlaySound(IEntity e, int soundID) => PlaySound(e.Location, e.Map, soundID);
public static void PlaySound(Point3D p, Map map, int soundID)
{
Moving,
Lightning,
FixedXYZ,
FixedFrom
}
public enum ScreenEffectType
{
FadeOut = 0x00,
FadeIn = 0x01,
LightFlash = 0x02,
FadeInOut = 0x03,
DarkFlash = 0x04
}
public enum EffectLayer
{
Head = 0,
RightHand = 1,
LeftHand = 2,
Waist = 3,
LeftFoot = 4,
RightFoot = 5,
CenterFeet = 7
}
public enum ParticleSupportType
{
Full,
Detect,
None
}
public static class Effects
{
public static ParticleSupportType ParticleSupportType { get; set; } = ParticleSupportType.Detect;
public static bool SendParticlesTo(NetState state) =>
ParticleSupportType == ParticleSupportType.Full ||
ParticleSupportType == ParticleSupportType.Detect && state.IsUOTDClient;
public static void PlaySound(IEntity e, int soundID) => PlaySound(e.Location, e.Map, soundID);
public static void PlaySound(Point3D p, Map map, int soundID)
if (soundID <= -1)
{
if (soundID <= -1)
{
return;
}
if (map != null)
{
Span<byte> buffer = stackalloc byte[OutgoingEffectPackets.SoundPacketLength].InitializePacket();
var eable = map.GetClientsInRange(new Point3D(p));
foreach (var state in eable)
{
state.Mobile.ProcessDelta();
OutgoingEffectPackets.CreateSoundEffect(buffer, soundID, p);
state.Send(buffer);
}
eable.Free();
}
return;
}
public static void SendBoltEffect(IEntity e, bool sound = true, int hue = 0)
if (map != null)
{
var map = e.Map;
Span<byte> buffer = stackalloc byte[OutgoingEffectPackets.SoundPacketLength].InitializePacket();
if (map == null)
{
return;
}
e.ProcessDelta();
Span<byte> preEffect = stackalloc byte[OutgoingEffectPackets.ParticleEffectLength].InitializePacket();
Span<byte> boltEffect = stackalloc byte[OutgoingEffectPackets.BoltEffectLength].InitializePacket();
Span<byte> soundEffect = sound ? stackalloc byte[OutgoingEffectPackets.SoundPacketLength].InitializePacket() : null;
var eable = map.GetClientsInRange(e.Location);
foreach (var state in eable)
{
if (state.Mobile.CanSee(e))
{
if (SendParticlesTo(state))
{
OutgoingEffectPackets.CreateTargetParticleEffect(
preEffect,
e, 0, 10, 5, 0, 0, 5031, 3, 0
);
state.Send(preEffect);
}
OutgoingEffectPackets.CreateBoltEffect(boltEffect, e, hue);
state.Send(boltEffect);
if (sound)
{
OutgoingEffectPackets.CreateSoundEffect(soundEffect, 0x29, e);
state.Send(soundEffect);
}
}
}
eable.Free();
}
public static void SendLocationEffect(
IEntity e, int itemID, int duration, int speed = 10, int hue = 0, int renderMode = 0
) => SendLocationEffect(e.Location, e.Map, itemID, duration, speed, hue, renderMode);
public static void SendLocationEffect(
Point3D p, Map map, int itemID, int duration, int speed = 10, int hue = 0, int renderMode = 0
)
{
Span<byte> effect = stackalloc byte[OutgoingEffectPackets.HuedEffectLength].InitializePacket();
OutgoingEffectPackets.CreateLocationHuedEffect(
effect,
p, itemID, speed, duration, hue, renderMode
);
SendPacket(p, map, effect);
}
public static void SendLocationParticles(IEntity e, int itemID, int speed, int duration, int effect)
{
SendLocationParticles(e, itemID, speed, duration, 0, 0, effect, 0);
}
public static void SendLocationParticles(IEntity e, int itemID, int speed, int duration, int effect, int unknown)
{
SendLocationParticles(e, itemID, speed, duration, 0, 0, effect, unknown);
}
public static void SendLocationParticles(
IEntity e, int itemID, int speed, int duration, int hue, int renderMode, int effect, int unknown
)
{
var map = e.Map;
if (map == null)
{
return;
}
Span<byte> particles = stackalloc byte[OutgoingEffectPackets.ParticleEffectLength].InitializePacket();
Span<byte> regular = itemID != 0 ? stackalloc byte[OutgoingEffectPackets.HuedEffectLength].InitializePacket() : null;
var eable = map.GetClientsInRange(e.Location);
var eable = map.GetClientsInRange(new Point3D(p));
foreach (var state in eable)
{
state.Mobile.ProcessDelta();
if (SendParticlesTo(state))
{
OutgoingEffectPackets.CreateLocationParticleEffect(
particles,
e, itemID, speed, duration, hue, renderMode, effect, unknown
);
state.Send(particles);
}
else if (itemID != 0)
{
OutgoingEffectPackets.CreateLocationHuedEffect(
regular,
e.Location, itemID, speed, duration, hue, renderMode
);
state.Send(regular);
}
OutgoingEffectPackets.CreateSoundEffect(buffer, soundID, p);
state.Send(buffer);
}
eable.Free();
}
}
public static void SendTargetEffect(IEntity target, int itemID, int speed, int duration, int hue = 0, int renderMode = 0)
public static void SendBoltEffect(IEntity e, bool sound = true, int hue = 0)
{
var map = e.Map;
if (map == null)
{
(target as Mobile)?.ProcessDelta();
Span<byte> effect = stackalloc byte[OutgoingEffectPackets.HuedEffectLength].InitializePacket();
OutgoingEffectPackets.CreateTargetHuedEffect(
effect,
target, itemID, speed, duration, hue, renderMode
);
SendPacket(target.Location, target.Map, effect);
return;
}
public static void SendTargetParticles(
IEntity target, int itemID, int speed, int duration, int effect,
EffectLayer layer
)
e.ProcessDelta();
Span<byte> preEffect = stackalloc byte[OutgoingEffectPackets.ParticleEffectLength].InitializePacket();
Span<byte> boltEffect = stackalloc byte[OutgoingEffectPackets.BoltEffectLength].InitializePacket();
Span<byte> soundEffect = sound ? stackalloc byte[OutgoingEffectPackets.SoundPacketLength].InitializePacket() : null;
var eable = map.GetClientsInRange(e.Location);
foreach (var state in eable)
{
SendTargetParticles(target, itemID, speed, duration, 0, 0, effect, layer);
}
public static void SendTargetParticles(
IEntity target, int itemID, int speed, int duration, int hue, int renderMode,
int effect, EffectLayer layer, int unknown = 0
)
{
(target as Mobile)?.ProcessDelta();
var map = target.Map;
if (map == null)
if (state.Mobile.CanSee(e))
{
return;
}
Span<byte> particles = stackalloc byte[OutgoingEffectPackets.ParticleEffectLength].InitializePacket();
Span<byte> regular = itemID != 0 ? stackalloc byte[OutgoingEffectPackets.HuedEffectLength].InitializePacket() : null;
var eable = map.GetClientsInRange(target.Location);
foreach (var state in eable)
{
state.Mobile.ProcessDelta();
if (SendParticlesTo(state))
{
OutgoingEffectPackets.CreateTargetParticleEffect(
particles,
target, itemID, speed, duration, hue, renderMode, effect, (int)layer, unknown
preEffect,
e, 0, 10, 5, 0, 0, 5031, 3, 0
);
state.Send(particles);
state.Send(preEffect);
}
else if (itemID != 0)
OutgoingEffectPackets.CreateBoltEffect(boltEffect, e, hue);
state.Send(boltEffect);
if (sound)
{
OutgoingEffectPackets.CreateTargetHuedEffect(regular, target, itemID, speed, duration, hue, renderMode);
state.Send(regular);
OutgoingEffectPackets.CreateSoundEffect(soundEffect, 0x29, e);
state.Send(soundEffect);
}
}
eable.Free();
}
public static void SendMovingEffect(
Map map, int itemID, Point3D from, Point3D to, int speed, int duration,
bool fixedDirection = false, bool explodes = false, int hue = 0, int renderMode = 0
) => SendMovingEffect(
eable.Free();
}
public static void SendLocationEffect(
IEntity e, int itemID, int duration, int speed = 10, int hue = 0, int renderMode = 0
) => SendLocationEffect(e.Location, e.Map, itemID, duration, speed, hue, renderMode);
public static void SendLocationEffect(
Point3D p, Map map, int itemID, int duration, int speed = 10, int hue = 0, int renderMode = 0
)
{
Span<byte> effect = stackalloc byte[OutgoingEffectPackets.HuedEffectLength].InitializePacket();
OutgoingEffectPackets.CreateLocationHuedEffect(
effect,
p, itemID, speed, duration, hue, renderMode
);
SendPacket(p, map, effect);
}
public static void SendLocationParticles(IEntity e, int itemID, int speed, int duration, int effect)
{
SendLocationParticles(e, itemID, speed, duration, 0, 0, effect, 0);
}
public static void SendLocationParticles(IEntity e, int itemID, int speed, int duration, int effect, int unknown)
{
SendLocationParticles(e, itemID, speed, duration, 0, 0, effect, unknown);
}
public static void SendLocationParticles(
IEntity e, int itemID, int speed, int duration, int hue, int renderMode, int effect, int unknown
)
{
var map = e.Map;
if (map == null)
{
return;
}
Span<byte> particles = stackalloc byte[OutgoingEffectPackets.ParticleEffectLength].InitializePacket();
Span<byte> regular = itemID != 0 ? stackalloc byte[OutgoingEffectPackets.HuedEffectLength].InitializePacket() : null;
var eable = map.GetClientsInRange(e.Location);
foreach (var state in eable)
{
state.Mobile.ProcessDelta();
if (SendParticlesTo(state))
{
OutgoingEffectPackets.CreateLocationParticleEffect(
particles,
e, itemID, speed, duration, hue, renderMode, effect, unknown
);
state.Send(particles);
}
else if (itemID != 0)
{
OutgoingEffectPackets.CreateLocationHuedEffect(
regular,
e.Location, itemID, speed, duration, hue, renderMode
);
state.Send(regular);
}
}
eable.Free();
}
public static void SendTargetEffect(IEntity target, int itemID, int speed, int duration, int hue = 0, int renderMode = 0)
{
(target as Mobile)?.ProcessDelta();
Span<byte> effect = stackalloc byte[OutgoingEffectPackets.HuedEffectLength].InitializePacket();
OutgoingEffectPackets.CreateTargetHuedEffect(
effect,
target, itemID, speed, duration, hue, renderMode
);
SendPacket(target.Location, target.Map, effect);
}
public static void SendTargetParticles(
IEntity target, int itemID, int speed, int duration, int effect,
EffectLayer layer
)
{
SendTargetParticles(target, itemID, speed, duration, 0, 0, effect, layer);
}
public static void SendTargetParticles(
IEntity target, int itemID, int speed, int duration, int hue, int renderMode,
int effect, EffectLayer layer, int unknown = 0
)
{
(target as Mobile)?.ProcessDelta();
var map = target.Map;
if (map == null)
{
return;
}
Span<byte> particles = stackalloc byte[OutgoingEffectPackets.ParticleEffectLength].InitializePacket();
Span<byte> regular = itemID != 0 ? stackalloc byte[OutgoingEffectPackets.HuedEffectLength].InitializePacket() : null;
var eable = map.GetClientsInRange(target.Location);
foreach (var state in eable)
{
state.Mobile.ProcessDelta();
if (SendParticlesTo(state))
{
OutgoingEffectPackets.CreateTargetParticleEffect(
particles,
target, itemID, speed, duration, hue, renderMode, effect, (int)layer, unknown
);
state.Send(particles);
}
else if (itemID != 0)
{
OutgoingEffectPackets.CreateTargetHuedEffect(regular, target, itemID, speed, duration, hue, renderMode);
state.Send(regular);
}
}
eable.Free();
}
public static void SendMovingEffect(
Map map, int itemID, Point3D from, Point3D to, int speed, int duration,
bool fixedDirection = false, bool explodes = false, int hue = 0, int renderMode = 0
) => SendMovingEffect(
Serial.Zero,
Serial.Zero,
from,
map,
itemID,
from,
to,
speed,
duration,
fixedDirection,
explodes,
hue,
renderMode
);
public static void SendMovingEffect(
Point3D origin, Map map, int itemID, Point3D from, Point3D to, int speed, int duration,
bool fixedDirection = false, bool explodes = false, int hue = 0, int renderMode = 0
) => SendMovingEffect(
Serial.Zero,
Serial.Zero,
origin,
map,
itemID,
from,
to,
speed,
duration,
fixedDirection,
explodes,
hue,
renderMode
);
public static void SendMovingEffect(
IEntity from, Point3D to, int itemID,
int speed, int duration, bool fixedDirection = false, bool explodes = false, int hue = 0, int renderMode = 0
)
{
(from as Mobile)?.ProcessDelta();
SendMovingEffect(
from.Serial,
Serial.Zero,
Serial.Zero,
from,
map,
from.Location,
from.Map,
itemID,
from,
from.Location,
to,
speed,
duration,
@ -280,18 +322,49 @@ namespace Server
hue,
renderMode
);
}
public static void SendMovingEffect(
Point3D origin, Map map, int itemID, Point3D from, Point3D to, int speed, int duration,
bool fixedDirection = false, bool explodes = false, int hue = 0, int renderMode = 0
) => SendMovingEffect(
Serial.Zero,
Serial.Zero,
public static void SendMovingEffect(
IEntity from, IEntity to, int itemID,
int speed, int duration, bool fixedDirection = false, bool explodes = false, int hue = 0, int renderMode = 0
)
{
(from as Mobile)?.ProcessDelta();
(to as Mobile)?.ProcessDelta();
SendMovingEffect(
from,
to,
from.Location,
from.Map,
itemID,
from.Location,
to.Location,
speed,
duration,
fixedDirection,
explodes,
hue,
renderMode
);
}
public static void SendMovingEffect(
IEntity from, IEntity to, Point3D origin, Map map, int itemID, Point3D fromLocation, Point3D toLocation,
int speed, int duration, bool fixedDirection = false, bool explodes = false, int hue = 0, int renderMode = 0
)
{
(from as Mobile)?.ProcessDelta();
(to as Mobile)?.ProcessDelta();
SendMovingEffect(
from.Serial,
to.Serial,
origin,
map,
itemID,
from,
to,
fromLocation,
toLocation,
speed,
duration,
fixedDirection,
@ -299,205 +372,131 @@ namespace Server
hue,
renderMode
);
}
public static void SendMovingEffect(
IEntity from, Point3D to, int itemID,
int speed, int duration, bool fixedDirection = false, bool explodes = false, int hue = 0, int renderMode = 0
)
public static void SendMovingEffect(
Serial from, Serial to, Point3D origin, Map map, int itemID, Point3D fromLocation, Point3D toLocation,
int speed, int duration, bool fixedDirection = false, bool explodes = false, int hue = 0, int renderMode = 0
)
{
Span<byte> effect = stackalloc byte[OutgoingEffectPackets.HuedEffectLength];
OutgoingEffectPackets.CreateMovingHuedEffect(
effect,
from, to, itemID, fromLocation, toLocation, speed, duration, fixedDirection,
explodes, hue, renderMode
);
SendPacket(origin, map, effect);
}
public static void SendMovingParticles(
IEntity from, IEntity to, int itemID, int speed, int duration,
bool fixedDirection, bool explodes, int effect, int explodeEffect, int explodeSound, int unknown = 0
)
{
SendMovingParticles(
from,
to,
itemID,
speed,
duration,
fixedDirection,
explodes,
0,
0,
effect,
explodeEffect,
explodeSound,
unknown
);
}
public static void SendMovingParticles(
IEntity from, IEntity to, int itemID, int speed, int duration,
bool fixedDirection, bool explodes, int hue, int renderMode, int effect, int explodeEffect, int explodeSound,
int unknown
)
{
SendMovingParticles(
from,
to,
itemID,
speed,
duration,
fixedDirection,
explodes,
hue,
renderMode,
effect,
explodeEffect,
explodeSound,
(EffectLayer)255,
unknown
);
}
public static void SendMovingParticles(
IEntity from, IEntity to, int itemID, int speed, int duration,
bool fixedDirection, bool explodes, int hue, int renderMode, int effect, int explodeEffect, int explodeSound,
EffectLayer layer, int unknown
)
{
(from as Mobile)?.ProcessDelta();
(to as Mobile)?.ProcessDelta();
var map = from.Map;
if (map == null)
{
(from as Mobile)?.ProcessDelta();
SendMovingEffect(
from.Serial,
Serial.Zero,
from.Location,
from.Map,
itemID,
from.Location,
to,
speed,
duration,
fixedDirection,
explodes,
hue,
renderMode
);
return;
}
public static void SendMovingEffect(
IEntity from, IEntity to, int itemID,
int speed, int duration, bool fixedDirection = false, bool explodes = false, int hue = 0, int renderMode = 0
)
Span<byte> particles = stackalloc byte[OutgoingEffectPackets.ParticleEffectLength].InitializePacket();
Span<byte> regular = itemID != 0 ? stackalloc byte[OutgoingEffectPackets.HuedEffectLength].InitializePacket() : null;
var eable = map.GetClientsInRange(from.Location);
foreach (var state in eable)
{
(from as Mobile)?.ProcessDelta();
(to as Mobile)?.ProcessDelta();
state.Mobile.ProcessDelta();
SendMovingEffect(
from,
to,
from.Location,
from.Map,
itemID,
from.Location,
to.Location,
speed,
duration,
fixedDirection,
explodes,
hue,
renderMode
);
}
public static void SendMovingEffect(
IEntity from, IEntity to, Point3D origin, Map map, int itemID, Point3D fromLocation, Point3D toLocation,
int speed, int duration, bool fixedDirection = false, bool explodes = false, int hue = 0, int renderMode = 0
)
{
(from as Mobile)?.ProcessDelta();
(to as Mobile)?.ProcessDelta();
SendMovingEffect(
from.Serial,
to.Serial,
origin,
map,
itemID,
fromLocation,
toLocation,
speed,
duration,
fixedDirection,
explodes,
hue,
renderMode
);
}
public static void SendMovingEffect(
Serial from, Serial to, Point3D origin, Map map, int itemID, Point3D fromLocation, Point3D toLocation,
int speed, int duration, bool fixedDirection = false, bool explodes = false, int hue = 0, int renderMode = 0
)
{
Span<byte> effect = stackalloc byte[OutgoingEffectPackets.HuedEffectLength];
OutgoingEffectPackets.CreateMovingHuedEffect(
effect,
from, to, itemID, fromLocation, toLocation, speed, duration, fixedDirection,
explodes, hue, renderMode
);
SendPacket(origin, map, effect);
}
public static void SendMovingParticles(
IEntity from, IEntity to, int itemID, int speed, int duration,
bool fixedDirection, bool explodes, int effect, int explodeEffect, int explodeSound, int unknown = 0
)
{
SendMovingParticles(
from,
to,
itemID,
speed,
duration,
fixedDirection,
explodes,
0,
0,
effect,
explodeEffect,
explodeSound,
unknown
);
}
public static void SendMovingParticles(
IEntity from, IEntity to, int itemID, int speed, int duration,
bool fixedDirection, bool explodes, int hue, int renderMode, int effect, int explodeEffect, int explodeSound,
int unknown
)
{
SendMovingParticles(
from,
to,
itemID,
speed,
duration,
fixedDirection,
explodes,
hue,
renderMode,
effect,
explodeEffect,
explodeSound,
(EffectLayer)255,
unknown
);
}
public static void SendMovingParticles(
IEntity from, IEntity to, int itemID, int speed, int duration,
bool fixedDirection, bool explodes, int hue, int renderMode, int effect, int explodeEffect, int explodeSound,
EffectLayer layer, int unknown
)
{
(from as Mobile)?.ProcessDelta();
(to as Mobile)?.ProcessDelta();
var map = from.Map;
if (map == null)
if (SendParticlesTo(state))
{
return;
OutgoingEffectPackets.CreateMovingParticleEffect(
particles,
from, to, itemID, speed, duration, fixedDirection, explodes, hue, renderMode, effect,
explodeEffect, explodeSound, layer, unknown
);
state.Send(particles);
}
Span<byte> particles = stackalloc byte[OutgoingEffectPackets.ParticleEffectLength].InitializePacket();
Span<byte> regular = itemID != 0 ? stackalloc byte[OutgoingEffectPackets.HuedEffectLength].InitializePacket() : null;
var eable = map.GetClientsInRange(from.Location);
foreach (var state in eable)
else if (itemID > 1)
{
state.Mobile.ProcessDelta();
if (SendParticlesTo(state))
{
OutgoingEffectPackets.CreateMovingParticleEffect(
particles,
from, to, itemID, speed, duration, fixedDirection, explodes, hue, renderMode, effect,
explodeEffect, explodeSound, layer, unknown
);
state.Send(particles);
}
else if (itemID > 1)
{
OutgoingEffectPackets.CreateMovingHuedEffect(
regular,
from, to, itemID, speed, duration, fixedDirection, explodes, hue, renderMode
);
state.Send(regular);
}
OutgoingEffectPackets.CreateMovingHuedEffect(
regular,
from, to, itemID, speed, duration, fixedDirection, explodes, hue, renderMode
);
state.Send(regular);
}
eable.Free();
}
public static void SendPacket(Point3D origin, Map map, Span<byte> effectBuffer)
eable.Free();
}
public static void SendPacket(Point3D origin, Map map, Span<byte> effectBuffer)
{
if (map == null)
{
if (map == null)
{
return;
}
var eable = map.GetClientsInRange(new Point3D(origin));
foreach (var state in eable)
{
state.Mobile.ProcessDelta();
state.Send(effectBuffer);
}
eable.Free();
return;
}
var eable = map.GetClientsInRange(new Point3D(origin));
foreach (var state in eable)
{
state.Mobile.ProcessDelta();
state.Send(effectBuffer);
}
eable.Free();
}
}

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright (C) 2019-2021 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: EventLoopTasks.cs *
* *
@ -17,59 +17,58 @@ using System;
using System.Collections.Concurrent;
using System.Threading;
namespace Server
namespace Server;
public sealed class EventLoopContext : SynchronizationContext
{
public sealed class EventLoopContext : SynchronizationContext
private readonly ConcurrentQueue<Action> _queue;
private readonly Thread _mainThread;
public EventLoopContext()
{
private readonly ConcurrentQueue<Action> _queue;
private readonly Thread _mainThread;
_queue = new ConcurrentQueue<Action>();
_mainThread = Thread.CurrentThread;
}
public EventLoopContext()
public override SynchronizationContext CreateCopy() => new EventLoopContext();
public void Post(Action d) => _queue.Enqueue(d);
public override void Post(SendOrPostCallback d, object state) => _queue.Enqueue(() => d(state));
public override void Send(SendOrPostCallback d, object state)
{
if (Thread.CurrentThread == _mainThread)
{
_queue = new ConcurrentQueue<Action>();
_mainThread = Thread.CurrentThread;
d(state);
return;
}
public override SynchronizationContext CreateCopy() => new EventLoopContext();
AutoResetEvent evt = new AutoResetEvent(false);
public void Post(Action d) => _queue.Enqueue(d);
public override void Post(SendOrPostCallback d, object state) => _queue.Enqueue(() => d(state));
public override void Send(SendOrPostCallback d, object state)
_queue.Enqueue(() =>
{
if (Thread.CurrentThread == _mainThread)
{
d(state);
return;
}
d(state);
evt.Set();
});
AutoResetEvent evt = new AutoResetEvent(false);
evt.WaitOne();
}
_queue.Enqueue(() =>
{
d(state);
evt.Set();
});
evt.WaitOne();
public void ExecuteTasks()
{
if (Thread.CurrentThread != _mainThread)
{
throw new Exception("Called EventLoop.ExecuteTasks on incorrect thread!");
}
public void ExecuteTasks()
var count = _queue.Count;
for (int i = 0; i < count; i++)
{
if (Thread.CurrentThread != _mainThread)
if (_queue.TryDequeue(out var a))
{
throw new Exception("Called EventLoop.ExecuteTasks on incorrect thread!");
}
var count = _queue.Count;
for (int i = 0; i < count; i++)
{
if (_queue.TryDequeue(out var a))
{
a();
}
a();
}
}
}

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: AccountLoginEvent.cs *
* *
@ -17,33 +17,32 @@ using System;
using System.Runtime.CompilerServices;
using Server.Network;
namespace Server
namespace Server;
public class AccountLoginEventArgs
{
public class AccountLoginEventArgs
public AccountLoginEventArgs(NetState state, string username, string password)
{
public AccountLoginEventArgs(NetState state, string username, string password)
{
State = state;
Username = username;
Password = password;
}
public NetState State { get; }
public string Username { get; }
public string Password { get; }
public bool Accepted { get; set; }
public ALRReason RejectReason { get; set; }
State = state;
Username = username;
Password = password;
}
public static partial class EventSink
{
public static event Action<AccountLoginEventArgs> AccountLogin;
public NetState State { get; }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void InvokeAccountLogin(AccountLoginEventArgs e) => AccountLogin?.Invoke(e);
}
public string Username { get; }
public string Password { get; }
public bool Accepted { get; set; }
public ALRReason RejectReason { get; set; }
}
public static partial class EventSink
{
public static event Action<AccountLoginEventArgs> AccountLogin;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void InvokeAccountLogin(AccountLoginEventArgs e) => AccountLogin?.Invoke(e);
}

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: AggressiveActionEvent.cs *
* *
@ -17,56 +17,55 @@ using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
namespace Server
namespace Server;
public class AggressiveActionEventArgs : EventArgs
{
public class AggressiveActionEventArgs : EventArgs
private static readonly Queue<AggressiveActionEventArgs> m_Pool = new();
private AggressiveActionEventArgs(Mobile aggressed, Mobile aggressor, bool criminal)
{
private static readonly Queue<AggressiveActionEventArgs> m_Pool = new();
private AggressiveActionEventArgs(Mobile aggressed, Mobile aggressor, bool criminal)
{
Aggressed = aggressed;
Aggressor = aggressor;
Criminal = criminal;
}
public Mobile Aggressed { get; private set; }
public Mobile Aggressor { get; private set; }
public bool Criminal { get; private set; }
public static AggressiveActionEventArgs Create(Mobile aggressed, Mobile aggressor, bool criminal)
{
AggressiveActionEventArgs args;
if (m_Pool.Count > 0)
{
args = m_Pool.Dequeue();
args.Aggressed = aggressed;
args.Aggressor = aggressor;
args.Criminal = criminal;
}
else
{
args = new AggressiveActionEventArgs(aggressed, aggressor, criminal);
}
return args;
}
public void Free()
{
m_Pool.Enqueue(this);
}
Aggressed = aggressed;
Aggressor = aggressor;
Criminal = criminal;
}
public static partial class EventSink
{
public static event Action<AggressiveActionEventArgs> AggressiveAction;
public Mobile Aggressed { get; private set; }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void InvokeAggressiveAction(AggressiveActionEventArgs e) => AggressiveAction?.Invoke(e);
public Mobile Aggressor { get; private set; }
public bool Criminal { get; private set; }
public static AggressiveActionEventArgs Create(Mobile aggressed, Mobile aggressor, bool criminal)
{
AggressiveActionEventArgs args;
if (m_Pool.Count > 0)
{
args = m_Pool.Dequeue();
args.Aggressed = aggressed;
args.Aggressor = aggressor;
args.Criminal = criminal;
}
else
{
args = new AggressiveActionEventArgs(aggressed, aggressor, criminal);
}
return args;
}
public void Free()
{
m_Pool.Enqueue(this);
}
}
public static partial class EventSink
{
public static event Action<AggressiveActionEventArgs> AggressiveAction;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void InvokeAggressiveAction(AggressiveActionEventArgs e) => AggressiveAction?.Invoke(e);
}

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: CharacterCreatedEvent.cs *
* *
@ -18,77 +18,76 @@ using System.Runtime.CompilerServices;
using Server.Accounting;
using Server.Network;
namespace Server
namespace Server;
public class CharacterCreatedEventArgs
{
public class CharacterCreatedEventArgs
public CharacterCreatedEventArgs(
NetState state, IAccount a, string name, bool female, int hue, StatNameValue[] stats, CityInfo city,
SkillNameValue[] skills, int shirtHue, int pantsHue, int hairID, int hairHue, int beardID, int beardHue,
int profession, Race race
)
{
public CharacterCreatedEventArgs(
NetState state, IAccount a, string name, bool female, int hue, StatNameValue[] stats, CityInfo city,
SkillNameValue[] skills, int shirtHue, int pantsHue, int hairID, int hairHue, int beardID, int beardHue,
int profession, Race race
)
{
State = state;
Account = a;
Name = name;
Female = female;
Hue = hue;
Stats = stats;
City = city;
Skills = skills;
ShirtHue = shirtHue;
PantsHue = pantsHue;
HairID = hairID;
HairHue = hairHue;
BeardID = beardID;
BeardHue = beardHue;
Profession = profession;
Race = race;
}
public NetState State { get; }
public IAccount Account { get; }
public Mobile Mobile { get; set; }
public string Name { get; }
public bool Female { get; }
public int Hue { get; }
public StatNameValue[] Stats { get; }
public CityInfo City { get; }
public SkillNameValue[] Skills { get; }
public int ShirtHue { get; }
public int PantsHue { get; }
public int HairID { get; }
public int HairHue { get; }
public int BeardID { get; }
public int BeardHue { get; }
public int Profession { get; set; }
public Race Race { get; }
State = state;
Account = a;
Name = name;
Female = female;
Hue = hue;
Stats = stats;
City = city;
Skills = skills;
ShirtHue = shirtHue;
PantsHue = pantsHue;
HairID = hairID;
HairHue = hairHue;
BeardID = beardID;
BeardHue = beardHue;
Profession = profession;
Race = race;
}
public readonly record struct SkillNameValue(SkillName Name, int Value);
public readonly record struct StatNameValue(StatType Name, int Value);
public NetState State { get; }
public static partial class EventSink
{
public static event Action<CharacterCreatedEventArgs> CharacterCreated;
public IAccount Account { get; }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void InvokeCharacterCreated(CharacterCreatedEventArgs e) => CharacterCreated?.Invoke(e);
}
public Mobile Mobile { get; set; }
public string Name { get; }
public bool Female { get; }
public int Hue { get; }
public StatNameValue[] Stats { get; }
public CityInfo City { get; }
public SkillNameValue[] Skills { get; }
public int ShirtHue { get; }
public int PantsHue { get; }
public int HairID { get; }
public int HairHue { get; }
public int BeardID { get; }
public int BeardHue { get; }
public int Profession { get; set; }
public Race Race { get; }
}
public readonly record struct SkillNameValue(SkillName Name, int Value);
public readonly record struct StatNameValue(StatType Name, int Value);
public static partial class EventSink
{
public static event Action<CharacterCreatedEventArgs> CharacterCreated;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void InvokeCharacterCreated(CharacterCreatedEventArgs e) => CharacterCreated?.Invoke(e);
}

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: EventSink.cs *
* *
@ -17,145 +17,144 @@ using System;
using System.Collections.Generic;
using Server.Network;
namespace Server
namespace Server;
public static partial class EventSink
{
public static partial class EventSink
public static event Action<Mobile> OpenDoorMacroUsed;
public static void InvokeOpenDoorMacroUsed(Mobile m) => OpenDoorMacroUsed?.Invoke(m);
public static event Action<Mobile> Login;
public static void InvokeLogin(Mobile m) => Login?.Invoke(m);
public static event Action<Mobile, int> HungerChanged;
public static void InvokeHungerChanged(Mobile mobile, int oldValue) => HungerChanged?.Invoke(mobile, oldValue);
public static event Action Shutdown;
public static void InvokeShutdown() => Shutdown?.Invoke();
public static event Action<Mobile> HelpRequest;
public static void InvokeHelpRequest(Mobile m) => HelpRequest?.Invoke(m);
public static event Action<Mobile> DisarmRequest;
public static void InvokeDisarmRequest(Mobile m) => DisarmRequest?.Invoke(m);
public static event Action<Mobile> StunRequest;
public static void InvokeStunRequest(Mobile m) => StunRequest?.Invoke(m);
public static event Action<Mobile, int> OpenSpellbookRequest;
public static void InvokeOpenSpellbookRequest(Mobile m, int type) => OpenSpellbookRequest?.Invoke(m, type);
public static event Action<Mobile, int, Item> CastSpellRequest;
public static void InvokeCastSpellRequest(Mobile m, int spellID, Item book) =>
CastSpellRequest?.Invoke(m, spellID, book);
public static event Action<Mobile, Item, Mobile> BandageTargetRequest;
public static void InvokeBandageTargetRequest(Mobile m, Item bandage, Mobile target) =>
BandageTargetRequest?.Invoke(m, bandage, target);
public static event Action<Mobile, string> AnimateRequest;
public static void InvokeAnimateRequest(Mobile m, string action) => AnimateRequest?.Invoke(m, action);
public static event Action<Mobile> Logout;
public static void InvokeLogout(Mobile m) => Logout?.Invoke(m);
public static event Action<Mobile> Connected;
public static void InvokeConnected(Mobile m) => Connected?.Invoke(m);
public static event Action<Mobile> BeforeDisconnected;
public static void InvokeBeforeDisconnected(Mobile m) => BeforeDisconnected?.Invoke(m);
public static event Action<Mobile> Disconnected;
public static void InvokeDisconnected(Mobile m) => Disconnected?.Invoke(m);
public static event Action<Mobile, Mobile, string> RenameRequest;
public static void InvokeRenameRequest(Mobile from, Mobile target, string name) =>
RenameRequest?.Invoke(from, target, name);
public static event Action<Mobile> PlayerDeath;
public static void InvokePlayerDeath(Mobile m) => PlayerDeath?.Invoke(m);
public static event Action<Mobile, Mobile> VirtueGumpRequest;
public static void InvokeVirtueGumpRequest(Mobile beholder, Mobile beheld) =>
VirtueGumpRequest?.Invoke(beholder, beheld);
public static event Action<Mobile, Mobile, int> VirtueItemRequest;
public static void InvokeVirtueItemRequest(Mobile beholder, Mobile beheld, int gumpID) =>
VirtueItemRequest?.Invoke(beholder, beheld, gumpID);
public static event Action<Mobile, int> VirtueMacroRequest;
public static void InvokeVirtueMacroRequest(Mobile mobile, int virtueID) =>
VirtueMacroRequest?.Invoke(mobile, virtueID);
public static event Action<Mobile, Mobile> PaperdollRequest;
public static void InvokePaperdollRequest(Mobile beholder, Mobile beheld) =>
PaperdollRequest?.Invoke(beholder, beheld);
public static event Action<Mobile, Mobile> ProfileRequest;
public static void InvokeProfileRequest(Mobile beholder, Mobile beheld) => ProfileRequest?.Invoke(beholder, beheld);
public static event Action<Mobile, Mobile, string> ChangeProfileRequest;
public static void InvokeChangeProfileRequest(Mobile beholder, Mobile beheld, string text) =>
ChangeProfileRequest?.Invoke(beholder, beheld, text);
public static event Action<NetState, int> DeleteRequest;
public static void InvokeDeleteRequest(NetState state, int index) => DeleteRequest?.Invoke(state, index);
public static event Action ServerStarted;
public static void InvokeServerStarted() => ServerStarted?.Invoke();
public static event Action<Mobile> GuildGumpRequest;
public static void InvokeGuildGumpRequest(Mobile m) => GuildGumpRequest?.Invoke(m);
public static event Action<Mobile> QuestGumpRequest;
public static void InvokeQuestGumpRequest(Mobile m) => QuestGumpRequest?.Invoke(m);
public static event Action<NetState, ClientVersion> ClientVersionReceived;
public static void InvokeClientVersionReceived(NetState state, ClientVersion cv) =>
ClientVersionReceived?.Invoke(state, cv);
public static event Action<Mobile, List<Serial>> EquipMacro;
public static void InvokeEquipMacro(Mobile m, List<Serial> list)
{
public static event Action<Mobile> OpenDoorMacroUsed;
public static void InvokeOpenDoorMacroUsed(Mobile m) => OpenDoorMacroUsed?.Invoke(m);
public static event Action<Mobile> Login;
public static void InvokeLogin(Mobile m) => Login?.Invoke(m);
public static event Action<Mobile, int> HungerChanged;
public static void InvokeHungerChanged(Mobile mobile, int oldValue) => HungerChanged?.Invoke(mobile, oldValue);
public static event Action Shutdown;
public static void InvokeShutdown() => Shutdown?.Invoke();
public static event Action<Mobile> HelpRequest;
public static void InvokeHelpRequest(Mobile m) => HelpRequest?.Invoke(m);
public static event Action<Mobile> DisarmRequest;
public static void InvokeDisarmRequest(Mobile m) => DisarmRequest?.Invoke(m);
public static event Action<Mobile> StunRequest;
public static void InvokeStunRequest(Mobile m) => StunRequest?.Invoke(m);
public static event Action<Mobile, int> OpenSpellbookRequest;
public static void InvokeOpenSpellbookRequest(Mobile m, int type) => OpenSpellbookRequest?.Invoke(m, type);
public static event Action<Mobile, int, Item> CastSpellRequest;
public static void InvokeCastSpellRequest(Mobile m, int spellID, Item book) =>
CastSpellRequest?.Invoke(m, spellID, book);
public static event Action<Mobile, Item, Mobile> BandageTargetRequest;
public static void InvokeBandageTargetRequest(Mobile m, Item bandage, Mobile target) =>
BandageTargetRequest?.Invoke(m, bandage, target);
public static event Action<Mobile, string> AnimateRequest;
public static void InvokeAnimateRequest(Mobile m, string action) => AnimateRequest?.Invoke(m, action);
public static event Action<Mobile> Logout;
public static void InvokeLogout(Mobile m) => Logout?.Invoke(m);
public static event Action<Mobile> Connected;
public static void InvokeConnected(Mobile m) => Connected?.Invoke(m);
public static event Action<Mobile> BeforeDisconnected;
public static void InvokeBeforeDisconnected(Mobile m) => BeforeDisconnected?.Invoke(m);
public static event Action<Mobile> Disconnected;
public static void InvokeDisconnected(Mobile m) => Disconnected?.Invoke(m);
public static event Action<Mobile, Mobile, string> RenameRequest;
public static void InvokeRenameRequest(Mobile from, Mobile target, string name) =>
RenameRequest?.Invoke(from, target, name);
public static event Action<Mobile> PlayerDeath;
public static void InvokePlayerDeath(Mobile m) => PlayerDeath?.Invoke(m);
public static event Action<Mobile, Mobile> VirtueGumpRequest;
public static void InvokeVirtueGumpRequest(Mobile beholder, Mobile beheld) =>
VirtueGumpRequest?.Invoke(beholder, beheld);
public static event Action<Mobile, Mobile, int> VirtueItemRequest;
public static void InvokeVirtueItemRequest(Mobile beholder, Mobile beheld, int gumpID) =>
VirtueItemRequest?.Invoke(beholder, beheld, gumpID);
public static event Action<Mobile, int> VirtueMacroRequest;
public static void InvokeVirtueMacroRequest(Mobile mobile, int virtueID) =>
VirtueMacroRequest?.Invoke(mobile, virtueID);
public static event Action<Mobile, Mobile> PaperdollRequest;
public static void InvokePaperdollRequest(Mobile beholder, Mobile beheld) =>
PaperdollRequest?.Invoke(beholder, beheld);
public static event Action<Mobile, Mobile> ProfileRequest;
public static void InvokeProfileRequest(Mobile beholder, Mobile beheld) => ProfileRequest?.Invoke(beholder, beheld);
public static event Action<Mobile, Mobile, string> ChangeProfileRequest;
public static void InvokeChangeProfileRequest(Mobile beholder, Mobile beheld, string text) =>
ChangeProfileRequest?.Invoke(beholder, beheld, text);
public static event Action<NetState, int> DeleteRequest;
public static void InvokeDeleteRequest(NetState state, int index) => DeleteRequest?.Invoke(state, index);
public static event Action ServerStarted;
public static void InvokeServerStarted() => ServerStarted?.Invoke();
public static event Action<Mobile> GuildGumpRequest;
public static void InvokeGuildGumpRequest(Mobile m) => GuildGumpRequest?.Invoke(m);
public static event Action<Mobile> QuestGumpRequest;
public static void InvokeQuestGumpRequest(Mobile m) => QuestGumpRequest?.Invoke(m);
public static event Action<NetState, ClientVersion> ClientVersionReceived;
public static void InvokeClientVersionReceived(NetState state, ClientVersion cv) =>
ClientVersionReceived?.Invoke(state, cv);
public static event Action<Mobile, List<Serial>> EquipMacro;
public static void InvokeEquipMacro(Mobile m, List<Serial> list)
if (list?.Count > 0)
{
if (list?.Count > 0)
{
EquipMacro?.Invoke(m, list);
}
EquipMacro?.Invoke(m, list);
}
public static event Action<Mobile, List<Layer>> UnequipMacro;
public static void InvokeUnequipMacro(Mobile m, List<Layer> layers)
{
if (layers?.Count > 0)
{
UnequipMacro?.Invoke(m, layers);
}
}
public static event Action<Mobile, IEntity, int> TargetedSpell;
public static void InvokeTargetedSpell(Mobile m, IEntity target, int spellId) =>
TargetedSpell?.Invoke(m, target, spellId);
public static event Action<Mobile, IEntity, int> TargetedSkillUse;
public static void InvokeTargetedSkillUse(Mobile m, IEntity target, int skillId) =>
TargetedSkillUse?.Invoke(m, target, skillId);
public static event Action<Mobile, Item, short> TargetByResourceMacro;
public static void InvokeTargetByResourceMacro(Mobile m, Item item, short resourceType) =>
TargetByResourceMacro?.Invoke(m, item, resourceType);
}
public static event Action<Mobile, List<Layer>> UnequipMacro;
public static void InvokeUnequipMacro(Mobile m, List<Layer> layers)
{
if (layers?.Count > 0)
{
UnequipMacro?.Invoke(m, layers);
}
}
public static event Action<Mobile, IEntity, int> TargetedSpell;
public static void InvokeTargetedSpell(Mobile m, IEntity target, int spellId) =>
TargetedSpell?.Invoke(m, target, spellId);
public static event Action<Mobile, IEntity, int> TargetedSkillUse;
public static void InvokeTargetedSkillUse(Mobile m, IEntity target, int skillId) =>
TargetedSkillUse?.Invoke(m, target, skillId);
public static event Action<Mobile, Item, short> TargetByResourceMacro;
public static void InvokeTargetByResourceMacro(Mobile m, Item item, short resourceType) =>
TargetByResourceMacro?.Invoke(m, item, resourceType);
}

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: FastwalkEvent.cs *
* *
@ -17,22 +17,21 @@ using System;
using System.Runtime.CompilerServices;
using Server.Network;
namespace Server
namespace Server;
public class FastWalkEventArgs
{
public class FastWalkEventArgs
{
public FastWalkEventArgs(NetState state) => NetState = state;
public FastWalkEventArgs(NetState state) => NetState = state;
public NetState NetState { get; }
public NetState NetState { get; }
public bool Blocked { get; set; } = true;
}
public static partial class EventSink
{
public static event Action<FastWalkEventArgs> FastWalk;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void InvokeFastWalk(FastWalkEventArgs e) => FastWalk?.Invoke(e);
}
public bool Blocked { get; set; } = true;
}
public static partial class EventSink
{
public static event Action<FastWalkEventArgs> FastWalk;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void InvokeFastWalk(FastWalkEventArgs e) => FastWalk?.Invoke(e);
}

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: GameLoginEvent.cs *
* *
@ -17,33 +17,32 @@ using System;
using System.Runtime.CompilerServices;
using Server.Network;
namespace Server
namespace Server;
public class GameLoginEventArgs
{
public class GameLoginEventArgs
public GameLoginEventArgs(NetState state, string un, string pw)
{
public GameLoginEventArgs(NetState state, string un, string pw)
{
State = state;
Username = un;
Password = pw;
}
public NetState State { get; }
public string Username { get; }
public string Password { get; }
public bool Accepted { get; set; }
public CityInfo[] CityInfo { get; set; }
State = state;
Username = un;
Password = pw;
}
public static partial class EventSink
{
public static event Action<GameLoginEventArgs> GameLogin;
public NetState State { get; }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void InvokeGameLogin(GameLoginEventArgs e) => GameLogin?.Invoke(e);
}
public string Username { get; }
public string Password { get; }
public bool Accepted { get; set; }
public CityInfo[] CityInfo { get; set; }
}
public static partial class EventSink
{
public static event Action<GameLoginEventArgs> GameLogin;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void InvokeGameLogin(GameLoginEventArgs e) => GameLogin?.Invoke(e);
}

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: MovementEvent.cs *
* *
@ -17,55 +17,54 @@ using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
namespace Server
namespace Server;
public class MovementEventArgs : EventArgs
{
public class MovementEventArgs : EventArgs
private static readonly Queue<MovementEventArgs> m_Pool = new();
public MovementEventArgs(Mobile mobile, Direction dir)
{
private static readonly Queue<MovementEventArgs> m_Pool = new();
public MovementEventArgs(Mobile mobile, Direction dir)
{
Mobile = mobile;
Direction = dir;
}
public Mobile Mobile { get; private set; }
public Direction Direction { get; private set; }
public bool Blocked { get; set; }
public static MovementEventArgs Create(Mobile mobile, Direction dir)
{
MovementEventArgs args;
if (m_Pool.Count > 0)
{
args = m_Pool.Dequeue();
args.Mobile = mobile;
args.Direction = dir;
args.Blocked = false;
}
else
{
args = new MovementEventArgs(mobile, dir);
}
return args;
}
public void Free()
{
m_Pool.Enqueue(this);
}
Mobile = mobile;
Direction = dir;
}
public static partial class EventSink
{
public static event Action<MovementEventArgs> Movement;
public Mobile Mobile { get; private set; }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void InvokeMovement(MovementEventArgs e) => Movement?.Invoke(e);
public Direction Direction { get; private set; }
public bool Blocked { get; set; }
public static MovementEventArgs Create(Mobile mobile, Direction dir)
{
MovementEventArgs args;
if (m_Pool.Count > 0)
{
args = m_Pool.Dequeue();
args.Mobile = mobile;
args.Direction = dir;
args.Blocked = false;
}
else
{
args = new MovementEventArgs(mobile, dir);
}
return args;
}
public void Free()
{
m_Pool.Enqueue(this);
}
}
public static partial class EventSink
{
public static event Action<MovementEventArgs> Movement;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void InvokeMovement(MovementEventArgs e) => Movement?.Invoke(e);
}

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: ServerCrashedEvent.cs *
* *
@ -16,22 +16,21 @@
using System;
using System.Runtime.CompilerServices;
namespace Server
namespace Server;
public class ServerCrashedEventArgs
{
public class ServerCrashedEventArgs
{
public ServerCrashedEventArgs(Exception e) => Exception = e;
public ServerCrashedEventArgs(Exception e) => Exception = e;
public Exception Exception { get; }
public Exception Exception { get; }
public bool Close { get; set; }
}
public static partial class EventSink
{
public static event Action<ServerCrashedEventArgs> ServerCrashed;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void InvokeServerCrashed(ServerCrashedEventArgs e) => ServerCrashed?.Invoke(e);
}
public bool Close { get; set; }
}
public static partial class EventSink
{
public static event Action<ServerCrashedEventArgs> ServerCrashed;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void InvokeServerCrashed(ServerCrashedEventArgs e) => ServerCrashed?.Invoke(e);
}

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: ServerListEvent.cs *
* *
@ -20,41 +20,40 @@ using System.Runtime.CompilerServices;
using Server.Accounting;
using Server.Network;
namespace Server
namespace Server;
public class ServerListEventArgs
{
public class ServerListEventArgs
public ServerListEventArgs(NetState state, IAccount account)
{
public ServerListEventArgs(NetState state, IAccount account)
{
State = state;
Account = account;
Servers = new List<ServerInfo>();
}
public NetState State { get; }
public IAccount Account { get; }
public bool Rejected { get; set; }
public List<ServerInfo> Servers { get; }
public void AddServer(string name, IPEndPoint address)
{
AddServer(name, 0, TimeZoneInfo.Local, address);
}
public void AddServer(string name, int fullPercent, TimeZoneInfo tz, IPEndPoint address)
{
Servers.Add(new ServerInfo(name, fullPercent, tz, address));
}
State = state;
Account = account;
Servers = new List<ServerInfo>();
}
public static partial class EventSink
{
public static event Action<ServerListEventArgs> ServerList;
public NetState State { get; }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void InvokeServerList(ServerListEventArgs e) => ServerList?.Invoke(e);
public IAccount Account { get; }
public bool Rejected { get; set; }
public List<ServerInfo> Servers { get; }
public void AddServer(string name, IPEndPoint address)
{
AddServer(name, 0, TimeZoneInfo.Local, address);
}
public void AddServer(string name, int fullPercent, TimeZoneInfo tz, IPEndPoint address)
{
Servers.Add(new ServerInfo(name, fullPercent, tz, address));
}
}
public static partial class EventSink
{
public static event Action<ServerListEventArgs> ServerList;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void InvokeServerList(ServerListEventArgs e) => ServerList?.Invoke(e);
}

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: SocketConnectionEvent.cs *
* *
@ -17,26 +17,25 @@ using System;
using System.Net.Sockets;
using System.Runtime.CompilerServices;
namespace Server
namespace Server;
public class SocketConnectEventArgs
{
public class SocketConnectEventArgs
public SocketConnectEventArgs(Socket c)
{
public SocketConnectEventArgs(Socket c)
{
Connection = c;
AllowConnection = true;
}
public Socket Connection { get; }
public bool AllowConnection { get; set; }
Connection = c;
AllowConnection = true;
}
public static partial class EventSink
{
public static event Action<SocketConnectEventArgs> SocketConnect;
public Socket Connection { get; }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void InvokeSocketConnect(SocketConnectEventArgs e) => SocketConnect?.Invoke(e);
}
public bool AllowConnection { get; set; }
}
public static partial class EventSink
{
public static event Action<SocketConnectEventArgs> SocketConnect;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void InvokeSocketConnect(SocketConnectEventArgs e) => SocketConnect?.Invoke(e);
}

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: SpeechEvent.cs *
* *
@ -17,52 +17,51 @@ using System;
using System.Runtime.CompilerServices;
using Server.Network;
namespace Server
namespace Server;
public class SpeechEventArgs
{
public class SpeechEventArgs
public SpeechEventArgs(Mobile mobile, string speech, MessageType type, int hue, int[] keywords)
{
public SpeechEventArgs(Mobile mobile, string speech, MessageType type, int hue, int[] keywords)
{
Mobile = mobile;
Speech = speech;
Type = type;
Hue = hue;
Keywords = keywords;
}
public Mobile Mobile { get; }
public string Speech { get; set; }
public MessageType Type { get; }
public int Hue { get; }
public int[] Keywords { get; }
public bool Handled { get; set; }
public bool Blocked { get; set; }
public bool HasKeyword(int keyword)
{
for (var i = 0; i < Keywords.Length; ++i)
{
if (Keywords[i] == keyword)
{
return true;
}
}
return false;
}
Mobile = mobile;
Speech = speech;
Type = type;
Hue = hue;
Keywords = keywords;
}
public static partial class EventSink
{
public static event Action<SpeechEventArgs> Speech;
public Mobile Mobile { get; }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void InvokeSpeech(SpeechEventArgs e) => Speech?.Invoke(e);
public string Speech { get; set; }
public MessageType Type { get; }
public int Hue { get; }
public int[] Keywords { get; }
public bool Handled { get; set; }
public bool Blocked { get; set; }
public bool HasKeyword(int keyword)
{
for (var i = 0; i < Keywords.Length; ++i)
{
if (Keywords[i] == keyword)
{
return true;
}
}
return false;
}
}
public static partial class EventSink
{
public static event Action<SpeechEventArgs> Speech;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void InvokeSpeech(SpeechEventArgs e) => Speech?.Invoke(e);
}

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright (C) 2019-2021 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: ExceptionExtensions.cs *
* *
@ -18,25 +18,24 @@ using System.Diagnostics;
using System.Linq.Expressions;
using System.Reflection;
namespace Server.Exceptions
namespace Server.Exceptions;
public static class ExceptionExtensions
{
public static class ExceptionExtensions
public static Exception SetStackTrace(this Exception target, StackTrace stack) => _setStackTrace(target, stack);
private static readonly Func<Exception, StackTrace, Exception> _setStackTrace = _createStackTraceMethod();
private static Func<Exception, StackTrace, Exception> _createStackTraceMethod()
{
public static Exception SetStackTrace(this Exception target, StackTrace stack) => _setStackTrace(target, stack);
private static readonly Func<Exception, StackTrace, Exception> _setStackTrace = _createStackTraceMethod();
private static Func<Exception, StackTrace, Exception> _createStackTraceMethod()
{
ParameterExpression target = Expression.Parameter(typeof(Exception));
ParameterExpression stack = Expression.Parameter(typeof(StackTrace));
Type traceFormatType = typeof(StackTrace).GetNestedType("TraceFormat", BindingFlags.NonPublic);
MethodInfo toString = typeof(StackTrace).GetMethod("ToString", BindingFlags.NonPublic | BindingFlags.Instance, null, new[] { traceFormatType }, null);
object normalTraceFormat = Enum.GetValues(traceFormatType!).GetValue(0);
MethodCallExpression stackTraceString = Expression.Call(stack, toString!, Expression.Constant(normalTraceFormat, traceFormatType));
FieldInfo stackTraceStringField = typeof(Exception).GetField("_stackTraceString", BindingFlags.NonPublic | BindingFlags.Instance);
BinaryExpression assign = Expression.Assign(Expression.Field(target, stackTraceStringField!), stackTraceString);
return Expression.Lambda<Func<Exception, StackTrace, Exception>>(Expression.Block(assign, target), target, stack).Compile();
}
ParameterExpression target = Expression.Parameter(typeof(Exception));
ParameterExpression stack = Expression.Parameter(typeof(StackTrace));
Type traceFormatType = typeof(StackTrace).GetNestedType("TraceFormat", BindingFlags.NonPublic);
MethodInfo toString = typeof(StackTrace).GetMethod("ToString", BindingFlags.NonPublic | BindingFlags.Instance, null, new[] { traceFormatType }, null);
object normalTraceFormat = Enum.GetValues(traceFormatType!).GetValue(0);
MethodCallExpression stackTraceString = Expression.Call(stack, toString!, Expression.Constant(normalTraceFormat, traceFormatType));
FieldInfo stackTraceStringField = typeof(Exception).GetField("_stackTraceString", BindingFlags.NonPublic | BindingFlags.Instance);
BinaryExpression assign = Expression.Assign(Expression.Field(target, stackTraceStringField!), stackTraceString);
return Expression.Lambda<Func<Exception, StackTrace, Exception>>(Expression.Block(assign, target), target, stack).Compile();
}
}

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: InvalidThreadException.cs *
* *
@ -15,12 +15,11 @@
using System;
namespace Server.Exceptions
namespace Server.Exceptions;
public class InvalidThreadException : Exception
{
public class InvalidThreadException : Exception
public InvalidThreadException(string methodName) : base($"{methodName} executed on an invalid thread.")
{
public InvalidThreadException(string methodName) : base($"{methodName} executed on an invalid thread.")
{
}
}
}

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: MaxConnectionsException.cs *
* *
@ -15,12 +15,11 @@
using System;
namespace Server.Exceptions
namespace Server.Exceptions;
public class MaxConnectionsException : Exception
{
public class MaxConnectionsException : Exception
public MaxConnectionsException() : base("Maximum connections exceeded")
{
public MaxConnectionsException() : base("Maximum connections exceeded")
{
}
}
}

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2021 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: ExpansionInfo.cs *
* *

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: Point2D.cs *
* *
@ -15,102 +15,101 @@
using System;
namespace Server
namespace Server;
[Parsable]
public struct Point2D
: IPoint2D, IComparable<Point2D>, IComparable<IPoint2D>, IEquatable<object>, IEquatable<Point2D>,
IEquatable<IPoint2D>
{
[Parsable]
public struct Point2D
: IPoint2D, IComparable<Point2D>, IComparable<IPoint2D>, IEquatable<object>, IEquatable<Point2D>,
IEquatable<IPoint2D>
internal int m_X;
internal int m_Y;
public static readonly Point2D Zero = new(0, 0);
[CommandProperty(AccessLevel.Counselor)]
public int X
{
internal int m_X;
internal int m_Y;
get => m_X;
set => m_X = value;
}
public static readonly Point2D Zero = new(0, 0);
[CommandProperty(AccessLevel.Counselor)]
public int Y
{
get => m_Y;
set => m_Y = value;
}
[CommandProperty(AccessLevel.Counselor)]
public int X
{
get => m_X;
set => m_X = value;
}
public Point2D(int x, int y)
{
m_X = x;
m_Y = y;
}
[CommandProperty(AccessLevel.Counselor)]
public int Y
{
get => m_Y;
set => m_Y = value;
}
public Point2D(Point2D p) : this(p.X, p.Y)
{
}
public Point2D(int x, int y)
{
m_X = x;
m_Y = y;
}
public override string ToString() => $"({m_X}, {m_Y})";
public Point2D(Point2D p) : this(p.X, p.Y)
{
}
public static Point2D Parse(string value)
{
var start = value.IndexOfOrdinal('(');
var end = value.IndexOf(',', start + 1);
public override string ToString() => $"({m_X}, {m_Y})";
Utility.ToInt32(value.AsSpan(start + 1, end - (start + 1)).Trim(), out var x);
public static Point2D Parse(string value)
{
var start = value.IndexOfOrdinal('(');
var end = value.IndexOf(',', start + 1);
start = end;
end = value.IndexOf(')', start + 1);
Utility.ToInt32(value.AsSpan(start + 1, end - (start + 1)).Trim(), out var x);
Utility.ToInt32(value.AsSpan(start + 1, end - (start + 1)).Trim(), out var y);
start = end;
end = value.IndexOf(')', start + 1);
return new Point2D(x, y);
}
Utility.ToInt32(value.AsSpan(start + 1, end - (start + 1)).Trim(), out var y);
public bool Equals(Point2D other) => m_X == other.m_X && m_Y == other.m_Y;
return new Point2D(x, y);
}
public bool Equals(IPoint2D other) =>
m_X == other?.X && m_Y == other.Y;
public bool Equals(Point2D other) => m_X == other.m_X && m_Y == other.m_Y;
public override bool Equals(object obj) => obj is Point2D other && Equals(other);
public bool Equals(IPoint2D other) =>
m_X == other?.X && m_Y == other.Y;
public override int GetHashCode() => HashCode.Combine(m_X, m_Y);
public override bool Equals(object obj) => obj is Point2D other && Equals(other);
public static bool operator ==(Point2D l, Point2D r) => l.m_X == r.m_X && l.m_Y == r.m_Y;
public override int GetHashCode() => HashCode.Combine(m_X, m_Y);
public static bool operator !=(Point2D l, Point2D r) => l.m_X != r.m_X || l.m_Y != r.m_Y;
public static bool operator ==(Point2D l, Point2D r) => l.m_X == r.m_X && l.m_Y == r.m_Y;
public static bool operator ==(Point2D l, IPoint2D r) => !ReferenceEquals(r, null) && l.m_X == r.X && l.m_Y == r.Y;
public static bool operator !=(Point2D l, Point2D r) => l.m_X != r.m_X || l.m_Y != r.m_Y;
public static bool operator !=(Point2D l, IPoint2D r) => !ReferenceEquals(r, null) && (l.m_X != r.X || l.m_Y != r.Y);
public static bool operator ==(Point2D l, IPoint2D r) => !ReferenceEquals(r, null) && l.m_X == r.X && l.m_Y == r.Y;
public static bool operator >(Point2D l, Point2D r) => l.m_X > r.m_X && l.m_Y > r.m_Y;
public static bool operator !=(Point2D l, IPoint2D r) => !ReferenceEquals(r, null) && (l.m_X != r.X || l.m_Y != r.Y);
public static bool operator >(Point2D l, IPoint2D r) => !ReferenceEquals(r, null) && l.m_X > r.X && l.m_Y > r.Y;
public static bool operator >(Point2D l, Point2D r) => l.m_X > r.m_X && l.m_Y > r.m_Y;
public static bool operator <(Point2D l, Point2D r) => l.m_X < r.m_X && l.m_Y < r.m_Y;
public static bool operator >(Point2D l, IPoint2D r) => !ReferenceEquals(r, null) && l.m_X > r.X && l.m_Y > r.Y;
public static bool operator <(Point2D l, IPoint2D r) => !ReferenceEquals(r, null) && l.m_X < r.X && l.m_Y < r.Y;
public static bool operator <(Point2D l, Point2D r) => l.m_X < r.m_X && l.m_Y < r.m_Y;
public static bool operator >=(Point2D l, Point2D r) => l.m_X >= r.m_X && l.m_Y >= r.m_Y;
public static bool operator <(Point2D l, IPoint2D r) => !ReferenceEquals(r, null) && l.m_X < r.X && l.m_Y < r.Y;
public static bool operator >=(Point2D l, IPoint2D r) => !ReferenceEquals(r, null) && l.m_X >= r.X && l.m_Y >= r.Y;
public static bool operator >=(Point2D l, Point2D r) => l.m_X >= r.m_X && l.m_Y >= r.m_Y;
public static bool operator <=(Point2D l, Point2D r) => l.m_X <= r.m_X && l.m_Y <= r.m_Y;
public static bool operator >=(Point2D l, IPoint2D r) => !ReferenceEquals(r, null) && l.m_X >= r.X && l.m_Y >= r.Y;
public static bool operator <=(Point2D l, IPoint2D r) => !ReferenceEquals(r, null) && l.m_X <= r.X && l.m_Y <= r.Y;
public static bool operator <=(Point2D l, Point2D r) => l.m_X <= r.m_X && l.m_Y <= r.m_Y;
public int CompareTo(Point2D other)
{
var xComparison = m_X.CompareTo(other.m_X);
return xComparison != 0 ? xComparison : m_Y.CompareTo(other.m_Y);
}
public static bool operator <=(Point2D l, IPoint2D r) => !ReferenceEquals(r, null) && l.m_X <= r.X && l.m_Y <= r.Y;
public int CompareTo(Point2D other)
{
var xComparison = m_X.CompareTo(other.m_X);
return xComparison != 0 ? xComparison : m_Y.CompareTo(other.m_Y);
}
public int CompareTo(IPoint2D other)
{
var xComparison = m_X.CompareTo(other.X);
return xComparison != 0 ? xComparison : m_Y.CompareTo(other.Y);
}
public int CompareTo(IPoint2D other)
{
var xComparison = m_X.CompareTo(other.X);
return xComparison != 0 ? xComparison : m_Y.CompareTo(other.Y);
}
}

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: Point3D.cs *
* *
@ -16,153 +16,152 @@
using System;
using System.Runtime.CompilerServices;
namespace Server
namespace Server;
[Parsable]
public struct Point3D
: IPoint3D, IComparable<Point3D>, IComparable<IPoint3D>, IEquatable<object>, IEquatable<Point3D>,
IEquatable<IPoint3D>
{
[Parsable]
public struct Point3D
: IPoint3D, IComparable<Point3D>, IComparable<IPoint3D>, IEquatable<object>, IEquatable<Point3D>,
IEquatable<IPoint3D>
internal int m_X;
internal int m_Y;
internal int m_Z;
public static readonly Point3D Zero = new(0, 0, 0);
[CommandProperty(AccessLevel.Counselor)]
public int X
{
internal int m_X;
internal int m_Y;
internal int m_Z;
get => m_X;
set => m_X = value;
}
public static readonly Point3D Zero = new(0, 0, 0);
[CommandProperty(AccessLevel.Counselor)]
public int Y
{
get => m_Y;
set => m_Y = value;
}
[CommandProperty(AccessLevel.Counselor)]
public int X
[CommandProperty(AccessLevel.Counselor)]
public int Z
{
get => m_Z;
set => m_Z = value;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Point3D(IPoint3D p) : this(p.X, p.Y, p.Z)
{
}
public Point3D(Point3D p) : this(p.X, p.Y, p.Z)
{
}
public Point3D(Point2D p, int z) : this(p.X, p.Y, z)
{
}
public Point3D(int x, int y, int z)
{
m_X = x;
m_Y = y;
m_Z = z;
}
public override string ToString() => $"({m_X}, {m_Y}, {m_Z})";
public bool Equals(Point3D other) => m_X == other.m_X && m_Y == other.m_Y && m_Z == other.m_Z;
public bool Equals(IPoint3D other) =>
m_X == other?.X && m_Y == other.Y && m_Z == other.Z;
public override bool Equals(object obj) => obj is Point3D other && Equals(other);
public override int GetHashCode() => HashCode.Combine(m_X, m_Y, m_Z);
public static Point3D Parse(string value)
{
var start = value.IndexOfOrdinal('(');
var end = value.IndexOf(',', start + 1);
Utility.ToInt32(value.AsSpan(start + 1, end - (start + 1)).Trim(), out var x);
start = end;
end = value.IndexOf(',', start + 1);
Utility.ToInt32(value.AsSpan(start + 1, end - (start + 1)).Trim(), out var y);
start = end;
end = value.IndexOf(')', start + 1);
Utility.ToInt32(value.AsSpan(start + 1, end - (start + 1)).Trim(), out var z);
return new Point3D(x, y, z);
}
public static bool operator ==(Point3D l, Point3D r) => l.m_X == r.m_X && l.m_Y == r.m_Y && l.m_Z == r.m_Z;
public static bool operator ==(Point3D l, IPoint3D r) =>
!ReferenceEquals(r, null) && l.m_X == r.X && l.m_Y == r.Y && l.m_Z == r.Z;
public static bool operator !=(Point3D l, Point3D r) => l.m_X != r.m_X || l.m_Y != r.m_Y || l.m_Z != r.m_Z;
public static bool operator !=(Point3D l, IPoint3D r) =>
!ReferenceEquals(r, null) && (l.m_X != r.X || l.m_Y != r.Y || l.m_Z != r.Z);
public static bool operator >(Point3D l, Point3D r) => l.m_X > r.m_X && l.m_Y > r.m_Y && l.m_Z > r.m_Z;
public static bool operator >(Point3D l, IPoint3D r) =>
!ReferenceEquals(r, null) && l.m_X > r.X && l.m_Y > r.Y && l.m_Z > r.Z;
public static bool operator <(Point3D l, Point3D r) => l.m_X < r.m_X && l.m_Y < r.m_Y && l.m_Z > r.m_Z;
public static bool operator <(Point3D l, IPoint3D r) =>
!ReferenceEquals(r, null) && l.m_X < r.X && l.m_Y < r.Y && l.m_Z > r.Z;
public static bool operator >=(Point3D l, Point3D r) => l.m_X >= r.m_X && l.m_Y >= r.m_Y && l.m_Z > r.m_Z;
public static bool operator >=(Point3D l, IPoint3D r) =>
!ReferenceEquals(r, null) && l.m_X >= r.X && l.m_Y >= r.Y && l.m_Z > r.Z;
public static bool operator <=(Point3D l, Point3D r) => l.m_X <= r.m_X && l.m_Y <= r.m_Y && l.m_Z > r.m_Z;
public static bool operator <=(Point3D l, IPoint3D r) =>
!ReferenceEquals(r, null) && l.m_X <= r.X && l.m_Y <= r.Y && l.m_Z > r.Z;
public int CompareTo(Point3D other)
{
var xComparison = m_X.CompareTo(other.m_X);
if (xComparison != 0)
{
get => m_X;
set => m_X = value;
return xComparison;
}
[CommandProperty(AccessLevel.Counselor)]
public int Y
var yComparison = m_Y.CompareTo(other.m_Y);
if (yComparison != 0)
{
get => m_Y;
set => m_Y = value;
return yComparison;
}
[CommandProperty(AccessLevel.Counselor)]
public int Z
return m_Z.CompareTo(other.m_Z);
}
public int CompareTo(IPoint3D other)
{
var xComparison = m_X.CompareTo(other.X);
if (xComparison != 0)
{
get => m_Z;
set => m_Z = value;
return xComparison;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Point3D(IPoint3D p) : this(p.X, p.Y, p.Z)
var yComparison = m_Y.CompareTo(other.Y);
if (yComparison != 0)
{
return yComparison;
}
public Point3D(Point3D p) : this(p.X, p.Y, p.Z)
{
}
public Point3D(Point2D p, int z) : this(p.X, p.Y, z)
{
}
public Point3D(int x, int y, int z)
{
m_X = x;
m_Y = y;
m_Z = z;
}
public override string ToString() => $"({m_X}, {m_Y}, {m_Z})";
public bool Equals(Point3D other) => m_X == other.m_X && m_Y == other.m_Y && m_Z == other.m_Z;
public bool Equals(IPoint3D other) =>
m_X == other?.X && m_Y == other.Y && m_Z == other.Z;
public override bool Equals(object obj) => obj is Point3D other && Equals(other);
public override int GetHashCode() => HashCode.Combine(m_X, m_Y, m_Z);
public static Point3D Parse(string value)
{
var start = value.IndexOfOrdinal('(');
var end = value.IndexOf(',', start + 1);
Utility.ToInt32(value.AsSpan(start + 1, end - (start + 1)).Trim(), out var x);
start = end;
end = value.IndexOf(',', start + 1);
Utility.ToInt32(value.AsSpan(start + 1, end - (start + 1)).Trim(), out var y);
start = end;
end = value.IndexOf(')', start + 1);
Utility.ToInt32(value.AsSpan(start + 1, end - (start + 1)).Trim(), out var z);
return new Point3D(x, y, z);
}
public static bool operator ==(Point3D l, Point3D r) => l.m_X == r.m_X && l.m_Y == r.m_Y && l.m_Z == r.m_Z;
public static bool operator ==(Point3D l, IPoint3D r) =>
!ReferenceEquals(r, null) && l.m_X == r.X && l.m_Y == r.Y && l.m_Z == r.Z;
public static bool operator !=(Point3D l, Point3D r) => l.m_X != r.m_X || l.m_Y != r.m_Y || l.m_Z != r.m_Z;
public static bool operator !=(Point3D l, IPoint3D r) =>
!ReferenceEquals(r, null) && (l.m_X != r.X || l.m_Y != r.Y || l.m_Z != r.Z);
public static bool operator >(Point3D l, Point3D r) => l.m_X > r.m_X && l.m_Y > r.m_Y && l.m_Z > r.m_Z;
public static bool operator >(Point3D l, IPoint3D r) =>
!ReferenceEquals(r, null) && l.m_X > r.X && l.m_Y > r.Y && l.m_Z > r.Z;
public static bool operator <(Point3D l, Point3D r) => l.m_X < r.m_X && l.m_Y < r.m_Y && l.m_Z > r.m_Z;
public static bool operator <(Point3D l, IPoint3D r) =>
!ReferenceEquals(r, null) && l.m_X < r.X && l.m_Y < r.Y && l.m_Z > r.Z;
public static bool operator >=(Point3D l, Point3D r) => l.m_X >= r.m_X && l.m_Y >= r.m_Y && l.m_Z > r.m_Z;
public static bool operator >=(Point3D l, IPoint3D r) =>
!ReferenceEquals(r, null) && l.m_X >= r.X && l.m_Y >= r.Y && l.m_Z > r.Z;
public static bool operator <=(Point3D l, Point3D r) => l.m_X <= r.m_X && l.m_Y <= r.m_Y && l.m_Z > r.m_Z;
public static bool operator <=(Point3D l, IPoint3D r) =>
!ReferenceEquals(r, null) && l.m_X <= r.X && l.m_Y <= r.Y && l.m_Z > r.Z;
public int CompareTo(Point3D other)
{
var xComparison = m_X.CompareTo(other.m_X);
if (xComparison != 0)
{
return xComparison;
}
var yComparison = m_Y.CompareTo(other.m_Y);
if (yComparison != 0)
{
return yComparison;
}
return m_Z.CompareTo(other.m_Z);
}
public int CompareTo(IPoint3D other)
{
var xComparison = m_X.CompareTo(other.X);
if (xComparison != 0)
{
return xComparison;
}
var yComparison = m_Y.CompareTo(other.Y);
if (yComparison != 0)
{
return yComparison;
}
return m_Z.CompareTo(other.Z);
}
return m_Z.CompareTo(other.Z);
}
}

View file

@ -1,84 +1,83 @@
using System;
namespace Server
namespace Server;
public class Point3DList
{
public class Point3DList
private static readonly Point3D[] m_EmptyList = Array.Empty<Point3D>();
private Point3D[] m_List;
public Point3DList()
{
private static readonly Point3D[] m_EmptyList = Array.Empty<Point3D>();
private Point3D[] m_List;
m_List = new Point3D[8];
Count = 0;
}
public Point3DList()
public int Count { get; private set; }
public Point3D Last => m_List[Count - 1];
public Point3D this[int index] => m_List[index];
public void Clear()
{
Count = 0;
}
public void Add(int x, int y, int z)
{
if (Count + 1 > m_List.Length)
{
m_List = new Point3D[8];
Count = 0;
}
var old = m_List;
m_List = new Point3D[old.Length * 2];
public int Count { get; private set; }
public Point3D Last => m_List[Count - 1];
public Point3D this[int index] => m_List[index];
public void Clear()
{
Count = 0;
}
public void Add(int x, int y, int z)
{
if (Count + 1 > m_List.Length)
for (var i = 0; i < old.Length; ++i)
{
var old = m_List;
m_List = new Point3D[old.Length * 2];
for (var i = 0; i < old.Length; ++i)
{
m_List[i] = old[i];
}
m_List[i] = old[i];
}
m_List[Count].m_X = x;
m_List[Count].m_Y = y;
m_List[Count].m_Z = z;
++Count;
}
public void Add(Point3D p)
m_List[Count].m_X = x;
m_List[Count].m_Y = y;
m_List[Count].m_Z = z;
++Count;
}
public void Add(Point3D p)
{
if (Count + 1 > m_List.Length)
{
if (Count + 1 > m_List.Length)
var old = m_List;
m_List = new Point3D[old.Length * 2];
for (var i = 0; i < old.Length; ++i)
{
var old = m_List;
m_List = new Point3D[old.Length * 2];
for (var i = 0; i < old.Length; ++i)
{
m_List[i] = old[i];
}
m_List[i] = old[i];
}
m_List[Count].m_X = p.m_X;
m_List[Count].m_Y = p.m_Y;
m_List[Count].m_Z = p.m_Z;
++Count;
}
public Point3D[] ToArray()
m_List[Count].m_X = p.m_X;
m_List[Count].m_Y = p.m_Y;
m_List[Count].m_Z = p.m_Z;
++Count;
}
public Point3D[] ToArray()
{
if (Count == 0)
{
if (Count == 0)
{
return m_EmptyList;
}
var list = new Point3D[Count];
for (var i = 0; i < Count; ++i)
{
list[i] = m_List[i];
}
Count = 0;
return list;
return m_EmptyList;
}
var list = new Point3D[Count];
for (var i = 0; i < Count; ++i)
{
list[i] = m_List[i];
}
Count = 0;
return list;
}
}

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: Rectangle2D.cs *
* *

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: Rectangle3D.cs *
* *
@ -13,130 +13,129 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
*************************************************************************/
namespace Server
namespace Server;
[NoSort]
[PropertyObject]
public struct Rectangle3D
{
[NoSort]
[PropertyObject]
public struct Rectangle3D
private Point3D m_Start;
private Point3D m_End;
public Rectangle3D(Point3D start, Point3D end)
{
private Point3D m_Start;
private Point3D m_End;
public Rectangle3D(Point3D start, Point3D end)
{
m_Start = start;
m_End = end;
}
public Rectangle3D(int x, int y, int z, int width, int height, int depth)
{
m_Start = new Point3D(x, y, z);
m_End = new Point3D(x + width, y + height, z + depth);
}
[CommandProperty(AccessLevel.Counselor)]
public Point3D Start
{
get => m_Start;
set => m_Start = value;
}
[CommandProperty(AccessLevel.Counselor)]
public Point3D End
{
get => m_End;
set => m_End = value;
}
[CommandProperty(AccessLevel.Counselor)]
public int X
{
get => m_Start.m_X;
set => m_Start.m_X = value;
}
[CommandProperty(AccessLevel.Counselor)]
public int Y
{
get => m_Start.m_Y;
set => m_Start.m_Y = value;
}
[CommandProperty(AccessLevel.Counselor)]
public int Z
{
get => m_Start.m_Z;
set => m_Start.m_Z = value;
}
[CommandProperty(AccessLevel.Counselor)]
public int Width => m_End.X - m_Start.X;
[CommandProperty(AccessLevel.Counselor)]
public int Height => m_End.Y - m_Start.Y;
[CommandProperty(AccessLevel.Counselor)]
public int Depth => m_End.Z - m_Start.Z;
public void MakeHold(Rectangle3D r)
{
if (r.m_Start.m_X < m_Start.m_X)
{
m_Start.m_X = r.m_Start.m_X;
}
if (r.m_Start.m_Y < m_Start.m_Y)
{
m_Start.m_Y = r.m_Start.m_Y;
}
if (r.m_Start.m_Z < m_Start.m_Z)
{
m_Start.m_Z = r.m_Start.m_Z;
}
if (r.m_End.m_X > m_End.m_X)
{
m_End.m_X = r.m_End.m_X;
}
if (r.m_End.m_Y > m_End.m_Y)
{
m_End.m_Y = r.m_End.m_Y;
}
if (r.m_End.m_Z < m_End.m_Z)
{
m_End.m_Z = r.m_End.m_Z;
}
}
public bool Contains(Point3D p) =>
p.m_X >= m_Start.m_X
&& p.m_X < m_End.m_X
&& p.m_Y >= m_Start.m_Y
&& p.m_Y < m_End.m_Y
&& p.m_Z >= m_Start.m_Z
&& p.m_Z < m_End.m_Z;
public bool Contains(Point2D p) =>
p.m_X >= m_Start.m_X
&& p.m_X < m_End.m_X
&& p.m_Y >= m_Start.m_Y
&& p.m_Y < m_End.m_Y;
public bool Contains(IPoint2D p) =>
p.X >= m_Start.m_X
&& p.X < m_End.m_X
&& p.Y >= m_Start.m_Y
&& p.Y < m_End.m_Y;
public bool Contains(IPoint3D p) =>
p.X >= m_Start.m_X
&& p.X < m_End.m_X
&& p.Y >= m_Start.m_Y
&& p.Y < m_End.m_Y
&& p.Z >= m_Start.m_Z
&& p.Z < m_End.m_Z;
m_Start = start;
m_End = end;
}
public Rectangle3D(int x, int y, int z, int width, int height, int depth)
{
m_Start = new Point3D(x, y, z);
m_End = new Point3D(x + width, y + height, z + depth);
}
[CommandProperty(AccessLevel.Counselor)]
public Point3D Start
{
get => m_Start;
set => m_Start = value;
}
[CommandProperty(AccessLevel.Counselor)]
public Point3D End
{
get => m_End;
set => m_End = value;
}
[CommandProperty(AccessLevel.Counselor)]
public int X
{
get => m_Start.m_X;
set => m_Start.m_X = value;
}
[CommandProperty(AccessLevel.Counselor)]
public int Y
{
get => m_Start.m_Y;
set => m_Start.m_Y = value;
}
[CommandProperty(AccessLevel.Counselor)]
public int Z
{
get => m_Start.m_Z;
set => m_Start.m_Z = value;
}
[CommandProperty(AccessLevel.Counselor)]
public int Width => m_End.X - m_Start.X;
[CommandProperty(AccessLevel.Counselor)]
public int Height => m_End.Y - m_Start.Y;
[CommandProperty(AccessLevel.Counselor)]
public int Depth => m_End.Z - m_Start.Z;
public void MakeHold(Rectangle3D r)
{
if (r.m_Start.m_X < m_Start.m_X)
{
m_Start.m_X = r.m_Start.m_X;
}
if (r.m_Start.m_Y < m_Start.m_Y)
{
m_Start.m_Y = r.m_Start.m_Y;
}
if (r.m_Start.m_Z < m_Start.m_Z)
{
m_Start.m_Z = r.m_Start.m_Z;
}
if (r.m_End.m_X > m_End.m_X)
{
m_End.m_X = r.m_End.m_X;
}
if (r.m_End.m_Y > m_End.m_Y)
{
m_End.m_Y = r.m_End.m_Y;
}
if (r.m_End.m_Z < m_End.m_Z)
{
m_End.m_Z = r.m_End.m_Z;
}
}
public bool Contains(Point3D p) =>
p.m_X >= m_Start.m_X
&& p.m_X < m_End.m_X
&& p.m_Y >= m_Start.m_Y
&& p.m_Y < m_End.m_Y
&& p.m_Z >= m_Start.m_Z
&& p.m_Z < m_End.m_Z;
public bool Contains(Point2D p) =>
p.m_X >= m_Start.m_X
&& p.m_X < m_End.m_X
&& p.m_Y >= m_Start.m_Y
&& p.m_Y < m_End.m_Y;
public bool Contains(IPoint2D p) =>
p.X >= m_Start.m_X
&& p.X < m_End.m_X
&& p.Y >= m_Start.m_Y
&& p.Y < m_End.m_Y;
public bool Contains(IPoint3D p) =>
p.X >= m_Start.m_X
&& p.X < m_End.m_X
&& p.Y >= m_Start.m_Y
&& p.Y < m_End.m_Y
&& p.Z >= m_Start.m_Z
&& p.Z < m_End.m_Z;
}

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: WorldLocation.cs *
* *
@ -16,153 +16,152 @@
using System;
using System.Collections.Generic;
namespace Server
namespace Server;
[Parsable]
public struct WorldLocation
: IPoint3D, IComparable<WorldLocation>, IEquatable<object>, IEquatable<WorldLocation>, IEquatable<IEntity>
{
[Parsable]
public struct WorldLocation
: IPoint3D, IComparable<WorldLocation>, IEquatable<object>, IEquatable<WorldLocation>, IEquatable<IEntity>
internal Point3D m_Loc;
internal Map m_Map;
public static readonly WorldLocation Zero = new(0, 0, 0, Map.Internal);
[CommandProperty(AccessLevel.Counselor)]
public Point3D Location
{
internal Point3D m_Loc;
internal Map m_Map;
get => m_Loc;
set => m_Loc = value;
}
public static readonly WorldLocation Zero = new(0, 0, 0, Map.Internal);
[CommandProperty(AccessLevel.Counselor)]
public int X
{
get => m_Loc.m_X;
set => m_Loc.m_X = value;
}
[CommandProperty(AccessLevel.Counselor)]
public Point3D Location
{
get => m_Loc;
set => m_Loc = value;
}
[CommandProperty(AccessLevel.Counselor)]
public int Y
{
get => m_Loc.m_Y;
set => m_Loc.m_Y = value;
}
[CommandProperty(AccessLevel.Counselor)]
public int X
{
get => m_Loc.m_X;
set => m_Loc.m_X = value;
}
[CommandProperty(AccessLevel.Counselor)]
public int Z
{
get => m_Loc.m_Z;
set => m_Loc.m_Z = value;
}
[CommandProperty(AccessLevel.Counselor)]
public int Y
{
get => m_Loc.m_Y;
set => m_Loc.m_Y = value;
}
[CommandProperty(AccessLevel.Counselor)]
public Map Map
{
get => m_Map;
set => m_Map = value;
}
[CommandProperty(AccessLevel.Counselor)]
public int Z
{
get => m_Loc.m_Z;
set => m_Loc.m_Z = value;
}
public WorldLocation(IEntity e) : this(e.Location.X, e.Location.Y, e.Location.Z, e.Map)
{
}
[CommandProperty(AccessLevel.Counselor)]
public Map Map
{
get => m_Map;
set => m_Map = value;
}
public WorldLocation(Point2D p, Map map) : this(p.X, p.Y, 0, map)
{
}
public WorldLocation(IEntity e) : this(e.Location.X, e.Location.Y, e.Location.Z, e.Map)
{
}
public WorldLocation(int x, int y, Map map) : this(x, y, 0, map)
{
}
public WorldLocation(Point2D p, Map map) : this(p.X, p.Y, 0, map)
{
}
public WorldLocation(Point3D p, Map map) : this(p.X, p.Y, p.Z, map)
{
}
public WorldLocation(int x, int y, Map map) : this(x, y, 0, map)
{
}
public WorldLocation(int x, int y, int z, Map map)
{
m_Loc.m_X = x;
m_Loc.m_Y = y;
m_Loc.m_Z = z;
m_Map = map;
}
public WorldLocation(Point3D p, Map map) : this(p.X, p.Y, p.Z, map)
{
}
public override string ToString() =>
$"({m_Loc.m_X}, {m_Loc.m_Y}, {m_Loc.m_Z}, {m_Map?.ToString() ?? "(-null-)"})";
public WorldLocation(int x, int y, int z, Map map)
{
m_Loc.m_X = x;
m_Loc.m_Y = y;
m_Loc.m_Z = z;
m_Map = map;
}
public bool Equals(WorldLocation other) =>
m_Loc.Equals(other.m_Loc) && m_Map.MapID == other.m_Map.MapID;
public override string ToString() =>
$"({m_Loc.m_X}, {m_Loc.m_Y}, {m_Loc.m_Z}, {m_Map?.ToString() ?? "(-null-)"})";
public bool Equals(IEntity other) =>
!ReferenceEquals(other, null) && m_Loc == other.Location &&
m_Map.MapID == other.Map.MapID;
public bool Equals(WorldLocation other) =>
m_Loc.Equals(other.m_Loc) && m_Map.MapID == other.m_Map.MapID;
public override bool Equals(object obj) =>
obj is WorldLocation other && Equals(other);
public bool Equals(IEntity other) =>
!ReferenceEquals(other, null) && m_Loc == other.Location &&
m_Map.MapID == other.Map.MapID;
public override int GetHashCode() => HashCode.Combine(m_Loc, m_Map);
public override bool Equals(object obj) =>
obj is WorldLocation other && Equals(other);
public int CompareTo(WorldLocation other)
{
var locComparison = m_Loc.CompareTo(other.m_Loc);
return locComparison != 0 ? locComparison : Comparer<Map>.Default.Compare(m_Map, other.m_Map);
}
public override int GetHashCode() => HashCode.Combine(m_Loc, m_Map);
public static implicit operator Point3D(WorldLocation worldLocation) => worldLocation.Location;
public int CompareTo(WorldLocation other)
{
var locComparison = m_Loc.CompareTo(other.m_Loc);
return locComparison != 0 ? locComparison : Comparer<Map>.Default.Compare(m_Map, other.m_Map);
}
public static bool operator ==(WorldLocation l, WorldLocation r) =>
l.m_Loc == r.m_Loc && l.m_Map == r.m_Map;
public static implicit operator Point3D(WorldLocation worldLocation) => worldLocation.Location;
public static bool operator ==(WorldLocation l, IEntity r) =>
!ReferenceEquals(r, null) && l.m_Loc == r.Location && l.m_Map == r.Map;
public static bool operator ==(WorldLocation l, WorldLocation r) =>
l.m_Loc == r.m_Loc && l.m_Map == r.m_Map;
public static bool operator !=(WorldLocation l, WorldLocation r) => l.m_Loc != r.m_Loc && l.m_Map != r.m_Map;
public static bool operator ==(WorldLocation l, IEntity r) =>
!ReferenceEquals(r, null) && l.m_Loc == r.Location && l.m_Map == r.Map;
public static bool operator !=(WorldLocation l, IEntity r) =>
!ReferenceEquals(r, null) && l.m_Loc != r.Location && l.m_Map != r.Map;
public static bool operator !=(WorldLocation l, WorldLocation r) => l.m_Loc != r.m_Loc && l.m_Map != r.m_Map;
public static bool operator >(WorldLocation l, WorldLocation r) => l.m_Loc > r.m_Loc && l.m_Map == r.m_Map;
public static bool operator !=(WorldLocation l, IEntity r) =>
!ReferenceEquals(r, null) && l.m_Loc != r.Location && l.m_Map != r.Map;
public static bool operator >(WorldLocation l, IEntity r) =>
!ReferenceEquals(r, null) && l.m_Loc > r.Location && l.m_Map == r.Map;
public static bool operator >(WorldLocation l, WorldLocation r) => l.m_Loc > r.m_Loc && l.m_Map == r.m_Map;
public static bool operator <(WorldLocation l, WorldLocation r) => l.m_Loc < r.m_Loc && l.m_Map == r.m_Map;
public static bool operator >(WorldLocation l, IEntity r) =>
!ReferenceEquals(r, null) && l.m_Loc > r.Location && l.m_Map == r.Map;
public static bool operator <(WorldLocation l, IEntity r) =>
!ReferenceEquals(r, null) && l.m_Loc < r.Location && l.m_Map == r.Map;
public static bool operator <(WorldLocation l, WorldLocation r) => l.m_Loc < r.m_Loc && l.m_Map == r.m_Map;
public static bool operator >=(WorldLocation l, WorldLocation r) => l.m_Loc >= r.m_Loc && l.m_Map == r.m_Map;
public static bool operator <(WorldLocation l, IEntity r) =>
!ReferenceEquals(r, null) && l.m_Loc < r.Location && l.m_Map == r.Map;
public static bool operator >=(WorldLocation l, IEntity r) =>
!ReferenceEquals(r, null) && l.m_Loc >= r.Location && l.m_Map == r.Map;
public static bool operator >=(WorldLocation l, WorldLocation r) => l.m_Loc >= r.m_Loc && l.m_Map == r.m_Map;
public static bool operator <=(WorldLocation l, WorldLocation r) => l.m_Loc <= r.m_Loc && l.m_Map == r.m_Map;
public static bool operator >=(WorldLocation l, IEntity r) =>
!ReferenceEquals(r, null) && l.m_Loc >= r.Location && l.m_Map == r.Map;
public static bool operator <=(WorldLocation l, IEntity r) =>
!ReferenceEquals(r, null) && l.m_Loc <= r.Location && l.m_Map == r.Map;
public static bool operator <=(WorldLocation l, WorldLocation r) => l.m_Loc <= r.m_Loc && l.m_Map == r.m_Map;
public static WorldLocation Parse(string value)
{
var start = value.IndexOfOrdinal('(');
var end = value.IndexOf(',', start + 1);
public static bool operator <=(WorldLocation l, IEntity r) =>
!ReferenceEquals(r, null) && l.m_Loc <= r.Location && l.m_Map == r.Map;
Utility.ToInt32(value.AsSpan(start + 1, end - (start + 1)).Trim(), out var x);
public static WorldLocation Parse(string value)
{
var start = value.IndexOfOrdinal('(');
var end = value.IndexOf(',', start + 1);
start = end;
end = value.IndexOf(',', start + 1);
Utility.ToInt32(value.AsSpan(start + 1, end - (start + 1)).Trim(), out var x);
Utility.ToInt32(value.AsSpan(start + 1, end - (start + 1)).Trim(), out var y);
start = end;
end = value.IndexOf(',', start + 1);
start = end;
end = value.IndexOf(',', start + 1);
Utility.ToInt32(value.AsSpan(start + 1, end - (start + 1)).Trim(), out var y);
Utility.ToInt32(value.AsSpan(start + 1, end - (start + 1)).Trim(), out var z);
start = end;
end = value.IndexOf(',', start + 1);
start = end;
end = value.IndexOf(')', start + 1);
Utility.ToInt32(value.AsSpan(start + 1, end - (start + 1)).Trim(), out var z);
var map = Map.Parse(value.AsSpan(start + 1, end - (start + 1)).Trim());
start = end;
end = value.IndexOf(')', start + 1);
var map = Map.Parse(value.AsSpan(start + 1, end - (start + 1)).Trim());
return new WorldLocation(x, y, z, map);
}
return new WorldLocation(x, y, z, map);
}
}

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright (C) 2019-2021 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: Guild.cs *
* *
@ -16,125 +16,124 @@
using System;
using System.Collections.Generic;
namespace Server.Guilds
namespace Server.Guilds;
public enum GuildType
{
public enum GuildType
{
Regular,
Chaos,
Order
}
public abstract class BaseGuild : ISerializable
{
protected BaseGuild()
{
Serial = World.NewGuild;
World.AddGuild(this);
SetTypeRef(GetType());
}
protected BaseGuild(Serial serial)
{
Serial = serial;
SetTypeRef(GetType());
}
public void SetTypeRef(Type type)
{
TypeRef = World.GuildTypes.IndexOf(type);
if (TypeRef == -1)
{
World.GuildTypes.Add(type);
TypeRef = World.GuildTypes.Count - 1;
}
}
public abstract string Abbreviation { get; set; }
public abstract string Name { get; set; }
public abstract GuildType Type { get; set; }
public abstract bool Disbanded { get; }
public abstract void Delete();
public bool Deleted => Disbanded;
[CommandProperty(AccessLevel.Counselor)]
public Serial Serial { get; }
[CommandProperty(AccessLevel.GameMaster, readOnly: true)]
public DateTime Created { get; set; } = Core.Now;
[CommandProperty(AccessLevel.GameMaster)]
DateTime ISerializable.LastSerialized { get; set; } = Core.Now;
long ISerializable.SavePosition { get; set; } = -1;
BufferWriter ISerializable.SaveBuffer { get; set; }
public int TypeRef { get; private set; }
public abstract void BeforeSerialize();
public abstract void Serialize(IGenericWriter writer);
public abstract void Deserialize(IGenericReader reader);
public abstract void OnDelete(Mobile mob);
public static BaseGuild FindByName(string name)
{
foreach (var g in World.Guilds.Values)
{
if (g.Name == name)
{
return g;
}
}
return null;
}
public static BaseGuild FindByAbbrev(string abbr)
{
foreach (var g in World.Guilds.Values)
{
if (g.Abbreviation == abbr)
{
return g;
}
}
return null;
}
public static HashSet<BaseGuild> Search(string find)
{
var words = find.ToLower().Split(' ');
var results = new HashSet<BaseGuild>();
foreach (var g in World.Guilds.Values)
{
var name = g.Name;
bool all = true;
foreach (var t in words)
{
if (name.InsensitiveIndexOf(t) == -1)
{
all = false;
break;
}
}
if (all)
{
results.Add(g);
}
}
return results;
}
public override string ToString() => $"{Serial} \"{Name} [{Abbreviation}]\"";
}
Regular,
Chaos,
Order
}
public abstract class BaseGuild : ISerializable
{
protected BaseGuild()
{
Serial = World.NewGuild;
World.AddGuild(this);
SetTypeRef(GetType());
}
protected BaseGuild(Serial serial)
{
Serial = serial;
SetTypeRef(GetType());
}
public void SetTypeRef(Type type)
{
TypeRef = World.GuildTypes.IndexOf(type);
if (TypeRef == -1)
{
World.GuildTypes.Add(type);
TypeRef = World.GuildTypes.Count - 1;
}
}
public abstract string Abbreviation { get; set; }
public abstract string Name { get; set; }
public abstract GuildType Type { get; set; }
public abstract bool Disbanded { get; }
public abstract void Delete();
public bool Deleted => Disbanded;
[CommandProperty(AccessLevel.Counselor)]
public Serial Serial { get; }
[CommandProperty(AccessLevel.GameMaster, readOnly: true)]
public DateTime Created { get; set; } = Core.Now;
[CommandProperty(AccessLevel.GameMaster)]
DateTime ISerializable.LastSerialized { get; set; } = Core.Now;
long ISerializable.SavePosition { get; set; } = -1;
BufferWriter ISerializable.SaveBuffer { get; set; }
public int TypeRef { get; private set; }
public abstract void BeforeSerialize();
public abstract void Serialize(IGenericWriter writer);
public abstract void Deserialize(IGenericReader reader);
public abstract void OnDelete(Mobile mob);
public static BaseGuild FindByName(string name)
{
foreach (var g in World.Guilds.Values)
{
if (g.Name == name)
{
return g;
}
}
return null;
}
public static BaseGuild FindByAbbrev(string abbr)
{
foreach (var g in World.Guilds.Values)
{
if (g.Abbreviation == abbr)
{
return g;
}
}
return null;
}
public static HashSet<BaseGuild> Search(string find)
{
var words = find.ToLower().Split(' ');
var results = new HashSet<BaseGuild>();
foreach (var g in World.Guilds.Values)
{
var name = g.Name;
bool all = true;
foreach (var t in words)
{
if (name.InsensitiveIndexOf(t) == -1)
{
all = false;
break;
}
}
if (all)
{
results.Add(g);
}
}
return results;
}
public override string ToString() => $"{Serial} \"{Name} [{Abbreviation}]\"";
}

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: GumpECHandleInput.cs *
* *

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: GumpMasterGump.cs *
* *

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: GumpSpriteImage.cs *
* *

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: GumpTooltip.cs *
* *

View file

@ -1,33 +1,32 @@
using Server.Network;
namespace Server.HuePickers
namespace Server.HuePickers;
public class HuePicker
{
public class HuePicker
private static Serial _nextSerial = (Serial)1;
public HuePicker(int itemID)
{
private static Serial _nextSerial = (Serial)1;
public HuePicker(int itemID)
do
{
do
{
Serial = _nextSerial++;
} while (Serial == 0);
Serial = _nextSerial++;
} while (Serial == 0);
ItemID = itemID;
}
ItemID = itemID;
}
public Serial Serial { get; }
public Serial Serial { get; }
public int ItemID { get; }
public int ItemID { get; }
public virtual void OnResponse(int hue)
{
}
public virtual void OnResponse(int hue)
{
}
public void SendTo(NetState state)
{
state.SendDisplayHuePicker(Serial, ItemID);
state.AddHuePicker(this);
}
public void SendTo(NetState state)
{
state.SendDisplayHuePicker(Serial, ItemID);
state.AddHuePicker(this);
}
}

View file

@ -1,113 +1,112 @@
using System;
namespace Server.Accounting
namespace Server.Accounting;
public static class AccountGold
{
public static class AccountGold
public static bool Enabled { get; private set; }
/// <summary>
/// This amount specifies the value at which point Gold turns to Platinum.
/// By default, when 1,000,000,000 Gold is accumulated, it will transform
/// into 1 Platinum.
/// !!! WARNING !!!
/// The client is designed to perceive the currency threshold at 1,000,000,000
/// if you change this, it may cause unexpected results when using secure trading.
/// </summary>
public static int CurrencyThreshold = 1000000000;
/// <summary>
/// Enables or Disables automatic conversion of Gold and Checks to Bank Currency
/// when they are added to a bank box container.
/// </summary>
public static bool ConvertOnBank { get; private set; }
/// <summary>
/// Enables or Disables automatic conversion of Gold and Checks to Bank Currency
/// when they are added to a secure trade container.
/// </summary>
public static bool ConvertOnTrade { get; private set; }
public static void Configure()
{
public static bool Enabled { get; private set; }
/// <summary>
/// This amount specifies the value at which point Gold turns to Platinum.
/// By default, when 1,000,000,000 Gold is accumulated, it will transform
/// into 1 Platinum.
/// !!! WARNING !!!
/// The client is designed to perceive the currency threshold at 1,000,000,000
/// if you change this, it may cause unexpected results when using secure trading.
/// </summary>
public static int CurrencyThreshold = 1000000000;
/// <summary>
/// Enables or Disables automatic conversion of Gold and Checks to Bank Currency
/// when they are added to a bank box container.
/// </summary>
public static bool ConvertOnBank { get; private set; }
/// <summary>
/// Enables or Disables automatic conversion of Gold and Checks to Bank Currency
/// when they are added to a secure trade container.
/// </summary>
public static bool ConvertOnTrade { get; private set; }
public static void Configure()
{
Enabled = ServerConfiguration.GetSetting("accountGold.enable", Core.TOL);
ConvertOnBank = ServerConfiguration.GetSetting("accountGold.convertOnBank", true);
ConvertOnTrade = ServerConfiguration.GetSetting("accountGold.convertOnTrade", false);
}
}
public interface IGoldAccount
{
/// <summary>
/// This amount represents the current amount of Gold owned by the player.
/// The value does not include the value of Platinum and ranges from
/// 0 to 999,999,999 by default.
/// </summary>
[CommandProperty(AccessLevel.Administrator)]
int TotalGold { get; }
/// <summary>
/// This amount represents the current amount of Platinum owned by the player.
/// The value does not include the value of Gold and ranges from
/// 0 to 2,147,483,647 by default.
/// One Platinum represents the value of CurrencyThreshold in Gold.
/// </summary>
[CommandProperty(AccessLevel.Administrator)]
int TotalPlat { get; }
/// <summary>
/// Attempts to deposit the given amount of Gold into this account.
/// If the given amount is greater than the CurrencyThreshold,
/// Platinum will be deposited to offset the difference.
/// </summary>
/// <param name="amount">Amount to deposit.</param>
/// <returns>True if successful, false if amount given is less than or equal to zero.</returns>
bool DepositGold(int amount);
/// <summary>
/// Attempts to deposit the given amount of Platinum into this account.
/// </summary>
/// <param name="amount">Amount to deposit.</param>
/// <returns>True if successful, false if amount given is less than or equal to zero.</returns>
bool DepositPlat(int amount);
/// <summary>
/// Attempts to withdraw the given amount of Gold from this account.
/// If the given amount is greater than the CurrencyThreshold,
/// Platinum will be withdrawn to offset the difference.
/// </summary>
/// <param name="amount">Amount to withdraw.</param>
/// <returns>True if successful, false if balance was too low.</returns>
bool WithdrawGold(int amount);
/// <summary>
/// Attempts to withdraw the given amount of Platinum from this account.
/// </summary>
/// <param name="amount">Amount to withdraw.</param>
/// <returns>True if successful, false if balance was too low.</returns>
bool WithdrawPlat(int amount);
/// <summary>
/// Returns total gold inclusive of platinum, capped to Int32.
/// This is strictly for backwards compatibility
/// </summary>
/// <returns>Total gold, capped at Int32.MaxValue</returns>
long GetTotalGold();
}
public interface IAccount : IGoldAccount, IComparable<IAccount>
{
string Username { get; set; }
string Email { get; set; }
AccessLevel AccessLevel { get; set; }
int Length { get; }
int Limit { get; }
int Count { get; }
Mobile this[int index] { get; set; }
void Delete();
void SetPassword(string password);
bool CheckPassword(string password);
Enabled = ServerConfiguration.GetSetting("accountGold.enable", Core.TOL);
ConvertOnBank = ServerConfiguration.GetSetting("accountGold.convertOnBank", true);
ConvertOnTrade = ServerConfiguration.GetSetting("accountGold.convertOnTrade", false);
}
}
public interface IGoldAccount
{
/// <summary>
/// This amount represents the current amount of Gold owned by the player.
/// The value does not include the value of Platinum and ranges from
/// 0 to 999,999,999 by default.
/// </summary>
[CommandProperty(AccessLevel.Administrator)]
int TotalGold { get; }
/// <summary>
/// This amount represents the current amount of Platinum owned by the player.
/// The value does not include the value of Gold and ranges from
/// 0 to 2,147,483,647 by default.
/// One Platinum represents the value of CurrencyThreshold in Gold.
/// </summary>
[CommandProperty(AccessLevel.Administrator)]
int TotalPlat { get; }
/// <summary>
/// Attempts to deposit the given amount of Gold into this account.
/// If the given amount is greater than the CurrencyThreshold,
/// Platinum will be deposited to offset the difference.
/// </summary>
/// <param name="amount">Amount to deposit.</param>
/// <returns>True if successful, false if amount given is less than or equal to zero.</returns>
bool DepositGold(int amount);
/// <summary>
/// Attempts to deposit the given amount of Platinum into this account.
/// </summary>
/// <param name="amount">Amount to deposit.</param>
/// <returns>True if successful, false if amount given is less than or equal to zero.</returns>
bool DepositPlat(int amount);
/// <summary>
/// Attempts to withdraw the given amount of Gold from this account.
/// If the given amount is greater than the CurrencyThreshold,
/// Platinum will be withdrawn to offset the difference.
/// </summary>
/// <param name="amount">Amount to withdraw.</param>
/// <returns>True if successful, false if balance was too low.</returns>
bool WithdrawGold(int amount);
/// <summary>
/// Attempts to withdraw the given amount of Platinum from this account.
/// </summary>
/// <param name="amount">Amount to withdraw.</param>
/// <returns>True if successful, false if balance was too low.</returns>
bool WithdrawPlat(int amount);
/// <summary>
/// Returns total gold inclusive of platinum, capped to Int32.
/// This is strictly for backwards compatibility
/// </summary>
/// <returns>Total gold, capped at Int32.MaxValue</returns>
long GetTotalGold();
}
public interface IAccount : IGoldAccount, IComparable<IAccount>
{
string Username { get; set; }
string Email { get; set; }
AccessLevel AccessLevel { get; set; }
int Length { get; }
int Limit { get; }
int Count { get; }
Mobile this[int index] { get; set; }
void Delete();
void SetPassword(string password);
bool CheckPassword(string password);
}

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: IEntity.cs *
* *
@ -15,110 +15,109 @@
using System;
namespace Server
namespace Server;
public interface IEntity : IPoint3D, ISerializable
{
public interface IEntity : IPoint3D, ISerializable
Point3D Location { get; }
Map Map { get; }
void MoveToWorld(Point3D location, Map map);
void ProcessDelta();
bool InRange(Point2D p, int range);
bool InRange(Point3D p, int range);
void RemoveItem(Item item);
}
public class Entity : IEntity
{
public Entity(Serial serial, Point3D loc, Map map) : this(serial)
{
Point3D Location { get; }
Map Map { get; }
void MoveToWorld(Point3D location, Map map);
void ProcessDelta();
bool InRange(Point2D p, int range);
bool InRange(Point3D p, int range);
void RemoveItem(Item item);
Location = loc;
Map = map;
Deleted = false;
}
public class Entity : IEntity
public Entity(Serial serial) => Serial = serial;
public void SetTypeRef(Type type)
{
public Entity(Serial serial, Point3D loc, Map map) : this(serial)
{
Location = loc;
Map = map;
Deleted = false;
}
}
public Entity(Serial serial) => Serial = serial;
DateTime ISerializable.Created { get; set; } = Core.Now;
public void SetTypeRef(Type type)
{
}
DateTime ISerializable.LastSerialized { get; set; } = DateTime.MaxValue;
DateTime ISerializable.Created { get; set; } = Core.Now;
long ISerializable.SavePosition { get; set; } = -1;
DateTime ISerializable.LastSerialized { get; set; } = DateTime.MaxValue;
BufferWriter ISerializable.SaveBuffer { get; set; }
long ISerializable.SavePosition { get; set; } = -1;
public int TypeRef => -1;
BufferWriter ISerializable.SaveBuffer { get; set; }
public Serial Serial { get; }
public int TypeRef => -1;
public Point3D Location { get; private set; }
public Serial Serial { get; }
public int X => Location.X;
public Point3D Location { get; private set; }
public int Y => Location.Y;
public int X => Location.X;
public int Z => Location.Z;
public int Y => Location.Y;
public Map Map { get; private set; }
public int Z => Location.Z;
public void MoveToWorld(Point3D newLocation, Map map)
{
Location = newLocation;
Map = map;
}
public Map Map { get; private set; }
public bool Deleted { get; }
public void MoveToWorld(Point3D newLocation, Map map)
{
Location = newLocation;
Map = map;
}
public void Delete()
{
}
public bool Deleted { get; }
public void ProcessDelta()
{
}
public void Delete()
{
}
public void RemoveItem(Item item)
{
}
public void ProcessDelta()
{
}
public bool InRange(Point2D p, int range) =>
p.m_X >= Location.m_X - range
&& p.m_X <= Location.m_X + range
&& p.m_Y >= Location.m_Y - range
&& p.m_Y <= Location.m_Y + range;
public void RemoveItem(Item item)
{
}
public bool InRange(Point3D p, int range) =>
p.m_X >= Location.m_X - range
&& p.m_X <= Location.m_X + range
&& p.m_Y >= Location.m_Y - range
&& p.m_Y <= Location.m_Y + range;
public bool InRange(Point2D p, int range) =>
p.m_X >= Location.m_X - range
&& p.m_X <= Location.m_X + range
&& p.m_Y >= Location.m_Y - range
&& p.m_Y <= Location.m_Y + range;
public bool InRange(IPoint2D p, int range) =>
p.X >= Location.m_X - range
&& p.X <= Location.m_X + range
&& p.Y >= Location.m_Y - range
&& p.Y <= Location.m_Y + range;
public bool InRange(Point3D p, int range) =>
p.m_X >= Location.m_X - range
&& p.m_X <= Location.m_X + range
&& p.m_Y >= Location.m_Y - range
&& p.m_Y <= Location.m_Y + range;
public void BeforeSerialize()
{
}
public bool InRange(IPoint2D p, int range) =>
p.X >= Location.m_X - range
&& p.X <= Location.m_X + range
&& p.Y >= Location.m_Y - range
&& p.Y <= Location.m_Y + range;
public void Deserialize(IGenericReader reader)
{
// Should not actually be saved
Timer.StartTimer(Delete);
}
public void BeforeSerialize()
{
}
public void Deserialize(IGenericReader reader)
{
// Should not actually be saved
Timer.StartTimer(Delete);
}
public void Serialize(IGenericWriter writer)
{
}
public void Serialize(IGenericWriter writer)
{
}
}

View file

@ -1,75 +1,74 @@
using System;
namespace Server
namespace Server;
public interface IPoint2D
{
public interface IPoint2D
{
int X { get; }
int Y { get; }
}
public interface IPoint3D : IPoint2D
{
int Z { get; }
}
public interface ICarvable
{
void Carve(Mobile from, Item item);
}
public interface IWeapon
{
int MaxRange { get; }
void OnBeforeSwing(Mobile attacker, Mobile defender);
TimeSpan OnSwing(Mobile attacker, Mobile defender, double damageBonus = 1.0);
void GetStatusDamage(Mobile from, out int min, out int max);
}
public interface IHued
{
int HuedItemID { get; }
}
public interface ISpell
{
bool IsCasting { get; }
void OnCasterHurt();
void OnCasterKilled();
void OnConnectionChanged();
bool OnCasterMoving(Direction d);
bool OnCasterEquipping(Item item);
bool OnCasterUsingObject(IEntity entity);
bool OnCastInTown(Region r);
void FinishSequence();
}
public interface IParty
{
void OnStamChanged(Mobile m);
void OnManaChanged(Mobile m);
void OnStatsQuery(Mobile beholder, Mobile beheld);
}
// TODO: Add SpawnMap and change Spawner.Map to use it
public interface ISpawner : IEntity
{
Guid Guid { get; }
bool UnlinkOnTaming { get; }
Point3D HomeLocation { get; }
int HomeRange { get; }
Region Region { get; }
bool ReturnOnDeactivate { get; }
void Remove(ISpawnable spawn);
Point3D GetSpawnPosition(ISpawnable spawned, Map map);
void Respawn();
}
public interface ISpawnable : IEntity
{
ISpawner Spawner { get; set; }
void OnBeforeSpawn(Point3D location, Map map);
void OnAfterSpawn();
}
int X { get; }
int Y { get; }
}
public interface IPoint3D : IPoint2D
{
int Z { get; }
}
public interface ICarvable
{
void Carve(Mobile from, Item item);
}
public interface IWeapon
{
int MaxRange { get; }
void OnBeforeSwing(Mobile attacker, Mobile defender);
TimeSpan OnSwing(Mobile attacker, Mobile defender, double damageBonus = 1.0);
void GetStatusDamage(Mobile from, out int min, out int max);
}
public interface IHued
{
int HuedItemID { get; }
}
public interface ISpell
{
bool IsCasting { get; }
void OnCasterHurt();
void OnCasterKilled();
void OnConnectionChanged();
bool OnCasterMoving(Direction d);
bool OnCasterEquipping(Item item);
bool OnCasterUsingObject(IEntity entity);
bool OnCastInTown(Region r);
void FinishSequence();
}
public interface IParty
{
void OnStamChanged(Mobile m);
void OnManaChanged(Mobile m);
void OnStatsQuery(Mobile beholder, Mobile beheld);
}
// TODO: Add SpawnMap and change Spawner.Map to use it
public interface ISpawner : IEntity
{
Guid Guid { get; }
bool UnlinkOnTaming { get; }
Point3D HomeLocation { get; }
int HomeRange { get; }
Region Region { get; }
bool ReturnOnDeactivate { get; }
void Remove(ISpawnable spawn);
Point3D GetSpawnPosition(ISpawnable spawned, Map map);
void Respawn();
}
public interface ISpawnable : IEntity
{
ISpawner Spawner { get; set; }
void OnBeforeSpawn(Point3D location, Map map);
void OnAfterSpawn();
}

View file

@ -1,125 +1,124 @@
using System;
using System.Runtime.CompilerServices;
namespace Server.Items
namespace Server.Items;
public abstract class BaseMulti : Item
{
public abstract class BaseMulti : Item
public BaseMulti(int itemID) : base(itemID) => Movable = false;
public BaseMulti(Serial serial) : base(serial)
{
public BaseMulti(int itemID) : base(itemID) => Movable = false;
}
public BaseMulti(Serial serial) : base(serial)
[CommandProperty(AccessLevel.GameMaster)]
public override int ItemID
{
get => base.ItemID;
set
{
}
[CommandProperty(AccessLevel.GameMaster)]
public override int ItemID
{
get => base.ItemID;
set
if (base.ItemID != value)
{
if (base.ItemID != value)
{
var facet = Parent == null ? Map : null;
var facet = Parent == null ? Map : null;
facet?.OnLeave(this);
facet?.OnLeave(this);
base.ItemID = value;
base.ItemID = value;
facet?.OnEnter(this);
}
facet?.OnEnter(this);
}
}
}
public override int LabelNumber
{
get
{
var mcl = Components;
if (mcl.List.Length > 0)
{
int id = mcl.List[0].ItemId;
if (id < 0x4000)
{
return 1020000 + id;
}
return 1078872 + id;
}
return base.LabelNumber;
}
}
public virtual bool AllowsRelativeDrop => false;
public virtual MultiComponentList Components => MultiData.GetComponents(ItemID);
[Obsolete("Replace with calls to OnLeave and OnEnter surrounding component invalidation.", true)]
public virtual void RefreshComponents()
{
if (Parent == null)
{
var facet = Map;
if (facet != null)
{
facet.OnLeave(this);
facet.OnEnter(this);
}
}
}
public override int GetMaxUpdateRange() => 22;
public override int GetUpdateRange(Mobile m) => 22;
public virtual bool Contains(Point2D p) => Contains(p.m_X, p.m_Y);
public virtual bool Contains(Point3D p) => Contains(p.m_X, p.m_Y);
public virtual bool Contains(IPoint3D p) => Contains(p.X, p.Y);
public virtual bool Contains(int x, int y)
public override int LabelNumber
{
get
{
var mcl = Components;
x -= X + mcl.Min.m_X;
y -= Y + mcl.Min.m_Y;
return x >= 0
&& x < mcl.Width
&& y >= 0
&& y < mcl.Height
&& mcl.Tiles[x][y].Length > 0;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Contains(Mobile m) => m.Map == Map && Contains(m.X, m.Y);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Contains(Item item) => item.Map == Map && Contains(item.X, item.Y);
public override void Serialize(IGenericWriter writer)
{
base.Serialize(writer);
writer.Write(1); // version
}
public override void Deserialize(IGenericReader reader)
{
base.Deserialize(reader);
var version = reader.ReadInt();
if (version == 0)
if (mcl.List.Length > 0)
{
if (ItemID >= 0x4000)
int id = mcl.List[0].ItemId;
if (id < 0x4000)
{
ItemID -= 0x4000;
return 1020000 + id;
}
return 1078872 + id;
}
return base.LabelNumber;
}
}
public virtual bool AllowsRelativeDrop => false;
public virtual MultiComponentList Components => MultiData.GetComponents(ItemID);
[Obsolete("Replace with calls to OnLeave and OnEnter surrounding component invalidation.", true)]
public virtual void RefreshComponents()
{
if (Parent == null)
{
var facet = Map;
if (facet != null)
{
facet.OnLeave(this);
facet.OnEnter(this);
}
}
}
public override int GetMaxUpdateRange() => 22;
public override int GetUpdateRange(Mobile m) => 22;
public virtual bool Contains(Point2D p) => Contains(p.m_X, p.m_Y);
public virtual bool Contains(Point3D p) => Contains(p.m_X, p.m_Y);
public virtual bool Contains(IPoint3D p) => Contains(p.X, p.Y);
public virtual bool Contains(int x, int y)
{
var mcl = Components;
x -= X + mcl.Min.m_X;
y -= Y + mcl.Min.m_Y;
return x >= 0
&& x < mcl.Width
&& y >= 0
&& y < mcl.Height
&& mcl.Tiles[x][y].Length > 0;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Contains(Mobile m) => m.Map == Map && Contains(m.X, m.Y);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool Contains(Item item) => item.Map == Map && Contains(item.X, item.Y);
public override void Serialize(IGenericWriter writer)
{
base.Serialize(writer);
writer.Write(1); // version
}
public override void Deserialize(IGenericReader reader)
{
base.Deserialize(reader);
var version = reader.ReadInt();
if (version == 0)
{
if (ItemID >= 0x4000)
{
ItemID -= 0x4000;
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,126 +1,125 @@
using Server.Accounting;
using Server.Network;
namespace Server.Items
namespace Server.Items;
public class BankBox : Container
{
public class BankBox : Container
public BankBox(Serial serial) : base(serial)
{
public BankBox(Serial serial) : base(serial)
}
public BankBox(Mobile owner) : base(0xE7C)
{
Layer = Layer.Bank;
Movable = false;
Owner = owner;
}
public override int DefaultMaxWeight => 0;
public override bool IsVirtualItem => true;
public Mobile Owner { get; private set; }
public bool Opened { get; private set; }
public static bool SendDeleteOnClose { get; set; }
public void Open()
{
Opened = true;
if (Owner != null)
{
}
Owner.PrivateOverheadMessage(
MessageType.Regular,
0x3B2,
true,
$"Bank container has {TotalItems} items, {TotalWeight} stones",
Owner.NetState
);
public BankBox(Mobile owner) : base(0xE7C)
{
Layer = Layer.Bank;
Movable = false;
Owner = owner;
}
public override int DefaultMaxWeight => 0;
public override bool IsVirtualItem => true;
public Mobile Owner { get; private set; }
public bool Opened { get; private set; }
public static bool SendDeleteOnClose { get; set; }
public void Open()
{
Opened = true;
if (Owner != null)
{
Owner.PrivateOverheadMessage(
MessageType.Regular,
0x3B2,
true,
$"Bank container has {TotalItems} items, {TotalWeight} stones",
Owner.NetState
);
Owner.NetState?.SendEquipUpdate(this);
DisplayTo(Owner);
}
}
public override void Serialize(IGenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
writer.Write(Owner);
writer.Write(Opened);
}
public override void Deserialize(IGenericReader reader)
{
base.Deserialize(reader);
var version = reader.ReadInt();
switch (version)
{
case 0:
{
Owner = reader.ReadEntity<Mobile>();
Opened = reader.ReadBool();
if (Owner == null)
{
Delete();
}
break;
}
}
if (ItemID == 0xE41)
{
ItemID = 0xE7C;
}
}
public void Close()
{
Opened = false;
if (SendDeleteOnClose)
{
Owner?.NetState.SendRemoveEntity(Serial);
}
}
public override void OnSingleClick(Mobile from)
{
}
public override void OnDoubleClick(Mobile from)
{
}
public override DeathMoveResult OnParentDeath(Mobile parent) => DeathMoveResult.RemainEquipped;
public override bool IsAccessibleTo(Mobile check) =>
(check == Owner && Opened || check.AccessLevel >= AccessLevel.GameMaster) && base.IsAccessibleTo(check);
public override bool OnDragDrop(Mobile from, Item dropped) =>
(from == Owner && Opened || from.AccessLevel >= AccessLevel.GameMaster) && base.OnDragDrop(from, dropped);
public override bool OnDragDropInto(Mobile from, Item item, Point3D p) =>
(from == Owner && Opened || from.AccessLevel >= AccessLevel.GameMaster) &&
base.OnDragDropInto(from, item, p);
public override int GetTotal(TotalType type)
{
if (AccountGold.Enabled && Owner?.Account != null && type == TotalType.Gold)
{
return Owner.Account.TotalGold;
}
return base.GetTotal(type);
Owner.NetState?.SendEquipUpdate(this);
DisplayTo(Owner);
}
}
public override void Serialize(IGenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
writer.Write(Owner);
writer.Write(Opened);
}
public override void Deserialize(IGenericReader reader)
{
base.Deserialize(reader);
var version = reader.ReadInt();
switch (version)
{
case 0:
{
Owner = reader.ReadEntity<Mobile>();
Opened = reader.ReadBool();
if (Owner == null)
{
Delete();
}
break;
}
}
if (ItemID == 0xE41)
{
ItemID = 0xE7C;
}
}
public void Close()
{
Opened = false;
if (SendDeleteOnClose)
{
Owner?.NetState.SendRemoveEntity(Serial);
}
}
public override void OnSingleClick(Mobile from)
{
}
public override void OnDoubleClick(Mobile from)
{
}
public override DeathMoveResult OnParentDeath(Mobile parent) => DeathMoveResult.RemainEquipped;
public override bool IsAccessibleTo(Mobile check) =>
(check == Owner && Opened || check.AccessLevel >= AccessLevel.GameMaster) && base.IsAccessibleTo(check);
public override bool OnDragDrop(Mobile from, Item dropped) =>
(from == Owner && Opened || from.AccessLevel >= AccessLevel.GameMaster) && base.OnDragDrop(from, dropped);
public override bool OnDragDropInto(Mobile from, Item item, Point3D p) =>
(from == Owner && Opened || from.AccessLevel >= AccessLevel.GameMaster) &&
base.OnDragDropInto(from, item, p);
public override int GetTotal(TotalType type)
{
if (AccountGold.Enabled && Owner?.Account != null && type == TotalType.Gold)
{
return Owner.Account.TotalGold;
}
return base.GetTotal(type);
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: Layer.cs *
* *
@ -13,176 +13,175 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
*************************************************************************/
namespace Server
namespace Server;
/// <summary>
/// Enumeration of item layer values.
/// </summary>
public enum Layer : byte
{
/// <summary>
/// Enumeration of item layer values.
/// Invalid layer.
/// </summary>
public enum Layer : byte
{
/// <summary>
/// Invalid layer.
/// </summary>
Invalid = 0x00,
Invalid = 0x00,
/// <summary>
/// First valid layer. Equivalent to <c>Layer.OneHanded</c>.
/// </summary>
FirstValid = 0x01,
/// <summary>
/// First valid layer. Equivalent to <c>Layer.OneHanded</c>.
/// </summary>
FirstValid = 0x01,
/// <summary>
/// One handed weapon.
/// </summary>
OneHanded = 0x01,
/// <summary>
/// One handed weapon.
/// </summary>
OneHanded = 0x01,
/// <summary>
/// Two handed weapon or shield.
/// </summary>
TwoHanded = 0x02,
/// <summary>
/// Two handed weapon or shield.
/// </summary>
TwoHanded = 0x02,
/// <summary>
/// Shoes.
/// </summary>
Shoes = 0x03,
/// <summary>
/// Shoes.
/// </summary>
Shoes = 0x03,
/// <summary>
/// Pants.
/// </summary>
Pants = 0x04,
/// <summary>
/// Pants.
/// </summary>
Pants = 0x04,
/// <summary>
/// Shirts.
/// </summary>
Shirt = 0x05,
/// <summary>
/// Shirts.
/// </summary>
Shirt = 0x05,
/// <summary>
/// Helmets, hats, and masks.
/// </summary>
Helm = 0x06,
/// <summary>
/// Helmets, hats, and masks.
/// </summary>
Helm = 0x06,
/// <summary>
/// Gloves.
/// </summary>
Gloves = 0x07,
/// <summary>
/// Gloves.
/// </summary>
Gloves = 0x07,
/// <summary>
/// Rings.
/// </summary>
Ring = 0x08,
/// <summary>
/// Rings.
/// </summary>
Ring = 0x08,
/// <summary>
/// Talismans.
/// </summary>
Talisman = 0x09,
/// <summary>
/// Talismans.
/// </summary>
Talisman = 0x09,
/// <summary>
/// Gorgets and necklaces.
/// </summary>
Neck = 0x0A,
/// <summary>
/// Gorgets and necklaces.
/// </summary>
Neck = 0x0A,
/// <summary>
/// Hair.
/// </summary>
Hair = 0x0B,
/// <summary>
/// Hair.
/// </summary>
Hair = 0x0B,
/// <summary>
/// Half aprons.
/// </summary>
Waist = 0x0C,
/// <summary>
/// Half aprons.
/// </summary>
Waist = 0x0C,
/// <summary>
/// Torso, inner layer.
/// </summary>
InnerTorso = 0x0D,
/// <summary>
/// Torso, inner layer.
/// </summary>
InnerTorso = 0x0D,
/// <summary>
/// Bracelets.
/// </summary>
Bracelet = 0x0E,
/// <summary>
/// Bracelets.
/// </summary>
Bracelet = 0x0E,
/// <summary>
/// Unused.
/// </summary>
Unused_xF = 0x0F,
/// <summary>
/// Unused.
/// </summary>
Unused_xF = 0x0F,
/// <summary>
/// Beards and mustaches.
/// </summary>
FacialHair = 0x10,
/// <summary>
/// Beards and mustaches.
/// </summary>
FacialHair = 0x10,
/// <summary>
/// Torso, outer layer.
/// </summary>
MiddleTorso = 0x11,
/// <summary>
/// Torso, outer layer.
/// </summary>
MiddleTorso = 0x11,
/// <summary>
/// Earings.
/// </summary>
Earrings = 0x12,
/// <summary>
/// Earings.
/// </summary>
Earrings = 0x12,
/// <summary>
/// Arms and sleeves.
/// </summary>
Arms = 0x13,
/// <summary>
/// Arms and sleeves.
/// </summary>
Arms = 0x13,
/// <summary>
/// Cloaks.
/// </summary>
Cloak = 0x14,
/// <summary>
/// Cloaks.
/// </summary>
Cloak = 0x14,
/// <summary>
/// Backpacks.
/// </summary>
Backpack = 0x15,
/// <summary>
/// Backpacks.
/// </summary>
Backpack = 0x15,
/// <summary>
/// Torso, outer layer.
/// </summary>
OuterTorso = 0x16,
/// <summary>
/// Torso, outer layer.
/// </summary>
OuterTorso = 0x16,
/// <summary>
/// Leggings, outer layer.
/// </summary>
OuterLegs = 0x17,
/// <summary>
/// Leggings, outer layer.
/// </summary>
OuterLegs = 0x17,
/// <summary>
/// Leggings, inner layer.
/// </summary>
InnerLegs = 0x18,
/// <summary>
/// Leggings, inner layer.
/// </summary>
InnerLegs = 0x18,
/// <summary>
/// Last valid non-internal layer. Equivalent to <c>Layer.InnerLegs</c>.
/// </summary>
LastUserValid = 0x18,
/// <summary>
/// Last valid non-internal layer. Equivalent to <c>Layer.InnerLegs</c>.
/// </summary>
LastUserValid = 0x18,
/// <summary>
/// Mount item layer.
/// </summary>
Mount = 0x19,
/// <summary>
/// Mount item layer.
/// </summary>
Mount = 0x19,
/// <summary>
/// Vendor 'buy pack' layer.
/// </summary>
ShopBuy = 0x1A,
/// <summary>
/// Vendor 'buy pack' layer.
/// </summary>
ShopBuy = 0x1A,
/// <summary>
/// Vendor 'resale pack' layer.
/// </summary>
ShopResale = 0x1B,
/// <summary>
/// Vendor 'resale pack' layer.
/// </summary>
ShopResale = 0x1B,
/// <summary>
/// Vendor 'sell pack' layer.
/// </summary>
ShopSell = 0x1C,
/// <summary>
/// Vendor 'sell pack' layer.
/// </summary>
ShopSell = 0x1C,
/// <summary>
/// Bank box layer.
/// </summary>
Bank = 0x1D,
/// <summary>
/// Bank box layer.
/// </summary>
Bank = 0x1D,
/// <summary>
/// Last valid layer. Equivalent to <c>Layer.Bank</c>.
/// </summary>
LastValid = 0x1D
}
/// <summary>
/// Last valid layer. Equivalent to <c>Layer.Bank</c>.
/// </summary>
LastValid = 0x1D
}

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: LightType.cs *
* *
@ -13,291 +13,290 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
*************************************************************************/
namespace Server
namespace Server;
public enum LightType
{
public enum LightType
{
/// <summary>
/// Window shape, arched, ray shining east.
/// </summary>
ArchedWindowEast,
/// <summary>
/// Window shape, arched, ray shining east.
/// </summary>
ArchedWindowEast,
/// <summary>
/// Medium circular shape.
/// </summary>
Circle225,
/// <summary>
/// Medium circular shape.
/// </summary>
Circle225,
/// <summary>
/// Small circular shape.
/// </summary>
Circle150,
/// <summary>
/// Small circular shape.
/// </summary>
Circle150,
/// <summary>
/// Door shape, shining south.
/// </summary>
DoorSouth,
/// <summary>
/// Door shape, shining south.
/// </summary>
DoorSouth,
/// <summary>
/// Door shape, shining east.
/// </summary>
DoorEast,
/// <summary>
/// Door shape, shining east.
/// </summary>
DoorEast,
/// <summary>
/// Large semicircular shape (180 degrees), north wall.
/// </summary>
NorthBig,
/// <summary>
/// Large semicircular shape (180 degrees), north wall.
/// </summary>
NorthBig,
/// <summary>
/// Large pie shape (90 degrees), north-east corner.
/// </summary>
NorthEastBig,
/// <summary>
/// Large pie shape (90 degrees), north-east corner.
/// </summary>
NorthEastBig,
/// <summary>
/// Large semicircular shape (180 degrees), east wall.
/// </summary>
EastBig,
/// <summary>
/// Large semicircular shape (180 degrees), east wall.
/// </summary>
EastBig,
/// <summary>
/// Large semicircular shape (180 degrees), west wall.
/// </summary>
WestBig,
/// <summary>
/// Large semicircular shape (180 degrees), west wall.
/// </summary>
WestBig,
/// <summary>
/// Large pie shape (90 degrees), south-west corner.
/// </summary>
SouthWestBig,
/// <summary>
/// Large pie shape (90 degrees), south-west corner.
/// </summary>
SouthWestBig,
/// <summary>
/// Large semicircular shape (180 degrees), south wall.
/// </summary>
SouthBig,
/// <summary>
/// Large semicircular shape (180 degrees), south wall.
/// </summary>
SouthBig,
/// <summary>
/// Medium semicircular shape (180 degrees), north wall.
/// </summary>
NorthSmall,
/// <summary>
/// Medium semicircular shape (180 degrees), north wall.
/// </summary>
NorthSmall,
/// <summary>
/// Medium pie shape (90 degrees), north-east corner.
/// </summary>
NorthEastSmall,
/// <summary>
/// Medium pie shape (90 degrees), north-east corner.
/// </summary>
NorthEastSmall,
/// <summary>
/// Medium semicircular shape (180 degrees), east wall.
/// </summary>
EastSmall,
/// <summary>
/// Medium semicircular shape (180 degrees), east wall.
/// </summary>
EastSmall,
/// <summary>
/// Medium semicircular shape (180 degrees), west wall.
/// </summary>
WestSmall,
/// <summary>
/// Medium semicircular shape (180 degrees), west wall.
/// </summary>
WestSmall,
/// <summary>
/// Medium semicircular shape (180 degrees), south wall.
/// </summary>
SouthSmall,
/// <summary>
/// Medium semicircular shape (180 degrees), south wall.
/// </summary>
SouthSmall,
/// <summary>
/// Shaped like a wall decoration, north wall.
/// </summary>
DecorationNorth,
/// <summary>
/// Shaped like a wall decoration, north wall.
/// </summary>
DecorationNorth,
/// <summary>
/// Shaped like a wall decoration, north-east corner.
/// </summary>
DecorationNorthEast,
/// <summary>
/// Shaped like a wall decoration, north-east corner.
/// </summary>
DecorationNorthEast,
/// <summary>
/// Small semicircular shape (180 degrees), east wall.
/// </summary>
EastTiny,
/// <summary>
/// Small semicircular shape (180 degrees), east wall.
/// </summary>
EastTiny,
/// <summary>
/// Shaped like a wall decoration, west wall.
/// </summary>
DecorationWest,
/// <summary>
/// Shaped like a wall decoration, west wall.
/// </summary>
DecorationWest,
/// <summary>
/// Shaped like a wall decoration, south-west corner.
/// </summary>
DecorationSouthWest,
/// <summary>
/// Shaped like a wall decoration, south-west corner.
/// </summary>
DecorationSouthWest,
/// <summary>
/// Small semicircular shape (180 degrees), south wall.
/// </summary>
SouthTiny,
/// <summary>
/// Small semicircular shape (180 degrees), south wall.
/// </summary>
SouthTiny,
/// <summary>
/// Window shape, rectangular, no ray, shining south.
/// </summary>
RectWindowSouthNoRay,
/// <summary>
/// Window shape, rectangular, no ray, shining south.
/// </summary>
RectWindowSouthNoRay,
/// <summary>
/// Window shape, rectangular, no ray, shining east.
/// </summary>
RectWindowEastNoRay,
/// <summary>
/// Window shape, rectangular, no ray, shining east.
/// </summary>
RectWindowEastNoRay,
/// <summary>
/// Window shape, rectangular, ray shining south.
/// </summary>
RectWindowSouth,
/// <summary>
/// Window shape, rectangular, ray shining south.
/// </summary>
RectWindowSouth,
/// <summary>
/// Window shape, rectangular, ray shining east.
/// </summary>
RectWindowEast,
/// <summary>
/// Window shape, rectangular, ray shining east.
/// </summary>
RectWindowEast,
/// <summary>
/// Window shape, arched, no ray, shining south.
/// </summary>
ArchedWindowSouthNoRay,
/// <summary>
/// Window shape, arched, no ray, shining south.
/// </summary>
ArchedWindowSouthNoRay,
/// <summary>
/// Window shape, arched, no ray, shining east.
/// </summary>
ArchedWindowEastNoRay,
/// <summary>
/// Window shape, arched, no ray, shining east.
/// </summary>
ArchedWindowEastNoRay,
/// <summary>
/// Window shape, arched, ray shining south.
/// </summary>
ArchedWindowSouth,
/// <summary>
/// Window shape, arched, ray shining south.
/// </summary>
ArchedWindowSouth,
/// <summary>
/// Large circular shape.
/// </summary>
Circle300,
/// <summary>
/// Large circular shape.
/// </summary>
Circle300,
/// <summary>
/// Large pie shape (90 degrees), north-west corner.
/// </summary>
NorthWestBig,
/// <summary>
/// Large pie shape (90 degrees), north-west corner.
/// </summary>
NorthWestBig,
/// <summary>
/// Negative light. Medium pie shape (90 degrees), south-east corner.
/// </summary>
DarkSouthEast,
/// <summary>
/// Negative light. Medium pie shape (90 degrees), south-east corner.
/// </summary>
DarkSouthEast,
/// <summary>
/// Negative light. Medium semicircular shape (180 degrees), south wall.
/// </summary>
DarkSouth,
/// <summary>
/// Negative light. Medium semicircular shape (180 degrees), south wall.
/// </summary>
DarkSouth,
/// <summary>
/// Negative light. Medium pie shape (90 degrees), north-west corner.
/// </summary>
DarkNorthWest,
/// <summary>
/// Negative light. Medium pie shape (90 degrees), north-west corner.
/// </summary>
DarkNorthWest,
/// <summary>
/// Negative light. Medium pie shape (90 degrees), south-east corner. Equivalent to <c>LightType.SouthEast</c>.
/// </summary>
DarkSouthEast2,
/// <summary>
/// Negative light. Medium pie shape (90 degrees), south-east corner. Equivalent to <c>LightType.SouthEast</c>.
/// </summary>
DarkSouthEast2,
/// <summary>
/// Negative light. Medium circular shape (180 degrees), east wall.
/// </summary>
DarkEast,
/// <summary>
/// Negative light. Medium circular shape (180 degrees), east wall.
/// </summary>
DarkEast,
/// <summary>
/// Negative light. Large circular shape.
/// </summary>
DarkCircle300,
/// <summary>
/// Negative light. Large circular shape.
/// </summary>
DarkCircle300,
/// <summary>
/// Opened door shape, shining south.
/// </summary>
DoorOpenSouth,
/// <summary>
/// Opened door shape, shining south.
/// </summary>
DoorOpenSouth,
/// <summary>
/// Opened door shape, shining east.
/// </summary>
DoorOpenEast,
/// <summary>
/// Opened door shape, shining east.
/// </summary>
DoorOpenEast,
/// <summary>
/// Window shape, square, ray shining east.
/// </summary>
SquareWindowEast,
/// <summary>
/// Window shape, square, ray shining east.
/// </summary>
SquareWindowEast,
/// <summary>
/// Window shape, square, no ray, shining east.
/// </summary>
SquareWindowEastNoRay,
/// <summary>
/// Window shape, square, no ray, shining east.
/// </summary>
SquareWindowEastNoRay,
/// <summary>
/// Window shape, square, ray shining south.
/// </summary>
SquareWindowSouth,
/// <summary>
/// Window shape, square, ray shining south.
/// </summary>
SquareWindowSouth,
/// <summary>
/// Window shape, square, no ray, shining south.
/// </summary>
SquareWindowSouthNoRay,
/// <summary>
/// Window shape, square, no ray, shining south.
/// </summary>
SquareWindowSouthNoRay,
/// <summary>
/// Empty.
/// </summary>
Empty,
/// <summary>
/// Empty.
/// </summary>
Empty,
/// <summary>
/// Window shape, skinny, no ray, shining south.
/// </summary>
SkinnyWindowSouthNoRay,
/// <summary>
/// Window shape, skinny, no ray, shining south.
/// </summary>
SkinnyWindowSouthNoRay,
/// <summary>
/// Window shape, skinny, ray shining east.
/// </summary>
SkinnyWindowEast,
/// <summary>
/// Window shape, skinny, ray shining east.
/// </summary>
SkinnyWindowEast,
/// <summary>
/// Window shape, skinny, no ray, shining east.
/// </summary>
SkinnyWindowEastNoRay,
/// <summary>
/// Window shape, skinny, no ray, shining east.
/// </summary>
SkinnyWindowEastNoRay,
/// <summary>
/// Shaped like a hole, shining south.
/// </summary>
HoleSouth,
/// <summary>
/// Shaped like a hole, shining south.
/// </summary>
HoleSouth,
/// <summary>
/// Shaped like a hole, shining south.
/// </summary>
HoleEast,
/// <summary>
/// Shaped like a hole, shining south.
/// </summary>
HoleEast,
/// <summary>
/// Large circular shape with a moongate graphic embedded.
/// </summary>
Moongate,
/// <summary>
/// Large circular shape with a moongate graphic embedded.
/// </summary>
Moongate,
/// <summary>
/// Unknown usage. Many rows of slightly angled lines.
/// </summary>
Strips,
/// <summary>
/// Unknown usage. Many rows of slightly angled lines.
/// </summary>
Strips,
/// <summary>
/// Shaped like a small hole, shining south.
/// </summary>
SmallHoleSouth,
/// <summary>
/// Shaped like a small hole, shining south.
/// </summary>
SmallHoleSouth,
/// <summary>
/// Shaped like a small hole, shining east.
/// </summary>
SmallHoleEast,
/// <summary>
/// Shaped like a small hole, shining east.
/// </summary>
SmallHoleEast,
/// <summary>
/// Large semicircular shape (180 degrees), north wall. Identical graphic as <c>LightType.NorthBig</c>, but slightly
/// different
/// positioning.
/// </summary>
NorthBig2,
/// <summary>
/// Large semicircular shape (180 degrees), north wall. Identical graphic as <c>LightType.NorthBig</c>, but slightly
/// different
/// positioning.
/// </summary>
NorthBig2,
/// <summary>
/// Large semicircular shape (180 degrees), west wall. Identical graphic as <c>LightType.WestBig</c>, but slightly different
/// positioning.
/// </summary>
WestBig2,
/// <summary>
/// Large semicircular shape (180 degrees), west wall. Identical graphic as <c>LightType.WestBig</c>, but slightly different
/// positioning.
/// </summary>
WestBig2,
/// <summary>
/// Large pie shape (90 degrees), north-west corner. Equivalent to <c>LightType.NorthWestBig</c>.
/// </summary>
NorthWestBig2
}
/// <summary>
/// Large pie shape (90 degrees), north-west corner. Equivalent to <c>LightType.NorthWestBig</c>.
/// </summary>
NorthWestBig2
}

View file

@ -1,113 +1,112 @@
using Server.Accounting;
using Server.Network;
namespace Server.Items
namespace Server.Items;
public class SecureTradeContainer : Container
{
public class SecureTradeContainer : Container
public SecureTradeContainer(SecureTrade trade) : base(0x1E5E)
{
public SecureTradeContainer(SecureTrade trade) : base(0x1E5E)
{
Trade = trade;
Trade = trade;
Movable = false;
Movable = false;
}
public SecureTradeContainer(Serial serial) : base(serial)
{
}
public SecureTrade Trade { get; }
public override bool CheckHold(Mobile m, Item item, bool message, bool checkItems, int plusItems, int plusWeight)
{
if (item == Trade.From.VirtualCheck || item == Trade.To.VirtualCheck)
{
return true;
}
public SecureTradeContainer(Serial serial) : base(serial)
var to = Trade.From.Container != this ? Trade.From.Mobile : Trade.To.Mobile;
return m.CheckTrade(to, item, this, message, checkItems, plusItems, plusWeight);
}
public override bool CheckLift(Mobile from, Item item, ref LRReason reject)
{
reject = LRReason.CannotLift;
return false;
}
public override bool IsAccessibleTo(Mobile check) =>
IsChildOf(check) && Trade?.Valid == true && base.IsAccessibleTo(check);
public override void OnItemAdded(Item item)
{
if (item is not VirtualCheck)
{
}
public SecureTrade Trade { get; }
public override bool CheckHold(Mobile m, Item item, bool message, bool checkItems, int plusItems, int plusWeight)
{
if (item == Trade.From.VirtualCheck || item == Trade.To.VirtualCheck)
{
return true;
}
var to = Trade.From.Container != this ? Trade.From.Mobile : Trade.To.Mobile;
return m.CheckTrade(to, item, this, message, checkItems, plusItems, plusWeight);
}
public override bool CheckLift(Mobile from, Item item, ref LRReason reject)
{
reject = LRReason.CannotLift;
return false;
}
public override bool IsAccessibleTo(Mobile check) =>
IsChildOf(check) && Trade?.Valid == true && base.IsAccessibleTo(check);
public override void OnItemAdded(Item item)
{
if (item is not VirtualCheck)
{
ClearChecks();
}
}
public override void OnItemRemoved(Item item)
{
if (item is not VirtualCheck)
{
ClearChecks();
}
}
public override void OnSubItemAdded(Item item)
{
if (item is not VirtualCheck)
{
ClearChecks();
}
}
public override void OnSubItemRemoved(Item item)
{
if (item is not VirtualCheck)
{
ClearChecks();
}
}
public void ClearChecks()
{
if (Trade == null)
{
return;
}
if (Trade.From?.IsDisposed == false)
{
Trade.From.Accepted = false;
}
if (Trade.To?.IsDisposed == false)
{
Trade.To.Accepted = false;
}
Trade.Update();
}
public override bool IsChildVisibleTo(Mobile m, Item child) =>
child is VirtualCheck
? AccountGold.Enabled && m.NetState is not { NewSecureTrading: true }
: base.IsChildVisibleTo(m, child);
public override void Serialize(IGenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
}
public override void Deserialize(IGenericReader reader)
{
base.Deserialize(reader);
var version = reader.ReadInt();
ClearChecks();
}
}
public override void OnItemRemoved(Item item)
{
if (item is not VirtualCheck)
{
ClearChecks();
}
}
public override void OnSubItemAdded(Item item)
{
if (item is not VirtualCheck)
{
ClearChecks();
}
}
public override void OnSubItemRemoved(Item item)
{
if (item is not VirtualCheck)
{
ClearChecks();
}
}
public void ClearChecks()
{
if (Trade == null)
{
return;
}
if (Trade.From?.IsDisposed == false)
{
Trade.From.Accepted = false;
}
if (Trade.To?.IsDisposed == false)
{
Trade.To.Accepted = false;
}
Trade.Update();
}
public override bool IsChildVisibleTo(Mobile m, Item child) =>
child is VirtualCheck
? AccountGold.Enabled && m.NetState is not { NewSecureTrading: true }
: base.IsChildVisibleTo(m, child);
public override void Serialize(IGenericWriter writer)
{
base.Serialize(writer);
writer.Write(0); // version
}
public override void Deserialize(IGenericReader reader)
{
base.Deserialize(reader);
var version = reader.ReadInt();
}
}

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: VirtualCheck.cs *
* *
@ -16,382 +16,381 @@
using Server.Gumps;
using Server.Network;
namespace Server.Items
namespace Server.Items;
public sealed class VirtualCheck : Item
{
public sealed class VirtualCheck : Item
public static bool UseEditGump { get; private set; }
public static void Configure()
{
public static bool UseEditGump { get; private set; }
UseEditGump = ServerConfiguration.GetSetting("virtualChecks.useEditGump", Core.TOL);
}
public static void Configure()
private int m_Gold;
private int m_Plat;
public VirtualCheck(int plat = 0, int gold = 0) : base(0x14F0)
{
Plat = plat;
Gold = gold;
Movable = false;
}
public VirtualCheck(Serial serial)
: base(serial)
{
}
public override bool IsVirtualItem => true;
public override bool DisplayWeight => false;
public override bool DisplayLootType => false;
public override double DefaultWeight => 0;
public override string DefaultName => "Offer Of Currency";
public EditGump Editor { get; private set; }
[CommandProperty(AccessLevel.Administrator)]
public int Plat
{
get => m_Plat;
set
{
UseEditGump = ServerConfiguration.GetSetting("virtualChecks.useEditGump", Core.TOL);
m_Plat = value;
InvalidateProperties();
}
}
[CommandProperty(AccessLevel.Administrator)]
public int Gold
{
get => m_Gold;
set
{
m_Gold = value;
InvalidateProperties();
}
}
public override bool IsAccessibleTo(Mobile check)
{
var c = GetSecureTradeCont();
if (check == null || c == null)
{
return base.IsAccessibleTo(check);
}
private int m_Gold;
return c.RootParent == check && IsChildOf(c);
}
private int m_Plat;
public VirtualCheck(int plat = 0, int gold = 0) : base(0x14F0)
public override void OnDoubleClickSecureTrade(Mobile from)
{
if (UseEditGump && IsAccessibleTo(from))
{
Plat = plat;
Gold = gold;
Movable = false;
}
public VirtualCheck(Serial serial)
: base(serial)
{
}
public override bool IsVirtualItem => true;
public override bool DisplayWeight => false;
public override bool DisplayLootType => false;
public override double DefaultWeight => 0;
public override string DefaultName => "Offer Of Currency";
public EditGump Editor { get; private set; }
[CommandProperty(AccessLevel.Administrator)]
public int Plat
{
get => m_Plat;
set
if (Editor?.Check?.Deleted != false)
{
m_Plat = value;
InvalidateProperties();
}
}
[CommandProperty(AccessLevel.Administrator)]
public int Gold
{
get => m_Gold;
set
{
m_Gold = value;
InvalidateProperties();
}
}
public override bool IsAccessibleTo(Mobile check)
{
var c = GetSecureTradeCont();
if (check == null || c == null)
{
return base.IsAccessibleTo(check);
}
return c.RootParent == check && IsChildOf(c);
}
public override void OnDoubleClickSecureTrade(Mobile from)
{
if (UseEditGump && IsAccessibleTo(from))
{
if (Editor?.Check?.Deleted != false)
{
Editor = new EditGump(from, this);
Editor.Send();
}
else
{
Editor.Refresh(true);
}
Editor = new EditGump(from, this);
Editor.Send();
}
else
{
if (Editor != null)
{
Editor.Close();
Editor = null;
}
base.OnDoubleClickSecureTrade(from);
Editor.Refresh(true);
}
}
public override void OnSingleClick(Mobile from)
else
{
LabelTo(from, "Offer: {0:#,0} platinum, {1:#,0} gold", Plat, Gold);
}
public override void GetProperties(IPropertyList list)
{
base.GetProperties(list);
list.Add(1060738, $"{Plat:#,0} platinum, {Gold:#,0} gold"); // value: ~1_val~
}
public void UpdateTrade(Mobile user)
{
var c = GetSecureTradeCont();
if (c?.Trade == null)
{
return;
}
if (user == c.Trade.From.Mobile)
{
c.Trade.UpdateFromCurrency();
}
else if (user == c.Trade.To.Mobile)
{
c.Trade.UpdateToCurrency();
}
c.ClearChecks();
}
public override void OnAfterDelete()
{
base.OnAfterDelete();
if (Editor != null)
{
Editor.Close();
Editor = null;
}
base.OnDoubleClickSecureTrade(from);
}
}
public override void OnSingleClick(Mobile from)
{
LabelTo(from, "Offer: {0:#,0} platinum, {1:#,0} gold", Plat, Gold);
}
public override void GetProperties(IPropertyList list)
{
base.GetProperties(list);
list.Add(1060738, $"{Plat:#,0} platinum, {Gold:#,0} gold"); // value: ~1_val~
}
public void UpdateTrade(Mobile user)
{
var c = GetSecureTradeCont();
if (c?.Trade == null)
{
return;
}
public override void Serialize(IGenericWriter writer)
if (user == c.Trade.From.Mobile)
{
c.Trade.UpdateFromCurrency();
}
else if (user == c.Trade.To.Mobile)
{
c.Trade.UpdateToCurrency();
}
public override void Deserialize(IGenericReader reader)
c.ClearChecks();
}
public override void OnAfterDelete()
{
base.OnAfterDelete();
if (Editor != null)
{
Delete();
Editor.Close();
Editor = null;
}
}
public override void Serialize(IGenericWriter writer)
{
}
public override void Deserialize(IGenericReader reader)
{
Delete();
}
public class EditGump : Gump
{
public enum Buttons
{
Close,
Clear,
Accept,
AllPlat,
AllGold
}
public class EditGump : Gump
private int m_Plat, m_Gold;
public EditGump(Mobile user, VirtualCheck check) : base(50, 50)
{
public enum Buttons
User = user;
Check = check;
m_Plat = Check.Plat;
m_Gold = Check.Gold;
Closable = true;
Disposable = true;
Draggable = true;
Resizable = false;
User.CloseGump<EditGump>();
CompileLayout();
}
public Mobile User { get; }
public VirtualCheck Check { get; private set; }
public override void OnServerClose(NetState owner)
{
base.OnServerClose(owner);
if (Check?.Deleted == false)
{
Close,
Clear,
Accept,
AllPlat,
AllGold
Check.UpdateTrade(User);
}
}
public void Close()
{
User.CloseGump<EditGump>();
if (Check?.Deleted == false)
{
Check.UpdateTrade(User);
}
else
{
Check = null;
}
}
public void Send()
{
if (Check?.Deleted == false)
{
User.SendGump(this);
}
else
{
Close();
}
}
public void Refresh(bool recompile)
{
if (Check?.Deleted != false)
{
Close();
return;
}
private int m_Plat, m_Gold;
public EditGump(Mobile user, VirtualCheck check) : base(50, 50)
if (recompile)
{
User = user;
Check = check;
m_Plat = Check.Plat;
m_Gold = Check.Gold;
Closable = true;
Disposable = true;
Draggable = true;
Resizable = false;
User.CloseGump<EditGump>();
CompileLayout();
}
public Mobile User { get; }
public VirtualCheck Check { get; private set; }
Close();
Send();
}
public override void OnServerClose(NetState owner)
private void CompileLayout()
{
if (Check?.Deleted != false)
{
base.OnServerClose(owner);
if (Check?.Deleted == false)
{
Check.UpdateTrade(User);
}
return;
}
public void Close()
Entries.ForEach(e => e.Parent = null);
Entries.Clear();
AddPage(0);
AddBackground(0, 0, 400, 160, 3500);
// Title
AddImageTiled(25, 35, 350, 3, 96);
AddImage(10, 8, 113);
AddImage(360, 8, 113);
var title =
$"<BASEFONT COLOR=#FF2F4F4F><CENTER>BANK OF {User.RawName.ToUpper()}</CENTER>";
AddHtml(40, 15, 320, 20, title);
// Platinum Row
AddBackground(15, 60, 175, 20, 9300);
AddBackground(20, 45, 165, 30, 9350);
AddItem(20, 45, 3826); // Plat
AddLabel(60, 50, 0, User.Account.TotalPlat.ToString("#,0"));
AddButton(195, 50, 95, 95, (int)Buttons.AllPlat); // ->
AddBackground(210, 60, 175, 20, 9300);
AddBackground(215, 45, 165, 30, 9350);
AddTextEntry(225, 50, 145, 20, 0, 0, m_Plat.ToString(), User.Account.TotalPlat.ToString().Length);
// Gold Row
AddBackground(15, 100, 175, 20, 9300);
AddBackground(20, 85, 165, 30, 9350);
AddItem(20, 85, 3823); // Gold
AddLabel(60, 90, 0, User.Account.TotalGold.ToString("#,0"));
AddButton(195, 90, 95, 95, (int)Buttons.AllGold); // ->
AddBackground(210, 100, 175, 20, 9300);
AddBackground(215, 85, 165, 30, 9350);
AddTextEntry(225, 90, 145, 20, 0, 1, m_Gold.ToString(), User.Account.TotalGold.ToString().Length);
// Buttons
AddButton(20, 128, 12006, 12007, (int)Buttons.Close);
AddButton(215, 128, 12003, 12004, (int)Buttons.Clear);
AddButton(305, 128, 12000, 12002, (int)Buttons.Accept);
}
public override void OnResponse(NetState sender, RelayInfo info)
{
if (Check?.Deleted != false || sender.Mobile != User)
{
User.CloseGump<EditGump>();
if (Check?.Deleted == false)
{
Check.UpdateTrade(User);
}
else
{
Check = null;
}
}
public void Send()
{
if (Check?.Deleted == false)
{
User.SendGump(this);
}
else
{
Close();
}
}
public void Refresh(bool recompile)
{
if (Check?.Deleted != false)
{
Close();
return;
}
if (recompile)
{
CompileLayout();
}
Close();
Send();
return;
}
private void CompileLayout()
bool refresh = false, updated = false;
switch ((Buttons)info.ButtonID)
{
if (Check?.Deleted != false)
{
return;
}
case Buttons.Close:
break;
case Buttons.Clear:
{
m_Plat = m_Gold = 0;
refresh = true;
}
break;
case Buttons.Accept:
{
var platText = info.GetTextEntry(0).Text;
var goldText = info.GetTextEntry(1).Text;
Entries.ForEach(e => e.Parent = null);
Entries.Clear();
AddPage(0);
AddBackground(0, 0, 400, 160, 3500);
// Title
AddImageTiled(25, 35, 350, 3, 96);
AddImage(10, 8, 113);
AddImage(360, 8, 113);
var title =
$"<BASEFONT COLOR=#FF2F4F4F><CENTER>BANK OF {User.RawName.ToUpper()}</CENTER>";
AddHtml(40, 15, 320, 20, title);
// Platinum Row
AddBackground(15, 60, 175, 20, 9300);
AddBackground(20, 45, 165, 30, 9350);
AddItem(20, 45, 3826); // Plat
AddLabel(60, 50, 0, User.Account.TotalPlat.ToString("#,0"));
AddButton(195, 50, 95, 95, (int)Buttons.AllPlat); // ->
AddBackground(210, 60, 175, 20, 9300);
AddBackground(215, 45, 165, 30, 9350);
AddTextEntry(225, 50, 145, 20, 0, 0, m_Plat.ToString(), User.Account.TotalPlat.ToString().Length);
// Gold Row
AddBackground(15, 100, 175, 20, 9300);
AddBackground(20, 85, 165, 30, 9350);
AddItem(20, 85, 3823); // Gold
AddLabel(60, 90, 0, User.Account.TotalGold.ToString("#,0"));
AddButton(195, 90, 95, 95, (int)Buttons.AllGold); // ->
AddBackground(210, 100, 175, 20, 9300);
AddBackground(215, 85, 165, 30, 9350);
AddTextEntry(225, 90, 145, 20, 0, 1, m_Gold.ToString(), User.Account.TotalGold.ToString().Length);
// Buttons
AddButton(20, 128, 12006, 12007, (int)Buttons.Close);
AddButton(215, 128, 12003, 12004, (int)Buttons.Clear);
AddButton(305, 128, 12000, 12002, (int)Buttons.Accept);
}
public override void OnResponse(NetState sender, RelayInfo info)
{
if (Check?.Deleted != false || sender.Mobile != User)
{
Close();
return;
}
bool refresh = false, updated = false;
switch ((Buttons)info.ButtonID)
{
case Buttons.Close:
break;
case Buttons.Clear:
if (!int.TryParse(platText, out m_Plat))
{
m_Plat = m_Gold = 0;
User.SendMessage("That is not a valid amount of platinum.");
refresh = true;
}
break;
case Buttons.Accept:
else if (!int.TryParse(goldText, out m_Gold))
{
var platText = info.GetTextEntry(0).Text;
var goldText = info.GetTextEntry(1).Text;
User.SendMessage("That is not a valid amount of gold.");
refresh = true;
}
else
{
var totalPlat = User.Account.TotalPlat;
var totalGold = User.Account.TotalGold;
if (!int.TryParse(platText, out m_Plat))
if (totalPlat < m_Plat || totalGold < m_Gold)
{
User.SendMessage("That is not a valid amount of platinum.");
refresh = true;
}
else if (!int.TryParse(goldText, out m_Gold))
{
User.SendMessage("That is not a valid amount of gold.");
m_Plat = User.Account.TotalPlat;
m_Gold = User.Account.TotalGold;
User.SendMessage("You do not have that much currency.");
refresh = true;
}
else
{
var totalPlat = User.Account.TotalPlat;
var totalGold = User.Account.TotalGold;
if (totalPlat < m_Plat || totalGold < m_Gold)
{
m_Plat = User.Account.TotalPlat;
m_Gold = User.Account.TotalGold;
User.SendMessage("You do not have that much currency.");
refresh = true;
}
else
{
Check.Plat = m_Plat;
Check.Gold = m_Gold;
updated = true;
}
Check.Plat = m_Plat;
Check.Gold = m_Gold;
updated = true;
}
}
break;
case Buttons.AllPlat:
{
m_Plat = User.Account.TotalPlat;
refresh = true;
}
break;
case Buttons.AllGold:
{
m_Gold = User.Account.TotalGold;
refresh = true;
}
break;
}
if (updated)
{
User.SendMessage("Your offer has been updated.");
}
if (refresh && Check?.Deleted == false)
{
Refresh(true);
return;
}
Close();
}
break;
case Buttons.AllPlat:
{
m_Plat = User.Account.TotalPlat;
refresh = true;
}
break;
case Buttons.AllGold:
{
m_Gold = User.Account.TotalGold;
refresh = true;
}
break;
}
if (updated)
{
User.SendMessage("Your offer has been updated.");
}
if (refresh && Check?.Deleted == false)
{
Refresh(true);
return;
}
Close();
}
}
}

View file

@ -3,146 +3,145 @@ using System.Buffers;
using System.Runtime.CompilerServices;
using Server.Network;
namespace Server
namespace Server;
public static class OutgoingVirtualHairPackets
{
public static class OutgoingVirtualHairPackets
public const int EquipUpdatePacketLength = 15;
public const int RemovePacketLength = 5;
public static void SendHairEquipUpdatePacket(this NetState ns, Mobile m, uint hairSerial, int itemId, int hue, Layer layer)
{
public const int EquipUpdatePacketLength = 15;
public const int RemovePacketLength = 5;
public static void SendHairEquipUpdatePacket(this NetState ns, Mobile m, uint hairSerial, int itemId, int hue, Layer layer)
if (ns.CannotSendPackets())
{
if (ns.CannotSendPackets())
{
return;
}
Span<byte> buffer = stackalloc byte[EquipUpdatePacketLength];
CreateHairEquipUpdatePacket(buffer, m, hairSerial, itemId, hue, layer);
ns.Send(buffer);
return;
}
public static void CreateHairEquipUpdatePacket(Span<byte> buffer, Mobile m, uint hairSerial, int itemId, int hue, Layer layer)
{
if (buffer[0] != 0)
{
return;
}
var writer = new SpanWriter(buffer);
writer.Write((byte)0x2E); // Packet ID
writer.Write(hairSerial);
writer.Write((short)itemId);
writer.Write((byte)0);
writer.Write((byte)layer);
writer.Write(m.Serial);
writer.Write((short)(m.SolidHueOverride >= 0 ? m.SolidHueOverride : hue));
}
public static void SendRemoveHairPacket(this NetState ns, uint hairSerial)
{
if (ns.CannotSendPackets())
{
return;
}
Span<byte> buffer = stackalloc byte[RemovePacketLength];
CreateRemoveHairPacket(buffer, hairSerial);
ns.Send(buffer);
}
public static void CreateRemoveHairPacket(Span<byte> buffer, uint hairSerial)
{
if (buffer[0] != 0)
{
return;
}
var writer = new SpanWriter(buffer);
writer.Write((byte)0x1D); // Packet ID
writer.Write(hairSerial);
}
Span<byte> buffer = stackalloc byte[EquipUpdatePacketLength];
CreateHairEquipUpdatePacket(buffer, m, hairSerial, itemId, hue, layer);
ns.Send(buffer);
}
public abstract class BaseHairInfo
public static void CreateHairEquipUpdatePacket(Span<byte> buffer, Mobile m, uint hairSerial, int itemId, int hue, Layer layer)
{
protected BaseHairInfo(int itemid, int hue = 0)
if (buffer[0] != 0)
{
ItemID = itemid;
Hue = hue;
return;
}
protected BaseHairInfo(IGenericReader reader)
{
var version = reader.ReadInt();
var writer = new SpanWriter(buffer);
writer.Write((byte)0x2E); // Packet ID
switch (version)
{
case 0:
{
ItemID = reader.ReadInt();
Hue = reader.ReadInt();
break;
}
}
}
[CommandProperty(AccessLevel.GameMaster)]
public int ItemID { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public int Hue { get; set; }
public virtual void Serialize(IGenericWriter writer)
{
writer.Write(0); // version
writer.Write(ItemID);
writer.Write(Hue);
}
writer.Write(hairSerial);
writer.Write((short)itemId);
writer.Write((byte)0);
writer.Write((byte)layer);
writer.Write(m.Serial);
writer.Write((short)(m.SolidHueOverride >= 0 ? m.SolidHueOverride : hue));
}
public class HairInfo : BaseHairInfo
public static void SendRemoveHairPacket(this NetState ns, uint hairSerial)
{
public HairInfo(int itemid)
: base(itemid)
if (ns.CannotSendPackets())
{
return;
}
public HairInfo(int itemid, int hue)
: base(itemid, hue)
{
}
public HairInfo(IGenericReader reader)
: base(reader)
{
}
// TODO: Can we make this higher for newer clients?
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static uint FakeSerial(Serial m) => 0x7FFFFFFF - 0x400 - m.Value * 4;
Span<byte> buffer = stackalloc byte[RemovePacketLength];
CreateRemoveHairPacket(buffer, hairSerial);
ns.Send(buffer);
}
public class FacialHairInfo : BaseHairInfo
public static void CreateRemoveHairPacket(Span<byte> buffer, uint hairSerial)
{
public FacialHairInfo(int itemid)
: base(itemid)
if (buffer[0] != 0)
{
return;
}
public FacialHairInfo(int itemid, int hue)
: base(itemid, hue)
{
}
public FacialHairInfo(IGenericReader reader)
: base(reader)
{
}
// TODO: Can we make this higher for newer clients?
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static uint FakeSerial(Serial m) => 0x7FFFFFFF - 0x400 - 1 - m.Value* 4;
var writer = new SpanWriter(buffer);
writer.Write((byte)0x1D); // Packet ID
writer.Write(hairSerial);
}
}
public abstract class BaseHairInfo
{
protected BaseHairInfo(int itemid, int hue = 0)
{
ItemID = itemid;
Hue = hue;
}
protected BaseHairInfo(IGenericReader reader)
{
var version = reader.ReadInt();
switch (version)
{
case 0:
{
ItemID = reader.ReadInt();
Hue = reader.ReadInt();
break;
}
}
}
[CommandProperty(AccessLevel.GameMaster)]
public int ItemID { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public int Hue { get; set; }
public virtual void Serialize(IGenericWriter writer)
{
writer.Write(0); // version
writer.Write(ItemID);
writer.Write(Hue);
}
}
public class HairInfo : BaseHairInfo
{
public HairInfo(int itemid)
: base(itemid)
{
}
public HairInfo(int itemid, int hue)
: base(itemid, hue)
{
}
public HairInfo(IGenericReader reader)
: base(reader)
{
}
// TODO: Can we make this higher for newer clients?
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static uint FakeSerial(Serial m) => 0x7FFFFFFF - 0x400 - m.Value * 4;
}
public class FacialHairInfo : BaseHairInfo
{
public FacialHairInfo(int itemid)
: base(itemid)
{
}
public FacialHairInfo(int itemid, int hue)
: base(itemid, hue)
{
}
public FacialHairInfo(IGenericReader reader)
: base(reader)
{
}
// TODO: Can we make this higher for newer clients?
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static uint FakeSerial(Serial m) => 0x7FFFFFFF - 0x400 - 1 - m.Value* 4;
}

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2021 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: ClientVersionConverterFactory.cs *
* *
@ -25,4 +25,4 @@ public class ClientVersionConverterFactory : JsonConverterFactory
public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options) =>
new ClientVersionConverter();
}
}

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2021 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: GuidConverter.cs *
* *
@ -33,4 +33,4 @@ public class GuidConverter : JsonConverter<Guid>
public override void Write(Utf8JsonWriter writer, Guid value, JsonSerializerOptions options)
=> writer.WriteStringValue(value.ToString());
}
}

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2021 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: GuidConverterFactory.cs *
* *
@ -25,4 +25,4 @@ public class GuidConverterFactory : JsonConverterFactory
public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options) =>
new GuidConverter();
}
}

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: IPEndPointConverter.cs *
* *
@ -34,4 +34,4 @@ public class IPEndPointConverter : JsonConverter<IPEndPoint>
public override void Write(Utf8JsonWriter writer, IPEndPoint value, JsonSerializerOptions options)
=> writer.WriteStringValue(value.ToString());
}
}

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: IPEndPointConverterFactory.cs *
* *
@ -26,4 +26,4 @@ public class IPEndPointConverterFactory : JsonConverterFactory
public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options) =>
new IPEndPointConverter();
}
}

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: MapConverter.cs *
* *
@ -31,4 +31,4 @@ public class MapConverter : JsonConverter<Map>
public override void Write(Utf8JsonWriter writer, Map value, JsonSerializerOptions options) =>
writer.WriteStringValue(value.Name);
}
}

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: MapConverterFactory.cs *
* *
@ -25,4 +25,4 @@ public class MapConverterFactory : JsonConverterFactory
public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options) =>
new MapConverter();
}
}

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: Point2DConverter.cs *
* *
@ -107,4 +107,4 @@ public class Point2DConverter : JsonConverter<Point2D>
writer.WriteNumberValue(value.Y);
writer.WriteEndArray();
}
}
}

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: Point2DConverterFactory.cs *
* *
@ -26,4 +26,4 @@ public class Point2DConverterFactory : JsonConverterFactory
public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options) =>
new Point2DConverter();
}
}

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: Point3DConverter.cs *
* *
@ -109,4 +109,4 @@ public class Point3DConverter : JsonConverter<Point3D>
writer.WriteNumberValue(value.Z);
writer.WriteEndArray();
}
}
}

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: Point3DConverterFactory.cs *
* *
@ -26,4 +26,4 @@ public class Point3DConverterFactory : JsonConverterFactory
public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options) =>
new Point3DConverter();
}
}

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: Rectangle3DConverter.cs *
* *
@ -180,4 +180,4 @@ public class Rectangle3DConverter : JsonConverter<Rectangle3D>
writer.WriteNumberValue(value.Depth);
writer.WriteEndArray();
}
}
}

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: Rectangle3DConverterFactory.cs *
* *
@ -25,4 +25,4 @@ public class Rectangle3DConverterFactory : JsonConverterFactory
public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options) =>
new Rectangle3DConverter();
}
}

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: TimeSpanConverter.cs *
* *
@ -26,4 +26,4 @@ public class TimeSpanConverter : JsonConverter<TimeSpan>
public override void Write(Utf8JsonWriter writer, TimeSpan value, JsonSerializerOptions options)
=> writer.WriteStringValue(value.ToString());
}
}

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: TimeSpanConverterFactory.cs *
* *
@ -25,4 +25,4 @@ public class TimeSpanConverterFactory : JsonConverterFactory
public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options) =>
new TimeSpanConverter();
}
}

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: TypeConverter.cs *
* *

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: TypeConverterFactory.cs *
* *

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: WorldLocationConverter.cs *
* *
@ -185,4 +185,4 @@ public class WorldLocationConverter : JsonConverter<WorldLocation>
writer.WriteStringValue(value.Map.ToString());
writer.WriteEndArray();
}
}
}

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: WorldLocationConverterFactory.cs *
* *
@ -25,4 +25,4 @@ public class WorldLocationConverterFactory : JsonConverterFactory
public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options) =>
new WorldLocationConverter();
}
}

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: DynamicJson.cs *
* *
@ -18,50 +18,49 @@ using System.Collections.Generic;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace Server.Json
namespace Server.Json;
public class DynamicJson
{
public class DynamicJson
public static DynamicJson Create(Type type) => new()
{
public static DynamicJson Create(Type type) => new()
Type = type.Name,
Data = new Dictionary<string, JsonElement>()
};
[JsonPropertyName("type")]
public string Type { get; set; }
[JsonExtensionData]
public Dictionary<string, JsonElement> Data { get; set; }
// TODO: Use JSON Node in .NET 6
public void SetProperty<T>(string key, JsonSerializerOptions options, T value)
{
using var doc = JsonDocument.Parse(JsonSerializer.SerializeToUtf8Bytes(value, options));
Data[key] = doc.RootElement.Clone();
}
public bool GetProperty<T>(string key, JsonSerializerOptions options, out T t)
{
if (Data.TryGetValue(key, out var el))
{
Type = type.Name,
Data = new Dictionary<string, JsonElement>()
};
[JsonPropertyName("type")]
public string Type { get; set; }
[JsonExtensionData]
public Dictionary<string, JsonElement> Data { get; set; }
// TODO: Use JSON Node in .NET 6
public void SetProperty<T>(string key, JsonSerializerOptions options, T value)
{
using var doc = JsonDocument.Parse(JsonSerializer.SerializeToUtf8Bytes(value, options));
Data[key] = doc.RootElement.Clone();
t = el.ToObject<T>(options);
return true;
}
public bool GetProperty<T>(string key, JsonSerializerOptions options, out T t)
{
if (Data.TryGetValue(key, out var el))
{
t = el.ToObject<T>(options);
return true;
}
t = default;
return false;
}
t = default;
return false;
public bool GetEnumProperty<T>(string key, JsonSerializerOptions options, out T t) where T : struct, Enum
{
if (Data.TryGetValue(key, out var el))
{
return Enum.TryParse(el.ToObject<string>(options), out t);
}
public bool GetEnumProperty<T>(string key, JsonSerializerOptions options, out T t) where T : struct, Enum
{
if (Data.TryGetValue(key, out var el))
{
return Enum.TryParse(el.ToObject<string>(options), out t);
}
t = default;
return false;
}
t = default;
return false;
}
}

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: JsonConfig.cs *
* *
@ -21,93 +21,92 @@ using System.Text.Json;
using System.Text.Json.Serialization;
using Server.Text;
namespace Server.Json
namespace Server.Json;
public static class JsonConfig
{
public static class JsonConfig
public static readonly JsonSerializerOptions DefaultOptions = GetOptions();
public static JsonSerializerOptions GetOptions(params JsonConverterFactory[] converters)
{
public static readonly JsonSerializerOptions DefaultOptions = GetOptions();
public static JsonSerializerOptions GetOptions(params JsonConverterFactory[] converters)
// In the future this should be optimized by cloning DefaultOptions
var options = new JsonSerializerOptions
{
// In the future this should be optimized by cloning DefaultOptions
var options = new JsonSerializerOptions
{
WriteIndented = true,
AllowTrailingCommas = true,
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
ReadCommentHandling = JsonCommentHandling.Skip,
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
};
WriteIndented = true,
AllowTrailingCommas = true,
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
ReadCommentHandling = JsonCommentHandling.Skip,
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
};
options.Converters.Add(new ClientVersionConverterFactory());
options.Converters.Add(new GuidConverterFactory());
options.Converters.Add(new JsonStringEnumConverter());
options.Converters.Add(new MapConverterFactory());
options.Converters.Add(new Point3DConverterFactory());
options.Converters.Add(new Rectangle3DConverterFactory());
options.Converters.Add(new TimeSpanConverterFactory());
options.Converters.Add(new IPEndPointConverterFactory());
options.Converters.Add(new TypeConverterFactory());
options.Converters.Add(new WorldLocationConverterFactory());
options.Converters.Add(new ClientVersionConverterFactory());
options.Converters.Add(new GuidConverterFactory());
options.Converters.Add(new JsonStringEnumConverter());
options.Converters.Add(new MapConverterFactory());
options.Converters.Add(new Point3DConverterFactory());
options.Converters.Add(new Rectangle3DConverterFactory());
options.Converters.Add(new TimeSpanConverterFactory());
options.Converters.Add(new IPEndPointConverterFactory());
options.Converters.Add(new TypeConverterFactory());
options.Converters.Add(new WorldLocationConverterFactory());
for (var i = 0; i < converters.Length; i++)
{
options.Converters.Add(converters[i]);
}
return options;
for (var i = 0; i < converters.Length; i++)
{
options.Converters.Add(converters[i]);
}
public static T Deserialize<T>(string filePath, JsonSerializerOptions options = null)
{
if (!File.Exists(filePath))
{
return default;
}
return options;
}
var text = File.ReadAllText(filePath, TextEncoding.UTF8);
return JsonSerializer.Deserialize<T>(text, options ?? DefaultOptions);
public static T Deserialize<T>(string filePath, JsonSerializerOptions options = null)
{
if (!File.Exists(filePath))
{
return default;
}
public static string Serialize(object value, JsonSerializerOptions options = null) =>
JsonSerializer.Serialize(value, options ?? DefaultOptions);
var text = File.ReadAllText(filePath, TextEncoding.UTF8);
return JsonSerializer.Deserialize<T>(text, options ?? DefaultOptions);
}
public static void Serialize(string filePath, object value, JsonSerializerOptions options = null)
public static string Serialize(object value, JsonSerializerOptions options = null) =>
JsonSerializer.Serialize(value, options ?? DefaultOptions);
public static void Serialize(string filePath, object value, JsonSerializerOptions options = null)
{
var contents = Serialize(value, options);
if (File.Exists(filePath))
{
var contents = Serialize(value, options);
if (File.Exists(filePath))
{
File.Delete(filePath);
}
Directory.CreateDirectory(Path.GetDirectoryName(filePath)!);
File.WriteAllText(filePath, contents);
File.Delete(filePath);
}
public static T ToObject<T>(this ref Utf8JsonReader reader, JsonSerializerOptions options = null) =>
JsonSerializer.Deserialize<T>(ref reader, options);
Directory.CreateDirectory(Path.GetDirectoryName(filePath)!);
public static T ToObject<T>(this JsonElement element, JsonSerializerOptions options = null)
File.WriteAllText(filePath, contents);
}
public static T ToObject<T>(this ref Utf8JsonReader reader, JsonSerializerOptions options = null) =>
JsonSerializer.Deserialize<T>(ref reader, options);
public static T ToObject<T>(this JsonElement element, JsonSerializerOptions options = null)
{
var bufferWriter = new ArrayBufferWriter<byte>();
using (var writer = new Utf8JsonWriter(bufferWriter))
{
var bufferWriter = new ArrayBufferWriter<byte>();
using (var writer = new Utf8JsonWriter(bufferWriter))
{
element.WriteTo(writer);
}
return JsonSerializer.Deserialize<T>(bufferWriter.WrittenSpan, options);
element.WriteTo(writer);
}
public static T ToObject<T>(this JsonDocument document, JsonSerializerOptions options = null)
{
if (document == null)
{
throw new ArgumentNullException(nameof(document));
}
return JsonSerializer.Deserialize<T>(bufferWriter.WrittenSpan, options);
}
return document.RootElement.ToObject<T>(options);
public static T ToObject<T>(this JsonDocument document, JsonSerializerOptions options = null)
{
if (document == null)
{
throw new ArgumentNullException(nameof(document));
}
return document.RootElement.ToObject<T>(options);
}
}

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2020 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: JsonPropertySorter.cs *
* *
@ -20,81 +20,80 @@ using System.Text;
using System.Text.Encodings.Web;
using System.Text.Json;
namespace Server.Json
namespace Server.Json;
public static class JsonUtilities
{
public static class JsonUtilities
public static string SortByPropertyName(string jsonStr)
{
public static string SortByPropertyName(string jsonStr)
using JsonDocument doc = JsonDocument.Parse(jsonStr);
return SortByPropertyName(doc.RootElement);
}
public static string SortByPropertyName(JsonElement je)
{
// TODO: Better way to do this than a stream?
using var ms = new MemoryStream();
JsonWriterOptions opts = new JsonWriterOptions
{
using JsonDocument doc = JsonDocument.Parse(jsonStr);
return SortByPropertyName(doc.RootElement);
Indented = true,
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
};
using (var writer = new Utf8JsonWriter(ms, opts))
{
WriteJsonElementSorted(je, writer);
}
public static string SortByPropertyName(JsonElement je)
ms.TryGetBuffer(out var buffer);
return Encoding.UTF8.GetString(buffer);
}
private static void WriteJsonElementSorted(JsonElement je, Utf8JsonWriter writer)
{
switch(je.ValueKind)
{
// TODO: Better way to do this than a stream?
using var ms = new MemoryStream();
JsonWriterOptions opts = new JsonWriterOptions
{
Indented = true,
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
};
case JsonValueKind.Object:
writer.WriteStartObject();
using (var writer = new Utf8JsonWriter(ms, opts))
{
WriteJsonElementSorted(je, writer);
}
// TODO: This is slow, can make it faster?
foreach (JsonProperty x in je.EnumerateObject().OrderBy(prop => prop.Name))
{
writer.WritePropertyName(x.Name);
WriteJsonElementSorted(x.Value, writer);
}
ms.TryGetBuffer(out var buffer);
return Encoding.UTF8.GetString(buffer);
}
writer.WriteEndObject();
break;
case JsonValueKind.Array:
writer.WriteStartArray();
foreach(JsonElement x in je.EnumerateArray())
{
WriteJsonElementSorted(x, writer);
}
writer.WriteEndArray();
break;
case JsonValueKind.Number:
writer.WriteNumberValue(je.GetDouble());
break;
case JsonValueKind.String:
// Escape the string
writer.WriteStringValue(je.GetString());
break;
case JsonValueKind.Null:
writer.WriteNullValue();
break;
case JsonValueKind.True:
writer.WriteBooleanValue(true);
break;
case JsonValueKind.False:
writer.WriteBooleanValue(false);
break;
case JsonValueKind.Undefined: // Don't write anything
break;
default:
throw new NotImplementedException($"Kind: {je.ValueKind}");
private static void WriteJsonElementSorted(JsonElement je, Utf8JsonWriter writer)
{
switch(je.ValueKind)
{
case JsonValueKind.Object:
writer.WriteStartObject();
// TODO: This is slow, can make it faster?
foreach (JsonProperty x in je.EnumerateObject().OrderBy(prop => prop.Name))
{
writer.WritePropertyName(x.Name);
WriteJsonElementSorted(x.Value, writer);
}
writer.WriteEndObject();
break;
case JsonValueKind.Array:
writer.WriteStartArray();
foreach(JsonElement x in je.EnumerateArray())
{
WriteJsonElementSorted(x, writer);
}
writer.WriteEndArray();
break;
case JsonValueKind.Number:
writer.WriteNumberValue(je.GetDouble());
break;
case JsonValueKind.String:
// Escape the string
writer.WriteStringValue(je.GetString());
break;
case JsonValueKind.Null:
writer.WriteNullValue();
break;
case JsonValueKind.True:
writer.WriteBooleanValue(true);
break;
case JsonValueKind.False:
writer.WriteBooleanValue(false);
break;
case JsonValueKind.Undefined: // Don't write anything
break;
default:
throw new NotImplementedException($"Kind: {je.ValueKind}");
}
}
}
}

View file

@ -1,65 +1,64 @@
using System;
namespace Server
namespace Server;
public class KeywordList
{
public class KeywordList
private static readonly int[] m_EmptyInts = Array.Empty<int>();
private int[] m_Keywords;
public KeywordList()
{
private static readonly int[] m_EmptyInts = Array.Empty<int>();
private int[] m_Keywords;
m_Keywords = new int[8];
Count = 0;
}
public KeywordList()
public int Count { get; private set; }
public bool Contains(int keyword)
{
var contains = false;
for (var i = 0; !contains && i < Count; ++i)
{
m_Keywords = new int[8];
Count = 0;
contains = keyword == m_Keywords[i];
}
public int Count { get; private set; }
return contains;
}
public bool Contains(int keyword)
public void Add(int keyword)
{
if (Count + 1 > m_Keywords.Length)
{
var contains = false;
var old = m_Keywords;
m_Keywords = new int[old.Length * 2];
for (var i = 0; !contains && i < Count; ++i)
for (var i = 0; i < old.Length; ++i)
{
contains = keyword == m_Keywords[i];
m_Keywords[i] = old[i];
}
return contains;
}
public void Add(int keyword)
m_Keywords[Count++] = keyword;
}
public int[] ToArray()
{
if (Count == 0)
{
if (Count + 1 > m_Keywords.Length)
{
var old = m_Keywords;
m_Keywords = new int[old.Length * 2];
for (var i = 0; i < old.Length; ++i)
{
m_Keywords[i] = old[i];
}
}
m_Keywords[Count++] = keyword;
return m_EmptyInts;
}
public int[] ToArray()
var keywords = new int[Count];
for (var i = 0; i < Count; ++i)
{
if (Count == 0)
{
return m_EmptyInts;
}
var keywords = new int[Count];
for (var i = 0; i < Count; ++i)
{
keywords[i] = m_Keywords[i];
}
Count = 0;
return keywords;
keywords[i] = m_Keywords[i];
}
Count = 0;
return keywords;
}
}

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2021 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: ILogger.cs *
* *
@ -15,23 +15,22 @@
using System;
namespace Server.Logging
namespace Server.Logging;
public interface ILogger
{
public interface ILogger
{
void Debug(string message, params object[] args);
void Debug(Exception exception, string message, params object[] args);
void Debug(string message, params object[] args);
void Debug(Exception exception, string message, params object[] args);
void Information(string message, params object[] args);
void Information(Exception exception, string message, params object[] args);
void Information(string message, params object[] args);
void Information(Exception exception, string message, params object[] args);
void Warning(string message, params object[] args);
void Warning(Exception exception, string message, params object[] args);
void Warning(string message, params object[] args);
void Warning(Exception exception, string message, params object[] args);
void Error(string message, params object[] args);
void Error(Exception exception, string message, params object[] args);
void Error(string message, params object[] args);
void Error(Exception exception, string message, params object[] args);
void Fatal(string message, params object[] args);
void Fatal(Exception exception, string message, params object[] args);
}
void Fatal(string message, params object[] args);
void Fatal(Exception exception, string message, params object[] args);
}

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright 2019-2021 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: SerilogLogger.cs *
* *
@ -16,53 +16,52 @@
using System;
using System.Runtime.CompilerServices;
namespace Server.Logging
namespace Server.Logging;
public class SerilogLogger : ILogger
{
public class SerilogLogger : ILogger
{
private readonly Serilog.ILogger serilogLogger;
private readonly Serilog.ILogger serilogLogger;
public SerilogLogger(Serilog.ILogger serilogLogger) =>
this.serilogLogger = serilogLogger;
public SerilogLogger(Serilog.ILogger serilogLogger) =>
this.serilogLogger = serilogLogger;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Debug(string message, params object[] args) =>
serilogLogger.Debug(message, args);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Debug(string message, params object[] args) =>
serilogLogger.Debug(message, args);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Debug(Exception exception, string message, params object[] args) =>
serilogLogger.Debug(exception, message, args);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Debug(Exception exception, string message, params object[] args) =>
serilogLogger.Debug(exception, message, args);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Information(string message, params object[] args) =>
serilogLogger.Information(message, args);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Information(string message, params object[] args) =>
serilogLogger.Information(message, args);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Information(Exception exception, string message, params object[] args) =>
serilogLogger.Information(exception, message, args);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Information(Exception exception, string message, params object[] args) =>
serilogLogger.Information(exception, message, args);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Warning(string message, params object[] args) =>
serilogLogger.Warning(message, args);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Warning(string message, params object[] args) =>
serilogLogger.Warning(message, args);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Warning(Exception exception, string message, params object[] args) =>
serilogLogger.Information(exception, message, args);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Warning(Exception exception, string message, params object[] args) =>
serilogLogger.Warning(exception, message, args);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Error(string message, params object[] args) =>
serilogLogger.Error(message, args);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Error(string message, params object[] args) =>
serilogLogger.Error(message, args);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Error(Exception exception, string message, params object[] args) =>
serilogLogger.Error(exception, message, args);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Error(Exception exception, string message, params object[] args) =>
serilogLogger.Error(exception, message, args);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Fatal(string message, params object[] args) =>
serilogLogger.Fatal(message, args);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Fatal(string message, params object[] args) =>
serilogLogger.Fatal(message, args);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Fatal(Exception exception, string message, params object[] args) =>
serilogLogger.Fatal(exception, message, args);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Fatal(Exception exception, string message, params object[] args) =>
serilogLogger.Fatal(exception, message, args);
}

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
/*************************************************************************
* ModernUO *
* Copyright (C) 2019-2021 - ModernUO Development Team *
* Copyright 2019-2022 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: MapLoader.cs *
* *
@ -22,125 +22,124 @@ using System.Text.Json.Serialization;
using Server.Json;
using Server.Logging;
namespace Server
namespace Server;
public static class MapLoader
{
public static class MapLoader
private static readonly ILogger logger = LogFactory.GetLogger(typeof(MapLoader));
/* Here we configure all maps. Some notes:
*
* 1) The first 32 maps are reserved for core use.
* 2) Map 127 is reserved for core use.
* 3) Map 255 is reserved for core use.
* 4) Changing or removing any predefined maps may cause server instability.
*
* Map definitions are modified in Data/Map Definitions/<expansion>.json:
* - <index> : An unreserved unique index for this map
* - <id> : An identification number used in client communications. For any visible maps, this value must be from 0-5
* - <fileIndex> : A file identification number. For any visible maps, this value must be from 0-5
* - <width>, <height> : Size of the map (in tiles)
* - <season> : Season of the map. 0 = Spring, 1 = Summer, 2 = Fall, 3 = Winter, 4 = Desolation
* - <name> : Reference name for the map, used in props gump, get/set commands, region loading, etc
* - <rules> : Rules and restrictions associated with the map. See documentation for details
*/
[CallPriority(2)]
public static void Configure()
{
private static readonly ILogger logger = LogFactory.GetLogger(typeof(MapLoader));
var failures = new List<string>();
var count = 0;
/* Here we configure all maps. Some notes:
*
* 1) The first 32 maps are reserved for core use.
* 2) Map 127 is reserved for core use.
* 3) Map 255 is reserved for core use.
* 4) Changing or removing any predefined maps may cause server instability.
*
* Map definitions are modified in Data/Map Definitions/<expansion>.json:
* - <index> : An unreserved unique index for this map
* - <id> : An identification number used in client communications. For any visible maps, this value must be from 0-5
* - <fileIndex> : A file identification number. For any visible maps, this value must be from 0-5
* - <width>, <height> : Size of the map (in tiles)
* - <season> : Season of the map. 0 = Spring, 1 = Summer, 2 = Fall, 3 = Winter, 4 = Desolation
* - <name> : Reference name for the map, used in props gump, get/set commands, region loading, etc
* - <rules> : Rules and restrictions associated with the map. See documentation for details
*/
[CallPriority(2)]
public static void Configure()
var path = Path.Combine(Core.BaseDirectory, "Data/map-definitions.json");
logger.Information("Loading Map Definitions");
var stopwatch = Stopwatch.StartNew();
var maps = JsonConfig.Deserialize<List<MapDefinition>>(path);
if (maps == null)
{
var failures = new List<string>();
var count = 0;
throw new JsonException($"Failed to deserialize {path}.");
}
var path = Path.Combine(Core.BaseDirectory, "Data/map-definitions.json");
logger.Information("Loading Map Definitions");
var stopwatch = Stopwatch.StartNew();
var maps = JsonConfig.Deserialize<List<MapDefinition>>(path);
if (maps == null)
foreach (var def in maps)
{
try
{
throw new JsonException($"Failed to deserialize {path}.");
RegisterMap(def);
count++;
}
foreach (var def in maps)
catch (Exception ex)
{
try
{
RegisterMap(def);
count++;
}
catch (Exception ex)
{
logger.Debug(ex, "Failed to load map definition {MapDefName} ({MapDefId})", def.Name, def.Id);
failures.Add($"\tInvalid map definition {def.Name} ({def.Id})");
}
}
stopwatch.Stop();
if (failures.Count > 0)
{
logger.Warning(
"Map Definitions loaded with failures ({Count} maps, {FailureCount} failures) ({Duration:F2} seconds)",
count,
failures.Count,
stopwatch.Elapsed.TotalSeconds
);
logger.Warning("Map load failures: {Failure}", failures);
}
else
{
logger.Information(
"Map Definitions loaded successfully ({Count} maps, {FailureCount} failures) ({Duration:F2} seconds)",
count,
failures.Count,
stopwatch.Elapsed.TotalSeconds
);
logger.Debug(ex, "Failed to load map definition {MapDefName} ({MapDefId})", def.Name, def.Id);
failures.Add($"\tInvalid map definition {def.Name} ({def.Id})");
}
}
private static void RegisterMap(MapDefinition mapDefinition)
stopwatch.Stop();
if (failures.Count > 0)
{
var newMap = new Map(
mapDefinition.Id,
mapDefinition.Index,
mapDefinition.FileIndex,
Math.Max(mapDefinition.Width, Map.SectorSize),
Math.Max(mapDefinition.Height, Map.SectorSize),
mapDefinition.Season,
mapDefinition.Name,
mapDefinition.Rules
logger.Warning(
"Map Definitions loaded with failures ({Count} maps, {FailureCount} failures) ({Duration:F2} seconds)",
count,
failures.Count,
stopwatch.Elapsed.TotalSeconds
);
Map.Maps[mapDefinition.Index] = newMap;
Map.AllMaps.Add(newMap);
logger.Warning("Map load failures: {Failure}", failures);
}
internal class MapDefinition
else
{
[JsonPropertyName("index")]
public int Index { get; set; }
[JsonPropertyName("id")]
public int Id { get; set; }
[JsonPropertyName("fileIndex")]
public int FileIndex { get; set; }
[JsonPropertyName("name")]
public string Name { get; set; }
[JsonPropertyName("width")]
public int Width { get; set; }
[JsonPropertyName("height")]
public int Height { get; set; }
[JsonPropertyName("season")]
public int Season { get; set; }
[JsonPropertyName("rules")]
public MapRules Rules { get; set; }
logger.Information(
"Map Definitions loaded successfully ({Count} maps, {FailureCount} failures) ({Duration:F2} seconds)",
count,
failures.Count,
stopwatch.Elapsed.TotalSeconds
);
}
}
private static void RegisterMap(MapDefinition mapDefinition)
{
var newMap = new Map(
mapDefinition.Id,
mapDefinition.Index,
mapDefinition.FileIndex,
Math.Max(mapDefinition.Width, Map.SectorSize),
Math.Max(mapDefinition.Height, Map.SectorSize),
mapDefinition.Season,
mapDefinition.Name,
mapDefinition.Rules
);
Map.Maps[mapDefinition.Index] = newMap;
Map.AllMaps.Add(newMap);
}
internal class MapDefinition
{
[JsonPropertyName("index")]
public int Index { get; set; }
[JsonPropertyName("id")]
public int Id { get; set; }
[JsonPropertyName("fileIndex")]
public int FileIndex { get; set; }
[JsonPropertyName("name")]
public string Name { get; set; }
[JsonPropertyName("width")]
public int Width { get; set; }
[JsonPropertyName("height")]
public int Height { get; set; }
[JsonPropertyName("season")]
public int Season { get; set; }
[JsonPropertyName("rules")]
public MapRules Rules { get; set; }
}
}

View file

@ -1,13 +1,12 @@
using Server.Network;
namespace Server.Menus
namespace Server.Menus;
public interface IMenu
{
public interface IMenu
{
int Serial { get; }
int EntryLength { get; }
void SendTo(NetState state);
void OnCancel(NetState state);
void OnResponse(NetState state, int index);
}
int Serial { get; }
int EntryLength { get; }
void SendTo(NetState state);
void OnCancel(NetState state);
void OnResponse(NetState state, int index);
}

View file

@ -1,61 +1,60 @@
using Server.Network;
namespace Server.Menus.ItemLists
namespace Server.Menus.ItemLists;
public class ItemListEntry
{
public class ItemListEntry
public ItemListEntry(string name, int itemID, int hue = 0)
{
public ItemListEntry(string name, int itemID, int hue = 0)
{
Name = name?.Trim() ?? "";
ItemID = itemID;
Hue = hue;
}
public string Name { get; }
public int ItemID { get; }
public int Hue { get; }
Name = name?.Trim() ?? "";
ItemID = itemID;
Hue = hue;
}
public class ItemListMenu : IMenu
public string Name { get; }
public int ItemID { get; }
public int Hue { get; }
}
public class ItemListMenu : IMenu
{
private static int m_NextSerial;
public ItemListMenu(string question, ItemListEntry[] entries)
{
private static int m_NextSerial;
Question = question.Trim();
Entries = entries;
public ItemListMenu(string question, ItemListEntry[] entries)
do
{
Question = question.Trim();
Entries = entries;
Serial = m_NextSerial++;
Serial &= 0x7FFFFFFF;
} while (Serial == 0);
do
{
Serial = m_NextSerial++;
Serial &= 0x7FFFFFFF;
} while (Serial == 0);
Serial = (int)((uint)Serial | 0x80000000);
}
Serial = (int)((uint)Serial | 0x80000000);
}
public string Question { get; }
public string Question { get; }
public ItemListEntry[] Entries { get; set; }
public ItemListEntry[] Entries { get; set; }
public int Serial { get; }
public int Serial { get; }
public int EntryLength => Entries.Length;
public int EntryLength => Entries.Length;
public virtual void OnCancel(NetState state)
{
}
public virtual void OnCancel(NetState state)
{
}
public virtual void OnResponse(NetState state, int index)
{
}
public virtual void OnResponse(NetState state, int index)
{
}
public void SendTo(NetState state)
{
state.AddMenu(this);
state.SendDisplayItemListMenu(this);
}
public void SendTo(NetState state)
{
state.AddMenu(this);
state.SendDisplayItemListMenu(this);
}
}

Some files were not shown because too many files have changed in this diff Show more