diff --git a/XIVChatPlugin/Client.cs b/XIVChatPlugin/Client.cs index 3d23e12..b561295 100644 --- a/XIVChatPlugin/Client.cs +++ b/XIVChatPlugin/Client.cs @@ -137,7 +137,7 @@ namespace XIVChatPlugin { private List ReadBuffer { get; } = new(); private List WriteBuffer { get; } = new(); - internal RelayConnected(byte[] publicKey, IPAddress remote, ChannelWriter toRelay, Channel fromRelay) { + internal RelayConnected(byte[] publicKey, IPAddress? remote, ChannelWriter toRelay, Channel fromRelay) { this.PublicKey = publicKey; this.Remote = remote; this.Connected = true; diff --git a/XIVChatPlugin/DalamudPlugin.cs b/XIVChatPlugin/DalamudPlugin.cs deleted file mode 100644 index 5e5783c..0000000 --- a/XIVChatPlugin/DalamudPlugin.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System.Diagnostics.CodeAnalysis; -using System.Reflection; -using Dalamud.Plugin; - -namespace XIVChatPlugin { - // ReSharper disable once ClassNeverInstantiated.Global - public class DalamudPlugin : IDalamudPlugin { - public string Name => "XIVChat"; - - private Plugin? Plugin { get; set; } - - // ReSharper disable once UnusedMember.Global - // ReSharper disable once AutoPropertyCanBeMadeGetOnly.Local - internal string Location { get; private set; } = Assembly.GetExecutingAssembly().Location; - - public void Initialize(DalamudPluginInterface pluginInterface) { - this.Plugin = new Plugin(this, pluginInterface); - } - - public void Dispose() { - this.Plugin?.Dispose(); - } - - [SuppressMessage("ReSharper", "UnusedMember.Local")] - private void SetLocation(string path) { - this.Location = path; - } - } -} diff --git a/XIVChatPlugin/GameFunctions.cs b/XIVChatPlugin/GameFunctions.cs index 7005f79..0dd249b 100644 --- a/XIVChatPlugin/GameFunctions.cs +++ b/XIVChatPlugin/GameFunctions.cs @@ -6,7 +6,7 @@ using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Runtime.InteropServices; using System.Text; -using Dalamud.Plugin; +using Dalamud.Logging; using XIVChatCommon.Message; namespace XIVChatPlugin { @@ -142,37 +142,37 @@ namespace XIVChatPlugin { } if (friendListPtr != IntPtr.Zero) { - this._friendListHook = new Hook(friendListPtr, new RequestFriendListDelegate(this.OnRequestFriendList)); + this._friendListHook = new Hook(friendListPtr, this.OnRequestFriendList); } else { PluginLog.Warning("Pointer was null, disabling hook: {0}", nameof(friendListPtr)); } if (formatPtr != IntPtr.Zero) { - this._formatHook = new Hook(formatPtr, new FormatFriendListNameDelegate(this.OnFormatFriendList)); + this._formatHook = new Hook(formatPtr, this.OnFormatFriendList); } else { PluginLog.Warning("Pointer was null, disabling hook: {0}", nameof(formatPtr)); } if (recvChunkPtr != IntPtr.Zero) { - this._receiveChunkHook = new Hook(recvChunkPtr, new OnReceiveFriendListChunkDelegate(this.OnReceiveFriendList)); + this._receiveChunkHook = new Hook(recvChunkPtr, this.OnReceiveFriendList); } else { PluginLog.Warning("Pointer was null, disabling hook: {0}", nameof(recvChunkPtr)); } if (channelPtr != IntPtr.Zero) { - this._chatChannelChangeHook = new Hook(channelPtr, new ChatChannelChangeDelegate(this.ChangeChatChannelDetour)); + this._chatChannelChangeHook = new Hook(channelPtr, this.ChangeChatChannelDetour); } else { PluginLog.Warning("Pointer was null, disabling hook: {0}", nameof(channelPtr)); } if (inputPtr != IntPtr.Zero) { - this._isInputHook = new Hook(inputPtr, new IsInputDelegate(this.IsInputDetour)); + this._isInputHook = new Hook(inputPtr, this.IsInputDetour); } else { PluginLog.Warning("Pointer was null, disabling hook: {0}", nameof(inputPtr)); } if (inputAfkPtr != IntPtr.Zero) { - this._isInputAfkHook = new Hook(inputAfkPtr, new IsInputAfkDelegate(this.IsInputAfkDetour)); + this._isInputAfkHook = new Hook(inputAfkPtr, this.IsInputAfkDetour); } else { PluginLog.Warning("Pointer was null, disabling hook: {0}", nameof(inputAfkPtr)); } @@ -220,7 +220,7 @@ namespace XIVChatPlugin { // // If this function would ever return 0, it returns null instead. internal uint? GetChannelColour(ChatCode channel) { - if (this.ColourLookup == IntPtr.Zero || this.ColourHandler == IntPtr.Zero) { + if (this._getColourInfo == null || this.ColourLookup == IntPtr.Zero || this.ColourHandler == IntPtr.Zero) { return null; } @@ -250,7 +250,7 @@ namespace XIVChatPlugin { } internal void ProcessChatBox(string message) { - if (this._easierProcessChatBox == null || this.UiModulePtr == IntPtr.Zero) { + if (this._easierProcessChatBox == null || this._getUiModule == null || this.UiModulePtr == IntPtr.Zero) { return; } @@ -307,13 +307,13 @@ namespace XIVChatPlugin { string? jobName = null; if (entry.job > 0) { - jobName = this.Plugin.Interface.Data.GetExcelSheet().GetRow(entry.job)?.Name; + jobName = this.Plugin.DataManager.GetExcelSheet()!.GetRow(entry.job)?.Name?.ToString(); } // FIXME: remove this try/catch when lumina fixes bug with .Value string? territoryName; try { - territoryName = this.Plugin.Interface.Data.GetExcelSheet().GetRow(entry.territoryId)?.PlaceName?.Value?.Name; + territoryName = this.Plugin.DataManager.GetExcelSheet()!.GetRow(entry.territoryId)?.PlaceName?.Value?.Name?.ToString(); } catch (NullReferenceException) { territoryName = null; } @@ -324,9 +324,9 @@ namespace XIVChatPlugin { Status = entry.flags, CurrentWorld = entry.currentWorldId, - CurrentWorldName = this.Plugin.Interface.Data.GetExcelSheet().GetRow(entry.currentWorldId)?.Name, + CurrentWorldName = this.Plugin.DataManager.GetExcelSheet()!.GetRow(entry.currentWorldId)?.Name?.ToString(), HomeWorld = entry.homeWorldId, - HomeWorldName = this.Plugin.Interface.Data.GetExcelSheet().GetRow(entry.homeWorldId)?.Name, + HomeWorldName = this.Plugin.DataManager.GetExcelSheet()!.GetRow(entry.homeWorldId)?.Name?.ToString(), Territory = entry.territoryId, TerritoryName = territoryName, @@ -335,7 +335,7 @@ namespace XIVChatPlugin { JobName = jobName, GrandCompany = entry.grandCompany, - GrandCompanyName = this.Plugin.Interface.Data.GetExcelSheet().GetRow(entry.grandCompany)?.Name, + GrandCompanyName = this.Plugin.DataManager.GetExcelSheet()!.GetRow(entry.grandCompany)?.Name?.ToString(), Languages = entry.langsEnabled, MainLanguage = entry.mainLanguage, diff --git a/XIVChatPlugin/ILRepack.targets b/XIVChatPlugin/ILRepack.targets deleted file mode 100644 index 26dc630..0000000 --- a/XIVChatPlugin/ILRepack.targets +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - - - - - - - - $([System.IO.Directory]::GetFiles("%(Directories.Identity)", "*", System.IO.SearchOption.AllDirectories).get_Length()) - - - - diff --git a/XIVChatPlugin/InternalEvents.cs b/XIVChatPlugin/InternalEvents.cs new file mode 100644 index 0000000..149355a --- /dev/null +++ b/XIVChatPlugin/InternalEvents.cs @@ -0,0 +1,13 @@ +using System; + +namespace XIVChatPlugin { + internal class InternalEvents { + internal delegate void NewClientDelegate(Guid id, BaseClient client); + + internal event NewClientDelegate? NewClient; + + internal void FireNewClientEvent(Guid id, BaseClient client) { + this.NewClient?.Invoke(id, client); + } + } +} diff --git a/XIVChatPlugin/Ipc/PeepingTom.cs b/XIVChatPlugin/Ipc/PeepingTom.cs index 77ee8eb..5d67fe6 100644 --- a/XIVChatPlugin/Ipc/PeepingTom.cs +++ b/XIVChatPlugin/Ipc/PeepingTom.cs @@ -1,9 +1,11 @@ using System; using System.Collections.Generic; -using System.Dynamic; using System.Linq; -using Dalamud.Game.ClientState.Actors.Types; +using Dalamud.Game.ClientState.Objects.SubKinds; using Lumina.Excel.GeneratedSheets; +using PeepingTom.Ipc; +using PeepingTom.Ipc.From; +using PeepingTom.Ipc.To; using XIVChatCommon.Message; using XIVChatCommon.Message.Client; using XIVChatCommon.Message.Server; @@ -11,38 +13,84 @@ using XIVChatCommon.Message.Server; namespace XIVChatPlugin.Ipc { internal class PeepingTom : IDisposable { private Plugin Plugin { get; } + private List Targeters { get; } = new(); + + private class TargeterWithStatus { + public Targeter Targeter { get; set; } = null!; + public bool Targeting { get; set; } + } internal PeepingTom(Plugin plugin) { this.Plugin = plugin; - #pragma warning disable 618 - this.Plugin.Interface.Subscribe("PeepingTom", this.ReceiveTargeting); - #pragma warning restore 618 + IpcInfo.GetSubscriber(this.Plugin.Interface).Subscribe(this.ReceiveMessage); + IpcInfo.GetProvider(this.Plugin.Interface).SendMessage(new RequestTargetersMessage()); + this.Plugin.Events.NewClient += this.OnNewClient; } public void Dispose() { - #pragma warning disable 618 - this.Plugin.Interface.Unsubscribe("PeepingTom"); - #pragma warning restore 618 + this.Plugin.Events.NewClient -= this.OnNewClient; + IpcInfo.GetSubscriber(this.Plugin.Interface).Unsubscribe(this.ReceiveMessage); } - private void ReceiveTargeting(dynamic obj) { - List list = obj.Targeting; - var players = list - .Select((dynamic player) => (uint) player.ActorId) - .Select(targeting => this.Plugin.Interface.ClientState.Actors.FirstOrDefault(actor => actor.ActorId == targeting)) + private void ReceiveMessage(IFromMessage message) { + switch (message) { + case AllTargetersMessage allMessage: { + this.Targeters.Clear(); + this.Targeters.AddRange(allMessage.Targeters + .Select(t => new TargeterWithStatus { + Targeter = t.targeter, + Targeting = t.currentlyTargeting, + })); + break; + } + case NewTargeterMessage newMessage: { + this.UpdateTargeter(newMessage.Targeter, true); + + break; + } + case StoppedTargetingMessage stoppedMessage: { + this.UpdateTargeter(stoppedMessage.Targeter, false); + + break; + } + } + + var xivChatMessage = this.GetMessage(); + foreach (var client in this.Plugin.Server.Clients.Values) { + this.SendToClient(client, xivChatMessage); + } + } + + private void UpdateTargeter(Targeter targeter, bool targeting) { + var existing = this.Targeters.FirstOrDefault(t => t.Targeter.ObjectId == targeter.ObjectId); + if (existing == default) { + this.Targeters.Add(new TargeterWithStatus { + Targeter = targeter, + Targeting = targeting, + }); + } else { + existing.Targeter = targeter; + existing.Targeting = targeting; + } + } + + private ServerPlayerList GetMessage() { + var players = this.Targeters + .Where(targeter => targeter.Targeting) // FIXME: send entire history so clients don't have to do logic + .Select(targeter => this.Plugin.ObjectTable.FirstOrDefault(obj => obj.ObjectId == targeter.Targeter.ObjectId)) .Where(actor => actor is PlayerCharacter) .Cast() .Select(chara => new Player { - Name = chara.Name, - FreeCompany = chara.CompanyTag, + Name = chara.Name.TextValue, + FreeCompany = chara.CompanyTag.TextValue, Status = 0, CurrentWorld = (ushort) chara.CurrentWorld.Id, CurrentWorldName = chara.CurrentWorld.GameData.Name.ToString(), HomeWorld = (ushort) chara.HomeWorld.Id, HomeWorldName = chara.HomeWorld.GameData.Name.ToString(), - Territory = this.Plugin.Interface.ClientState.TerritoryType, - TerritoryName = this.Plugin.Interface.Data.GetExcelSheet().GetRow(this.Plugin.Interface.ClientState.TerritoryType)?.Name, + Territory = this.Plugin.ClientState.TerritoryType, + TerritoryName = this.Plugin.DataManager.GetExcelSheet()!.GetRow(this.Plugin.ClientState.TerritoryType)?.Name?.ToString(), Job = (byte) chara.ClassJob.Id, JobName = chara.ClassJob.GameData.Name.ToString(), GrandCompany = 0, @@ -51,14 +99,19 @@ namespace XIVChatPlugin.Ipc { MainLanguage = 0, }) .ToArray(); + return new ServerPlayerList(PlayerListType.Targeting, players); + } - foreach (var client in this.Plugin.Server.Clients.Values) { - if (!client.GetPreference(ClientPreference.TargetingListSupport, false)) { - continue; - } - - client.Queue.Writer.TryWrite(new ServerPlayerList(PlayerListType.Targeting, players)); + private void SendToClient(BaseClient client, ServerPlayerList list) { + if (!client.GetPreference(ClientPreference.TargetingListSupport, false)) { + return; } + + client.Queue.Writer.TryWrite(list); + } + + private void OnNewClient(Guid id, BaseClient client) { + this.SendToClient(client, this.GetMessage()); } } } diff --git a/XIVChatPlugin/Plugin.cs b/XIVChatPlugin/Plugin.cs index cc6197b..1546415 100644 --- a/XIVChatPlugin/Plugin.cs +++ b/XIVChatPlugin/Plugin.cs @@ -2,26 +2,69 @@ using Dalamud.Plugin; using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Reflection; +using Dalamud.Data; +using Dalamud.Game; +using Dalamud.Game.ClientState; +using Dalamud.Game.ClientState.Objects; +using Dalamud.Game.Gui; +using Dalamud.IoC; #if DEBUG using System.IO; #endif namespace XIVChatPlugin { - internal class Plugin : IDisposable { + internal class Plugin : IDalamudPlugin { + public string Name => "XIVChat"; + private bool _disposedValue; - internal DalamudPluginInterface Interface { get; } - internal DalamudPlugin DalamudPlugin { get; } + [PluginService] + internal DalamudPluginInterface Interface { get; private init; } = null!; + + [PluginService] + internal ChatGui ChatGui { get; private init; } = null!; + + [PluginService] + internal ClientState ClientState { get; private init; } = null!; + + [PluginService] + private CommandManager CommandManager { get; init; } = null!; + + [PluginService] + internal DataManager DataManager { get; private init; } = null!; + + [PluginService] + private Framework Framework { get; init; } = null!; + + [PluginService] + internal ObjectTable ObjectTable { get; private init; } = null!; + + [PluginService] + private SigScanner SigScanner { get; init; } = null!; + internal Configuration Config { get; } private PluginUi Ui { get; } - internal Server Server { get; private set; } = null!; + internal Server Server { get; private set; } internal Relay? Relay { get; private set; } internal GameFunctions Functions { get; } + internal InternalEvents Events { get; } private List Ipcs { get; } = new(); - internal Plugin(DalamudPlugin dalamudPlugin, DalamudPluginInterface pluginInterface) { - this.Interface = pluginInterface; - this.DalamudPlugin = dalamudPlugin; + // ReSharper disable once UnusedMember.Global + // ReSharper disable once AutoPropertyCanBeMadeGetOnly.Local + // ReSharper disable once UnusedAutoPropertyAccessor.Global + // ReSharper disable once MemberCanBePrivate.Global + internal string Location { get; private set; } = Assembly.GetExecutingAssembly().Location; + + [SuppressMessage("ReSharper", "UnusedMember.Local")] + private void SetLocation(string path) { + this.Location = path; + } + + public Plugin() { + this.Events = new InternalEvents(); // load libsodium.so from debug location if in debug mode #if DEBUG @@ -43,14 +86,14 @@ namespace XIVChatPlugin { this.StartRelay(); } - this.Interface.UiBuilder.OnBuildUi += this.Ui.Draw; - this.Interface.UiBuilder.OnOpenConfigUi += this.Ui.OpenSettings; - this.Interface.Framework.OnUpdateEvent += this.Server.OnFrameworkUpdate; - this.Interface.Framework.Gui.Chat.OnChatMessage += this.Server.OnChat; - this.Interface.ClientState.OnLogin += this.Server.OnLogIn; - this.Interface.ClientState.OnLogout += this.Server.OnLogOut; - this.Interface.ClientState.TerritoryChanged += this.Server.OnTerritoryChange; - this.Interface.CommandManager.AddHandler("/xivchat", new CommandInfo(this.OnCommand) { + this.Interface.UiBuilder.Draw += this.Ui.Draw; + this.Interface.UiBuilder.OpenConfigUi += this.Ui.OpenSettings; + this.Framework.Update += this.Server!.OnFrameworkUpdate; + this.ChatGui.ChatMessage += this.Server.OnChat; + this.ClientState.Login += this.Server.OnLogIn; + this.ClientState.Logout += this.Server.OnLogOut; + this.ClientState.TerritoryChanged += this.Server.OnTerritoryChange; + this.CommandManager.AddHandler("/xivchat", new CommandInfo(this.OnCommand) { HelpMessage = "Opens the config for the XIVChat plugin", }); @@ -67,14 +110,14 @@ namespace XIVChatPlugin { this.Relay?.Dispose(); this.Server.Dispose(); - this.Interface.UiBuilder.OnBuildUi -= this.Ui.Draw; - this.Interface.UiBuilder.OnOpenConfigUi -= this.Ui.OpenSettings; - this.Interface.Framework.OnUpdateEvent -= this.Server.OnFrameworkUpdate; - this.Interface.Framework.Gui.Chat.OnChatMessage -= this.Server.OnChat; - this.Interface.ClientState.OnLogin -= this.Server.OnLogIn; - this.Interface.ClientState.OnLogout -= this.Server.OnLogOut; - this.Interface.ClientState.TerritoryChanged -= this.Server.OnTerritoryChange; - this.Interface.CommandManager.RemoveHandler("/xivchat"); + this.Interface.UiBuilder.Draw -= this.Ui.Draw; + this.Interface.UiBuilder.OpenConfigUi -= this.Ui.OpenSettings; + this.Framework.Update -= this.Server.OnFrameworkUpdate; + this.ChatGui.ChatMessage -= this.Server.OnChat; + this.ClientState.Login -= this.Server.OnLogIn; + this.ClientState.Logout -= this.Server.OnLogOut; + this.ClientState.TerritoryChanged -= this.Server.OnTerritoryChange; + this.CommandManager.RemoveHandler("/xivchat"); foreach (var ipc in this.Ipcs) { ipc.Dispose(); @@ -101,7 +144,7 @@ namespace XIVChatPlugin { internal IntPtr ScanText(string sig) { try { - return this.Interface.TargetModuleScanner.ScanText(sig); + return this.SigScanner.ScanText(sig); } catch (KeyNotFoundException) { return IntPtr.Zero; } @@ -109,7 +152,7 @@ namespace XIVChatPlugin { internal IntPtr GetStaticAddressFromSig(string sig) { try { - return this.Interface.TargetModuleScanner.GetStaticAddressFromSig(sig); + return this.SigScanner.GetStaticAddressFromSig(sig); } catch (KeyNotFoundException) { return IntPtr.Zero; } @@ -126,7 +169,7 @@ namespace XIVChatPlugin { } private void OnCommand(string command, string args) { - this.Ui.OpenSettings(null, null); + this.Ui.OpenSettings(); } } } diff --git a/XIVChatPlugin/PluginUI.cs b/XIVChatPlugin/PluginUI.cs index 8cadc15..2bc63ee 100644 --- a/XIVChatPlugin/PluginUI.cs +++ b/XIVChatPlugin/PluginUI.cs @@ -102,7 +102,12 @@ namespace XIVChatPlugin { } } - if (!this.ShowSettings || !Begin(this.Plugin.DalamudPlugin.Name, ref this._showSettings, ImGuiWindowFlags.AlwaysAutoResize)) { + if (!this.ShowSettings) { + return; + } + + if (!Begin(this.Plugin.Name, ref this._showSettings, ImGuiWindowFlags.AlwaysAutoResize)) { + ImGui.End(); return; } @@ -345,16 +350,6 @@ namespace XIVChatPlugin { } } - if (WithWhiteText(() => ImGui.CollapsingHeader("ACT/Teamcraft issues?"))) { - ImGui.PushTextWrapPos(ImGui.GetFontSize() * 20); - ImGui.TextUnformatted("Click on the button below to visit a website showing a workaround for ACT and Teamcraft having issues."); - ImGui.PopTextWrapPos(); - - if (WithWhiteText(() => ImGui.Button("Open website"))) { - System.Diagnostics.Process.Start("https://xiv.chat/server/workaround"); - } - } - ImGui.End(); } @@ -391,7 +386,7 @@ namespace XIVChatPlugin { ImGui.Dummy(new Vector2(0, 16 + spacing.Y * 2)); } - public void OpenSettings(object? sender, EventArgs? args) { + public void OpenSettings() { this.ShowSettings = true; } @@ -437,7 +432,7 @@ namespace XIVChatPlugin { ImGui.PopTextWrapPos(); - if (!this._pendingNames.TryGetValue(id, out string name)) { + if (!this._pendingNames.TryGetValue(id, out var name)) { name = "No name"; } diff --git a/XIVChatPlugin/Relay.cs b/XIVChatPlugin/Relay.cs index 1b668b4..ad762c2 100644 --- a/XIVChatPlugin/Relay.cs +++ b/XIVChatPlugin/Relay.cs @@ -2,9 +2,11 @@ using System.Collections.Generic; using System.Linq; using System.Net; +using System.Security.Authentication; +using System.Threading; using System.Threading.Channels; using System.Threading.Tasks; -using Dalamud.Plugin; +using Dalamud.Logging; using MessagePack; using WebSocketSharp; using XIVChatCommon.Message.Relay; @@ -19,9 +21,9 @@ namespace XIVChatPlugin { internal class Relay : IDisposable { #if DEBUG - private const string RelayUrl = "ws://localhost:14555/"; + private static readonly Uri RelayUrl = new("ws://localhost:14555/", UriKind.Absolute); #else - private const string RelayUrl = "wss://relay.xiv.chat/"; + private static readonly Uri RelayUrl = new("wss://relay.xiv.chat/", UriKind.Absolute); #endif internal static string? ConnectionError { get; private set; } @@ -41,9 +43,9 @@ namespace XIVChatPlugin { internal Relay(Plugin plugin) { this.Plugin = plugin; - this.Connection = new WebSocket(RelayUrl) { + this.Connection = new WebSocket(RelayUrl.ToString()) { SslConfiguration = { - EnabledSslProtocols = System.Security.Authentication.SslProtocols.Tls12, + EnabledSslProtocols = SslProtocols.Tls12 | SslProtocols.Tls13, }, }; @@ -55,7 +57,7 @@ namespace XIVChatPlugin { public void Dispose() { this.Disposed = true; - this.Connection.CloseAsync(); + new Thread(() => this.Connection.Close(CloseStatusCode.Normal)).Start(); this.Running = false; } @@ -67,7 +69,7 @@ namespace XIVChatPlugin { this.Running = true; this.Status = ConnectionStatus.Connecting; - this.Connection.ConnectAsync(); + new Thread(() => this.Connection.Connect()).Start(); } internal void ResendPublicKey() { @@ -94,7 +96,7 @@ namespace XIVChatPlugin { this.Connection.Send(bytes); } - private void OnOpen(object sender, EventArgs e) { + private void OnOpen(object? o, EventArgs eventArgs) { this.Status = ConnectionStatus.Negotiating; var auth = this.Plugin.Config.RelayAuth; @@ -132,8 +134,8 @@ namespace XIVChatPlugin { }); } - private void OnMessage(object sender, MessageEventArgs e) { - var message = MessagePackSerializer.Deserialize(e.RawData); + private void OnMessage(object? sender, MessageEventArgs args) { + var message = MessagePackSerializer.Deserialize(args.RawData); switch (message) { case RelaySuccess success: if (success.Success) { @@ -148,7 +150,9 @@ namespace XIVChatPlugin { break; case RelayNewClient newClient: + #pragma warning disable CA1806 IPAddress.TryParse(newClient.Address, out var remote); + #pragma warning restore CA1806 var client = new RelayConnected( newClient.PublicKey.ToArray(), remote, @@ -181,17 +185,17 @@ namespace XIVChatPlugin { } } - private void OnClose(object sender, CloseEventArgs e) { + private void OnClose(object? sender, CloseEventArgs args) { this.Running = false; this.Status = ConnectionStatus.Disconnected; - if (!e.WasClean && !this.Disposed) { + if (!args.WasClean && !this.Disposed) { Task.Run(async () => await Task.Delay(3_000)).ContinueWith(_ => this.Start()); } } - private void OnError(object sender, ErrorEventArgs e) { - PluginLog.LogError(e.Exception, $"Error in relay connection: {e.Message}"); + private void OnError(object? sender, ErrorEventArgs args) { + PluginLog.LogError(args.Exception, $"Error in relay connection: {args.Message}"); this.Running = false; this.Status = ConnectionStatus.Disconnected; diff --git a/XIVChatPlugin/Server.cs b/XIVChatPlugin/Server.cs index b90c0c5..a482dc1 100644 --- a/XIVChatPlugin/Server.cs +++ b/XIVChatPlugin/Server.cs @@ -1,6 +1,4 @@ -using Dalamud.Game.Internal; -using Dalamud.Plugin; -using Lumina.Excel.GeneratedSheets; +using Lumina.Excel.GeneratedSheets; using MessagePack; using Sodium; using System; @@ -14,9 +12,11 @@ using System.Text; using System.Threading; using System.Threading.Channels; using System.Threading.Tasks; +using Dalamud.Game; using Dalamud.Game.Text; using Dalamud.Game.Text.SeStringHandling; using Dalamud.Game.Text.SeStringHandling.Payloads; +using Dalamud.Logging; using XIVChatCommon; using XIVChatCommon.Message; using XIVChatCommon.Message.Client; @@ -91,7 +91,7 @@ namespace XIVChatPlugin { var multicastAddr = IPAddress.Parse("224.0.0.147"); udp.JoinMulticastGroup(multicastAddr); - string? lastPlayerName = null; + SeString? lastPlayerName = null; Task? receiveTask = null; @@ -101,7 +101,7 @@ namespace XIVChatPlugin { continue; } - var playerName = this._plugin.Interface.ClientState.LocalPlayer?.Name; + var playerName = this._plugin.ClientState.LocalPlayer?.Name; if (playerName != null) { lastPlayerName = playerName; @@ -135,7 +135,7 @@ namespace XIVChatPlugin { continue; } - var utf8 = Encoding.UTF8.GetBytes(lastPlayerName); + var utf8 = Encoding.UTF8.GetBytes(lastPlayerName.TextValue); var portBytes = BitConverter.GetBytes(this._plugin.Config.Port).Reverse().ToArray(); var key = this._plugin.Config.KeyPair!.PublicKey; // magic + string length + string + port + key @@ -244,8 +244,8 @@ namespace XIVChatPlugin { } } - internal void OnFrameworkUpdate(Framework framework) { - var player = this._plugin.Interface.ClientState.LocalPlayer; + internal void OnFrameworkUpdate(Framework framework1) { + var player = this._plugin.ClientState.LocalPlayer; if (player != null && this._sendPlayerData) { this.BroadcastPlayerData(); this._sendPlayerData = false; @@ -382,6 +382,8 @@ namespace XIVChatPlugin { } }); + this._plugin.Events.FireNewClientEvent(id, client); + while (this._clients.TryGetValue(id, out var client) && client.Connected && !client.TokenSource.IsCancellationRequested) { try { var msg = await client.Queue.Reader.ReadAsync(client.TokenSource.Token); @@ -480,7 +482,7 @@ namespace XIVChatPlugin { this._waitingForFriendList.Add(id); if (!this._plugin.Functions.RequestingFriendList && !this._plugin.Functions.RequestFriendList()) { - this._plugin.Interface.Framework.Gui.Chat.PrintError($"[{this._plugin.DalamudPlugin.Name}] Please open your friend list to enable friend list support. You should only need to do this on initial install or after updates."); + this._plugin.ChatGui.PrintError($"[{this._plugin.Name}] Please open your friend list to enable friend list support. You should only need to do this on initial install or after updates."); } } @@ -524,14 +526,13 @@ namespace XIVChatPlugin { return cached; } - var logKind = this._plugin.Interface.Data.GetExcelSheet().GetRow((ushort) type); + var logKind = this._plugin.DataManager.GetExcelSheet()!.GetRow((ushort) type); if (logKind == null) { return null; } - var format = logKind.Format; - var sestring = this._plugin.Interface.SeStringManager.Parse(format.RawData.ToArray()); + var format = (SeString) logKind.Format; static bool IsStringParam(Payload payload, byte num) { var data = payload.Encode(); @@ -539,19 +540,19 @@ namespace XIVChatPlugin { return data.Length >= 5 && data[1] == 0x29 && data[4] == num + 1; } - var firstStringParam = sestring.Payloads.FindIndex(payload => IsStringParam(payload, 1)); - var secondStringParam = sestring.Payloads.FindIndex(payload => IsStringParam(payload, 2)); + var firstStringParam = format.Payloads.FindIndex(payload => IsStringParam(payload, 1)); + var secondStringParam = format.Payloads.FindIndex(payload => IsStringParam(payload, 2)); if (firstStringParam == -1 || secondStringParam == -1) { return NameFormatting.Empty(); } - var before = sestring.Payloads + var before = format.Payloads .GetRange(0, firstStringParam) .Where(payload => payload is ITextProvider) .Cast() .Select(text => text.Text); - var after = sestring.Payloads + var after = format.Payloads .GetRange(firstStringParam + 1, secondStringParam - firstStringParam) .Where(payload => payload is ITextProvider) .Cast() @@ -690,16 +691,16 @@ namespace XIVChatPlugin { if (input.StartsWith("/")) { var space = input.IndexOf(' '); if (space != -1) { - prefix = input.Substring(0, space); + prefix = input[..space]; // handle wrapping tells if (prefix is "/tell" or "/t") { var tellSpace = input.IndexOfCount(' ', 3); if (tellSpace != -1) { - prefix = input.Substring(0, tellSpace); - input = input.Substring(tellSpace + 1); + prefix = input[..tellSpace]; + input = input[(tellSpace + 1)..]; } } else { - input = input.Substring(space + 1); + input = input[(space + 1)..]; } } } @@ -745,7 +746,7 @@ namespace XIVChatPlugin { _ => 0, }; - return this._plugin.Interface.Data.GetExcelSheet().GetRow(rowId).Name; + return this._plugin.DataManager.GetExcelSheet()!.GetRow(rowId)?.Name ?? string.Empty; } internal void OnChatChannelChange(uint channel) { @@ -763,16 +764,16 @@ namespace XIVChatPlugin { } private PlayerData? GeneratePlayerData() { - var player = this._plugin.Interface.ClientState.LocalPlayer; + var player = this._plugin.ClientState.LocalPlayer; if (player == null) { return null; } var homeWorld = player.HomeWorld.GameData.Name; var currentWorld = player.CurrentWorld.GameData.Name; - var territory = this._plugin.Interface.Data.GetExcelSheet().GetRow(this._plugin.Interface.ClientState.TerritoryType); + var territory = this._plugin.DataManager.GetExcelSheet()!.GetRow(this._plugin.ClientState.TerritoryType); var location = territory?.PlaceName?.Value?.Name ?? "???"; - var name = player.Name; + var name = player.Name.TextValue; return new PlayerData(homeWorld, currentWorld, location, name); } @@ -783,18 +784,18 @@ namespace XIVChatPlugin { this.BroadcastMessage(playerData); } - internal void OnLogIn(object sender, EventArgs e) { + internal void OnLogIn(object? sender, EventArgs e) { this.BroadcastAvailability(true); // send player data on next framework update this._sendPlayerData = true; } - internal void OnLogOut(object sender, EventArgs e) { + internal void OnLogOut(object? sender, EventArgs e) { this.BroadcastAvailability(false); this.BroadcastPlayerData(); } - internal void OnTerritoryChange(object sender, ushort territoryId) => this._sendPlayerData = true; + internal void OnTerritoryChange(object? sender, ushort territoryId) => this._sendPlayerData = true; public void Dispose() { // stop accepting new clients @@ -821,7 +822,7 @@ namespace XIVChatPlugin { internal static class TcpListenerExt { internal static async Task GetTcpClient(this TcpListener listener, CancellationTokenSource source) { - using (source.Token.Register(listener.Stop)) { + await using (source.Token.Register(listener.Stop)) { try { var client = await listener.AcceptTcpClientAsync().ConfigureAwait(false); return client; diff --git a/XIVChatPlugin/XIVChatPlugin.csproj b/XIVChatPlugin/XIVChatPlugin.csproj index 84f4f67..964471d 100644 --- a/XIVChatPlugin/XIVChatPlugin.csproj +++ b/XIVChatPlugin/XIVChatPlugin.csproj @@ -2,11 +2,13 @@ XIVChatPlugin XIVChat - net48 + net5-windows enable latest - 1.6.0 + 1.7.0 true + true + false @@ -17,10 +19,6 @@ $(AppData)\XIVLauncher\addon\Hooks\dev\ImGui.NET.dll False - - $(AppData)\XIVLauncher\addon\Hooks\dev\ImGuiScene.dll - False - $(AppData)\XIVLauncher\addon\Hooks\dev\Lumina.dll False @@ -29,21 +27,25 @@ $(AppData)\XIVLauncher\addon\Hooks\dev\Lumina.Excel.dll False - + + ..\..\PeepingTom\Peeping Tom.Ipc\bin\Release\net5.0-windows\Peeping Tom.Ipc.dll + - - - - - - + + + + + - + - - + + + + +