Merge pull request #456 from daemitus/utility

This commit is contained in:
goaaats 2021-08-10 13:58:57 +02:00 committed by GitHub
commit 9199adb261
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
44 changed files with 485 additions and 444 deletions

View file

@ -0,0 +1,27 @@
using System;
namespace Dalamud
{
/// <summary>
/// Extension methods for the <see cref="ClientLanguage"/> class.
/// </summary>
public static class ClientLanguageExtensions
{
/// <summary>
/// Converts a Dalamud ClientLanguage to the corresponding Lumina variant.
/// </summary>
/// <param name="language">Langauge to convert.</param>
/// <returns>Converted langauge.</returns>
public static Lumina.Data.Language ToLumina(this ClientLanguage language)
{
return language switch
{
ClientLanguage.Japanese => Lumina.Data.Language.Japanese,
ClientLanguage.English => Lumina.Data.Language.English,
ClientLanguage.German => Lumina.Data.Language.German,
ClientLanguage.French => Lumina.Data.Language.French,
_ => throw new ArgumentOutOfRangeException(nameof(language)),
};
}
}
}

View file

@ -5,9 +5,8 @@ using System.Diagnostics;
using System.IO;
using System.Threading;
using Dalamud.Data.LuminaExtensions;
using Dalamud.Interface;
using Dalamud.Interface.Internal;
using Dalamud.Utility;
using ImGuiScene;
using JetBrains.Annotations;
using Lumina;
@ -96,15 +95,7 @@ namespace Dalamud.Data
/// <returns>The <see cref="ExcelSheet{T}"/>, giving access to game rows.</returns>
public ExcelSheet<T> GetExcelSheet<T>(ClientLanguage language) where T : ExcelRow
{
var lang = language switch
{
ClientLanguage.Japanese => Lumina.Data.Language.Japanese,
ClientLanguage.English => Lumina.Data.Language.English,
ClientLanguage.German => Lumina.Data.Language.German,
ClientLanguage.French => Lumina.Data.Language.French,
_ => throw new ArgumentOutOfRangeException(nameof(language), $"Unknown Language: {language}"),
};
return this.Excel.GetSheet<T>(lang);
return this.Excel.GetSheet<T>(language.ToLumina());
}
/// <summary>
@ -146,18 +137,30 @@ namespace Dalamud.Data
/// </summary>
/// <param name="iconId">The icon ID.</param>
/// <returns>The <see cref="TexFile"/> containing the icon.</returns>
public TexFile GetIcon(int iconId)
public TexFile GetIcon(uint iconId)
{
return this.GetIcon(this.Language, iconId);
}
/// <summary>
/// Get a <see cref="TexFile"/> containing the icon with the given ID, of the given quality.
/// </summary>
/// <param name="isHq">A value indicating whether the icon should be HQ.</param>
/// <param name="iconId">The icon ID.</param>
/// <returns>The <see cref="TexFile"/> containing the icon.</returns>
public TexFile GetIcon(bool isHq, uint iconId)
{
var type = isHq ? "hq/" : string.Empty;
return this.GetIcon(type, iconId);
}
/// <summary>
/// Get a <see cref="TexFile"/> containing the icon with the given ID, of the given language.
/// </summary>
/// <param name="iconLanguage">The requested language.</param>
/// <param name="iconId">The icon ID.</param>
/// <returns>The <see cref="TexFile"/> containing the icon.</returns>
public TexFile GetIcon(ClientLanguage iconLanguage, int iconId)
public TexFile GetIcon(ClientLanguage iconLanguage, uint iconId)
{
var type = iconLanguage switch
{
@ -177,7 +180,7 @@ namespace Dalamud.Data
/// <param name="type">The type of the icon (e.g. 'hq' to get the HQ variant of an item icon).</param>
/// <param name="iconId">The icon ID.</param>
/// <returns>The <see cref="TexFile"/> containing the icon.</returns>
public TexFile GetIcon(string type, int iconId)
public TexFile GetIcon(string type, uint iconId)
{
type ??= string.Empty;
if (type.Length > 0 && !type.EndsWith("/"))
@ -186,7 +189,8 @@ namespace Dalamud.Data
var filePath = string.Format(IconFileFormat, iconId / 1000, type, iconId);
var file = this.GetFile<TexFile>(filePath);
if (file != default(TexFile) || type.Length <= 0) return file;
if (type == string.Empty || file != default)
return file;
// Couldn't get specific type, try for generic version.
filePath = string.Format(IconFileFormat, iconId / 1000, string.Empty, iconId);
@ -194,6 +198,14 @@ namespace Dalamud.Data
return file;
}
/// <summary>
/// Get a <see cref="TexFile"/> containing the HQ icon with the given ID.
/// </summary>
/// <param name="iconId">The icon ID.</param>
/// <returns>The <see cref="TexFile"/> containing the icon.</returns>
public TexFile GetHqIcon(uint iconId)
=> this.GetIcon(true, iconId);
/// <summary>
/// Get the passed <see cref="TexFile"/> as a drawable ImGui TextureWrap.
/// </summary>
@ -210,13 +222,30 @@ namespace Dalamud.Data
public TextureWrap GetImGuiTexture(string path)
=> this.GetImGuiTexture(this.GetFile<TexFile>(path));
/// <summary>
/// Get a <see cref="TextureWrap"/> containing the icon with the given ID.
/// </summary>
/// <param name="iconId">The icon ID.</param>
/// <returns>The <see cref="TextureWrap"/> containing the icon.</returns>
public TextureWrap GetImGuiTextureIcon(uint iconId)
=> this.GetImGuiTexture(this.GetIcon(iconId));
/// <summary>
/// Get a <see cref="TextureWrap"/> containing the icon with the given ID, of the given quality.
/// </summary>
/// <param name="isHq">A value indicating whether the icon should be HQ.</param>
/// <param name="iconId">The icon ID.</param>
/// <returns>The <see cref="TextureWrap"/> containing the icon.</returns>
public TextureWrap GetImGuiTextureIcon(bool isHq, uint iconId)
=> this.GetImGuiTexture(this.GetIcon(isHq, iconId));
/// <summary>
/// Get a <see cref="TextureWrap"/> containing the icon with the given ID, of the given language.
/// </summary>
/// <param name="iconLanguage">The requested language.</param>
/// <param name="iconId">The icon ID.</param>
/// <returns>The <see cref="TextureWrap"/> containing the icon.</returns>
public TextureWrap GetImGuiTextureIcon(ClientLanguage iconLanguage, int iconId)
public TextureWrap GetImGuiTextureIcon(ClientLanguage iconLanguage, uint iconId)
=> this.GetImGuiTexture(this.GetIcon(iconLanguage, iconId));
/// <summary>
@ -225,9 +254,17 @@ namespace Dalamud.Data
/// <param name="type">The type of the icon (e.g. 'hq' to get the HQ variant of an item icon).</param>
/// <param name="iconId">The icon ID.</param>
/// <returns>The <see cref="TextureWrap"/> containing the icon.</returns>
public TextureWrap GetImGuiTextureIcon(string type, int iconId)
public TextureWrap GetImGuiTextureIcon(string type, uint iconId)
=> this.GetImGuiTexture(this.GetIcon(type, iconId));
/// <summary>
/// Get a <see cref="TextureWrap"/> containing the HQ icon with the given ID.
/// </summary>
/// <param name="iconId">The icon ID.</param>
/// <returns>The <see cref="TextureWrap"/> containing the icon.</returns>
public TextureWrap GetImGuiTextureHqIcon(uint iconId)
=> this.GetImGuiTexture(this.GetHqIcon(iconId));
#endregion
/// <summary>
@ -263,21 +300,12 @@ namespace Dalamud.Data
var luminaOptions = new LuminaOptions
{
CacheFileResources = true,
#if DEBUG
PanicOnSheetChecksumMismatch = true,
#else
PanicOnSheetChecksumMismatch = false,
#endif
DefaultExcelLanguage = this.Language switch
{
ClientLanguage.Japanese => Lumina.Data.Language.Japanese,
ClientLanguage.English => Lumina.Data.Language.English,
ClientLanguage.German => Lumina.Data.Language.German,
ClientLanguage.French => Lumina.Data.Language.French,
_ => throw new ArgumentOutOfRangeException(nameof(this.Language), $"Unknown Language: {this.Language}"),
},
DefaultExcelLanguage = this.Language.ToLumina(),
};
var processModule = Process.GetCurrentProcess().MainModule;

View file

@ -142,7 +142,7 @@ namespace Dalamud
var oldFile = new FileInfo(oldPath);
if (!oldFile.Exists)
oldFile.Create();
oldFile.Create().Close();
using var reader = new BinaryReader(logFile.Open(FileMode.Open, FileAccess.Read));
using var writer = new BinaryWriter(oldFile.Open(FileMode.Append, FileAccess.Write));

View file

@ -3,7 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
namespace Dalamud.Game.Internal
namespace Dalamud.Game
{
/// <summary>
/// Base memory address resolver.
@ -11,9 +11,9 @@ namespace Dalamud.Game.Internal
public abstract class BaseAddressResolver
{
/// <summary>
/// A list of memory addresses that were found, to list in /xldata.
/// Gets a list of memory addresses that were found, to list in /xldata.
/// </summary>
public static Dictionary<string, List<(string, IntPtr)>> DebugScannedValues = new();
public static Dictionary<string, List<(string ClassName, IntPtr Address)>> DebugScannedValues { get; } = new();
/// <summary>
/// Gets or sets a value indicating whether the resolver has successfully run <see cref="Setup32Bit(SigScanner)"/> or <see cref="Setup64Bit(SigScanner)"/>.

View file

@ -6,8 +6,8 @@ using System.Runtime.InteropServices;
using System.Threading;
using Dalamud.Game.Internal.Gui;
using Dalamud.Game.Internal.Libc;
using Dalamud.Game.Internal.Network;
using Dalamud.Game.Libc;
using Dalamud.Hooking;
using Serilog;

View file

@ -2,9 +2,8 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using Dalamud.Game.Internal.Libc;
using Dalamud.Game.Libc;
using Dalamud.Game.Text;
using Dalamud.Game.Text.SeStringHandling;
using Dalamud.Game.Text.SeStringHandling.Payloads;
@ -60,17 +59,6 @@ namespace Dalamud.Game.Internal.Gui
/// <param name="isHandled">A value indicating whether the message was handled or should be propagated.</param>
public delegate void OnMessageDelegate(XivChatType type, uint senderId, ref SeString sender, ref SeString message, ref bool isHandled);
/// <summary>
/// A delegate type used with the <see cref="OnChatMessageRaw"/> event.
/// </summary>
/// <param name="type">The type of chat.</param>
/// <param name="senderId">The sender ID.</param>
/// <param name="sender">The sender name.</param>
/// <param name="message">The message sent.</param>
/// <param name="isHandled">A value indicating whether the message was handled or should be propagated.</param>
[Obsolete("Please use OnMessageDelegate instead. For modifications, it will take precedence.")]
public delegate void OnMessageRawDelegate(XivChatType type, uint senderId, ref StdString sender, ref StdString message, ref bool isHandled);
/// <summary>
/// A delegate type used with the <see cref="OnCheckMessageHandled"/> event.
/// </summary>
@ -113,12 +101,6 @@ namespace Dalamud.Game.Internal.Gui
/// </summary>
public event OnMessageDelegate OnChatMessage;
/// <summary>
/// Event that will be fired when a chat message is sent by the game, containing raw, unparsed data.
/// </summary>
[Obsolete("Please use OnChatMessage instead. For modifications, it will take precedence.")]
public event OnMessageRawDelegate OnChatMessageRaw;
/// <summary>
/// Event that allows you to stop messages from appearing in chat by setting the isHandled parameter to true.
/// </summary>
@ -388,7 +370,6 @@ namespace Dalamud.Game.Internal.Gui
if (!isHandled)
{
this.OnChatMessage?.Invoke(chattype, senderid, ref parsedSender, ref parsedMessage, ref isHandled);
this.OnChatMessageRaw?.Invoke(chattype, senderid, ref sender, ref message, ref isHandled);
}
var newEdited = parsedMessage.Encode();

View file

@ -1,159 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using Dalamud.Hooking;
using Serilog;
namespace Dalamud.Game.Internal.File
{
/// <summary>
/// This class facilitates modifying how the game loads resources from disk.
/// </summary>
public class ResourceManager
{
private readonly Dalamud dalamud;
private readonly ResourceManagerAddressResolver address;
private readonly Hook<GetResourceAsyncDelegate> getResourceAsyncHook;
private readonly Hook<GetResourceSyncDelegate> getResourceSyncHook;
private Dictionary<IntPtr, ResourceHandleHookInfo> resourceHookMap = new();
/// <summary>
/// Initializes a new instance of the <see cref="ResourceManager"/> class.
/// </summary>
/// <param name="dalamud">The Dalamud instance.</param>
/// <param name="scanner">The SigScanner instance.</param>
internal ResourceManager(Dalamud dalamud, SigScanner scanner)
{
this.dalamud = dalamud;
this.address = new ResourceManagerAddressResolver();
this.address.Setup(scanner);
Log.Verbose("===== R E S O U R C E M A N A G E R =====");
Log.Verbose("GetResourceAsync address {GetResourceAsync}", this.address.GetResourceAsync);
Log.Verbose("GetResourceSync address {GetResourceSync}", this.address.GetResourceSync);
this.getResourceAsyncHook = new Hook<GetResourceAsyncDelegate>(this.address.GetResourceAsync, this.GetResourceAsyncDetour);
this.getResourceSyncHook = new Hook<GetResourceSyncDelegate>(this.address.GetResourceSync, this.GetResourceSyncDetour);
}
[UnmanagedFunctionPointer(CallingConvention.ThisCall)]
private delegate IntPtr GetResourceAsyncDelegate(IntPtr manager, IntPtr a2, IntPtr a3, IntPtr a4, IntPtr pathPtr, IntPtr a6, byte a7);
[UnmanagedFunctionPointer(CallingConvention.ThisCall)]
private delegate IntPtr GetResourceSyncDelegate(IntPtr manager, IntPtr a2, IntPtr a3, IntPtr a4, IntPtr pathPtr, IntPtr a6);
/// <summary>
/// Check if a filepath has any invalid characters.
/// </summary>
/// <param name="path">The filepath to check.</param>
/// <returns>A value indicating whether the filepath is safe to use.</returns>
public static bool FilePathHasInvalidChars(string path)
{
return !string.IsNullOrEmpty(path) && path.IndexOfAny(Path.GetInvalidPathChars()) >= 0;
}
/// <summary>
/// Enable this module.
/// </summary>
public void Enable()
{
this.getResourceAsyncHook.Enable();
this.getResourceSyncHook.Enable();
}
/// <summary>
/// Dispose of managed and unmanaged resources.
/// </summary>
public void Dispose()
{
this.getResourceAsyncHook.Dispose();
this.getResourceSyncHook.Dispose();
}
private IntPtr GetResourceAsyncDetour(IntPtr manager, IntPtr a2, IntPtr a3, IntPtr a4, IntPtr pathPtr, IntPtr a6, byte a7)
{
try
{
var path = Marshal.PtrToStringAnsi(pathPtr);
var resourceHandle = this.getResourceAsyncHook.Original(manager, a2, a3, a4, IntPtr.Zero, a6, a7);
// var resourceHandle = IntPtr.Zero;
Log.Verbose("GetResourceAsync CALL - this:{0} a2:{1} a3:{2} a4:{3} a5:{4} a6:{5} a7:{6} => RET:{7}", manager, a2, a3, a4, pathPtr, a6, a7, resourceHandle);
Log.Verbose($"->{path}");
this.HandleGetResourceHookAcquire(resourceHandle, path);
return resourceHandle;
}
catch (Exception ex)
{
Log.Error(ex, "Exception on ReadResourceAsync hook.");
return this.getResourceAsyncHook.Original(manager, a2, a3, a4, pathPtr, a6, a7);
}
}
private IntPtr GetResourceSyncDetour(IntPtr manager, IntPtr a2, IntPtr a3, IntPtr a4, IntPtr pathPtr, IntPtr a6)
{
try
{
var resourceHandle = this.getResourceSyncHook.Original(manager, a2, a3, a4, pathPtr, a6);
Log.Verbose("GetResourceSync CALL - this:{0} a2:{1} a3:{2} a4:{3} a5:{4} a6:{5} => RET:{6}", manager, a2, a3, a4, pathPtr, a6, resourceHandle);
var path = Marshal.PtrToStringAnsi(pathPtr);
Log.Verbose($"->{path}");
this.HandleGetResourceHookAcquire(resourceHandle, path);
return resourceHandle;
}
catch (Exception ex)
{
Log.Error(ex, "Exception on ReadResourceSync hook.");
return this.getResourceSyncHook.Original(manager, a2, a3, a4, pathPtr, a6);
}
}
private void HandleGetResourceHookAcquire(IntPtr handlePtr, string path)
{
if (FilePathHasInvalidChars(path))
return;
if (this.resourceHookMap.ContainsKey(handlePtr))
{
Log.Verbose($"-> Handle {handlePtr.ToInt64():X}({path}) was cached!");
return;
}
var hookInfo = new ResourceHandleHookInfo
{
Path = path,
};
var hookPath = Path.Combine(this.dalamud.StartInfo.WorkingDirectory, "ResourceHook", path);
if (System.IO.File.Exists(hookPath))
{
hookInfo.DetourFile = new FileStream(hookPath, FileMode.Open);
Log.Verbose("-> Added resource hook detour at {0}", hookPath);
}
this.resourceHookMap.Add(handlePtr, hookInfo);
}
private class ResourceHandleHookInfo
{
public string Path { get; set; }
public Stream DetourFile { get; set; }
}
}
}

View file

@ -1,28 +0,0 @@
using System;
namespace Dalamud.Game.Internal.File
{
/// <summary>
/// The address resolver for the <see cref="ResourceManager"/> class.
/// </summary>
internal class ResourceManagerAddressResolver : BaseAddressResolver
{
/// <summary>
/// Gets the address of the GetResourceAsync method.
/// </summary>
public IntPtr GetResourceAsync { get; private set; }
/// <summary>
/// Gets the address of the GetResourceSync method.
/// </summary>
public IntPtr GetResourceSync { get; private set; }
/// <inheritdoc/>
protected override void Setup64Bit(SigScanner sig)
{
this.GetResourceAsync = sig.ScanText("48 89 5C 24 08 48 89 54 24 10 57 48 83 EC 20 B8 03 00 00 00 48 8B F9 86 82 A1 00 00 00 48 8B 5C 24 38 B8 01 00 00 00 87 83 90 00 00 00 85 C0 74");
this.GetResourceSync = sig.ScanText("48 89 5C 24 08 48 89 6C 24 10 48 89 74 24 18 57 41 54 41 55 41 56 41 57 48 83 EC 30 48 8B F9 49 8B E9 48 83 C1 30 4D 8B F0 4C 8B EA FF 15 CE F6");
// ReadResourceSync = sig.ScanText("48 89 74 24 18 57 48 83 EC 50 8B F2 49 8B F8 41 0F B7 50 02 8B CE E8 ?? ?? 7A FF 0F B7 57 02 8D 42 89 3D 5F 02 00 00 0F 87 60 01 00 00 4C 8D 05");
}
}
}

View file

@ -2,7 +2,7 @@ using System;
using System.Runtime.InteropServices;
using System.Text;
namespace Dalamud.Game.Internal.Libc
namespace Dalamud.Game.Libc
{
/// <summary>
/// This class handles creating cstrings utilizing native game methods.

View file

@ -1,6 +1,8 @@
using System;
namespace Dalamud.Game.Internal.Libc
using Dalamud.Game.Internal;
namespace Dalamud.Game.Libc
{
/// <summary>
/// The address resolver for the <see cref="LibcFunction"/> class.

View file

@ -1,7 +1,7 @@
using System;
using System.Runtime.InteropServices;
namespace Dalamud.Game.Internal.Libc
namespace Dalamud.Game.Libc
{
/// <summary>
/// An address wrapper around the <see cref="StdString"/> class.

View file

@ -2,7 +2,7 @@ using System;
using System.Runtime.InteropServices;
using System.Text;
namespace Dalamud.Game.Internal.Libc
namespace Dalamud.Game.Libc
{
/// <summary>
/// Interation with std::string.

View file

@ -23,6 +23,19 @@ namespace Dalamud.Game
/// </summary>
public float Y;
/// <summary>
/// Initializes a new instance of the <see cref="Position3"/> struct.
/// </summary>
/// <param name="x">The X position.</param>
/// <param name="z">The Z position.</param>
/// <param name="y">The Y position.</param>
public Position3(float x, float z, float y)
{
this.X = x;
this.Z = z;
this.Y = y;
}
/// <summary>
/// Convert this Position3 to a System.Numerics.Vector3.
/// </summary>

View file

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using Dalamud.Data;
@ -21,15 +22,15 @@ namespace Dalamud.Game.Text.SeStringHandling
/// </summary>
public abstract partial class Payload
{
/// <summary>
/// The Lumina instance to use for any necessary data lookups.
/// </summary>
public DataManager DataResolver;
// private for now, since subclasses shouldn't interact with this
// private for now, since subclasses shouldn't interact with this.
// To force-invalidate it, Dirty can be set to true
private byte[] encodedData;
/// <summary>
/// Gets or sets the Lumina instance to use for any necessary data lookups.
/// </summary>
public DataManager DataResolver { get; set; }
/// <summary>
/// Gets the type of this payload.
/// </summary>
@ -233,11 +234,13 @@ namespace Dalamud.Game.Text.SeStringHandling
/// <summary>
/// The start byte of a payload.
/// </summary>
[SuppressMessage("StyleCop.CSharp.NamingRules", "SA1310:Field names should not contain underscore", Justification = "This is prefered.")]
protected const byte START_BYTE = 0x02;
/// <summary>
/// The end byte of a payload.
/// </summary>
[SuppressMessage("StyleCop.CSharp.NamingRules", "SA1310:Field names should not contain underscore", Justification = "This is prefered.")]
protected const byte END_BYTE = 0x03;
/// <summary>

View file

@ -19,17 +19,6 @@ namespace Dalamud.Game.Text.SeStringHandling.Payloads
this.Icon = icon;
}
/// <summary>
/// Initializes a new instance of the <see cref="IconPayload"/> class.
/// Create a Icon payload for the specified icon.
/// </summary>
/// <param name="iconIndex">Index of the icon.</param>
[Obsolete("IconPayload(uint) is deprecated, please use IconPayload(BitmapFontIcon).")]
public IconPayload(uint iconIndex)
: this((BitmapFontIcon)iconIndex)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="IconPayload"/> class.
/// Create a Icon payload for the specified icon.
@ -41,12 +30,6 @@ namespace Dalamud.Game.Text.SeStringHandling.Payloads
/// <inheritdoc/>
public override PayloadType Type => PayloadType.Icon;
/// <summary>
/// Gets the index of the icon.
/// </summary>
[Obsolete("Use IconPayload.Icon")]
public uint IconIndex => (uint)this.Icon;
/// <summary>
/// Gets or sets the icon the payload represents.
/// </summary>

View file

@ -222,7 +222,7 @@ namespace Dalamud.Game.Text.SeStringHandling.Payloads
var c = scale / 100.0f;
var scaledPos = pos * c / 1000.0f;
return ((41.0f / c) * ((scaledPos + 1024.0f) / 2048.0f)) + 1.0f;
return (41.0f / c * ((scaledPos + 1024.0f) / 2048.0f)) + 1.0f;
}
// Created as the inverse of ConvertRawPositionToMapCoordinate(), since no one seemed to have a version of that
@ -230,7 +230,7 @@ namespace Dalamud.Game.Text.SeStringHandling.Payloads
{
var c = scale / 100.0f;
var scaledPos = ((((pos - 1.0f) * c / 41.0f) * 2048.0f) - 1024.0f) / c;
var scaledPos = (((pos - 1.0f) * c / 41.0f * 2048.0f) - 1024.0f) / c;
scaledPos *= 1000.0f;
return (int)scaledPos;

View file

@ -84,12 +84,7 @@ namespace Dalamud.Game.Text.SeStringHandling.Payloads
/// <inheritdoc/>
public override int GetHashCode()
{
// Generated random values.
var hashCode = 1216194372;
hashCode = (hashCode * -1521134295) + this.Type.GetHashCode();
hashCode = (hashCode * -1521134295) + this.chunkType.GetHashCode();
hashCode = (hashCode * -1521134295) + EqualityComparer<byte[]>.Default.GetHashCode(this.data);
return hashCode;
return HashCode.Combine(this.Type, this.chunkType, this.data);
}
/// <inheritdoc/>

View file

@ -1,3 +1,4 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
@ -67,7 +68,7 @@ namespace Dalamud.Game.Text.SeStringHandling.Payloads
// this may change or go away
if (string.IsNullOrEmpty(this.text))
{
return new byte[] { };
return Array.Empty<byte>();
}
return Encoding.UTF8.GetBytes(this.text);

View file

@ -1,6 +1,3 @@
using System;
using System.Linq;
namespace Dalamud.Game.Text
{
/// <summary>
@ -237,77 +234,4 @@ namespace Dalamud.Game.Text
[XivChatTypeInfo("Crossworld Linkshell 8", "cw8", 0xFF1E90FF)]
CrossLinkShell8 = 107,
}
/// <summary>
/// Extension methods for the <see cref="XivChatType"/> type.
/// </summary>
public static class XivChatTypeExtensions
{
/// <summary>
/// Get the InfoAttribute associated with this chat type.
/// </summary>
/// <param name="chatType">The chat type.</param>
/// <returns>The info attribute.</returns>
public static XivChatTypeInfoAttribute GetDetails(this XivChatType chatType)
{
return chatType.GetAttribute<XivChatTypeInfoAttribute>();
}
}
/// <summary>
/// Storage for relevant information associated with the chat type.
/// </summary>
public class XivChatTypeInfoAttribute : Attribute
{
/// <summary>
/// Initializes a new instance of the <see cref="XivChatTypeInfoAttribute"/> class.
/// </summary>
/// <param name="fancyName">The fancy name.</param>
/// <param name="slug">The name slug.</param>
/// <param name="defaultColor">The default color.</param>
internal XivChatTypeInfoAttribute(string fancyName, string slug, uint defaultColor)
{
this.FancyName = fancyName;
this.Slug = slug;
this.DefaultColor = defaultColor;
}
/// <summary>
/// Gets the "fancy" name of the type.
/// </summary>
public string FancyName { get; }
/// <summary>
/// Gets the type name slug or short-form.
/// </summary>
public string Slug { get; }
/// <summary>
/// Gets the type default color.
/// </summary>
public uint DefaultColor { get; }
}
/// <summary>
/// Extension methods for enums.
/// </summary>
public static class EnumExtensions
{
/// <summary>
/// Gets an attribute on an enum.
/// </summary>
/// <typeparam name="TAttribute">The type of attribute to get.</typeparam>
/// <param name="value">The enum value that has an attached attribute.</param>
/// <returns>The attached attribute, if any.</returns>
public static TAttribute GetAttribute<TAttribute>(this Enum value)
where TAttribute : Attribute
{
var type = value.GetType();
var name = Enum.GetName(type, value);
return type.GetField(name) // I prefer to get attributes this way
.GetCustomAttributes(false)
.OfType<TAttribute>()
.SingleOrDefault();
}
}
}

View file

@ -0,0 +1,20 @@
using Dalamud.Utility;
namespace Dalamud.Game.Text
{
/// <summary>
/// Extension methods for the <see cref="XivChatType"/> type.
/// </summary>
public static class XivChatTypeExtensions
{
/// <summary>
/// Get the InfoAttribute associated with this chat type.
/// </summary>
/// <param name="chatType">The chat type.</param>
/// <returns>The info attribute.</returns>
public static XivChatTypeInfoAttribute GetDetails(this XivChatType chatType)
{
return chatType.GetAttribute<XivChatTypeInfoAttribute>();
}
}
}

View file

@ -0,0 +1,39 @@
using System;
namespace Dalamud.Game.Text
{
/// <summary>
/// Storage for relevant information associated with the chat type.
/// </summary>
[AttributeUsage(AttributeTargets.Field)]
public class XivChatTypeInfoAttribute : Attribute
{
/// <summary>
/// Initializes a new instance of the <see cref="XivChatTypeInfoAttribute"/> class.
/// </summary>
/// <param name="fancyName">The fancy name.</param>
/// <param name="slug">The name slug.</param>
/// <param name="defaultColor">The default color.</param>
internal XivChatTypeInfoAttribute(string fancyName, string slug, uint defaultColor)
{
this.FancyName = fancyName;
this.Slug = slug;
this.DefaultColor = defaultColor;
}
/// <summary>
/// Gets the "fancy" name of the type.
/// </summary>
public string FancyName { get; }
/// <summary>
/// Gets the type name slug or short-form.
/// </summary>
public string Slug { get; }
/// <summary>
/// Gets the type default color.
/// </summary>
public uint DefaultColor { get; }
}
}

View file

@ -67,7 +67,7 @@ namespace Dalamud.Hooking.Internal
internal Delegate Delegate { get; }
/// <summary>
/// Gets the hooked assembly.
/// Gets the assembly implementing the hook.
/// </summary>
internal Assembly Assembly { get; }
}

View file

@ -0,0 +1,30 @@
// Font-Awesome - Version 5.0.9
namespace Dalamud.Interface
{
/// <summary>
/// Extension methods for <see cref="FontAwesomeIcon"/>.
/// </summary>
public static class FontAwesomeExtensions
{
/// <summary>
/// Convert the FontAwesomeIcon to a <see cref="char"/> type.
/// </summary>
/// <param name="icon">The icon to convert.</param>
/// <returns>The converted icon.</returns>
public static char ToIconChar(this FontAwesomeIcon icon)
{
return (char)icon;
}
/// <summary>
/// Conver the FontAwesomeIcon to a <see cref="string"/> type.
/// </summary>
/// <param name="icon">The icon to convert.</param>
/// <returns>The converted icon.</returns>
public static string ToIconString(this FontAwesomeIcon icon)
{
return string.Empty + (char)icon;
}
}
}

View file

@ -7047,30 +7047,4 @@ namespace Dalamud.Interface
/// </summary>
Zhihu = 0xF63F,
}
/// <summary>
/// Extension methods for <see cref="FontAwesomeIcon"/>.
/// </summary>
public static class FontAwesomeExtensions
{
/// <summary>
/// Convert the FontAwesomeIcon to a <see cref="char"/> type.
/// </summary>
/// <param name="icon">The icon to convert.</param>
/// <returns>The converted icon.</returns>
public static char ToIconChar(this FontAwesomeIcon icon)
{
return (char)icon;
}
/// <summary>
/// Conver the FontAwesomeIcon to a <see cref="string"/> type.
/// </summary>
/// <param name="icon">The icon to convert.</param>
/// <returns>The converted icon.</returns>
public static string ToIconString(this FontAwesomeIcon icon)
{
return string.Empty + (char)icon;
}
}
}

View file

@ -242,7 +242,7 @@ namespace Dalamud.Interface.Internal
if (string.IsNullOrEmpty(arguments))
this.dalamud.DalamudUi.ToggleDataWindow();
else
this.dalamud.DalamudUi.ToggleDataWindow(arguments);
this.dalamud.DalamudUi.OpenDataWindow(arguments);
}
private void OnOpenLog(string command, string arguments)

View file

@ -9,6 +9,7 @@ using Dalamud.Interface.Windowing;
using Dalamud.Logging;
using Dalamud.Logging.Internal;
using Dalamud.Plugin.Internal;
using Dalamud.Utility;
using ImGuiNET;
using Serilog.Events;

View file

@ -11,6 +11,7 @@ using Dalamud.Game.ClientState;
using Dalamud.Game.Internal.DXGI;
using Dalamud.Hooking;
using Dalamud.Hooking.Internal;
using Dalamud.Utility;
using ImGuiNET;
using ImGuiScene;
using Serilog;
@ -322,9 +323,7 @@ namespace Dalamud.Interface.Internal
private static void ShowFontError(string path)
{
Util.Fatal(
$"One or more files required by XIVLauncher were not found.\nPlease restart and report this error if it occurs again.\n\n{path}",
"Error");
Util.Fatal($"One or more files required by XIVLauncher were not found.\nPlease restart and report this error if it occurs again.\n\n{path}", "Error");
}
private IntPtr PresentDetour(IntPtr swapChain, uint syncInterval, uint presentFlags)

View file

@ -83,7 +83,7 @@ namespace Dalamud.Interface.Internal.Scratchpad
{
var script = CSharpScript.Create(code, options);
var pi = new DalamudPluginInterface(this.dalamud, "Scratch-" + doc.Id, null, PluginLoadReason.Unknown);
var pi = new DalamudPluginInterface(this.dalamud, "Scratch-" + doc.Id, PluginLoadReason.Unknown);
var plugin = script.ContinueWith<IDalamudPlugin>("return new ScratchPlugin() as IDalamudPlugin;")
.RunAsync().GetAwaiter().GetResult().ReturnValue;

View file

@ -131,7 +131,7 @@ public class ScratchPlugin : IDalamudPlugin {
case ParseContext.Dispose:
break;
default:
throw new ArgumentOutOfRangeException();
throw new ArgumentOutOfRangeException(paramName: nameof(input));
}
ctx = ParseContext.None;
@ -156,7 +156,7 @@ public class ScratchPlugin : IDalamudPlugin {
disposeBody += line + "\n";
break;
default:
throw new ArgumentOutOfRangeException();
throw new ArgumentOutOfRangeException(paramName: nameof(input));
}
}

View file

@ -1,6 +1,7 @@
using System.Diagnostics;
using Dalamud.Interface.Windowing;
using Dalamud.Utility;
using ImGuiNET;
namespace Dalamud.Interface.Internal.Windows

View file

@ -4,16 +4,17 @@ using System.Dynamic;
using System.Linq;
using System.Numerics;
using Dalamud.Game;
using Dalamud.Game.ClientState;
using Dalamud.Game.ClientState.Actors.Types;
using Dalamud.Game.ClientState.Actors.Types.NonPlayer;
using Dalamud.Game.ClientState.Structs.JobGauge;
using Dalamud.Game.Internal;
using Dalamud.Game.Internal.Gui.Addon;
using Dalamud.Game.Internal.Gui.Toast;
using Dalamud.Game.Text;
using Dalamud.Interface.Windowing;
using Dalamud.Plugin;
using Dalamud.Utility;
using ImGuiNET;
using ImGuiScene;
using Newtonsoft.Json;
@ -285,11 +286,11 @@ namespace Dalamud.Interface.Internal.Windows
foreach (var valueTuple in debugScannedValue.Value)
{
ImGui.TextUnformatted(
$" {valueTuple.Item1} - 0x{valueTuple.Item2.ToInt64():x}");
$" {valueTuple.ClassName} - 0x{valueTuple.Address.ToInt64():x}");
ImGui.SameLine();
if (ImGui.Button($"C##copyAddress{this.copyButtonIndex++}"))
ImGui.SetClipboardText(valueTuple.Item2.ToInt64().ToString("x"));
ImGui.SetClipboardText(valueTuple.Address.ToInt64().ToString("x"));
}
}
}
@ -468,8 +469,8 @@ namespace Dalamud.Interface.Internal.Windows
private void DrawPluginIPC()
{
#pragma warning disable CS0618 // Type or member is obsolete
var i1 = new DalamudPluginInterface(this.dalamud, "DalamudTestSub", null, PluginLoadReason.Unknown);
var i2 = new DalamudPluginInterface(this.dalamud, "DalamudTestPub", null, PluginLoadReason.Unknown);
var i1 = new DalamudPluginInterface(this.dalamud, "DalamudTestSub", PluginLoadReason.Unknown);
var i2 = new DalamudPluginInterface(this.dalamud, "DalamudTestPub", PluginLoadReason.Unknown);
if (ImGui.Button("Add test sub"))
{

View file

@ -18,6 +18,7 @@ using Dalamud.Plugin;
using Dalamud.Plugin.Internal;
using Dalamud.Plugin.Internal.Exceptions;
using Dalamud.Plugin.Internal.Types;
using Dalamud.Utility;
using ImGuiNET;
using ImGuiScene;

View file

@ -2,6 +2,7 @@ using System;
using System.Linq;
using System.Reflection;
using Dalamud.Game;
using Dalamud.Game.Internal;
using Dalamud.Hooking.Internal;
using Dalamud.Interface.Windowing;

View file

@ -8,6 +8,131 @@ namespace Dalamud.Logging
/// </summary>
public static class PluginLog
{
#region "Log" prefixed Serilog style methods
/// <summary>
/// Log a templated message to the in-game debug log.
/// </summary>
/// <param name="messageTemplate">The message template.</param>
/// <param name="values">Values to log.</param>
public static void Log(string messageTemplate, params object[] values)
=> Serilog.Log.Information($"[{Assembly.GetCallingAssembly().GetName().Name}] {messageTemplate}", values);
/// <summary>
/// Log a templated message to the in-game debug log.
/// </summary>
/// <param name="exception">The exception that caused the error.</param>
/// <param name="messageTemplate">The message template.</param>
/// <param name="values">Values to log.</param>
public static void Log(Exception exception, string messageTemplate, params object[] values)
=> Serilog.Log.Information(exception, $"[{Assembly.GetCallingAssembly().GetName().Name}] {messageTemplate}", values);
/// <summary>
/// Log a templated verbose message to the in-game debug log.
/// </summary>
/// <param name="messageTemplate">The message template.</param>
/// <param name="values">Values to log.</param>
public static void LogVerbose(string messageTemplate, params object[] values)
=> Serilog.Log.Verbose($"[{Assembly.GetCallingAssembly().GetName().Name}] {messageTemplate}", values);
/// <summary>
/// Log a templated verbose message to the in-game debug log.
/// </summary>
/// <param name="exception">The exception that caused the error.</param>
/// <param name="messageTemplate">The message template.</param>
/// <param name="values">Values to log.</param>
public static void LogVerbose(Exception exception, string messageTemplate, params object[] values)
=> Serilog.Log.Verbose(exception, $"[{Assembly.GetCallingAssembly().GetName().Name}] {messageTemplate}", values);
/// <summary>
/// Log a templated debug message to the in-game debug log.
/// </summary>
/// <param name="messageTemplate">The message template.</param>
/// <param name="values">Values to log.</param>
public static void LogDebug(string messageTemplate, params object[] values)
=> Serilog.Log.Debug($"[{Assembly.GetCallingAssembly().GetName().Name}] {messageTemplate}", values);
/// <summary>
/// Log a templated debug message to the in-game debug log.
/// </summary>
/// <param name="exception">The exception that caused the error.</param>
/// <param name="messageTemplate">The message template.</param>
/// <param name="values">Values to log.</param>
public static void LogDebug(Exception exception, string messageTemplate, params object[] values)
=> Serilog.Log.Debug(exception, $"[{Assembly.GetCallingAssembly().GetName().Name}] {messageTemplate}", values);
/// <summary>
/// Log a templated information message to the in-game debug log.
/// </summary>
/// <param name="messageTemplate">The message template.</param>
/// <param name="values">Values to log.</param>
public static void LogInformation(string messageTemplate, params object[] values)
=> Serilog.Log.Information($"[{Assembly.GetCallingAssembly().GetName().Name}] {messageTemplate}", values);
/// <summary>
/// Log a templated information message to the in-game debug log.
/// </summary>
/// <param name="exception">The exception that caused the error.</param>
/// <param name="messageTemplate">The message template.</param>
/// <param name="values">Values to log.</param>
public static void LogInformation(Exception exception, string messageTemplate, params object[] values)
=> Serilog.Log.Information(exception, $"[{Assembly.GetCallingAssembly().GetName().Name}] {messageTemplate}", values);
/// <summary>
/// Log a templated warning message to the in-game debug log.
/// </summary>
/// <param name="messageTemplate">The message template.</param>
/// <param name="values">Values to log.</param>
public static void LogWarning(string messageTemplate, params object[] values)
=> Serilog.Log.Warning($"[{Assembly.GetCallingAssembly().GetName().Name}] {messageTemplate}", values);
/// <summary>
/// Log a templated warning message to the in-game debug log.
/// </summary>
/// <param name="exception">The exception that caused the error.</param>
/// <param name="messageTemplate">The message template.</param>
/// <param name="values">Values to log.</param>
public static void LogWarning(Exception exception, string messageTemplate, params object[] values)
=> Serilog.Log.Warning(exception, $"[{Assembly.GetCallingAssembly().GetName().Name}] {messageTemplate}", values);
/// <summary>
/// Log a templated error message to the in-game debug log.
/// </summary>
/// <param name="messageTemplate">The message template.</param>
/// <param name="values">Values to log.</param>
public static void LogError(string messageTemplate, params object[] values)
=> Serilog.Log.Error($"[{Assembly.GetCallingAssembly().GetName().Name}] {messageTemplate}", values);
/// <summary>
/// Log a templated error message to the in-game debug log.
/// </summary>
/// <param name="exception">The exception that caused the error.</param>
/// <param name="messageTemplate">The message template.</param>
/// <param name="values">Values to log.</param>
public static void LogError(Exception exception, string messageTemplate, params object[] values)
=> Serilog.Log.Error(exception, $"[{Assembly.GetCallingAssembly().GetName().Name}] {messageTemplate}", values);
/// <summary>
/// Log a templated fatal message to the in-game debug log.
/// </summary>
/// <param name="messageTemplate">The message template.</param>
/// <param name="values">Values to log.</param>
public static void LogFatal(string messageTemplate, params object[] values)
=> Serilog.Log.Fatal($"[{Assembly.GetCallingAssembly().GetName().Name}] {messageTemplate}", values);
/// <summary>
/// Log a templated fatal message to the in-game debug log.
/// </summary>
/// <param name="exception">The exception that caused the error.</param>
/// <param name="messageTemplate">The message template.</param>
/// <param name="values">Values to log.</param>
public static void LogFatal(Exception exception, string messageTemplate, params object[] values)
=> Serilog.Log.Fatal(exception, $"[{Assembly.GetCallingAssembly().GetName().Name}] {messageTemplate}", values);
#endregion
#region Serilog style methods
/// <summary>
/// Log a templated verbose message to the in-game debug log.
/// </summary>
@ -109,5 +234,7 @@ namespace Dalamud.Logging
/// <param name="values">Values to log.</param>
public static void Fatal(Exception exception, string messageTemplate, params object[] values)
=> Serilog.Log.Fatal(exception, $"[{Assembly.GetCallingAssembly().GetName().Name}] {messageTemplate}", values);
#endregion
}
}

View file

@ -35,9 +35,8 @@ namespace Dalamud.Plugin
/// </summary>
/// <param name="dalamud">The dalamud instance to expose.</param>
/// <param name="pluginName">The internal name of the plugin.</param>
/// <param name="assemblyLocation">The equivalent of what Assembly.GetExecutingAssembly().Location should return.</param>
/// <param name="reason">The reason the plugin was loaded.</param>
internal DalamudPluginInterface(Dalamud dalamud, string pluginName, string assemblyLocation, PluginLoadReason reason)
internal DalamudPluginInterface(Dalamud dalamud, string pluginName, PluginLoadReason reason)
{
this.CommandManager = dalamud.CommandManager;
this.Framework = dalamud.Framework;
@ -50,7 +49,6 @@ namespace Dalamud.Plugin
this.dalamud = dalamud;
this.pluginName = pluginName;
this.configs = dalamud.PluginManager.PluginConfigs;
this.AssemblyLocation = assemblyLocation;
this.Reason = reason;
this.GeneralChatType = this.dalamud.Configuration.GeneralChatType;
@ -88,11 +86,6 @@ namespace Dalamud.Plugin
/// </summary>
public PluginLoadReason Reason { get; }
/// <summary>
/// Gets the plugin assembly location.
/// </summary>
public string AssemblyLocation { get; private set; }
/// <summary>
/// Gets the directory Dalamud assets are stored in.
/// </summary>
@ -124,7 +117,7 @@ namespace Dalamud.Plugin
public Framework Framework { get; private set; }
/// <summary>
/// Gets the <see cref="UiBuilder">UiBuilder</see> instance which allows you to draw UI into the game via ImGui draw calls.
/// Gets the <see cref="UiBuilder"/> instance which allows you to draw UI into the game via ImGui draw calls.
/// </summary>
public UiBuilder UiBuilder { get; private set; }
@ -172,6 +165,8 @@ namespace Dalamud.Plugin
/// </summary>
internal Action<string, ExpandoObject> AnyPluginIpcAction { get; private set; }
#region Configuration
/// <summary>
/// Save a plugin configuration(inheriting IPluginConfiguration).
/// </summary>
@ -223,6 +218,8 @@ namespace Dalamud.Plugin
/// <returns>directory with path of AppData/XIVLauncher/pluginConfig/PluginInternalName/loc.</returns>
public string GetPluginLocDirectory() => this.configs.GetDirectory(Path.Combine(this.pluginName, "loc"));
#endregion
#region Chat Links
/// <summary>

View file

@ -272,7 +272,7 @@ namespace Dalamud.Plugin.Internal
this.Manifest.Save(this.manifestFile);
}
this.DalamudInterface = new DalamudPluginInterface(this.dalamud, this.pluginAssembly.GetName().Name, this.DllFile.FullName, reason);
this.DalamudInterface = new DalamudPluginInterface(this.dalamud, this.pluginAssembly.GetName().Name, reason);
if (this.IsDev)
{

View file

@ -6,7 +6,7 @@ using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
@ -17,6 +17,7 @@ using Dalamud.Game.Text;
using Dalamud.Logging.Internal;
using Dalamud.Plugin.Internal.Exceptions;
using Dalamud.Plugin.Internal.Types;
using Dalamud.Utility;
using HarmonyLib;
using JetBrains.Annotations;
using Newtonsoft.Json;
@ -359,16 +360,17 @@ namespace Dalamud.Plugin.Internal
// ignored, since the plugin may be loaded already
}
using var client = new WebClient();
var tempZip = new FileInfo(Path.GetTempFileName());
try
{
Log.Debug($"Downloading plugin to {tempZip} from {downloadUrl}");
client.DownloadFile(downloadUrl, tempZip.FullName);
using var client = new HttpClient();
var response = client.GetAsync(downloadUrl).Result;
using var fs = new FileStream(tempZip.FullName, FileMode.CreateNew);
response.Content.CopyToAsync(fs).GetAwaiter().GetResult();
}
catch (WebException ex)
catch (HttpRequestException ex)
{
Log.Error(ex, $"Download of plugin {repoManifest.Name} failed unexpectedly.");
throw;
@ -977,26 +979,21 @@ namespace Dalamud.Plugin.Internal
[SuppressMessage("StyleCop.CSharp.NamingRules", "SA1313:Parameter names should begin with lower-case letter", Justification = "Enforced naming for special injected parameters")]
private static void AssemblyLocationPatch(Assembly __instance, ref string __result)
{
// Assembly.GetExecutingAssembly can return this.
// Check for it as a special case and find the plugin.
if (__result.EndsWith("System.Private.CoreLib.dll", StringComparison.InvariantCultureIgnoreCase))
if (string.IsNullOrEmpty(__result))
{
foreach (var assemblyName in GetStackFrameAssemblyNames())
{
if (PluginLocations.TryGetValue(assemblyName, out var data))
{
__result = data.Location;
return;
break;
}
}
}
else if (string.IsNullOrEmpty(__result))
{
if (PluginLocations.TryGetValue(__instance.FullName, out var data))
{
__result = data.Location;
}
}
__result ??= string.Empty;
Log.Verbose($"Assembly.Location // {__instance.FullName} // {__result}");
}
/// <summary>
@ -1009,26 +1006,21 @@ namespace Dalamud.Plugin.Internal
[SuppressMessage("StyleCop.CSharp.NamingRules", "SA1313:Parameter names should begin with lower-case letter", Justification = "Enforced naming for special injected parameters")]
private static void AssemblyCodeBasePatch(Assembly __instance, ref string __result)
{
// Assembly.GetExecutingAssembly can return this.
// Check for it as a special case and find the plugin.
if (__result.EndsWith("System.Private.CoreLib.dll"))
if (string.IsNullOrEmpty(__result))
{
foreach (var assemblyName in GetStackFrameAssemblyNames())
{
if (PluginLocations.TryGetValue(assemblyName, out var data))
{
__result = data.Location;
return;
__result = data.CodeBase;
break;
}
}
}
else if (string.IsNullOrEmpty(__result))
{
if (PluginLocations.TryGetValue(__instance.FullName, out var data))
{
__result = data.Location;
}
}
__result ??= string.Empty;
Log.Verbose($"Assembly.CodeBase // {__instance.FullName} // {__result}");
}
private static IEnumerable<string> GetStackFrameAssemblyNames()

View file

@ -1,6 +1,6 @@
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using Dalamud.Logging.Internal;
@ -74,11 +74,10 @@ namespace Dalamud.Plugin.Internal
return Task.Run(() =>
{
using var client = new WebClient();
Log.Information($"Fetching repo: {this.PluginMasterUrl}");
var data = client.DownloadString(this.PluginMasterUrl);
using var client = new HttpClient();
using var response = client.GetAsync(this.PluginMasterUrl).Result;
var data = response.Content.ReadAsStringAsync().Result;
var pluginMaster = JsonConvert.DeserializeObject<List<RemotePluginManifest>>(data);
pluginMaster.Sort((pm1, pm2) => pm1.Name.CompareTo(pm2.Name));

View file

@ -4,8 +4,8 @@ using System.Linq;
using System.Text;
using Dalamud.Configuration;
using Dalamud.Plugin;
using Dalamud.Plugin.Internal.Types;
using Dalamud.Utility;
using Newtonsoft.Json;
using Serilog;

View file

@ -0,0 +1,28 @@
using System;
using System.Linq;
namespace Dalamud.Utility
{
/// <summary>
/// Extension methods for enums.
/// </summary>
public static class EnumExtensions
{
/// <summary>
/// Gets an attribute on an enum.
/// </summary>
/// <typeparam name="TAttribute">The type of attribute to get.</typeparam>
/// <param name="value">The enum value that has an attached attribute.</param>
/// <returns>The attached attribute, if any.</returns>
public static TAttribute GetAttribute<TAttribute>(this Enum value)
where TAttribute : Attribute
{
var type = value.GetType();
var name = Enum.GetName(type, value);
return type.GetField(name) // I prefer to get attributes this way
.GetCustomAttributes(false)
.OfType<TAttribute>()
.SingleOrDefault();
}
}
}

View file

@ -0,0 +1,16 @@
namespace Dalamud.Utility
{
/// <summary>
/// Extension methods for strings.
/// </summary>
public static class StringExtensions
{
/// <summary>
/// An extension method to chain usage of string.Format.
/// </summary>
/// <param name="format">Format string.</param>
/// <param name="args">Format arguments.</param>
/// <returns>Formatted string.</returns>
public static string Format(this string format, params object[] args) => string.Format(format, args);
}
}

View file

@ -1,7 +1,7 @@
using ImGuiScene;
using Lumina.Data.Files;
namespace Dalamud.Data.LuminaExtensions
namespace Dalamud.Utility
{
/// <summary>
/// Extensions to <see cref="TexFile"/>.

View file

@ -7,10 +7,11 @@ using System.Text;
using Dalamud.Game;
using Dalamud.Interface;
using Dalamud.Interface.Colors;
using Dalamud.Logging.Internal;
using ImGuiNET;
using Serilog;
namespace Dalamud
namespace Dalamud.Utility
{
/// <summary>
/// Class providing various helper methods for use in Dalamud and plugins.
@ -196,13 +197,5 @@ namespace Dalamud
// TODO: Someone implement GetUTF8String with some IntPtr overloads.
// while(Marshal.ReadByte(0, sz) != 0) { sz++; }
/// <summary>
/// An extension method to chain usage of string.Format.
/// </summary>
/// <param name="format">Format string.</param>
/// <param name="args">Format arguments.</param>
/// <returns>Formatted string.</returns>
public static string Format(this string format, params object[] args) => string.Format(format, args);
}
}

View file

@ -0,0 +1,52 @@
using System.Numerics;
namespace Dalamud.Utility
{
/// <summary>
/// Extension methods for System.Numerics.VectorN and SharpDX.VectorN.
/// </summary>
public static class VectorExtensions
{
/// <summary>
/// Converts a SharpDX vector to System.Numerics.
/// </summary>
/// <param name="vec">Vector to convert.</param>
/// <returns>A converted vector.</returns>
public static Vector2 ToSystem(this SharpDX.Vector2 vec) => new(x: vec.X, y: vec.Y);
/// <summary>
/// Converts a SharpDX vector to System.Numerics.
/// </summary>
/// <param name="vec">Vector to convert.</param>
/// <returns>A converted vector.</returns>
public static Vector3 ToSystem(this SharpDX.Vector3 vec) => new(x: vec.X, y: vec.Y, z: vec.Z);
/// <summary>
/// Converts a SharpDX vector to System.Numerics.
/// </summary>
/// <param name="vec">Vector to convert.</param>
/// <returns>A converted vector.</returns>
public static Vector4 ToSystem(this SharpDX.Vector4 vec) => new(x: vec.X, y: vec.Y, z: vec.Z, w: vec.W);
/// <summary>
/// Converts a System.Numerics vector to SharpDX.
/// </summary>
/// <param name="vec">Vector to convert.</param>
/// <returns>A converted vector.</returns>
public static SharpDX.Vector2 ToSharpDX(this Vector2 vec) => new(x: vec.X, y: vec.Y);
/// <summary>
/// Converts a System.Numerics vector to SharpDX.
/// </summary>
/// <param name="vec">Vector to convert.</param>
/// <returns>A converted vector.</returns>
public static SharpDX.Vector3 ToSharpDX(this Vector3 vec) => new(x: vec.X, y: vec.Y, z: vec.Z);
/// <summary>
/// Converts a System.Numerics vector to SharpDX.
/// </summary>
/// <param name="vec">Vector to convert.</param>
/// <returns>A converted vector.</returns>
public static SharpDX.Vector4 ToSharpDX(this Vector4 vec) => new(x: vec.X, y: vec.Y, z: vec.Z, w: vec.W);
}
}