private void CalculatePing(IntPtr dataPtr, ushort opcode, NetworkMessageDirection direction) { if (direction == NetworkMessageDirection.ZoneDown && opcode == this.predictedDownOpcode) { // The response packet has the same timestamp as the request packet, so we can just // take it from here instead of keeping state. var prevMs = (uint)Marshal.ReadInt32(dataPtr); if (QueryPerformanceCounter(out var nextNs)) { var nextMs = nextNs / 10000; this.pingMs = nextMs - prevMs; this.gotPing = true; if (Verbose) { PluginLog.LogDebug("Packet ping: {LastPing}ms", this.pingMs); } } else { PluginLog.LogError("Failed to call QueryPerformanceCounter! (How can this happen?)"); } } }
static ActivityType ToNetworkActivityType(NetworkMessageDirection direction) { switch (direction) { case NetworkMessageDirection.Incoming: return(ActivityType.IncomingNetworking); case NetworkMessageDirection.Outgoing: return(ActivityType.OutgoingNetworking); default: return(ActivityType.Procedure); } }
private void OnNetworkMessage(IntPtr dataPtr, ushort opCode, uint targetId, NetworkMessageDirection direction) { if (!this.pluginInterface.Data.IsDataReady || this.pluginInterface.ClientState.LocalPlayer == null) { return; } if (direction == NetworkMessageDirection.ZoneUp) { if (opCode == 0x241) { this.pingTracker.StartNextRTTWait(); } } if (direction == NetworkMessageDirection.ZoneDown) { if (opCode == 0xC4 && targetId == this.pluginInterface.ClientState.LocalPlayer.ActorId) { this.pingTracker.StartNextRTTCalculation(); } } }
private void OnNetworkMessage(IntPtr dataPtr, ushort opcode, uint sourceActorId, uint targetActorId, NetworkMessageDirection direction) { if (OnNetworkContext == null) { return; } var header = new byte[IpcHeader.IpcHeaderLength]; if (direction == NetworkMessageDirection.ZoneDown) { Marshal.Copy(dataPtr - 0x20, header, 0, header.Length); } var data = new byte[maxByteLength]; Marshal.Copy(dataPtr, data, 0, data.Length); var context = new NetworkContext { Time = DateTime.Now, RawHeader = header, Opcode = opcode, Data = data, DataPtr = dataPtr, SourceActorId = sourceActorId, TargetActorId = targetActorId, Direction = direction, }; OnNetworkContext.Invoke(context); }
public NetworkMessageEvent(object trigger, string displayName, string messageId, ActivityEventType type, NetworkMessageDirection direction, int templateId = 0, ActivityStatus status = ActivityStatus.Unspecified) : base(trigger, displayName, messageId, type, templateId, status) { Direction = direction; }
private void OnNetworkMessage(IntPtr dataPtr, ushort opCode, uint sourceActorId, uint targetActorId, NetworkMessageDirection direction) { const ushort eventPlay = 0x02C3; // TODO: Get goat to hook the handlers for these const ushort eventFinish = 0x0239; if (opCode == eventPlay) { var packetData = Marshal.PtrToStructure <EventPlay>(dataPtr); if ((packetData.Flags & 0x00000400) != 0) // TODO: PR Sapphire, HIDE_UI seems to be wrong now { this.ui.CutsceneActive = true; } } else if (opCode == eventFinish) { this.ui.CutsceneActive = false; } }
private void OnNetworkEvent(IntPtr dataPtr, ushort opCode, uint sourceActorId, uint targetActorId, NetworkMessageDirection direction) { if (!this.configuration.Enabled) { return; } if (direction != NetworkMessageDirection.ZoneDown) { return; } if (!this.pi.Data.IsDataReady) { return; } if (opCode == this.pi.Data.ServerOpCodes["HousingWardInfo"]) { this.OnHousingWardInfo(dataPtr); } }
private void OnNetworkMessage(IntPtr dataPtr, ushort opcode, uint sourceId, uint targetId, NetworkMessageDirection direction) { // Tracking ping using ping packets is unreliable, because we can't confirm that the server // responds to the ping immediately. With ICMP, we know that this is true, but using packets, // messages on both the client and server are restrained by TCP ordering requirements. That // said, considering TCP-related latency in calculations is arguably more useful than a real // ping calculation. // Predict the up/down Ping opcodes if (!this.predictedUpOpcodeSet && direction == NetworkMessageDirection.ZoneUp) { // Client send, executes first TrackPredictedPingUp(dataPtr, opcode); } else if (this.predictedUpOpcodeSet && !this.predictedDownOpcodeSet && direction == NetworkMessageDirection.ZoneDown) { // Server send, executes last CheckPredictedPingDown(dataPtr, opcode); } // Calculate ping if (this.predictedDownOpcodeSet && this.predictedUpOpcodeSet) { CalculatePing(dataPtr, opcode, direction); } }
public void OnNetwork(IntPtr dataPtr, ushort opCode, uint sourceActorId, uint targetActorId, NetworkMessageDirection direction) { var OpcodeLoadHousing = Int32.Parse(Offset.LoadHousing, NumberStyles.HexNumber); var OpcodeMoveItem = Int32.Parse(Offset.MoveItem, NumberStyles.HexNumber); if (direction == NetworkMessageDirection.ZoneDown) { if (opCode != OpcodeLoadHousing || !Config.Recording) { return; } byte[] posArr = new byte[2416]; Marshal.Copy(dataPtr, posArr, 0, 2416); if (BitConverter.ToString(posArr).Replace("-", " ").StartsWith("FF FF FF FF FF FF FF FF")) { Config.SelectedItemIndex = -1; Config.HousingItemList.Clear(); Config.Save(); return; } if (DateTime.Now > Config.lastPosPackageTime.AddSeconds(5)) { Config.HousingItemList.Clear(); Config.lastPosPackageTime = DateTime.Now; Config.Save(); } for (int i = 12; i < posArr.Length && i + 24 < posArr.Length; i += 24) { var modelKey = BitConverter.ToUInt16(posArr, i); var item = Interface.Data.GetExcelSheet <HousingFurniture>().GetRow((uint)(modelKey + 196608)).Item.Value; if (item.RowId == 0) { continue; } var rotate = BitConverter.ToSingle(posArr, i + 8); var x = BitConverter.ToSingle(posArr, i + 12); var y = BitConverter.ToSingle(posArr, i + 16); var z = BitConverter.ToSingle(posArr, i + 20); Config.HousingItemList.Add(new HousingItem( modelKey, item.RowId, x, y, z, rotate, item.Name )); } Log($"Load {Config.HousingItemList.Count} items."); Config.Save(); } else { if (opCode != OpcodeMoveItem || !Config.ForceMove) { return; } byte[] posArr = new byte[28]; Marshal.Copy(dataPtr, posArr, 0, 28); //Log(BitConverter.ToString(posArr).Replace("-", " ")); float x = BitConverter.ToSingle(posArr, 12); float y = BitConverter.ToSingle(posArr, 16); float z = BitConverter.ToSingle(posArr, 20); float rotate = BitConverter.ToSingle(posArr, 24); Log($"Moving to ({x:N3}, {y:N3}, {z:N3}, {rotate:N3})"); x = Config.PlaceX; y = Config.PlaceY; z = Config.PlaceZ; rotate = Config.PlaceRotate; Log($"Forced to ({x:N3}, {y:N3}, {z:N3}, {rotate:N3})"); byte[] bx = BitConverter.GetBytes(x); bx.CopyTo(posArr, 12); byte[] by = BitConverter.GetBytes(y); by.CopyTo(posArr, 16); byte[] bz = BitConverter.GetBytes(z); bz.CopyTo(posArr, 20); byte[] br = BitConverter.GetBytes(rotate); br.CopyTo(posArr, 24); Marshal.Copy(posArr, 0, dataPtr, 28); Config.ForceMove = false; Config.Save(); WritePrePosition(); } }
private void Chat_OnNetworkMessage(IntPtr dataPtr, ushort opCode, uint sourceActorId, uint targetActorId, NetworkMessageDirection direction) { return; /* * if (!Config.Enable || !Config.Eureka) return; * if (direction != NetworkMessageDirection.ZoneDown) * return; * var client = ClientState.ClientLanguage == ClientLanguage.ChineseSimplified ? "cn" : "intl"; * // not used after hooking the function * // https://github.com/karashiiro/MachinaWrapperJSON/blob/master/MachinaWrapper/Models/Sapphire/Ipcs.cs * // https://github.com/karashiiro/MachinaWrapperJSON/blob/master/MachinaWrapper/Models/Sapphire/Ipcs_cn.cs * // if not found, it'll be triggered when chatting and the length should be 1104. * ushort chat_opcode = (ushort)(client == "cn" ? 0x021e : 0x02c2); * if (opCode != chat_opcode) * return; * byte[] managedArray = new byte[32]; * Marshal.Copy(dataPtr, managedArray, 0, 32); * Log("Network dataPtr"); * Log(BitConverter.ToString(managedArray).Replace("-", " ")); * return; * Int64 CID = Marshal.ReadInt64(dataPtr); * short world_id = Marshal.ReadInt16(dataPtr, 12); * string name = StringFromNativeUtf8(dataPtr + 16); * Log($"{name}@{world_id}:{CID}"); * string playerNameKey = $"{name}@{world_id}"; * if (!name2CID.ContainsKey(playerNameKey)) * { * name2CID.Add(playerNameKey, CID); * } */ }
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."); } } } }
public NetworkMessageEvent(object trigger, string displayName, string messageId, ActivityEventType type, NetworkMessageDirection direction, int templateId = 0) : base(trigger, displayName, messageId, type, templateId) { Direction = direction; }
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; } if (string.IsNullOrEmpty(contentFinderCondition.Name)) { contentFinderCondition.Name = "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(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[rouletteIndex]; var prevRoleKey = this.lastPreferredRole[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); 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 (opCode == this.dalamud.Data.ServerOpCodes["MarketTaxRates"]) { 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."); } } } }
private void OnNetworkEvent(IntPtr dataPtr, ushort opCode, uint sourceActorId, uint targetActorId, NetworkMessageDirection direction) { if (direction != NetworkMessageDirection.ZoneDown) { return; } if (!this.pi.Data.IsDataReady) { return; } if (opCode == this.pi.Data.ServerOpCodes["MarketBoardItemRequestStart"]) { this.newRequest = true; } if (opCode != this.pi.Data.ServerOpCodes["MarketBoardOfferings"] || !this.newRequest) { return; } if (!this.configuration.alwaysOn && (!this.configuration.smart || !Retainer())) { return; } var listing = MarketBoardCurrentOfferings.Read(dataPtr); var i = 0; if (this.configuration.hq && this.items.Single(j => j.RowId == listing.ItemListings[0].CatalogId).CanBeHq) { while (i < listing.ItemListings.Count && !listing.ItemListings[i].IsHq) { i++; } if (i == listing.ItemListings.Count) { return; } } while (i != listing.ItemListings.Count && this.configuration.whitelist.Contains(listing.ItemListings[i].RetainerName)) { i++; } var price = listing.ItemListings[i].PricePerUnit - this.configuration.delta; Clipboard.SetText(price.ToString()); if (this.configuration.verbose) { this.pi.Framework.Gui.Chat.Print($"{price} copied to clipboard."); } this.newRequest = false; }
private void OnNetworkEvent(IntPtr dataPtr, ushort opCode, uint sourceActorId, uint targetActorId, NetworkMessageDirection direction) { if (direction != NetworkMessageDirection.ZoneDown) { return; } if (!Data.IsDataReady) { return; } if (opCode == Data.ServerOpCodes["MarketBoardItemRequestStart"]) { newRequest = true; } if (opCode != Data.ServerOpCodes["MarketBoardOfferings"] || !newRequest) { return; } if (!configuration.alwaysOn && (!configuration.smart || !Retainer())) { return; } var listing = MarketBoardCurrentOfferings.Read(dataPtr); var i = 0; if (configuration.hq && items.Single(j => j.RowId == listing.ItemListings[0].CatalogId).CanBeHq) { while (i < listing.ItemListings.Count && !listing.ItemListings[i].IsHq) { i++; } if (i == listing.ItemListings.Count) { return; } } var price = listing.ItemListings[i].PricePerUnit - (listing.ItemListings[i].PricePerUnit % configuration.mod) - configuration.delta; price = Math.Max(price, configuration.min); ImGui.SetClipboardText(price.ToString()); if (configuration.verbose) { Chat.Print((configuration.hq ? "[HQ] " : string.Empty) + $"{price:n0} copied to clipboard."); } newRequest = false; }
public void OnNetwork(IntPtr dataPtr, ushort opCode, uint sourceActorId, uint targetActorId, NetworkMessageDirection direction) { return; if (direction == NetworkMessageDirection.ZoneDown) { ushort[] filteredOpcodes = new ushort[] { 439, 0x1CB, 0xA1, 0x269, 0x30C, 0x103, 0x263 }; if (filteredOpcodes.ToList().IndexOf(opCode) == -1) { Log($"Receive opcode:0x{opCode:X}"); } } }