mirror of
https://github.com/goatcorp/Dalamud.git
synced 2026-01-02 05:43:40 +01:00
StyleCop: everything else
This commit is contained in:
parent
f64c9b8321
commit
595fd3f1e4
134 changed files with 16346 additions and 6202 deletions
|
|
@ -1,16 +1,21 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
using Dalamud.Game.Network.Structures;
|
||||
|
||||
namespace Dalamud.Game.Network {
|
||||
internal class MarketBoardItemRequest {
|
||||
namespace Dalamud.Game.Network
|
||||
{
|
||||
internal class MarketBoardItemRequest
|
||||
{
|
||||
public uint CatalogId { get; set; }
|
||||
|
||||
public byte AmountToArrive { get; set; }
|
||||
|
||||
public List<MarketBoardCurrentOfferings.MarketBoardItemListing> Listings { get; set; }
|
||||
|
||||
public List<MarketBoardHistory.MarketBoardHistoryListing> History { get; set; }
|
||||
|
||||
public int ListingsRequestId { get; set; } = -1;
|
||||
|
||||
public bool IsDone => Listings.Count == AmountToArrive && History.Count != 0;
|
||||
public bool IsDone => this.Listings.Count == this.AmountToArrive && this.History.Count != 0;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,22 @@
|
|||
using Dalamud.Game.Network.Structures;
|
||||
|
||||
namespace Dalamud.Game.Network.MarketBoardUploaders {
|
||||
internal interface IMarketBoardUploader {
|
||||
void Upload(MarketBoardItemRequest itemRequest);
|
||||
namespace Dalamud.Game.Network.MarketBoardUploaders
|
||||
{
|
||||
/// <summary>
|
||||
/// An interface binding for the Universalis uploader.
|
||||
/// </summary>
|
||||
internal interface IMarketBoardUploader
|
||||
{
|
||||
/// <summary>
|
||||
/// Upload data about an item.
|
||||
/// </summary>
|
||||
/// <param name="item">The item request data being uploaded.</param>
|
||||
void Upload(MarketBoardItemRequest item);
|
||||
|
||||
/// <summary>
|
||||
/// Upload tax rate data.
|
||||
/// </summary>
|
||||
/// <param name="taxRates">The tax rate data being uploaded.</param>
|
||||
void UploadTax(MarketTaxRates taxRates);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,28 +1,57 @@
|
|||
using Newtonsoft.Json;
|
||||
|
||||
namespace Dalamud.Game.Network.MarketBoardUploaders.Universalis {
|
||||
internal class UniversalisHistoryEntry {
|
||||
namespace Dalamud.Game.Network.MarketBoardUploaders.Universalis
|
||||
{
|
||||
/// <summary>
|
||||
/// A Universalis API structure.
|
||||
/// </summary>
|
||||
internal class UniversalisHistoryEntry
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the item is HQ or not.
|
||||
/// </summary>
|
||||
[JsonProperty("hq")]
|
||||
public bool Hq { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the item price per unit.
|
||||
/// </summary>
|
||||
[JsonProperty("pricePerUnit")]
|
||||
public uint PricePerUnit { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the quantity of items available.
|
||||
/// </summary>
|
||||
[JsonProperty("quantity")]
|
||||
public uint Quantity { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the name of the buyer.
|
||||
/// </summary>
|
||||
[JsonProperty("buyerName")]
|
||||
public string BuyerName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this item was on a mannequin.
|
||||
/// </summary>
|
||||
[JsonProperty("onMannequin")]
|
||||
public bool OnMannequin { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the seller ID.
|
||||
/// </summary>
|
||||
[JsonProperty("sellerID")]
|
||||
public string SellerId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the buyer ID.
|
||||
/// </summary>
|
||||
[JsonProperty("buyerID")]
|
||||
public string BuyerId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the timestamp of the transaction.
|
||||
/// </summary>
|
||||
[JsonProperty("timestamp")]
|
||||
public long Timestamp { get; set; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,17 +1,35 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Dalamud.Game.Network.MarketBoardUploaders.Universalis {
|
||||
internal class UniversalisHistoryUploadRequest {
|
||||
namespace Dalamud.Game.Network.MarketBoardUploaders.Universalis
|
||||
{
|
||||
/// <summary>
|
||||
/// A Universalis API structure.
|
||||
/// </summary>
|
||||
internal class UniversalisHistoryUploadRequest
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the world ID.
|
||||
/// </summary>
|
||||
[JsonProperty("worldID")]
|
||||
public uint WorldId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the item ID.
|
||||
/// </summary>
|
||||
[JsonProperty("itemID")]
|
||||
public uint ItemId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the list of available entries.
|
||||
/// </summary>
|
||||
[JsonProperty("entries")]
|
||||
public List<UniversalisHistoryEntry> Entries { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the uploader ID.
|
||||
/// </summary>
|
||||
[JsonProperty("uploaderID")]
|
||||
public string UploaderId { get; set; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,47 +1,95 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Dalamud.Game.Network.MarketBoardUploaders.Universalis {
|
||||
internal class UniversalisItemListingsEntry {
|
||||
namespace Dalamud.Game.Network.MarketBoardUploaders.Universalis
|
||||
{
|
||||
/// <summary>
|
||||
/// A Universalis API structure.
|
||||
/// </summary>
|
||||
internal class UniversalisItemListingsEntry
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the listing ID.
|
||||
/// </summary>
|
||||
[JsonProperty("listingID")]
|
||||
public string ListingId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the item is HQ.
|
||||
/// </summary>
|
||||
[JsonProperty("hq")]
|
||||
public bool Hq { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the item price per unit.
|
||||
/// </summary>
|
||||
[JsonProperty("pricePerUnit")]
|
||||
public uint PricePerUnit { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the item quantity.
|
||||
/// </summary>
|
||||
[JsonProperty("quantity")]
|
||||
public uint Quantity { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the name of the retainer selling the item.
|
||||
/// </summary>
|
||||
[JsonProperty("retainerName")]
|
||||
public string RetainerName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the ID of the retainer selling the item.
|
||||
/// </summary>
|
||||
[JsonProperty("retainerID")]
|
||||
public string RetainerId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the name of the user who created the entry.
|
||||
/// </summary>
|
||||
[JsonProperty("creatorName")]
|
||||
public string CreatorName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the item is on a mannequin.
|
||||
/// </summary>
|
||||
[JsonProperty("onMannequin")]
|
||||
public bool OnMannequin { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the seller ID.
|
||||
/// </summary>
|
||||
[JsonProperty("sellerID")]
|
||||
public string SellerId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the ID of the user who created the entry.
|
||||
/// </summary>
|
||||
[JsonProperty("creatorID")]
|
||||
public string CreatorId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the ID of the dye on the item.
|
||||
/// </summary>
|
||||
[JsonProperty("stainID")]
|
||||
public int StainId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the city where the selling retainer resides.
|
||||
/// </summary>
|
||||
[JsonProperty("retainerCity")]
|
||||
public int RetainerCity { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the last time the entry was reviewed.
|
||||
/// </summary>
|
||||
[JsonProperty("lastReviewTime")]
|
||||
public long LastReviewTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the materia attached to the item.
|
||||
/// </summary>
|
||||
[JsonProperty("materia")]
|
||||
public List<UniversalisItemMateria> Materia { get; set; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,17 +1,35 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Dalamud.Game.Network.MarketBoardUploaders.Universalis {
|
||||
internal class UniversalisItemListingsUploadRequest {
|
||||
namespace Dalamud.Game.Network.MarketBoardUploaders.Universalis
|
||||
{
|
||||
/// <summary>
|
||||
/// A Universalis API structure.
|
||||
/// </summary>
|
||||
internal class UniversalisItemListingsUploadRequest
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the world ID.
|
||||
/// </summary>
|
||||
[JsonProperty("worldID")]
|
||||
public uint WorldId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the item ID.
|
||||
/// </summary>
|
||||
[JsonProperty("itemID")]
|
||||
public uint ItemId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the list of available items.
|
||||
/// </summary>
|
||||
[JsonProperty("listings")]
|
||||
public List<UniversalisItemListingsEntry> Listings { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the uploader ID.
|
||||
/// </summary>
|
||||
[JsonProperty("uploaderID")]
|
||||
public string UploaderId { get; set; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,21 @@
|
|||
using Newtonsoft.Json;
|
||||
|
||||
namespace Dalamud.Game.Network.MarketBoardUploaders.Universalis {
|
||||
internal class UniversalisItemMateria {
|
||||
namespace Dalamud.Game.Network.MarketBoardUploaders.Universalis
|
||||
{
|
||||
/// <summary>
|
||||
/// A Universalis API structure.
|
||||
/// </summary>
|
||||
internal class UniversalisItemMateria
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the item slot ID.
|
||||
/// </summary>
|
||||
[JsonProperty("slotID")]
|
||||
public int SlotId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the materia ID.
|
||||
/// </summary>
|
||||
[JsonProperty("materiaID")]
|
||||
public int MateriaId { get; set; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,117 +1,140 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
|
||||
using Dalamud.Game.Network.MarketBoardUploaders;
|
||||
using Dalamud.Game.Network.MarketBoardUploaders.Universalis;
|
||||
using Dalamud.Game.Network.Structures;
|
||||
using Newtonsoft.Json;
|
||||
using Serilog;
|
||||
|
||||
namespace Dalamud.Game.Network.Universalis.MarketBoardUploaders {
|
||||
internal class UniversalisMarketBoardUploader : IMarketBoardUploader {
|
||||
namespace Dalamud.Game.Network.Universalis.MarketBoardUploaders
|
||||
{
|
||||
/// <summary>
|
||||
/// This class represents an uploader for contributing data to Universalis.
|
||||
/// </summary>
|
||||
internal class UniversalisMarketBoardUploader : IMarketBoardUploader
|
||||
{
|
||||
private const string ApiBase = "https://universalis.app";
|
||||
|
||||
//private const string ApiBase = "https://127.0.0.1:443";
|
||||
// private const string ApiBase = "https://127.0.0.1:443";
|
||||
private const string ApiKey = "GGD6RdSfGyRiHM5WDnAo0Nj9Nv7aC5NDhMj3BebT";
|
||||
|
||||
private readonly Dalamud dalamud;
|
||||
|
||||
public UniversalisMarketBoardUploader(Dalamud dalamud) {
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="UniversalisMarketBoardUploader"/> class.
|
||||
/// </summary>
|
||||
/// <param name="dalamud">The Dalamud instance.</param>
|
||||
public UniversalisMarketBoardUploader(Dalamud dalamud)
|
||||
{
|
||||
this.dalamud = dalamud;
|
||||
}
|
||||
|
||||
public void Upload(MarketBoardItemRequest request) {
|
||||
using (var client = new WebClient()) {
|
||||
client.Headers.Add(HttpRequestHeader.ContentType, "application/json");
|
||||
/// <inheritdoc/>
|
||||
public void Upload(MarketBoardItemRequest request)
|
||||
{
|
||||
using var client = new WebClient();
|
||||
|
||||
Log.Verbose("Starting Universalis upload.");
|
||||
var uploader = this.dalamud.ClientState.LocalContentId;
|
||||
client.Headers.Add(HttpRequestHeader.ContentType, "application/json");
|
||||
|
||||
var listingsRequestObject = new UniversalisItemListingsUploadRequest();
|
||||
listingsRequestObject.WorldId = this.dalamud.ClientState.LocalPlayer?.CurrentWorld.Id ?? 0;
|
||||
listingsRequestObject.UploaderId = uploader.ToString();
|
||||
listingsRequestObject.ItemId = request.CatalogId;
|
||||
Log.Verbose("Starting Universalis upload.");
|
||||
var uploader = this.dalamud.ClientState.LocalContentId;
|
||||
|
||||
listingsRequestObject.Listings = new List<UniversalisItemListingsEntry>();
|
||||
foreach (var marketBoardItemListing in request.Listings) {
|
||||
var universalisListing = new UniversalisItemListingsEntry {
|
||||
Hq = marketBoardItemListing.IsHq,
|
||||
SellerId = marketBoardItemListing.RetainerOwnerId.ToString(),
|
||||
RetainerName = marketBoardItemListing.RetainerName,
|
||||
RetainerId = marketBoardItemListing.RetainerId.ToString(),
|
||||
CreatorId = marketBoardItemListing.ArtisanId.ToString(),
|
||||
CreatorName = marketBoardItemListing.PlayerName,
|
||||
OnMannequin = marketBoardItemListing.OnMannequin,
|
||||
LastReviewTime = ((DateTimeOffset) marketBoardItemListing.LastReviewTime).ToUnixTimeSeconds(),
|
||||
PricePerUnit = marketBoardItemListing.PricePerUnit,
|
||||
Quantity = marketBoardItemListing.ItemQuantity,
|
||||
RetainerCity = marketBoardItemListing.RetainerCityId
|
||||
};
|
||||
var listingsRequestObject = new UniversalisItemListingsUploadRequest();
|
||||
listingsRequestObject.WorldId = this.dalamud.ClientState.LocalPlayer?.CurrentWorld.Id ?? 0;
|
||||
listingsRequestObject.UploaderId = uploader.ToString();
|
||||
listingsRequestObject.ItemId = request.CatalogId;
|
||||
|
||||
universalisListing.Materia = new List<UniversalisItemMateria>();
|
||||
foreach (var itemMateria in marketBoardItemListing.Materia)
|
||||
universalisListing.Materia.Add(new UniversalisItemMateria {
|
||||
MateriaId = itemMateria.MateriaId,
|
||||
SlotId = itemMateria.Index
|
||||
});
|
||||
|
||||
listingsRequestObject.Listings.Add(universalisListing);
|
||||
}
|
||||
|
||||
var upload = JsonConvert.SerializeObject(listingsRequestObject);
|
||||
client.UploadString(ApiBase + $"/upload/{ApiKey}", "POST", upload);
|
||||
Log.Verbose(upload);
|
||||
|
||||
var historyRequestObject = new UniversalisHistoryUploadRequest();
|
||||
historyRequestObject.WorldId = this.dalamud.ClientState.LocalPlayer?.CurrentWorld.Id ?? 0;
|
||||
historyRequestObject.UploaderId = uploader.ToString();
|
||||
historyRequestObject.ItemId = request.CatalogId;
|
||||
|
||||
historyRequestObject.Entries = new List<UniversalisHistoryEntry>();
|
||||
foreach (var marketBoardHistoryListing in request.History)
|
||||
historyRequestObject.Entries.Add(new UniversalisHistoryEntry {
|
||||
BuyerName = marketBoardHistoryListing.BuyerName,
|
||||
Hq = marketBoardHistoryListing.IsHq,
|
||||
OnMannequin = marketBoardHistoryListing.OnMannequin,
|
||||
PricePerUnit = marketBoardHistoryListing.SalePrice,
|
||||
Quantity = marketBoardHistoryListing.Quantity,
|
||||
Timestamp = ((DateTimeOffset) marketBoardHistoryListing.PurchaseTime).ToUnixTimeSeconds()
|
||||
});
|
||||
|
||||
client.Headers.Add(HttpRequestHeader.ContentType, "application/json");
|
||||
|
||||
var historyUpload = JsonConvert.SerializeObject(historyRequestObject);
|
||||
client.UploadString(ApiBase + $"/upload/{ApiKey}", "POST", historyUpload);
|
||||
Log.Verbose(historyUpload);
|
||||
|
||||
Log.Verbose("Universalis data upload for item#{0} completed.", request.CatalogId);
|
||||
}
|
||||
}
|
||||
|
||||
public void UploadTax(MarketTaxRates taxRates) {
|
||||
using (var client = new WebClient())
|
||||
listingsRequestObject.Listings = new List<UniversalisItemListingsEntry>();
|
||||
foreach (var marketBoardItemListing in request.Listings)
|
||||
{
|
||||
var taxRatesRequest = new UniversalisTaxUploadRequest();
|
||||
taxRatesRequest.WorldId = this.dalamud.ClientState.LocalPlayer?.CurrentWorld.Id ?? 0;
|
||||
taxRatesRequest.UploaderId = this.dalamud.ClientState.LocalContentId.ToString();
|
||||
|
||||
taxRatesRequest.TaxData = new UniversalisTaxData {
|
||||
LimsaLominsa = taxRates.LimsaLominsaTax,
|
||||
Gridania = taxRates.GridaniaTax,
|
||||
Uldah = taxRates.UldahTax,
|
||||
Ishgard = taxRates.IshgardTax,
|
||||
Kugane = taxRates.KuganeTax,
|
||||
Crystarium = taxRates.CrystariumTax
|
||||
var universalisListing = new UniversalisItemListingsEntry
|
||||
{
|
||||
Hq = marketBoardItemListing.IsHq,
|
||||
SellerId = marketBoardItemListing.RetainerOwnerId.ToString(),
|
||||
RetainerName = marketBoardItemListing.RetainerName,
|
||||
RetainerId = marketBoardItemListing.RetainerId.ToString(),
|
||||
CreatorId = marketBoardItemListing.ArtisanId.ToString(),
|
||||
CreatorName = marketBoardItemListing.PlayerName,
|
||||
OnMannequin = marketBoardItemListing.OnMannequin,
|
||||
LastReviewTime = ((DateTimeOffset)marketBoardItemListing.LastReviewTime).ToUnixTimeSeconds(),
|
||||
PricePerUnit = marketBoardItemListing.PricePerUnit,
|
||||
Quantity = marketBoardItemListing.ItemQuantity,
|
||||
RetainerCity = marketBoardItemListing.RetainerCityId,
|
||||
};
|
||||
|
||||
client.Headers.Add(HttpRequestHeader.ContentType, "application/json");
|
||||
universalisListing.Materia = new List<UniversalisItemMateria>();
|
||||
foreach (var itemMateria in marketBoardItemListing.Materia)
|
||||
{
|
||||
universalisListing.Materia.Add(new UniversalisItemMateria
|
||||
{
|
||||
MateriaId = itemMateria.MateriaId,
|
||||
SlotId = itemMateria.Index,
|
||||
});
|
||||
}
|
||||
|
||||
var historyUpload = JsonConvert.SerializeObject(taxRatesRequest);
|
||||
client.UploadString(ApiBase + $"/upload/{ApiKey}", "POST", historyUpload);
|
||||
Log.Verbose(historyUpload);
|
||||
|
||||
Log.Verbose("Universalis tax upload completed.");
|
||||
listingsRequestObject.Listings.Add(universalisListing);
|
||||
}
|
||||
|
||||
var upload = JsonConvert.SerializeObject(listingsRequestObject);
|
||||
client.UploadString(ApiBase + $"/upload/{ApiKey}", "POST", upload);
|
||||
Log.Verbose(upload);
|
||||
|
||||
var historyRequestObject = new UniversalisHistoryUploadRequest();
|
||||
historyRequestObject.WorldId = this.dalamud.ClientState.LocalPlayer?.CurrentWorld.Id ?? 0;
|
||||
historyRequestObject.UploaderId = uploader.ToString();
|
||||
historyRequestObject.ItemId = request.CatalogId;
|
||||
|
||||
historyRequestObject.Entries = new List<UniversalisHistoryEntry>();
|
||||
foreach (var marketBoardHistoryListing in request.History)
|
||||
{
|
||||
historyRequestObject.Entries.Add(new UniversalisHistoryEntry
|
||||
{
|
||||
BuyerName = marketBoardHistoryListing.BuyerName,
|
||||
Hq = marketBoardHistoryListing.IsHq,
|
||||
OnMannequin = marketBoardHistoryListing.OnMannequin,
|
||||
PricePerUnit = marketBoardHistoryListing.SalePrice,
|
||||
Quantity = marketBoardHistoryListing.Quantity,
|
||||
Timestamp = ((DateTimeOffset)marketBoardHistoryListing.PurchaseTime).ToUnixTimeSeconds(),
|
||||
});
|
||||
}
|
||||
|
||||
client.Headers.Add(HttpRequestHeader.ContentType, "application/json");
|
||||
|
||||
var historyUpload = JsonConvert.SerializeObject(historyRequestObject);
|
||||
client.UploadString(ApiBase + $"/upload/{ApiKey}", "POST", historyUpload);
|
||||
Log.Verbose(historyUpload);
|
||||
|
||||
Log.Verbose("Universalis data upload for item#{0} completed.", request.CatalogId);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void UploadTax(MarketTaxRates taxRates)
|
||||
{
|
||||
using var client = new WebClient();
|
||||
|
||||
var taxRatesRequest = new UniversalisTaxUploadRequest();
|
||||
taxRatesRequest.WorldId = this.dalamud.ClientState.LocalPlayer?.CurrentWorld.Id ?? 0;
|
||||
taxRatesRequest.UploaderId = this.dalamud.ClientState.LocalContentId.ToString();
|
||||
|
||||
taxRatesRequest.TaxData = new UniversalisTaxData
|
||||
{
|
||||
LimsaLominsa = taxRates.LimsaLominsaTax,
|
||||
Gridania = taxRates.GridaniaTax,
|
||||
Uldah = taxRates.UldahTax,
|
||||
Ishgard = taxRates.IshgardTax,
|
||||
Kugane = taxRates.KuganeTax,
|
||||
Crystarium = taxRates.CrystariumTax,
|
||||
};
|
||||
|
||||
client.Headers.Add(HttpRequestHeader.ContentType, "application/json");
|
||||
|
||||
var historyUpload = JsonConvert.SerializeObject(taxRatesRequest);
|
||||
client.UploadString(ApiBase + $"/upload/{ApiKey}", "POST", historyUpload);
|
||||
Log.Verbose(historyUpload);
|
||||
|
||||
Log.Verbose("Universalis tax upload completed.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,46 @@
|
|||
using Newtonsoft.Json;
|
||||
|
||||
namespace Dalamud.Game.Network.MarketBoardUploaders.Universalis
|
||||
{
|
||||
/// <summary>
|
||||
/// A Universalis API structure.
|
||||
/// </summary>
|
||||
internal class UniversalisTaxData
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets Limsa Lominsa's current tax rate.
|
||||
/// </summary>
|
||||
[JsonProperty("limsaLominsa")]
|
||||
public uint LimsaLominsa { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets Gridania's current tax rate.
|
||||
/// </summary>
|
||||
[JsonProperty("gridania")]
|
||||
public uint Gridania { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets Ul'dah's current tax rate.
|
||||
/// </summary>
|
||||
[JsonProperty("uldah")]
|
||||
public uint Uldah { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets Ishgard's current tax rate.
|
||||
/// </summary>
|
||||
[JsonProperty("ishgard")]
|
||||
public uint Ishgard { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets Kugane's current tax rate.
|
||||
/// </summary>
|
||||
[JsonProperty("kugane")]
|
||||
public uint Kugane { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets The Crystarium's current tax rate.
|
||||
/// </summary>
|
||||
[JsonProperty("crystarium")]
|
||||
public uint Crystarium { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -1,41 +1,28 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Dalamud.Game.Network.MarketBoardUploaders.Universalis
|
||||
{
|
||||
class UniversalisTaxUploadRequest
|
||||
/// <summary>
|
||||
/// A Universalis API structure.
|
||||
/// </summary>
|
||||
internal class UniversalisTaxUploadRequest
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the uploader's ID.
|
||||
/// </summary>
|
||||
[JsonProperty("uploaderID")]
|
||||
public string UploaderId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the world to retrieve data from.
|
||||
/// </summary>
|
||||
[JsonProperty("worldID")]
|
||||
public uint WorldId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets tax data for each city's market.
|
||||
/// </summary>
|
||||
[JsonProperty("marketTaxRates")]
|
||||
public UniversalisTaxData TaxData { get; set; }
|
||||
}
|
||||
|
||||
class UniversalisTaxData {
|
||||
[JsonProperty("limsaLominsa")]
|
||||
public uint LimsaLominsa { get; set; }
|
||||
|
||||
[JsonProperty("gridania")]
|
||||
public uint Gridania { get; set; }
|
||||
|
||||
[JsonProperty("uldah")]
|
||||
public uint Uldah { get; set; }
|
||||
|
||||
[JsonProperty("ishgard")]
|
||||
public uint Ishgard { get; set; }
|
||||
|
||||
[JsonProperty("kugane")]
|
||||
public uint Kugane { get; set; }
|
||||
|
||||
[JsonProperty("crystarium")]
|
||||
public uint Crystarium { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,47 +4,58 @@ using System.Diagnostics;
|
|||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Dalamud.Game.Internal.Network;
|
||||
using Dalamud.Game.Network.MarketBoardUploaders;
|
||||
using Dalamud.Game.Network.Structures;
|
||||
using Dalamud.Game.Network.Universalis.MarketBoardUploaders;
|
||||
using Lumina.Excel;
|
||||
using Lumina.Excel.GeneratedSheets;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Serilog;
|
||||
|
||||
namespace Dalamud.Game.Network {
|
||||
public class NetworkHandlers {
|
||||
namespace Dalamud.Game.Network
|
||||
{
|
||||
/// <summary>
|
||||
/// This class handles network notifications and uploading Marketboard data.
|
||||
/// </summary>
|
||||
public class NetworkHandlers
|
||||
{
|
||||
private readonly Dalamud dalamud;
|
||||
|
||||
private readonly List<MarketBoardItemRequest> marketBoardRequests = new List<MarketBoardItemRequest>();
|
||||
private readonly List<MarketBoardItemRequest> marketBoardRequests = new();
|
||||
|
||||
private readonly bool optOutMbUploads;
|
||||
private readonly IMarketBoardUploader uploader;
|
||||
|
||||
/// <summary>
|
||||
/// Event which gets fired when a duty is ready.
|
||||
/// Initializes a new instance of the <see cref="NetworkHandlers"/> class.
|
||||
/// </summary>
|
||||
public event EventHandler<ContentFinderCondition> CfPop;
|
||||
|
||||
public NetworkHandlers(Dalamud dalamud, bool optOutMbUploads) {
|
||||
/// <param name="dalamud">The Dalamud instance.</param>
|
||||
/// <param name="optOutMbUploads">Whether the client should opt out of marketboard uploads.</param>
|
||||
public NetworkHandlers(Dalamud dalamud, bool optOutMbUploads)
|
||||
{
|
||||
this.dalamud = dalamud;
|
||||
this.optOutMbUploads = optOutMbUploads;
|
||||
|
||||
this.uploader = new UniversalisMarketBoardUploader(dalamud);
|
||||
|
||||
dalamud.Framework.Network.OnNetworkMessage += OnNetworkMessage;
|
||||
|
||||
dalamud.Framework.Network.OnNetworkMessage += this.OnNetworkMessage;
|
||||
}
|
||||
|
||||
private void OnNetworkMessage(IntPtr dataPtr, ushort opCode, uint sourceActorId, uint targetActorId, NetworkMessageDirection direction) {
|
||||
/// <summary>
|
||||
/// Event which gets fired when a duty is ready.
|
||||
/// </summary>
|
||||
public event EventHandler<ContentFinderCondition> CfPop;
|
||||
|
||||
private void OnNetworkMessage(IntPtr dataPtr, ushort opCode, uint sourceActorId, uint targetActorId, NetworkMessageDirection direction)
|
||||
{
|
||||
if (direction != NetworkMessageDirection.ZoneDown)
|
||||
return;
|
||||
|
||||
if (!this.dalamud.Data.IsDataReady)
|
||||
return;
|
||||
|
||||
if (opCode == this.dalamud.Data.ServerOpCodes["CfNotifyPop"]) {
|
||||
if (opCode == this.dalamud.Data.ServerOpCodes["CfNotifyPop"])
|
||||
{
|
||||
var data = new byte[64];
|
||||
Marshal.Copy(dataPtr, data, 0, 64);
|
||||
|
||||
|
|
@ -63,98 +74,114 @@ namespace Dalamud.Game.Network {
|
|||
}
|
||||
|
||||
var cfcName = contentFinderCondition.Name.ToString();
|
||||
if (string.IsNullOrEmpty(contentFinderCondition.Name)) {
|
||||
if (string.IsNullOrEmpty(contentFinderCondition.Name))
|
||||
{
|
||||
cfcName = "Duty Roulette";
|
||||
contentFinderCondition.Image = 112324;
|
||||
}
|
||||
|
||||
if (this.dalamud.Configuration.DutyFinderTaskbarFlash && !NativeFunctions.ApplicationIsActivated()) {
|
||||
var flashInfo = new NativeFunctions.FLASHWINFO
|
||||
if (this.dalamud.Configuration.DutyFinderTaskbarFlash && !NativeFunctions.ApplicationIsActivated())
|
||||
{
|
||||
var flashInfo = new NativeFunctions.FlashWindowInfo
|
||||
{
|
||||
cbSize = (uint)Marshal.SizeOf<NativeFunctions.FLASHWINFO>(),
|
||||
cbSize = (uint)Marshal.SizeOf<NativeFunctions.FlashWindowInfo>(),
|
||||
uCount = uint.MaxValue,
|
||||
dwTimeout = 0,
|
||||
dwFlags = NativeFunctions.FlashWindow.FLASHW_ALL |
|
||||
NativeFunctions.FlashWindow.FLASHW_TIMERNOFG,
|
||||
hwnd = Process.GetCurrentProcess().MainWindowHandle
|
||||
dwFlags = NativeFunctions.FlashWindow.All | NativeFunctions.FlashWindow.TimerNoFG,
|
||||
hwnd = Process.GetCurrentProcess().MainWindowHandle,
|
||||
};
|
||||
NativeFunctions.FlashWindowEx(ref flashInfo);
|
||||
}
|
||||
|
||||
Task.Run(() => {
|
||||
if(this.dalamud.Configuration.DutyFinderChatMessage)
|
||||
Task.Run(() =>
|
||||
{
|
||||
if (this.dalamud.Configuration.DutyFinderChatMessage)
|
||||
this.dalamud.Framework.Gui.Chat.Print("Duty pop: " + cfcName);
|
||||
|
||||
CfPop?.Invoke(this, contentFinderCondition);
|
||||
this.CfPop?.Invoke(this, contentFinderCondition);
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.optOutMbUploads) {
|
||||
if (opCode == this.dalamud.Data.ServerOpCodes["MarketBoardItemRequestStart"]) {
|
||||
var catalogId = (uint) Marshal.ReadInt32(dataPtr);
|
||||
if (!this.optOutMbUploads)
|
||||
{
|
||||
if (opCode == this.dalamud.Data.ServerOpCodes["MarketBoardItemRequestStart"])
|
||||
{
|
||||
var catalogId = (uint)Marshal.ReadInt32(dataPtr);
|
||||
var amount = Marshal.ReadByte(dataPtr + 0xB);
|
||||
|
||||
this.marketBoardRequests.Add(new MarketBoardItemRequest {
|
||||
this.marketBoardRequests.Add(new MarketBoardItemRequest
|
||||
{
|
||||
CatalogId = catalogId,
|
||||
AmountToArrive = amount,
|
||||
Listings = new List<MarketBoardCurrentOfferings.MarketBoardItemListing>(),
|
||||
History = new List<MarketBoardHistory.MarketBoardHistoryListing>()
|
||||
History = new List<MarketBoardHistory.MarketBoardHistoryListing>(),
|
||||
});
|
||||
|
||||
Log.Verbose($"NEW MB REQUEST START: item#{catalogId} amount#{amount}");
|
||||
return;
|
||||
}
|
||||
|
||||
if (opCode == this.dalamud.Data.ServerOpCodes["MarketBoardOfferings"]) {
|
||||
if (opCode == this.dalamud.Data.ServerOpCodes["MarketBoardOfferings"])
|
||||
{
|
||||
var listing = MarketBoardCurrentOfferings.Read(dataPtr);
|
||||
|
||||
var request =
|
||||
this.marketBoardRequests.LastOrDefault(
|
||||
r => r.CatalogId == listing.ItemListings[0].CatalogId && !r.IsDone);
|
||||
var request = this.marketBoardRequests.LastOrDefault(r => r.CatalogId == listing.ItemListings[0].CatalogId && !r.IsDone);
|
||||
|
||||
if (request == null) {
|
||||
Log.Error(
|
||||
$"Market Board data arrived without a corresponding request: item#{listing.ItemListings[0].CatalogId}");
|
||||
if (request == null)
|
||||
{
|
||||
Log.Error($"Market Board data arrived without a corresponding request: item#{listing.ItemListings[0].CatalogId}");
|
||||
return;
|
||||
}
|
||||
|
||||
if (request.Listings.Count + listing.ItemListings.Count > request.AmountToArrive) {
|
||||
Log.Error(
|
||||
$"Too many Market Board listings received for request: {request.Listings.Count + listing.ItemListings.Count} > {request.AmountToArrive} item#{listing.ItemListings[0].CatalogId}");
|
||||
if (request.Listings.Count + listing.ItemListings.Count > request.AmountToArrive)
|
||||
{
|
||||
Log.Error($"Too many Market Board listings received for request: {request.Listings.Count + listing.ItemListings.Count} > {request.AmountToArrive} item#{listing.ItemListings[0].CatalogId}");
|
||||
return;
|
||||
}
|
||||
|
||||
if (request.ListingsRequestId != -1 && request.ListingsRequestId != listing.RequestId) {
|
||||
Log.Error(
|
||||
$"Non-matching RequestIds for Market Board data request: {request.ListingsRequestId}, {listing.RequestId}");
|
||||
if (request.ListingsRequestId != -1 && request.ListingsRequestId != listing.RequestId)
|
||||
{
|
||||
Log.Error($"Non-matching RequestIds for Market Board data request: {request.ListingsRequestId}, {listing.RequestId}");
|
||||
return;
|
||||
}
|
||||
|
||||
if (request.ListingsRequestId == -1 && request.Listings.Count > 0) {
|
||||
Log.Error(
|
||||
$"Market Board data request sequence break: {request.ListingsRequestId}, {request.Listings.Count}");
|
||||
if (request.ListingsRequestId == -1 && request.Listings.Count > 0)
|
||||
{
|
||||
Log.Error($"Market Board data request sequence break: {request.ListingsRequestId}, {request.Listings.Count}");
|
||||
return;
|
||||
}
|
||||
|
||||
if (request.ListingsRequestId == -1) {
|
||||
if (request.ListingsRequestId == -1)
|
||||
{
|
||||
request.ListingsRequestId = listing.RequestId;
|
||||
Log.Verbose($"First Market Board packet in sequence: {listing.RequestId}");
|
||||
}
|
||||
|
||||
request.Listings.AddRange(listing.ItemListings);
|
||||
|
||||
Log.Verbose("Added {0} ItemListings to request#{1}, now {2}/{3}, item#{4}",
|
||||
listing.ItemListings.Count, request.ListingsRequestId, request.Listings.Count,
|
||||
request.AmountToArrive, request.CatalogId);
|
||||
Log.Verbose(
|
||||
"Added {0} ItemListings to request#{1}, now {2}/{3}, item#{4}",
|
||||
listing.ItemListings.Count,
|
||||
request.ListingsRequestId,
|
||||
request.Listings.Count,
|
||||
request.AmountToArrive,
|
||||
request.CatalogId);
|
||||
|
||||
if (request.IsDone) {
|
||||
Log.Verbose("Market Board request finished, starting upload: request#{0} item#{1} amount#{2}",
|
||||
request.ListingsRequestId, request.CatalogId, request.AmountToArrive);
|
||||
try {
|
||||
if (request.IsDone)
|
||||
{
|
||||
Log.Verbose(
|
||||
"Market Board request finished, starting upload: request#{0} item#{1} amount#{2}",
|
||||
request.ListingsRequestId,
|
||||
request.CatalogId,
|
||||
request.AmountToArrive);
|
||||
try
|
||||
{
|
||||
Task.Run(() => this.uploader.Upload(request));
|
||||
} catch (Exception ex) {
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(ex, "Market Board data upload failed.");
|
||||
}
|
||||
}
|
||||
|
|
@ -162,18 +189,21 @@ namespace Dalamud.Game.Network {
|
|||
return;
|
||||
}
|
||||
|
||||
if (opCode == this.dalamud.Data.ServerOpCodes["MarketBoardHistory"]) {
|
||||
if (opCode == this.dalamud.Data.ServerOpCodes["MarketBoardHistory"])
|
||||
{
|
||||
var listing = MarketBoardHistory.Read(dataPtr);
|
||||
|
||||
var request = this.marketBoardRequests.LastOrDefault(r => r.CatalogId == listing.CatalogId);
|
||||
|
||||
if (request == null) {
|
||||
if (request == null)
|
||||
{
|
||||
Log.Error(
|
||||
$"Market Board data arrived without a corresponding request: item#{listing.CatalogId}");
|
||||
return;
|
||||
}
|
||||
|
||||
if (request.ListingsRequestId != -1) {
|
||||
if (request.ListingsRequestId != -1)
|
||||
{
|
||||
Log.Error(
|
||||
$"Market Board data history sequence break: {request.ListingsRequestId}, {request.Listings.Count}");
|
||||
return;
|
||||
|
|
@ -183,7 +213,8 @@ namespace Dalamud.Game.Network {
|
|||
|
||||
Log.Verbose("Added history for item#{0}", listing.CatalogId);
|
||||
|
||||
if (request.AmountToArrive == 0) {
|
||||
if (request.AmountToArrive == 0)
|
||||
{
|
||||
Log.Verbose("Request had 0 amount, uploading now");
|
||||
|
||||
try
|
||||
|
|
@ -197,17 +228,25 @@ namespace Dalamud.Game.Network {
|
|||
}
|
||||
}
|
||||
|
||||
if (opCode == this.dalamud.Data.ServerOpCodes["MarketTaxRates"]) {
|
||||
var category = (uint) Marshal.ReadInt32(dataPtr);
|
||||
if (opCode == this.dalamud.Data.ServerOpCodes["MarketTaxRates"])
|
||||
{
|
||||
var category = (uint)Marshal.ReadInt32(dataPtr);
|
||||
// Result dialog packet does not contain market tax rates
|
||||
if (category != 720905) {
|
||||
if (category != 720905)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var taxes = MarketTaxRates.Read(dataPtr);
|
||||
|
||||
Log.Verbose("MarketTaxRates: limsa#{0} grid#{1} uldah#{2} ish#{3} kugane#{4} cr#{5}",
|
||||
taxes.LimsaLominsaTax, taxes.GridaniaTax, taxes.UldahTax, taxes.IshgardTax, taxes.KuganeTax, taxes.CrystariumTax);
|
||||
Log.Verbose(
|
||||
"MarketTaxRates: limsa#{0} grid#{1} uldah#{2} ish#{3} kugane#{4} cr#{5}",
|
||||
taxes.LimsaLominsaTax,
|
||||
taxes.GridaniaTax,
|
||||
taxes.UldahTax,
|
||||
taxes.IshgardTax,
|
||||
taxes.KuganeTax,
|
||||
taxes.CrystariumTax);
|
||||
try
|
||||
{
|
||||
Task.Run(() => this.uploader.UploadTax(taxes));
|
||||
|
|
|
|||
|
|
@ -17,69 +17,66 @@ namespace Dalamud.Game.Network.Structures
|
|||
{
|
||||
var output = new MarketBoardCurrentOfferings();
|
||||
|
||||
using (var stream = new UnmanagedMemoryStream((byte*)dataPtr.ToPointer(), 1544))
|
||||
using var stream = new UnmanagedMemoryStream((byte*)dataPtr.ToPointer(), 1544);
|
||||
using var reader = new BinaryReader(stream);
|
||||
|
||||
output.ItemListings = new List<MarketBoardItemListing>();
|
||||
|
||||
for (var i = 0; i < 10; i++)
|
||||
{
|
||||
using (var reader = new BinaryReader(stream))
|
||||
var listingEntry = new MarketBoardItemListing();
|
||||
|
||||
listingEntry.ListingId = reader.ReadUInt64();
|
||||
listingEntry.RetainerId = reader.ReadUInt64();
|
||||
listingEntry.RetainerOwnerId = reader.ReadUInt64();
|
||||
listingEntry.ArtisanId = reader.ReadUInt64();
|
||||
listingEntry.PricePerUnit = reader.ReadUInt32();
|
||||
listingEntry.TotalTax = reader.ReadUInt32();
|
||||
listingEntry.ItemQuantity = reader.ReadUInt32();
|
||||
listingEntry.CatalogId = reader.ReadUInt32();
|
||||
listingEntry.LastReviewTime = DateTimeOffset.UtcNow.AddSeconds(-reader.ReadUInt16()).DateTime;
|
||||
|
||||
reader.ReadUInt16(); // container
|
||||
reader.ReadUInt32(); // slot
|
||||
reader.ReadUInt16(); // durability
|
||||
reader.ReadUInt16(); // spiritbond
|
||||
|
||||
listingEntry.Materia = new List<MarketBoardItemListing.ItemMateria>();
|
||||
|
||||
for (var materiaIndex = 0; materiaIndex < 5; materiaIndex++)
|
||||
{
|
||||
output.ItemListings = new List<MarketBoardItemListing>();
|
||||
var materiaVal = reader.ReadUInt16();
|
||||
|
||||
for (var i = 0; i < 10; i++)
|
||||
{
|
||||
var listingEntry = new MarketBoardItemListing();
|
||||
var materiaEntry = new MarketBoardItemListing.ItemMateria();
|
||||
materiaEntry.MateriaId = (materiaVal & 0xFF0) >> 4;
|
||||
materiaEntry.Index = materiaVal & 0xF;
|
||||
|
||||
listingEntry.ListingId = reader.ReadUInt64();
|
||||
listingEntry.RetainerId = reader.ReadUInt64();
|
||||
listingEntry.RetainerOwnerId = reader.ReadUInt64();
|
||||
listingEntry.ArtisanId = reader.ReadUInt64();
|
||||
listingEntry.PricePerUnit = reader.ReadUInt32();
|
||||
listingEntry.TotalTax = reader.ReadUInt32();
|
||||
listingEntry.ItemQuantity = reader.ReadUInt32();
|
||||
listingEntry.CatalogId = reader.ReadUInt32();
|
||||
listingEntry.LastReviewTime = DateTimeOffset.UtcNow.AddSeconds(-reader.ReadUInt16()).DateTime;
|
||||
|
||||
reader.ReadUInt16(); // container
|
||||
reader.ReadUInt32(); // slot
|
||||
reader.ReadUInt16(); // durability
|
||||
reader.ReadUInt16(); // spiritbond
|
||||
|
||||
listingEntry.Materia = new List<MarketBoardItemListing.ItemMateria>();
|
||||
|
||||
for (var materiaIndex = 0; materiaIndex < 5; materiaIndex++)
|
||||
{
|
||||
var materiaVal = reader.ReadUInt16();
|
||||
|
||||
var materiaEntry = new MarketBoardItemListing.ItemMateria();
|
||||
materiaEntry.MateriaId = (materiaVal & 0xFF0) >> 4;
|
||||
materiaEntry.Index = materiaVal & 0xF;
|
||||
|
||||
if (materiaEntry.MateriaId != 0)
|
||||
listingEntry.Materia.Add(materiaEntry);
|
||||
}
|
||||
|
||||
reader.ReadUInt16();
|
||||
reader.ReadUInt32();
|
||||
|
||||
listingEntry.RetainerName = Encoding.UTF8.GetString(reader.ReadBytes(32)).TrimEnd('\u0000');
|
||||
listingEntry.PlayerName = Encoding.UTF8.GetString(reader.ReadBytes(32)).TrimEnd('\u0000');
|
||||
listingEntry.IsHq = reader.ReadBoolean();
|
||||
listingEntry.MateriaCount = reader.ReadByte();
|
||||
listingEntry.OnMannequin = reader.ReadBoolean();
|
||||
listingEntry.RetainerCityId = reader.ReadByte();
|
||||
listingEntry.StainId = reader.ReadUInt16();
|
||||
|
||||
reader.ReadUInt16();
|
||||
reader.ReadUInt32();
|
||||
|
||||
if (listingEntry.CatalogId != 0)
|
||||
output.ItemListings.Add(listingEntry);
|
||||
}
|
||||
|
||||
output.ListingIndexEnd = reader.ReadByte();
|
||||
output.ListingIndexStart = reader.ReadByte();
|
||||
output.RequestId = reader.ReadUInt16();
|
||||
if (materiaEntry.MateriaId != 0)
|
||||
listingEntry.Materia.Add(materiaEntry);
|
||||
}
|
||||
|
||||
reader.ReadUInt16();
|
||||
reader.ReadUInt32();
|
||||
|
||||
listingEntry.RetainerName = Encoding.UTF8.GetString(reader.ReadBytes(32)).TrimEnd('\u0000');
|
||||
listingEntry.PlayerName = Encoding.UTF8.GetString(reader.ReadBytes(32)).TrimEnd('\u0000');
|
||||
listingEntry.IsHq = reader.ReadBoolean();
|
||||
listingEntry.MateriaCount = reader.ReadByte();
|
||||
listingEntry.OnMannequin = reader.ReadBoolean();
|
||||
listingEntry.RetainerCityId = reader.ReadByte();
|
||||
listingEntry.StainId = reader.ReadUInt16();
|
||||
|
||||
reader.ReadUInt16();
|
||||
reader.ReadUInt32();
|
||||
|
||||
if (listingEntry.CatalogId != 0)
|
||||
output.ItemListings.Add(listingEntry);
|
||||
}
|
||||
|
||||
output.ListingIndexEnd = reader.ReadByte();
|
||||
output.ListingIndexStart = reader.ReadByte();
|
||||
output.RequestId = reader.ReadUInt16();
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,47 +3,52 @@ using System.Collections.Generic;
|
|||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
namespace Dalamud.Game.Network.Structures {
|
||||
public class MarketBoardHistory {
|
||||
namespace Dalamud.Game.Network.Structures
|
||||
{
|
||||
public class MarketBoardHistory
|
||||
{
|
||||
public uint CatalogId;
|
||||
public uint CatalogId2;
|
||||
|
||||
public List<MarketBoardHistoryListing> HistoryListings;
|
||||
|
||||
public static unsafe MarketBoardHistory Read(IntPtr dataPtr) {
|
||||
public static unsafe MarketBoardHistory Read(IntPtr dataPtr)
|
||||
{
|
||||
var output = new MarketBoardHistory();
|
||||
|
||||
using (var stream = new UnmanagedMemoryStream((byte*) dataPtr.ToPointer(), 1544)) {
|
||||
using (var reader = new BinaryReader(stream)) {
|
||||
output.CatalogId = reader.ReadUInt32();
|
||||
output.CatalogId2 = reader.ReadUInt32();
|
||||
using var stream = new UnmanagedMemoryStream((byte*)dataPtr.ToPointer(), 1544);
|
||||
using var reader = new BinaryReader(stream);
|
||||
|
||||
output.HistoryListings = new List<MarketBoardHistoryListing>();
|
||||
output.CatalogId = reader.ReadUInt32();
|
||||
output.CatalogId2 = reader.ReadUInt32();
|
||||
|
||||
for (var i = 0; i < 10; i++) {
|
||||
var listingEntry = new MarketBoardHistoryListing();
|
||||
output.HistoryListings = new List<MarketBoardHistoryListing>();
|
||||
|
||||
listingEntry.SalePrice = reader.ReadUInt32();
|
||||
listingEntry.PurchaseTime = DateTimeOffset.FromUnixTimeSeconds(reader.ReadUInt32()).UtcDateTime;
|
||||
listingEntry.Quantity = reader.ReadUInt32();
|
||||
listingEntry.IsHq = reader.ReadBoolean();
|
||||
for (var i = 0; i < 10; i++)
|
||||
{
|
||||
var listingEntry = new MarketBoardHistoryListing
|
||||
{
|
||||
SalePrice = reader.ReadUInt32(),
|
||||
PurchaseTime = DateTimeOffset.FromUnixTimeSeconds(reader.ReadUInt32()).UtcDateTime,
|
||||
Quantity = reader.ReadUInt32(),
|
||||
IsHq = reader.ReadBoolean(),
|
||||
};
|
||||
|
||||
reader.ReadBoolean();
|
||||
reader.ReadBoolean();
|
||||
|
||||
listingEntry.OnMannequin = reader.ReadBoolean();
|
||||
listingEntry.BuyerName = Encoding.UTF8.GetString(reader.ReadBytes(33)).TrimEnd('\u0000');
|
||||
listingEntry.CatalogId = reader.ReadUInt32();
|
||||
listingEntry.OnMannequin = reader.ReadBoolean();
|
||||
listingEntry.BuyerName = Encoding.UTF8.GetString(reader.ReadBytes(33)).TrimEnd('\u0000');
|
||||
listingEntry.CatalogId = reader.ReadUInt32();
|
||||
|
||||
if (listingEntry.CatalogId != 0)
|
||||
output.HistoryListings.Add(listingEntry);
|
||||
}
|
||||
}
|
||||
if (listingEntry.CatalogId != 0)
|
||||
output.HistoryListings.Add(listingEntry);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
public class MarketBoardHistoryListing {
|
||||
public class MarketBoardHistoryListing
|
||||
{
|
||||
public string BuyerName;
|
||||
|
||||
public uint CatalogId;
|
||||
|
|
|
|||
|
|
@ -1,41 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
namespace Dalamud.Game.Network.Structures
|
||||
{
|
||||
public class MarketTaxRates
|
||||
{
|
||||
public uint LimsaLominsaTax;
|
||||
public uint GridaniaTax;
|
||||
public uint UldahTax;
|
||||
public uint IshgardTax;
|
||||
public uint KuganeTax;
|
||||
public uint CrystariumTax;
|
||||
|
||||
|
||||
public static unsafe MarketTaxRates Read(IntPtr dataPtr)
|
||||
{
|
||||
var output = new MarketTaxRates();
|
||||
|
||||
using (var stream = new UnmanagedMemoryStream((byte*)dataPtr.ToPointer(), 1544))
|
||||
{
|
||||
using (var reader = new BinaryReader(stream))
|
||||
{
|
||||
stream.Position += 8;
|
||||
|
||||
output.LimsaLominsaTax = reader.ReadUInt32();
|
||||
output.GridaniaTax = reader.ReadUInt32();
|
||||
output.UldahTax = reader.ReadUInt32();
|
||||
output.IshgardTax = reader.ReadUInt32();
|
||||
output.KuganeTax = reader.ReadUInt32();
|
||||
output.CrystariumTax = reader.ReadUInt32();
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
}
|
||||
}
|
||||
34
Dalamud/Game/Network/Structures/MarketTaxRates.cs
Normal file
34
Dalamud/Game/Network/Structures/MarketTaxRates.cs
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace Dalamud.Game.Network.Structures
|
||||
{
|
||||
public class MarketTaxRates
|
||||
{
|
||||
public uint LimsaLominsaTax;
|
||||
public uint GridaniaTax;
|
||||
public uint UldahTax;
|
||||
public uint IshgardTax;
|
||||
public uint KuganeTax;
|
||||
public uint CrystariumTax;
|
||||
|
||||
public static unsafe MarketTaxRates Read(IntPtr dataPtr)
|
||||
{
|
||||
var output = new MarketTaxRates();
|
||||
|
||||
using var stream = new UnmanagedMemoryStream((byte*)dataPtr.ToPointer(), 1544);
|
||||
using var reader = new BinaryReader(stream);
|
||||
|
||||
stream.Position += 8;
|
||||
|
||||
output.LimsaLominsaTax = reader.ReadUInt32();
|
||||
output.GridaniaTax = reader.ReadUInt32();
|
||||
output.UldahTax = reader.ReadUInt32();
|
||||
output.IshgardTax = reader.ReadUInt32();
|
||||
output.KuganeTax = reader.ReadUInt32();
|
||||
output.CrystariumTax = reader.ReadUInt32();
|
||||
|
||||
return output;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,28 +1,38 @@
|
|||
using Dalamud.Hooking;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Sockets;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Dalamud.Hooking;
|
||||
|
||||
namespace Dalamud.Game
|
||||
{
|
||||
/// <summary>
|
||||
/// This class enables TCP optimizations in the game socket for better performance.
|
||||
/// </summary>
|
||||
internal sealed class WinSockHandlers : IDisposable
|
||||
{
|
||||
[UnmanagedFunctionPointer(CallingConvention.Winapi)]
|
||||
private delegate IntPtr SocketDelegate(int af, int type, int protocol);
|
||||
private Hook<SocketDelegate> ws2SocketHook;
|
||||
|
||||
[DllImport("ws2_32.dll", CallingConvention = CallingConvention.Winapi)]
|
||||
private static extern int setsockopt(IntPtr socket, SocketOptionLevel level, SocketOptionName optName, ref IntPtr optVal, int optLen);
|
||||
|
||||
public WinSockHandlers() {
|
||||
this.ws2SocketHook = Hook<SocketDelegate>.FromSymbol("ws2_32.dll", "socket", new SocketDelegate(OnSocket));
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="WinSockHandlers"/> class.
|
||||
/// </summary>
|
||||
public WinSockHandlers()
|
||||
{
|
||||
this.ws2SocketHook = Hook<SocketDelegate>.FromSymbol("ws2_32.dll", "socket", new SocketDelegate(this.OnSocket));
|
||||
this.ws2SocketHook.Enable();
|
||||
}
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Winapi)]
|
||||
private delegate IntPtr SocketDelegate(int af, int type, int protocol);
|
||||
|
||||
/// <summary>
|
||||
/// Disposes of managed and unmanaged resources.
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
this.ws2SocketHook.Dispose();
|
||||
}
|
||||
|
||||
private IntPtr OnSocket(int af, int type, int protocol)
|
||||
{
|
||||
var socket = this.ws2SocketHook.Original(af, type, protocol);
|
||||
|
|
@ -30,26 +40,22 @@ namespace Dalamud.Game
|
|||
// IPPROTO_TCP
|
||||
if (type == 1)
|
||||
{
|
||||
// INVALID_SOCKET
|
||||
// INVALID_SOCKET
|
||||
if (socket != new IntPtr(-1))
|
||||
{
|
||||
// In case you're not aware of it: (albeit you should)
|
||||
// https://linux.die.net/man/7/tcp
|
||||
// https://assets.extrahop.com/whitepapers/TCP-Optimization-Guide-by-ExtraHop.pdf
|
||||
var value = new IntPtr(1);
|
||||
setsockopt(socket, SocketOptionLevel.Tcp, SocketOptionName.NoDelay, ref value, 4);
|
||||
NativeFunctions.SetSockOpt(socket, SocketOptionLevel.Tcp, SocketOptionName.NoDelay, ref value, 4);
|
||||
|
||||
// Enable tcp_quickack option. This option is undocumented in MSDN but it is supported in Windows 7 and onwards.
|
||||
value = new IntPtr(1);
|
||||
setsockopt(socket, SocketOptionLevel.Tcp, (SocketOptionName)12, ref value, 4);
|
||||
NativeFunctions.SetSockOpt(socket, SocketOptionLevel.Tcp, SocketOptionName.AddMembership, ref value, 4);
|
||||
}
|
||||
}
|
||||
|
||||
return socket;
|
||||
}
|
||||
|
||||
public void Dispose() {
|
||||
ws2SocketHook.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue