mirror of
https://github.com/goatcorp/Dalamud.git
synced 2025-12-13 12:14:16 +01:00
feat: add toast queue and event
This commit is contained in:
parent
94d27b2428
commit
5845af4fe3
3 changed files with 90 additions and 12 deletions
|
|
@ -120,6 +120,7 @@ namespace Dalamud.Game.Internal {
|
||||||
private bool HandleFrameworkUpdate(IntPtr framework) {
|
private bool HandleFrameworkUpdate(IntPtr framework) {
|
||||||
try {
|
try {
|
||||||
Gui.Chat.UpdateQueue(this);
|
Gui.Chat.UpdateQueue(this);
|
||||||
|
Gui.Toast.UpdateQueue();
|
||||||
Network.UpdateQueue(this);
|
Network.UpdateQueue(this);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
Log.Error(ex, "Exception while handling Framework::Update hook.");
|
Log.Error(ex, "Exception while handling Framework::Update hook.");
|
||||||
|
|
|
||||||
|
|
@ -452,6 +452,7 @@ namespace Dalamud.Game.Internal.Gui {
|
||||||
|
|
||||||
public void Enable() {
|
public void Enable() {
|
||||||
Chat.Enable();
|
Chat.Enable();
|
||||||
|
Toast.Enable();
|
||||||
PartyFinder.Enable();
|
PartyFinder.Enable();
|
||||||
this.setGlobalBgmHook.Enable();
|
this.setGlobalBgmHook.Enable();
|
||||||
this.handleItemHoverHook.Enable();
|
this.handleItemHoverHook.Enable();
|
||||||
|
|
@ -463,6 +464,7 @@ namespace Dalamud.Game.Internal.Gui {
|
||||||
|
|
||||||
public void Dispose() {
|
public void Dispose() {
|
||||||
Chat.Dispose();
|
Chat.Dispose();
|
||||||
|
Toast.Dispose();
|
||||||
PartyFinder.Dispose();
|
PartyFinder.Dispose();
|
||||||
this.setGlobalBgmHook.Dispose();
|
this.setGlobalBgmHook.Dispose();
|
||||||
this.handleItemHoverHook.Dispose();
|
this.handleItemHoverHook.Dispose();
|
||||||
|
|
|
||||||
|
|
@ -1,28 +1,60 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
using Dalamud.Game.Text.SeStringHandling;
|
using Dalamud.Game.Text.SeStringHandling;
|
||||||
|
using Dalamud.Hooking;
|
||||||
|
|
||||||
namespace Dalamud.Game.Internal.Gui
|
namespace Dalamud.Game.Internal.Gui
|
||||||
{
|
{
|
||||||
public class ToastGui
|
public class ToastGui : IDisposable
|
||||||
{
|
{
|
||||||
|
#region Events
|
||||||
|
|
||||||
|
public delegate void OnToastDelegate(ref SeString message, ref bool isHandled);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Event that will be fired when a toast is sent by the game or a plugin.
|
||||||
|
/// </summary>
|
||||||
|
public event OnToastDelegate OnToast;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Hooks
|
||||||
|
|
||||||
|
private readonly Hook<ShowToastDelegate> showToastHook;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private delegate IntPtr ShowToastDelegate(IntPtr manager, IntPtr text, int layer, byte bool1, byte bool2, int logMessageId);
|
||||||
|
|
||||||
private Dalamud Dalamud { get; }
|
private Dalamud Dalamud { get; }
|
||||||
|
|
||||||
private ToastGuiAddressResolver Address { get; }
|
private ToastGuiAddressResolver Address { get; }
|
||||||
|
|
||||||
private delegate IntPtr ShowToastDelegate(IntPtr manager, IntPtr text, int layer, byte bool1, byte bool2, int logMessageId);
|
private Queue<byte[]> ToastQueue { get; } = new Queue<byte[]>();
|
||||||
|
|
||||||
private readonly ShowToastDelegate showToast;
|
|
||||||
|
|
||||||
public ToastGui(SigScanner scanner, Dalamud dalamud)
|
public ToastGui(SigScanner scanner, Dalamud dalamud)
|
||||||
{
|
{
|
||||||
Dalamud = dalamud;
|
this.Dalamud = dalamud;
|
||||||
|
|
||||||
Address = new ToastGuiAddressResolver();
|
this.Address = new ToastGuiAddressResolver();
|
||||||
Address.Setup(scanner);
|
this.Address.Setup(scanner);
|
||||||
|
|
||||||
this.showToast = Marshal.GetDelegateForFunctionPointer<ShowToastDelegate>(Address.ShowToast);
|
Marshal.GetDelegateForFunctionPointer<ShowToastDelegate>(this.Address.ShowToast);
|
||||||
|
this.showToastHook = new Hook<ShowToastDelegate>(this.Address.ShowToast, new ShowToastDelegate(this.HandleToastDetour));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Enable()
|
||||||
|
{
|
||||||
|
this.showToastHook.Enable();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
this.showToastHook.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -31,7 +63,7 @@ namespace Dalamud.Game.Internal.Gui
|
||||||
/// <param name="message">The message to be shown</param>
|
/// <param name="message">The message to be shown</param>
|
||||||
public void Show(string message)
|
public void Show(string message)
|
||||||
{
|
{
|
||||||
this.Show(Encoding.UTF8.GetBytes(message));
|
this.ToastQueue.Enqueue(Encoding.UTF8.GetBytes(message));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -40,20 +72,63 @@ namespace Dalamud.Game.Internal.Gui
|
||||||
/// <param name="message">The message to be shown</param>
|
/// <param name="message">The message to be shown</param>
|
||||||
public void Show(SeString message)
|
public void Show(SeString message)
|
||||||
{
|
{
|
||||||
this.Show(message.Encode());
|
this.ToastQueue.Enqueue(message.Encode());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Process the toast queue.
|
||||||
|
/// </summary>
|
||||||
|
internal void UpdateQueue()
|
||||||
|
{
|
||||||
|
while (this.ToastQueue.Count > 0)
|
||||||
|
{
|
||||||
|
var message = this.ToastQueue.Dequeue();
|
||||||
|
this.Show(message);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Show(byte[] bytes)
|
private void Show(byte[] bytes)
|
||||||
{
|
{
|
||||||
var manager = Dalamud.Framework.Gui.GetUIModule();
|
var manager = this.Dalamud.Framework.Gui.GetUIModule();
|
||||||
|
|
||||||
|
// terminate the string
|
||||||
|
var terminated = new byte[bytes.Length + 1];
|
||||||
|
Array.Copy(bytes, 0, terminated, 0, bytes.Length);
|
||||||
|
terminated[^1] = 0;
|
||||||
|
|
||||||
unsafe
|
unsafe
|
||||||
{
|
{
|
||||||
fixed (byte* ptr = bytes)
|
fixed (byte* ptr = terminated)
|
||||||
{
|
{
|
||||||
this.showToast(manager, (IntPtr) ptr, 5, 0, 1, 0);
|
this.HandleToastDetour(manager, (IntPtr)ptr, 5, 0, 1, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private IntPtr HandleToastDetour(IntPtr manager, IntPtr text, int layer, byte bool1, byte bool2, int logMessageId)
|
||||||
|
{
|
||||||
|
// get the message as an sestring
|
||||||
|
var bytes = new List<byte>();
|
||||||
|
unsafe
|
||||||
|
{
|
||||||
|
var ptr = (byte*)text;
|
||||||
|
while (*ptr != 0)
|
||||||
|
{
|
||||||
|
bytes.Add(*ptr);
|
||||||
|
ptr += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// call events
|
||||||
|
var isHandled = false;
|
||||||
|
var str = this.Dalamud.SeStringManager.Parse(bytes.ToArray());
|
||||||
|
|
||||||
|
this.OnToast?.Invoke(ref str, ref isHandled);
|
||||||
|
|
||||||
|
// do nothing if handled or show the toast
|
||||||
|
return isHandled
|
||||||
|
? IntPtr.Zero
|
||||||
|
: this.showToastHook.Original(manager, text, layer, bool1, bool2, logMessageId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue