feat(plugin): add PeepingTom integration

This commit is contained in:
Anna 2021-07-04 21:09:38 -04:00
parent a3fcd576a7
commit c48a3ef0d8
12 changed files with 214 additions and 136 deletions

View File

@ -13,20 +13,20 @@ using XIVChatCommon.Message.Client;
using XIVChatCommon.Message.Relay;
namespace XIVChatPlugin {
public abstract class BaseClient : Stream {
public virtual bool Connected { get; set; }
internal abstract class BaseClient : Stream {
internal virtual bool Connected { get; set; }
public HandshakeInfo? Handshake { get; set; }
internal HandshakeInfo? Handshake { get; set; }
public ClientPreferences? Preferences { get; set; }
internal ClientPreferences? Preferences { get; set; }
public IPAddress? Remote { get; set; }
internal IPAddress? Remote { get; set; }
public CancellationTokenSource TokenSource { get; } = new();
internal CancellationTokenSource TokenSource { get; } = new();
public Channel<Encodable> Queue { get; } = Channel.CreateUnbounded<Encodable>();
internal Channel<Encodable> Queue { get; } = Channel.CreateUnbounded<Encodable>();
public void Disconnect() {
internal void Disconnect() {
this.Connected = false;
this.TokenSource.Cancel();
@ -37,7 +37,7 @@ namespace XIVChatPlugin {
}
}
public T? GetPreference<T>(ClientPreference pref, T? def = default) {
internal T? GetPreference<T>(ClientPreference pref, T? def = default) {
var prefs = this.Preferences;
if (prefs == null) {
@ -48,12 +48,12 @@ namespace XIVChatPlugin {
}
}
public sealed class TcpConnected : BaseClient {
internal sealed class TcpConnected : BaseClient {
private TcpClient Client { get; }
private readonly Stream _streamImplementation;
private bool _connected;
public override bool Connected {
internal override bool Connected {
get {
var ret = this._connected;
try {
@ -67,7 +67,7 @@ namespace XIVChatPlugin {
set => this._connected = value;
}
public TcpConnected(TcpClient client) {
internal TcpConnected(TcpClient client) {
this.Client = client;
this.Client.ReceiveTimeout = 5_000;
@ -126,7 +126,7 @@ namespace XIVChatPlugin {
}
}
public sealed class RelayConnected : BaseClient {
internal sealed class RelayConnected : BaseClient {
internal byte[] PublicKey { get; }
private ChannelWriter<IToRelay> ToRelay { get; }
@ -137,7 +137,7 @@ namespace XIVChatPlugin {
private List<byte> ReadBuffer { get; } = new();
private List<byte> WriteBuffer { get; } = new();
public RelayConnected(byte[] publicKey, IPAddress remote, ChannelWriter<IToRelay> toRelay, Channel<byte[]> fromRelay) {
internal RelayConnected(byte[] publicKey, IPAddress remote, ChannelWriter<IToRelay> toRelay, Channel<byte[]> fromRelay) {
this.PublicKey = publicKey;
this.Remote = remote;
this.Connected = true;

View File

@ -5,7 +5,7 @@ using System.Collections.Generic;
namespace XIVChatPlugin {
[Serializable]
public class Configuration : IPluginConfiguration {
internal class Configuration : IPluginConfiguration {
private Plugin? _plugin;
public int Version { get; set; } = 1;
@ -28,11 +28,11 @@ namespace XIVChatPlugin {
public Dictionary<Guid, Tuple<string, byte[]>> TrustedKeys { get; set; } = new();
public KeyPair? KeyPair { get; set; }
public void Initialise(Plugin plugin) {
internal void Initialise(Plugin plugin) {
this._plugin = plugin;
}
public void Save() {
internal void Save() {
this._plugin?.Interface.SavePluginConfig(this);
}
}

View File

@ -0,0 +1,29 @@
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;
}
}
}

View File

@ -10,7 +10,7 @@ using Dalamud.Plugin;
using XIVChatCommon.Message;
namespace XIVChatPlugin {
public class GameFunctions : IDisposable {
internal class GameFunctions : IDisposable {
private Plugin Plugin { get; }
private delegate IntPtr GetUiModuleDelegate(IntPtr basePtr);
@ -66,15 +66,15 @@ namespace XIVChatPlugin {
private IntPtr _chatManager = IntPtr.Zero;
private readonly IntPtr _emptyXivString = IntPtr.Zero;
public bool RequestingFriendList { get; private set; }
internal bool RequestingFriendList { get; private set; }
private readonly List<Player> _friends = new();
public delegate void ReceiveFriendListHandler(List<Player> friends);
internal delegate void ReceiveFriendListHandler(List<Player> friends);
public event ReceiveFriendListHandler? ReceiveFriendList;
internal event ReceiveFriendListHandler? ReceiveFriendList;
public GameFunctions(Plugin plugin) {
internal GameFunctions(Plugin plugin) {
this.Plugin = plugin;
var getUiModulePtr = this.Plugin.ScanText("E8 ?? ?? ?? ?? 48 83 7F ?? 00 48 8B F0");
@ -208,7 +208,7 @@ namespace XIVChatPlugin {
return 1;
}
public void ChangeChatChannel(InputChannel channel) {
internal void ChangeChatChannel(InputChannel channel) {
if (this._chatManager == IntPtr.Zero || this._channelChangeCommand == null || this._emptyXivString == IntPtr.Zero) {
return;
}
@ -219,7 +219,7 @@ namespace XIVChatPlugin {
// This function looks up a channel's user-defined colour.
//
// If this function would ever return 0, it returns null instead.
public uint? GetChannelColour(ChatCode channel) {
internal uint? GetChannelColour(ChatCode channel) {
if (this.ColourLookup == IntPtr.Zero || this.ColourHandler == IntPtr.Zero) {
return null;
}
@ -249,7 +249,7 @@ namespace XIVChatPlugin {
return 0xFF | (rgb << 8);
}
public void ProcessChatBox(string message) {
internal void ProcessChatBox(string message) {
if (this._easierProcessChatBox == null || this.UiModulePtr == IntPtr.Zero) {
return;
}
@ -271,7 +271,7 @@ namespace XIVChatPlugin {
Marshal.FreeHGlobal(mem1);
}
public bool RequestFriendList() {
internal bool RequestFriendList() {
if (this._friendListManager == IntPtr.Zero || this._friendListHook == null) {
return false;
}
@ -452,7 +452,7 @@ namespace XIVChatPlugin {
return nonNull.Length == 0 ? null : Encoding.UTF8.GetString(nonNull);
}
public string? Name() => HandleString(this.name);
public string? FreeCompany() => HandleString(this.fc);
internal string? Name() => HandleString(this.name);
internal string? FreeCompany() => HandleString(this.fc);
}
}

View File

@ -0,0 +1,64 @@
using System;
using System.Collections.Generic;
using System.Dynamic;
using System.Linq;
using Dalamud.Game.ClientState.Actors.Types;
using Lumina.Excel.GeneratedSheets;
using XIVChatCommon.Message;
using XIVChatCommon.Message.Client;
using XIVChatCommon.Message.Server;
namespace XIVChatPlugin.Ipc {
internal class PeepingTom : IDisposable {
private Plugin Plugin { get; }
internal PeepingTom(Plugin plugin) {
this.Plugin = plugin;
#pragma warning disable 618
this.Plugin.Interface.Subscribe("PeepingTom", this.ReceiveTargeting);
#pragma warning restore 618
}
public void Dispose() {
#pragma warning disable 618
this.Plugin.Interface.Unsubscribe("PeepingTom");
#pragma warning restore 618
}
private void ReceiveTargeting(dynamic obj) {
List<ExpandoObject> list = obj.Targeting;
var players = list
.Select((dynamic player) => (uint) player.ActorId)
.Select(targeting => this.Plugin.Interface.ClientState.Actors.FirstOrDefault(actor => actor.ActorId == targeting))
.Where(actor => actor is PlayerCharacter)
.Cast<PlayerCharacter>()
.Select(chara => new Player {
Name = chara.Name,
FreeCompany = chara.CompanyTag,
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<TerritoryType>().GetRow(this.Plugin.Interface.ClientState.TerritoryType)?.Name,
Job = (byte) chara.ClassJob.Id,
JobName = chara.ClassJob.GameData.Name.ToString(),
GrandCompany = 0,
GrandCompanyName = null,
Languages = 0,
MainLanguage = 0,
})
.ToArray();
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));
}
}
}
}

View File

@ -4,7 +4,7 @@ using System.Runtime.InteropServices;
using System.Text;
namespace XIVChatPlugin {
public static unsafe class NativeTools {
internal static unsafe class NativeTools {
[StructLayout(LayoutKind.Sequential)]
private readonly struct RawVec {
public readonly byte** pointer;
@ -18,7 +18,7 @@ namespace XIVChatPlugin {
[DllImport("xivchat_native_tools.dll")]
private static extern void wrap_free(RawVec* raw);
public static IEnumerable<string> Wrap(string input, uint width) {
internal static IEnumerable<string> Wrap(string input, uint width) {
RawVec* raw;
fixed (byte* ptr = Encoding.UTF8.GetBytes(input).Terminate()) {
raw = wrap(ptr, width);

View File

@ -2,42 +2,31 @@
using Dalamud.Plugin;
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
#if DEBUG
using System.IO;
#endif
using System.Reflection;
namespace XIVChatPlugin {
// ReSharper disable once ClassNeverInstantiated.Global
public class Plugin : IDalamudPlugin {
internal class Plugin : IDisposable {
private bool _disposedValue;
public string Name => "XIVChat";
internal DalamudPluginInterface Interface { get; }
internal DalamudPlugin DalamudPlugin { get; }
internal Configuration Config { get; }
private PluginUi Ui { get; }
internal Server Server { get; private set; } = null!;
internal Relay? Relay { get; private set; }
internal GameFunctions Functions { get; }
private List<IDisposable> Ipcs { get; } = new();
// ReSharper disable once MemberCanBePrivate.Global
// ReSharper disable once UnusedAutoPropertyAccessor.Global
internal string Location { get; private set; } = Assembly.GetExecutingAssembly().Location;
[SuppressMessage("ReSharper", "UnusedMember.Local")]
private void SetLocation(string path) {
this.Location = path;
}
public DalamudPluginInterface Interface { get; private set; } = null!;
public Configuration Config { get; private set; } = null!;
private PluginUi Ui { get; set; } = null!;
public Server Server { get; private set; } = null!;
public Relay? Relay { get; private set; }
public GameFunctions Functions { get; private set; } = null!;
public void Initialize(DalamudPluginInterface pluginInterface) {
this.Interface = pluginInterface ?? throw new ArgumentNullException(nameof(pluginInterface), "DalamudPluginInterface cannot be null");
internal Plugin(DalamudPlugin dalamudPlugin, DalamudPluginInterface pluginInterface) {
this.Interface = pluginInterface;
this.DalamudPlugin = dalamudPlugin;
// load libsodium.so from debug location if in debug mode
#if DEBUG
string path = Environment.GetEnvironmentVariable("PATH")!;
string newPath = Path.GetDirectoryName(this.Location)!;
string newPath = Path.GetDirectoryName(this.DalamudPlugin.Location)!;
Environment.SetEnvironmentVariable("PATH", $"{path};{newPath}");
#endif
@ -64,6 +53,32 @@ namespace XIVChatPlugin {
this.Interface.CommandManager.AddHandler("/xivchat", new CommandInfo(this.OnCommand) {
HelpMessage = "Opens the config for the XIVChat plugin",
});
this.Ipcs.Add(new Ipc.PeepingTom(this));
}
public void Dispose() {
if (this._disposedValue) {
return;
}
this._disposedValue = true;
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");
foreach (var ipc in this.Ipcs) {
ipc.Dispose();
}
}
internal void StartRelay() {
@ -105,7 +120,7 @@ namespace XIVChatPlugin {
this.Server.Spawn();
}
public void RelaunchServer() {
internal void RelaunchServer() {
this.Server.Dispose();
this.LaunchServer();
}
@ -113,34 +128,5 @@ namespace XIVChatPlugin {
private void OnCommand(string command, string args) {
this.Ui.OpenSettings(null, null);
}
[SuppressMessage("ReSharper", "DelegateSubtraction")]
protected virtual void Dispose(bool disposing) {
if (this._disposedValue) {
return;
}
if (disposing) {
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._disposedValue = true;
}
public void Dispose() {
// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
this.Dispose(true);
GC.SuppressFinalize(this);
}
}
}

View File

@ -8,7 +8,7 @@ using System.Threading.Channels;
using System.Threading.Tasks;
namespace XIVChatPlugin {
public class PluginUi {
internal class PluginUi {
private Plugin Plugin { get; }
private bool _showSettings;
@ -21,23 +21,23 @@ namespace XIVChatPlugin {
private readonly Dictionary<Guid, Tuple<BaseClient, Channel<bool>>> _pending = new();
private readonly Dictionary<Guid, string> _pendingNames = new(0);
public PluginUi(Plugin plugin) {
internal PluginUi(Plugin plugin) {
this.Plugin = plugin ?? throw new ArgumentNullException(nameof(plugin), "Plugin cannot be null");
}
private static class Colours {
public static readonly Vector4 Primary = new(2 / 255f, 204 / 255f, 238 / 255f, 1.0f);
public static readonly Vector4 PrimaryDark = new(2 / 255f, 180 / 255f, 211 / 255f, 1.0f);
public static readonly Vector4 Background = new(46 / 255f, 46 / 255f, 46 / 255f, 1.0f);
public static readonly Vector4 Text = new(190 / 255f, 190 / 255f, 190 / 255f, 1.0f);
public static readonly Vector4 Button = new(90 / 255f, 89 / 255f, 90 / 255f, 1.0f);
public static readonly Vector4 ButtonActive = new(123 / 255f, 122 / 255f, 124 / 255f, 1.0f);
public static readonly Vector4 ButtonHovered = new(108 / 255f, 107 / 255f, 109 / 255f, 1.0f);
internal static readonly Vector4 Primary = new(2 / 255f, 204 / 255f, 238 / 255f, 1.0f);
internal static readonly Vector4 PrimaryDark = new(2 / 255f, 180 / 255f, 211 / 255f, 1.0f);
internal static readonly Vector4 Background = new(46 / 255f, 46 / 255f, 46 / 255f, 1.0f);
internal static readonly Vector4 Text = new(190 / 255f, 190 / 255f, 190 / 255f, 1.0f);
internal static readonly Vector4 Button = new(90 / 255f, 89 / 255f, 90 / 255f, 1.0f);
internal static readonly Vector4 ButtonActive = new(123 / 255f, 122 / 255f, 124 / 255f, 1.0f);
internal static readonly Vector4 ButtonHovered = new(108 / 255f, 107 / 255f, 109 / 255f, 1.0f);
public static readonly Vector4 White = new(1f, 1f, 1f, 1f);
internal static readonly Vector4 White = new(1f, 1f, 1f, 1f);
}
public void Draw() {
internal void Draw() {
ImGui.PushStyleColor(ImGuiCol.TitleBg, Colours.PrimaryDark);
ImGui.PushStyleColor(ImGuiCol.TitleBgActive, Colours.Primary);
ImGui.PushStyleColor(ImGuiCol.TitleBgCollapsed, Colours.PrimaryDark);
@ -102,7 +102,7 @@ namespace XIVChatPlugin {
}
}
if (!this.ShowSettings || !Begin(this.Plugin.Name, ref this._showSettings, ImGuiWindowFlags.AlwaysAutoResize)) {
if (!this.ShowSettings || !Begin(this.Plugin.DalamudPlugin.Name, ref this._showSettings, ImGuiWindowFlags.AlwaysAutoResize)) {
return;
}

View File

@ -10,21 +10,21 @@ using WebSocketSharp;
using XIVChatCommon.Message.Relay;
namespace XIVChatPlugin {
public enum ConnectionStatus {
internal enum ConnectionStatus {
Disconnected,
Connecting,
Negotiating,
Connected,
}
public class Relay : IDisposable {
internal class Relay : IDisposable {
#if DEBUG
private const string RelayUrl = "ws://localhost:14555/";
#else
private const string RelayUrl = "wss://relay.xiv.chat/";
#endif
public static string? ConnectionError { get; private set; }
internal static string? ConnectionError { get; private set; }
private bool Disposed { get; set; }
@ -34,7 +34,7 @@ namespace XIVChatPlugin {
private bool Running { get; set; }
public ConnectionStatus Status { get; private set; }
internal ConnectionStatus Status { get; private set; }
private Channel<IToRelay> ToRelay { get; } = Channel.CreateUnbounded<IToRelay>();

View File

@ -23,7 +23,7 @@ using XIVChatCommon.Message.Client;
using XIVChatCommon.Message.Server;
namespace XIVChatPlugin {
public class Server : IDisposable {
internal class Server : IDisposable {
private const int MaxMessageLength = 500;
private static readonly string[] PublicPrefixes = {
@ -47,8 +47,8 @@ namespace XIVChatPlugin {
private readonly ConcurrentQueue<string> _toGame = new();
private readonly ConcurrentDictionary<Guid, BaseClient> _clients = new();
public IReadOnlyDictionary<Guid, BaseClient> Clients => this._clients;
public readonly Channel<Tuple<BaseClient, Channel<bool>>> PendingClients = Channel.CreateUnbounded<Tuple<BaseClient, Channel<bool>>>();
internal IReadOnlyDictionary<Guid, BaseClient> Clients => this._clients;
internal readonly Channel<Tuple<BaseClient, Channel<bool>>> PendingClients = Channel.CreateUnbounded<Tuple<BaseClient, Channel<bool>>>();
private readonly HashSet<Guid> _waitingForFriendList = new();
@ -67,7 +67,7 @@ namespace XIVChatPlugin {
private const int MaxMessageSize = 128_000;
public Server(Plugin plugin) {
internal Server(Plugin plugin) {
this._plugin = plugin;
if (this._plugin.Config.KeyPair == null) {
this.RegenerateKeyPair();
@ -167,7 +167,7 @@ namespace XIVChatPlugin {
this._waitingForFriendList.Clear();
}
public void Spawn() {
internal void Spawn() {
var port = this._plugin.Config.Port;
Task.Run(async () => {
@ -191,13 +191,12 @@ namespace XIVChatPlugin {
});
}
public void RegenerateKeyPair() {
internal void RegenerateKeyPair() {
this._plugin.Config.KeyPair = PublicKeyBox.GenerateKeyPair();
this._plugin.Config.Save();
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE0060:Remove unused parameter", Justification = "delegate")]
public void OnChat(XivChatType type, uint senderId, ref SeString sender, ref SeString message, ref bool isHandled) {
internal void OnChat(XivChatType type, uint senderId, ref SeString sender, ref SeString message, ref bool isHandled) {
if (isHandled) {
return;
}
@ -245,8 +244,7 @@ namespace XIVChatPlugin {
}
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE0060:Remove unused parameter", Justification = "delegate")]
public void OnFrameworkUpdate(Framework framework) {
internal void OnFrameworkUpdate(Framework framework) {
var player = this._plugin.Interface.ClientState.LocalPlayer;
if (player != null && this._sendPlayerData) {
this.BroadcastPlayerData();
@ -482,7 +480,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.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.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.");
}
}
@ -500,18 +498,18 @@ namespace XIVChatPlugin {
}
}
public class NameFormatting {
public string Before { get; private set; } = string.Empty;
public string After { get; private set; } = string.Empty;
public bool IsPresent { get; private set; } = true;
internal class NameFormatting {
internal string Before { get; private set; } = string.Empty;
internal string After { get; private set; } = string.Empty;
internal bool IsPresent { get; private set; } = true;
public static NameFormatting Empty() {
internal static NameFormatting Empty() {
return new() {
IsPresent = false,
};
}
public static NameFormatting Of(string before, string after) {
internal static NameFormatting Of(string before, string after) {
return new() {
Before = before,
After = after,
@ -750,7 +748,7 @@ namespace XIVChatPlugin {
return this._plugin.Interface.Data.GetExcelSheet<LogFilter>().GetRow(rowId).Name;
}
public void OnChatChannelChange(uint channel) {
internal void OnChatChannelChange(uint channel) {
var inputChannel = (InputChannel) channel;
this._currentChannel = inputChannel;
@ -785,18 +783,18 @@ namespace XIVChatPlugin {
this.BroadcastMessage(playerData);
}
public 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;
}
public void OnLogOut(object sender, EventArgs e) {
internal void OnLogOut(object sender, EventArgs e) {
this.BroadcastAvailability(false);
this.BroadcastPlayerData();
}
public 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
@ -822,7 +820,7 @@ namespace XIVChatPlugin {
}
internal static class TcpListenerExt {
public static async Task<TcpClient?> GetTcpClient(this TcpListener listener, CancellationTokenSource source) {
internal static async Task<TcpClient?> GetTcpClient(this TcpListener listener, CancellationTokenSource source) {
using (source.Token.Register(listener.Stop)) {
try {
var client = await listener.AcceptTcpClientAsync().ConfigureAwait(false);

View File

@ -5,11 +5,11 @@ using System.Numerics;
namespace XIVChatPlugin {
internal static class Util {
public static string ToHexString(this IEnumerable<byte> bytes, bool upper = false, string separator = "") {
internal static string ToHexString(this IEnumerable<byte> bytes, bool upper = false, string separator = "") {
return string.Join(separator, bytes.Select(b => b.ToString(upper ? "X2" : "x2")));
}
public static List<Vector4> ToColours(this byte[] bytes) {
internal static List<Vector4> ToColours(this byte[] bytes) {
var colours = new List<Vector4>();
var colour = new Vector4(0f, 0f, 0f, 1f);
@ -41,7 +41,7 @@ namespace XIVChatPlugin {
return colours;
}
public static int IndexOfCount(this string source, char toFind, int position) {
internal static int IndexOfCount(this string source, char toFind, int position) {
var index = -1;
for (var i = 0; i < position; i++) {
index = source.IndexOf(toFind, index + 1);
@ -54,14 +54,14 @@ namespace XIVChatPlugin {
return index;
}
public static byte[] Terminate(this byte[] bytes) {
internal static byte[] Terminate(this byte[] bytes) {
var terminated = new byte[bytes.Length + 1];
Array.Copy(bytes, terminated, bytes.Length);
terminated[terminated.Length - 1] = 0;
return terminated;
}
public static unsafe byte[] ReadTerminated(byte* mem) {
internal static unsafe byte[] ReadTerminated(byte* mem) {
var bytes = new List<byte>();
while (*mem != 0) {
bytes.Add(*mem);

View File

@ -29,20 +29,21 @@
<HintPath>$(AppData)\XIVLauncher\addon\Hooks\dev\Lumina.Excel.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Microsoft.CSharp" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="DalamudPackager" Version="1.2.1"/>
<PackageReference Include="ILRepack.Lib.MSBuild.Task" Version="2.0.18.2"/>
<PackageReference Include="MessagePack" Version="2.2.85"/>
<PackageReference Include="Sodium.Core" Version="1.2.3"/>
<PackageReference Include="System.Threading.Channels" Version="5.0.0"/>
<PackageReference Include="WebSocketSharp" Version="1.0.3-rc11"/>
<PackageReference Include="DalamudPackager" Version="1.2.1" />
<PackageReference Include="ILRepack.Lib.MSBuild.Task" Version="2.0.18.2" />
<PackageReference Include="MessagePack" Version="2.2.85" />
<PackageReference Include="Sodium.Core" Version="1.2.3" />
<PackageReference Include="System.Threading.Channels" Version="5.0.0" />
<PackageReference Include="WebSocketSharp" Version="1.0.3-rc11" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\XIVChatCommon\XIVChatCommon.csproj"/>
<ProjectReference Include="..\XIVChatCommon\XIVChatCommon.csproj" />
</ItemGroup>
<Target Name="CopyNativeLibraries" AfterTargets="AfterBuild">
<Copy SourceFiles="Resources\lib\libsodium.dll" DestinationFolder="$(OutDir)"/>
<Copy SourceFiles="Resources\lib\xivchat_native_tools.dll" DestinationFolder="$(OutDir)"/>
<Copy SourceFiles="Resources\lib\libsodium.dll" DestinationFolder="$(OutDir)" />
<Copy SourceFiles="Resources\lib\xivchat_native_tools.dll" DestinationFolder="$(OutDir)" />
</Target>
</Project>