feat: handle tells
This commit is contained in:
parent
d844b000e5
commit
027a9946d7
@ -36,6 +36,15 @@ internal sealed unsafe class Chat : IDisposable {
|
|||||||
[Signature("44 8B 89 ?? ?? ?? ?? 4C 8B C1")]
|
[Signature("44 8B 89 ?? ?? ?? ?? 4C 8B C1")]
|
||||||
private readonly delegate* unmanaged<void*, int, IntPtr> _getTellHistory = null!;
|
private readonly delegate* unmanaged<void*, int, IntPtr> _getTellHistory = null!;
|
||||||
|
|
||||||
|
[Signature("E8 ?? ?? ?? ?? B8 ?? ?? ?? ?? 48 8D 4D 50")]
|
||||||
|
private readonly delegate* unmanaged<RaptureLogModule*, ushort, Utf8String*, Utf8String*, ulong, ushort, byte, int, byte, void> _printTell = null!;
|
||||||
|
|
||||||
|
[Signature("E8 ?? ?? ?? ?? 48 8D 4C 24 ?? E8 ?? ?? ?? ?? 48 8D 8C 24 ?? ?? ?? ?? E8 ?? ?? ?? ?? B0 01")]
|
||||||
|
private readonly delegate* unmanaged<IntPtr, ulong, ushort, Utf8String*, Utf8String*, byte, ulong, byte> _sendTell = null!;
|
||||||
|
|
||||||
|
[Signature("E8 ?? ?? ?? ?? F6 43 0A 40")]
|
||||||
|
private readonly delegate* unmanaged<Framework*, IntPtr> _getNetworkModule = null!;
|
||||||
|
|
||||||
// Hooks
|
// Hooks
|
||||||
|
|
||||||
private delegate byte ChatLogRefreshDelegate(IntPtr log, ushort eventId, AtkValue* value);
|
private delegate byte ChatLogRefreshDelegate(IntPtr log, ushort eventId, AtkValue* value);
|
||||||
@ -84,7 +93,7 @@ internal sealed unsafe class Chat : IDisposable {
|
|||||||
|
|
||||||
// Events
|
// Events
|
||||||
|
|
||||||
internal delegate void ChatActivatedEventDelegate(string? input, ChannelSwitchInfo info);
|
internal delegate void ChatActivatedEventDelegate(string? input, ChannelSwitchInfo info, TellReason? reason, TellTarget? target);
|
||||||
|
|
||||||
internal event ChatActivatedEventDelegate? Activated;
|
internal event ChatActivatedEventDelegate? Activated;
|
||||||
|
|
||||||
@ -279,7 +288,7 @@ internal sealed unsafe class Chat : IDisposable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
this.Activated?.Invoke(null, info);
|
this.Activated?.Invoke(null, info, TellReason.Reply, null);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
PluginLog.LogError(ex, "Error in chat Activated event");
|
PluginLog.LogError(ex, "Error in chat Activated event");
|
||||||
}
|
}
|
||||||
@ -315,7 +324,7 @@ internal sealed unsafe class Chat : IDisposable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
this.Activated?.Invoke(eventInput, new ChannelSwitchInfo(null));
|
this.Activated?.Invoke(eventInput, new ChannelSwitchInfo(null), null, null);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
PluginLog.LogError(ex, "Error in chat Activated event");
|
PluginLog.LogError(ex, "Error in chat Activated event");
|
||||||
}
|
}
|
||||||
@ -393,7 +402,12 @@ internal sealed unsafe class Chat : IDisposable {
|
|||||||
|
|
||||||
private byte SetChatLogTellTargetDetour(IntPtr a1, Utf8String* name, Utf8String* a3, ushort world, ulong contentId, ushort reason, byte a7) {
|
private byte SetChatLogTellTargetDetour(IntPtr a1, Utf8String* name, Utf8String* a3, ushort world, ulong contentId, ushort reason, byte a7) {
|
||||||
if (name != null) {
|
if (name != null) {
|
||||||
PluginLog.Log($"{name->ToString()}@{world} ({contentId}) {(TellReason) reason}");
|
try {
|
||||||
|
var target = new TellTarget(name->ToString(), world, contentId, (TellReason) reason);
|
||||||
|
this.Activated?.Invoke(null, new ChannelSwitchInfo(InputChannel.Tell), (TellReason) reason, target);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
PluginLog.LogError(ex, "Error in chat Activated event");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.SetChatLogTellTargetHook!.Original(a1, name, a3, world, contentId, reason, a7);
|
return this.SetChatLogTellTargetHook!.Original(a1, name, a3, world, contentId, reason, a7);
|
||||||
@ -487,4 +501,16 @@ internal sealed unsafe class Chat : IDisposable {
|
|||||||
|
|
||||||
return new TellHistoryInfo(name, world, contentId);
|
return new TellHistoryInfo(name, world, contentId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal void SendTell(TellReason reason, ulong contentId, string name, ushort homeWorld, string message) {
|
||||||
|
var uName = Utf8String.FromString(name);
|
||||||
|
var uMessage = Utf8String.FromString(message);
|
||||||
|
|
||||||
|
var networkModule = this._getNetworkModule(Framework.Instance());
|
||||||
|
var a1 = *(IntPtr*) (networkModule + 8);
|
||||||
|
var logModule = Framework.Instance()->GetUiModule()->GetRaptureLogModule();
|
||||||
|
|
||||||
|
this._printTell(logModule, 33, uName, uMessage, contentId, homeWorld, 255, 0, 0);
|
||||||
|
this._sendTell(a1, contentId, homeWorld, uName, uMessage, (byte) reason, homeWorld);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,5 +3,6 @@ namespace ChatTwo.GameFunctions.Types;
|
|||||||
internal enum TellReason {
|
internal enum TellReason {
|
||||||
Direct = 0,
|
Direct = 0,
|
||||||
PartyFinder = 1,
|
PartyFinder = 1,
|
||||||
|
Reply = 2,
|
||||||
Friend = 3,
|
Friend = 3,
|
||||||
}
|
}
|
||||||
|
15
ChatTwo/GameFunctions/Types/TellTarget.cs
Executable file
15
ChatTwo/GameFunctions/Types/TellTarget.cs
Executable file
@ -0,0 +1,15 @@
|
|||||||
|
namespace ChatTwo.GameFunctions.Types;
|
||||||
|
|
||||||
|
internal sealed class TellTarget {
|
||||||
|
internal string Name { get; }
|
||||||
|
internal ushort World { get; }
|
||||||
|
internal ulong ContentId { get; }
|
||||||
|
internal TellReason Reason { get; }
|
||||||
|
|
||||||
|
internal TellTarget(string name, ushort world, ulong contentId, TellReason reason) {
|
||||||
|
this.Name = name;
|
||||||
|
this.World = world;
|
||||||
|
this.ContentId = contentId;
|
||||||
|
this.Reason = reason;
|
||||||
|
}
|
||||||
|
}
|
@ -4,6 +4,7 @@ using ChatTwo.GameFunctions.Types;
|
|||||||
using ChatTwo.Util;
|
using ChatTwo.Util;
|
||||||
using Dalamud.Game.ClientState.Keys;
|
using Dalamud.Game.ClientState.Keys;
|
||||||
using Dalamud.Game.Command;
|
using Dalamud.Game.Command;
|
||||||
|
using Dalamud.Game.Text.SeStringHandling;
|
||||||
using Dalamud.Game.Text.SeStringHandling.Payloads;
|
using Dalamud.Game.Text.SeStringHandling.Payloads;
|
||||||
using Dalamud.Interface;
|
using Dalamud.Interface;
|
||||||
using Dalamud.Logging;
|
using Dalamud.Logging;
|
||||||
@ -25,7 +26,7 @@ internal sealed class ChatLog : IUiComponent {
|
|||||||
private int _inputBacklogIdx = -1;
|
private int _inputBacklogIdx = -1;
|
||||||
private int _lastTab;
|
private int _lastTab;
|
||||||
private InputChannel? _tempChannel;
|
private InputChannel? _tempChannel;
|
||||||
private (string, string, ulong)? _tellTarget;
|
private TellTarget? _tellTarget;
|
||||||
private int _tellIdx;
|
private int _tellIdx;
|
||||||
|
|
||||||
private PayloadHandler PayloadHandler { get; }
|
private PayloadHandler PayloadHandler { get; }
|
||||||
@ -52,7 +53,7 @@ internal sealed class ChatLog : IUiComponent {
|
|||||||
this.Ui.Plugin.CommandManager.RemoveHandler("/clearlog2");
|
this.Ui.Plugin.CommandManager.RemoveHandler("/clearlog2");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Activated(string? input, ChannelSwitchInfo info) {
|
private void Activated(string? input, ChannelSwitchInfo info, TellReason? reason, TellTarget? target) {
|
||||||
this.Activate = true;
|
this.Activate = true;
|
||||||
if (input != null && !this.Chat.Contains(input)) {
|
if (input != null && !this.Chat.Contains(input)) {
|
||||||
this.Chat += input;
|
this.Chat += input;
|
||||||
@ -67,7 +68,8 @@ internal sealed class ChatLog : IUiComponent {
|
|||||||
this._tempChannel = info.Channel.Value;
|
this._tempChannel = info.Channel.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info.Channel is InputChannel.Tell && info.Rotate != RotateMode.None) {
|
if (info.Channel is InputChannel.Tell) {
|
||||||
|
if (info.Rotate != RotateMode.None) {
|
||||||
this._tellIdx = prevTemp != InputChannel.Tell
|
this._tellIdx = prevTemp != InputChannel.Tell
|
||||||
? 0
|
? 0
|
||||||
: info.Rotate == RotateMode.Reverse
|
: info.Rotate == RotateMode.Reverse
|
||||||
@ -75,10 +77,15 @@ internal sealed class ChatLog : IUiComponent {
|
|||||||
: 1;
|
: 1;
|
||||||
|
|
||||||
var tellInfo = this.Ui.Plugin.Functions.Chat.GetTellHistoryInfo(this._tellIdx);
|
var tellInfo = this.Ui.Plugin.Functions.Chat.GetTellHistoryInfo(this._tellIdx);
|
||||||
if (tellInfo != null) {
|
if (tellInfo != null && reason != null) {
|
||||||
var world = this.Ui.Plugin.DataManager.GetExcelSheet<World>()?.GetRow(tellInfo.World);
|
this._tellTarget = new TellTarget(tellInfo.Name, (ushort) tellInfo.World, tellInfo.ContentId, reason.Value);
|
||||||
if (world != null) {
|
}
|
||||||
this._tellTarget = (tellInfo.Name, world.Name, tellInfo.ContentId);
|
} else {
|
||||||
|
this._tellIdx = 0;
|
||||||
|
this._tellTarget = null;
|
||||||
|
|
||||||
|
if (target != null) {
|
||||||
|
this._tellTarget = target;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -211,7 +218,8 @@ internal sealed class ChatLog : IUiComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
this.Activated(null, info);
|
TellReason? reason = info.Channel == InputChannel.Tell ? TellReason.Reply : null;
|
||||||
|
this.Activated(null, info, reason, null);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
PluginLog.LogError(ex, "Error in chat Activated event");
|
PluginLog.LogError(ex, "Error in chat Activated event");
|
||||||
}
|
}
|
||||||
@ -261,7 +269,17 @@ internal sealed class ChatLog : IUiComponent {
|
|||||||
try {
|
try {
|
||||||
if (this._tempChannel != null) {
|
if (this._tempChannel != null) {
|
||||||
if (this._tellTarget != null) {
|
if (this._tellTarget != null) {
|
||||||
ImGui.TextUnformatted($"Tell {this._tellTarget.Value.Item1}@{this._tellTarget.Value.Item2}");
|
var world = this.Ui.Plugin.DataManager.GetExcelSheet<World>()
|
||||||
|
?.GetRow(this._tellTarget.World)
|
||||||
|
?.Name
|
||||||
|
?.RawString ?? "???";
|
||||||
|
|
||||||
|
this.DrawChunks(new List<Chunk> {
|
||||||
|
new TextChunk(null, null, "Tell "),
|
||||||
|
new TextChunk(null, null, this._tellTarget.Name),
|
||||||
|
new IconChunk(null, null, BitmapFontIcon.CrossWorld),
|
||||||
|
new TextChunk(null, null, world),
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
ImGui.TextUnformatted(this._tempChannel.Value.ToChatType().Name());
|
ImGui.TextUnformatted(this._tempChannel.Value.ToChatType().Name());
|
||||||
}
|
}
|
||||||
@ -333,12 +351,23 @@ internal sealed class ChatLog : IUiComponent {
|
|||||||
this.AddBacklog(trimmed);
|
this.AddBacklog(trimmed);
|
||||||
this._inputBacklogIdx = -1;
|
this._inputBacklogIdx = -1;
|
||||||
|
|
||||||
if (this._tempChannel != null) {
|
|
||||||
if (this._tellTarget != null) {
|
if (this._tellTarget != null) {
|
||||||
trimmed = $"{this._tempChannel.Value.Prefix()} {this._tellTarget.Value.Item1}@{this._tellTarget.Value.Item2} {trimmed}";
|
var target = this._tellTarget;
|
||||||
} else {
|
var reason = target.Reason;
|
||||||
trimmed = $"{this._tempChannel.Value.Prefix()} {trimmed}";
|
var world = this.Ui.Plugin.DataManager.GetExcelSheet<World>()?.GetRow(target.World);
|
||||||
|
if (world is { IsPublic: true }) {
|
||||||
|
if (reason == TellReason.Reply && this.Ui.Plugin.Common.Functions.FriendList.List.Any(friend => friend.ContentId == target.ContentId)) {
|
||||||
|
reason = TellReason.Friend;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.Ui.Plugin.Functions.Chat.SendTell(reason, target.ContentId, target.Name, (ushort) world.RowId, trimmed);
|
||||||
|
}
|
||||||
|
|
||||||
|
goto Skip;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this._tempChannel != null) {
|
||||||
|
trimmed = $"{this._tempChannel.Value.Prefix()} {trimmed}";
|
||||||
} else if (activeTab is { Channel: { } channel } && !trimmed.StartsWith('/')) {
|
} else if (activeTab is { Channel: { } channel } && !trimmed.StartsWith('/')) {
|
||||||
trimmed = $"{channel.Prefix()} {trimmed}";
|
trimmed = $"{channel.Prefix()} {trimmed}";
|
||||||
}
|
}
|
||||||
@ -346,6 +375,7 @@ internal sealed class ChatLog : IUiComponent {
|
|||||||
this.Ui.Plugin.Common.Functions.Chat.SendMessage(trimmed);
|
this.Ui.Plugin.Common.Functions.Chat.SendMessage(trimmed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Skip:
|
||||||
this.Chat = string.Empty;
|
this.Chat = string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user