mirror of
https://github.com/goatcorp/Dalamud.git
synced 2025-12-12 10:17:22 +01:00
merge
This commit is contained in:
commit
c925611674
19 changed files with 540 additions and 561 deletions
|
|
@ -1,11 +1,14 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Dalamud.Configuration.Internal;
|
||||
using Dalamud.Interface.Colors;
|
||||
using Dalamud.Interface.Components;
|
||||
using Dalamud.Interface.Internal.Windows.StyleEditor;
|
||||
using Dalamud.Interface.Windowing;
|
||||
using ImGuiNET;
|
||||
using JetBrains.Annotations;
|
||||
using Serilog;
|
||||
|
||||
namespace Dalamud.Interface.Internal.Windows
|
||||
{
|
||||
|
|
@ -14,34 +17,56 @@ namespace Dalamud.Interface.Internal.Windows
|
|||
private ImGuiColorEditFlags alphaFlags = ImGuiColorEditFlags.None;
|
||||
private StyleModel workStyle = StyleModel.DalamudStandard;
|
||||
|
||||
private int currentSel = 0;
|
||||
private string initialStyle;
|
||||
|
||||
public StyleEditorWindow()
|
||||
: base("Dalamud Style Editor")
|
||||
{
|
||||
IsOpen = true;
|
||||
this.IsOpen = true;
|
||||
|
||||
var config = Service<DalamudConfiguration>.Get();
|
||||
config.SavedStyles ??= new List<StyleModel>();
|
||||
this.currentSel = config.SavedStyles.FindIndex(x => x.Name == config.ChosenStyle);
|
||||
|
||||
this.initialStyle = config.ChosenStyle;
|
||||
}
|
||||
|
||||
public override void Draw()
|
||||
{
|
||||
var config = Service<DalamudConfiguration>.Get();
|
||||
|
||||
var style = ImGui.GetStyle();
|
||||
|
||||
var a = 0;
|
||||
ImGui.Text("Choose Style:");
|
||||
if (ImGui.Combo("###styleChooserCombo", ref a, new[] { "Dalamud Standard" }, 1))
|
||||
if (ImGui.Combo("###styleChooserCombo", ref this.currentSel, config.SavedStyles.Select(x => x.Name).ToArray(), 1))
|
||||
{
|
||||
|
||||
var newStyle = config.SavedStyles[this.currentSel];
|
||||
newStyle.Apply();
|
||||
}
|
||||
|
||||
if (ImGui.Button("Add current style"))
|
||||
if (ImGui.Button("Add new style"))
|
||||
{
|
||||
var newStyle = StyleModel.DalamudStandard;
|
||||
newStyle.Name = "New Style";
|
||||
config.SavedStyles.Add(newStyle);
|
||||
|
||||
this.currentSel = config.SavedStyles.Count - 1;
|
||||
|
||||
config.Save();
|
||||
}
|
||||
|
||||
ImGui.SameLine();
|
||||
|
||||
if (ImGuiComponents.IconButton(FontAwesomeIcon.Trash))
|
||||
if (ImGuiComponents.IconButton(FontAwesomeIcon.Trash) && this.currentSel != 0)
|
||||
{
|
||||
this.currentSel--;
|
||||
var newStyle = config.SavedStyles[this.currentSel];
|
||||
newStyle.Apply();
|
||||
|
||||
config.SavedStyles.RemoveAt(this.currentSel + 1);
|
||||
|
||||
config.Save();
|
||||
}
|
||||
|
||||
if (ImGui.IsItemHovered())
|
||||
|
|
@ -64,7 +89,23 @@ namespace Dalamud.Interface.Internal.Windows
|
|||
|
||||
if (ImGuiComponents.IconButton(FontAwesomeIcon.FileImport))
|
||||
{
|
||||
var styleJson = ImGui.GetClipboardText();
|
||||
|
||||
try
|
||||
{
|
||||
var newStyle = StyleModel.FromJsonEncoded(styleJson);
|
||||
|
||||
config.SavedStyles.Add(newStyle);
|
||||
newStyle.Apply();
|
||||
|
||||
this.currentSel = config.SavedStyles.Count - 1;
|
||||
|
||||
config.Save();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(ex, "Could not import style");
|
||||
}
|
||||
}
|
||||
|
||||
if (ImGui.IsItemHovered())
|
||||
|
|
@ -74,7 +115,11 @@ namespace Dalamud.Interface.Internal.Windows
|
|||
|
||||
ImGui.PushItemWidth(ImGui.GetWindowWidth() * 0.50f);
|
||||
|
||||
if (ImGui.BeginTabBar("StyleEditorTabs"))
|
||||
if (this.currentSel == 0)
|
||||
{
|
||||
ImGui.TextColored(ImGuiColors.DalamudRed, "You cannot edit the \"Dalamud Standard\" style. Please add a new style first.");
|
||||
}
|
||||
else if (ImGui.BeginTabBar("StyleEditorTabs"))
|
||||
{
|
||||
if (ImGui.BeginTabItem("Variables"))
|
||||
{
|
||||
|
|
@ -178,14 +223,23 @@ namespace Dalamud.Interface.Internal.Windows
|
|||
|
||||
if (ImGui.Button("Close"))
|
||||
{
|
||||
var newStyle = config.SavedStyles.FirstOrDefault(x => x.Name == this.initialStyle);
|
||||
newStyle?.Apply();
|
||||
|
||||
this.IsOpen = false;
|
||||
}
|
||||
|
||||
ImGui.SameLine();
|
||||
|
||||
if (ImGui.Button("Save and Close"))
|
||||
{
|
||||
config.SavedStyles.Add();
|
||||
config.ChosenStyle = config.SavedStyles[this.currentSel].Name;
|
||||
|
||||
var newStyle = StyleModel.Get();
|
||||
newStyle.Name = config.ChosenStyle;
|
||||
config.SavedStyles[this.currentSel] = newStyle;
|
||||
|
||||
config.Save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -205,6 +205,11 @@ namespace Dalamud.Configuration.Internal
|
|||
/// </summary>
|
||||
public string ChosenStyle { get; set; } = "Dalamud Standard";
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether or not Dalamud RMT filtering should be disabled.
|
||||
/// </summary>
|
||||
public bool DisableRmtFiltering { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Load a configuration from the provided path.
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -151,13 +151,16 @@ namespace Dalamud.Game
|
|||
|
||||
var textVal = message.TextValue;
|
||||
|
||||
var matched = this.rmtRegex.IsMatch(textVal);
|
||||
if (matched)
|
||||
if (!configuration.DisableRmtFiltering)
|
||||
{
|
||||
// This seems to be a RMT ad - let's not show it
|
||||
Log.Debug("Handled RMT ad: " + message.TextValue);
|
||||
isHandled = true;
|
||||
return;
|
||||
var matched = this.rmtRegex.IsMatch(textVal);
|
||||
if (matched)
|
||||
{
|
||||
// This seems to be a RMT ad - let's not show it
|
||||
Log.Debug("Handled RMT ad: " + message.TextValue);
|
||||
isHandled = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (configuration.BadWords != null &&
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ namespace Dalamud.Game.ClientState.Keys
|
|||
// The array is accessed in a way that this limit doesn't appear to exist
|
||||
// but there is other state data past this point, and keys beyond here aren't
|
||||
// generally valid for most things anyway
|
||||
private const int MaxKeyCodeIndex = 0xA0;
|
||||
private const int MaxKeyCode = 0xF0;
|
||||
private readonly IntPtr bufferBase;
|
||||
private readonly IntPtr indexBase;
|
||||
private VirtualKey[] validVirtualKeyCache = null;
|
||||
|
|
@ -104,7 +104,7 @@ namespace Dalamud.Game.ClientState.Keys
|
|||
/// <param name="vkCode">Virtual key code.</param>
|
||||
/// <returns>If the code is valid.</returns>
|
||||
public bool IsVirtualKeyValid(int vkCode)
|
||||
=> vkCode > 0 && vkCode < MaxKeyCodeIndex && this.ConvertVirtualKey(vkCode) != 0;
|
||||
=> this.ConvertVirtualKey(vkCode) != 0;
|
||||
|
||||
/// <inheritdoc cref="IsVirtualKeyValid(int)"/>
|
||||
public bool IsVirtualKeyValid(VirtualKey vkCode)
|
||||
|
|
@ -136,7 +136,7 @@ namespace Dalamud.Game.ClientState.Keys
|
|||
/// <returns>Converted value.</returns>
|
||||
private unsafe byte ConvertVirtualKey(int vkCode)
|
||||
{
|
||||
if (vkCode <= 0 || vkCode >= 240)
|
||||
if (vkCode <= 0 || vkCode >= MaxKeyCode)
|
||||
return 0;
|
||||
|
||||
return *(byte*)(this.indexBase + vkCode);
|
||||
|
|
@ -149,9 +149,6 @@ namespace Dalamud.Game.ClientState.Keys
|
|||
/// <returns>A reference to the indexed array.</returns>
|
||||
private unsafe ref int GetRefValue(int vkCode)
|
||||
{
|
||||
if (vkCode < 0 || vkCode > MaxKeyCodeIndex)
|
||||
throw new ArgumentException($"Keycode state is only valid up to {MaxKeyCodeIndex}");
|
||||
|
||||
vkCode = this.ConvertVirtualKey(vkCode);
|
||||
|
||||
if (vkCode == 0)
|
||||
|
|
|
|||
|
|
@ -134,6 +134,28 @@ namespace Dalamud.Game
|
|||
return baseAddress + index;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Try scanning memory for a signature.
|
||||
/// </summary>
|
||||
/// <param name="baseAddress">The base address to scan from.</param>
|
||||
/// <param name="size">The amount of bytes to scan.</param>
|
||||
/// <param name="signature">The signature to search for.</param>
|
||||
/// <param name="result">The offset, if found.</param>
|
||||
/// <returns>true if the signature was found.</returns>
|
||||
public static bool TryScan(IntPtr baseAddress, int size, string signature, out IntPtr result)
|
||||
{
|
||||
try
|
||||
{
|
||||
result = Scan(baseAddress, size, signature);
|
||||
return true;
|
||||
}
|
||||
catch (KeyNotFoundException)
|
||||
{
|
||||
result = IntPtr.Zero;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Scan for a .data address using a .text function.
|
||||
/// This is intended to be used with IDA sigs.
|
||||
|
|
@ -160,6 +182,29 @@ namespace Dalamud.Game
|
|||
return IntPtr.Add(instrAddr, Marshal.ReadInt32(instrAddr) + 4);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Try scanning for a .data address using a .text function.
|
||||
/// This is intended to be used with IDA sigs.
|
||||
/// Place your cursor on the line calling a static address, and create and IDA sig.
|
||||
/// </summary>
|
||||
/// <param name="signature">The signature of the function using the data.</param>
|
||||
/// <param name="result">An IntPtr to the static memory location, if found.</param>
|
||||
/// <param name="offset">The offset from function start of the instruction using the data.</param>
|
||||
/// <returns>true if the signature was found.</returns>
|
||||
public bool TryGetStaticAddressFromSig(string signature, out IntPtr result, int offset = 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
result = this.GetStaticAddressFromSig(signature, offset);
|
||||
return true;
|
||||
}
|
||||
catch (KeyNotFoundException)
|
||||
{
|
||||
result = IntPtr.Zero;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Scan for a byte signature in the .data section.
|
||||
/// </summary>
|
||||
|
|
@ -175,6 +220,26 @@ namespace Dalamud.Game
|
|||
return scanRet;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Try scanning for a byte signature in the .data section.
|
||||
/// </summary>
|
||||
/// <param name="signature">The signature.</param>
|
||||
/// <param name="result">The real offset of the signature, if found.</param>
|
||||
/// <returns>true if the signature was found.</returns>
|
||||
public bool TryScanData(string signature, out IntPtr result)
|
||||
{
|
||||
try
|
||||
{
|
||||
result = this.ScanData(signature);
|
||||
return true;
|
||||
}
|
||||
catch (KeyNotFoundException)
|
||||
{
|
||||
result = IntPtr.Zero;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Scan for a byte signature in the whole module search area.
|
||||
/// </summary>
|
||||
|
|
@ -190,6 +255,26 @@ namespace Dalamud.Game
|
|||
return scanRet;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Try scanning for a byte signature in the whole module search area.
|
||||
/// </summary>
|
||||
/// <param name="signature">The signature.</param>
|
||||
/// <param name="result">The real offset of the signature, if found.</param>
|
||||
/// <returns>true if the signature was found.</returns>
|
||||
public bool TryScanModule(string signature, out IntPtr result)
|
||||
{
|
||||
try
|
||||
{
|
||||
result = this.ScanModule(signature);
|
||||
return true;
|
||||
}
|
||||
catch (KeyNotFoundException)
|
||||
{
|
||||
result = IntPtr.Zero;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resolve a RVA address.
|
||||
/// </summary>
|
||||
|
|
@ -224,6 +309,26 @@ namespace Dalamud.Game
|
|||
return scanRet;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Try scanning for a byte signature in the .text section.
|
||||
/// </summary>
|
||||
/// <param name="signature">The signature.</param>
|
||||
/// <param name="result">The real offset of the signature, if found.</param>
|
||||
/// <returns>true if the signature was found.</returns>
|
||||
public bool TryScanText(string signature, out IntPtr result)
|
||||
{
|
||||
try
|
||||
{
|
||||
result = this.ScanText(signature);
|
||||
return true;
|
||||
}
|
||||
catch (KeyNotFoundException)
|
||||
{
|
||||
result = IntPtr.Zero;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Free the memory of the copied module search area on object disposal, if applicable.
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -340,8 +340,7 @@ namespace Dalamud.Interface.Internal
|
|||
|
||||
if (configuration.SavedStyles == null || configuration.SavedStyles.All(x => x.Name != StyleModel.DalamudStandard.Name))
|
||||
{
|
||||
configuration.SavedStyles = new List<StyleModel>();
|
||||
configuration.SavedStyles.Add(StyleModel.DalamudStandard);
|
||||
configuration.SavedStyles = new List<StyleModel> { StyleModel.DalamudStandard };
|
||||
configuration.ChosenStyle = StyleModel.DalamudStandard.Name;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@ using Dalamud.Plugin.Internal.Types;
|
|||
using Dalamud.Utility;
|
||||
using ImGuiNET;
|
||||
using ImGuiScene;
|
||||
using Microsoft.VisualBasic;
|
||||
|
||||
namespace Dalamud.Interface.Internal.Windows
|
||||
{
|
||||
|
|
@ -56,7 +55,7 @@ namespace Dalamud.Interface.Internal.Windows
|
|||
private string[] testerImagePaths = new string[5];
|
||||
private string testerIconPath = string.Empty;
|
||||
|
||||
private TextureWrap?[]? testerImages;
|
||||
private TextureWrap?[] testerImages;
|
||||
private TextureWrap? testerIcon;
|
||||
|
||||
private bool testerError = false;
|
||||
|
|
@ -76,9 +75,8 @@ namespace Dalamud.Interface.Internal.Windows
|
|||
private List<AvailablePluginUpdate> pluginListUpdatable = new();
|
||||
private bool hasDevPlugins = false;
|
||||
|
||||
private bool downloadingIcons = false;
|
||||
private Dictionary<string, (bool IsDownloaded, TextureWrap?[]? Textures)> pluginImagesMap = new();
|
||||
private Dictionary<string, (bool IsDownloaded, TextureWrap? Texture)> pluginIconMap = new();
|
||||
private Dictionary<string, TextureWrap?> pluginIconMap = new();
|
||||
private Dictionary<string, TextureWrap?[]> pluginImagesMap = new();
|
||||
|
||||
private string searchText = string.Empty;
|
||||
|
||||
|
|
@ -197,8 +195,6 @@ namespace Dalamud.Interface.Internal.Windows
|
|||
{
|
||||
this.pluginIconMap.Clear();
|
||||
this.pluginImagesMap.Clear();
|
||||
|
||||
this.DownloadPluginIcons();
|
||||
}
|
||||
|
||||
private static string? GetPluginIconUrl(PluginManifest manifest, bool isThirdParty, bool isTesting)
|
||||
|
|
@ -209,10 +205,18 @@ namespace Dalamud.Interface.Internal.Windows
|
|||
return MainRepoImageUrl.Format(isTesting ? "testing" : "plugins", manifest.InternalName, "icon.png");
|
||||
}
|
||||
|
||||
private static List<string>? GetPluginImageUrls(PluginManifest manifest, bool isThirdParty, bool isTesting)
|
||||
private static List<string?> GetPluginImageUrls(PluginManifest manifest, bool isThirdParty, bool isTesting)
|
||||
{
|
||||
if (isThirdParty)
|
||||
{
|
||||
if (manifest.ImageUrls.Count > 5)
|
||||
{
|
||||
Log.Warning($"Plugin {manifest.InternalName} has too many images");
|
||||
return manifest.ImageUrls.Take(5).ToList();
|
||||
}
|
||||
|
||||
return manifest.ImageUrls;
|
||||
}
|
||||
|
||||
var output = new List<string>();
|
||||
for (var i = 1; i <= 5; i++)
|
||||
|
|
@ -223,6 +227,36 @@ namespace Dalamud.Interface.Internal.Windows
|
|||
return output;
|
||||
}
|
||||
|
||||
private static FileInfo? GetPluginIconFileInfo(LocalPlugin? plugin)
|
||||
{
|
||||
var pluginDir = plugin.DllFile.Directory;
|
||||
|
||||
var devUrl = new FileInfo(Path.Combine(pluginDir.FullName, "images", "icon.png"));
|
||||
if (devUrl.Exists)
|
||||
return devUrl;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static List<FileInfo?> GetPluginImageFileInfos(LocalPlugin? plugin)
|
||||
{
|
||||
var pluginDir = plugin.DllFile.Directory;
|
||||
var output = new List<FileInfo>();
|
||||
for (var i = 1; i <= 5; i++)
|
||||
{
|
||||
var devUrl = new FileInfo(Path.Combine(pluginDir.FullName, "images", $"image{i}.png"));
|
||||
if (devUrl.Exists)
|
||||
{
|
||||
output.Add(devUrl);
|
||||
continue;
|
||||
}
|
||||
|
||||
output.Add(null);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
private void DrawHeader()
|
||||
{
|
||||
var style = ImGui.GetStyle();
|
||||
|
|
@ -555,7 +589,6 @@ namespace Dalamud.Interface.Internal.Windows
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: Technically, we really should just load images from a devplugin folder
|
||||
private void DrawImageTester()
|
||||
{
|
||||
var sectionSize = ImGuiHelpers.GlobalScale * 66;
|
||||
|
|
@ -800,7 +833,7 @@ namespace Dalamud.Interface.Internal.Windows
|
|||
return ready;
|
||||
}
|
||||
|
||||
private bool DrawPluginCollapsingHeader(string label, PluginManifest manifest, bool trouble, bool updateAvailable, bool isNew, Action drawContextMenuAction, int index)
|
||||
private bool DrawPluginCollapsingHeader(string label, LocalPlugin? plugin, PluginManifest manifest, bool isThirdParty, bool trouble, bool updateAvailable, bool isNew, Action drawContextMenuAction, int index)
|
||||
{
|
||||
ImGui.Separator();
|
||||
|
||||
|
|
@ -837,12 +870,20 @@ namespace Dalamud.Interface.Internal.Windows
|
|||
|
||||
ImGui.SetCursorPos(startCursor);
|
||||
|
||||
var hasIcon = this.pluginIconMap.TryGetValue(manifest.InternalName, out var icon);
|
||||
|
||||
var iconTex = this.defaultIcon;
|
||||
if (hasIcon && icon.IsDownloaded && icon.Texture != null)
|
||||
var hasIcon = this.pluginIconMap.TryGetValue(manifest.InternalName, out var cachedIconTex);
|
||||
if (!hasIcon)
|
||||
{
|
||||
iconTex = icon.Texture;
|
||||
this.pluginIconMap.Add(manifest.InternalName, null);
|
||||
Task.Run(async () => await this.DownloadPluginIconAsync(plugin, manifest, isThirdParty));
|
||||
}
|
||||
else if (cachedIconTex != null)
|
||||
{
|
||||
iconTex = cachedIconTex;
|
||||
}
|
||||
else
|
||||
{
|
||||
// nothing
|
||||
}
|
||||
|
||||
var iconSize = ImGuiHelpers.ScaledVector2(64, 64);
|
||||
|
|
@ -868,13 +909,14 @@ namespace Dalamud.Interface.Internal.Windows
|
|||
ImGui.SameLine();
|
||||
|
||||
var cursor = ImGui.GetCursorPos();
|
||||
|
||||
// Name
|
||||
ImGui.Text(label);
|
||||
|
||||
// Download count
|
||||
var downloadCountText = manifest.DownloadCount > 0
|
||||
? Locs.PluginBody_AuthorWithDownloadCount(manifest.Author, manifest.DownloadCount)
|
||||
: Locs.PluginBody_AuthorWithDownloadCountUnavailable(manifest.Author);
|
||||
? Locs.PluginBody_AuthorWithDownloadCount(manifest.Author, manifest.DownloadCount)
|
||||
: Locs.PluginBody_AuthorWithDownloadCountUnavailable(manifest.Author);
|
||||
|
||||
ImGui.SameLine();
|
||||
ImGui.TextColored(ImGuiColors.DalamudGrey3, downloadCountText);
|
||||
|
|
@ -927,7 +969,8 @@ namespace Dalamud.Interface.Internal.Windows
|
|||
|
||||
ImGui.PushID($"available{index}{manifest.InternalName}");
|
||||
|
||||
if (this.DrawPluginCollapsingHeader(label, manifest, false, false, !wasSeen, () => this.DrawAvailablePluginContextMenu(manifest), index))
|
||||
var isThirdParty = manifest.SourceRepo.IsThirdParty;
|
||||
if (this.DrawPluginCollapsingHeader(label, null, manifest, isThirdParty, false, false, !wasSeen, () => this.DrawAvailablePluginContextMenu(manifest), index))
|
||||
{
|
||||
if (!wasSeen)
|
||||
configuration.SeenPluginInternalName.Add(manifest.InternalName);
|
||||
|
|
@ -996,7 +1039,7 @@ namespace Dalamud.Interface.Internal.Windows
|
|||
|
||||
ImGuiHelpers.ScaledDummy(5);
|
||||
|
||||
if (this.DrawPluginImages(manifest, index, manifest.SourceRepo.IsThirdParty))
|
||||
if (this.DrawPluginImages(null, manifest, isThirdParty, index))
|
||||
ImGuiHelpers.ScaledDummy(5);
|
||||
|
||||
ImGui.Unindent();
|
||||
|
|
@ -1124,15 +1167,22 @@ namespace Dalamud.Interface.Internal.Windows
|
|||
}
|
||||
|
||||
// Outdated API level
|
||||
if (plugin.Manifest.DalamudApiLevel < PluginManager.DalamudApiLevel)
|
||||
if (plugin.IsOutdated)
|
||||
{
|
||||
label += Locs.PluginTitleMod_OutdatedError;
|
||||
trouble = true;
|
||||
}
|
||||
|
||||
// Banned
|
||||
if (plugin.IsBanned)
|
||||
{
|
||||
label += Locs.PluginTitleMod_BannedError;
|
||||
trouble = true;
|
||||
}
|
||||
|
||||
ImGui.PushID($"installed{index}{plugin.Manifest.InternalName}");
|
||||
|
||||
if (this.DrawPluginCollapsingHeader(label, plugin.Manifest, trouble, availablePluginUpdate != default, false, () => this.DrawInstalledPluginContextMenu(plugin), index))
|
||||
if (this.DrawPluginCollapsingHeader(label, plugin, plugin.Manifest, plugin.Manifest.IsThirdParty, trouble, availablePluginUpdate != default, false, () => this.DrawInstalledPluginContextMenu(plugin), index))
|
||||
{
|
||||
if (!this.WasPluginSeen(plugin.Manifest.InternalName))
|
||||
configuration.SeenPluginInternalName.Add(plugin.Manifest.InternalName);
|
||||
|
|
@ -1154,7 +1204,7 @@ namespace Dalamud.Interface.Internal.Windows
|
|||
ImGui.SameLine();
|
||||
ImGui.TextColored(ImGuiColors.DalamudGrey3, downloadText);
|
||||
|
||||
var isThirdParty = !string.IsNullOrEmpty(manifest.InstalledFromUrl);
|
||||
var isThirdParty = manifest.IsThirdParty;
|
||||
|
||||
// Installed from
|
||||
if (plugin.IsDev)
|
||||
|
|
@ -1174,13 +1224,20 @@ namespace Dalamud.Interface.Internal.Windows
|
|||
ImGui.TextWrapped(manifest.Description);
|
||||
}
|
||||
|
||||
if (plugin.Manifest.DalamudApiLevel < PluginManager.DalamudApiLevel)
|
||||
if (plugin.IsOutdated)
|
||||
{
|
||||
ImGui.PushStyleColor(ImGuiCol.Text, ImGuiColors.DalamudRed);
|
||||
ImGui.TextWrapped(Locs.PluginBody_Outdated);
|
||||
ImGui.PopStyleColor();
|
||||
}
|
||||
|
||||
if (plugin.IsBanned)
|
||||
{
|
||||
ImGui.PushStyleColor(ImGuiCol.Text, ImGuiColors.DalamudRed);
|
||||
ImGui.TextWrapped(Locs.PluginBody_Banned);
|
||||
ImGui.PopStyleColor();
|
||||
}
|
||||
|
||||
// Available commands (if loaded)
|
||||
if (plugin.IsLoaded)
|
||||
{
|
||||
|
|
@ -1201,6 +1258,7 @@ namespace Dalamud.Interface.Internal.Windows
|
|||
// Controls
|
||||
this.DrawPluginControlButton(plugin);
|
||||
this.DrawDevPluginButtons(plugin);
|
||||
this.DrawDeletePluginButton(plugin);
|
||||
this.DrawVisitRepoUrlButton(plugin.Manifest.RepoUrl);
|
||||
|
||||
if (availablePluginUpdate != default)
|
||||
|
|
@ -1217,9 +1275,8 @@ namespace Dalamud.Interface.Internal.Windows
|
|||
|
||||
ImGuiHelpers.ScaledDummy(5);
|
||||
|
||||
this.DrawPluginImages(manifest, index, isThirdParty);
|
||||
|
||||
ImGuiHelpers.ScaledDummy(5);
|
||||
if (this.DrawPluginImages(plugin, manifest, isThirdParty, index))
|
||||
ImGuiHelpers.ScaledDummy(5);
|
||||
|
||||
ImGui.Unindent();
|
||||
}
|
||||
|
|
@ -1263,7 +1320,7 @@ namespace Dalamud.Interface.Internal.Windows
|
|||
var disabled = this.updateStatus == OperationStatus.InProgress || this.installStatus == OperationStatus.InProgress;
|
||||
|
||||
// Disable everything if the plugin is outdated
|
||||
disabled = disabled || (plugin.Manifest.DalamudApiLevel < PluginManager.DalamudApiLevel && !configuration.LoadAllApiLevels);
|
||||
disabled = disabled || (plugin.IsOutdated && !configuration.LoadAllApiLevels) || plugin.IsBanned;
|
||||
|
||||
if (plugin.State == PluginState.InProgress)
|
||||
{
|
||||
|
|
@ -1411,7 +1468,6 @@ namespace Dalamud.Interface.Internal.Windows
|
|||
private void DrawDevPluginButtons(LocalPlugin localPlugin)
|
||||
{
|
||||
var configuration = Service<DalamudConfiguration>.Get();
|
||||
var pluginManager = Service<PluginManager>.Get();
|
||||
|
||||
if (localPlugin is LocalDevPlugin plugin)
|
||||
{
|
||||
|
|
@ -1454,33 +1510,40 @@ namespace Dalamud.Interface.Internal.Windows
|
|||
{
|
||||
ImGui.SetTooltip(Locs.PluginButtonToolTip_AutomaticReloading);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Delete
|
||||
if (plugin.State == PluginState.Unloaded)
|
||||
private void DrawDeletePluginButton(LocalPlugin plugin)
|
||||
{
|
||||
var unloaded = plugin.State == PluginState.Unloaded;
|
||||
var showButton = unloaded && (plugin.IsDev || plugin.IsOutdated || plugin.IsBanned);
|
||||
|
||||
if (!showButton)
|
||||
return;
|
||||
|
||||
var pluginManager = Service<PluginManager>.Get();
|
||||
|
||||
ImGui.SameLine();
|
||||
if (ImGuiComponents.IconButton(FontAwesomeIcon.TrashAlt))
|
||||
{
|
||||
try
|
||||
{
|
||||
ImGui.SameLine();
|
||||
if (ImGuiComponents.IconButton(FontAwesomeIcon.TrashAlt))
|
||||
{
|
||||
try
|
||||
{
|
||||
plugin.DllFile.Delete();
|
||||
pluginManager.RemovePlugin(plugin);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(ex, $"Plugin installer threw an error during removal of {plugin.Name}");
|
||||
|
||||
this.errorModalMessage = Locs.ErrorModal_DeleteFail(plugin.Name);
|
||||
this.errorModalDrawing = true;
|
||||
this.errorModalOnNextFrame = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (ImGui.IsItemHovered())
|
||||
{
|
||||
ImGui.SetTooltip(Locs.PluginBody_DeleteDevPlugin);
|
||||
}
|
||||
plugin.DllFile.Delete();
|
||||
pluginManager.RemovePlugin(plugin);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(ex, $"Plugin installer threw an error during removal of {plugin.Name}");
|
||||
|
||||
this.errorModalMessage = Locs.ErrorModal_DeleteFail(plugin.Name);
|
||||
this.errorModalDrawing = true;
|
||||
this.errorModalOnNextFrame = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (ImGui.IsItemHovered())
|
||||
{
|
||||
ImGui.SetTooltip(Locs.PluginButtonToolTip_DeletePlugin);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1510,18 +1573,18 @@ namespace Dalamud.Interface.Internal.Windows
|
|||
}
|
||||
}
|
||||
|
||||
private bool DrawPluginImages(PluginManifest manifest, int index, bool isThirdParty)
|
||||
private bool DrawPluginImages(LocalPlugin? plugin, PluginManifest manifest, bool isThirdParty, int index)
|
||||
{
|
||||
if (!this.pluginImagesMap.TryGetValue(manifest.InternalName, out var images))
|
||||
var hasImages = this.pluginImagesMap.TryGetValue(manifest.InternalName, out var imageTextures);
|
||||
if (!hasImages)
|
||||
{
|
||||
Task.Run(() => this.DownloadPluginImagesAsync(manifest, isThirdParty));
|
||||
this.pluginImagesMap.Add(manifest.InternalName, Array.Empty<TextureWrap>());
|
||||
Task.Run(async () => await this.DownloadPluginImagesAsync(plugin, manifest, isThirdParty));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!images.IsDownloaded)
|
||||
return false;
|
||||
|
||||
if (images.Textures == null)
|
||||
if (imageTextures.Length == 0)
|
||||
return false;
|
||||
|
||||
const float thumbFactor = 2.7f;
|
||||
|
|
@ -1534,42 +1597,39 @@ namespace Dalamud.Interface.Internal.Windows
|
|||
|
||||
if (ImGui.BeginChild($"plugin{index}ImageScrolling", new Vector2(width - (70 * ImGuiHelpers.GlobalScale), (PluginImageHeight / thumbFactor) + scrollBarSize), false, ImGuiWindowFlags.HorizontalScrollbar | ImGuiWindowFlags.NoScrollWithMouse | ImGuiWindowFlags.NoBackground))
|
||||
{
|
||||
if (images.Textures != null && images.Textures is { Length: > 0 })
|
||||
for (var i = 0; i < imageTextures.Length; i++)
|
||||
{
|
||||
for (var i = 0; i < images.Textures.Length; i++)
|
||||
var image = imageTextures[i];
|
||||
if (image == null)
|
||||
continue;
|
||||
|
||||
ImGui.PushStyleVar(ImGuiStyleVar.PopupBorderSize, 0);
|
||||
ImGui.PushStyleVar(ImGuiStyleVar.WindowPadding, Vector2.Zero);
|
||||
ImGui.PushStyleVar(ImGuiStyleVar.FramePadding, Vector2.Zero);
|
||||
|
||||
var popupId = $"plugin{index}image{i}";
|
||||
if (ImGui.BeginPopup(popupId))
|
||||
{
|
||||
var popupId = $"plugin{index}image{i}";
|
||||
var image = images.Textures[i];
|
||||
if (image == null)
|
||||
continue;
|
||||
if (ImGui.ImageButton(image.ImGuiHandle, new Vector2(image.Width, image.Height)))
|
||||
ImGui.CloseCurrentPopup();
|
||||
|
||||
ImGui.PushStyleVar(ImGuiStyleVar.PopupBorderSize, 0);
|
||||
ImGui.PushStyleVar(ImGuiStyleVar.WindowPadding, Vector2.Zero);
|
||||
ImGui.PushStyleVar(ImGuiStyleVar.FramePadding, Vector2.Zero);
|
||||
ImGui.EndPopup();
|
||||
}
|
||||
|
||||
if (ImGui.BeginPopup(popupId))
|
||||
{
|
||||
if (ImGui.ImageButton(image.ImGuiHandle, new Vector2(image.Width, image.Height)))
|
||||
ImGui.CloseCurrentPopup();
|
||||
ImGui.PopStyleVar(3);
|
||||
|
||||
ImGui.EndPopup();
|
||||
}
|
||||
ImGui.PushStyleVar(ImGuiStyleVar.FramePadding, Vector2.Zero);
|
||||
|
||||
ImGui.PopStyleVar(3);
|
||||
if (ImGui.ImageButton(image.ImGuiHandle, ImGuiHelpers.ScaledVector2(image.Width / thumbFactor, image.Height / thumbFactor)))
|
||||
ImGui.OpenPopup(popupId);
|
||||
|
||||
ImGui.PushStyleVar(ImGuiStyleVar.FramePadding, Vector2.Zero);
|
||||
ImGui.PopStyleVar();
|
||||
|
||||
if (ImGui.ImageButton(image.ImGuiHandle, ImGuiHelpers.ScaledVector2(image.Width / thumbFactor, image.Height / thumbFactor)))
|
||||
ImGui.OpenPopup(popupId);
|
||||
|
||||
ImGui.PopStyleVar();
|
||||
|
||||
if (i < images.Textures.Length - 1)
|
||||
{
|
||||
ImGui.SameLine();
|
||||
ImGuiHelpers.ScaledDummy(5);
|
||||
ImGui.SameLine();
|
||||
}
|
||||
if (i < imageTextures.Length - 1)
|
||||
{
|
||||
ImGui.SameLine();
|
||||
ImGuiHelpers.ScaledDummy(5);
|
||||
ImGui.SameLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1612,8 +1672,6 @@ namespace Dalamud.Interface.Internal.Windows
|
|||
.ToList();
|
||||
this.pluginListUpdatable = pluginManager.UpdatablePlugins.ToList();
|
||||
this.ResortPlugins();
|
||||
|
||||
this.DownloadPluginIcons();
|
||||
}
|
||||
|
||||
private void OnInstalledPluginsChanged()
|
||||
|
|
@ -1624,8 +1682,6 @@ namespace Dalamud.Interface.Internal.Windows
|
|||
this.pluginListUpdatable = pluginManager.UpdatablePlugins.ToList();
|
||||
this.hasDevPlugins = this.pluginListInstalled.Any(plugin => plugin.IsDev);
|
||||
this.ResortPlugins();
|
||||
|
||||
this.DownloadPluginIcons();
|
||||
}
|
||||
|
||||
private void ResortPlugins()
|
||||
|
|
@ -1705,133 +1761,173 @@ namespace Dalamud.Interface.Internal.Windows
|
|||
this.errorModalOnNextFrame = true;
|
||||
}
|
||||
|
||||
private void DownloadPluginIcons()
|
||||
private async Task DownloadPluginIconAsync(LocalPlugin? plugin, PluginManifest manifest, bool isThirdParty)
|
||||
{
|
||||
if (this.downloadingIcons)
|
||||
var interfaceManager = Service<InterfaceManager>.Get();
|
||||
var pluginManager = Service<PluginManager>.Get();
|
||||
|
||||
static bool ValidateIcon(TextureWrap icon, string loc)
|
||||
{
|
||||
Log.Error("Already downloading icons, skipping...");
|
||||
if (icon == null)
|
||||
return false;
|
||||
|
||||
if (icon.Height > PluginIconHeight || icon.Width > PluginIconWidth)
|
||||
{
|
||||
Log.Error($"Icon at {loc} was not of the correct resolution.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (icon.Height != icon.Width)
|
||||
{
|
||||
Log.Error($"Icon at {loc} was not square.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (plugin != null && plugin.IsDev)
|
||||
{
|
||||
var file = GetPluginIconFileInfo(plugin);
|
||||
if (file != null)
|
||||
{
|
||||
Log.Verbose($"Fetching icon for {manifest.InternalName} from {file.FullName}");
|
||||
|
||||
var icon = interfaceManager.LoadImage(file.FullName);
|
||||
|
||||
if (!ValidateIcon(icon, file.FullName))
|
||||
return;
|
||||
|
||||
this.pluginIconMap[manifest.InternalName] = icon;
|
||||
Log.Verbose($"Plugin icon for {manifest.InternalName} loaded from disk");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
this.downloadingIcons = true;
|
||||
|
||||
var pluginManager = Service<PluginManager>.Get();
|
||||
|
||||
Log.Verbose("Start downloading plugin icons...");
|
||||
|
||||
Task.Run(async () =>
|
||||
{
|
||||
var plugins = pluginManager.AvailablePlugins.Select(x => x);
|
||||
|
||||
foreach (var pluginManifest in plugins)
|
||||
{
|
||||
var useTesting = pluginManager.UseTesting(pluginManifest);
|
||||
|
||||
if (!this.pluginIconMap.ContainsKey(pluginManifest.InternalName))
|
||||
await this.DownloadPluginIconAsync(pluginManifest, useTesting);
|
||||
}
|
||||
}).ContinueWith(t =>
|
||||
{
|
||||
Log.Verbose($"Icon download finished, faulted: {t.IsFaulted}");
|
||||
this.downloadingIcons = false;
|
||||
});
|
||||
}
|
||||
|
||||
private async Task DownloadPluginIconAsync(RemotePluginManifest manifest, bool isTesting)
|
||||
{
|
||||
var interfaceManager = Service<InterfaceManager>.Get();
|
||||
|
||||
Log.Verbose($"Downloading icon for {manifest.InternalName}");
|
||||
this.pluginIconMap.Add(manifest.InternalName, (false, null));
|
||||
|
||||
var url = GetPluginIconUrl(manifest, manifest.SourceRepo.IsThirdParty, isTesting);
|
||||
|
||||
Log.Verbose($"Icon from {url}");
|
||||
|
||||
var useTesting = pluginManager.UseTesting(manifest);
|
||||
var url = GetPluginIconUrl(manifest, isThirdParty, useTesting);
|
||||
if (url != null)
|
||||
{
|
||||
Log.Verbose($"Downloading icon for {manifest.InternalName} from {url}");
|
||||
|
||||
var data = await this.httpClient.GetAsync(url);
|
||||
if (data.StatusCode == HttpStatusCode.NotFound)
|
||||
return;
|
||||
|
||||
data.EnsureSuccessStatusCode();
|
||||
|
||||
var icon = interfaceManager.LoadImage(await data.Content.ReadAsByteArrayAsync());
|
||||
|
||||
if (icon != null)
|
||||
{
|
||||
if (icon.Height > PluginIconHeight || icon.Width > PluginIconWidth)
|
||||
{
|
||||
Log.Error($"Icon at {manifest.IconUrl} was not of the correct resolution.");
|
||||
return;
|
||||
}
|
||||
if (!ValidateIcon(icon, url))
|
||||
return;
|
||||
|
||||
if (icon.Height != icon.Width)
|
||||
{
|
||||
Log.Error($"Icon at {manifest.IconUrl} was not square.");
|
||||
return;
|
||||
}
|
||||
this.pluginIconMap[manifest.InternalName] = icon;
|
||||
Log.Verbose($"Plugin icon for {manifest.InternalName} downloaded");
|
||||
|
||||
this.pluginIconMap[manifest.InternalName] = (true, icon);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
Log.Verbose($"Icon for {manifest.InternalName} is not available");
|
||||
}
|
||||
|
||||
private async Task DownloadPluginImagesAsync(PluginManifest manifest, bool isThirdParty)
|
||||
private async Task DownloadPluginImagesAsync(LocalPlugin? plugin, PluginManifest manifest, bool isThirdParty)
|
||||
{
|
||||
var interfaceManager = Service<InterfaceManager>.Get();
|
||||
var pluginManager = Service<PluginManager>.Get();
|
||||
|
||||
Log.Verbose($"Downloading images for {manifest.InternalName}");
|
||||
|
||||
this.pluginImagesMap.Add(manifest.InternalName, (false, null));
|
||||
|
||||
var urls = GetPluginImageUrls(manifest, isThirdParty, pluginManager.UseTesting(manifest));
|
||||
var didAny = false;
|
||||
|
||||
if (urls != null)
|
||||
static bool ValidateImage(TextureWrap image, string loc)
|
||||
{
|
||||
if (urls.Count > 5)
|
||||
if (image == null)
|
||||
return false;
|
||||
|
||||
if (image.Height != PluginImageHeight || image.Width != PluginImageWidth)
|
||||
{
|
||||
Log.Error($"Plugin {manifest.InternalName} has too many images.");
|
||||
return;
|
||||
Log.Error($"Image at {loc} was not of the correct resolution.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (plugin != null && plugin.IsDev)
|
||||
{
|
||||
var files = GetPluginImageFileInfos(plugin);
|
||||
if (files != null)
|
||||
{
|
||||
var didAny = false;
|
||||
var pluginImages = new TextureWrap[files.Count];
|
||||
for (var i = 0; i < files.Count; i++)
|
||||
{
|
||||
var file = files[i];
|
||||
|
||||
if (file == null)
|
||||
continue;
|
||||
|
||||
Log.Verbose($"Loading image{i + 1} for {manifest.InternalName} from {file.FullName}");
|
||||
|
||||
var image = interfaceManager.LoadImage(await File.ReadAllBytesAsync(file.FullName));
|
||||
|
||||
if (!ValidateImage(image, file.FullName))
|
||||
continue;
|
||||
|
||||
Log.Verbose($"Plugin image{i + 1} for {manifest.InternalName} loaded from disk");
|
||||
pluginImages[i] = image;
|
||||
didAny = true;
|
||||
}
|
||||
|
||||
if (didAny)
|
||||
{
|
||||
Log.Verbose($"Plugin images for {manifest.InternalName} loaded from disk");
|
||||
this.pluginImagesMap[manifest.InternalName] = pluginImages;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Dev plugins are loaded from disk only
|
||||
return;
|
||||
}
|
||||
|
||||
var useTesting = pluginManager.UseTesting(manifest);
|
||||
var urls = GetPluginImageUrls(manifest, isThirdParty, useTesting);
|
||||
if (urls != null)
|
||||
{
|
||||
var didAny = false;
|
||||
var pluginImages = new TextureWrap[urls.Count];
|
||||
for (var i = 0; i < urls.Count; i++)
|
||||
{
|
||||
var data = await this.httpClient.GetAsync(urls[i]);
|
||||
var url = urls[i];
|
||||
|
||||
Serilog.Log.Information($"Download from {urls[i]}");
|
||||
Log.Verbose($"Downloading image{i + 1} for {manifest.InternalName} from {url}");
|
||||
|
||||
var data = await this.httpClient.GetAsync(url);
|
||||
|
||||
if (data.StatusCode == HttpStatusCode.NotFound)
|
||||
continue;
|
||||
|
||||
data.EnsureSuccessStatusCode();
|
||||
|
||||
var image = interfaceManager.LoadImage(await data.Content.ReadAsByteArrayAsync());
|
||||
|
||||
if (image == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (image.Height != PluginImageHeight || image.Width != PluginImageWidth)
|
||||
{
|
||||
Log.Error($"Image at {urls[i]} was not of the correct resolution.");
|
||||
return;
|
||||
}
|
||||
|
||||
didAny = true;
|
||||
if (!ValidateImage(image, url))
|
||||
continue;
|
||||
|
||||
Log.Verbose($"Plugin image{i + 1} for {manifest.InternalName} downloaded");
|
||||
pluginImages[i] = image;
|
||||
didAny = true;
|
||||
}
|
||||
|
||||
if (didAny)
|
||||
{
|
||||
this.pluginImagesMap[manifest.InternalName] = (true, pluginImages);
|
||||
Log.Verbose($"Plugin images for {manifest.InternalName} downloaded");
|
||||
this.pluginImagesMap[manifest.InternalName] = pluginImages;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Log.Verbose($"Plugin images for {manifest.InternalName} downloaded");
|
||||
Log.Verbose($"Images for {manifest.InternalName} are not available");
|
||||
}
|
||||
|
||||
[SuppressMessage("StyleCop.CSharp.OrderingRules", "SA1201:Elements should appear in the correct order", Justification = "Disregard here")]
|
||||
|
|
@ -1919,6 +2015,8 @@ namespace Dalamud.Interface.Internal.Windows
|
|||
|
||||
public static string PluginTitleMod_OutdatedError => Loc.Localize("InstallerOutdatedError", " (outdated)");
|
||||
|
||||
public static string PluginTitleMod_BannedError => Loc.Localize("InstallerOutdatedError", " (banned)");
|
||||
|
||||
public static string PluginTitleMod_New => Loc.Localize("InstallerNewPlugin ", " New!");
|
||||
|
||||
#endregion
|
||||
|
|
@ -1953,6 +2051,8 @@ namespace Dalamud.Interface.Internal.Windows
|
|||
|
||||
public static string PluginBody_Outdated => Loc.Localize("InstallerOutdatedPluginBody ", "This plugin is outdated and incompatible at the moment. Please wait for it to be updated by its author.");
|
||||
|
||||
public static string PluginBody_Banned => Loc.Localize("InstallerBannedPluginBody ", "This plugin version is banned and not available at the moment. Please wait for it to be updated by its author.");
|
||||
|
||||
#endregion
|
||||
|
||||
#region Plugin buttons
|
||||
|
|
|
|||
|
|
@ -59,6 +59,7 @@ namespace Dalamud.Interface.Internal.Windows
|
|||
private bool printPluginsWelcomeMsg;
|
||||
private bool autoUpdatePlugins;
|
||||
private bool doButtonsSystemMenu;
|
||||
private bool disableRmtFiltering;
|
||||
|
||||
#region Experimental
|
||||
|
||||
|
|
@ -99,6 +100,7 @@ namespace Dalamud.Interface.Internal.Windows
|
|||
this.printPluginsWelcomeMsg = configuration.PrintPluginsWelcomeMsg;
|
||||
this.autoUpdatePlugins = configuration.AutoUpdatePlugins;
|
||||
this.doButtonsSystemMenu = configuration.DoButtonsSystemMenu;
|
||||
this.disableRmtFiltering = configuration.DisableRmtFiltering;
|
||||
|
||||
this.languages = Localization.ApplicableLangCodes.Prepend("en").ToArray();
|
||||
try
|
||||
|
|
@ -238,6 +240,9 @@ namespace Dalamud.Interface.Internal.Windows
|
|||
|
||||
ImGui.Checkbox(Loc.Localize("DalamudSettingsSystemMenu", "Dalamud buttons in system menu"), ref this.doButtonsSystemMenu);
|
||||
ImGui.TextColored(this.hintTextColor, Loc.Localize("DalamudSettingsSystemMenuMsgHint", "Add buttons for Dalamud plugins and settings to the system menu."));
|
||||
|
||||
ImGui.Checkbox(Loc.Localize("DalamudSettingsDisableRmtFiltering", "Disable RMT Filtering"), ref this.disableRmtFiltering);
|
||||
ImGui.TextColored(this.hintTextColor, Loc.Localize("DalamudSettingsDisableRmtFilteringMsgHint", "Disable dalamud's built-in RMT ad filtering."));
|
||||
}
|
||||
|
||||
private void DrawLookAndFeelTab()
|
||||
|
|
@ -689,6 +694,7 @@ namespace Dalamud.Interface.Internal.Windows
|
|||
configuration.PrintPluginsWelcomeMsg = this.printPluginsWelcomeMsg;
|
||||
configuration.AutoUpdatePlugins = this.autoUpdatePlugins;
|
||||
configuration.DoButtonsSystemMenu = this.doButtonsSystemMenu;
|
||||
configuration.DisableRmtFiltering = this.disableRmtFiltering;
|
||||
|
||||
configuration.Save();
|
||||
|
||||
|
|
|
|||
22
Dalamud/Plugin/Internal/Exceptions/BannedPluginException.cs
Normal file
22
Dalamud/Plugin/Internal/Exceptions/BannedPluginException.cs
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
namespace Dalamud.Plugin.Internal.Exceptions
|
||||
{
|
||||
/// <summary>
|
||||
/// This represents a banned plugin that attempted an operation.
|
||||
/// </summary>
|
||||
internal class BannedPluginException : PluginException
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="BannedPluginException"/> class.
|
||||
/// </summary>
|
||||
/// <param name="message">The message describing the invalid operation.</param>
|
||||
public BannedPluginException(string message)
|
||||
{
|
||||
this.Message = message;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the message describing the invalid operation.
|
||||
/// </summary>
|
||||
public override string Message { get; }
|
||||
}
|
||||
}
|
||||
|
|
@ -145,19 +145,17 @@ namespace Dalamud.Plugin.Internal
|
|||
return;
|
||||
}
|
||||
|
||||
var notificationManager = Service<NotificationManager>.Get();
|
||||
|
||||
try
|
||||
{
|
||||
this.Reload();
|
||||
Service<NotificationManager>.Get()
|
||||
.AddNotification(
|
||||
$"The DevPlugin '{this.Name} was reloaded successfully.", "Plugin reloaded!", NotificationType.Success);
|
||||
notificationManager.AddNotification($"The DevPlugin '{this.Name} was reloaded successfully.", "Plugin reloaded!", NotificationType.Success);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(ex, "DevPlugin reload failed.");
|
||||
Service<NotificationManager>.Get()
|
||||
.AddNotification(
|
||||
$"The DevPlugin '{this.Name} could not be reloaded.", "Plugin reload failed!", NotificationType.Error);
|
||||
notificationManager.AddNotification($"The DevPlugin '{this.Name} could not be reloaded.", "Plugin reload failed!", NotificationType.Error);
|
||||
}
|
||||
},
|
||||
this.fileWatcherTokenSource.Token);
|
||||
|
|
|
|||
|
|
@ -86,10 +86,8 @@ namespace Dalamud.Plugin.Internal
|
|||
|
||||
var assemblyVersion = this.pluginAssembly.GetName().Version;
|
||||
|
||||
// Files that may or may not exist
|
||||
// Although it is conditionally used here, we need to set the initial value regardless.
|
||||
this.manifestFile = LocalPluginManifest.GetManifestFile(this.DllFile);
|
||||
this.disabledFile = LocalPluginManifest.GetDisabledFile(this.DllFile);
|
||||
this.testingFile = LocalPluginManifest.GetTestingFile(this.DllFile);
|
||||
|
||||
// If the parameter manifest was null
|
||||
if (manifest == null)
|
||||
|
|
@ -108,28 +106,32 @@ namespace Dalamud.Plugin.Internal
|
|||
|
||||
// Save the manifest to disk so there won't be any problems later.
|
||||
// We'll update the name property after it can be retrieved from the instance.
|
||||
var manifestFile = LocalPluginManifest.GetManifestFile(this.DllFile);
|
||||
this.Manifest.Save(manifestFile);
|
||||
this.Manifest.Save(this.manifestFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.Manifest = manifest;
|
||||
}
|
||||
|
||||
// This bit converts from ".disabled" functionality to using the manifest.
|
||||
// This converts from the ".disabled" file feature to the manifest instead.
|
||||
this.disabledFile = LocalPluginManifest.GetDisabledFile(this.DllFile);
|
||||
if (this.disabledFile.Exists)
|
||||
{
|
||||
this.Manifest.Disabled = true;
|
||||
this.disabledFile.Delete();
|
||||
}
|
||||
|
||||
// This bit converts from ".testing" functionality to using the manifest.
|
||||
// This converts from the ".testing" file feature to the manifest instead.
|
||||
this.testingFile = LocalPluginManifest.GetTestingFile(this.DllFile);
|
||||
if (this.testingFile.Exists)
|
||||
{
|
||||
this.Manifest.Testing = true;
|
||||
this.testingFile.Delete();
|
||||
}
|
||||
|
||||
var pluginManager = Service<PluginManager>.Get();
|
||||
this.IsBanned = pluginManager.IsManifestBanned(this.Manifest);
|
||||
|
||||
this.SaveManifest();
|
||||
}
|
||||
|
||||
|
|
@ -157,7 +159,7 @@ namespace Dalamud.Plugin.Internal
|
|||
/// Gets the AssemblyName plugin, populated during <see cref="Load(PluginLoadReason, bool)"/>.
|
||||
/// </summary>
|
||||
/// <returns>Plugin type.</returns>
|
||||
public AssemblyName AssemblyName { get; private set; } = null;
|
||||
public AssemblyName? AssemblyName { get; private set; } = null;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the plugin name, directly from the plugin or if it is not loaded from the manifest.
|
||||
|
|
@ -174,11 +176,21 @@ namespace Dalamud.Plugin.Internal
|
|||
/// </summary>
|
||||
public bool IsDisabled => this.Manifest.Disabled;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this plugin's API level is out of date.
|
||||
/// </summary>
|
||||
public bool IsOutdated => this.Manifest.DalamudApiLevel < PluginManager.DalamudApiLevel;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the plugin is for testing use only.
|
||||
/// </summary>
|
||||
public bool IsTesting => this.Manifest.IsTestingExclusive || this.Manifest.Testing;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this plugin has been banned.
|
||||
/// </summary>
|
||||
public bool IsBanned { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this plugin is dev plugin.
|
||||
/// </summary>
|
||||
|
|
@ -223,6 +235,9 @@ namespace Dalamud.Plugin.Internal
|
|||
throw new InvalidPluginOperationException($"Unable to load {this.Name}, unload previously faulted, restart Dalamud");
|
||||
}
|
||||
|
||||
if (pluginManager.IsManifestBanned(this.Manifest))
|
||||
throw new BannedPluginException($"Unable to load {this.Name}, banned");
|
||||
|
||||
if (this.Manifest.ApplicableVersion < startInfo.GameVersion)
|
||||
throw new InvalidPluginOperationException($"Unable to load {this.Name}, no applicable version");
|
||||
|
||||
|
|
@ -255,7 +270,9 @@ namespace Dalamud.Plugin.Internal
|
|||
{
|
||||
var manifestFile = LocalPluginManifest.GetManifestFile(this.DllFile);
|
||||
if (manifestFile.Exists)
|
||||
{
|
||||
this.Manifest = LocalPluginManifest.Load(manifestFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -475,6 +475,9 @@ namespace Dalamud.Plugin.Internal
|
|||
var dllFile = LocalPluginManifest.GetPluginFile(outputDir, repoManifest);
|
||||
var manifestFile = LocalPluginManifest.GetManifestFile(dllFile);
|
||||
|
||||
// We need to save the repoManifest due to how the repo fills in some fields that authors are not expected to use.
|
||||
File.WriteAllText(manifestFile.FullName, JsonConvert.SerializeObject(repoManifest, Formatting.Indented));
|
||||
|
||||
// Reload as a local manifest, add some attributes, and save again.
|
||||
var manifest = LocalPluginManifest.Load(manifestFile);
|
||||
|
||||
|
|
@ -545,26 +548,31 @@ namespace Dalamud.Plugin.Internal
|
|||
}
|
||||
catch (InvalidPluginException)
|
||||
{
|
||||
PluginLocations.Remove(plugin.AssemblyName.FullName);
|
||||
PluginLocations.Remove(plugin.AssemblyName?.FullName ?? string.Empty);
|
||||
throw;
|
||||
}
|
||||
catch (BannedPluginException)
|
||||
{
|
||||
// Out of date plugins get added so they can be updated.
|
||||
Log.Information($"Plugin was banned, adding anyways: {dllFile.Name}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (plugin.IsDev)
|
||||
{
|
||||
// Dev plugins always get added to the list so they can be fiddled with in the UI
|
||||
Log.Information(ex, $"Dev plugin failed to load, adding anyways: {dllFile.Name}");
|
||||
Log.Information(ex, $"Dev plugin failed to load, adding anyways: {dllFile.Name}");
|
||||
plugin.Disable(); // Disable here, otherwise you can't enable+load later
|
||||
}
|
||||
else if (plugin.Manifest.DalamudApiLevel < DalamudApiLevel)
|
||||
else if (plugin.IsOutdated)
|
||||
{
|
||||
// Out of date plugins get added so they can be updated.
|
||||
Log.Information(ex, $"Plugin was outdated, adding anyways: {dllFile.Name}");
|
||||
Log.Information(ex, $"Plugin was outdated, adding anyways: {dllFile.Name}");
|
||||
// plugin.Disable(); // Don't disable, or it gets deleted next boot.
|
||||
}
|
||||
else
|
||||
{
|
||||
PluginLocations.Remove(plugin.AssemblyName.FullName);
|
||||
PluginLocations.Remove(plugin.AssemblyName?.FullName ?? string.Empty);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
|
@ -584,7 +592,7 @@ namespace Dalamud.Plugin.Internal
|
|||
throw new InvalidPluginOperationException($"Unable to remove {plugin.Name}, not unloaded");
|
||||
|
||||
this.InstalledPlugins = this.InstalledPlugins.Remove(plugin);
|
||||
PluginLocations.Remove(plugin.AssemblyName.FullName);
|
||||
PluginLocations.Remove(plugin.AssemblyName?.FullName ?? string.Empty);
|
||||
|
||||
this.NotifyInstalledPluginsChanged();
|
||||
this.NotifyAvailablePluginsChanged();
|
||||
|
|
@ -936,7 +944,12 @@ namespace Dalamud.Plugin.Internal
|
|||
return true;
|
||||
}
|
||||
|
||||
private bool IsManifestBanned(PluginManifest manifest)
|
||||
/// <summary>
|
||||
/// Determine if a plugin has been banned by inspecting the manifest.
|
||||
/// </summary>
|
||||
/// <param name="manifest">Manifest to inspect.</param>
|
||||
/// <returns>A value indicating whether the plugin/manifest has been banned.</returns>
|
||||
public bool IsManifestBanned(PluginManifest manifest)
|
||||
{
|
||||
return this.bannedPlugins.Any(ban => ban.Name == manifest.InternalName && ban.AssemblyVersion == manifest.AssemblyVersion);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,10 +24,17 @@ namespace Dalamud.Plugin.Internal.Types
|
|||
|
||||
/// <summary>
|
||||
/// Gets or sets the 3rd party repo URL that this plugin was installed from. Used to display where the plugin was
|
||||
/// sourced from on the installed plugin view. This should not be included in the plugin master.
|
||||
/// sourced from on the installed plugin view. This should not be included in the plugin master. This value is null
|
||||
/// when installed from the main repo.
|
||||
/// </summary>
|
||||
public string InstalledFromUrl { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this manifest is associated with a plugin that was installed from a third party
|
||||
/// repo. Unless the manifest has been manually modified, this is determined by the InstalledFromUrl being null.
|
||||
/// </summary>
|
||||
public bool IsThirdParty => !string.IsNullOrEmpty(this.InstalledFromUrl);
|
||||
|
||||
/// <summary>
|
||||
/// Save a plugin manifest to file.
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -1,173 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>16.0</VCProjectVersion>
|
||||
<ProjectGuid>{9FDA9A5C-50C6-4333-8DCE-DFEB89363F2A}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>DalamudDebugStub</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
<OutDir>$(SolutionDir)bin\</OutDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
<OutDir>$(SolutionDir)bin\</OutDir>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;DALAMUDDEBUGSTUB_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableUAC>false</EnableUAC>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_DEBUG;DALAMUDDEBUGSTUB_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableUAC>false</EnableUAC>
|
||||
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;dbghelp.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;DALAMUDDEBUGSTUB_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableUAC>false</EnableUAC>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>NDEBUG;DALAMUDDEBUGSTUB_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableUAC>false</EnableUAC>
|
||||
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;dbghelp.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="framework.h" />
|
||||
<ClInclude Include="pch.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="dllmain.cpp" />
|
||||
<ClCompile Include="pch.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;c++;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="framework.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="pch.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="dllmain.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="pch.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
@ -1,118 +0,0 @@
|
|||
// dllmain.cpp : Defines the entry point for the DLL application.
|
||||
#include "pch.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <tchar.h>
|
||||
#include <cstdio>
|
||||
#include <DbgHelp.h>
|
||||
|
||||
bool isExcept = false;
|
||||
|
||||
LONG WINAPI
|
||||
VectoredHandler(
|
||||
struct _EXCEPTION_POINTERS* ExceptionInfo
|
||||
)
|
||||
{
|
||||
PEXCEPTION_RECORD Record = ExceptionInfo->ExceptionRecord;
|
||||
|
||||
if (Record->ExceptionCode != EXCEPTION_ACCESS_VIOLATION)
|
||||
return EXCEPTION_CONTINUE_SEARCH;
|
||||
|
||||
//ListProcessThreads(GetCurrentProcessId());
|
||||
|
||||
if (!isExcept)
|
||||
{
|
||||
isExcept = true;
|
||||
|
||||
TCHAR pszMessage[1024] = { 0 };
|
||||
_stprintf_s(pszMessage, _T("An internal error in Dalamud or a FFXIV plugin occured.\nThe game must close.\n\nDo you wish to save troubleshooting information?\n\nReasoning: 0x%x at 0x%x"), Record->ExceptionCode, Record->ExceptionAddress);
|
||||
|
||||
auto res = MessageBox(NULL, pszMessage, L"Dalamud", MB_YESNO | MB_ICONERROR | MB_TOPMOST);
|
||||
|
||||
if (res == IDYES)
|
||||
{
|
||||
TCHAR fileName[255] = { 0 };
|
||||
|
||||
char* pValue;
|
||||
size_t len;
|
||||
errno_t err = _dupenv_s(&pValue, &len, "APPDATA");
|
||||
|
||||
wchar_t* fullPath = new wchar_t[2048];
|
||||
|
||||
// Convert char* string to a wchar_t* string.
|
||||
size_t convertedChars = 0;
|
||||
mbstowcs_s(&convertedChars, fullPath, strlen(pValue) + 1, pValue, _TRUNCATE);
|
||||
|
||||
SYSTEMTIME t;
|
||||
GetSystemTime(&t);
|
||||
_stprintf_s(fileName, _T("MD-%d-%d-%d-%d-%d-%d.dmp"), t.wYear, t.wMonth, t.wDay, t.wHour, t.wMinute, t.wSecond);
|
||||
|
||||
_tcscat_s(fullPath, 2048, TEXT("\\XIVLauncher\\"));
|
||||
_tcscat_s(fullPath, 2048, fileName);
|
||||
|
||||
HANDLE hFile = CreateFileW(fullPath, GENERIC_READ | GENERIC_WRITE,
|
||||
0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
|
||||
if ((hFile != NULL) && (hFile != INVALID_HANDLE_VALUE))
|
||||
{
|
||||
// Create the minidump
|
||||
|
||||
MINIDUMP_EXCEPTION_INFORMATION mdei;
|
||||
|
||||
mdei.ThreadId = GetCurrentThreadId();
|
||||
mdei.ExceptionPointers = ExceptionInfo;
|
||||
mdei.ClientPointers = TRUE;
|
||||
|
||||
BOOL rv = MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(),
|
||||
hFile, (MINIDUMP_TYPE)(MiniDumpWithFullMemory | MiniDumpWithDataSegs | MiniDumpWithThreadInfo), (ExceptionInfo != 0) ? &mdei : 0, 0, 0);
|
||||
|
||||
if (!rv)
|
||||
_stprintf_s(pszMessage, _T("MiniDumpWriteDump failed. Error: %u \n"), GetLastError());
|
||||
else
|
||||
_stprintf_s(pszMessage, _T("Minidump created.\n"));
|
||||
|
||||
MessageBox(NULL, pszMessage, L"Dalamud", MB_OK | MB_ICONINFORMATION | MB_TOPMOST);
|
||||
|
||||
// Close the file
|
||||
|
||||
CloseHandle(hFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
_tprintf(_T("CreateFile failed. Error: %u \n"), GetLastError());
|
||||
}
|
||||
}
|
||||
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
PCONTEXT Context;
|
||||
|
||||
Context = ExceptionInfo->ContextRecord;
|
||||
#ifdef _AMD64_
|
||||
Context->Rip++;
|
||||
#else
|
||||
Context->Eip++;
|
||||
#endif
|
||||
return EXCEPTION_CONTINUE_EXECUTION;
|
||||
}
|
||||
|
||||
BOOL APIENTRY DllMain( HMODULE hModule,
|
||||
DWORD ul_reason_for_call,
|
||||
LPVOID lpReserved
|
||||
)
|
||||
{
|
||||
switch (ul_reason_for_call)
|
||||
{
|
||||
case DLL_PROCESS_ATTACH:
|
||||
|
||||
AddVectoredExceptionHandler(99, VectoredHandler);
|
||||
break;
|
||||
case DLL_THREAD_ATTACH:
|
||||
case DLL_THREAD_DETACH:
|
||||
case DLL_PROCESS_DETACH:
|
||||
break;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
|
||||
// Windows Header Files
|
||||
#include <windows.h>
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
// pch.cpp: source file corresponding to the pre-compiled header
|
||||
|
||||
#include "pch.h"
|
||||
|
||||
// When you are using pre-compiled headers, this source file is necessary for compilation to succeed.
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
// pch.h: This is a precompiled header file.
|
||||
// Files listed below are compiled only once, improving build performance for future builds.
|
||||
// This also affects IntelliSense performance, including code completion and many code browsing features.
|
||||
// However, files listed here are ALL re-compiled if any one of them is updated between builds.
|
||||
// Do not add files here that you will be updating frequently as this negates the performance advantage.
|
||||
|
||||
#ifndef PCH_H
|
||||
#define PCH_H
|
||||
|
||||
// add headers that you want to pre-compile here
|
||||
#include "framework.h"
|
||||
|
||||
#endif //PCH_H
|
||||
Loading…
Add table
Add a link
Reference in a new issue