/// <inheritdoc/> public async Task UploadTax(MarketTaxRates taxRates) { var clientState = Service <ClientState.ClientState> .Get(); // ==================================================================================== var taxUploadObject = new UniversalisTaxUploadRequest { WorldId = clientState.LocalPlayer?.CurrentWorld.Id ?? 0, UploaderId = clientState.LocalContentId.ToString(), TaxData = new UniversalisTaxData { LimsaLominsa = taxRates.LimsaLominsaTax, Gridania = taxRates.GridaniaTax, Uldah = taxRates.UldahTax, Ishgard = taxRates.IshgardTax, Kugane = taxRates.KuganeTax, Crystarium = taxRates.CrystariumTax, Sharlayan = taxRates.SharlayanTax, }, }; var taxPath = "/upload"; var taxUpload = JsonConvert.SerializeObject(taxUploadObject); Log.Verbose($"{taxPath}: {taxUpload}"); await Util.HttpClient.PostAsync($"{ApiBase}{taxPath}/{ApiKey}", new StringContent(taxUpload, Encoding.UTF8, "application/json")); // ==================================================================================== Log.Verbose("Universalis tax upload completed."); }
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; 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."); } }
/// <summary> /// Read a <see cref="MarketTaxRates"/> object from memory. /// </summary> /// <param name="dataPtr">Address to read.</param> /// <returns>A new <see cref="MarketTaxRates"/> object.</returns> public static unsafe MarketTaxRates Read(IntPtr dataPtr) { using var stream = new UnmanagedMemoryStream((byte *)dataPtr.ToPointer(), 1544); using var reader = new BinaryReader(stream); var output = new MarketTaxRates(); 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); }
private void OnZonePacket(IntPtr dataPtr) { if (!this.dalamud.Data.IsDataReady) { return; } var opCode = (ushort)Marshal.ReadInt16(dataPtr, 2); if (opCode == this.dalamud.Data.ServerOpCodes["CfNotifyPop"]) { var data = new byte[64]; Marshal.Copy(dataPtr, data, 0, 64); var notifyType = data[16]; var contentFinderConditionId = BitConverter.ToUInt16(data, 36); if (notifyType != 3) { return; } var contentFinderCondition = this.dalamud.Data.GetExcelSheet <ContentFinderCondition>().GetRow(contentFinderConditionId); if (contentFinderCondition == null) { Log.Error("CFC key {0} not in lumina data.", contentFinderConditionId); return; } if (string.IsNullOrEmpty(contentFinderCondition.Name)) { contentFinderCondition.Name = "Duty Roulette"; contentFinderCondition.Image = 112324; } var flashInfo = new NativeFunctions.FLASHWINFO(); flashInfo.cbSize = (uint)Marshal.SizeOf <NativeFunctions.FLASHWINFO>(); flashInfo.uCount = uint.MaxValue; flashInfo.dwTimeout = 0; flashInfo.dwFlags = NativeFunctions.FlashWindow.FLASHW_TRAY | NativeFunctions.FlashWindow.FLASHW_TIMERNOFG; flashInfo.hwnd = Process.GetCurrentProcess().MainWindowHandle; NativeFunctions.FlashWindowEx(ref flashInfo); Task.Run(async() => { this.dalamud.Framework.Gui.Chat.Print("Duty pop: " + contentFinderCondition.Name); await this.ProcessCfPop?.Invoke(contentFinderCondition); }); return; } if (opCode == this.dalamud.Data.ServerOpCodes["CfPreferredRole"]) { if (this.dalamud.Configuration.PreferredRoleReminders == null) { return; } var data = new byte[64]; Marshal.Copy(dataPtr, data, 0, 32); if (this.lastPreferredRole == null) { this.lastPreferredRole = data; return; } Task.Run(async() => { for (var rouletteIndex = 1; rouletteIndex < 11; rouletteIndex++) { var currentRoleKey = data[16 + rouletteIndex]; var prevRoleKey = this.lastPreferredRole[16 + rouletteIndex]; Log.Verbose("CfPreferredRole: {0} - {1} => {2}", rouletteIndex, prevRoleKey, currentRoleKey); if (currentRoleKey != prevRoleKey) { var rouletteName = rouletteIndex switch { 1 => "Duty Roulette: Leveling", 2 => "Duty Roulette: Level 50/60/70 Dungeons", 3 => "Duty Roulette: Main Scenario", 4 => "Duty Roulette: Guildhests", 5 => "Duty Roulette: Expert", 6 => "Duty Roulette: Trials", 8 => "Duty Roulette: Mentor", 9 => "Duty Roulette: Alliance Raids", 10 => "Duty Roulette: Normal Raids", _ => "Unknown ContentRoulette" }; var prevRoleName = RoleKeyToPreferredRole(prevRoleKey); var currentRoleName = RoleKeyToPreferredRole(currentRoleKey); if (!this.dalamud.Configuration.PreferredRoleReminders.TryGetValue(rouletteIndex, out var roleToCheck)) { return; } if (roleToCheck == DalamudConfiguration.PreferredRole.All || currentRoleName != roleToCheck) { return; } this.dalamud.Framework.Gui.Chat.Print($"Roulette bonus for {rouletteName} changed: {prevRoleName} => {currentRoleName}"); if (this.dalamud.BotManager.IsConnected) { await this.dalamud.BotManager.ProcessCfPreferredRoleChange(rouletteName, prevRoleName.ToString(), currentRoleName.ToString()); } } } this.lastPreferredRole = data; }); return; } if (!this.optOutMbUploads) { if (opCode == this.dalamud.Data.ServerOpCodes["MarketBoardItemRequestStart"]) { var catalogId = (uint)Marshal.ReadInt32(dataPtr + 0x10); var amount = Marshal.ReadByte(dataPtr + 0x1B); this.marketBoardRequests.Add(new MarketBoardItemRequest { CatalogId = catalogId, AmountToArrive = amount, Listings = new List <MarketBoardCurrentOfferings.MarketBoardItemListing>(), History = new List <MarketBoardHistory.MarketBoardHistoryListing>() }); Log.Verbose($"NEW MB REQUEST START: item#{catalogId} amount#{amount}"); return; } if (opCode == this.dalamud.Data.ServerOpCodes["MarketBoardOfferings"]) { var listing = MarketBoardCurrentOfferings.Read(dataPtr + 0x10); 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}"); 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}"); return; } 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}"); return; } 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); 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) { Log.Error(ex, "Market Board data upload failed."); } } return; } if (opCode == this.dalamud.Data.ServerOpCodes["MarketBoardHistory"]) { var listing = MarketBoardHistory.Read(dataPtr + 0x10); var request = this.marketBoardRequests.LastOrDefault(r => r.CatalogId == listing.CatalogId); if (request == null) { Log.Error( $"Market Board data arrived without a corresponding request: item#{listing.CatalogId}"); return; } if (request.ListingsRequestId != -1) { Log.Error( $"Market Board data history sequence break: {request.ListingsRequestId}, {request.Listings.Count}"); return; } request.History.AddRange(listing.HistoryListings); Log.Verbose("Added history for item#{0}", listing.CatalogId); } if (opCode == this.dalamud.Data.ServerOpCodes["MarketTaxRates"]) { var taxes = MarketTaxRates.Read(dataPtr + 0x10); 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)); } catch (Exception ex) { Log.Error(ex, "Market Board data upload failed."); } } } }
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"]) { var data = new byte[64]; Marshal.Copy(dataPtr, data, 0, 64); var notifyType = data[0]; var contentFinderConditionId = BitConverter.ToUInt16(data, 0x14); if (notifyType != 3) { return; } var contentFinderCondition = this.dalamud.Data.GetExcelSheet <ContentFinderCondition>().GetRow(contentFinderConditionId); if (contentFinderCondition == null) { Log.Error("CFC key {0} not in lumina data.", contentFinderConditionId); return; } var cfcName = contentFinderCondition.Name.ToString(); if (string.IsNullOrEmpty(contentFinderCondition.Name)) { cfcName = "Duty Roulette"; contentFinderCondition.Image = 112324; } if (this.dalamud.Configuration.DutyFinderTaskbarFlash && !NativeFunctions.ApplicationIsActivated()) { var flashInfo = new NativeFunctions.FLASHWINFO { cbSize = (uint)Marshal.SizeOf <NativeFunctions.FLASHWINFO>(), uCount = uint.MaxValue, dwTimeout = 0, dwFlags = NativeFunctions.FlashWindow.FLASHW_ALL | NativeFunctions.FlashWindow.FLASHW_TIMERNOFG, hwnd = Process.GetCurrentProcess().MainWindowHandle }; NativeFunctions.FlashWindowEx(ref flashInfo); } Task.Run(() => { if (this.dalamud.Configuration.DutyFinderChatMessage) { this.dalamud.Framework.Gui.Chat.Print("Duty pop: " + cfcName); } CfPop?.Invoke(this, contentFinderCondition); }); return; } 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 { CatalogId = catalogId, AmountToArrive = amount, Listings = new List <MarketBoardCurrentOfferings.MarketBoardItemListing>(), History = new List <MarketBoardHistory.MarketBoardHistoryListing>() }); Log.Verbose($"NEW MB REQUEST START: item#{catalogId} amount#{amount}"); return; } 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); 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}"); return; } 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}"); return; } 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); 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) { Log.Error(ex, "Market Board data upload failed."); } } return; } 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) { Log.Error( $"Market Board data arrived without a corresponding request: item#{listing.CatalogId}"); return; } if (request.ListingsRequestId != -1) { Log.Error( $"Market Board data history sequence break: {request.ListingsRequestId}, {request.Listings.Count}"); return; } request.History.AddRange(listing.HistoryListings); Log.Verbose("Added history for item#{0}", listing.CatalogId); if (request.AmountToArrive == 0) { Log.Verbose("Request had 0 amount, uploading now"); try { Task.Run(() => this.uploader.Upload(request)); } catch (Exception ex) { Log.Error(ex, "Market Board data upload failed."); } } } 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) { 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); try { Task.Run(() => this.uploader.UploadTax(taxes)); } catch (Exception ex) { Log.Error(ex, "Market Board data upload failed."); } } } }