Пример #1
0
        /// <summary>
        /// Saves the bound to a file.
        /// </summary>
        public void Save(string fileName)
        {
            var resource = new ResourceFile_GTA5_pc <Bound>();

            resource.ResourceData = bound;
            resource.Version      = 43;
            resource.Save(fileName);
        }
        public void Save(string fileName)
        {
            var resource = new ResourceFile_GTA5_pc <ParticleEffectsList>();

            resource.ResourceData = particles;
            resource.Version      = 68;
            resource.Save(fileName);
        }
        public void Save(string fileName)
        {
            var resource = new ResourceFile_GTA5_pc <ClipDictionary>();

            resource.ResourceData = clipDictionary;
            resource.Version      = 46;
            resource.Save(fileName);
        }
        public void Save(Stream stream)
        {
            var resource = new ResourceFile_GTA5_pc <GtaDrawableDictionary>();

            resource.ResourceData = drawableDictionary;
            resource.Version      = 165;
            resource.Save(stream);
        }
Пример #5
0
        /// <summary>
        /// Saves the texture dictionary to a file.
        /// </summary>
        public void Save(string fileName)
        {
            var resource = new ResourceFile_GTA5_pc <Drawable_GTA5_pc>();

            resource.ResourceData = drawable;
            resource.Version      = 165;
            resource.Save(fileName);
        }
        public void Save(string fileName)
        {
            var resource = new ResourceFile_GTA5_pc <PgDictionary64 <Expression> >();

            resource.ResourceData = expressionDictionary;
            resource.Version      = 25;
            resource.Save(fileName);
        }
        public void Save(string fileName)
        {
            var resource = new ResourceFile_GTA5_pc <Navigation>();

            resource.ResourceData = navigation;
            resource.Version      = 2;
            resource.Save(fileName);
        }
Пример #8
0
        public void Save(Stream stream)
        {
            var resource = new ResourceFile_GTA5_pc <Bound>();

            resource.ResourceData = bound;
            resource.Version      = 43;
            resource.Save(stream);
        }
        public void Save(string fileName)
        {
            var resource = new ResourceFile_GTA5_pc <PgDictionary64 <CharacterCloth> >();

            resource.ResourceData = clothDictionary;
            resource.Version      = 8;
            resource.Save(fileName);
        }
        public void Save(Stream stream)
        {
            var resource = new ResourceFile_GTA5_pc <Navigation>();

            resource.ResourceData = navigation;
            resource.Version      = 2;
            resource.Save(stream);
        }
        public void Save(string fileName)
        {
            var resource = new ResourceFile_GTA5_pc <PgDictionary64 <Filter> >();

            resource.ResourceData = filterDictionary;
            resource.Version      = 4;
            resource.Save(fileName);
        }
Пример #12
0
        public void Save(string fileName)
        {
            var resource = new ResourceFile_GTA5_pc <NodesFile>();

            resource.ResourceData = nodes;
            resource.Version      = 1;
            resource.Save(fileName);
        }
Пример #13
0
        public void Save(Stream stream)
        {
            var resource = new ResourceFile_GTA5_pc <NodesFile>();

            resource.ResourceData = nodes;
            resource.Version      = 1;
            resource.Save(stream);
        }
        public void Save(string fileName)
        {
            var resource = new ResourceFile_GTA5_pc <PgDictionary64 <GtaDrawable> >();

            resource.ResourceData = drawableDictionary;
            resource.Version      = 165;
            resource.Save(fileName);
        }
        public void Save(Stream stream)
        {
            var resource = new ResourceFile_GTA5_pc <ParticleEffectsList>();

            resource.ResourceData = particles;
            resource.Version      = 68;
            resource.Save(stream);
        }
Пример #16
0
        public void Save(Stream stream)
        {
            var resource = new ResourceFile_GTA5_pc <Drawable_GTA5_pc>();

            resource.ResourceData = drawable;
            resource.Version      = 165;
            resource.Save(stream);
        }
        public void Save(Stream stream)
        {
            var resource = new ResourceFile_GTA5_pc <ClipDictionary>();

            resource.ResourceData = clipDictionary;
            resource.Version      = 46;
            resource.Save(stream);
        }
        public void Save(string fileName)
        {
            var resource = new ResourceFile_GTA5_pc <PgDictionary64 <Bound> >();

            resource.ResourceData = boundDictionary;
            resource.Version      = 43;
            resource.Save(fileName);
        }
Пример #19
0
        public void Write(IMetaValue value, Stream fileStream)
        {
            var resource = new ResourceFile_GTA5_pc <Meta_GTA5_pc>();

            resource.Version      = 2;
            resource.ResourceData = Build(value);
            resource.Save(fileStream);
        }
        public void Save(Stream stream)
        {
            var resource = new ResourceFile_GTA5_pc <PgDictionary64 <Bound> >();

            resource.ResourceData = boundDictionary;
            resource.Version      = 43;
            resource.Save(stream);
        }
Пример #21
0
        public void Save(Stream stream)
        {
            var w = new FragTypeWrapper_GTA5_pc(fragType);

            w.UpdateClass();

            var resource = new ResourceFile_GTA5_pc <FragType_GTA5_pc>();

            resource.ResourceData = fragType;
            resource.Version      = 162;
            resource.Save(stream);
        }
Пример #22
0
        public void Save(Stream stream)
        {
            var w = new TextureDictionaryWrapper_GTA5_pc(textureDictionary);

            w.UpdateClass();

            var resource = new ResourceFile_GTA5_pc <TextureDictionary>();

            resource.ResourceData = textureDictionary;
            resource.Version      = 13;
            resource.Save(stream);
        }
        /// <summary>
        /// Saves the texture dictionary to a file.
        /// </summary>
        public void Save(string fileName)
        {
            var w = new TextureDictionaryWrapper_GTA5_pc(textureDictionary);

            w.UpdateClass();

            var resource = new ResourceFile_GTA5_pc <PgDictionary64 <TextureDX11> >();

            resource.ResourceData = textureDictionary;
            resource.Version      = 13;
            resource.Save(fileName);
        }
Пример #24
0
        private void ConvertToMetaResource()
        {
            string inputFileName  = arguments[0];
            string outputFileName = inputFileName.Replace(".xml", "");

            var xmlDoc = new XmlDocument();

            xmlDoc.Load(inputFileName);

            var res = new ResourceFile_GTA5_pc <MetaFile>();

            res.Version      = 2;
            res.ResourceData = XmlMeta.GetMeta(xmlDoc);

            res.Save(outputFileName);
        }
Пример #25
0
        public void Rebuild(IArchiveResourceFile sourceFile, IArchiveDirectory targetDirectory, RageArchiveEncryption7 encryption)
        {
            try
            {
                var resourceStream = new MemoryStream();
                sourceFile.Export(resourceStream);

                var buffer = new byte[resourceStream.Length];
                resourceStream.Position = 0;
                resourceStream.Read(buffer, 0, (int)resourceStream.Length);
                resourceStream = new MemoryStream(buffer);

                var resource = new ResourceFile_GTA5_pc <T>();
                resourceStream.Position = 0;
                resource.Load(resourceStream);

                if (resource.Version != fileType.Version)
                {
                    throw new Exception("Wrong version");
                }

                var newResourceStream = new MemoryStream();
                resource.Save(newResourceStream);

                buffer = new byte[newResourceStream.Length];
                newResourceStream.Position = 0;
                newResourceStream.Read(buffer, 0, (int)newResourceStream.Length);
                newResourceStream = new MemoryStream(buffer);

                var targetResource = targetDirectory.CreateResourceFile();
                targetResource.Name        = sourceFile.Name;
                newResourceStream.Position = 0;
                targetResource.Import(newResourceStream);

                Console.WriteLine("Rebuilt " + sourceFile.Name);
            }
            catch (Exception ex)
            {
                Console.WriteLine("ERROR in " + sourceFile.Name + ": " + ex.Message);
            }
        }
Пример #26
0
        static void HandleImportMetaOptions(string[] args)
        {
            CommandLine.Parse <ImportMetaOptions>(args, (opts, gOpts) =>
            {
                if (opts.Metadata)
                {
                    Init(args);
                }
                else
                {
                    EnsurePath();
                    EnsureKeys();
                    EnsureCache();
                }

                if (opts.InputFiles == null)
                {
                    Console.WriteLine("Please provide input files with -i --input");
                    return;
                }
                else
                {
                    var inputFiles = Utils.Expand(opts.InputFiles);

                    for (int i = 0; i < inputFiles.Length; i++)
                    {
                        var fileInfo = inputFiles[i];

                        Console.WriteLine(fileInfo.FullName);

                        var strings = MetaUtilities.GetAllStringsFromXml(fileInfo.FullName);

                        foreach (var str in strings)
                        {
                            Utils.Hash(str.ToLowerInvariant());
                        }

                        var doc = new XmlDocument();

                        doc.Load(fileInfo.FullName);

                        var res          = new ResourceFile_GTA5_pc <MetaFile>();
                        res.Version      = 2;
                        res.ResourceData = XmlMeta.GetMeta(doc);

                        if (fileInfo.Name.EndsWith(".ymap.xml") && opts.Metadata)
                        {
                            var toDelete = opts.Delete?.Select(e => Convert.ToUInt32(e)).ToList() ?? new List <uint>();

                            var mappings   = new Dictionary <uint, Dictionary <uint, JObject> >();
                            var basePath   = Path.GetDirectoryName(fileInfo.FullName);
                            var ymaps      = new List <YmapFile>();
                            var ymap       = new YmapFile();
                            var nameHashes = new Dictionary <uint, string>();

                            ymap.ResourceFile = res;

                            ymap.Parse();

                            var topParent     = ImportMeta_GetTopYmapParent((uint)ymap.CMapData.Name);
                            var topParentHash = (uint)topParent["hash"];
                            var topParentName = (string)topParent["name"];
                            var topParentPath = (string)topParent["path"];
                            var topParentYmap = new YmapFile();

                            Console.WriteLine("Top parent is " + topParentName);

                            var entries = new List <JObject>()
                            {
                                topParent
                            };

                            entries.AddRange(ImportMeta_GetYmapChildrens(topParent));

                            for (int j = 0; j < entries.Count; j++)
                            {
                                var entry        = entries[j];
                                var entryHash    = (uint)entry["hash"];
                                var entryName    = (string)entry["name"];
                                var entryPath    = (string)entry["path"];
                                var ymapPath     = basePath + "\\" + entryName + ".ymap";
                                var metadataPath = ymapPath + ".json";

                                nameHashes.Add(entryHash, entryName);

                                if (!File.Exists(ymapPath))
                                {
                                    Console.WriteLine("ERROR => File not found : " + entryName + ".ymap");
                                    return;
                                }

                                if (!File.Exists(metadataPath))
                                {
                                    Console.WriteLine("ERROR => Metadata not found for " + entryName);
                                    return;
                                }

                                var metadataMapping = (JArray)JObject.Parse(File.ReadAllText(metadataPath))["mapping"];
                                var mapping         = new Dictionary <uint, JObject>();

                                for (int k = 0; k < metadataMapping.Count; k++)
                                {
                                    mapping.Add((uint)metadataMapping[k]["guid"], (JObject)metadataMapping[k]);
                                }

                                mappings.Add(entryHash, mapping);

                                if (entryHash == (uint)ymap.CMapData.Name)
                                {
                                    ymaps.Add(ymap);
                                }
                                else
                                {
                                    var ymap2 = new YmapFile();
                                    ymap2.Load(ymapPath);
                                    ymaps.Add(ymap2);
                                }
                            }

                            for (int j = 0; j < ymaps.Count; j++)
                            {
                                var ymap2 = ymaps[j];

                                if (ymap2.CMapData.Parent != 0)
                                {
                                    ymap2.CMapData.ParentMapData = ymaps.Find(e => e.CMapData.Name == ymap2.CMapData.Parent).CMapData;
                                }
                            }

                            bool modified;

                            do
                            {
                                modified = false;

                                for (int j = 0; j < ymaps.Count; j++)
                                {
                                    var ymap2 = ymaps[j];

                                    Console.WriteLine(nameHashes[(uint)ymap2.CMapData.Name]);

                                    var toRemove      = new List <MCEntityDef>();
                                    var toSet         = new List <Tuple <MCEntityDef, MCEntityDef> >();
                                    bool currModified = false;

                                    for (int k = 0; k < ymap2.CMapData.Entities.Count; k++)
                                    {
                                        var entity        = ymap2.CMapData.Entities[k];
                                        var oldHasParent  = (bool)mappings[(uint)ymap2.CMapData.Name][entity.Guid]["hasParent"];
                                        var currHasParent = entity.ParentIndex != -1;

                                        if (oldHasParent)
                                        {
                                            var oldParent         = (uint)mappings[(uint)ymap2.CMapData.Name][entity.Guid]["parent"];
                                            var oldParentYmapName = (string)mappings[(uint)ymap2.CMapData.Name][entity.Guid]["parentYmap"];
                                            var oldParentYmap     = Utils.Hash(oldParentYmapName);

                                            if (currHasParent)
                                            {
                                                if (entity.ParentEntity == null || entity.ParentEntity.Guid != oldParent)
                                                {
                                                    var parentYmap = ymaps.Find(e => (uint)e.CMapData.Name == oldParentYmap);
                                                    var parentIdx  = parentYmap.CMapData.Entities.FindIndex(e => e.Guid == oldParent);

                                                    if (parentIdx == -1)
                                                    {
                                                        Console.WriteLine("DELETE " + entity.Guid + " => Missing parent (" + oldParentYmapName + ")");
                                                        toRemove.Add(entity);
                                                        modified     = true;
                                                        currModified = true;
                                                    }
                                                    else
                                                    {
                                                        Console.WriteLine("ASSIGN parent " + oldParent + " to " + entity.Guid);
                                                        var parent = parentYmap.CMapData.Entities[parentIdx];
                                                        toSet.Add(new Tuple <MCEntityDef, MCEntityDef>(entity, parent));
                                                        modified     = true;
                                                        currModified = true;
                                                    }
                                                }
                                                else
                                                {
                                                    if (toDelete.IndexOf(oldParent) != -1 || (opts.DeleteScope == "full" && toDelete.IndexOf(entity.Guid) != -1))
                                                    {
                                                        Console.WriteLine("DELETE " + entity.Guid + " => Marked for deletion @" + opts.DeleteMode);
                                                        toRemove.Add(entity);
                                                        modified     = true;
                                                        currModified = true;
                                                    }
                                                }
                                            }
                                        }
                                    }

                                    if (opts.DeleteMode == "dummy")
                                    {
                                        for (int k = 0; k < toRemove.Count; k++)
                                        {
                                            toRemove[k].ArchetypeName = Utils.Hash("gtautil_dummy");
                                        }
                                    }
                                    else
                                    {
                                        ymap2.CMapData.RemoveEntities(toRemove);
                                    }

                                    for (int k = 0; k < toSet.Count; k++)
                                    {
                                        toSet[k].Item1.ParentEntity = toSet[k].Item2;
                                    }

                                    if (currModified)
                                    {
                                        Console.WriteLine("MODIFIED");
                                    }
                                }
                            } while (modified && opts.DeleteMode != "dummy");

                            for (int j = 0; j < ymaps.Count; j++)
                            {
                                var ymap2   = ymaps[j];
                                var mapping = new Dictionary <uint, int>();
                                var name    = nameHashes[(uint)ymap2.CMapData.Name];

                                ymap2.Save(basePath + "\\" + name + ".ymap");

                                var data = new JObject
                                {
                                    ["mapping"] = new JArray()
                                };

                                var dataMapping = (JArray)(data["mapping"]);

                                for (int k = 0; k < ymap2.CMapData.Entities.Count; k++)
                                {
                                    var entity = ymap2.CMapData.Entities[k];

                                    if (mapping.ContainsKey(entity.Guid))
                                    {
                                        Console.WriteLine("Duplicate GUID found => " + entity.Guid + " at index " + j + " ABORTING");
                                        return;
                                    }
                                    else
                                    {
                                        mapping.Add(entity.Guid, k);

                                        var entry = new JObject()
                                        {
                                            ["guid"]      = entity.Guid,
                                            ["hasParent"] = entity.ParentIndex != -1,
                                        };

                                        if (entity.ParentIndex != -1)
                                        {
                                            entry["parent"]     = entity.ParentEntity.Guid;
                                            entry["parentName"] = MetaXml.HashString((MetaName)entity.ParentEntity.Guid);
                                            entry["parentYmap"] = nameHashes[(uint)entity.ParentEntity.Parent.Name];
                                        }

                                        dataMapping.Add(entry);
                                    }
                                }

                                var jsonString = JsonConvert.SerializeObject(data, new JsonSerializerSettings()
                                {
                                    Formatting = Newtonsoft.Json.Formatting.Indented
                                });

                                File.WriteAllText(basePath + "\\" + name + ".ymap.json", jsonString);
                            }
                        }
                        else
                        {
                            string fileName = fileInfo.FullName.Replace(".xml", "");
                            res.Save(fileName);
                        }
                    }

                    using (StreamWriter writer = new StreamWriter(AssemblyDirectory + "\\strings.txt"))
                    {
                        foreach (var kvp in Jenkins.Index)
                        {
                            writer.Write(kvp.Value + "\n");
                        }
                    }
                }
            });
        }
Пример #27
0
        static void Main(string[] args)
        {
            EnsurePath();
            EnsureKeys();
            EnsureCache();

            CommandLine.Parse <GenPropDefsOptions>(args, opts =>
            {
                if (opts.InputFiles != null)
                {
                    var inputFiles = Utils.Expand(opts.InputFiles);
                    var ytyp       = new YtypFile();

                    for (int i = 0; i < inputFiles.Length; i++)
                    {
                        var fileInfo = inputFiles[i];

                        string name = "";
                        var split   = fileInfo.Name.Split('.');

                        for (int j = 0; j < split.Length; j++)
                        {
                            if (j < split.Length - 1)
                            {
                                if (j > 0)
                                {
                                    name += ".";
                                }

                                name += split[j];
                            }
                        }

                        Console.WriteLine(name);

                        try
                        {
                            switch (fileInfo.Extension)
                            {
                            case ".ydr":
                                {
                                    var ydr      = new YdrFile();
                                    var arch     = new RageLib.GTA5.ResourceWrappers.PC.Meta.Structures.CBaseArchetypeDef();
                                    var nameHash = (MetaName)Jenkins.Hash(name);

                                    ydr.Load(fileInfo.FullName);

                                    arch.Name              = nameHash;
                                    arch.AssetName         = nameHash;
                                    arch.TextureDictionary = nameHash;
                                    arch.PhysicsDictionary = (MetaName)Jenkins.Hash("prop_" + name);
                                    arch.Flags             = 32;
                                    arch.AssetType         = Unk_1991964615.ASSET_TYPE_DRAWABLE;
                                    arch.BbMin             = (Vector3)(Vector4)ydr.Drawable.BoundingBoxMin;
                                    arch.BbMax             = (Vector3)(Vector4)ydr.Drawable.BoundingBoxMax;
                                    arch.BsCentre          = (Vector3)ydr.Drawable.BoundingCenter;
                                    arch.BsRadius          = ydr.Drawable.BoundingSphereRadius;
                                    arch.LodDist           = 500f;
                                    arch.HdTextureDist     = 5;

                                    ytyp.CMapTypes.Archetypes.Add(arch);

                                    break;
                                }

                            case ".ydd":     // TODO
                                {
                                    break;
                                }

                            default: break;
                            }
                        }
                        catch (Exception e)
                        {
                            Console.Error.WriteLine("ERROR => " + e.Message);
                        }
                    }

                    string path = (opts.Directory == null) ? @".\props.ytyp" : opts.Directory + @"\props.ytyp";

                    ytyp.Save(path);
                }
            });

            CommandLine.Parse <ImportMetaOptions>(args, opts =>
            {
                if (opts.InputFiles != null && opts.Directory != null)
                {
                    var inputFiles = Utils.Expand(opts.InputFiles);

                    for (int i = 0; i < inputFiles.Length; i++)
                    {
                        var fileInfo = inputFiles[i];

                        Console.WriteLine(fileInfo.FullName);

                        var doc = new XmlDocument();

                        doc.Load(fileInfo.FullName);

                        var res          = new ResourceFile_GTA5_pc <MetaFile>();
                        res.Version      = 2;
                        res.ResourceData = XmlMeta.GetMeta(doc);;

                        string fileName = fileInfo.FullName.Replace(".xml", "");

                        res.Save(fileName);
                    }
                }
            });

            CommandLine.Parse <ExportMetaOptions>(args, opts =>
            {
                if (opts.InputFiles != null && opts.Directory != null)
                {
                    var inputFiles = Utils.Expand(opts.InputFiles);

                    for (int i = 0; i < inputFiles.Length; i++)
                    {
                        var fileInfo = inputFiles[i];

                        Console.WriteLine(fileInfo.FullName);

                        var res = new ResourceFile_GTA5_pc <MetaFile>();
                        res.Load(fileInfo.FullName);

                        var xml = MetaXml.GetXml(res.ResourceData);

                        File.WriteAllText(opts.Directory + "\\" + fileInfo.Name + ".xml", xml);
                    }
                }
            });

            CommandLine.Parse <InjectEntitiesOptions>(args, opts =>
            {
                if (opts.Ymap == null)
                {
                    Console.WriteLine("Please provide source ymap file with --ymap");
                    return;
                }

                if (opts.Ytyp == null)
                {
                    Console.WriteLine("Please provide source ytyp file with --ytyp");
                    return;
                }

                if (opts.Room == null)
                {
                    Console.WriteLine("Please provide mlo room name with --room");
                    return;
                }

                if (opts.Position == null || opts.Position.Count() != 3)
                {
                    Console.WriteLine("Please provide a correct position ex: --position 120.5,1370.312,769.2");
                    return;
                }

                if (opts.Rotation == null || opts.Rotation.Count() != 4)
                {
                    Console.WriteLine("Plase provide a correct rotation ex: --rotation 0,0,0,1");
                    return;
                }

                if (opts.Name == null)
                {
                    Console.WriteLine("Plase provide new generated ytyp name with --name");
                    return;
                }

                var position = new Vector3(opts.Position.ElementAt(0), opts.Position.ElementAt(1), opts.Position.ElementAt(2));
                var rotation = new Quaternion(opts.Rotation.ElementAt(0), opts.Rotation.ElementAt(1), opts.Rotation.ElementAt(2), opts.Rotation.ElementAt(3));

                var ymap = new YmapFile();
                var ytyp = new YtypFile();

                ymap.Load(opts.Ymap);
                ytyp.Load(opts.Ytyp);

                RageLib.GTA5.ResourceWrappers.PC.Meta.Structures.CMloArchetypeDef mlo = null;

                for (int i = 0; i < ytyp.CMapTypes.MloArchetypes.Count; i++)
                {
                    mlo = ytyp.CMapTypes.MloArchetypes[i];
                    break;
                }

                if (mlo == null)
                {
                    Console.WriteLine("MLO archetype not found");
                    return;
                }

                RageLib.GTA5.ResourceWrappers.PC.Meta.Structures.CMloRoomDef room = null;

                for (int i = 0; i < mlo.Rooms.Count; i++)
                {
                    if (mlo.Rooms[i].Name == opts.Room)
                    {
                        room = mlo.Rooms[i];
                        break;
                    }
                }

                if (room == null)
                {
                    Console.WriteLine("MLO room not found");
                    return;
                }

                var mloEntities     = new List <RageLib.GTA5.ResourceWrappers.PC.Meta.Structures.CEntityDef>();
                var attachedObjects = new List <uint>();

                mloEntities.AddRange(mlo.Entities);
                attachedObjects.AddRange(room.AttachedObjects);

                for (int i = 0; i < ymap.CMapData.Entities.Count; i++)
                {
                    var entity       = ymap.CMapData.Entities[i];
                    var mloRot       = rotation;
                    var objRot       = new Quaternion(entity.Rotation.X, entity.Rotation.Y, entity.Rotation.Z, entity.Rotation.W);
                    var rotationDiff = objRot * mloRot;                                                                    // Multiply initial entity rotation by mlo rotation

                    entity.Position -= position;                                                                           // Substract mlo world coords from entity world coords
                    entity.Position  = Utils.RotateTransform(Quaternion.Conjugate(mloRot), entity.Position, Vector3.Zero); // Rotate entity around center of mlo instance (mlo entities rotations in space are inverted)
                    entity.Rotation  = new Vector4(rotationDiff.X, rotationDiff.Y, rotationDiff.Z, rotationDiff.W);

                    mloEntities.Add(entity);
                    attachedObjects.Add((uint)mloEntities.IndexOf(entity));
                }

                mlo.Entities         = mloEntities;
                room.AttachedObjects = attachedObjects;

                ytyp.Save(opts.Name.EndsWith(".ytyp") ? opts.Name : opts.Name + ".ytyp");
            });

            CommandLine.Parse <FindOptions>(args, opts =>
            {
                if (opts.Position == null || opts.Position.Count != 3)
                {
                    Console.Error.WriteLine("Please specify position with -p --position");
                    return;
                }

                if (Cache == null)
                {
                    Console.Error.WriteLine("Please build cache first with buildcache");
                    return;
                }

                var c = CultureInfo.InvariantCulture;

                for (int i = 0; i < Cache["ymap"].Count; i++)
                {
                    var cYmap = Cache["ymap"][i];

                    var entitiesExtentsMin = new Vector3((float)cYmap["entitiesExtentsMin"]["x"], (float)cYmap["entitiesExtentsMin"]["y"], (float)cYmap["entitiesExtentsMin"]["z"]);
                    var entitiesExtentsMax = new Vector3((float)cYmap["entitiesExtentsMax"]["x"], (float)cYmap["entitiesExtentsMax"]["y"], (float)cYmap["entitiesExtentsMax"]["z"]);

                    if (
                        opts.Position[0] >= entitiesExtentsMin.X && opts.Position[0] <= entitiesExtentsMax.X &&
                        opts.Position[1] >= entitiesExtentsMin.Y && opts.Position[1] <= entitiesExtentsMax.Y &&
                        opts.Position[2] >= entitiesExtentsMin.Z && opts.Position[2] <= entitiesExtentsMax.Z
                        )
                    {
                        Console.WriteLine("ymap: " + ((string)cYmap["path"]).Split('\\').Last());

                        for (int j = 0; j < cYmap["mloInstances"].Count; j++)
                        {
                            var cMloInstance     = cYmap["mloInstances"][j];
                            var cMloInstanceHash = (uint)cMloInstance["name"];

                            var instancePos = new Vector3((float)cMloInstance["position"]["x"], (float)cMloInstance["position"]["y"], (float)cMloInstance["position"]["z"]);
                            var instanceRot = new Quaternion((float)cMloInstance["rotation"]["x"], (float)cMloInstance["rotation"]["y"], (float)cMloInstance["rotation"]["z"], (float)cMloInstance["rotation"]["w"]);

                            for (int k = 0; k < Cache["ytyp"].Count; k++)
                            {
                                var cYtyp     = Cache["ytyp"][k];
                                var cYtypHash = (uint)cYtyp["hash"];

                                for (int l = 0; l < cYtyp["mloArchetypes"].Count; l++)
                                {
                                    var cMloArch     = cYtyp["mloArchetypes"][l];
                                    var cMloArchHash = (uint)cMloArch["name"];

                                    if (cMloInstanceHash == cMloArchHash)
                                    {
                                        Console.WriteLine("  ytyp => " + ((string)cYtyp["path"]).Split('\\').Last());
                                        Console.WriteLine("    mlo => " + Jenkins.GetString(cMloArchHash));
                                        Console.WriteLine("    position => " + instancePos.X.ToString(c) + "," + instancePos.Y.ToString(c) + "," + instancePos.Z.ToString(c));
                                        Console.WriteLine("    rotation => " + instanceRot.X.ToString(c) + "," + instanceRot.Y.ToString(c) + "," + instanceRot.Z.ToString(c) + "," + instanceRot.W.ToString(c));

                                        for (int m = 0; m < cMloArch["rooms"].Count; m++)
                                        {
                                            var cMloRoom = cMloArch["rooms"][m];

                                            var roomBbMin = new Vector3((float)cMloRoom["bbMin"]["x"], (float)cMloRoom["bbMin"]["y"], (float)cMloRoom["bbMin"]["z"]);
                                            var roomBbMax = new Vector3((float)cMloRoom["bbMax"]["x"], (float)cMloRoom["bbMax"]["y"], (float)cMloRoom["bbMax"]["z"]);

                                            var roomBbMinWorld = instancePos + roomBbMin;
                                            var roomBbMaxWorld = instancePos + roomBbMax;

                                            roomBbMinWorld = Utils.RotateTransform(Quaternion.Conjugate(instanceRot), roomBbMinWorld, Vector3.Zero);
                                            roomBbMaxWorld = Utils.RotateTransform(Quaternion.Conjugate(instanceRot), roomBbMaxWorld, Vector3.Zero);

                                            if (
                                                opts.Position[0] >= roomBbMinWorld.X && opts.Position[0] <= roomBbMaxWorld.X &&
                                                opts.Position[1] >= roomBbMinWorld.Y && opts.Position[1] <= roomBbMaxWorld.Y &&
                                                opts.Position[2] >= roomBbMinWorld.Z && opts.Position[2] <= roomBbMaxWorld.Z
                                                )
                                            {
                                                Console.WriteLine("      room => " + cMloRoom["name"]);
                                            }
                                        }
                                    }
                                }
                            }
                        }

                        Console.WriteLine("");
                    }
                }
            });

            CommandLine.Parse <BuildCacheOptions>(args, opts =>
            {
                dynamic cache = new JObject();

                cache["ymap"] = new JArray();
                cache["ytyp"] = new JArray();

                ArchiveUtilities.ForEachFile(Settings.Default.GTAFolder, (fullFileName, file, encryption) =>
                {
                    Console.WriteLine(fullFileName);

                    string fileNameWithoutExtension = file.Name.Split('.').First();

                    Jenkins.Ensure(fileNameWithoutExtension);

                    if (file.Name.EndsWith(".ymap"))
                    {
                        var ymap = new YmapFile();

                        using (MemoryStream ms = new MemoryStream())
                        {
                            file.Export(ms);
                            ymap.Load(ms);
                        }

                        dynamic entry = new JObject()
                        {
                            ["name"] = fileNameWithoutExtension,
                            ["path"] = fullFileName,
                            ["hash"] = Jenkins.Hash(fileNameWithoutExtension),
                            ["entitiesExtentsMin"] = new JObject()
                            {
                                ["x"] = ymap.CMapData.EntitiesExtentsMin.X,
                                ["y"] = ymap.CMapData.EntitiesExtentsMin.Y,
                                ["z"] = ymap.CMapData.EntitiesExtentsMin.Z,
                            },
                            ["entitiesExtentsMax"] = new JObject()
                            {
                                ["x"] = ymap.CMapData.EntitiesExtentsMax.X,
                                ["y"] = ymap.CMapData.EntitiesExtentsMax.Y,
                                ["z"] = ymap.CMapData.EntitiesExtentsMax.Z,
                            },
                            ["mloInstances"] = new JArray(),
                        };

                        if (ymap.CMapData.MloInstances != null)
                        {
                            for (int i = 0; i < ymap.CMapData.MloInstances.Count; i++)
                            {
                                var mloInstance = ymap.CMapData.MloInstances[i];

                                var mloInstanceEntry = new JObject()
                                {
                                    ["name"]     = ymap.CMapData.MloInstances[i].ArchetypeName,
                                    ["position"] = new JObject()
                                    {
                                        ["x"] = mloInstance.Position.X,
                                        ["y"] = mloInstance.Position.Y,
                                        ["z"] = mloInstance.Position.Z,
                                    },
                                    ["rotation"] = new JObject()
                                    {
                                        ["x"] = mloInstance.Rotation.X,
                                        ["y"] = mloInstance.Rotation.Y,
                                        ["z"] = mloInstance.Rotation.Z,
                                        ["w"] = mloInstance.Rotation.W,
                                    }
                                };

                                entry["mloInstances"].Add(mloInstanceEntry);
                            }
                        }

                        cache["ymap"].Add(entry);
                    }
                    else if (file.Name.EndsWith(".ytyp"))
                    {
                        var ytyp = new YtypFile();

                        using (MemoryStream ms = new MemoryStream())
                        {
                            file.Export(ms);
                            ytyp.Load(ms);
                        }

                        dynamic entry = new JObject()
                        {
                            ["name"]          = fileNameWithoutExtension,
                            ["path"]          = fullFileName,
                            ["hash"]          = Jenkins.Hash(fileNameWithoutExtension),
                            ["mloArchetypes"] = new JArray(),
                        };

                        if (ytyp.CMapTypes.MloArchetypes != null)
                        {
                            for (int i = 0; i < ytyp.CMapTypes.MloArchetypes.Count; i++)
                            {
                                var archetype = ytyp.CMapTypes.MloArchetypes[i];
                                var mloEntry  = new JObject
                                {
                                    ["name"]  = archetype.Name,
                                    ["rooms"] = new JArray(),
                                };

                                if (archetype.Rooms != null)
                                {
                                    for (int j = 0; j < archetype.Rooms.Count; j++)
                                    {
                                        var room      = archetype.Rooms[j];
                                        var roomEntry = new JObject
                                        {
                                            ["name"]  = room.Name,
                                            ["bbMin"] = new JObject()
                                            {
                                                ["x"] = room.BbMin.X,
                                                ["y"] = room.BbMin.Y,
                                                ["z"] = room.BbMin.Z,
                                            },
                                            ["bbMax"] = new JObject()
                                            {
                                                ["x"] = room.BbMax.X,
                                                ["y"] = room.BbMax.Y,
                                                ["z"] = room.BbMax.Z,
                                            }
                                        };

                                        ((JArray)mloEntry["rooms"]).Add(roomEntry);
                                    }
                                }

                                entry["mloArchetypes"].Add(mloEntry);
                            }
                        }

                        cache["ytyp"].Add(entry);
                    }
                });

                var jsonString = JsonConvert.SerializeObject(cache, new JsonSerializerSettings()
                {
                    Formatting = Newtonsoft.Json.Formatting.None
                });

                File.WriteAllText(AssemblyDirectory + "\\cache.json", jsonString);

                using (StreamWriter writer = new StreamWriter(AssemblyDirectory + "\\strings.txt"))
                {
                    foreach (var kvp in Jenkins.Index)
                    {
                        writer.Write(kvp.Value + "\n");
                    }
                }
            });

            if (args.Length == 0 || args[0] == "help")
            {
                Console.Error.Write(CommandLine.GenHelp());
                return;
            }
        }