Example #1
0
        public async Task ProcessRetainerSale(uint itemId, int amount, bool isHq)
        {
            if (this.config.RetainerNotificationChannel == null)
            {
                return;
            }

            var channel = await GetChannel(this.config.RetainerNotificationChannel);

            dynamic item = XivApi.GetItem(itemId).GetAwaiter().GetResult();

            var character     = this.dalamud.ClientState.LocalPlayer;
            var characterInfo = await GetCharacterInfo(character.Name, character.HomeWorld.GameData.Name);

            var embedBuilder = new EmbedBuilder {
                Title        = (isHq ? "<:hq:593406013651156994> " : "") + item.Name,
                Url          = "https://www.garlandtools.org/db/#item/" + itemId,
                Description  = "Sold " + amount,
                Timestamp    = DateTimeOffset.Now,
                Color        = new Color(0xd89b0d),
                ThumbnailUrl = "https://xivapi.com" + item.Icon,
                Footer       = new EmbedFooterBuilder {
                    Text    = $"XIVLauncher | {character.Name}",
                    IconUrl = characterInfo.AvatarUrl
                }
            };

            await channel.SendMessageAsync(embed : embedBuilder.Build());
        }
Example #2
0
 public override void Resolve()
 {
     if (string.IsNullOrEmpty(ServerName))
     {
         dynamic server = XivApi.Get($"World/{ServerId}").GetAwaiter().GetResult();
         ServerName = server.Name;
     }
 }
Example #3
0
 public override void Resolve()
 {
     if (string.IsNullOrEmpty(ItemName))
     {
         dynamic item = XivApi.GetItem((int)ItemId).GetAwaiter().GetResult();
         ItemName = item.Name;
     }
 }
Example #4
0
 public override void Resolve()
 {
     if (string.IsNullOrEmpty(StatusName))
     {
         dynamic status = XivApi.Get($"Status/{StatusId}").GetAwaiter().GetResult();
         //Console.WriteLine($"Resolved status {StatusId} to {status.Name}");
         StatusName = status.Name;
     }
 }
Example #5
0
        private async Task <(string LodestoneId, string AvatarUrl)> GetCharacterInfo(string name, string worldName)
        {
            try
            {
                dynamic charCandidates = await XivApi.GetCharacterSearch(name, worldName);

                if (charCandidates.Results.Count > 0)
                {
                    var avatarUrl   = charCandidates.Results[0].Avatar;
                    var lodestoneId = charCandidates.Results[0].ID;

                    return(lodestoneId, avatarUrl);
                }
            }
            catch (Exception ex)
            {
                Log.Error(ex, "Could not get XIVAPI character search result.");
            }

            return(null, null);
        }
Example #6
0
        public async Task ProcessFate(int id)
        {
            if (this.config.FateNotificationChannel == null)
            {
                return;
            }

            var channel = await GetChannel(this.config.FateNotificationChannel);

            dynamic fateInfo = XivApi.GetFate(id).GetAwaiter().GetResult();

            this.dalamud.Framework.Gui.Chat.Print("Watched Fate spawned: " + (string)fateInfo.Name);

            var embedBuilder = new EmbedBuilder {
                Author = new EmbedAuthorBuilder {
                    IconUrl = "https://xivapi.com" + (string)fateInfo.Icon,
                    Name    = "Fate spawned: " + (string)fateInfo.Name
                },
                Color     = new Color(0xa73ed1),
                Timestamp = DateTimeOffset.Now
            };

            await channel.SendMessageAsync(embed : embedBuilder.Build());
        }
Example #7
0
        private void OnZonePacket(IntPtr dataPtr)
        {
            var opCode = (ZoneOpCode)Marshal.ReadInt16(dataPtr, 2);

            if (opCode == ZoneOpCode.CfNotifyPop)
            {
                var data = new byte[64];
                Marshal.Copy(dataPtr, data, 0, 64);

                var notifyType = data[16];
                var contentFinderConditionId = BitConverter.ToInt16(data, 36);


                Task.Run(async() => {
                    if (notifyType != 3 || contentFinderConditionId == 0)
                    {
                        return;
                    }

                    var contentFinderCondition =
                        await XivApi.GetContentFinderCondition(contentFinderConditionId);

                    this.dalamud.Framework.Gui.Chat.Print($"Duty pop: " + contentFinderCondition["Name"]);

                    if (this.dalamud.BotManager.IsConnected)
                    {
                        await this.dalamud.BotManager.ProcessCfPop(contentFinderCondition);
                    }
                });

                return;
            }

            if (opCode == ZoneOpCode.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 == ZoneOpCode.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 == ZoneOpCode.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 == ZoneOpCode.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 == ZoneOpCode.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.");
                    }
                }
            }
        }
        public async void DoWork(object state)
        {
            var cancellationToken = (CancellationToken)state;

            if (!Settings.IsDX11())
            {
                return;
            }

            CheckManualInstall();

            var discordManager = new DiscordPresenceManager(DefaultPresence, ClientID);

            try
            {
                var game = new Nhaama.FFXIV.Game(_gameProcess);

                discordManager.SetPresence(DefaultPresence);

                Log.Information("RichPresence DoWork started.");

                while (!cancellationToken.IsCancellationRequested)
                {
                    try
                    {
                        game.Update();
                    }
                    catch (Exception ex)
                    {
                        Log.Information(ex, "Nhaama game data update failed.");
                        Thread.Sleep(2000);
                        continue;
                    }

                    if (game.ActorTable == null)
                    {
                        discordManager.SetPresence(DefaultPresence);
                        continue;
                    }

                    if (game.ActorTable.Length > 0)
                    {
                        var player = game.ActorTable[0];

                        if (player.ActorID == 0)
                        {
                            discordManager.SetPresence(DefaultPresence);
                            continue;
                        }

                        var territoryType = game.TerritoryType;

                        var placeName       = "Hydaelyn";
                        var loadingImageKey = 1;
                        if (territoryType != 0)
                        {
                            placeName = await XivApi.GetPlaceNameForTerritoryType(territoryType);

                            loadingImageKey = await XivApi.GetLoadingImageKeyForTerritoryType(territoryType);
                        }


                        var largeImageKey = $"li_{loadingImageKey}";

                        var fcName = player.CompanyTag;

                        if (fcName != string.Empty)
                        {
                            _lastFc = fcName;
                            fcName  = $" <{fcName}>";
                        }
                        else if (_lastFc != string.Empty)
                        {
                            fcName = $" <{_lastFc}>";
                        }

                        var worldName = await XivApi.GetNameForWorld(player.World);

                        if (player.World != player.HomeWorld)
                        {
                            worldName = $"{worldName} (🏠{await XivApi.GetNameForWorld(player.HomeWorld)})";
                        }

                        discordManager.SetPresence(new RichPresence
                        {
                            Details = $"{player.Name}{fcName}",
                            State   = worldName,
                            Assets  = new Assets
                            {
                                LargeImageKey  = largeImageKey,
                                LargeImageText = placeName,
                                SmallImageKey  = $"class_{player.Job}",
                                SmallImageText = await XivApi.GetJobName(player.Job) + " Lv." + player.Level
                            }
                        });
                    }

                    Thread.Sleep(1000);
                }
            }
            catch (Exception ex)
            {
                Log.Error(ex, "Critical error in RichPresence.");
            }
            finally
            {
                discordManager.Deinitialize();
            }

            Log.Information("RichPresence exited!");
        }