예제 #1
0
        public override void Write(Vault vault, BinaryWriter bw)
        {
            bw.Write(VLT64Hasher.Hash(Collection.Name));
            bw.Write(VLT64Hasher.Hash(Collection.Class.Name));
            bw.Write(Collection.Parent != null ? VLT64Hasher.Hash(Collection.Parent.Name) : 0L);
            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);
            _srcLayoutPtr = bw.BaseStream.Position;
            bw.Write(0);
            bw.Write(0); // align

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

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

            foreach (var attribEntry in _entries)
            {
                attribEntry.Write(vault, bw);
            }
        }
예제 #2
0
        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(VLT64Hasher.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());
            bw.Write(0); // align
        }
예제 #3
0
 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);
 }
예제 #4
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));
     }
 }
예제 #5
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 <AttribEntry64>();
            _types   = Collection.Class.BaseFields.Select(f => f.TypeName)
                       .Concat(optionalDataColumns.Select(c => Collection.Class[c.Key].TypeName))
                       .Select(s => VLT64Hasher.Hash(s)).Distinct().ToArray();

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

                entry.Key       = VLT64Hasher.Hash(optionalDataColumn.Key);
                entry.TypeIndex = (ushort)Array.IndexOf(_types,
                                                        VLT64Hasher.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);
            }
        }
예제 #6
0
        public override void WritePointerData(Vault vault, BinaryWriter bw)
        {
            _dstDefinitionsPtr = bw.BaseStream.Position;

            foreach (var field in Class.Fields.Values)
            {
                AttribDefinition64 definition = new AttribDefinition64();
                definition.Key       = VLT64Hasher.Hash(field.Name);
                definition.Type      = VLT64Hasher.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);
            }
        }
예제 #7
0
        public override void Write(Vault vault, BinaryWriter bw)
        {
            bw.Write(VLT64Hasher.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);
        }
예제 #8
0
        public override void WritePointerData(Vault vault, BinaryWriter bw)
        {
            _dstDefinitionsPtr = bw.BaseStream.Position;

            foreach (var field in Class.Fields.Values)
            {
                AttribDefinition64 definition = new AttribDefinition64();
                definition.Key       = VLT64Hasher.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      = VLT64Hasher.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);
                    }
                }
            }
        }
예제 #9
0
        public override void Write(Vault vault, BinaryWriter bw)
        {
            bw.Write(VLT64Hasher.Hash(Collection.Name));
            bw.Write(VLT64Hasher.Hash(Collection.Class.Name));
            //bw.Write((uint) (Collection.Parent?.Key ?? 0));
            bw.Write(Collection.Parent != null ? VLT64Hasher.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);
            }
        }
예제 #10
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);
        }
예제 #11
0
 public override ulong GetExportID()
 {
     return(VLT64Hasher.Hash(Class.Name));
 }
예제 #12
0
 public override ulong GetExportID()
 {
     return(VLT64Hasher.Hash($"{Collection.Class.Name}/{Collection.Name}"));
 }