예제 #1
0
            public static OwnerTarget GetBinaryOwner(ReadOnlySpan <byte> span, RecordInfoCache cache, MasterReferenceReader masters)
            {
                FormID  form    = new FormID(BinaryPrimitives.ReadUInt32LittleEndian(span));
                FormKey formKey = FormKey.Factory(masters, form.Raw);

                if (cache.IsOfRecordType <Npc>(formKey))
                {
                    return(new NpcOwner()
                    {
                        Npc = new FormLink <INpcGetter>(FormKeyBinaryTranslation.Instance.Parse(span, masters)),
                        Global = new FormLink <IGlobalGetter>(FormKeyBinaryTranslation.Instance.Parse(span.Slice(4), masters))
                    });
                }
                else if (cache.IsOfRecordType <Faction>(formKey))
                {
                    return(new FactionOwner()
                    {
                        Faction = new FormLink <IFactionGetter>(FormKeyBinaryTranslation.Instance.Parse(span, masters)),
                        RequiredRank = BinaryPrimitives.ReadInt32LittleEndian(span.Slice(4))
                    });
                }
                else
                {
                    return(new NoOwner()
                    {
                        RawOwnerData = BinaryPrimitives.ReadUInt32LittleEndian(span),
                        RawVariableData = BinaryPrimitives.ReadUInt32LittleEndian(span.Slice(4))
                    });
                }
            }
예제 #2
0
        public void Write_MasterListSync_Throw()
        {
            using var tmp = GetFile();
            var mod = new SkyrimMod(WriteKey, SkyrimRelease.SkyrimLE);

            mod.Weapons.RecordCache.Set(
                new Weapon(FormKey.Factory("012345:Skyrim.esm"), SkyrimRelease.SkyrimLE));
            Assert.Throws <RecordException>(
                () =>
            {
                try
                {
                    mod.WriteToBinary(
                        tmp.File.Path,
                        new BinaryWriteParameters()
                    {
                        ModKey             = BinaryWriteParameters.ModKeyOption.NoCheck,
                        MastersListContent = BinaryWriteParameters.MastersListContentOption.NoCheck,
                    });
                }
                catch (RecordException ex)
                {
                    Assert.IsType <ArgumentException>(ex.InnerException);
                    throw;
                }
            });
        }
예제 #3
0
        private TextFileFormKeyAllocator(IMod mod, string filePath)
        {
            this.Mod = mod;
            using var streamReader = new StreamReader(filePath);
            var idLine = streamReader.ReadLine();

            if (!uint.TryParse(idLine, out var nextID))
            {
                throw new ArgumentException($"Unconvertable next ID line: {idLine}");
            }
            this.Mod.NextObjectID = nextID;
            while (true)
            {
                var edidStr    = streamReader.ReadLine();
                var formKeyStr = streamReader.ReadLine();
                if (edidStr == null)
                {
                    break;
                }
                if (formKeyStr == null)
                {
                    throw new ArgumentException("Unexpected odd number of lines.");
                }
                var formKey = FormKey.Factory(formKeyStr);
                _cache.Add(edidStr, formKey);
            }
        }
예제 #4
0
        public override object?ReadJson(JsonReader reader, Type objectType, object?existingValue, JsonSerializer serializer)
        {
            var obj = reader.Value;

            if (obj == null)
            {
                if (objectType == typeof(FormKey))
                {
                    return(FormKey.Null);
                }
                if (objectType == typeof(FormKey?))
                {
                    return(null);
                }
                throw new NotImplementedException();
            }
            else
            {
                if (objectType == typeof(FormKey) ||
                    objectType == typeof(FormKey?))
                {
                    return(FormKey.Factory(obj.ToString()));
                }
                if (!objectType.Name.Contains("FormLink"))
                {
                    throw new ArgumentException();
                }

                if (objectType.Name.AsSpan()[..^ 2].EndsWith("Nullable", StringComparison.Ordinal))
 public FormKey Parse(
     ReadOnlySpan<byte> span,
     MasterReferenceReader masterReferences)
 {
     var id = BinaryPrimitives.ReadUInt32LittleEndian(span);
     return FormKey.Factory(masterReferences, id);
 }
예제 #6
0
        public void Comparer_Alphabetical_Equal()
        {
            FormKey k1      = FormKey.Factory("00C51A:Oblivion.esm");
            FormKey k2      = FormKey.Factory("00C51A:Oblivion.esm");
            var     compare = FormKey.AlphabeticalComparer();

            Assert.Equal(0, compare.Compare(k2, k1));
        }
예제 #7
0
        public void Comparer_Alphabetical_ByIDGreater()
        {
            FormKey k1      = FormKey.Factory("00C51A:Oblivion.esm");
            FormKey k2      = FormKey.Factory("00C51B:Oblivion.esm");
            var     compare = FormKey.AlphabeticalComparer();

            Assert.True(compare.Compare(k2, k1) > 0);
        }
예제 #8
0
        public void Comparer_Alphabetical_ByName()
        {
            FormKey k1      = FormKey.Factory("00C51A:Knights.esm");
            FormKey k2      = FormKey.Factory("00C51A:Oblivion.esm");
            var     compare = FormKey.AlphabeticalComparer();

            Assert.True(compare.Compare(k1, k2) < 0);
        }
예제 #9
0
    public void IteratesContainedFormLinks()
    {
        var mod = new SkyrimMod(ModKey.FromNameAndExtension("Test.esp"), SkyrimRelease.SkyrimSE);
        var npc = mod.Npcs.AddNew();
        var key = FormKey.Factory("123456:Skyrim.esm");

        npc.Class.SetTo(key);
        mod.ContainedFormLinks.Select(x => x.FormKey).Should().Contain(key);
    }
        public override object?ConvertFrom(ITypeDescriptorContext?context, CultureInfo?culture, object value)
        {
            switch (value)
            {
            case string str:
                return(FormKey.Factory(str));

            default:
                throw new NotImplementedException();
            }
        }
예제 #11
0
        public void Comparer_LoadOrder_Unknown()
        {
            var loadOrder = new LoadOrder <OblivionMod>()
            {
                new OblivionMod(ModKey.FromNameAndExtension("Oblivion.esm")),
                new OblivionMod(ModKey.FromNameAndExtension("Knights.esm")),
            };
            FormKey k1      = FormKey.Factory("00C51A:MyMod.esm");
            FormKey k2      = FormKey.Factory("00C51B:Oblivion.esm");
            var     compare = FormKey.LoadOrderComparer(loadOrder);

            Assert.Throws <ArgumentOutOfRangeException>(() => compare.Compare(k1, k2));
        }
예제 #12
0
        public void Comparer_LoadOrder_Typical()
        {
            var loadOrder = new LoadOrder <OblivionMod>()
            {
                new OblivionMod(ModKey.FromNameAndExtension("Oblivion.esm")),
                new OblivionMod(ModKey.FromNameAndExtension("Knights.esm")),
            };
            FormKey k1      = FormKey.Factory("00C51A:Oblivion.esm");
            FormKey k2      = FormKey.Factory("00C51A:Knights.esm");
            var     compare = FormKey.LoadOrderComparer(loadOrder);

            Assert.True(compare.Compare(k1, k2) < 0);
        }
예제 #13
0
        public void Comparer_ModKeyList_Unknown()
        {
            List <ModKey> modKeys = new List <ModKey>()
            {
                ModKey.FromNameAndExtension("Oblivion.esm"),
                ModKey.FromNameAndExtension("Knights.esm"),
            };
            FormKey k1      = FormKey.Factory("00C51A:MyMod.esm");
            FormKey k2      = FormKey.Factory("00C51B:Oblivion.esm");
            var     compare = FormKey.LoadOrderComparer(modKeys);

            Assert.Throws <ArgumentOutOfRangeException>(() => compare.Compare(k1, k2));
        }
예제 #14
0
        public void Comparer_ModKeyList_FallbackGreater()
        {
            List <ModKey> modKeys = new List <ModKey>()
            {
                ModKey.FromNameAndExtension("Oblivion.esm"),
                ModKey.FromNameAndExtension("Knights.esm"),
            };
            FormKey k1      = FormKey.Factory("00C51A:Oblivion.esm");
            FormKey k2      = FormKey.Factory("00C51B:Oblivion.esm");
            var     compare = FormKey.LoadOrderComparer(modKeys);

            Assert.True(compare.Compare(k2, k1) > 0);
        }
예제 #15
0
        public void Comparer_ModKeyList_Typical()
        {
            List <ModKey> modKeys = new List <ModKey>()
            {
                ModKey.FromNameAndExtension("Oblivion.esm"),
                ModKey.FromNameAndExtension("Knights.esm"),
            };
            FormKey k1      = FormKey.Factory("00C51A:Oblivion.esm");
            FormKey k2      = FormKey.Factory("00C51A:Knights.esm");
            var     compare = FormKey.LoadOrderComparer(modKeys);

            Assert.True(compare.Compare(k1, k2) < 0);
        }
예제 #16
0
        public void Comparer_LoadOrder_FallbackGreater()
        {
            var loadOrder = new LoadOrder <OblivionMod>()
            {
                new OblivionMod(ModKey.FromNameAndExtension("Oblivion.esm")),
                new OblivionMod(ModKey.FromNameAndExtension("Knights.esm")),
            };
            FormKey k1      = FormKey.Factory("00C51A:Oblivion.esm");
            FormKey k2      = FormKey.Factory("00C51B:Oblivion.esm");
            var     compare = FormKey.LoadOrderComparer(loadOrder);

            Assert.True(compare.Compare(k2, k1) > 0);
        }
예제 #17
0
        public static EnumerableFormKeySettingsVM Factory(FieldMeta fieldMeta, object?defaultVal)
        {
            var defaultKeys = new List <FormKey>();

            if (defaultVal is IEnumerable e)
            {
                foreach (var item in e)
                {
                    defaultKeys.Add(FormKey.Factory(item.ToString()));
                }
            }
            return(new EnumerableFormKeySettingsVM(
                       fieldMeta,
                       defaultVal as IEnumerable <FormKey> ?? Enumerable.Empty <FormKey>()));
        }
예제 #18
0
        public void Write_MasterListSync()
        {
            using var tmp = GetFile();
            var mod = new SkyrimMod(WriteKey, SkyrimRelease.SkyrimLE);

            mod.Weapons.RecordCache.Set(
                new Weapon(FormKey.Factory("012345:Skyrim.esm"), SkyrimRelease.SkyrimLE));
            mod.WriteToBinary(
                tmp.File.Path,
                new BinaryWriteParameters()
            {
                ModKey             = BinaryWriteParameters.ModKeyOption.NoCheck,
                MastersListContent = BinaryWriteParameters.MastersListContentOption.Iterate,
            });
        }
예제 #19
0
        public void ParallelWrite_MasterListSync_Throw()
        {
            using var tmp = GetFile();
            var mod = new SkyrimMod(WriteKey, SkyrimRelease.SkyrimLE);

            mod.Weapons.RecordCache.Set(
                new Weapon(FormKey.Factory("012345:Skyrim.esm"), SkyrimRelease.SkyrimLE));
            Assert.Throws <AggregateException>(
                () => mod.WriteToBinaryParallel(
                    tmp.File.Path,
                    new BinaryWriteParameters()
            {
                ModKey             = BinaryWriteParameters.ModKeyOption.NoCheck,
                MastersListContent = BinaryWriteParameters.MastersListContentOption.NoCheck,
            }));
        }
예제 #20
0
        public LateSetPickerVM(MainVM mainVM)
        {
            SetCommand = ReactiveCommand.CreateFromTask(async() =>
            {
                LinkCache   = null;
                ScopedTypes = null;
                FormKey     = FormKey.Null;

                await Task.Delay(2000);

                FormKey = FormKey.Factory("0136D4:Skyrim.esm");

                await Task.Delay(2000);

                LinkCache   = mainVM.LinkCache;
                ScopedTypes = mainVM.ScopedTypes;
            });
        }
예제 #21
0
        public static void RunPatch(IPatcherState <ISkyrimMod, ISkyrimModGetter> state)
        {
            //Your code here!

            var keyword_IsAdultRace = FormKey.Factory("045AF7:ImCh.esm");
            var keyword_IsChildRace = FormKey.Factory("005901:ImCh.esm");

            foreach (var furnitureGetter in state.LoadOrder.PriorityOrder.Furniture().WinningOverrides())
            {
                if (furnitureGetter.InteractionKeyword == Skyrim.Keyword.ActorTypeNPC && !furnitureGetter.MajorFlags.HasFlag(Furniture.MajorFlag.ChildCanUse))
                {
                    var furniture = state.PatchMod.Furniture.GetOrAddAsOverride(furnitureGetter);

                    furniture.InteractionKeyword.SetTo(keyword_IsAdultRace);
                }
            }

            foreach (var raceGetter in state.LoadOrder.PriorityOrder.Race().WinningOverrides())
            {
                if (raceGetter.Keywords != null && raceGetter.Keywords.Contains(Skyrim.Keyword.ActorTypeNPC))
                {
                    var race = state.PatchMod.Races.GetOrAddAsOverride(raceGetter);

                    if (race.Flags.HasFlag(Race.Flag.Child))
                    {
                        if (race.Keywords != null)
                        {
                            race.Flags -= Race.Flag.Child;
                            race.Flags |= Race.Flag.AllowPickpocket;
                            race.Keywords.Add(keyword_IsChildRace);
                        }
                    }
                    else
                    {
                        if (race.Keywords != null)
                        {
                            race.Keywords.Add(keyword_IsAdultRace);
                        }
                    }
                }
            }
        }
예제 #22
0
        public void Write_ModNotOnLoadOrder()
        {
            using var tmp = GetFile();
            var mod = new SkyrimMod(WriteKey, SkyrimRelease.SkyrimLE);

            mod.Weapons.RecordCache.Set(
                new Weapon(FormKey.Factory("012345:Skyrim.esm"), SkyrimRelease.SkyrimLE));
            mod.Weapons.RecordCache.Set(
                new Weapon(FormKey.Factory("012345:SomeOtherMod.esp"), SkyrimRelease.SkyrimLE));
            Assert.Throws <MissingModException>(() =>
            {
                mod.WriteToBinary(
                    tmp.File,
                    new BinaryWriteParameters()
                {
                    ModKey              = BinaryWriteParameters.ModKeyOption.NoCheck,
                    MastersListContent  = BinaryWriteParameters.MastersListContentOption.Iterate,
                    MastersListOrdering = new BinaryWriteParameters.MastersListOrderingByLoadOrder(
                        Skyrim.Constants.Skyrim.AsEnumerable())
                });
            });
        }
예제 #23
0
        /// <summary>
        /// Some record copying and new record construction.  Writes to an esp
        /// </summary>
        public static void MakeAMod(string inputPath, string outputPath)
        {
            // Create a readonly mod object from the file path, using the overlay pattern
            using var inputMod = SkyrimMod.CreateFromBinaryOverlay(inputPath, SkyrimRelease.SkyrimSE);

            // Create our mod to eventually export
            var outputMod = new SkyrimMod(ModKey.FromNameAndExtension(Path.GetFileName(outputPath)), SkyrimRelease.SkyrimSE);

            // Copy over all existing weapons, while changing their damage
            foreach (var weap in inputMod.Weapons)
            {
                // Make a copy of the readonly record so we can modify it
                var copy = weap.DeepCopy();

                if (copy.BasicStats == null)
                {
                    // Skip any weapon that doesn't have the stats subrecord
                    continue;
                }

                // Bump up the damage!
                copy.BasicStats.Damage += 100;

                // Add to our output mod
                // The record is implicitly an override, as its FormKey originates from Skyrim.esm, not our mod.
                outputMod.Weapons.RecordCache.Set(copy);
                System.Console.WriteLine($"Overriding {copy.EditorID}");
            }

            // Add our own brand new weapon
            // This convenience function creates a new weapon already added to the mod, with a new FormID
            var overpoweredSword = outputMod.Weapons.AddNew();

            overpoweredSword.EditorID   = "MutagenBlade";
            overpoweredSword.Name       = "Mutagen Blade";
            overpoweredSword.BasicStats = new WeaponBasicStats()
            {
                Damage = 9000,
                Weight = 1,
                Value  = 9000,
            };
            // Actually, scrap this.  Too many things to add by hand.  Let's try by using an existing record as a template

            // Let's base our weapon off Skyrim's DraugrSword
            if (inputMod.Weapons.RecordCache.TryGetValue(FormKey.Factory("02C66F:Skyrim.esm"), out var templateSword))
            {
                // Now we can copy in the values we like from our template.  Let's skip the items we already set earlier
                overpoweredSword.DeepCopyIn(
                    templateSword,
                    // We can optionally specify a mask that copies over everything but our earlier items
                    new Weapon.TranslationMask(true)
                {
                    Name       = false,
                    EditorID   = false,
                    BasicStats = false
                });

                // Now we are good to go, as our weapon is already in our mod, and has the values we want
            }
            else
            {
                System.Console.WriteLine("Couldn't create our sword!  The template could not be found.");
                // I guess let's remove it
                outputMod.Weapons.RecordCache.Remove(overpoweredSword);
            }

            // Write out our mod
            outputMod.WriteToBinaryParallel(outputPath);
            System.Console.WriteLine($"Wrote out mod to: {new FilePath(outputPath).Path}");

            PrintSeparator();
        }
예제 #24
0
        public override object?ReadJson(JsonReader reader, Type objectType, object?existingValue, JsonSerializer serializer)
        {
            var obj = reader.Value;

            if (obj == null)
            {
                if (objectType == typeof(FormKey))
                {
                    return(FormKey.Null);
                }
                if (objectType == typeof(FormKey?))
                {
                    return(null);
                }
                if (!objectType.Name.Contains("FormLink"))
                {
                    throw new ArgumentException();
                }

                if (IsNullableLink(objectType))
                {
                    return(Activator.CreateInstance(
                               typeof(FormLinkNullable <>).MakeGenericType(objectType.GenericTypeArguments[0])));
                }
                else
                {
                    return(Activator.CreateInstance(
                               typeof(FormLink <>).MakeGenericType(objectType.GenericTypeArguments[0]),
                               FormKey.Null));
                }
            }
            else
            {
                var str = obj.ToString();

                if (objectType == typeof(FormKey))
                {
                    if (str.IsNullOrWhitespace())
                    {
                        return(FormKey.Null);
                    }
                    else
                    {
                        return(FormKey.Factory(str));
                    }
                }
                else if (objectType == typeof(FormKey?))
                {
                    if (str.IsNullOrWhitespace())
                    {
                        return(default(FormKey?));
                    }
                    else
                    {
                        return(FormKey.Factory(str));
                    }
                }

                if (!objectType.Name.Contains("FormLink"))
                {
                    throw new ArgumentException();
                }

                FormKey key;
                if (str.IsNullOrWhitespace())
                {
                    key = FormKey.Null;
                }
                else
                {
                    key = FormKey.Factory(str);
                }

                if (IsNullableLink(objectType))
                {
                    return(Activator.CreateInstance(
                               typeof(FormLinkNullable <>).MakeGenericType(objectType.GenericTypeArguments[0]),
                               key));
                }
                else
                {
                    return(Activator.CreateInstance(
                               typeof(FormLink <>).MakeGenericType(objectType.GenericTypeArguments[0]),
                               key));
                }
            }
        }