Example #1
0
        public static List <DinosaurEntry> ExtractDinos(UAssetCacheBlock cache, List <ArkAsset> assets, DeltaExportPatch patch, PropertyReader primalDataReader, Dictionary <string, PropertyReader> dinoEntries)
        {
            //Loop through assets and import them
            List <DinosaurEntry> dinos = new List <DinosaurEntry>();

            foreach (var a in assets)
            {
                //Open file
                UAssetFileBlueprint f;
                try
                {
                    f = UAssetFileBlueprint.OpenFile(a.filename, false, a.name, a.installation.contentFolder);
                } catch (Exception ex)
                {
                    continue;
                }

                //Convert file
                try
                {
                    //Create a dino entry
                    DinosaurEntry entry = ArkDinoEntryConverter.Convert(f, cache, patch, primalDataReader, dinoEntries);
                    dinos.Add(entry);
                } catch (Exception ex)
                {
                    continue;
                }
            }
            return(dinos);
        }
Example #2
0
        public static UAssetFileBlueprint GetFile(UAssetFileBlueprint f, UAssetCacheBlock cache)
        {
            //Search for this by name
            GameObjectTableHead hr          = null;
            UAssetFileBlueprint workingFile = f;

            while (hr == null && workingFile != null)
            {
                //Search
                foreach (var h in workingFile.gameObjectReferences)
                {
                    if (h.name.StartsWith("DinoCharacterStatusComponent_BP_"))
                    {
                        hr = h;
                    }
                }

                //Try to get the parent file
                workingFile = workingFile.GetParentBlueprint(cache);
            }
            if (hr == null)
            {
                throw new Exception("Could not find dino status component!");
            }

            //Open file
            string pathname = f.GetReferencedUAssetPathname(hr);

            return(f.GetReferencedUAssetBlueprintFromPathname(pathname));
        }
Example #3
0
        static void Main(string[] args)
        {
            //UAssetFileBlueprint bp = UAssetFileBlueprint.OpenFile(@"C:\Program Files (x86)\Steam\steamapps\common\ARK\ShooterGame\Content\ScorchedEarth/WeaponPlantSpeciesY/PrimalItemConsumable_Seed_PlantSpeciesY.uasset", true, "PrimalItemConsumable_Seed_PlantSpeciesY", @"C:\Program Files (x86)\Steam\steamapps\common\ARK\ShooterGame\Content\");
            UAssetFileBlueprint bp = UAssetFileBlueprint.OpenFile(@"C:\Program Files (x86)\Steam\steamapps\common\ARK\ShooterGame\Content\PrimalEarth\Dinos\Yutyrannus\Yutyrannus_Character_BP.uasset", true, "Yutyrannus_Character_BP", @"C:\Program Files (x86)\Steam\steamapps\common\ARK\ShooterGame\Content\");

            Console.WriteLine("Done!");
            Console.ReadLine();
        }
Example #4
0
        public static ArkDinoEntry Convert(UAssetFileBlueprint f, UAssetCacheBlock cache, Dictionary <string, PropertyReader> dinoEntries)
        {
            //Open reader
            PropertyReader reader = new PropertyReader(f.GetFullProperties(cache));

            //Get the dino settings
            UAssetFileBlueprint settingsFileAdult = ArkDinoFood.GetAdultFile(f, cache);
            UAssetFileBlueprint settingsFileBaby  = ArkDinoFood.GetBabyFile(f, cache);

            //Get time
            int time = (int)Math.Round((DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0)).TotalSeconds);

            //Get status component
            UAssetFileBlueprint statusComponent = ArkDinoEntryStatus.GetFile(f, cache);
            PropertyReader      statusReader    = new PropertyReader(statusComponent.GetFullProperties(cache));

            //Use name tag to find entry
            string tag = reader.GetPropertyStringOrName("DinoNameTag");

            if (!dinoEntries.ContainsKey(tag))
            {
                throw new Exception($"Could not find dino entry for '{f.classname}' (tag '{tag}')");
            }
            PropertyReader entry = dinoEntries[tag];

            //Now, load the material used for the dino image
            UAssetFileMaterial entryMaterial = entry.GetProperty <ObjectProperty>("DinoMaterial").GetReferencedFileMaterial();

            UAssetFileMaterial.TextureParameterValue entryMaterialTexture = entryMaterial.textureParameters[0];
            ClassnamePathnamePair entryTexture = entryMaterialTexture.prop.GetReferencedFile();

            //Read
            ArkDinoEntry e = new ArkDinoEntry
            {
                screen_name                       = reader.GetPropertyString("DescriptiveName", null),
                colorizationIntensity             = reader.GetPropertyFloat("ColorizationIntensity", 1),
                babyGestationSpeed                = reader.GetPropertyFloat("BabyGestationSpeed", -1),
                extraBabyGestationSpeedMultiplier = reader.GetPropertyFloat("ExtraBabyGestationSpeedMultiplier", -1),
                babyAgeSpeed                      = reader.GetPropertyFloat("BabyAgeSpeed", null),
                extraBabyAgeMultiplier            = reader.GetPropertyFloat("ExtraBabyAgeSpeedMultiplier", -1),
                useBabyGestation                  = reader.GetPropertyBool("bUseBabyGestation", false),
                statusComponent                   = ArkDinoEntryStatus.Convert(statusComponent, statusReader),
                adultFoods    = ArkDinoFood.Convert(settingsFileAdult, cache),
                childFoods    = ArkDinoFood.Convert(settingsFileBaby, cache),
                classname     = f.classname,
                blueprintPath = "N/A",
                captureTime   = time,
                icon          = ImageTool.QueueImage(entryTexture, ImageTool.ImageModifications.None),
                icon_white    = ImageTool.QueueImage(entryTexture, ImageTool.ImageModifications.White)
            };

            //Finally, read stats
            ArkStatsRipper.DoRipStats(statusReader, e);

            return(e);
        }
Example #5
0
 public static ArkDinoEntryStatus Convert(UAssetFileBlueprint f, PropertyReader reader)
 {
     return(new ArkDinoEntryStatus
     {
         baseFoodConsumptionRate = reader.GetPropertyFloat("BaseFoodConsumptionRate", null),
         babyDinoConsumingFoodRateMultiplier = reader.GetPropertyFloat("BabyDinoConsumingFoodRateMultiplier", 25.5f),
         extraBabyDinoConsumingFoodRateMultiplier = reader.GetPropertyFloat("ExtraBabyDinoConsumingFoodRateMultiplier", 20),
         foodConsumptionMultiplier = reader.GetPropertyFloat("FoodConsumptionMultiplier", 1),
         tamedBaseHealthMultiplier = reader.GetPropertyFloat("TamedBaseHealthMultiplier", 1)
     });
 }
Example #6
0
        static void MultipleFileTest()
        {
            //SingleFileTestBlueprint(@"Aberration\Dinos\RockDrake\RockDrake_Character_BP.uasset", "RockDrake_Character_BP");
            //SingleFileTestBlueprint(@"PrimalEarth\Dinos\Argentavis\Argent_Character_BP.uasset", "Argent_Character_BP");
            //SingleFileTestImage(@"PrimalEarth/UI/Empty_SpinoHead_Icon.uasset", "Empty_SpinoHead_Icon");
            //SingleFileTestImage(@"ScorchedEarth\Icons\Dinos\DinoEntryIcon_Camelsaurus.uasset", "DinoEntryIcon_Camelsaurus");

            UAssetFileBlueprint primalGameData       = UAssetFileBlueprint.OpenFile(Program.GAME_ROOT_PATH + @"PrimalEarth\CoreBlueprints\TestGameMode.uasset", false, "TestGameMode", Program.GAME_ROOT_PATH);
            PropertyReader      primalGameDataReader = new PropertyReader(primalGameData.GetFullProperties(new UAssetCacheBlock()));

            List <UProperty> p = primalGameDataReader.props.Where(x => x.name.StartsWith("PerLevelStatsMultiplier_DinoTamed")).ToList();

            Console.WriteLine("Done ALL");
            Console.ReadLine();
        }
Example #7
0
 static void DebugFile(string gameRoot, string package, string classname)
 {
     using (FileStream fs = new FileStream(gameRoot + package, FileMode.Open, FileAccess.Read))
     {
         UAssetFileBlueprint f     = UAssetFileBlueprint.OpenFile(fs, true, classname, gameRoot);
         UAssetCacheBlock    cache = new UAssetCacheBlock();
         List <UProperty>    props = f.GetFullProperties(cache);
         foreach (var p in props)
         {
             Console.WriteLine($"{p.name}, {p.type}, {p.WriteString()}");
         }
     }
     Console.WriteLine("Complete.");
     Console.ReadLine();
 }
Example #8
0
        public static UAssetFileBlueprint GetBabyFile(UAssetFileBlueprint f, UAssetCacheBlock cache)
        {
            //First, try to see if it's a property
            PropertyReader r = new PropertyReader(f.GetFullProperties(cache));
            ObjectProperty p = r.GetProperty <ObjectProperty>("BabyDinoSettings");

            if (p != null)
            {
                //Get file
                return(p.GetReferencedFileBlueprint());
            }

            //Fallback to adult settings
            return(GetAdultFile(f, cache));
        }
        /// <summary>
        /// Extracts data and returns the package
        /// </summary>
        public Stream Run(UAssetCacheBlock cache, out string hash)
        {
            //Get pathnames that match this
            List <ArkAsset>[] files = DiscoveryService.DiscoverFiles(installation, this);

            //Load mod info if this is a mod. TODO

            //Load Primal Data for mod
            string              primalDataPathname = "/Game/PrimalEarth/CoreBlueprints/PrimalGameData_BP";
            ArkAsset            primalDataNs       = ArkAsset.GetAssetFromGame(primalDataPathname, installation);
            UAssetFileBlueprint primalData         = UAssetFileBlueprint.OpenFile(primalDataNs.filename, false, primalDataNs.name, this.installation.contentFolder);
            PropertyReader      primalDataReader   = new PropertyReader(primalData.GetFullProperties(cache));

            //Load all dino entries
            var dinoEntriesArray = primalDataReader.GetProperty <ArrayProperty>("DinoEntries");
            Dictionary <string, PropertyReader> dinoEntries = new Dictionary <string, PropertyReader>(); //Dino entries mapped by tag name

            foreach (var i in dinoEntriesArray.props)
            {
                var    ii  = ((ObjectProperty)i).GetReferencedFileBlueprint();
                var    iir = new PropertyReader(ii.GetFullProperties(cache));
                string tag = iir.GetPropertyStringOrName("DinoNameTag");
                if (!dinoEntries.ContainsKey(tag))
                {
                    dinoEntries.Add(tag, iir);
                }
                else
                {
                    dinoEntries[tag] = iir;
                }
            }

            //Import dinos
            var dinos = DinoExtractorService.ExtractDinos(cache, files[(int)ArkAssetType.Dino], patch, primalDataReader, dinoEntries);

            //Import items
            var items = ItemExtractorService.ExtractItems(cache, files[(int)ArkAssetType.InventoryItem], patch);

            Log.WriteSuccess("Export-Package-Run", $"Package {name}: Processed {dinos.Count} dinos, {items.Count} items");

            //Return the package
            return(CompilePackage(new Dictionary <string, object>
            {
                { "items.bson", items },
                { "dinos.bson", dinos }
            }, out hash));
        }
Example #10
0
        public static void ImportItems(UAssetCacheBlock cache, Dictionary <string, string> map, List <string> readErrors)
        {
            //Find items to import
            List <ArkItemEntry> items = new List <ArkItemEntry>();

            foreach (var mapEntry in map)
            {
                //Check if this is an item
                if (!mapEntry.Key.StartsWith("PrimalItem"))
                {
                    continue;
                }

                //Open
                UAssetFileBlueprint bp;
                try
                {
                    bp = UAssetFileBlueprint.OpenFile(mapEntry.Value, false, mapEntry.Key, Program.GAME_ROOT_PATH);
                } catch (Exception ex)
                {
                    Console.WriteLine($"FAILED TO READ ITEM {mapEntry.Key} with error {ex.Message}");
                    readErrors.Add($"FAILED TO READ ITEM {mapEntry.Key} with error {ex.Message} {ex.StackTrace}");
                    continue;
                }

                //Decode
                try
                {
                    ArkItemEntry entry = ArkItemEntry.ConvertEntry(bp, cache);
                    items.Add(entry);
                } catch (Exception ex)
                {
                    Console.WriteLine("FAILED TO IMPORT ITEM " + bp.classname);
                    readErrors.Add($"FAILED TO IMPORT ITEM {bp.classname} {ex.Message} {ex.StackTrace}");
                    continue;
                }
            }

            //OK
            Console.WriteLine($"Imported {items.Count} items.");

            //Save
            File.WriteAllText(Program.GetOutputDir() + "items.json", JsonConvert.SerializeObject(items, Formatting.Indented));
            Console.WriteLine("Saved.");
        }
Example #11
0
        public static DinosaurEntry Convert(UAssetFileBlueprint f, UAssetCacheBlock cache, DeltaExportPatch patch, PropertyReader primalDataReader, Dictionary <string, PropertyReader> dinoEntries)
        {
            //Open reader
            PropertyReader reader = new PropertyReader(f.GetFullProperties(cache));

            //Get the dino settings
            UAssetFileBlueprint settingsFileAdult = ArkDinoFoodConverter.GetAdultFile(f, cache);
            UAssetFileBlueprint settingsFileBaby  = ArkDinoFoodConverter.GetBabyFile(f, cache);

            //Get status component
            UAssetFileBlueprint statusComponent = ArkDinoEntryStatusConverter.GetFile(f, cache);
            PropertyReader      statusReader    = new PropertyReader(statusComponent.GetFullProperties(cache));

            //Use name tag to find entry
            string         tag   = reader.GetPropertyStringOrName("DinoNameTag");
            PropertyReader entry = dinoEntries[tag];

            //Now, load the material used for the dino image
            UAssetFileMaterial entryMaterial = entry.GetProperty <ObjectProperty>("DinoMaterial").GetReferencedFileMaterial();

            UAssetFileMaterial.TextureParameterValue entryMaterialTexture = entryMaterial.textureParameters[0];
            ClassnamePathnamePair entryTexture = entryMaterialTexture.prop.GetReferencedFile();

            //Read
            DinosaurEntry e = new DinosaurEntry
            {
                screen_name                       = reader.GetPropertyString("DescriptiveName", null),
                colorizationIntensity             = reader.GetPropertyFloat("ColorizationIntensity", 1),
                babyGestationSpeed                = reader.GetPropertyFloat("BabyGestationSpeed", -1),
                extraBabyGestationSpeedMultiplier = reader.GetPropertyFloat("ExtraBabyGestationSpeedMultiplier", -1),
                babyAgeSpeed                      = reader.GetPropertyFloat("BabyAgeSpeed", null),
                extraBabyAgeMultiplier            = reader.GetPropertyFloat("ExtraBabyAgeSpeedMultiplier", -1),
                useBabyGestation                  = reader.GetPropertyBool("bUseBabyGestation", false),
                statusComponent                   = ArkDinoEntryStatusConverter.Convert(statusComponent, statusReader),
                adultFoods = ArkDinoFoodConverter.Convert(settingsFileAdult, cache),
                childFoods = ArkDinoFoodConverter.Convert(settingsFileBaby, cache),
                classname  = DeltaDataExtractor.Program.TrimArkClassname(f.classname),
                icon       = ImageTool.QueueImage(entryTexture, ImageTool.ImageModifications.None, patch),
            };

            //Finally, read stats
            ArkStatsRipper.DoRipStats(statusReader, e);

            return(e);
        }
Example #12
0
        static void SingleFileTestBlueprint(string path, string classname)
        {
            Console.WriteLine("Testing");
            using (FileStream fs = new FileStream(GAME_ROOT_PATH + path, FileMode.Open, FileAccess.Read))
            {
                UAssetFileBlueprint f     = UAssetFileBlueprint.OpenFile(fs, true, classname, GAME_ROOT_PATH);
                UAssetCacheBlock    cache = new UAssetCacheBlock();
                List <UProperty>    props = f.GetFullProperties(cache);
                foreach (var p in props)
                {
                    Console.WriteLine($"{p.name}, {p.type}, {p.WriteString()}");
                }

                //File.WriteAllText("E:\\rockdrake.json", JsonConvert.SerializeObject(props, Formatting.Indented));
                //ArkDinoEntry e = ArkDinoEntry.Convert(f, cache);
            }
            Console.WriteLine("Done");
            Console.ReadLine();
        }
Example #13
0
        public static List <ArkDinoFood> Convert(UAssetFileBlueprint f, UAssetCacheBlock cache)
        {
            //Open reader
            PropertyReader     reader = new PropertyReader(f.GetFullProperties(cache));
            List <ArkDinoFood> output = new List <ArkDinoFood>();

            //Get each
            ArrayProperty mBase  = reader.GetProperty <ArrayProperty>("FoodEffectivenessMultipliers");
            ArrayProperty mExtra = reader.GetProperty <ArrayProperty>("ExtraFoodEffectivenessMultipliers");

            //Convert
            if (mBase != null)
            {
                output.AddRange(ConvertMultiplier(f, cache, mBase));
            }
            if (mExtra != null)
            {
                output.AddRange(ConvertMultiplier(f, cache, mExtra));
            }

            return(output);
        }
Example #14
0
        public static List <ItemEntry> ExtractItems(UAssetCacheBlock cache, List <ArkAsset> assets, DeltaExportPatch patch)
        {
            //Loop through all assets
            List <ItemEntry> items = new List <ItemEntry>();

            foreach (var a in assets)
            {
                //Open
                DateTime            start = DateTime.UtcNow;
                UAssetFileBlueprint bp;
                try
                {
                    bp = UAssetFileBlueprint.OpenFile(a.filename, false, a.name, a.installation.contentFolder);
                }
                catch (Exception ex)
                {
                    Log.WriteError("Item Extractor", "Failed to open file " + a.fullName + ": " + ex.Message + ex.StackTrace);
                    continue;
                }

                //Decode
                try
                {
                    ItemEntry entry = ArkItemEntryReader.ConvertEntry(bp, cache, patch);
                    items.Add(entry);
                    TimeSpan time = DateTime.UtcNow - start;
                    Log.WriteInfo("Item Extractor", "Successfully opened and converted " + a.fullName + " in " + Math.Round(time.TotalMilliseconds) + "ms");
                }
                catch (Exception ex)
                {
                    Log.WriteError("Item Extractor", "Failed to import " + a.fullName + ": " + ex.Message + ex.StackTrace);
                    continue;
                }
            }

            Log.WriteSuccess("Item Extractor", "Extracted " + items.Count + "/" + assets.Count + " items.");
            return(items);
        }
Example #15
0
        public static UAssetFileBlueprint GetAdultFile(UAssetFileBlueprint f, UAssetCacheBlock cache)
        {
            //First, try to see if it's a property
            PropertyReader r = new PropertyReader(f.GetFullProperties(cache));
            ObjectProperty p = r.GetProperty <ObjectProperty>("AdultDinoSettings");

            if (p != null)
            {
                //Get file
                return(p.GetReferencedFileBlueprint());
            }

            //Get the base DinoSettingsClass property
            p = r.GetProperty <ObjectProperty>("DinoSettingsClass");
            if (p != null)
            {
                //Get file
                return(p.GetReferencedFileBlueprint());
            }

            //Throw error
            throw new Exception("Dino settings class was not found.");
        }
Example #16
0
        private static List <ArkDinoFood> ConvertMultiplier(UAssetFileBlueprint f, UAssetCacheBlock cache, ArrayProperty p)
        {
            //Convert each entry
            List <ArkDinoFood> output = new List <ArkDinoFood>();

            foreach (var s in p.props)
            {
                StructProperty      data      = (StructProperty)s;
                PropListStruct      sdata     = (PropListStruct)data.data;
                PropertyReader      reader    = new PropertyReader(sdata.propsList);
                UAssetFileBlueprint foodClass = reader.GetProperty <ObjectProperty>("FoodItemParent").GetReferencedFileBlueprint();
                ArkDinoFood         food      = new ArkDinoFood
                {
                    classname = foodClass.classname,
                    foodEffectivenessMultiplier     = reader.GetPropertyFloat("FoodEffectivenessMultiplier", null),
                    affinityOverride                = reader.GetPropertyFloat("AffinityOverride", null),
                    affinityEffectivenessMultiplier = reader.GetPropertyFloat("AffinityEffectivenessMultiplier", null),
                    foodCategory = reader.GetPropertyInt("FoodItemCategory", null),
                    priority     = reader.GetPropertyFloat("UntamedFoodConsumptionPriority", null)
                };
                output.Add(food);
            }
            return(output);
        }
Example #17
0
        public static ItemEntry ConvertEntry(UAssetFileBlueprint bp, UAssetCacheBlock cache, DeltaExportPatch patch)
        {
            //Open reader
            PropertyReader reader = new PropertyReader(bp.GetFullProperties(cache));

            //Get primary icon
            DeltaAsset icon;

            if (reader.GetProperty <ObjectProperty>("ItemIcon") != null)
            {
                icon = ImageTool.QueueImage(reader.GetProperty <ObjectProperty>("ItemIcon").GetReferencedFile(), ImageTool.ImageModifications.None, patch);
            }
            else
            {
                icon = DeltaAsset.MISSING_ICON;
            }

            //Get broken icon
            DeltaAsset brokenIcon;

            if (reader.GetProperty <ObjectProperty>("BrokenImage") != null)
            {
                brokenIcon = ImageTool.QueueImage(reader.GetProperty <ObjectProperty>("BrokenImage").GetReferencedFile(), ImageTool.ImageModifications.None, patch);
            }
            else
            {
                brokenIcon = DeltaAsset.MISSING_ICON;
            }

            //Get the array of UseItemAddCharacterStatusValues
            ArrayProperty statusValuesArray = reader.GetProperty <ArrayProperty>("UseItemAddCharacterStatusValues");
            Dictionary <string, ItemEntry_ConsumableAddStatusValue> statusValues = new Dictionary <string, ItemEntry_ConsumableAddStatusValue>();

            if (statusValuesArray != null)
            {
                foreach (var i in statusValuesArray.props)
                {
                    StructProperty sv   = (StructProperty)i;
                    var            svp  = ((PropListStruct)sv.data).propsList;
                    var            svpr = new PropertyReader(svp);
                    string         type = svpr.GetProperty <ByteProperty>("StatusValueType").enumValue;
                    ItemEntry_ConsumableAddStatusValue sve = ArkItemEntry_ConsumableAddStatusValueReader.Convert(svpr, type);
                    statusValues.Add(type, sve);
                }
            }

            //Create
            ItemEntry e = new ItemEntry
            {
                hideFromInventoryDisplay = reader.GetPropertyBool("bHideFromInventoryDisplay", false),
                useItemDurability        = reader.GetPropertyBool("bUseItemDurability", false),
                isTekItem           = reader.GetPropertyBool("bTekItem", false),
                allowUseWhileRiding = reader.GetPropertyBool("bAllowUseWhileRiding", false),
                name            = reader.GetPropertyString("DescriptiveNameBase", null),
                description     = reader.GetPropertyString("ItemDescription", null),
                spoilingTime    = reader.GetPropertyFloat("SpolingTime", 0),
                baseItemWeight  = reader.GetPropertyFloat("BaseItemWeight", 0),
                useCooldownTime = reader.GetPropertyFloat("MinimumUseInterval", 0),
                baseCraftingXP  = reader.GetPropertyFloat("BaseCraftingXP", 0),
                baseRepairingXP = reader.GetPropertyFloat("BaseRepairingXP", 0),
                maxItemQuantity = reader.GetPropertyInt("MaxItemQuantity", 0),
                classname       = DeltaDataExtractor.Program.TrimArkClassname(bp.classname),
                icon            = icon,
                broken_icon     = brokenIcon,
                addStatusValues = statusValues
            };

            return(e);
        }
Example #18
0
        public static void ImportDinos(UAssetCacheBlock cache, Dictionary <string, string> map, List <string> readErrors)
        {
            //Open PrimalGameData
            Console.WriteLine("Opening PrimalGameData...");
            UAssetFileBlueprint primalGameData       = UAssetFileBlueprint.OpenFile(Program.GAME_ROOT_PATH + @"PrimalEarth\CoreBlueprints\PrimalGameData_BP.uasset", false, "PrimalGameData_BP", Program.GAME_ROOT_PATH);
            PropertyReader      primalGameDataReader = new PropertyReader(primalGameData.GetFullProperties(cache));

            Console.WriteLine("PrimalGameData opened.");

            //Now, open all dino entries
            Console.WriteLine("Opening dino entries...");
            Dictionary <string, PropertyReader> dinoEntries = new Dictionary <string, PropertyReader>();
            ArrayProperty entriesArray = primalGameDataReader.GetProperty <ArrayProperty>("DinoEntries");
            int           entriesCount = 0;

            foreach (var en in entriesArray.props)
            {
                //Open
                UAssetFileBlueprint bp       = ((ObjectProperty)en).GetReferencedFileBlueprint();
                PropertyReader      bpReader = new PropertyReader(bp.GetFullProperties(cache));
                string name = bpReader.GetPropertyStringOrName("DinoNameTag");
                if (dinoEntries.ContainsKey(name))
                {
                    dinoEntries.Remove(name);
                }
                dinoEntries.Add(name, bpReader);
                entriesCount++;
            }
            Console.WriteLine($"Finished opening dino entries. Found {entriesCount} entries.");

            //Now, open binder
            ClassListBinder binder = ClassListBinder.OpenBinder("classes.json");

            //Find base dino
            ClassListEntry dinoBase = binder.ClassData.SearchForClass("Dino_Character_BP");

            if (dinoBase == null)
            {
                throw new Exception("Failed to find dino base class.");
            }

            //Get children
            List <ClassListEntry> dinoClasses = dinoBase.GetAllChildren();

            Console.WriteLine($"Found {dinoClasses.Count} dino classes to import.");

            //Loop classes and start reading
            List <ArkDinoEntry> dinos = new List <ArkDinoEntry>();

            foreach (ClassListEntry e in dinoClasses)
            {
                try
                {
                    //Find this dino file in the map
                    if (!map.ContainsKey(e.Name))
                    {
                        throw new Exception($"Failed to find dino {e.Name} in uasset map.");
                    }
                    string pathname = map[e.Name];

                    //Now, open the UASSET file
                    UAssetFileBlueprint f = UAssetFileBlueprint.OpenFile(pathname, false, e.Name, Program.GAME_ROOT_PATH);

                    //Create a dino entry
                    ArkDinoEntry entry = ArkDinoEntry.Convert(f, cache, dinoEntries);
                    dinos.Add(entry);
                } catch (Exception ex)
                {
                    Console.ForegroundColor = ConsoleColor.Red;
                    Console.WriteLine($"Failed to import dino {e.Name} with error {ex.Message}!");
                    readErrors.Add($"Failed to import dino {e.Name} with error {ex.Message}{ex.StackTrace}!");
                    Console.ForegroundColor = ConsoleColor.White;
                }
            }

            //Now, save
            Console.WriteLine($"Finished reading {dinos.Count}/{dinoClasses.Count} dinos. Saving now...");
            File.WriteAllText(Program.GetOutputDir() + "dinos.json", JsonConvert.SerializeObject(dinos, Formatting.Indented));

            Console.WriteLine("Done importing dinos.");
        }