private void extractBinaryObjectCryopods(ReadingOptions options) { if (!options.CryopodCreatures) { return; } // Parse creatures in cryopods and soultraps (from the mod DinoStorageV2) var cryopods = Objects.Where(x => x.ClassString.Contains("Cryop") || x.ClassString.Contains("SoulTrap_")).ToArray(); foreach (var cryo in cryopods) { ArkArrayStruct customItemDatas = cryo.GetPropertyValue <IArkArray, ArkArrayStruct>("CustomItemDatas"); StructPropertyList customDinoData = (StructPropertyList)customItemDatas?.FirstOrDefault(cd => ((StructPropertyList)cd).GetTypedProperty <PropertyName>("CustomDataName").Value.Name == "Dino"); PropertyStruct customDataBytes = customDinoData?.Properties.FirstOrDefault(p => p.NameString == "CustomDataBytes") as PropertyStruct; PropertyArray byteArrays = (customDataBytes?.Value as StructPropertyList)?.Properties.FirstOrDefault(property => property.NameString == "ByteArrays") as PropertyArray; ArkArrayStruct byteArraysValue = byteArrays?.Value as ArkArrayStruct; if (!(byteArraysValue?.Any() ?? false)) { continue; } ArkArrayUInt8 creatureBytes = ((byteArraysValue[0] as StructPropertyList)?.Properties.FirstOrDefault(p => p.NameString == "Bytes") as PropertyArray)?.Value as ArkArrayUInt8; if (creatureBytes == null) { continue; } var cryoStream = new System.IO.MemoryStream(creatureBytes.ToArray <byte>()); using (ArkArchive cryoArchive = new ArkArchive(cryoStream)) { // number of serialized objects int objCount = cryoArchive.ReadInt(); if (objCount == 0) { continue; } var storedGameObjects = new List <GameObject>(objCount); for (int oi = 0; oi < objCount; oi++) { storedGameObjects.Add(new GameObject(cryoArchive)); } foreach (var ob in storedGameObjects) { ob.LoadProperties(cryoArchive, new GameObject(), 0); } // assume the first object is the creature object string creatureActorId = storedGameObjects[0].Names[0].ToString(); storedGameObjects[0].IsCryo = true; // the tribe name is stored in `TamerString`, non-cryoed creatures have the property `TribeName` for that. if (!storedGameObjects[0].HasAnyProperty("TribeName") && storedGameObjects[0].HasAnyProperty("TamerString")) { storedGameObjects[0].Properties.Add(new PropertyString("TribeName", storedGameObjects[0].GetPropertyValue <string>("TamerString"))); } // add cryopod object as parent to all child objects of the creature object (ActorIDs are not unique across cryopodded and non-cryopodded creatures) // assume that child objects are stored after their parent objects for (int i = 0; i < objCount; i++) { var ob = storedGameObjects[i]; int nIndex = ob.Names.FindIndex(n => n.ToString() == creatureActorId); if (nIndex != -1) { ob.Names.Insert(nIndex + 1, cryo.Names[0]); addObject(ob, false); // processing the names can cause conflicts with reused ids } if (i == 0) { for (int ii = 1; ii < objCount; ii++) { ob.AddComponent(storedGameObjects[ii]); } } else { ob.Parent = storedGameObjects[0]; } } // assign the created ID of the components to the creature's properties AssignComponentId("DinoCharacterStatusComponent", "MyCharacterStatusComponent"); AssignComponentId("DinoTamedInventoryComponent", "MyInventoryComponent"); void AssignComponentId(string classStringStartsWith, string propertyName) { var statusComponentObject = storedGameObjects.FirstOrDefault(ob => ob.ClassString?.StartsWith(classStringStartsWith) ?? false); if (statusComponentObject == null) { return; } var statusComponentRef = storedGameObjects[0].GetTypedProperty <PropertyObject>(propertyName); if (statusComponentRef != null) { statusComponentRef.Value.ObjectId = statusComponentObject.Id; } } } } }
public void ReadBinary(ArkArchive archive, ReadingOptions options) { readBinaryHeader(archive); if (SaveVersion > 5) { // Name table is located after the objects block, but will be needed to read the objects block readBinaryNameTable(archive); } readBinaryDataFiles(archive, options); readBinaryEmbeddedData(archive, options); readBinaryDataFilesObjectMap(archive, options); readBinaryObjects(archive, options); readBinaryObjectProperties(archive, options); if (SaveVersion > 6) { readBinaryHibernation(archive, options); } // Parse creatures in cryopods and soultraps (from the mod DinoStorageV2) foreach (var cryo in this.Objects.Where(x => x.ClassString.Contains("Cryop") || x.ClassString.Contains("SoulTrap_")).ToList()) { ArkArrayStruct customItemDatas = cryo.GetPropertyValue <IArkArray, ArkArrayStruct>("CustomItemDatas"); StructPropertyList customDinoData = (StructPropertyList)customItemDatas?.FirstOrDefault(cd => ((StructPropertyList)cd).GetTypedProperty <PropertyName>("CustomDataName").Value.Name == "Dino"); PropertyStruct customDataBytes = customDinoData?.Properties.FirstOrDefault(p => p.NameString == "CustomDataBytes") as PropertyStruct; PropertyArray byteArrays = (customDataBytes?.Value as StructPropertyList)?.Properties.FirstOrDefault(property => property.NameString == "ByteArrays") as PropertyArray; ArkArrayStruct byteArraysValue = byteArrays?.Value as ArkArrayStruct; if (!(byteArraysValue?.Any() ?? false)) { continue; } ArkArrayUInt8 creatureBytes = ((byteArraysValue?[0] as StructPropertyList)?.Properties.FirstOrDefault(p => p.NameString == "Bytes") as PropertyArray)?.Value as ArkArrayUInt8; if (creatureBytes == null) { continue; } var cryoStream = new System.IO.MemoryStream(creatureBytes.ToArray <byte>()); using (ArkArchive cryoArchive = new ArkArchive(cryoStream)) { // number of serialized objects int objCount = cryoArchive.ReadInt(); if (objCount == 0) { continue; } var storedGameObjects = new List <GameObject>(objCount); for (int oi = 0; oi < objCount; oi++) { storedGameObjects.Add(new GameObject(cryoArchive)); } foreach (var ob in storedGameObjects) { ob.LoadProperties(cryoArchive, new GameObject(), 0); } // assume the first object is the creature object string creatureActorId = storedGameObjects[0].Names[0].ToString(); storedGameObjects[0].IsCryo = true; // the tribe name is stored in `TamerString`, non-cryoed creatures have the property `TribeName` for that. if (!storedGameObjects[0].HasAnyProperty("TribeName") && storedGameObjects[0].HasAnyProperty("TamerString")) { storedGameObjects[0].Properties.Add(new PropertyString("TribeName", storedGameObjects[0].GetPropertyValue <string>("TamerString"))); } // add cryopod object as parent to all child objects of the creature object (ActorIDs are not unique across cryopodded and non-cryopodded creatures) // assume that child objects are stored after their parent objects foreach (var ob in storedGameObjects) { int nIndex = ob.Names.FindIndex(n => n.ToString() == creatureActorId); if (nIndex != -1) { ob.Names.Insert(nIndex + 1, cryo.Names[0]); addObject(ob, true); } } // assign the created ID of the dinoStatusComponent to the creature's property. var statusComponentObject = storedGameObjects.FirstOrDefault(ob => ob.ClassString?.StartsWith("DinoCharacterStatusComponent") ?? false); if (statusComponentObject != null) { var statusComponentRef = storedGameObjects[0].GetTypedProperty <PropertyObject>("MyCharacterStatusComponent"); statusComponentRef.Value.ObjectId = statusComponentObject.Id; } } } OldNameList = archive.HasUnknownNames ? archive.NameTable : null; HasUnknownData = archive.HasUnknownData; }
protected override void RunCommand(IEnumerable <string> args) { List <string> argsList = args.ToList(); if (showCommandHelp(argsList)) { return; } string clusterDirectory = argsList[0]; string outputDirectory = argsList[1]; ArkDataManager.LoadData(GlobalOptions.Language); List <Action> tasks = GlobalOptions.Parallel ? new List <Action>() : null; Stopwatch stopwatch = new Stopwatch(GlobalOptions.UseStopWatch); foreach (string path in Directory.EnumerateFiles(clusterDirectory)) { Action task = () => { try { ArkCloudInventory cloudInventory = new ArkCloudInventory().ReadBinary <ArkCloudInventory>(path, ReadingOptions.Create()); CustomDataContext context = new CustomDataContext { ObjectContainer = cloudInventory }; IPropertyContainer arkData = cloudInventory.InventoryData.GetPropertyValue <IPropertyContainer>("MyArkData"); CommonFunctions.WriteJson(Path.Combine(outputDirectory, path + ".json"), (generator, writingOptions) => { generator.WriteStartObject(); ArkArrayStruct tamedDinosData = arkData.GetPropertyValue <ArkArrayStruct>("ArkTamedDinosData"); if (tamedDinosData != null && tamedDinosData.Any()) { generator.WriteArrayFieldStart("creatures"); foreach (IStruct dinoStruct in tamedDinosData) { IPropertyContainer dino = (IPropertyContainer)dinoStruct; ArkContainer container = null; if (cloudInventory.InventoryVersion == 1) { ArkArrayUInt8 byteData = dino.GetPropertyValue <ArkArrayUInt8>("DinoData"); container = new ArkContainer(byteData); } else if (cloudInventory.InventoryVersion == 3) { ArkArrayInt8 byteData = dino.GetPropertyValue <ArkArrayInt8>("DinoData"); container = new ArkContainer(byteData); } ObjectReference dinoClass = dino.GetPropertyValue <ObjectReference>("DinoClass"); // Skip "BlueprintGeneratedClass " = 24 chars string dinoClassName = dinoClass.ObjectString.ToString().Substring(24); generator.WriteStartObject(); generator.WriteField("type", ArkDataManager.HasCreatureByPath(dinoClassName) ? ArkDataManager.GetCreatureByPath(dinoClassName).Name : dinoClassName); // NPE for unknown versions Creature creature = new Creature(container.Objects[0], container); generator.WriteObjectFieldStart("data"); creature.writeAllProperties(generator, context, writeAllFields); generator.WriteEndObject(); generator.WriteEndObject(); } generator.WriteEndArray(); } ArkArrayStruct arkItems = arkData.GetPropertyValue <ArkArrayStruct>("ArkItems"); if (arkItems != null) { List <Item> items = new List <Item>(); foreach (IStruct itemStruct in arkItems) { IPropertyContainer item = (IPropertyContainer)itemStruct; IPropertyContainer netItem = item.GetPropertyValue <IPropertyContainer>("ArkTributeItem"); items.Add(new Item(netItem)); } if (items.Any()) { generator.WritePropertyName("items"); Inventory.writeInventoryLong(generator, context, items, writeAllFields); } } generator.WriteEndObject(); }, writingOptions); } catch (Exception ex) { Console.Error.WriteLine("Found potentially corrupt cluster data: " + path); if (GlobalOptions.Verbose) { Console.Error.WriteLine(ex.Message); Console.Error.WriteLine(ex.StackTrace); } } }; if (tasks != null) { tasks.Add(task); } else { task(); } } if (tasks != null) { Parallel.ForEach(tasks, task => task()); } stopwatch.Stop("Loading cluster data and writing info"); stopwatch.Print(); }