refactor: update to 6.0
This commit is contained in:
parent
48a7636797
commit
91ccf0ae0d
|
@ -26,6 +26,8 @@ namespace XIVChatPlugin {
|
|||
|
||||
internal Channel<Encodable> Queue { get; } = Channel.CreateUnbounded<Encodable>();
|
||||
|
||||
internal uint BacklogSequence { get; set; }
|
||||
|
||||
internal void Disconnect() {
|
||||
this.Connected = false;
|
||||
this.TokenSource.Cancel();
|
||||
|
|
|
@ -6,11 +6,35 @@ using System.Diagnostics.CodeAnalysis;
|
|||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using Dalamud.Game.Text.SeStringHandling;
|
||||
using Dalamud.Logging;
|
||||
using Dalamud.Memory;
|
||||
using XIVChatCommon.Message;
|
||||
using XIVChatCommon.Message.Server;
|
||||
|
||||
namespace XIVChatPlugin {
|
||||
internal class GameFunctions : IDisposable {
|
||||
private static class Signatures {
|
||||
internal const string GetUiModule = "E8 ?? ?? ?? ?? 48 83 7F ?? 00 48 8B F0";
|
||||
internal const string ProcessChat = "48 89 5C 24 ?? 57 48 83 EC 20 48 8B FA 48 8B D9 45 84 C9";
|
||||
internal const string Input = "80 B9 ?? ?? ?? ?? ?? 0F 9C C0";
|
||||
internal const string InputAfk = "E8 ?? ?? ?? ?? 0F 28 74 24 ?? 0F B6 F0";
|
||||
internal const string FriendList = "40 53 48 81 EC 80 0F 00 00 48 8B 05 ?? ?? ?? ?? 48 33 C4 48 89 84 24 ?? ?? ?? ?? 48 8B D9 48 8B 0D ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 85 C0 0F 84 ?? ?? ?? ?? 44 0F B6 43 ?? 33 C9";
|
||||
internal const string Format = "48 89 5C 24 ?? 48 89 6C 24 ?? 48 89 74 24 ?? 41 56 48 83 EC 30 48 8B 6C 24";
|
||||
internal const string ReceiveChunk = "48 89 5C 24 ?? 56 48 83 EC 20 48 8B 0D ?? ?? ?? ?? 48 8B F2";
|
||||
|
||||
internal const string GetColour = "48 89 5C 24 ?? 48 89 6C 24 ?? 48 89 74 24 ?? 57 48 83 EC 20 8B F2 48 8D B9";
|
||||
|
||||
internal const string Channel = "E8 ?? ?? ?? ?? E9 ?? ?? ?? ?? 85 D2 BB";
|
||||
internal const string ChannelCommand = "E8 ?? ?? ?? ?? 0F B7 44 37";
|
||||
internal const string ChannelNameChange = "E8 ?? ?? ?? ?? BA ?? ?? ?? ?? 48 8D 4D B0 48 8B F8 E8 ?? ?? ?? ?? 41 8B D6";
|
||||
internal const string XivStringCtor = "E8 ?? ?? ?? ?? 44 2B F7";
|
||||
internal const string XivStringDtor = "E8 ?? ?? ?? ?? B0 6E";
|
||||
internal const string UiModule = "48 8B 0D ?? ?? ?? ?? 48 8D 54 24 ?? 48 83 C1 10 E8";
|
||||
internal const string ColourHandler = "48 8B 0D ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 8B 0D ?? ?? ?? ?? 48 85 C9 0F 84 ?? ?? ?? ?? 66 85 DB 0F 94 C2 E8 ?? ?? ?? ?? E9";
|
||||
internal const string ColourLookup = "48 8D 0D ?? ?? ?? ?? 8B 14 ?? 85 D2 7E ?? 48 8B 0D ?? ?? ?? ?? 48 83 C1 10 E8 ?? ?? ?? ?? 8B 70 ?? 41 8D 4D";
|
||||
}
|
||||
|
||||
private Plugin Plugin { get; }
|
||||
|
||||
private delegate IntPtr GetUiModuleDelegate(IntPtr basePtr);
|
||||
|
@ -31,6 +55,8 @@ namespace XIVChatPlugin {
|
|||
|
||||
private delegate byte ChatChannelChangeDelegate(IntPtr a1, uint channel);
|
||||
|
||||
private delegate IntPtr ChatChannelChangeNameDelegate(IntPtr a1);
|
||||
|
||||
private delegate IntPtr ChannelChangeCommandDelegate(IntPtr a1, int inputChannel, uint linkshellIdx, IntPtr tellTarget, char canChangeChannel);
|
||||
|
||||
private delegate IntPtr XivStringCtorDelegate(IntPtr memory);
|
||||
|
@ -43,6 +69,7 @@ namespace XIVChatPlugin {
|
|||
private readonly Hook<FormatFriendListNameDelegate>? _formatHook;
|
||||
private readonly Hook<OnReceiveFriendListChunkDelegate>? _receiveChunkHook;
|
||||
private readonly Hook<ChatChannelChangeDelegate>? _chatChannelChangeHook;
|
||||
private readonly Hook<ChatChannelChangeNameDelegate>? _chatChannelChangeNameHook;
|
||||
|
||||
private readonly GetUiModuleDelegate? _getUiModule;
|
||||
private readonly EasierProcessChatBoxDelegate? _easierProcessChatBox;
|
||||
|
@ -51,6 +78,22 @@ namespace XIVChatPlugin {
|
|||
private readonly XivStringCtorDelegate? _xivStringCtor;
|
||||
private readonly XivStringDtorDelegate? _xivStringDtor;
|
||||
|
||||
public ServerHousingLocation HousingLocation {
|
||||
get {
|
||||
var info = this.Plugin.Common.Functions.Housing.Location;
|
||||
if (info == null) {
|
||||
return new ServerHousingLocation(null, null, false, null);
|
||||
}
|
||||
|
||||
var ward = info.Ward;
|
||||
var plot = info.Plot ?? info.Yard ?? info.Apartment;
|
||||
var wing = (byte?) info.ApartmentWing;
|
||||
var exterior = info.Yard != null;
|
||||
|
||||
return new ServerHousingLocation(ward, plot, exterior, wing);
|
||||
}
|
||||
}
|
||||
|
||||
[Flags]
|
||||
private enum InputSetters {
|
||||
None = 0,
|
||||
|
@ -77,30 +120,31 @@ namespace XIVChatPlugin {
|
|||
internal GameFunctions(Plugin plugin) {
|
||||
this.Plugin = plugin;
|
||||
|
||||
var getUiModulePtr = this.Plugin.ScanText("E8 ?? ?? ?? ?? 48 83 7F ?? 00 48 8B F0");
|
||||
var easierProcessChatBoxPtr = this.Plugin.ScanText("48 89 5C 24 ?? 57 48 83 EC 20 48 8B FA 48 8B D9 45 84 C9");
|
||||
var inputPtr = this.Plugin.ScanText("80 B9 ?? ?? ?? ?? ?? 0F 9C C0");
|
||||
var inputAfkPtr = this.Plugin.ScanText("E8 ?? ?? ?? ?? 0F 28 74 24 ?? 0F B6 F0");
|
||||
var friendListPtr = this.Plugin.ScanText("40 53 48 81 EC 80 0F 00 00 48 8B 05 ?? ?? ?? ?? 48 33 C4 48 89 84 24 ?? ?? ?? ?? 48 8B D9 48 8B 0D ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 85 C0 0F 84 ?? ?? ?? ?? 44 0F B6 43 ?? 33 C9");
|
||||
var formatPtr = this.Plugin.ScanText("48 89 5C 24 ?? 48 89 6C 24 ?? 48 89 74 24 ?? 41 56 48 83 EC 30 48 8B 6C 24 ??");
|
||||
var recvChunkPtr = this.Plugin.ScanText("48 89 5C 24 ?? 56 48 83 EC 20 48 8B 0D ?? ?? ?? ?? 48 8B F2");
|
||||
var getColourPtr = this.Plugin.ScanText("48 89 5C 24 ?? 48 89 6C 24 ?? 48 89 74 24 ?? 57 48 83 EC 20 8B F2 48 8D B9 ?? ?? ?? ??");
|
||||
var channelPtr = this.Plugin.ScanText("E8 ?? ?? ?? ?? E9 ?? ?? ?? ?? 85 D2 BB ?? ?? ?? ??");
|
||||
var channelCommandPtr = this.Plugin.ScanText("E8 ?? ?? ?? ?? 0F B7 44 37 ??");
|
||||
var xivStringCtorPtr = this.Plugin.ScanText("E8 ?? ?? ?? ?? 44 2B F7");
|
||||
var xivStringDtorPtr = this.Plugin.ScanText("E8 ?? ?? ?? ?? B0 6E");
|
||||
var getUiModulePtr = this.Plugin.ScanText(Signatures.GetUiModule);
|
||||
var easierProcessChatBoxPtr = this.Plugin.ScanText(Signatures.ProcessChat);
|
||||
var inputPtr = this.Plugin.ScanText(Signatures.Input);
|
||||
var inputAfkPtr = this.Plugin.ScanText(Signatures.InputAfk);
|
||||
var friendListPtr = this.Plugin.ScanText(Signatures.FriendList);
|
||||
var formatPtr = this.Plugin.ScanText(Signatures.Format);
|
||||
var recvChunkPtr = this.Plugin.ScanText(Signatures.ReceiveChunk);
|
||||
var getColourPtr = this.Plugin.ScanText(Signatures.GetColour);
|
||||
var channelPtr = this.Plugin.ScanText(Signatures.Channel);
|
||||
var channelNamePtr = this.Plugin.ScanText(Signatures.ChannelNameChange);
|
||||
var channelCommandPtr = this.Plugin.ScanText(Signatures.ChannelCommand);
|
||||
var xivStringCtorPtr = this.Plugin.ScanText(Signatures.XivStringCtor);
|
||||
var xivStringDtorPtr = this.Plugin.ScanText(Signatures.XivStringDtor);
|
||||
|
||||
this.UiModulePtr = this.Plugin.GetStaticAddressFromSig("48 8B 0D ?? ?? ?? ?? 48 8D 54 24 ?? 48 83 C1 10 E8 ?? ?? ?? ??");
|
||||
this.UiModulePtr = this.Plugin.GetStaticAddressFromSig(Signatures.UiModule);
|
||||
if (this.UiModulePtr == IntPtr.Zero) {
|
||||
PluginLog.Warning("Static pointer was null: {0}", nameof(this.UiModulePtr));
|
||||
}
|
||||
|
||||
this.ColourHandler = this.Plugin.GetStaticAddressFromSig("48 8B 05 ?? ?? ?? ?? 48 8B A8 ?? ?? ?? ?? 48 85 ED 0F 84 ?? ?? ?? ??");
|
||||
this.ColourHandler = this.Plugin.GetStaticAddressFromSig(Signatures.ColourHandler);
|
||||
if (this.ColourHandler == IntPtr.Zero) {
|
||||
PluginLog.Warning("Static pointer was null: {0}", nameof(this.ColourHandler));
|
||||
}
|
||||
|
||||
this.ColourLookup = this.Plugin.GetStaticAddressFromSig("48 8D 0D ?? ?? ?? ?? 8B 14 ?? 85 D2 7E ?? 48 8B 0D ?? ?? ?? ?? 48 83 C1 10 E8 ?? ?? ?? ?? 8B 70 ?? 41 8D 4D ??");
|
||||
this.ColourLookup = this.Plugin.GetStaticAddressFromSig(Signatures.ColourLookup);
|
||||
if (this.ColourLookup == IntPtr.Zero) {
|
||||
PluginLog.Warning("Static pointer was null: {0}", nameof(this.ColourLookup));
|
||||
}
|
||||
|
@ -165,6 +209,12 @@ namespace XIVChatPlugin {
|
|||
PluginLog.Warning("Pointer was null, disabling hook: {0}", nameof(channelPtr));
|
||||
}
|
||||
|
||||
if (channelNamePtr != IntPtr.Zero) {
|
||||
this._chatChannelChangeNameHook = new Hook<ChatChannelChangeNameDelegate>(channelNamePtr, this.ChangeChatChannelNameDetour);
|
||||
} else {
|
||||
PluginLog.Warning("Pointer was null, disabling hook: {0}", nameof(channelNamePtr));
|
||||
}
|
||||
|
||||
if (inputPtr != IntPtr.Zero) {
|
||||
this._isInputHook = new Hook<IsInputDelegate>(inputPtr, this.IsInputDetour);
|
||||
} else {
|
||||
|
@ -181,6 +231,7 @@ namespace XIVChatPlugin {
|
|||
this._formatHook?.Enable();
|
||||
this._receiveChunkHook?.Enable();
|
||||
this._chatChannelChangeHook?.Enable();
|
||||
this._chatChannelChangeNameHook?.Enable();
|
||||
this._isInputHook?.Enable();
|
||||
this._isInputAfkHook?.Enable();
|
||||
|
||||
|
@ -283,11 +334,45 @@ namespace XIVChatPlugin {
|
|||
|
||||
private byte ChangeChatChannelDetour(IntPtr a1, uint channel) {
|
||||
this._chatManager = a1;
|
||||
// Last ShB patch
|
||||
// a1 + 0xfd0 is the chat channel byte (including for when clicking on shout)
|
||||
this.Plugin.Server.OnChatChannelChange(channel);
|
||||
return this._chatChannelChangeHook!.Original(a1, channel);
|
||||
}
|
||||
|
||||
private unsafe IntPtr ChangeChatChannelNameDetour(IntPtr a1) {
|
||||
// Last ShB patch
|
||||
// +0x40 = chat channel (byte or uint?)
|
||||
// channel is 17 (maybe 18?) for tells
|
||||
// +0x48 = pointer to channel name string
|
||||
var ret = this._chatChannelChangeNameHook!.Original(a1);
|
||||
if (a1 == IntPtr.Zero) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
var channel = *(uint*) (a1 + 0x40);
|
||||
if (channel is 17 or 18) {
|
||||
channel = 0;
|
||||
}
|
||||
|
||||
SeString? name = null;
|
||||
var namePtrPtr = (byte**) (a1 + 0x48);
|
||||
if (namePtrPtr != null) {
|
||||
var namePtr = *namePtrPtr;
|
||||
name = MemoryHelper.ReadSeStringNullTerminated((IntPtr) namePtr);
|
||||
if (name.Payloads.Count == 0) {
|
||||
name = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (name == null) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
this.Plugin.Server.OnChatChannelChange(channel, name);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
private byte OnRequestFriendList(IntPtr manager) {
|
||||
this._friendListManager = manager;
|
||||
// NOTE: if this is being called, hook isn't null
|
||||
|
@ -378,6 +463,7 @@ namespace XIVChatPlugin {
|
|||
this._formatHook?.Dispose();
|
||||
this._receiveChunkHook?.Dispose();
|
||||
this._chatChannelChangeHook?.Dispose();
|
||||
this._chatChannelChangeNameHook?.Dispose();
|
||||
this._isInputHook?.Dispose();
|
||||
this._isInputAfkHook?.Dispose();
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ using Dalamud.Game.ClientState;
|
|||
using Dalamud.Game.ClientState.Objects;
|
||||
using Dalamud.Game.Gui;
|
||||
using Dalamud.IoC;
|
||||
using XivCommon;
|
||||
#if DEBUG
|
||||
using System.IO;
|
||||
#endif
|
||||
|
@ -44,6 +45,7 @@ namespace XIVChatPlugin {
|
|||
[PluginService]
|
||||
private SigScanner SigScanner { get; init; } = null!;
|
||||
|
||||
internal XivCommonBase Common { get; }
|
||||
internal Configuration Config { get; }
|
||||
private PluginUi Ui { get; }
|
||||
internal Server Server { get; private set; }
|
||||
|
@ -64,6 +66,7 @@ namespace XIVChatPlugin {
|
|||
}
|
||||
|
||||
public Plugin() {
|
||||
this.Common = new XivCommonBase();
|
||||
this.Events = new InternalEvents();
|
||||
|
||||
// load libsodium.so from debug location if in debug mode
|
||||
|
@ -118,10 +121,13 @@ namespace XIVChatPlugin {
|
|||
this.ClientState.Logout -= this.Server.OnLogOut;
|
||||
this.ClientState.TerritoryChanged -= this.Server.OnTerritoryChange;
|
||||
this.CommandManager.RemoveHandler("/xivchat");
|
||||
this.Functions.Dispose();
|
||||
|
||||
foreach (var ipc in this.Ipcs) {
|
||||
ipc.Dispose();
|
||||
}
|
||||
|
||||
this.Common.Dispose();
|
||||
}
|
||||
|
||||
internal void StartRelay() {
|
||||
|
|
|
@ -59,11 +59,15 @@ namespace XIVChatPlugin {
|
|||
private bool _sendPlayerData;
|
||||
private readonly ConcurrentQueue<Guid> _awaitingPlayerData = new();
|
||||
private readonly ConcurrentQueue<Guid> _awaitingAvailability = new();
|
||||
private readonly ConcurrentQueue<Guid> _awaitingHousingLocation = new();
|
||||
|
||||
private volatile bool _running;
|
||||
private bool Running => this._running;
|
||||
|
||||
private InputChannel _currentChannel = InputChannel.Say;
|
||||
private SeString? _currentChannelName;
|
||||
|
||||
private ServerHousingLocation _lastHousingLocation;
|
||||
|
||||
private const int MaxMessageSize = 128_000;
|
||||
|
||||
|
@ -73,6 +77,8 @@ namespace XIVChatPlugin {
|
|||
this.RegenerateKeyPair();
|
||||
}
|
||||
|
||||
this._lastHousingLocation = this._plugin.Functions.HousingLocation;
|
||||
|
||||
this._sendWatch.Start();
|
||||
|
||||
this._plugin.Functions.ReceiveFriendList += this.OnReceiveFriendList;
|
||||
|
@ -251,6 +257,12 @@ namespace XIVChatPlugin {
|
|||
this._sendPlayerData = false;
|
||||
}
|
||||
|
||||
var housingLocation = this._plugin.Functions.HousingLocation;
|
||||
if (!Equals(housingLocation, this._lastHousingLocation)) {
|
||||
this.BroadcastMessage(housingLocation, ClientPreference.HousingLocationSupport);
|
||||
this._lastHousingLocation = housingLocation;
|
||||
}
|
||||
|
||||
while (this._awaitingPlayerData.TryDequeue(out var id)) {
|
||||
if (!this.Clients.TryGetValue(id, out var client)) {
|
||||
continue;
|
||||
|
@ -269,6 +281,14 @@ namespace XIVChatPlugin {
|
|||
client.Queue.Writer.TryWrite(new Availability(available));
|
||||
}
|
||||
|
||||
while (this._awaitingHousingLocation.TryDequeue(out var id)) {
|
||||
if (!this.Clients.TryGetValue(id, out var client) || client.Handshake == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
client.Queue.Writer.TryWrite(this._lastHousingLocation);
|
||||
}
|
||||
|
||||
int time;
|
||||
if (this._toGame.TryPeek(out var peek) && PublicPrefixes.Any(prefix => peek.StartsWith(prefix))) {
|
||||
time = 1_000;
|
||||
|
@ -358,7 +378,7 @@ namespace XIVChatPlugin {
|
|||
handshake.Keys.tx,
|
||||
new ServerChannel(
|
||||
channel,
|
||||
this.LocalisedChannelName(channel)
|
||||
this._currentChannelName?.TextValue ?? this.LocalisedChannelName(channel)
|
||||
),
|
||||
this._tokenSource.Token
|
||||
);
|
||||
|
@ -491,6 +511,11 @@ namespace XIVChatPlugin {
|
|||
var preferences = ClientPreferences.Decode(payload);
|
||||
client.Preferences = preferences;
|
||||
|
||||
// immediately queue housing location
|
||||
if (client.GetPreference(ClientPreference.HousingLocationSupport, false)) {
|
||||
this._awaitingHousingLocation.Enqueue(id);
|
||||
}
|
||||
|
||||
break;
|
||||
case ClientOperation.Channel:
|
||||
var channel = ClientChannel.Decode(payload);
|
||||
|
@ -574,7 +599,7 @@ namespace XIVChatPlugin {
|
|||
var responseMessages = new List<ServerMessage>();
|
||||
|
||||
async Task SendBacklog() {
|
||||
var resp = new ServerBacklog(responseMessages.ToArray());
|
||||
var resp = new ServerBacklog(responseMessages.ToArray(), ++client.BacklogSequence);
|
||||
try {
|
||||
await client.Queue.Writer.WriteAsync(resp);
|
||||
} catch (Exception ex) {
|
||||
|
@ -716,6 +741,14 @@ namespace XIVChatPlugin {
|
|||
}
|
||||
}
|
||||
|
||||
private void BroadcastMessage(Encodable message, ClientPreference preference) {
|
||||
foreach (var client in this.Clients.Values) {
|
||||
if (client.GetPreference(preference, false)) {
|
||||
client.Queue.Writer.TryWrite(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private string LocalisedChannelName(InputChannel channel) {
|
||||
uint rowId = channel switch {
|
||||
InputChannel.Tell => 3,
|
||||
|
@ -749,13 +782,24 @@ namespace XIVChatPlugin {
|
|||
return this._plugin.DataManager.GetExcelSheet<LogFilter>()!.GetRow(rowId)?.Name ?? string.Empty;
|
||||
}
|
||||
|
||||
internal void OnChatChannelChange(uint channel) {
|
||||
internal void OnChatChannelChange(uint channel, SeString name) {
|
||||
// for now, to avoid changing the protocol further, convert crossworld icon into font icon
|
||||
for (var i = 0; i < name.Payloads.Count; i++) {
|
||||
var payload = name.Payloads[i];
|
||||
if (payload is IconPayload { Icon: BitmapFontIcon.CrossWorld }) {
|
||||
name.Payloads[i] = new TextPayload("\ue05d");
|
||||
}
|
||||
}
|
||||
|
||||
var inputChannel = (InputChannel) channel;
|
||||
if (inputChannel == this._currentChannel && name.Encode().SequenceEqual(this._currentChannelName?.Encode() ?? Array.Empty<byte>())) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._currentChannel = inputChannel;
|
||||
this._currentChannelName = name;
|
||||
|
||||
var localisedName = this.LocalisedChannelName(inputChannel);
|
||||
|
||||
var msg = new ServerChannel(inputChannel, localisedName);
|
||||
var msg = new ServerChannel(inputChannel, name.TextValue);
|
||||
this.BroadcastMessage(msg);
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace XIVChatPlugin {
|
||||
internal static class Util {
|
||||
|
@ -70,5 +71,23 @@ namespace XIVChatPlugin {
|
|||
|
||||
return bytes.ToArray();
|
||||
}
|
||||
|
||||
internal static IntPtr FollowPointerChain(IntPtr start, IEnumerable<int> offsets) {
|
||||
if (start == IntPtr.Zero) {
|
||||
return IntPtr.Zero;
|
||||
}
|
||||
|
||||
// PluginLog.Log($"start: {start.ToInt64():x}");
|
||||
|
||||
foreach (var offset in offsets) {
|
||||
start = Marshal.ReadIntPtr(start + offset);
|
||||
// PluginLog.Log($" + {offset}: {start.ToInt64():x}");
|
||||
if (start == IntPtr.Zero) {
|
||||
return IntPtr.Zero;
|
||||
}
|
||||
}
|
||||
|
||||
return start;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,11 +32,13 @@
|
|||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="DalamudPackager" Version="2.1.2"/>
|
||||
<PackageReference Include="MessagePack" Version="2.3.75"/>
|
||||
<PackageReference Include="DalamudLinter" Version="1.0.3"/>
|
||||
<PackageReference Include="DalamudPackager" Version="2.1.5"/>
|
||||
<PackageReference Include="MessagePack" Version="2.3.85"/>
|
||||
<PackageReference Include="Sodium.Core" Version="1.2.3"/>
|
||||
<PackageReference Include="System.Threading.Channels" Version="5.0.0"/>
|
||||
<PackageReference Include="System.Threading.Channels" Version="6.0.0"/>
|
||||
<PackageReference Include="WebSocketSharp-netstandard" Version="1.0.1"/>
|
||||
<PackageReference Include="XivCommon" Version="4.0.0-alpha.1"/>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\XIVChatCommon\XIVChatCommon.csproj"/>
|
||||
|
|
Loading…
Reference in New Issue