Fetch market board uploader info from main thread (#2158)

This commit is contained in:
Haselnussbomber 2024-12-26 16:39:54 +01:00 committed by GitHub
parent 0a3e88efca
commit f98da094f4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 62 additions and 38 deletions

View file

@ -13,20 +13,26 @@ internal interface IMarketBoardUploader
/// Upload data about an item.
/// </summary>
/// <param name="item">The item request data being uploaded.</param>
/// <param name="uploaderId">The uploaders ContentId.</param>
/// <param name="worldId">The uploaders WorldId.</param>
/// <returns>An async task.</returns>
Task Upload(MarketBoardItemRequest item);
Task Upload(MarketBoardItemRequest item, ulong uploaderId, uint worldId);
/// <summary>
/// Upload tax rate data.
/// </summary>
/// <param name="taxRates">The tax rate data being uploaded.</param>
/// <param name="uploaderId">The uploaders ContentId.</param>
/// <param name="worldId">The uploaders WorldId.</param>
/// <returns>An async task.</returns>
Task UploadTax(MarketTaxRates taxRates);
Task UploadTax(MarketTaxRates taxRates, ulong uploaderId, uint worldId);
/// <summary>
/// Upload information about a purchase this client has made.
/// </summary>
/// <param name="purchaseHandler">The purchase handler data associated with the sale.</param>
/// <param name="uploaderId">The uploaders ContentId.</param>
/// <param name="worldId">The uploaders WorldId.</param>
/// <returns>An async task.</returns>
Task UploadPurchase(MarketBoardPurchaseHandler purchaseHandler);
Task UploadPurchase(MarketBoardPurchaseHandler purchaseHandler, ulong uploaderId, uint worldId);
}

View file

@ -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;
/// <inheritdoc/>
public async Task Upload(MarketBoardItemRequest request)
public async Task Upload(MarketBoardItemRequest request, ulong uploaderId, uint worldId)
{
var clientState = Service<ClientState.ClientState>.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
}
/// <inheritdoc/>
public async Task UploadTax(MarketTaxRates taxRates)
public async Task UploadTax(MarketTaxRates taxRates, ulong uploaderId, uint worldId)
{
var clientState = Service<ClientState.ClientState>.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.
/// </remarks>
public async Task UploadPurchase(MarketBoardPurchaseHandler purchaseHandler)
public async Task UploadPurchase(MarketBoardPurchaseHandler purchaseHandler, ulong uploaderId, uint worldId)
{
var clientState = Service<ClientState.ClientState>.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";

View file

@ -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<MarketBoardHistory.MarketBoardHistoryListing> Sales) sales,
ICollection<MarketBoardCurrentOfferings.MarketBoardItemListing> listings)
ICollection<MarketBoardCurrentOfferings.MarketBoardItemListing> 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);