Exemple #1
0
        private void CycleCold()
        {
            if (this.coldCount > this.coldCapacity)
            {
                Interlocked.Decrement(ref this.coldCount);

                if (this.coldQueue.TryDequeue(out LongTickCountLruItem <TKey, TValue> item))
                {
                    ItemDestination where = this.policy.RouteCold(item);

                    if (where == ItemDestination.Warm && this.warmCount <= this.warmCapacity)
                    {
                        this.Move(item, where);
                    }
                    else
                    {
                        this.Move(item, ItemDestination.Remove);
                    }
                }
                else
                {
                    Interlocked.Increment(ref this.coldCount);
                }
            }
        }
Exemple #2
0
        private void CycleWarm()
        {
            if (this.warmCount > this.warmCapacity)
            {
                Interlocked.Decrement(ref this.warmCount);

                if (this.warmQueue.TryDequeue(out LongTickCountLruItem <TKey, TValue> item))
                {
                    ItemDestination where = this.policy.RouteWarm(item);

                    // When the warm queue is full, we allow an overflow of 1 item before redirecting warm items to cold.
                    // This only happens when hit rate is high, in which case we can consider all items relatively equal in
                    // terms of which was least recently used.
                    if (where == ItemDestination.Warm && this.warmCount <= this.warmCapacity)
                    {
                        this.Move(item, where);
                    }
                    else
                    {
                        this.Move(item, ItemDestination.Cold);
                    }
                }
                else
                {
                    Interlocked.Increment(ref this.warmCount);
                }
            }
        }
Exemple #3
0
        private void CycleHot()
        {
            if (this.hotCount > this.hotCapacity)
            {
                Interlocked.Decrement(ref this.hotCount);

                if (this.hotQueue.TryDequeue(out LongTickCountLruItem <TKey, TValue> item))
                {
                    ItemDestination where = this.policy.RouteHot(item);
                    this.Move(item, where);
                }
                else
                {
                    Interlocked.Increment(ref this.hotCount);
                }
            }
        }
Exemple #4
0
        private static Item FinalizeItem(int requestIndex, IConfigItem config, ItemDestination type, Item item)
        {
            if (type == ItemDestination.PlayerDropped)
            {
                if (!ItemInfo.IsSaneItemForDrop(item))
                {
                    throw new Exception($"Unsupported item: (index {requestIndex}).");
                }
                if (config.WrapAllItems && item.ShouldWrapItem())
                {
                    item.SetWrapping(ItemWrapping.WrappingPaper, config.WrappingPaper, true);
                }
            }

            item.IsDropped = type == ItemDestination.FieldItemDropped;

            return(item);
        }
Exemple #5
0
        private void Move(LongTickCountLruItem <TKey, TValue> item, ItemDestination where)
        {
            item.WasAccessed = false;

            switch (where)
            {
            case ItemDestination.Warm:
                this.warmQueue.Enqueue(item);
                Interlocked.Increment(ref this.warmCount);
                break;

            case ItemDestination.Cold:
                this.coldQueue.Enqueue(item);
                Interlocked.Increment(ref this.coldCount);
                break;

            case ItemDestination.Remove:
                if (!item.WasRemoved)
                {
                    // Avoid race where 2 threads could remove the same key - see TryRemove for details.
                    lock (item)
                    {
                        if (item.WasRemoved)
                        {
                            break;
                        }

                        if (this.dictionary.TryRemove(item.Key, out LongTickCountLruItem <TKey, TValue> removedItem))
                        {
                            item.WasRemoved = true;
                            if (removedItem.Value is IDisposable d)
                            {
                                d.Dispose();
                            }
                        }
                    }
                }

                break;
            }
        }
        public void RouteCold(bool wasAccessed, ItemDestination expectedDestination)
        {
            var item = CreateItem(wasAccessed);

            this.policy.RouteCold(item).Should().Be(expectedDestination);
        }
Exemple #7
0
        /// <summary>
        /// Gets a list of items from the requested hex string(s).
        /// </summary>
        /// <remarks>
        /// If the first input is a language code (2 characters), the logic will try to parse item names for that language instead of item IDs.
        /// </remarks>
        /// <param name="requestHex">8 byte hex item values (u64 format)</param>
        /// <param name="cfg">Options for packaging items</param>
        /// <param name="type">End destination of the item</param>
        public static IReadOnlyCollection <Item> GetItemsFromUserInput(string requestHex, IConfigItem cfg, ItemDestination type = ItemDestination.PlayerDropped)
        {
            try
            {
                // having a language 2char code will cause an exception in parsing; this is fine and is handled by our catch statement.
                var split = requestHex.Split(SplittersHex, StringSplitOptions.RemoveEmptyEntries);
                return(GetItemsHexCode(split, cfg, type));
            }
#pragma warning disable CA1031 // Do not catch general exception types
            catch
#pragma warning restore CA1031 // Do not catch general exception types
            {
                var split = requestHex.Split(SplittersName, StringSplitOptions.RemoveEmptyEntries);
                return(GetItemsLanguage(split, cfg, type, GameLanguage.DefaultLanguage));
            }
        }
Exemple #8
0
        private static Item CreateItem(byte[] convert, int requestIndex, IConfigItem config, ItemDestination type)
        {
            Item item;

            try
            {
                if (convert.Length != Item.SIZE)
                {
                    throw new Exception();
                }
                item = convert.ToClass <Item>();
            }
            catch (Exception ex)
            {
                throw new Exception($"Failed to convert item (index {requestIndex}: {ex.Message}).");
            }

            return(FinalizeItem(requestIndex, config, type, item));
        }
Exemple #9
0
        private static Item CreateItem(string name, int requestIndex, IConfigItem config, ItemDestination type, string lang = "en")
        {
            var item = GetItem(name, lang);

            if (item.IsNone)
            {
                throw new Exception($"Failed to convert item (index {requestIndex}: {name}) for Language {lang}.");
            }

            return(FinalizeItem(requestIndex, config, type, item));
        }
Exemple #10
0
        /// <summary>
        /// Gets a list of items from the requested list of item hex code strings.
        /// </summary>
        /// <remarks>
        /// If a hex code parse fails or a recipe ID does not exist, exceptions will be thrown.
        /// </remarks>
        /// <param name="split">List of recipe IDs as u16 hex</param>
        /// <param name="config">Item packaging options</param>
        /// <param name="type">Destination where the item will end up at</param>
        public static IReadOnlyCollection <Item> GetItemsHexCode(IReadOnlyList <string> split, IConfigItem config, ItemDestination type = ItemDestination.PlayerDropped)
        {
            var strings = GameInfo.Strings.itemlistdisplay;
            var result  = new Item[split.Count];

            for (int i = 0; i < result.Length; i++)
            {
                var text    = split[i].Trim();
                var convert = GetBytesFromString(text);
                var item    = CreateItem(convert, i, config, type);

                if (item.ItemId >= strings.Length)
                {
                    throw new Exception($"Item requested is out of expected range ({item.ItemId:X4} > {strings.Length:X4}).");
                }
                if (string.IsNullOrWhiteSpace(strings[item.ItemId]))
                {
                    throw new Exception($"Item requested does not have a valid name ({item.ItemId:X4}).");
                }

                result[i] = item;
            }
            return(result);
        }
Exemple #11
0
        /// <summary>
        /// Gets a list of items from the requested list of item name strings.
        /// </summary>
        /// <remarks>
        /// If a item name parse fails or the item ID does not exist as a known item, exceptions will be thrown.
        /// </remarks>
        /// <param name="split">List of item names</param>
        /// <param name="config">Item packaging options</param>
        /// <param name="type">Destination where the item will end up at</param>
        /// <param name="lang">Language code to parse with. If the first entry in <see cref="split"/> is a language code, it will be used instead of <see cref="lang"/>.</param>
        public static IReadOnlyCollection <Item> GetItemsLanguage(IReadOnlyList <string> split, IConfigItem config, ItemDestination type = ItemDestination.PlayerDropped, string lang = GameLanguage.DefaultLanguage)
        {
            if (split.Count > 1 && split[0].Length < 3)
            {
                var langIndex = GameLanguage.GetLanguageIndex(split[0]);
                lang  = GameLanguage.Language2Char(langIndex);
                split = split.Skip(1).ToArray();
            }

            var strings = GameInfo.Strings.itemlistdisplay;
            var result  = new Item[split.Count];

            for (int i = 0; i < result.Length; i++)
            {
                var text = split[i].Trim();
                var item = CreateItem(text, i, config, type, lang);

                if (item.ItemId >= strings.Length)
                {
                    throw new Exception($"Item requested is out of expected range ({item.ItemId:X4} > {strings.Length:X4}).");
                }
                if (string.IsNullOrWhiteSpace(strings[item.ItemId]))
                {
                    throw new Exception($"Item requested does not have a valid name ({item.ItemId:X4}).");
                }

                result[i] = item;
            }
            return(result);
        }
        // Methods
        public ItemAction(byte[] data)
            : base(data)
        {
            this.superiorType = SuperiorItemType.NotApplicable;
            this.charClass = CharacterClass.NotApplicable;
            this.level = -1;
            this.usedSockets = -1;
            this.use = -1;
            this.graphic = -1;
            this.color = -1;
            this.stats = new List<StatBase>();
            this.unknown1 = -1;
            this.runewordID = -1;
            this.runewordParam = -1;
            BitReader br = new BitReader(data, 1);
            this.action = (ItemActionType) br.ReadByte();
            br.SkipBytes(1);
            this.category = (ItemCategory) br.ReadByte();
            this.uid = br.ReadUInt32();
            if (data[0] == 0x9d)
            {
                br.SkipBytes(5);
            }
            this.flags = (ItemFlags) br.ReadUInt32();
            this.version = (ItemVersion) br.ReadByte();
            this.unknown1 = br.ReadByte(2);
            this.destination = (ItemDestination) br.ReadByte(3);
            if (this.destination == ItemDestination.Ground)
            {
                this.x = br.ReadUInt16();
                this.y = br.ReadUInt16();
            }
            else
            {
                this.location = (EquipmentLocation) br.ReadByte(4);
                this.x = br.ReadByte(4);
                this.y = br.ReadByte(3);
                this.container = (ItemContainer) br.ReadByte(4);
            }
            if ((this.action == ItemActionType.AddToShop) || (this.action == ItemActionType.RemoveFromShop))
            {
                int num = ((int) this.container) | 0x80;
                if ((num & 1) == 1)
                {
                    num--;
                    this.y += 8;
                }
                this.container = (ItemContainer) num;
            }
            else if (this.container == ItemContainer.Unspecified)
            {
                if (this.location == EquipmentLocation.NotApplicable)
                {
                    if ((this.Flags & ItemFlags.InSocket) == ItemFlags.InSocket)
                    {
                        this.container = ItemContainer.Item;
                        this.y = -1;
                    }
                    else if ((this.action == ItemActionType.PutInBelt) || (this.action == ItemActionType.RemoveFromBelt))
                    {
                        this.container = ItemContainer.Belt;
                        this.y = this.x / 4;
                        this.x = this.x % 4;
                    }
                }
                else
                {
                    this.x = -1;
                    this.y = -1;
                }
            }
            if ((this.flags & ItemFlags.Ear) == ItemFlags.Ear)
            {
                this.charClass = (CharacterClass) br.ReadByte(3);
                this.level = br.ReadByte(7);
                this.name = br.ReadString(7, '\0', 0x10);
                this.baseItem = BaseItem.Get(ItemType.Ear);
            }
            else
            {
                this.baseItem = BaseItem.GetByID(this.category, br.ReadUInt32());
                if (this.baseItem.Type == ItemType.Gold)
                {
                    this.stats.Add(new SignedStat(BaseStat.Get(StatType.Quantity), br.ReadInt32(br.ReadBoolean(1) ? 0x20 : 12)));
                }
                else
                {
                    this.usedSockets = br.ReadByte(3);
                    if ((this.flags & (ItemFlags.Compact | ItemFlags.Gamble)) == ItemFlags.None)
                    {
                        BaseStat stat;
                        int num2;
                        this.level = br.ReadByte(7);
                        this.quality = (ItemQuality) br.ReadByte(4);
                        if (br.ReadBoolean(1))
                        {
                            this.graphic = br.ReadByte(3);
                        }
                        if (br.ReadBoolean(1))
                        {
                            this.color = br.ReadInt32(11);
                        }
                        if ((this.flags & ItemFlags.Identified) == ItemFlags.Identified)
                        {
                            switch (this.quality)
                            {
                                case ItemQuality.Inferior:
                                    this.prefix = new ItemAffix(ItemAffixType.InferiorPrefix, br.ReadByte(3));
                                    break;

                                case ItemQuality.Superior:
                                    this.prefix = new ItemAffix(ItemAffixType.SuperiorPrefix, 0);
                                    this.superiorType = (SuperiorItemType) br.ReadByte(3);
                                    break;

                                case ItemQuality.Magic:
                                    this.prefix = new ItemAffix(ItemAffixType.MagicPrefix, br.ReadUInt16(11));
                                    this.suffix = new ItemAffix(ItemAffixType.MagicSuffix, br.ReadUInt16(11));
                                    break;

                                case ItemQuality.Set:
                                    this.setItem = BaseSetItem.Get(br.ReadUInt16(12));
                                    break;

                                case ItemQuality.Rare:
                                case ItemQuality.Crafted:
                                    this.prefix = new ItemAffix(ItemAffixType.RarePrefix, br.ReadByte(8));
                                    this.suffix = new ItemAffix(ItemAffixType.RareSuffix, br.ReadByte(8));
                                    break;

                                case ItemQuality.Unique:
                                    if (this.baseItem.Code != "std")
                                    {
                                        try
                                        {
                                            this.uniqueItem = BaseUniqueItem.Get(br.ReadUInt16(12));
                                        }
                                        catch{}
                                    }
                                    break;
                            }
                        }
                        if ((this.quality == ItemQuality.Rare) || (this.quality == ItemQuality.Crafted))
                        {
                            this.magicPrefixes = new List<MagicPrefixType>();
                            this.magicSuffixes = new List<MagicSuffixType>();
                            for (int i = 0; i < 3; i++)
                            {
                                if (br.ReadBoolean(1))
                                {
                                    this.magicPrefixes.Add((MagicPrefixType) br.ReadUInt16(11));
                                }
                                if (br.ReadBoolean(1))
                                {
                                    this.magicSuffixes.Add((MagicSuffixType) br.ReadUInt16(11));
                                }
                            }
                        }
                        if ((this.Flags & ItemFlags.Runeword) == ItemFlags.Runeword)
                        {
                            this.runewordID = br.ReadUInt16(12);
                            this.runewordParam = br.ReadUInt16(4);
                            num2 = -1;
                            if (this.runewordParam == 5)
                            {
                                num2 = this.runewordID - (this.runewordParam * 5);
                                if (num2 < 100)
                                {
                                    num2--;
                                }
                            }
                            else if (this.runewordParam == 2)
                            {
                                num2 = ((this.runewordID & 0x3ff) >> 5) + 2;
                            }
                            br.ByteOffset -= 2;
                            this.runewordParam = br.ReadUInt16();
                            this.runewordID = num2;
                            if (num2 == -1)
                            {
                                throw new Exception("Unknown Runeword: " + this.runewordParam);
                            }
                            this.runeword = BaseRuneword.Get(num2);
                        }
                        if ((this.Flags & ItemFlags.Personalized) == ItemFlags.Personalized)
                        {
                            this.name = br.ReadString(7, '\0', 0x10);
                        }
                        if (this.baseItem is BaseArmor)
                        {
                            stat = BaseStat.Get(StatType.ArmorClass);
                            this.stats.Add(new SignedStat(stat, br.ReadInt32(stat.SaveBits) - stat.SaveAdd));
                        }
                        if ((this.baseItem is BaseArmor) || (this.baseItem is BaseWeapon))
                        {
                            stat = BaseStat.Get(StatType.MaxDurability);
                            num2 = br.ReadInt32(stat.SaveBits);
                            this.stats.Add(new SignedStat(stat, num2));
                            if (num2 > 0)
                            {
                                stat = BaseStat.Get(StatType.Durability);
                                this.stats.Add(new SignedStat(stat, br.ReadInt32(stat.SaveBits)));
                            }
                        }
                        if ((this.Flags & (ItemFlags.None | ItemFlags.Socketed)) == (ItemFlags.None | ItemFlags.Socketed))
                        {
                            stat = BaseStat.Get(StatType.Sockets);
                            this.stats.Add(new SignedStat(stat, br.ReadInt32(stat.SaveBits)));
                        }
                        if (this.baseItem.Stackable)
                        {
                            if (this.baseItem.Useable)
                            {
                                this.use = br.ReadByte(5);
                            }
                            this.stats.Add(new SignedStat(BaseStat.Get(StatType.Quantity), br.ReadInt32(9)));
                        }
                        if ((this.Flags & ItemFlags.Identified) == ItemFlags.Identified)
                        {
                            StatBase base2;
                            int num4 = (this.Quality == ItemQuality.Set) ? br.ReadByte(5) : -1;
                            this.mods = new List<StatBase>();
                            while ((base2 = ReadStat(br)) != null)
                            {
                                this.mods.Add(base2);
                            }
                            if ((this.flags & ItemFlags.Runeword) == ItemFlags.Runeword)
                            {
                                while ((base2 = ReadStat(br)) != null)
                                {
                                    this.mods.Add(base2);
                                }
                            }
                            if (num4 > 0)
                            {
                                this.setBonuses = new List<StatBase>[5];
                                for (int j = 0; j < 5; j++)
                                {
                                    if ((num4 & (((int) 1) << j)) != 0)
                                    {
                                        this.setBonuses[j] = new List<StatBase>();
                                        while ((base2 = ReadStat(br)) != null)
                                        {
                                            this.setBonuses[j].Add(base2);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }