Exemple #1
0
        public async Task EditEntryReextractTest(string filename, string entryFilepath, string replacementFile, string expectedDir)
        {
            using (ArcFile arcFile = new ArcFile(filename))
            {
                ContainerEntry arcEntry = arcFile.GetEntry(entryFilepath);
                if (arcEntry == null)
                {
                    Assert.Fail("Entry not found.");
                }
                using (FileStream fileStream = new FileStream(replacementFile, FileMode.Open, FileAccess.Read))
                {
                    await arcEntry.SetData(fileStream);
                }
                await arcFile.SaveAs("temp.arc", progress);
            }
            using (ArcFile arcFile = new ArcFile("temp.arc"))
            {
                await arcFile.ExtractAllAsync("tempdir", false, progress);
            }
            File.Move(expectedDir + "/" + entryFilepath, "backup");
            File.Copy(replacementFile, expectedDir + "/" + entryFilepath);
            bool eq = Compare.CompareDirectories(expectedDir, "tempdir");

            File.Delete(expectedDir + "/" + entryFilepath);
            File.Move("backup", expectedDir + "/" + entryFilepath);

            DirectoryInfo directoryInfo = new DirectoryInfo("tempdir");

            directoryInfo.Delete(true);
            File.Delete("temp.arc");
            File.Delete("temp.bin");
            Assert.IsTrue(eq);
        }
        // Load All Container Arrays from  SQL
        void LoadFromSQL(string tablename)
        {
            // Empty the Array first
            for (int i = 0; i < Items.Length; i++)
            {
                Items[i] = null;
            }
            SqlWrapper sql = new SqlWrapper();
            DataTable  dt  = sql.ReadDatatable("SELECT * FROM " + tablename + " WHERE container=" + Type + " AND ID=" + Instance);

            foreach (DataRow row in dt.Rows)
            {
                int place = (Int32)row["placement"];
                if (place < NumberOfSlots)
                {
                    if (((Int32)row["type"] != 0) && ((Int32)row["instance"] != 0))
                    {
                        // Do stuff with instanced items
                        // Create item from lowid/highid interpolated by QL and read stats from sql
                    }
                    else
                    {
                        ContainerEntry ce = new ContainerEntry();
                        ce.LowID      = (Int32)row["lowid"];
                        ce.HighID     = (Int32)row["highid"];
                        ce.QL         = (Int32)row["quality"];
                        ce.Amount     = (Int32)row["multiplecount"];
                        ce.Flags      = (uint)row["flags"];
                        ce.InstanceID = 0;
                        ce.Type       = 0;
                        Items[place]  = ce;
                    }
                }
            }
        }
Exemple #3
0
        public void ContainerIndex_Basics()
        {
            int threshold = 20000;

            using (ContainerIndex index = ContainerIndex.OpenWrite("Sample.cdx"))
            {
                // Add three top level containers
                index.Start(threshold - 3);
                index.Start(threshold - 2);
                index.Start(threshold - 1);

                // Add 100 adjacent peers
                for (int i = 1; i <= 100; ++i)
                {
                    int start = i * threshold;
                    index.Start(start);
                    index.End(start + threshold - 1);
                }

                int end = (101 * threshold) - 1;

                // Close the top level parents
                index.End(end + 1);
                index.End(end + 2);
                index.End(end + 3);
            }

            using (ContainerIndex index = ContainerIndex.OpenRead("Sample.cdx"))
            {
                // Verify 103 entries read back
                Assert.AreEqual(103, index.Count);

                for (int i = 1; i < 100; ++i)
                {
                    int start = i * threshold;
                    int end   = start + threshold - 1;

                    // Verify positions inside each container return that container
                    Assert.AreEqual(start, index.NearestIndexedContainer(start).StartByteOffset);
                    Assert.AreEqual(start, index.NearestIndexedContainer(start + 1).StartByteOffset);
                    Assert.AreEqual(start, index.NearestIndexedContainer(end - 1).StartByteOffset);
                    Assert.AreEqual(start, index.NearestIndexedContainer(end).StartByteOffset);

                    // Verify the correct three parents are returned
                    ContainerEntry entry = index.NearestIndexedContainer(start);

                    entry = index.Parent(entry);
                    Assert.AreEqual(threshold - 1, entry.StartByteOffset);

                    entry = index.Parent(entry);
                    Assert.AreEqual(threshold - 2, entry.StartByteOffset);

                    entry = index.Parent(entry);
                    Assert.AreEqual(threshold - 3, entry.StartByteOffset);

                    entry = index.Parent(entry);
                    Assert.AreEqual(-1, entry.StartByteOffset);
                }
            }
        }
Exemple #4
0
        public async Task PatchFont()
        {
            try
            {
                ClearStatus();
                ContainerEntry fontEntry = ArcFile.GetEntry("im2nx_font.par");
                if (fontEntry == null)
                {
                    throw new FileNotFoundException("File im2nx_font.par not found. Make sure you are opening disc.arc");
                }
                using (Stream parStream = await fontEntry.GetData())
                {
                    ReportMessage("Reading im2nx_font.par...");
                    Font font = await Task.Run(() => Font.CreateFromPar(parStream));

                    ReportMessage("Patching font...");
                    await Task.Run(() => font.AddDigraphs());

                    ReportMessage("Writing font as par...");
                    using MemoryStream memStream = new MemoryStream();
                    await font.WriteFontPar(memStream, false);

                    memStream.Position = 0;
                    await fontEntry.SetData(memStream);
                }
                ReportMessage("Done.");
            }
            catch (Exception ex)
            {
                ReportException(ex);
            }
        }
Exemple #5
0
        public async Task EditThenSaveArcAsTwice(string filename, string entryPath, string replacementFile, string expectedFile)
        {
            using (ArcFile arcFile = new ArcFile(filename))
            {
                ContainerEntry arcEntry = arcFile.GetEntry(entryPath);
                if (arcEntry == null)
                {
                    Assert.Fail("Entry not found.");
                }
                using (FileStream fileStream = new FileStream(replacementFile, FileMode.Open, FileAccess.Read))
                {
                    await arcEntry.SetData(fileStream);
                }
                await arcFile.SaveAs("temp1.arc", progress);

                await arcFile.SaveAs("temp2.arc", progress);
            }
            bool eq1 = Compare.CompareFiles(expectedFile, "temp1.arc");
            bool eq2 = Compare.CompareFiles(ArcFile.GetBinName(expectedFile), "temp1.bin");
            bool eq3 = Compare.CompareFiles(expectedFile, "temp2.arc");
            bool eq4 = Compare.CompareFiles(ArcFile.GetBinName(expectedFile), "temp2.bin");

            File.Delete("temp1.arc");
            File.Delete("temp1.bin");
            File.Delete("temp2.arc");
            File.Delete("temp2.bin");
            Assert.IsTrue(eq1);
            Assert.IsTrue(eq2);
            Assert.IsTrue(eq3);
            Assert.IsTrue(eq4);
        }
Exemple #6
0
        /// <summary>
        /// Gets the instance.
        /// </summary>
        /// <param name="service">The service.</param>
        /// <param name="key">The key.</param>
        /// <returns></returns>
        public Object GetInstance(Type service, String key)
        {
            ContainerEntry entry = GetEntry(service, key);

            if (entry != null)
            {
                return(entry.Single()());
            }

            if (typeof(Delegate).IsAssignableFrom(service))
            {
                Type       typeToCreate         = service.GetGenericArguments()[0];
                Type       factoryFactoryType   = typeof(FactoryFactory <>).MakeGenericType(typeToCreate);
                Object     factoryFactoryHost   = Activator.CreateInstance(factoryFactoryType);
                MethodInfo factoryFactoryMethod = factoryFactoryType.GetMethod("Create");
                return(factoryFactoryMethod.Invoke(factoryFactoryHost, new Object[] { this }));
            }

            if (typeof(IEnumerable).IsAssignableFrom(service))
            {
                Type           listType  = service.GetGenericArguments()[0];
                IList <Object> instances = GetAllInstances(listType).ToList();
                Array          array     = Array.CreateInstance(listType, instances.Count);

                for (Int32 i = 0; i < array.Length; i++)
                {
                    array.SetValue(instances[i], i);
                }

                return(array);
            }

            return(null);
        }
Exemple #7
0
 private object GetInstance(ContainerEntry entry)
 {
     if (entry.Instance == null || entry.LifeCycle == LifeCycle.Transient)
     {
         var parameters = ResolveConstructorParameters(entry);
         entry.CreateInstance(parameters.ToArray());
     }
     return(entry.Instance);
 }
Exemple #8
0
            private IEnumerable <object> ResolveConstructorParameters(ContainerEntry entry)
            {
                var constructorInfo = entry.ConcreteType.GetTypeInfo().GetConstructors().First();

                foreach (var parameter in constructorInfo.GetParameters())
                {
                    yield return(ResolveObject(parameter.ParameterType));
                }
            }
Exemple #9
0
        private ContainerEntry GetOrCreateEntry(Type service, string key)
        {
            var entry = _entries.Find(x => x.Service == service && x.Key == key);

            if (entry is null)
            {
                entry = new ContainerEntry {
                    Service = service, Key = key
                };
                _entries.Add(entry);
            }

            return(entry);
        }
        /// <summary>
        /// The get or create entry.
        /// </summary>
        /// <param name="service">
        /// The service.
        /// </param>
        /// <param name="key">
        /// The key.
        /// </param>
        /// <returns>
        /// The <see cref="ContainerEntry"/>.
        /// </returns>
        private ContainerEntry GetOrCreateEntry(Type service, string key)
        {
            var entry = this.mEntries.FirstOrDefault(x => x.Service == service && x.Key == key);

            if (entry == null)
            {
                entry = new ContainerEntry {
                    Service = service, Key = key
                };
                this.mEntries.Add(entry);
            }

            return(entry);
        }
Exemple #11
0
    ContainerEntry GetOrCreateEntry(Type service, string key)
    {
        var entry = GetEntry(service, key);

        if (entry == null)
        {
            entry = new ContainerEntry {
                Service = service, Key = key
            };
            entries.Add(entry);
        }

        return(entry);
    }
Exemple #12
0
        void RemoveItem(int Place, int Amount)
        {
            ContainerEntry ce = (ContainerEntry)Items[Place];

            if (Items[Place] == null)
            {
                throw new NoNullAllowedException("Item at place " + Place + " of Container " + Type + ":" + Instance + " is NULL");
            }

            ce.Amount -= Amount;
            if (ce.Amount <= 0)
            {
                Items[Place] = null;
            }
        }
Exemple #13
0
        private ContainerEntry AncestorAtDepth(ContainerEntry entry, int entryDepth, int desiredDepth)
        {
            if (entryDepth < desiredDepth)
            {
                return(ContainerEntry.Empty);
            }

            while (entryDepth > desiredDepth)
            {
                entry = _containerIndex.Parent(entry);
                entryDepth--;
            }

            return(entry);
        }
Exemple #14
0
        public async Task WriteXlsxTest(string xlsxName, string arcName, string commuList)
        {
            using CommuToXlsx commu         = new CommuToXlsx(xlsxName, true);
            using StreamReader streamReader = new StreamReader(commuList);
            using ArcFile arcFile           = new ArcFile(arcName);
            while (!streamReader.EndOfStream)
            {
                string fileName = streamReader.ReadLine();
                using EntryStack entryStack = await arcFile.GetEntryRecursive(fileName);

                ContainerEntry entry = entryStack.Entry;
                using Stream memStream = await entry.GetData();

                commu.GetAndWriteCommu(memStream, fileName);
            }
        }
Exemple #15
0
        private async Task <EntryStack> GetEntryRecursive(string fileName, EntryStack stack)
        {
            int parIndex = fileName.IndexOf("_par/");
            int ptaIndex = fileName.IndexOf("_pta/");
            int index;

            if (parIndex == -1)
            {
                index = ptaIndex;
            }
            else if (ptaIndex == -1)
            {
                index = parIndex;
            }
            else
            {
                index = Math.Min(parIndex, ptaIndex);
            }

            if (index == -1)
            {
                ContainerEntry entry = GetEntry(fileName);
                if (entry == null)
                {
                    stack.Dispose();
                    return(null);
                }
                stack.Entry = entry;
                return(stack);
            }
            else
            {
                ContainerEntry entry = GetEntry(fileName.Substring(0, index) + '.' + fileName.Substring(index + 1, 3));
                if (entry == null)
                {
                    stack.Dispose();
                    return(null);
                }
                Stream stream = await entry.GetData();

                stack.Push(stream);
                ParFile parFile = new ParFile(stream);
                stack.Push(parFile);
                return(await parFile.GetEntryRecursive(fileName.Substring(index + 5)));
            }
        }
        /// <summary>
        /// The get on create or replace entry.
        /// </summary>
        /// <param name="service">
        /// The service.
        /// </param>
        /// <param name="key">
        /// The key.
        /// </param>
        /// <returns>
        /// The <see cref="ContainerEntry"/>.
        /// </returns>
        private ContainerEntry GetOnCreateOrReplaceEntry(Type service, string key)
        {
            lock (_entries)
            {
                var entry = _entries.FirstOrDefault(x => x.Service == service && x.Key == key);
                if (entry != null)
                {
                    _entries.Remove(entry);
                }

                entry = new ContainerEntry {
                    Service = service, Key = key
                };
                _entries.Add(entry);
                return(entry);
            }
        }
Exemple #17
0
        private ContainerEntry GetOrCreateEntry(Type service, string key)
        {
            if (service == null)
            {
                throw new ArgumentNullException(nameof(service));
            }

            var entry = _entries.FirstOrDefault(x => x.Service == service && x.Key == key);

            if (entry == null)
            {
                entry = new ContainerEntry {
                    Service = service, Key = key
                };
                _entries.Add(entry);
            }

            return(entry);
        }
Exemple #18
0
        public async Task GetEntryAndWriteToFile(string filename, string entryFilepath, string expectedFile)
        {
            using ArcFile arcFile = new ArcFile(filename);
            ContainerEntry arcEntry = arcFile.GetEntry(entryFilepath);

            if (arcEntry == null)
            {
                Assert.Fail("Entry not found.");
            }
            using (Stream stream = await arcEntry.GetData())
            {
                using FileStream fileStream = new FileStream("temp.dat", FileMode.Create, FileAccess.Write);
                stream.CopyTo(fileStream);
            }
            bool eq = Compare.CompareFiles(expectedFile, "temp.dat");

            File.Delete("temp.dat");
            Assert.IsTrue(eq);
        }
Exemple #19
0
        // Add Item To Container
        bool AddItem(int place, int lowID, int HighID, int Type, uint InstanceItemID, int Amount, int QL, uint Flags)
        {
            if (place == 0x6f)
            {
                // find next free
                int i = 0;
                while (i < NumberOfSlots)
                {
                    if (Items[i] == null)
                    {
                        break;
                    }
                    i++;
                }

                // No free slot found?
                if (i == NumberOfSlots)
                {
                    return(false);
                }

                place = i;
            }

            if ((Type == 0) && (InstanceItemID == 0))
            {
                ContainerEntry ce = new ContainerEntry();
                ce.Type       = 0;
                ce.InstanceID = 0;

                ce.LowID  = lowID;
                ce.HighID = HighID;
                ce.QL     = QL;
                ce.Flags  = Flags;

                Items[place] = ce;
            }
            else
            {
                //Instanced items stuff here
            }
            return(true);
        }
Exemple #20
0
        // Save All Container Arrays To SQL
        void SaveToSQL(string tablename)
        {
            SqlWrapper sql = new SqlWrapper();

            sql.SqlDelete("DELETE FROM " + tablename + " WHERE container=" + Type + " AND ID=" + Instance);

            for (int i = 0; i < Items.Length; i++)
            {
                if (Items[i] is ContainerEntry)
                {
                    // Not instanced items first
                    ContainerEntry ce = (ContainerEntry)Items[i];
                    sql.SqlInsert("INSERT INTO " + tablename + " (ID,Placement, flags, multiplecount, type,instance, lowid,highid, quality,nothing, container) VALUES (" + Instance + "," + i + "," + ce.Flags + "," + ce.Amount + ",0,0," + ce.LowID + "," + ce.HighID + "," + ce.QL + ",0," + Type + ")");
                }
                else
                {
                    // Do instanced items stuff here
                    // insert into inventory table AND store item's stats
                }
            }
        }
Exemple #21
0
        public void ContainerIndex_EndToEnd()
        {
            string jsonFilePath   = @"Content\Medium.json";
            string bionFilePath   = Path.ChangeExtension(jsonFilePath, ".bion");
            string dictionaryPath = Path.ChangeExtension(bionFilePath, "dict.bion");
            string comparePath    = Path.ChangeExtension(jsonFilePath, "compare.json");

            JsonBionConverter.JsonToBion(jsonFilePath, bionFilePath, dictionaryPath);

            using (WordCompressor compressor = WordCompressor.OpenRead(dictionaryPath))
                using (ContainerIndex cIndex = ContainerIndex.OpenRead(Path.ChangeExtension(bionFilePath, ".cdx")))
                    using (BionReader reader = new BionReader(File.OpenRead(bionFilePath), cIndex, compressor))
                    {
                        for (int i = 0; i < cIndex.Count; ++i)
                        {
                            ContainerEntry container = cIndex[i];

                            // Seek to container start
                            reader.Seek(container.StartByteOffset);

                            // Verify a container start is there
                            int depth = reader.Depth;
                            reader.Read();

                            bool isObject = (reader.TokenType == BionToken.StartObject);
                            Assert.AreEqual((isObject ? BionToken.StartObject : BionToken.StartArray), reader.TokenType);

                            // Read until the depth is back to the same value
                            while (reader.Depth != depth)
                            {
                                reader.Read();
                            }

                            // Verify this is the end container position
                            Assert.AreEqual((isObject ? BionToken.EndObject : BionToken.EndArray), reader.TokenType);
                            Assert.AreEqual(container.EndByteOffset, reader.BytesRead);
                        }
                    }
        }
        private static void RunPatch(IPatcherState <ISkyrimMod, ISkyrimModGetter> state)
        {
            // 0. Initialize method contextual variables and configurations.
            ILinkCache cache          = state.LinkCache;
            string     configFilePath = Path.Combine(state.ExtraSettingsDataPath, "currency-replacer-config.json");
            string     errorMessage   = "";

            if (!File.Exists(configFilePath))
            {
                errorMessage = "Cannot find currency-replacer-config.json for Currency Replacer Rules.";
                SynthesisLog(errorMessage);
                throw new FileNotFoundException(errorMessage, configFilePath);
            }

            SynthesisLog("**********************************", true);
            SynthesisLog("Currency Configuration File Used:");
            SynthesisLog(File.ReadAllText(configFilePath));
            SynthesisLog("**********************************");

            CurrencyConfig config;

            try
            {
                config = JsonConvert.DeserializeObject <CurrencyConfig>(File.ReadAllText(configFilePath));
            }
            catch (JsonSerializationException jsonException)
            {
                errorMessage = "Failed to parse currency-replacer-config.json, please review expected format.";
                SynthesisLog(errorMessage, true);
                throw new JsonSerializationException(errorMessage, jsonException);
            }

            // 1. Detect presence of Coins of Tamriel V2 Replacer plugin.
            if (!state.LoadOrder.TryGetValue(CoinsOfTamrielV2.ModKey, out var coinsOfTamrielContainer) ||
                coinsOfTamrielContainer.Mod is null)
            {
                throw new MissingModException(CoinsOfTamrielV2.ModKey,
                                              $"Mod {CoinsOfTamrielV2.ModKey.Name} was not found in Load Order.");
            }
            var coinsIndex = state.LoadOrder.IndexOf(CoinsOfTamrielV2.ModKey);

            // 2. Patching ALL Containers for Currency Related information dynamically.
            var coinsOfTamrielMod = coinsOfTamrielContainer.Mod;
            var nativeContainers  = coinsOfTamrielMod.Containers;

            // 2.a. Find Winning Containers we are allowed to clone, change and apply our algorithm to.
            var containersToPatch = state.LoadOrder
                                    .PriorityOrder
                                    .Container()
                                    .WinningContextOverrides()
                                    .Where(context =>
            {
                // Detection Triggers ...
                return(!nativeContainers.Contains(context.Record) &&
                       (context.Record.Items?.Any(container =>
                                                  container.Item.Item.IsOneOf(
                                                      LootGoldChange,
                                                      LootPerkGoldenTouch,
                                                      LootPerkGoldenTouchChange,
                                                      LootImperialLuck,
                                                      LootFalmerGoldBoss,
                                                      Gold)) ?? false) &&
                       context.Record.Matches(MatchType.Nordic, config));
            });

            // TESTING SECTION //
            containersToPatch.ForEach(ctx =>
                                      SynthesisLog(
                                          $"Container {ctx.Record.FormKey}: {ctx.Record.EditorID} - {ctx.Record.Name} from {ctx.ModKey.FileName} eligible."));
            return;

            // TESTING SECTION //


            // 2.b. Patch up Native containers originating within Coins of Tamriel plugin that are left over.
            // NOTE: Will only patch against the most recent override, i.e. The load order provided must be already
            // conflict resolved for everything UPTO BUT NOT INCLUSIVE OF Coins of Tamriel V2 itself.

            #region Test 1

            // Test 1 : Overriding containers proof of concept works as expected.
            var counter = 0;
            foreach (var container in nativeContainers)
            {
                //state.LoadOrder.ListedOrder.Take(coinsOfTamrielContainer.index)
                //  .Do(x => Console.WriteLine(x.ModKey));

                var containerContext = state.LoadOrder.ListedOrder.Take(coinsIndex)
                                       .Reverse()
                                       .Container()
                                       .WinningContextOverrides()
                                       .FirstOrDefault(recentContainer => container.FormKey == recentContainer.Record.FormKey);

                if (containerContext is null)
                {
                    continue;
                }
                var closestWinningContainer = containerContext.Record;

                SynthesisLog($"{containerContext.ModKey} for {containerContext.Record.Name}");
                //var cond2 = !Equals(closestWinningContainer, container);
                //var cond3 = !closestWinningContainer?.FormKey.ModKey.IsSkyrimBaseMod();
                //SynthesisLog($"{cond1} {cond2} {cond3}");

                if (!Equals(closestWinningContainer, container) &&
                    !Implicits.Get(state.PatchMod.GameRelease).BaseMasters.Contains(containerContext.ModKey))
                {
                    SynthesisLog("reached B");
                    var adjustedContainer = state.PatchMod.Containers.GetOrAddAsOverride(closestWinningContainer);
                    //var goldenTouchChange = state.LinkCache.Lookup<ILeveledItemGetter>(Skyrim.LeveledItem.LootPerkGoldenTouchChange);
                    var itemsToReplace = adjustedContainer.Items?.FindAll(i =>
                                                                          i.Item.Item.Equals(LootPerkGoldenTouchChange));
                    ContainerEntry goldenTouchChangeNordic = new ContainerEntry
                    {
                        Item = new ContainerItem()
                        {
                            Count = 1,
                            Item  = CoinsOfTamrielV2.LeveledItem.LootPerkGoldenTouchChangeNordic
                        }
                    };

                    itemsToReplace?.ForEach(goldenTouchChange =>
                                            adjustedContainer.Items.Replace <ContainerEntry>(goldenTouchChange, goldenTouchChangeNordic));

                    counter++;
                }
            }


            SynthesisLog($"Performed {counter} replacements in Containers", true);

            #endregion

            // 3. Patched Leveled List items based on predicate dynamically.

            // 4. Patch REFRs with randomized generated variations of coins/currencies across worldspaces and cells.


            // P.S: Activator, Flora, NAVI, Quest are either used in the above or are unrelated and don't need patching.
        }
Exemple #23
0
        public static void RunPatch(IPatcherState <ISkyrimMod, ISkyrimModGetter> state)
        {
            List <IngrCombination>          combinations = new List <IngrCombination>();
            IEnumerable <IIngredientGetter> ingredients  = state.LoadOrder.PriorityOrder.OnlyEnabled().Ingredient().WinningOverrides();

            ingredients = from ingrs in ingredients where !SkipPlugins.Contains(ingrs.FormKey.ModKey.Name.ToLower()) select ingrs;
            ingredients = from ingrs in ingredients where (!SkipIngrs.Intersect(ingrs.Name?.ToString()?.Split() !).Any() || SkipIngrs.Contains(ingrs.Name?.ToString())) select ingrs;
            ingredients = from ingrs in ingredients where !String.IsNullOrEmpty(ingrs.Name?.String) select ingrs;
            IEnumerator <IIngredientGetter> enumerator = ingredients.GetEnumerator();
            int i       = 0;
            int percent = (int)(ingredients.Count() * outputPercentage);

            while (enumerator.MoveNext())
            {
                sw.Start();
                if (i % percent == 0)
                {
                    Console.WriteLine(i + " out of " + ingredients.Count() + " ingredients processed.");
                }
                List <IIngredientGetter> remainingingr    = ingredients.Skip(i).ToList();
                IIngredientGetter[]      potionRecipeList = getIngredientsMatchingOneIngredient(enumerator.Current, remainingingr);
                if (String.IsNullOrEmpty(enumerator.Current.Name?.String))
                {
                    i++;
                    continue;
                }
                foreach (IIngredientGetter ingr in potionRecipeList)
                {
                    IEnumerable <IEffectGetter> ActiveEffects = ingr.Effects.Intersect(enumerator.Current.Effects).ToArray();
                    ActiveEffects = ActiveEffects.Distinct();
                    IEffectGetter[] ActiveEffectsA = ActiveEffects.ToArray();
                    if (ActiveEffectsA.Length < 1)
                    {
                        continue;
                    }
                    String potionString = "<font face='$HandwrittenFont'><font size='26'>";
                    potionString += "-<b>" + (enumerator.Current.Name + "<br><b>-<b>" + ingr.Name + "</b>");
                    List <String?> mgeflist  = new List <String?>();
                    List <String?> mgeflists = new List <String?>();
                    foreach (IEffectGetter effect in ActiveEffectsA)
                    {
                        state.LinkCache.TryResolve <IMagicEffectGetter>(effect.BaseEffect.FormKey, out var mgeffect);
                        mgeflist.Add(mgeffect?.Name?.String);
                        mgeflists.AddRange(mgeffect?.Name?.String?.Split() !);
                    }
                    String prefix = "Potion";
                    int    type   = 0;
                    if (!mgeflists.Intersect(potionWords.ToList()).Any() && mgeflists.Intersect(poisonWords.ToList()).Any())
                    {
                        prefix = "Poison";
                        type   = 1;
                        if (mgeflist.Count() <= poisonSkipThreshold)
                        {
                            continue;
                        }
                        poisonRecipeCount++;
                    }
                    else if (mgeflists.Intersect(potionWords.ToList()).Any() && mgeflists.Intersect(poisonWords.ToList()).Any())
                    {
                        prefix = "Impure Potion";
                        type   = 2;
                        if (mgeflist.Count() <= impureSkipThreshold)
                        {
                            continue;
                        }
                        impurepotionRecipeCount++;
                    }
                    else
                    {
                        if (mgeflist.Count() <= potionSkipThreshold)
                        {
                            continue;
                        }
                        potionRecipeCount++;
                    }
                    potionString += ("</font><font face='$HandwrittenFont'><font size='18'><br> to make " + prefix + " of ");
                    String potionName = "Recipe: ";
                    for (int k = 0; k < mgeflist.Count(); k++)
                    {
                        if (k > 0)
                        {
                            potionName   += " and ";
                            potionString += ("<br>");
                        }
                        potionName   += mgeflist[k];
                        potionString += (mgeflist[k]);
                    }
                    String sstring = "";

                    if (mgeflist.Count() > 1)
                    {
                        sstring = "s";
                    }

                    potionString += ("<br></font><font size='14'> Contains " + mgeflist.Count() + " Effect" + sstring);
                    potionString += "<\\font>";
                    IIngredientGetter[] ingrss = { enumerator.Current, ingr };
                    combinations.Add(new IngrCombination(potionName, ingrss, mgeflist?.ToArray() !, potionString, type));
                }
                int j = i + 1;
                IEnumerator <IIngredientGetter> enumerator2 = remainingingr.GetEnumerator();
                while (enumerator2.MoveNext())
                {
                    if (enumerator2.Current.Name?.Equals(enumerator.Current.Name) ?? true || String.IsNullOrEmpty(enumerator2.Current.Name?.String) || !enumerator.Current.Effects.Intersect(enumerator2.Current.Effects).Any())
                    {
                        j++;
                        continue;
                    }
                    List <IIngredientGetter> remainingingr2    = ingredients.Skip(j).ToList();
                    IIngredientGetter[]      potionRecipeList2 = getIngredientsMatchingTwoIngredients(enumerator.Current, enumerator2.Current, remainingingr2);
                    foreach (IIngredientGetter ingr in potionRecipeList2)
                    {
                        IEnumerable <IEffectGetter> ActiveEffects  = ingr.Effects.Intersect(enumerator.Current.Effects);
                        IEnumerable <IEffectGetter> ActiveEffects2 = ingr.Effects.Intersect(enumerator2.Current.Effects);
                        IEnumerable <IEffectGetter> ActiveEffects3 = enumerator.Current.Effects.Intersect(enumerator2.Current.Effects);
                        ActiveEffects.ToList().AddRange(ActiveEffects2);
                        ActiveEffects.ToList().AddRange(ActiveEffects3);
                        ActiveEffects = ActiveEffects.Distinct();
                        IEffectGetter[] ActiveEffectsA = ActiveEffects.ToArray();
                        if (ActiveEffectsA.Length < 1)
                        {
                            continue;
                        }
                        String potionString = "<font face='$HandwrittenFont'><font size='26'>";
                        potionString += "-<b>" + (enumerator.Current.Name + "<br></b>-<b>" + enumerator2.Current.Name + "<br></b>-<b>" + ingr.Name + "</b>");
                        List <String?> mgeflist  = new List <String?>();
                        List <String?> mgeflists = new List <String?>();
                        foreach (IEffectGetter effect in ActiveEffects)
                        {
                            state.LinkCache.TryResolve <IMagicEffectGetter>(effect.BaseEffect.FormKey, out var mgeffect);
                            mgeflist.Add(mgeffect?.Name?.String);
                            mgeflists.AddRange(mgeffect?.Name?.String?.Split() !);
                        }
                        String prefix = "Potion";
                        int    type   = 0;
                        if (!mgeflists.Intersect(potionWords.ToList()).Any() && mgeflists.Intersect(poisonWords.ToList()).Any())
                        {
                            prefix = "Poison";
                            type   = 1;
                            if (mgeflist.Count() <= poisonSkipThreshold)
                            {
                                continue;
                            }
                            poisonRecipeCount++;
                        }
                        else if (mgeflist.Intersect(potionWords.ToList()).Any() && mgeflists.Intersect(poisonWords.ToList()).Any())
                        {
                            prefix = "Impure Potion";
                            type   = 2;
                            if (mgeflists.Count() <= impureSkipThreshold)
                            {
                                continue;
                            }
                            impurepotionRecipeCount++;
                        }
                        else
                        {
                            if (mgeflist.Count() <= potionSkipThreshold)
                            {
                                continue;
                            }
                            potionRecipeCount++;
                        }
                        potionString += ("</font><font face='$HandwrittenFont'><font size='18'><br> to make " + prefix + " of: <br></font><font face='$HandwrittenFont'><font size='26'>");
                        String potionName = "Recipe: ";
                        for (int k = 0; k < mgeflist.Count(); k++)
                        {
                            if (k > 0)
                            {
                                potionName   += " and ";
                                potionString += ("<br>");
                            }
                            potionName   += mgeflist[k];
                            potionString += (mgeflist[k]);
                        }
                        String sstring = "";

                        if (mgeflist.Count() > 1)
                        {
                            sstring = "s";
                        }
                        potionString += ("<br></font><font size='14'> Contains " + mgeflist.Count() + " Effect" + sstring);
                        potionString += "<\\font>";
                        IIngredientGetter[] ingrss = { enumerator.Current, enumerator2.Current, ingr };
                        combinations.Add(new IngrCombination(potionName, ingrss, mgeflist?.ToArray() !, potionString, type));
                    }
                    j++;
                }
                i++;
                if (i % percent == 0)
                {
                    sw.Stop();
                    Console.WriteLine("time elapsed:  " + sw.Elapsed.TotalSeconds + " seconds");
                    sw.Reset();
                }
            }
            Console.WriteLine("Creating Leveled lists...");
            IEnumerable <IBookGetter> books = from book in state.LoadOrder.PriorityOrder.Book().WinningOverrides() where book.FormKey.Equals(new FormKey(new ModKey("Skyrim", ModType.Master), 0x0F5CB1)) select book;
            IBookGetter noteTemplate        = books.ToList()[0];

            Console.WriteLine("Creating " + combinations.Count() + " recipes.");
            percent = (int)(combinations.Count() * outputPercentage);
            i       = 0;
            /* Main leveled list that gets added to recipe drop */
            LeveledItem      mainpotionRecipeLVLI      = state.PatchMod.LeveledItems.AddNew();
            LeveledItemEntry mainpotionRecipeLVLIentry = new LeveledItemEntry();

            mainpotionRecipeLVLI.Entries = new Noggog.ExtendedList <LeveledItemEntry>();
            LeveledItemEntryData mainpotionRecipeLVLIentrydata = new LeveledItemEntryData();
            GlobalInt            mainpotionGlobal = new GlobalInt(state.PatchMod.GetNextFormKey(), SkyrimRelease.SkyrimSE);

            mainpotionGlobal.Data = new Random().Next(minChance, maxChance);
            state.PatchMod.Globals.Set(mainpotionGlobal);
            mainpotionRecipeLVLI.Global   = mainpotionGlobal;
            mainpotionRecipeLVLI.EditorID = "mainpotionRecipeList";
            /* Must split sub leveled lists because it can only hold 128 items */
            uint potionRecipeListCount       = (potionRecipeCount / 128) + 1;
            uint poisonRecipeListCount       = (poisonRecipeCount / 128) + 1;
            uint impurepotionRecipeListCount = (impurepotionRecipeCount / 128) + 1;

            LeveledItem[] potionRecipeLVLIs           = new LeveledItem[potionRecipeListCount];
            uint          masterpotionRecipeListCount = ((potionRecipeListCount + poisonRecipeListCount + impurepotionRecipeListCount) / 128) + 1;

            LeveledItem[]          masterpotionRecipeLVLIs           = new LeveledItem[masterpotionRecipeListCount];
            LeveledItemEntry[]     masterpotionRecipeLVLIentries     = new LeveledItemEntry[masterpotionRecipeListCount];
            LeveledItemEntryData[] masterpotionRecipeLVLIentriesdata = new LeveledItemEntryData[masterpotionRecipeListCount];
            GlobalInt[]            masterpotionGlobals         = new GlobalInt[masterpotionRecipeListCount];
            LeveledItemEntry[]     potionRecipeLVLIentries     = new LeveledItemEntry[potionRecipeListCount];
            LeveledItemEntryData[] potionRecipeLVLIentriesdata = new LeveledItemEntryData[potionRecipeListCount];
            GlobalInt[]            potionGlobals = new GlobalInt[potionRecipeListCount];
            for (int k = 0; k < masterpotionRecipeListCount; k++)
            {
                masterpotionRecipeLVLIentries[k]     = new LeveledItemEntry();
                masterpotionRecipeLVLIentriesdata[k] = new LeveledItemEntryData();
                masterpotionRecipeLVLIs[k]           = state.PatchMod.LeveledItems.AddNew();
                masterpotionRecipeLVLIs[k].Entries   = new Noggog.ExtendedList <LeveledItemEntry>();
                masterpotionGlobals[k]      = new GlobalInt(state.PatchMod.GetNextFormKey(), SkyrimRelease.SkyrimSE);
                masterpotionGlobals[k].Data = new Random().Next(5, 25);
                state.PatchMod.Globals.Set(masterpotionGlobals[k]);
                masterpotionRecipeLVLIs[k].Global              = masterpotionGlobals[k];
                masterpotionRecipeLVLIs[k].EditorID            = "masterpotionRecipeList" + k;
                masterpotionRecipeLVLIentriesdata[k].Reference = masterpotionRecipeLVLIs[k].FormKey;
                masterpotionRecipeLVLIentriesdata[k].Level     = 1;
                masterpotionRecipeLVLIentriesdata[k].Count     = 1;
            }
            for (int l = 0; l < potionRecipeListCount; l++)
            {
                potionRecipeLVLIentries[l]     = new LeveledItemEntry();
                potionRecipeLVLIentriesdata[l] = new LeveledItemEntryData();
                potionRecipeLVLIs[l]           = state.PatchMod.LeveledItems.AddNew();
                potionRecipeLVLIs[l].Entries   = new Noggog.ExtendedList <LeveledItemEntry>();
                potionGlobals[l]      = new GlobalInt(state.PatchMod.GetNextFormKey(), SkyrimRelease.SkyrimSE);
                potionGlobals[l].Data = new Random().Next(5, 25);
                state.PatchMod.Globals.Set(potionGlobals[l]);
                potionRecipeLVLIs[i].Global              = potionGlobals[l];
                potionRecipeLVLIs[l].EditorID            = "potionRecipeList" + l;
                potionRecipeLVLIentriesdata[l].Reference = potionRecipeLVLIs[l].FormKey;
                potionRecipeLVLIentriesdata[l].Level     = 1;
                potionRecipeLVLIentriesdata[l].Count     = 1;
            }
            LeveledItem[]          poisonRecipeLVLIs           = new LeveledItem[poisonRecipeListCount];
            LeveledItemEntry[]     poisonRecipeLVLIentries     = new LeveledItemEntry[poisonRecipeListCount];
            LeveledItemEntryData[] poisonRecipeLVLIentriesdata = new LeveledItemEntryData[poisonRecipeListCount];
            GlobalInt[]            poisonGlobals = new GlobalInt[poisonRecipeListCount];
            for (int l = 0; l < poisonRecipeListCount; l++)
            {
                poisonRecipeLVLIentries[l]     = new LeveledItemEntry();
                poisonRecipeLVLIentriesdata[l] = new LeveledItemEntryData();
                poisonRecipeLVLIs[l]           = state.PatchMod.LeveledItems.AddNew();
                poisonRecipeLVLIs[l].Entries   = new Noggog.ExtendedList <LeveledItemEntry>();
                poisonGlobals[l]      = new GlobalInt(state.PatchMod.GetNextFormKey(), SkyrimRelease.SkyrimSE);
                poisonGlobals[l].Data = new Random().Next(5, 25);
                state.PatchMod.Globals.Set(poisonGlobals[l]);
                poisonRecipeLVLIs[i].Global              = poisonGlobals[l];
                poisonRecipeLVLIs[l].EditorID            = "poisonRecipeList" + l;
                poisonRecipeLVLIentriesdata[l].Reference = poisonRecipeLVLIs[l].FormKey;
                poisonRecipeLVLIentriesdata[l].Level     = 1;
                poisonRecipeLVLIentriesdata[l].Count     = 1;
            }
            LeveledItem[]          impurepotionRecipeLVLIs           = new LeveledItem[impurepotionRecipeListCount];
            LeveledItemEntry[]     impurepotionRecipeLVLIentries     = new LeveledItemEntry[impurepotionRecipeListCount];
            LeveledItemEntryData[] impurepotionRecipeLVLIentriesdata = new LeveledItemEntryData[impurepotionRecipeListCount];
            GlobalInt[]            impurepotionGlobals = new GlobalInt[impurepotionRecipeListCount];
            for (int l = 0; l < impurepotionRecipeListCount; l++)
            {
                impurepotionRecipeLVLIentries[l]     = new LeveledItemEntry();
                impurepotionRecipeLVLIentriesdata[l] = new LeveledItemEntryData();
                impurepotionRecipeLVLIs[l]           = state.PatchMod.LeveledItems.AddNew();
                impurepotionRecipeLVLIs[l].Entries   = new Noggog.ExtendedList <LeveledItemEntry>();
                impurepotionGlobals[l]      = new GlobalInt(state.PatchMod.GetNextFormKey(), SkyrimRelease.SkyrimSE);
                impurepotionGlobals[l].Data = new Random().Next(5, 25);
                state.PatchMod.Globals.Set(impurepotionGlobals[l]);
                impurepotionRecipeLVLIs[i].Global              = impurepotionGlobals[l];
                impurepotionRecipeLVLIs[l].EditorID            = "impurepotionRecipeList" + l;
                impurepotionRecipeLVLIentriesdata[l].Reference = impurepotionRecipeLVLIs[l].FormKey;
                impurepotionRecipeLVLIentriesdata[l].Level     = 1;
                impurepotionRecipeLVLIentriesdata[l].Count     = 1;
            }
            Console.WriteLine("Splitting potions into lists (" + potionRecipeListCount + " " + poisonRecipeListCount + " " + impurepotionRecipeListCount + ")");
            uint potionIndex = 0, poisonIndex = 0, impurepotionIndex = 0;

            IEffectGetter[]          effectCache       = getAllEffects(ingredients).ToArray();
            Dictionary <String, int> nameCache         = new Dictionary <String, int>();

            foreach (IngrCombination ic in combinations)
            {
                if (i % percent == 0)
                {
                    Console.WriteLine(i + " out of " + combinations.Count() + " recipes created.");
                }
                IBook newRecipe = noteTemplate.DeepCopy();
                newRecipe.FormKey     = state.PatchMod.GetNextFormKey();
                newRecipe.Description = ic.RecipeName;
                newRecipe.Name        = ic.RecipeName;
                newRecipe.BookText    = ic.PotionString;
                newRecipe.Weight      = recipeWeight;
                String?name = "recipeof";
                foreach (String?s in ic.MyEffects !)
                {
                    name += s;
                }
                name = name.Replace(" ", String.Empty);
                int nameIndex = 0;
                if (nameCache.TryGetValue(name, out nameIndex))
                {
                    nameCache[name] = nameIndex + 1;
                    name            = name + nameCache[name];
                }
                else
                {
                    nameCache.Add(name, 0);
                    name = name + "0";
                }
                newRecipe.EditorID = name;
                state.PatchMod.Books.Set((Book)newRecipe);
                LeveledItemEntry     lie  = new LeveledItemEntry();
                LeveledItemEntryData data = new LeveledItemEntryData();
                data.Level     = 1;
                data.Count     = 1;
                data.Reference = new FormLink <IItemGetter>(newRecipe.FormKey);
                lie.Data       = data;
                switch (ic.Type)
                {
                case 0:
                    potionRecipeLVLIentriesdata[potionIndex / 128].Reference = potionRecipeLVLIs[potionIndex / 128].FormKey;
                    potionRecipeLVLIentries[potionIndex / 128].Data          = potionRecipeLVLIentriesdata[potionIndex / 128];
                    potionRecipeLVLIs[potionIndex / 128].Entries?.Add(lie);
                    potionIndex++;
                    break;

                case 1:
                    poisonRecipeLVLIentriesdata[poisonIndex / 128].Reference = poisonRecipeLVLIs[poisonIndex / 128].FormKey;
                    poisonRecipeLVLIentries[poisonIndex / 128].Data          = poisonRecipeLVLIentriesdata[poisonIndex / 128];
                    poisonRecipeLVLIs[poisonIndex / 128].Entries?.Add(lie);
                    poisonIndex++;
                    break;

                case 2:
                    impurepotionRecipeLVLIentriesdata[impurepotionIndex / 128].Reference = impurepotionRecipeLVLIs[impurepotionIndex / 128].FormKey;
                    impurepotionRecipeLVLIentries[impurepotionIndex / 128].Data          = impurepotionRecipeLVLIentriesdata[impurepotionIndex / 128];
                    impurepotionRecipeLVLIs[impurepotionIndex / 128].Entries?.Add(lie);
                    impurepotionIndex++;
                    break;
                }
                i++;
            }

            Console.WriteLine("Linking recipes to potion leveled list");
            IEnumerable <ILeveledItemGetter> lvlilists = from list in state.LoadOrder.PriorityOrder.OnlyEnabled().LeveledItem().WinningOverrides() where list.EditorID?.Equals("LItemPotionAll") ?? true select list;
            ILeveledItemGetter allList                 = lvlilists.ToList()[0];
            LeveledItem        modifiedList            = state.PatchMod.LeveledItems.GetOrAddAsOverride(allList);

            potionIndex       = 0;
            poisonIndex       = 0;
            impurepotionIndex = 0;
            for (int l = 0; l < masterpotionRecipeListCount; l++)
            {
                masterpotionRecipeLVLIentriesdata[l].Reference = masterpotionRecipeLVLIs[l].FormKey;
                masterpotionRecipeLVLIentries[l].Data          = masterpotionRecipeLVLIentriesdata[l];
                for (int k = 0; k < 128; k++)
                {
                    if (potionIndex < potionRecipeLVLIentries.Count())
                    {
                        masterpotionRecipeLVLIs[l].Entries?.Add(potionRecipeLVLIentries[potionIndex++]);
                    }
                    else if (poisonIndex < poisonRecipeLVLIentries.Count())
                    {
                        masterpotionRecipeLVLIs[l].Entries?.Add(poisonRecipeLVLIentries[poisonIndex++]);
                    }
                    else if (impurepotionIndex < impurepotionRecipeLVLIentries.Count())
                    {
                        masterpotionRecipeLVLIs[l].Entries?.Add(impurepotionRecipeLVLIentries[impurepotionIndex++]);
                    }
                    else
                    {
                        break;
                    }
                }
                mainpotionRecipeLVLI.Entries?.Add(masterpotionRecipeLVLIentries[l]);
            }
            foreach (LeveledItem li in potionRecipeLVLIs)
            {
                state.PatchMod.LeveledItems.Set(li);
            }
            foreach (LeveledItem li in poisonRecipeLVLIs)
            {
                state.PatchMod.LeveledItems.Set(li);
            }
            foreach (LeveledItem li in impurepotionRecipeLVLIs)
            {
                state.PatchMod.LeveledItems.Set(li);
            }
            foreach (LeveledItem li in masterpotionRecipeLVLIs)
            {
                state.PatchMod.LeveledItems.Set(li);
            }

            mainpotionRecipeLVLIentrydata.Reference = mainpotionRecipeLVLI.FormKey;
            mainpotionRecipeLVLIentry.Data          = mainpotionRecipeLVLIentrydata;
            mainpotionRecipeLVLIentrydata.Count     = 1;
            mainpotionRecipeLVLIentrydata.Level     = 1;
            modifiedList.Entries?.Add(mainpotionRecipeLVLIentry);
            state.PatchMod.LeveledItems.Set(mainpotionRecipeLVLI);
            Console.WriteLine("Adding recipes to defined containers");
            IEnumerable <IContainerGetter> chests   = from list in state.LoadOrder.PriorityOrder.OnlyEnabled().Container().WinningOverrides() where containerEditorIDs?.ToList().Contains(list.EditorID !) ?? true select list;
            ContainerEntry potionListContainerEntry = new ContainerEntry();
            ContainerItem  potionListContainerItem  = new ContainerItem();

            potionListContainerItem.Item  = mainpotionRecipeLVLI.FormKey;
            potionListContainerItem.Count = 1;
            potionListContainerEntry.Item = potionListContainerItem;
            foreach (IContainerGetter chest in chests)
            {
                Container rChest = state.PatchMod.Containers.GetOrAddAsOverride(chest);
                rChest.Items?.Add(potionListContainerEntry);
            }
        }
        /// <summary>
        ///     Get Or Create Entry
        /// </summary>
        /// <param name="service"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        private ContainerEntry GetOrCreateEntry(Type service, string key)
        {
            var entry = this.GetEntry(service, key);
            if (entry == null)
            {
                entry = new ContainerEntry { Service = service, Key = key };
                this.entries.Add(entry);
            }

            return entry;
        }
Exemple #25
0
        public static void RunPatch(IPatcherState <ISkyrimMod, ISkyrimModGetter> state)
        {
            badKeywordsF = (from keyword in state.LoadOrder.PriorityOrder.OnlyEnabled().Keyword().WinningOverrides() where badKeywords.Contains(keyword.EditorID) select(IFormLink <IKeyword>)(new FormLink <IKeyword>(keyword.FormKey))).ToList();
            IEnumerable <IIngredientGetter> ingredients = state.LoadOrder.PriorityOrder.OnlyEnabled().Ingredient().WinningOverrides().Where(x => !SkipPlugins.Contains(x.FormKey.ModKey.Name.ToLower())).Where(x => (!SkipIngrs.Intersect(x.Name?.ToString()?.Split() !).Any() || SkipIngrs.Contains(x.Name?.ToString()))).Where(x => !String.IsNullOrEmpty(x.Name?.String)).ToList();

            allIngredients       = ingredients;
            percent              = (int)(ingredients.Count() * outputPercentage);
            totalIngredientCount = ingredients.Count();
            Thread[] threads       = new Thread[workerThreadCount];
            int      partitionsize = (ingredients.Count() / workerThreadCount);

            /* Split ingredient list evenly across threads */
            IEnumerable <IIngredientGetter>[] ingredientsL = ingredients.Partition(partitionsize).ToArray();
            /* If there is a remainder add it to last thread */
            if (ingredientsL.Length > workerThreadCount)
            {
                ingredientsL[ingredientsL.Length - 2] = ingredientsL[ingredientsL.Length - 2].Concat(ingredientsL[ingredientsL.Length - 1]);
            }
            sw.Start();
            Console.WriteLine("Using " + workerThreadCount + " threads to handle " + partitionsize + " ingredients each.");
            int startindex = 0;

            for (int u = 0; u < workerThreadCount; u++)
            {
                ListProcessor lp = new ListProcessor(u, state, ingredientsL[u], startindex);
                threads[u] = new Thread(new ThreadStart(lp.run));
                threads[u].Start();
                startindex += partitionsize;
            }
            while (!finishedProcessing)
            {
                if (totalProcessedCount % percent == 0)
                {
                    if (reportedCount != totalProcessedCount)
                    {
                        Console.WriteLine(totalProcessedCount + " out of " + ingredients.Count() + " ingredients processed.");
                        sw.Stop();
                        Console.WriteLine("time elapsed:  " + sw.Elapsed.TotalSeconds + " seconds");
                        sw.Reset();
                        sw.Start();
                        reportedCount = totalProcessedCount;
                    }
                }
                Thread.Sleep(100);
            }
            ;
            Console.WriteLine("Terminating Threads.");
            for (int u = 0; u < workerThreadCount; u++)
            {
                threads[u].Join();
            }
            Console.WriteLine("Creating Leveled lists...");
            IEnumerable <IBookGetter> books = from book in state.LoadOrder.PriorityOrder.Book().WinningOverrides() where book.FormKey.Equals(new FormKey(new ModKey("Skyrim", ModType.Master), 0x0F5CB1)) select book;
            IBookGetter noteTemplate        = books.ToList()[0];

            Console.WriteLine("Creating " + combinations.Count + " recipes.");
            percent = (int)(combinations.Count * outputPercentage);
            int i = 0;
            /* Main leveled list that gets added to recipe drop */
            LeveledItem      mainpotionRecipeLVLI      = state.PatchMod.LeveledItems.AddNew();
            LeveledItemEntry mainpotionRecipeLVLIentry = new LeveledItemEntry();

            mainpotionRecipeLVLI.Entries = new Noggog.ExtendedList <LeveledItemEntry>();
            LeveledItemEntryData mainpotionRecipeLVLIentrydata = new LeveledItemEntryData();
            GlobalInt            mainpotionGlobal = new GlobalInt(state.PatchMod.GetNextFormKey(), SkyrimRelease.SkyrimSE);

            mainpotionGlobal.Data = new Random().Next(minChance, maxChance);
            state.PatchMod.Globals.Set(mainpotionGlobal);
            mainpotionRecipeLVLI.Global   = mainpotionGlobal;
            mainpotionRecipeLVLI.EditorID = "mainpotionRecipeList";
            /* Must split sub leveled lists because it can only hold 128 items */
            uint potionRecipeListCount       = (potionRecipeCount / 128) + 1;
            uint poisonRecipeListCount       = (poisonRecipeCount / 128) + 1;
            uint impurepotionRecipeListCount = (impurepotionRecipeCount / 128) + 1;

            LeveledItem[] potionRecipeLVLIs           = new LeveledItem[potionRecipeListCount];
            uint          masterpotionRecipeListCount = ((potionRecipeListCount + poisonRecipeListCount + impurepotionRecipeListCount) / 128) + 1;

            LeveledItem[]          masterpotionRecipeLVLIs           = new LeveledItem[masterpotionRecipeListCount];
            LeveledItemEntry[]     masterpotionRecipeLVLIentries     = new LeveledItemEntry[masterpotionRecipeListCount];
            LeveledItemEntryData[] masterpotionRecipeLVLIentriesdata = new LeveledItemEntryData[masterpotionRecipeListCount];
            GlobalInt[]            masterpotionGlobals         = new GlobalInt[masterpotionRecipeListCount];
            LeveledItemEntry[]     potionRecipeLVLIentries     = new LeveledItemEntry[potionRecipeListCount];
            LeveledItemEntryData[] potionRecipeLVLIentriesdata = new LeveledItemEntryData[potionRecipeListCount];
            GlobalInt[]            potionGlobals = new GlobalInt[potionRecipeListCount];
            for (int k = 0; k < masterpotionRecipeListCount; k++)
            {
                masterpotionRecipeLVLIentries[k]     = new LeveledItemEntry();
                masterpotionRecipeLVLIentriesdata[k] = new LeveledItemEntryData();
                masterpotionRecipeLVLIs[k]           = state.PatchMod.LeveledItems.AddNew();
                masterpotionRecipeLVLIs[k].Entries   = new Noggog.ExtendedList <LeveledItemEntry>();
                masterpotionGlobals[k]      = new GlobalInt(state.PatchMod.GetNextFormKey(), SkyrimRelease.SkyrimSE);
                masterpotionGlobals[k].Data = new Random().Next(5, 25);//Chance of picking a recipe from this list
                state.PatchMod.Globals.Set(masterpotionGlobals[k]);
                masterpotionRecipeLVLIs[k].Global              = masterpotionGlobals[k];
                masterpotionRecipeLVLIs[k].EditorID            = "masterpotionRecipeList" + k;
                masterpotionRecipeLVLIentriesdata[k].Reference = masterpotionRecipeLVLIs[k].FormKey;
                masterpotionRecipeLVLIentriesdata[k].Level     = 1;
                masterpotionRecipeLVLIentriesdata[k].Count     = 1;
            }
            for (int l = 0; l < potionRecipeListCount; l++)
            {
                potionRecipeLVLIentries[l]     = new LeveledItemEntry();
                potionRecipeLVLIentriesdata[l] = new LeveledItemEntryData();
                potionRecipeLVLIs[l]           = state.PatchMod.LeveledItems.AddNew();
                potionRecipeLVLIs[l].Entries   = new Noggog.ExtendedList <LeveledItemEntry>();
                potionGlobals[l]      = new GlobalInt(state.PatchMod.GetNextFormKey(), SkyrimRelease.SkyrimSE);
                potionGlobals[l].Data = new Random().Next(5, 25);//Chance of picking a recipe from this list
                state.PatchMod.Globals.Set(potionGlobals[l]);
                potionRecipeLVLIs[i].Global              = potionGlobals[l];
                potionRecipeLVLIs[l].EditorID            = "potionRecipeList" + l;
                potionRecipeLVLIentriesdata[l].Reference = potionRecipeLVLIs[l].FormKey;
                potionRecipeLVLIentriesdata[l].Level     = 1;
                potionRecipeLVLIentriesdata[l].Count     = 1;
            }
            LeveledItem[]          poisonRecipeLVLIs           = new LeveledItem[poisonRecipeListCount];
            LeveledItemEntry[]     poisonRecipeLVLIentries     = new LeveledItemEntry[poisonRecipeListCount];
            LeveledItemEntryData[] poisonRecipeLVLIentriesdata = new LeveledItemEntryData[poisonRecipeListCount];
            GlobalInt[]            poisonGlobals = new GlobalInt[poisonRecipeListCount];
            for (int l = 0; l < poisonRecipeListCount; l++)
            {
                poisonRecipeLVLIentries[l]     = new LeveledItemEntry();
                poisonRecipeLVLIentriesdata[l] = new LeveledItemEntryData();
                poisonRecipeLVLIs[l]           = state.PatchMod.LeveledItems.AddNew();
                poisonRecipeLVLIs[l].Entries   = new Noggog.ExtendedList <LeveledItemEntry>();
                poisonGlobals[l]      = new GlobalInt(state.PatchMod.GetNextFormKey(), SkyrimRelease.SkyrimSE);
                poisonGlobals[l].Data = new Random().Next(5, 25);//Chance of picking a recipe from this list
                state.PatchMod.Globals.Set(poisonGlobals[l]);
                poisonRecipeLVLIs[i].Global              = poisonGlobals[l];
                poisonRecipeLVLIs[l].EditorID            = "poisonRecipeList" + l;
                poisonRecipeLVLIentriesdata[l].Reference = poisonRecipeLVLIs[l].FormKey;
                poisonRecipeLVLIentriesdata[l].Level     = 1;
                poisonRecipeLVLIentriesdata[l].Count     = 1;
            }
            LeveledItem[]          impurepotionRecipeLVLIs           = new LeveledItem[impurepotionRecipeListCount];
            LeveledItemEntry[]     impurepotionRecipeLVLIentries     = new LeveledItemEntry[impurepotionRecipeListCount];
            LeveledItemEntryData[] impurepotionRecipeLVLIentriesdata = new LeveledItemEntryData[impurepotionRecipeListCount];
            GlobalInt[]            impurepotionGlobals = new GlobalInt[impurepotionRecipeListCount];
            for (int l = 0; l < impurepotionRecipeListCount; l++)
            {
                impurepotionRecipeLVLIentries[l]     = new LeveledItemEntry();
                impurepotionRecipeLVLIentriesdata[l] = new LeveledItemEntryData();
                impurepotionRecipeLVLIs[l]           = state.PatchMod.LeveledItems.AddNew();
                impurepotionRecipeLVLIs[l].Entries   = new Noggog.ExtendedList <LeveledItemEntry>();
                impurepotionGlobals[l]      = new GlobalInt(state.PatchMod.GetNextFormKey(), SkyrimRelease.SkyrimSE);
                impurepotionGlobals[l].Data = new Random().Next(5, 25);//Chance of picking a recipe from this list
                state.PatchMod.Globals.Set(impurepotionGlobals[l]);
                impurepotionRecipeLVLIs[i].Global              = impurepotionGlobals[l];
                impurepotionRecipeLVLIs[l].EditorID            = "impurepotionRecipeList" + l;
                impurepotionRecipeLVLIentriesdata[l].Reference = impurepotionRecipeLVLIs[l].FormKey;
                impurepotionRecipeLVLIentriesdata[l].Level     = 1;
                impurepotionRecipeLVLIentriesdata[l].Count     = 1;
            }
            Console.WriteLine("Splitting potions into lists (" + potionRecipeListCount + " " + poisonRecipeListCount + " " + impurepotionRecipeListCount + ")");
            uint potionIndex = 0, poisonIndex = 0, impurepotionIndex = 0;
            Dictionary <String, int> nameCache         = new Dictionary <String, int>();

            foreach (IngrCombination ic in combinations)
            {
                if (i % percent == 0)
                {
                    Console.WriteLine(i + " out of " + combinations.Count + " recipes created.");
                }
                IBook newRecipe = noteTemplate.DeepCopy();
                newRecipe.FormKey = state.PatchMod.GetNextFormKey();
                String prefix = "[Potion]";
                if (ic.Type == 1)
                {
                    prefix = "[Poison]";
                }
                if (ic.Type == 2)
                {
                    prefix = "[Impure Potion]";
                }
                newRecipe.Description = prefix + ic.RecipeName;
                newRecipe.Name        = ic.RecipeName;
                newRecipe.BookText    = ic.PotionString;
                newRecipe.Weight      = recipeWeight;
                newRecipe.Value       = recipeValue;
                String?name = "recipeof";
                foreach (String?s in ic.MyEffects !)
                {
                    name += s;
                }
                name = name.Replace(" ", String.Empty);
                int nameIndex = 0;
                if (nameCache.TryGetValue(name, out nameIndex))
                {
                    nameCache[name] = nameIndex + 1;
                    name            = name + nameCache[name];
                }
                else
                {
                    nameCache.Add(name, 0);
                    name = name + "0";
                }
                newRecipe.EditorID = name;
                /* Add ingredients to CACO learning recipe script */
                if (state.LoadOrder.ContainsKey(ModKey.FromNameAndExtension("Complete Alchemy & Cooking Overhaul.esp")))
                {
                    String[] s = (from scriptentry in newRecipe.VirtualMachineAdapter?.Scripts where scriptentry.Name.Equals("CACO_AlchemyRecipeScript") select scriptentry.Name).ToArray();
                    if (s.Length < 1 && learnEffectsFromRecipe)//For adding recipe to a brand new item (not a copy of a vanilla recipe)
                    {
                        ScriptEntry cacoscript = new ScriptEntry();
                        cacoscript.Name = "CACO_AlchemyRecipeScript";
                        newRecipe.VirtualMachineAdapter?.Scripts.Add(cacoscript);
                    }
                    if (newRecipe.VirtualMachineAdapter?.Scripts != null)//For modiying a copy of a vanilla recipe modified by CACO(default)
                    {
                        foreach (ScriptEntry se in newRecipe.VirtualMachineAdapter?.Scripts !)
                        {
                            if (se == null)
                            {
                                continue;
                            }
                            if (se.Name.Equals("CACO_AlchemyRecipeScript"))
                            {
                                if (!learnEffectsFromRecipe)
                                {
                                    newRecipe.VirtualMachineAdapter?.Scripts?.Remove(se);
                                    continue;
                                }
                                int[,] ingrEffectIndex = new int[3, 4];
                                for (int j = 0; j < ingrEffectIndex.GetLength(0); j++)
                                {
                                    for (int k = 0; k < ingrEffectIndex.GetLength(1); k++)
                                    {
                                        ingrEffectIndex[j, k] = -1;
                                    }
                                }
                                for (int j = 0; j < ic.MyIngrs.Length; j++)
                                {
                                    int offset = 0;
                                    for (int k = 0; k < ic.MyIngrs[j].Effects.Count; k++)
                                    {
                                        foreach (String mgefname in ic.MyEffects)
                                        {
                                            state.LinkCache.TryResolve <IMagicEffectGetter>(ic.MyIngrs[j].Effects[k].BaseEffect.FormKey, out var mgeffect);
                                            if (mgeffect?.Name?.String?.Equals(mgefname) ?? true)
                                            {
                                                ingrEffectIndex[j, offset++] = k;
                                            }
                                        }
                                    }
                                }
                                bool[,] exists = new bool[3, 4];
                                bool[] rexists = new bool[3];
                                bool   trexist = false, nvarexist = false, arrexist = false;
                                foreach (ScriptProperty sp in se.Properties)//Scan CACO learning script properties
                                {
                                    switch (sp.Name)
                                    {
                                    case "ThisRecipe":
                                        sp.Flags = ScriptProperty.Flag.Edited;
                                        ((ScriptObjectProperty)sp).Object = new FormLink <ISkyrimMajorRecordGetter>(newRecipe.FormKey);
                                        trexist = true;
                                        break;

                                    case "NoValueAfterRead":
                                        sp.Flags = ScriptProperty.Flag.Edited;
                                        ((ScriptBoolProperty)sp).Data = hasValueAfterRead;
                                        nvarexist = true;
                                        break;

                                    case "CACO_AlchemyRecipesRead":
                                        arrexist = true;
                                        break;
                                    }
                                    for (int j = 0; j < 3; j++)
                                    {
                                        if (sp.Name.Equals("Ingredient0" + (j + 1)))
                                        {
                                            if (ic.MyIngrs.Length > j)
                                            {
                                                sp.Flags = ScriptProperty.Flag.Edited;
                                                ((ScriptObjectProperty)sp).Object = new FormLink <ISkyrimMajorRecordGetter>(ic.MyIngrs[j].FormKey);
                                                rexists[j] = true;
                                            }
                                        }
                                    }
                                    for (int j = 0; j < 3; j++)
                                    {
                                        for (int k = 0; k < 4; k++)
                                        {
                                            if (sp.Name.Equals("Ingredient0" + (j + 1) + "Effect" + (k + 1)))
                                            {
                                                if (ingrEffectIndex[j, k] != -1)
                                                {
                                                    ((ScriptIntProperty)sp).Data = ingrEffectIndex[j, k];
                                                    exists[j, k] = true;
                                                }
                                            }
                                        }
                                    }
                                }
                                for (int j = 0; j < rexists.Length; j++)
                                {
                                    if (ic.MyIngrs.Length > j)
                                    {
                                        if (!rexists[j])
                                        {
                                            ScriptObjectProperty sop = new ScriptObjectProperty();
                                            sop.Object = new FormLink <ISkyrimMajorRecordGetter>(ic.MyIngrs[j].FormKey);
                                            sop.Name   = "Ingredient0" + (j + 1);
                                            sop.Flags  = ScriptProperty.Flag.Edited;
                                            se.Properties.Add(sop);
                                        }
                                    }
                                }
                                for (int j = 0; j < exists.GetLength(0); j++)
                                {
                                    for (int k = 0; k < exists.GetLength(1); k++)
                                    {
                                        if (ic.MyIngrs.Length > j)
                                        {
                                            if (!exists[j, k] && ingrEffectIndex[j, k] != -1)
                                            {
                                                ScriptIntProperty sip = new ScriptIntProperty();
                                                sip.Data  = ingrEffectIndex[j, k];
                                                sip.Name  = "Ingredient0" + (j + 1) + "Effect" + (k + 1);
                                                sip.Flags = ScriptProperty.Flag.Edited;
                                                se.Properties.Add(sip);
                                            }
                                        }
                                    }
                                }
                                if (!trexist)
                                {
                                    ScriptObjectProperty sop = new ScriptObjectProperty();
                                    sop.Object = new FormLink <ISkyrimMajorRecordGetter>(newRecipe.FormKey);
                                    sop.Name   = "ThisRecipe";
                                    sop.Flags  = ScriptProperty.Flag.Edited;
                                    se.Properties.Add(sop);
                                }
                                if (!nvarexist)
                                {
                                    ScriptBoolProperty sbp = new ScriptBoolProperty();
                                    sbp.Data  = hasValueAfterRead;
                                    sbp.Name  = "NoValueAfterRead";
                                    sbp.Flags = ScriptProperty.Flag.Edited;
                                    se.Properties.Add(sbp);
                                }
                                if (arrexist)
                                {
                                    FormList             fl  = new FormList(new FormKey(new ModKey("Complete Alchemy & Cooking Overhaul.esp", ModType.Plugin), 0xA2C667), SkyrimRelease.SkyrimSE);
                                    ScriptObjectProperty sop = new ScriptObjectProperty();
                                    sop.Object = fl;
                                    sop.Name   = "CACO_AlchemyRecipesRead";
                                    sop.Flags  = ScriptProperty.Flag.Edited;
                                    se.Properties.Add(sop);
                                }
                            }
                        }
                    }
                }

                state.PatchMod.Books.Set((Book)newRecipe);
                LeveledItemEntry     lie  = new LeveledItemEntry();
                LeveledItemEntryData data = new LeveledItemEntryData();
                data.Level     = 1;
                data.Count     = 1;
                data.Reference = new FormLink <IItemGetter>(newRecipe.FormKey);
                lie.Data       = data;
                switch (ic.Type)
                {
                case 0:
                    potionRecipeLVLIentriesdata[potionIndex / 128].Reference = potionRecipeLVLIs[potionIndex / 128].FormKey;
                    potionRecipeLVLIentries[potionIndex / 128].Data          = potionRecipeLVLIentriesdata[potionIndex / 128];
                    potionRecipeLVLIs[potionIndex / 128].Entries?.Add(lie);
                    potionIndex++;
                    break;

                case 1:
                    poisonRecipeLVLIentriesdata[poisonIndex / 128].Reference = poisonRecipeLVLIs[poisonIndex / 128].FormKey;
                    poisonRecipeLVLIentries[poisonIndex / 128].Data          = poisonRecipeLVLIentriesdata[poisonIndex / 128];
                    poisonRecipeLVLIs[poisonIndex / 128].Entries?.Add(lie);
                    poisonIndex++;
                    break;

                case 2:
                    impurepotionRecipeLVLIentriesdata[impurepotionIndex / 128].Reference = impurepotionRecipeLVLIs[impurepotionIndex / 128].FormKey;
                    impurepotionRecipeLVLIentries[impurepotionIndex / 128].Data          = impurepotionRecipeLVLIentriesdata[impurepotionIndex / 128];
                    impurepotionRecipeLVLIs[impurepotionIndex / 128].Entries?.Add(lie);
                    impurepotionIndex++;
                    break;
                }
                i++;
            }

            Console.WriteLine("Linking recipes to potion leveled list");
            IEnumerable <ILeveledItemGetter> lvlilists = from list in state.LoadOrder.PriorityOrder.OnlyEnabled().LeveledItem().WinningOverrides() where list.EditorID?.Equals("LItemPotionAll") ?? true select list;
            ILeveledItemGetter allList                 = lvlilists.ToList()[0];
            LeveledItem        modifiedList            = state.PatchMod.LeveledItems.GetOrAddAsOverride(allList);

            potionIndex       = 0;
            poisonIndex       = 0;
            impurepotionIndex = 0;
            for (int l = 0; l < masterpotionRecipeListCount; l++)
            {
                masterpotionRecipeLVLIentriesdata[l].Reference = masterpotionRecipeLVLIs[l].FormKey;
                masterpotionRecipeLVLIentries[l].Data          = masterpotionRecipeLVLIentriesdata[l];
                for (int k = 0; k < 128; k++)
                {
                    if (potionIndex < potionRecipeLVLIentries.Length)
                    {
                        masterpotionRecipeLVLIs[l].Entries?.Add(potionRecipeLVLIentries[potionIndex++]);
                    }
                    else if (poisonIndex < poisonRecipeLVLIentries.Length)
                    {
                        masterpotionRecipeLVLIs[l].Entries?.Add(poisonRecipeLVLIentries[poisonIndex++]);
                    }
                    else if (impurepotionIndex < impurepotionRecipeLVLIentries.Length)
                    {
                        masterpotionRecipeLVLIs[l].Entries?.Add(impurepotionRecipeLVLIentries[impurepotionIndex++]);
                    }
                    else
                    {
                        break;
                    }
                }
                mainpotionRecipeLVLI.Entries?.Add(masterpotionRecipeLVLIentries[l]);
            }
            foreach (LeveledItem li in potionRecipeLVLIs)
            {
                state.PatchMod.LeveledItems.Set(li);
            }
            foreach (LeveledItem li in poisonRecipeLVLIs)
            {
                state.PatchMod.LeveledItems.Set(li);
            }
            foreach (LeveledItem li in impurepotionRecipeLVLIs)
            {
                state.PatchMod.LeveledItems.Set(li);
            }
            foreach (LeveledItem li in masterpotionRecipeLVLIs)
            {
                state.PatchMod.LeveledItems.Set(li);
            }

            mainpotionRecipeLVLIentrydata.Reference = mainpotionRecipeLVLI.FormKey;
            mainpotionRecipeLVLIentry.Data          = mainpotionRecipeLVLIentrydata;
            mainpotionRecipeLVLIentrydata.Count     = 1;
            mainpotionRecipeLVLIentrydata.Level     = 1;
            modifiedList.Entries?.Add(mainpotionRecipeLVLIentry);
            state.PatchMod.LeveledItems.Set(mainpotionRecipeLVLI);
            Console.WriteLine("Adding recipes to defined containers");
            IEnumerable <IContainerGetter> chests   = from list in state.LoadOrder.PriorityOrder.OnlyEnabled().Container().WinningOverrides() where containerEditorIDs?.ToList().Contains(list.EditorID !) ?? true select list;
            ContainerEntry potionListContainerEntry = new ContainerEntry();
            ContainerItem  potionListContainerItem  = new ContainerItem();

            potionListContainerItem.Item  = mainpotionRecipeLVLI.FormKey;
            potionListContainerItem.Count = 1;
            potionListContainerEntry.Item = potionListContainerItem;
            foreach (IContainerGetter chest in chests)
            {
                Container rChest = state.PatchMod.Containers.GetOrAddAsOverride(chest);
                rChest.Items?.Add(potionListContainerEntry);
            }
        }
Exemple #26
0
        public int Write(JsonTextWriter writer, ISearchResult wordMatches, int skip = 0, int take = -1)
        {
            int matchCount = 0;

            ContainerEntry lastRun    = ContainerEntry.Empty;
            ContainerEntry lastResult = ContainerEntry.Empty;

            while (!wordMatches.Done)
            {
                int count = wordMatches.Page(ref _termPositions);
                for (int i = 0; i < count; ++i)
                {
                    long position = _termPositions[i];

                    // If this position isn't in the last run's results array, find the run which contains it
                    if (!lastRun.Contains(position))
                    {
                        // Close previous run, if any
                        if (!lastRun.IsEmpty())
                        {
                            WriteRunSubsetEnd(writer);
                        }

                        // Find containing run
                        lastRun = FindContainerAtDepth(position, _runDepth);

                        // Write run subset
                        _bionReader.Seek(lastRun.StartByteOffset);
                        WriteRunSubsetStart(writer);
                    }

                    // Find and write result
                    ContainerEntry result = FindContainerAtDepth(position, _runDepth + 2);
                    if (!result.IsEmpty() && !lastResult.Equals(result))
                    {
                        matchCount++;
                        if (matchCount <= skip)
                        {
                            continue;
                        }

                        _bionReader.Seek(result.StartByteOffset);
                        JsonBionConverter.BionToJson(_bionReader, writer);

                        if (take >= 0 && matchCount >= skip + take)
                        {
                            break;
                        }
                    }
                }

                if (take >= 0 && matchCount >= skip + take)
                {
                    break;
                }
            }

            // Close last run, if any
            if (!lastRun.IsEmpty())
            {
                WriteRunSubsetEnd(writer);
            }

            return(matchCount);
        }
Exemple #27
0
        private ContainerEntry FindContainerAtDepth(long position, int desiredDepth)
        {
            // Find the first container ending after position.
            ContainerEntry firstAfter      = _containerIndex.FirstEndingAfter(position);
            int            firstAfterDepth = _containerIndex.Depth(firstAfter);

            // Find the ancestor at the desired depth. If there is one, and it contains position, we can use it
            ContainerEntry firstAtDepth = AncestorAtDepth(firstAfter, firstAfterDepth, desiredDepth);

            if (firstAtDepth.Contains(position))
            {
                return(firstAtDepth);
            }

            // If nothing deep enough was indexed, we must find the nearest point of known depth and walk the BION
            long seekToPosition;
            int  seekToDepth;

            // The nearest point is...
            if (firstAfter.StartByteOffset < position)
            {
                // The start of the first container ending after position, if it starts before position
                seekToPosition = firstAfter.StartByteOffset;
                seekToDepth    = firstAfterDepth - 1;
            }
            else if (firstAfter.Index > 0)
            {
                // The end of the container before that, if it started after position
                ContainerEntry lastBefore = _containerIndex[firstAfter.Index - 1];
                seekToPosition = lastBefore.EndByteOffset;
                seekToDepth    = _containerIndex.Depth(lastBefore) - 1;
            }
            else
            {
                // The start of the document, if the first container was found
                seekToPosition = 0;
                seekToDepth    = 0;
            }

            // Seek to that position and read until we find a container at the right depth which contains position
            _bionReader.Seek(seekToPosition);
            long lastContainerStart = -1;
            long lastContainerEnd   = -1;

            while (_bionReader.BytesRead < position + 3)
            {
                _bionReader.Read();

                if (_bionReader.Depth + seekToDepth == desiredDepth)
                {
                    lastContainerStart = _bionReader.BytesRead - 1;
                    _bionReader.SkipRest();
                    lastContainerEnd = _bionReader.BytesRead;
                }
            }

            ContainerEntry found = new ContainerEntry(lastContainerStart, lastContainerEnd, -1);

            if (!found.Contains(position))
            {
                return(ContainerEntry.Empty);
            }

            return(found);
        }
        // Add Item To Container
        bool AddItem(int place, int lowID, int HighID, int Type, uint InstanceItemID, int Amount, int QL, uint Flags)
        {
            if (place == 0x6f)
            {
                // find next free
                int i = 0;
                while (i < NumberOfSlots)
                {
                    if (Items[i] == null)
                        break;
                    i++;
                }

                // No free slot found?
                if (i == NumberOfSlots)
                    return false;

                place = i;
            }

            if ((Type == 0) && (InstanceItemID == 0))
            {
                ContainerEntry ce = new ContainerEntry();
                ce.Type = 0;
                ce.InstanceID = 0;

                ce.LowID = lowID;
                ce.HighID = HighID;
                ce.QL = QL;
                ce.Flags = Flags;

                Items[place] = ce;
            }
            else
            {
                //Instanced items stuff here
            }
            return true;
        }
Exemple #29
0
        /// <summary>
        /// Gets all instances.
        /// </summary>
        /// <param name="service">The service.</param>
        /// <returns></returns>
        public IEnumerable <Object> GetAllInstances(Type service)
        {
            ContainerEntry entry = GetEntry(service, null);

            return(entry != null?entry.Select(x => x()) : new Object[0]);
        }
 // Load All Container Arrays from  SQL
 void LoadFromSQL(string tablename)
 {
     // Empty the Array first
     for (int i = 0; i < Items.Length; i++)
         Items[i] = null;
     SqlWrapper sql = new SqlWrapper();
     DataTable dt = sql.ReadDatatable("SELECT * FROM " + tablename + " WHERE container=" + Type + " AND ID=" + Instance);
     foreach (DataRow row in dt.Rows)
     {
         int place = (Int32)row["placement"];
         if (place < NumberOfSlots)
         {
             if (((Int32)row["type"] != 0) && ((Int32)row["instance"] != 0))
             {
                 // Do stuff with instanced items
                 // Create item from lowid/highid interpolated by QL and read stats from sql
             }
             else
             {
                 ContainerEntry ce = new ContainerEntry();
                 ce.LowID = (Int32)row["lowid"];
                 ce.HighID = (Int32)row["highid"];
                 ce.QL = (Int32)row["quality"];
                 ce.Amount = (Int32)row["multiplecount"];
                 ce.Flags = (uint)row["flags"];
                 ce.InstanceID = 0;
                 ce.Type = 0;
                 Items[place] = ce;
             }
         }
     }
 }