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:
parent
0138d40bda
commit
f268d5d4e2
262 changed files with 28527 additions and 28646 deletions
4
.github/workflows/build-test.yml
vendored
4
.github/workflows/build-test.yml
vendored
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*************************************************************************
|
||||
* ModernUO *
|
||||
* Copyright 2019-2020 - ModernUO Development Team *
|
||||
* Copyright 2019-2022 - ModernUO Development Team *
|
||||
* Email: hi@modernuo.com *
|
||||
* File: VendorSellPackets.cs *
|
||||
* *
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*************************************************************************
|
||||
* ModernUO *
|
||||
* Copyright 2019-2021 - ModernUO Development Team *
|
||||
* Copyright 2019-2022 - ModernUO Development Team *
|
||||
* Email: hi@modernuo.com *
|
||||
* File: CollectionThrowStrings.cs *
|
||||
* *
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -1,6 +1,6 @@
|
|||
/*************************************************************************
|
||||
* ModernUO *
|
||||
* Copyright 2019-2021 - ModernUO Development Team *
|
||||
* Copyright 2019-2022 - ModernUO Development Team *
|
||||
* Email: hi@modernuo.com *
|
||||
* File: PooledOrderedHashSet.cs *
|
||||
* *
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*************************************************************************
|
||||
* ModernUO *
|
||||
* Copyright 2019-2020 - ModernUO Development Team *
|
||||
* Copyright 2019-2022 - ModernUO Development Team *
|
||||
* Email: hi@modernuo.com *
|
||||
* File: ServerConfiguration.cs *
|
||||
* *
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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.")
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*************************************************************************
|
||||
* ModernUO *
|
||||
* Copyright 2019-2021 - ModernUO Development Team *
|
||||
* Copyright 2019-2022 - ModernUO Development Team *
|
||||
* Email: hi@modernuo.com *
|
||||
* File: ExpansionInfo.cs *
|
||||
* *
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*************************************************************************
|
||||
* ModernUO *
|
||||
* Copyright 2019-2020 - ModernUO Development Team *
|
||||
* Copyright 2019-2022 - ModernUO Development Team *
|
||||
* Email: hi@modernuo.com *
|
||||
* File: Rectangle2D.cs *
|
||||
* *
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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}]\"";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*************************************************************************
|
||||
* ModernUO *
|
||||
* Copyright 2019-2020 - ModernUO Development Team *
|
||||
* Copyright 2019-2022 - ModernUO Development Team *
|
||||
* Email: hi@modernuo.com *
|
||||
* File: GumpECHandleInput.cs *
|
||||
* *
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*************************************************************************
|
||||
* ModernUO *
|
||||
* Copyright 2019-2020 - ModernUO Development Team *
|
||||
* Copyright 2019-2022 - ModernUO Development Team *
|
||||
* Email: hi@modernuo.com *
|
||||
* File: GumpMasterGump.cs *
|
||||
* *
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*************************************************************************
|
||||
* ModernUO *
|
||||
* Copyright 2019-2020 - ModernUO Development Team *
|
||||
* Copyright 2019-2022 - ModernUO Development Team *
|
||||
* Email: hi@modernuo.com *
|
||||
* File: GumpSpriteImage.cs *
|
||||
* *
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*************************************************************************
|
||||
* ModernUO *
|
||||
* Copyright 2019-2020 - ModernUO Development Team *
|
||||
* Copyright 2019-2022 - ModernUO Development Team *
|
||||
* Email: hi@modernuo.com *
|
||||
* File: GumpTooltip.cs *
|
||||
* *
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*************************************************************************
|
||||
* ModernUO *
|
||||
* Copyright 2019-2020 - ModernUO Development Team *
|
||||
* Copyright 2019-2022 - ModernUO Development Team *
|
||||
* Email: hi@modernuo.com *
|
||||
* File: TypeConverter.cs *
|
||||
* *
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*************************************************************************
|
||||
* ModernUO *
|
||||
* Copyright 2019-2020 - ModernUO Development Team *
|
||||
* Copyright 2019-2022 - ModernUO Development Team *
|
||||
* Email: hi@modernuo.com *
|
||||
* File: TypeConverterFactory.cs *
|
||||
* *
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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}");
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -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; }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
Loading…
Add table
Add a link
Reference in a new issue