コード例 #1
0
ファイル: ClassLoad.cs プロジェクト: funk-yourself/VaultLib
        public override void Write(Vault vault, BinaryWriter bw)
        {
            int collectionReserve = (from collection in vault.SaveContext.Collections
                                     where collection.Class.Name == Class.Name
                                     select collection).Count();

            bw.Write(VLT32Hasher.Hash(Class.Name));
            bw.Write(collectionReserve);
            bw.Write(Class.Fields.Count);
            _srcDefinitionsPtr = bw.BaseStream.Position;
            bw.Write(0);
            int staticSize = ComputeStaticSize();

            bw.Write(staticSize);

            if (staticSize > 0)
            {
                _srcStaticPtr = bw.BaseStream.Position;
            }

            bw.Write(0);

            bw.Write(ComputeBaseSize());
            bw.Write((ushort)0);
            bw.Write((ushort)Class.BaseFields.Count());
        }
コード例 #2
0
        public override void Write(Vault vault, BinaryWriter bw)
        {
            bw.Write(VLT32Hasher.Hash(Collection.Name));
            bw.Write(VLT32Hasher.Hash(Collection.Class.Name));
            bw.Write(Collection.Parent != null ? VLT32Hasher.Hash(Collection.Parent.Name) : 0u);
            bw.Write(Entries.Count);
            bw.Write(0);
            bw.Write(Entries.Count);

            ushort numTypes = (ushort)Types.Length;
            ushort typesLen = (ushort)(numTypes % 2 == 0 ? numTypes : numTypes + 1);

            bw.Write(numTypes);
            bw.Write(typesLen);
            SourceLayoutPointer = bw.BaseStream.Position;
            bw.Write(0);

            foreach (var type in Types)
            {
                bw.Write(type);
            }

            if (typesLen != numTypes)
            {
                bw.Write(0);
            }

            foreach (var attribEntry in Entries)
            {
                attribEntry.Write(vault, bw);
            }
        }
コード例 #3
0
        public static object DoPrimitiveConversion(object value, string str)
        {
            if (value == null)
            {
                // we don't know the type, just assume we need a string
                return(str);
            }

            Type type = value.GetType();

            if (type == typeof(uint))
            {
                if (str.StartsWith("0x"))
                {
                    return(uint.Parse(str.Substring(2), NumberStyles.AllowHexSpecifier));
                }
                if (!uint.TryParse(str, out _))
                {
                    return(VLT32Hasher.Hash(str));
                }
            }
            else if (type == typeof(int))
            {
                if (str.StartsWith("0x"))
                {
                    return(int.Parse(str.Substring(2), NumberStyles.AllowHexSpecifier));
                }
                if (!uint.TryParse(str, out _))
                {
                    return(unchecked ((int)VLT32Hasher.Hash(str)));
                }
            }

            return(type.IsEnum ? Enum.Parse(type, str) : Convert.ChangeType(str, type, CultureInfo.InvariantCulture));
        }
コード例 #4
0
ファイル: StringKey64.cs プロジェクト: funk-yourself/VaultLib
 public override void Write(Vault vault, BinaryWriter bw)
 {
     _text       = new Text(Class, Field, Collection);
     _text.Value = Value;
     bw.Write(string.IsNullOrEmpty(Value) ? 0L : VLT64Hasher.Hash(Value));
     bw.Write(string.IsNullOrEmpty(Value) ? 0 : VLT32Hasher.Hash(Value));
     _text.Write(vault, bw);
 }
コード例 #5
0
 public override void Write(Vault vault, BinaryWriter bw)
 {
     _keyString = new Text(Class, Field, Collection)
     {
         Value = KeyString
     };
     _keyString.Write(vault, bw);
     bw.Write(string.IsNullOrEmpty(KeyString) ? 0 : VLT32Hasher.Hash(KeyString));
     bw.Write(Value);
 }
コード例 #6
0
 public override void Write(Vault vault, BinaryWriter bw)
 {
     if (vault.Database.Options.Type == DatabaseType.X86Database)
     {
         bw.Write(VLT32Hasher.Hash(CollectionKey));
     }
     else
     {
         bw.Write(VLT64Hasher.Hash(CollectionKey));
     }
 }
コード例 #7
0
 public override void Write(Vault vault, BinaryWriter bw)
 {
     _copType = new Text(Class, Field, Collection)
     {
         Value = CopType
     };
     _copType.Write(vault, bw);
     bw.Write(string.IsNullOrEmpty(CopType) ? 0 : VLT32Hasher.Hash(CopType));
     bw.Write(Count);
     bw.Write(Chance);
 }
コード例 #8
0
        public override void Prepare(Vault vault)
        {
            List <KeyValuePair <string, VLTBaseType> > optionalDataColumns = (from pair in Collection.GetData()
                                                                              let field = Collection.Class[pair.Key]
                                                                                          where !field.IsInLayout
                                                                                          orderby field.Name
                                                                                          select pair).ToList();

            Entries = new List <AttribEntry>();
            Types   = Collection.Class.BaseFields.Select(f => f.TypeName)
                      .Concat(optionalDataColumns.Select(c => Collection.Class[c.Key].TypeName))
                      .Select(s => VLT32Hasher.Hash(s)).Distinct().ToArray();

            for (var index = 0; index < optionalDataColumns.Count; index++)
            {
                var optionalDataColumn = optionalDataColumns[index];
                var entry         = new AttribEntry(Collection);
                var vltClassField = Collection.Class[optionalDataColumn.Key];

                entry.Key       = VLT32Hasher.Hash(optionalDataColumn.Key);
                entry.TypeIndex = (ushort)Array.IndexOf(Types,
                                                        VLT32Hasher.Hash(vltClassField.TypeName));
                entry.EntryFlags = 0;
                entry.NodeFlags  = NodeFlagsEnum.Default;

                if (entry.IsInline())
                {
                    entry.InlineData = optionalDataColumn.Value;
                    entry.NodeFlags |= NodeFlagsEnum.IsInline;
                }
                else
                {
                    entry.InlineData =
                        new VLTAttribType(Collection.Class, vltClassField, Collection)
                    {
                        Data = optionalDataColumn.Value
                    };
                }

                if (vltClassField.IsArray)
                {
                    entry.NodeFlags |= NodeFlagsEnum.IsArray;
                }

                if ((vltClassField.Flags & DefinitionFlags.HasHandler) != 0)
                {
                    entry.NodeFlags |= NodeFlagsEnum.HasHandler;
                }

                Entries.Add(entry);
            }
        }
コード例 #9
0
 public override void Write(Vault vault, BinaryWriter bw)
 {
     if (string.IsNullOrEmpty(KitName))
     {
         bw.Write(0);
     }
     else
     {
         bw.Write(VLT32Hasher.Hash(KitName));
     }
     _kitName = new Text(Class, Field, Collection)
     {
         Value = KitName
     };
     _kitName.Write(vault, bw);
     bw.Write(Offset);
 }
コード例 #10
0
ファイル: ClassLoad.cs プロジェクト: funk-yourself/VaultLib
        public override void WritePointerData(Vault vault, BinaryWriter bw)
        {
            _dstDefinitionsPtr = bw.BaseStream.Position;

            foreach (var field in Class.Fields.Values)
            {
                AttribDefinition definition = new AttribDefinition();
                definition.Key       = VLT32Hasher.Hash(field.Name);
                definition.Type      = VLT32Hasher.Hash(field.TypeName);
                definition.Flags     = field.Flags;
                definition.Size      = field.Size;
                definition.MaxCount  = field.MaxCount;
                definition.Offset    = field.Offset;
                definition.Alignment = field.Alignment;

                definition.Write(vault, bw);
            }
        }
コード例 #11
0
        private void UpdateClasses()
        {
            IEnumerable <WORLD_gameplay> carClassCollections =
                from collection in _attribService.FindCollections("gameplay/baseelement/serveritems/car_class/.*")
                let w = new WORLD_gameplay(collection)
                        where w.HasField(WORLD_gameplay.Name_FEIconLocked)
                        select w;

            foreach (var collection in carClassCollections)
            {
                int hash = unchecked ((int)VLT32Hasher.Hash(collection.Name()));

                _classes.Add(new CarClass
                {
                    CarClassHash = hash,
                    MinRating    = collection.CarClassMinRating(),
                    MaxRating    = collection.CarClassMaxRating()
                });
            }
        }
コード例 #12
0
ファイル: ClassLoad.cs プロジェクト: funk-yourself/VaultLib
        public override void Write(Vault vault, BinaryWriter bw)
        {
            bw.Write(VLT32Hasher.Hash(Class.Name));

            int collReserve = (from collection in vault.Database.RowManager.GetFlattenedCollections(Class.Name)
                               select collection).Count();

            if (collReserve == 0)
            {
                throw new InvalidDataException("Cannot serialize legacy ClassLoadData when mCollectionReserve is 0.");
            }

            bw.Write(collReserve);
            bw.Write(Class.Fields.Count);
            _srcDefinitionsPtr = bw.BaseStream.Position;
            bw.Write(0);
            bw.Write(ComputeBaseSize());
            bw.Write(0);
            bw.Write((ushort)Class.BaseFields.Count());
            bw.Write((ushort)0);
        }
コード例 #13
0
        public override void Execute(ModScriptDatabaseHelper database)
        {
            VltCollection collection = GetCollection(database, ClassName, CollectionName);

            if (collection.HasEntry(FieldName))
            {
                collection.RemoveValue(FieldName);
            }
            else
            {
                string hashed = $"0x{VLT32Hasher.Hash(FieldName):X8}";

                if (collection.HasEntry(hashed))
                {
                    collection.RemoveValue(hashed);
                }
                else
                {
                    throw new ModScriptCommandExecutionException($"Could not delete field: {ClassName}/{CollectionName}[{FieldName}]");
                }
            }
        }
コード例 #14
0
ファイル: ClassLoad.cs プロジェクト: funk-yourself/VaultLib
        public override void WritePointerData(Vault vault, BinaryWriter bw)
        {
            _dstDefinitionsPtr = bw.BaseStream.Position;

            foreach (var field in Class.Fields.Values)
            {
                AttribDefinition definition = new AttribDefinition();
                definition.Key       = VLT32Hasher.Hash(field.Name);
                definition.Alignment = field.Alignment;
                definition.Flags     = field.Flags;
                definition.MaxCount  = field.MaxCount;
                definition.Offset    = field.Offset;
                definition.Size      = field.Size;
                definition.Type      = VLT32Hasher.Hash(field.TypeName);
                definition.Write(vault, bw);
            }

            if (_srcStaticPtr != 0)
            {
                bw.AlignWriter(0x10);

                _dstStaticPtr = bw.BaseStream.Position;

                foreach (var staticField in Class.StaticFields)
                {
                    bw.AlignWriter(staticField.Alignment);
                    staticField.StaticValue.Write(vault, bw);
                }

                foreach (var staticField in Class.StaticFields)
                {
                    if (staticField.StaticValue is IPointerObject pointerObject)
                    {
                        pointerObject.WritePointerData(vault, bw);
                    }
                }
            }
        }
コード例 #15
0
        public override void Write(Vault vault, BinaryWriter bw)
        {
            bw.Write(VLT32Hasher.Hash(Collection.Name));
            bw.Write(VLT32Hasher.Hash(Collection.Class.Name));
            //bw.Write((uint) (Collection.Parent?.Key ?? 0));
            bw.Write(Collection.Parent != null ? VLT32Hasher.Hash(Collection.Parent.Name) : 0u);
            bw.Write((uint)_entries.Length);
            bw.Write(0);
            bw.Write((uint)_entries.Length);
            bw.Write((uint)_types.Length);
            _srcLayoutPtr = bw.BaseStream.Position;
            bw.Write(0);

            foreach (var type in _types)
            {
                bw.Write(type);
            }

            foreach (var entry in _entries)
            {
                entry.Write(vault, bw);
            }
        }
コード例 #16
0
        public override void Write(Vault vault, BinaryWriter bw)
        {
            ElementsPointer = 0;
            TreePointer     = 0;
            EndPointer      = 0;

            // Obtain the full list of collections
            List <VltCollection>             allCollections = vault.SaveContext.Collections.Where(c => c.Class.Name == Class.Name).ToList();
            Dictionary <VltCollection, uint> keys           = allCollections.ToDictionary(c => c, c => VLT32Hasher.Hash(c.Name));

            // Group list by parent
            Dictionary <uint, List <VltCollection> > groupedByParent = allCollections.GroupBy(c => c.Parent != null ? keys[c.Parent] : 0)
                                                                       .ToDictionary(g => g.Key, g => g.ToList());


            // Filter list to collections with children
            List <VltCollection> withChildren = allCollections.Where(c => groupedByParent.ContainsKey(keys[c])).OrderBy(c => keys[c]).ToList();

            // Get list of top-level (no parent) collections
            List <VltCollection> topLevel = allCollections.Where(c => c.Parent == null).ToList();

            List <uint> arrayElements = new List <uint>
            {
                0 // 0 represents the class root
            };

            // Collections with children are in the array and tree
            foreach (VltCollection c in withChildren)
            {
                arrayElements.Add(keys[c]);
            }

            Dictionary <int, int> tree = new Dictionary <int, int>
            {
                { 0, topLevel.Count } // class root
            };

            int treeIdx = topLevel.Count;
            int arrIdx  = 1;

            for (; arrIdx < arrayElements.Count; arrIdx++)
            {
                tree.Add(treeIdx, groupedByParent[arrayElements[arrIdx]].Count);

                treeIdx += tree[treeIdx];
            }

            Debug.Assert(tree.Count == arrayElements.Count);

            bw.Write(arrayElements.Count);
            ElementsPointer = bw.WritePointer();
            TreePointer     = bw.WritePointer();
            EndPointer      = bw.WritePointer();

            ElementsDest = bw.BaseStream.Position;

            foreach (uint arrayElement in arrayElements)
            {
                bw.Write(arrayElement);
            }

            TreeDest = bw.BaseStream.Position;

            foreach (KeyValuePair <int, int> i in tree)
            {
                bw.Write(i.Key);
                bw.Write(i.Value);
            }

            EndDest = bw.BaseStream.Position;
        }
コード例 #17
0
 public override ulong GetExportID()
 {
     return(VLT32Hasher.Hash($"{Collection.Class.Name}/{Collection.Name}"));
 }
コード例 #18
0
        /// <summary>
        /// Deserializes the files.
        /// </summary>
        public LoadedDatabase Deserialize()
        {
            var deserializer = new DeserializerBuilder().Build();

            using var dbs = new StreamReader(Path.Combine(_inputDirectory, "info.yml"));
            var loadedDatabase = deserializer.Deserialize <LoadedDatabase>(dbs);
            var isX86          = _database.Options.Type == DatabaseType.X86Database;

            foreach (var loadedDatabaseClass in loadedDatabase.Classes)
            {
                var vltClass = new VltClass(loadedDatabaseClass.Name);

                foreach (var loadedDatabaseClassField in loadedDatabaseClass.Fields)
                {
                    var field = new VltClassField(
                        isX86 ? VLT32Hasher.Hash(loadedDatabaseClassField.Name) : VLT64Hasher.Hash(loadedDatabaseClassField.Name),
                        loadedDatabaseClassField.Name,
                        loadedDatabaseClassField.TypeName,
                        loadedDatabaseClassField.Flags,
                        loadedDatabaseClassField.Alignment,
                        loadedDatabaseClassField.Size,
                        loadedDatabaseClassField.MaxCount,
                        loadedDatabaseClassField.Offset);
                    // Handle static value
                    if (loadedDatabaseClassField.StaticValue != null)
                    {
                        field.StaticValue = ConvertSerializedValueToDataValue(_database.Options.GameId, _inputDirectory, vltClass, field, null,
                                                                              loadedDatabaseClassField.StaticValue);
                    }

                    vltClass.Fields.Add(field.Key, field);
                }

                _database.AddClass(vltClass);
            }

            foreach (var loadedDatabaseType in loadedDatabase.Types)
            {
                _database.Types.Add(new DatabaseTypeInfo {
                    Name = loadedDatabaseType.Name, Size = loadedDatabaseType.Size
                });
            }

            var collectionParentDictionary = new Dictionary <string, string>();
            var collectionDictionary       = new Dictionary <string, VltCollection>();
            var vaultsToSaveDictionary     = new Dictionary <string, List <Vault> >();
            var collectionsToBeAdded       = new List <VltCollection>();

            foreach (var file in loadedDatabase.Files)
            {
                file.LoadedVaults = new List <Vault>();

                var baseDirectory = Path.Combine(_inputDirectory, file.Group, file.Name);
                vaultsToSaveDictionary[file.Name] = new List <Vault>();
                foreach (var vault in file.Vaults)
                {
                    var vaultDirectory = Path.Combine(baseDirectory, vault).Trim();
                    var newVault       = new Vault(vault)
                    {
                        Database = _database, IsPrimaryVault = vault == "db"
                    };
                    if (Directory.Exists(vaultDirectory))
                    {
                        HashSet <string> trackedCollections = new HashSet <string>();

                        foreach (var dataFile in Directory.GetFiles(vaultDirectory, "*.yml"))
                        {
                            var className = Path.GetFileNameWithoutExtension(dataFile);
                            var vltClass  = _database.FindClass(className);

                            if (vltClass == null)
                            {
                                throw new InvalidDataException($"Unknown class: {className} ({dataFile})");
                            }

                            //#if DEBUG
                            //                        Debug.WriteLine("Processing class '{0}' in vault '{1}' (file: {2})", className, vault, dataFile);
                            //#else
                            //                        Console.WriteLine("Processing class '{0}' in vault '{1}' (file: {2})", className, vault, dataFile);
                            //#endif

                            using var vr = new StreamReader(dataFile);
                            var collections = deserializer.Deserialize <List <LoadedCollection> >(vr);

                            foreach (var loadedCollection in collections)
                            {
                                // BUG 16.02.2020: we have to do this to get around a YamlDotNet bug
                                if (loadedCollection.Name == null)
                                {
                                    loadedCollection.Name = "null";
                                }

                                foreach (var k in loadedCollection.Data.Keys.ToList().Where(k => loadedCollection.Data[k] == null))
                                {
                                    loadedCollection.Data[k] = "null";
                                }
                            }

                            var newCollections = new List <VltCollection>();

                            void AddCollectionsToList(ICollection <VltCollection> collectionList,
                                                      IEnumerable <LoadedCollection> collectionsToAdd)
                            {
                                if (collectionList == null)
                                {
                                    throw new Exception("collectionList should not be null!");
                                }
                                collectionsToAdd ??= new List <LoadedCollection>();

                                foreach (var loadedCollection in collectionsToAdd)
                                {
                                    var newVltCollection = new VltCollection(newVault, vltClass, loadedCollection.Name);

                                    foreach (var(key, value) in loadedCollection.Data)
                                    {
                                        newVltCollection.SetRawValue(key,
                                                                     ConvertSerializedValueToDataValue(_database.Options.GameId, vaultDirectory, vltClass, vltClass[key],
                                                                                                       newVltCollection, value));
                                    }

                                    collectionParentDictionary[newVltCollection.ShortPath] = loadedCollection.ParentName;
                                    collectionList.Add(newVltCollection);
                                    collectionDictionary[newVltCollection.ShortPath] = newVltCollection;
                                }
                            }

                            AddCollectionsToList(newCollections, collections);


                            foreach (var newCollection in newCollections)
                            {
                                if (!trackedCollections.Add(newCollection.ShortPath))
                                {
                                    throw new SerializedDatabaseLoaderException($"Duplicate collection found! Multiple collections at '{newCollection.ShortPath}' have been defined in your YML files.");
                                }

                                collectionsToBeAdded.Add(newCollection);
                            }
                        }
                    }
                    else
                    {
                        Console.WriteLine("WARN: vault {0} has no folder; looked for {1}", vault, vaultDirectory);
                    }

                    vaultsToSaveDictionary[file.Name].Add(newVault);
                    _database.Vaults.Add(newVault);

                    file.LoadedVaults.Add(newVault);
                }
            }

            // dependency resolution
            var resolved   = new List <VaultDependencyNode>();
            var unresolved = new List <VaultDependencyNode>();

            foreach (var vault in _database.Vaults)
            {
                var vaultCollections     = collectionsToBeAdded.Where(c => c.Vault.Name == vault.Name).ToList();
                VaultDependencyNode node = new VaultDependencyNode(vault);

                foreach (var vaultCollection in vaultCollections)
                {
                    string parentKey = collectionParentDictionary[vaultCollection.ShortPath];

                    if (!string.IsNullOrEmpty(parentKey))
                    {
                        var parentCollection = collectionDictionary[$"{vaultCollection.Class.Name}/{parentKey}"];
                        if (parentCollection.Vault.Name != vault.Name)
                        {
                            node.AddEdge(new VaultDependencyNode(parentCollection.Vault));
                        }
                    }
                }

                ResolveDependencies(node, resolved, unresolved);

                Debug.WriteLine("Vault {0}: {1} collections", vault.Name, vaultCollections.Count);
            }

            resolved   = resolved.Distinct(VaultDependencyNode.VaultComparer).ToList();
            unresolved = unresolved.Distinct(VaultDependencyNode.VaultComparer).ToList();

            if (unresolved.Count != 0)
            {
                throw new SerializedDatabaseLoaderException("Cannot continue loading - unresolved vault dependencies");
            }

            foreach (var node in resolved)
            {
                var vault            = node.Vault;
                var vaultCollections = collectionsToBeAdded.Where(c => c.Vault.Name == vault.Name).ToList();

                Debug.WriteLine("Loading collections for vault {0} ({1})", vault.Name, vaultCollections.Count);

                foreach (var collection in vaultCollections)
                {
                    string parentKey = collectionParentDictionary[collection.ShortPath];

                    if (string.IsNullOrEmpty(parentKey))
                    {
                        // Add collection directly
                        _database.RowManager.AddCollection(collection);
                    }
                    else
                    {
                        var parentCollection = collectionDictionary[$"{collection.Class.Name}/{parentKey}"];
                        parentCollection.AddChild(collection);
                    }
                }
            }

            _loadedDatabase = loadedDatabase;

            return(loadedDatabase);
        }