From f98da094f416030b115e5e37356da49dda35aa42 Mon Sep 17 00:00:00 2001 From: Haselnussbomber Date: Thu, 26 Dec 2024 16:39:54 +0100 Subject: [PATCH] Fetch market board uploader info from main thread (#2158) --- .../IMarketBoardUploader.cs | 12 +++- .../UniversalisMarketBoardUploader.cs | 33 +++-------- .../Game/Network/Internal/NetworkHandlers.cs | 55 +++++++++++++++---- 3 files changed, 62 insertions(+), 38 deletions(-) diff --git a/Dalamud/Game/Network/Internal/MarketBoardUploaders/IMarketBoardUploader.cs b/Dalamud/Game/Network/Internal/MarketBoardUploaders/IMarketBoardUploader.cs index dadfef604..adf5f0228 100644 --- a/Dalamud/Game/Network/Internal/MarketBoardUploaders/IMarketBoardUploader.cs +++ b/Dalamud/Game/Network/Internal/MarketBoardUploaders/IMarketBoardUploader.cs @@ -13,20 +13,26 @@ internal interface IMarketBoardUploader /// Upload data about an item. /// /// The item request data being uploaded. + /// The uploaders ContentId. + /// The uploaders WorldId. /// An async task. - Task Upload(MarketBoardItemRequest item); + Task Upload(MarketBoardItemRequest item, ulong uploaderId, uint worldId); /// /// Upload tax rate data. /// /// The tax rate data being uploaded. + /// The uploaders ContentId. + /// The uploaders WorldId. /// An async task. - Task UploadTax(MarketTaxRates taxRates); + Task UploadTax(MarketTaxRates taxRates, ulong uploaderId, uint worldId); /// /// Upload information about a purchase this client has made. /// /// The purchase handler data associated with the sale. + /// The uploaders ContentId. + /// The uploaders WorldId. /// An async task. - Task UploadPurchase(MarketBoardPurchaseHandler purchaseHandler); + Task UploadPurchase(MarketBoardPurchaseHandler purchaseHandler, ulong uploaderId, uint worldId); } diff --git a/Dalamud/Game/Network/Internal/MarketBoardUploaders/Universalis/UniversalisMarketBoardUploader.cs b/Dalamud/Game/Network/Internal/MarketBoardUploaders/Universalis/UniversalisMarketBoardUploader.cs index f326c5ce0..7ecb9c397 100644 --- a/Dalamud/Game/Network/Internal/MarketBoardUploaders/Universalis/UniversalisMarketBoardUploader.cs +++ b/Dalamud/Game/Network/Internal/MarketBoardUploaders/Universalis/UniversalisMarketBoardUploader.cs @@ -1,5 +1,4 @@ using System.Collections.Generic; -using System.Linq; using System.Net.Http; using System.Text; using System.Threading.Tasks; @@ -33,21 +32,16 @@ internal class UniversalisMarketBoardUploader : IMarketBoardUploader this.httpClient = happyHttpClient.SharedHttpClient; /// - public async Task Upload(MarketBoardItemRequest request) + public async Task Upload(MarketBoardItemRequest request, ulong uploaderId, uint worldId) { - var clientState = Service.GetNullable(); - if (clientState == null) - return; - Log.Verbose("Starting Universalis upload"); - var uploader = clientState.LocalContentId; // ==================================================================================== var uploadObject = new UniversalisItemUploadRequest { - WorldId = clientState.LocalPlayer?.CurrentWorld.RowId ?? 0, - UploaderId = uploader.ToString(), + WorldId = worldId, + UploaderId = uploaderId.ToString(), ItemId = request.CatalogId, Listings = [], Sales = [], @@ -117,18 +111,12 @@ internal class UniversalisMarketBoardUploader : IMarketBoardUploader } /// - public async Task UploadTax(MarketTaxRates taxRates) + public async Task UploadTax(MarketTaxRates taxRates, ulong uploaderId, uint worldId) { - var clientState = Service.GetNullable(); - if (clientState == null) - return; - - // ==================================================================================== - var taxUploadObject = new UniversalisTaxUploadRequest { - WorldId = clientState.LocalPlayer?.CurrentWorld.RowId ?? 0, - UploaderId = clientState.LocalContentId.ToString(), + WorldId = worldId, + UploaderId = uploaderId.ToString(), TaxData = new UniversalisTaxData { LimsaLominsa = taxRates.LimsaLominsaTax, @@ -159,14 +147,9 @@ internal class UniversalisMarketBoardUploader : IMarketBoardUploader /// to track the available listings, that is done via the listings packet. All this does is remove /// a listing, or delete it, when a purchase has been made. /// - public async Task UploadPurchase(MarketBoardPurchaseHandler purchaseHandler) + public async Task UploadPurchase(MarketBoardPurchaseHandler purchaseHandler, ulong uploaderId, uint worldId) { - var clientState = Service.GetNullable(); - if (clientState == null) - return; - var itemId = purchaseHandler.CatalogId; - var worldId = clientState.LocalPlayer?.CurrentWorld.RowId ?? 0; // ==================================================================================== @@ -176,7 +159,7 @@ internal class UniversalisMarketBoardUploader : IMarketBoardUploader Quantity = purchaseHandler.ItemQuantity, ListingId = purchaseHandler.ListingId.ToString(), RetainerId = purchaseHandler.RetainerId.ToString(), - UploaderId = clientState.LocalContentId.ToString(), + UploaderId = uploaderId.ToString(), }; var deletePath = $"/api/{worldId}/{itemId}/delete"; diff --git a/Dalamud/Game/Network/Internal/NetworkHandlers.cs b/Dalamud/Game/Network/Internal/NetworkHandlers.cs index a25444f10..2ba7f2587 100644 --- a/Dalamud/Game/Network/Internal/NetworkHandlers.cs +++ b/Dalamud/Game/Network/Internal/NetworkHandlers.cs @@ -16,8 +16,11 @@ using Dalamud.Hooking; using Dalamud.Networking.Http; using Dalamud.Utility; +using FFXIVClientStructs.FFXIV.Client.Game.Control; using FFXIVClientStructs.FFXIV.Client.Game.InstanceContent; +using FFXIVClientStructs.FFXIV.Client.Game.UI; using FFXIVClientStructs.FFXIV.Client.Network; +using FFXIVClientStructs.FFXIV.Client.UI.Agent; using FFXIVClientStructs.FFXIV.Client.UI.Info; using Lumina.Excel.Sheets; using Serilog; @@ -264,6 +267,33 @@ internal unsafe class NetworkHandlers : IInternalDisposableService this.cfPopHook.Dispose(); } + private static (ulong UploaderId, uint WorldId) GetUploaderInfo() + { + var agentLobby = AgentLobby.Instance(); + + var uploaderId = agentLobby->LobbyData.ContentId; + if (uploaderId == 0) + { + var playerState = PlayerState.Instance(); + if (playerState->IsLoaded == 1) + { + uploaderId = playerState->ContentId; + } + } + + var worldId = agentLobby->LobbyData.CurrentWorldId; + if (worldId == 0) + { + var localPlayer = Control.GetLocalPlayer(); + if (localPlayer != null) + { + worldId = localPlayer->CurrentWorld; + } + } + + return (uploaderId, worldId); + } + private unsafe nint CfPopDetour(PublicContentDirector.EnterContentInfoPacket* packetData) { var result = this.cfPopHook.OriginalDisposeSafe(packetData); @@ -424,14 +454,14 @@ internal unsafe class NetworkHandlers : IInternalDisposableService startObservable .And(this.OnMarketBoardSalesBatch(startObservable)) .And(this.OnMarketBoardListingsBatch(startObservable)) - .Then((request, sales, listings) => (request, sales, listings))) + .Then((request, sales, listings) => (request, sales, listings, GetUploaderInfo()))) .Where(this.ShouldUpload) .SubscribeOn(ThreadPoolScheduler.Instance) .Subscribe( data => { - var (request, sales, listings) = data; - this.UploadMarketBoardData(request, sales, listings); + var (request, sales, listings, uploaderInfo) = data; + this.UploadMarketBoardData(request, sales, listings, uploaderInfo.UploaderId, uploaderInfo.WorldId); }, ex => Log.Error(ex, "Failed to handle Market Board item request event")); } @@ -439,7 +469,9 @@ internal unsafe class NetworkHandlers : IInternalDisposableService private void UploadMarketBoardData( MarketBoardItemRequest request, (uint CatalogId, ICollection Sales) sales, - ICollection listings) + ICollection listings, + ulong uploaderId, + uint worldId) { var catalogId = sales.CatalogId; if (listings.Count != request.AmountToArrive) @@ -460,7 +492,7 @@ internal unsafe class NetworkHandlers : IInternalDisposableService request.Listings.AddRange(listings); request.History.AddRange(sales.Sales); - Task.Run(() => this.uploader.Upload(request)) + Task.Run(() => this.uploader.Upload(request, uploaderId, worldId)) .ContinueWith( task => Log.Error(task.Exception, "Market Board offerings data upload failed"), TaskContinuationOptions.OnlyOnFaulted); @@ -469,11 +501,14 @@ internal unsafe class NetworkHandlers : IInternalDisposableService private IDisposable HandleMarketTaxRates() { return this.MbTaxesObservable + .Select((taxes) => (taxes, GetUploaderInfo())) .Where(this.ShouldUpload) .SubscribeOn(ThreadPoolScheduler.Instance) .Subscribe( - taxes => + data => { + var (taxes, uploaderInfo) = data; + Log.Verbose( "MarketTaxRates: limsa#{0} grid#{1} uldah#{2} ish#{3} kugane#{4} cr#{5} sh#{6}", taxes.LimsaLominsaTax, @@ -484,7 +519,7 @@ internal unsafe class NetworkHandlers : IInternalDisposableService taxes.CrystariumTax, taxes.SharlayanTax); - Task.Run(() => this.uploader.UploadTax(taxes)) + Task.Run(() => this.uploader.UploadTax(taxes, uploaderInfo.UploaderId, uploaderInfo.WorldId)) .ContinueWith( task => Log.Error(task.Exception, "Market Board tax data upload failed"), TaskContinuationOptions.OnlyOnFaulted); @@ -495,13 +530,13 @@ internal unsafe class NetworkHandlers : IInternalDisposableService private IDisposable HandleMarketBoardPurchaseHandler() { return this.MbPurchaseSentObservable - .Zip(this.MbPurchaseObservable) + .Zip(this.MbPurchaseObservable, (handler, purchase) => (handler, purchase, GetUploaderInfo())) .Where(this.ShouldUpload) .SubscribeOn(ThreadPoolScheduler.Instance) .Subscribe( data => { - var (handler, purchase) = data; + var (handler, purchase, uploaderInfo) = data; var sameQty = purchase.ItemQuantity == handler.ItemQuantity; var itemMatch = purchase.CatalogId == handler.CatalogId; @@ -516,7 +551,7 @@ internal unsafe class NetworkHandlers : IInternalDisposableService handler.CatalogId, handler.PricePerUnit * purchase.ItemQuantity, handler.ListingId); - Task.Run(() => this.uploader.UploadPurchase(handler)) + Task.Run(() => this.uploader.UploadPurchase(handler, uploaderInfo.UploaderId, uploaderInfo.WorldId)) .ContinueWith( task => Log.Error(task.Exception, "Market Board purchase data upload failed"), TaskContinuationOptions.OnlyOnFaulted);