public static void WriteDotArk(IOMemoryStream ms, DotArkFile f) { //Create instance DotArkSerializerInstance inst = new DotArkSerializerInstance(); //Write the game object bodies into their own temporary stream for later IOMemoryStream gameObjectBodyStream = new IOMemoryStream(true); long[] gameObjectPropertyOffsets = GameObjectBodyWriter.WriteGameObjectBodies(gameObjectBodyStream, f, inst); //Now, write the GameObject heads into their own temporary stream for later. IOMemoryStream gameObjectHeadStream = new IOMemoryStream(true); GameObjectHeadWriter.WriteGameObjectHeads(gameObjectHeadStream, f, inst, gameObjectPropertyOffsets); //Create the binary data names, the map parts. IOMemoryStream binaryDataNames = SmallArkDataWriter.WriteBinaryDataNames(f, inst); //Create the embedded binary data IOMemoryStream embeddedBinaryData = SmallArkDataWriter.WriteEmbeddedBinaryDataArray(f, inst); //Create flag data IOMemoryStream unknownFlagData = SmallArkDataWriter.WriteArkUnknownFlags(f, inst); //Finally, generate the name table. THIS STEP MUST COME LAST! IOMemoryStream nameTable = SmallArkDataWriter.WriteNameTable(f, inst); //Build the file BuildArkFile(nameTable, binaryDataNames, embeddedBinaryData, unknownFlagData, gameObjectHeadStream, gameObjectBodyStream, f.meta.unknownData1, f.gameTime, f.meta.saveCount).CopyFromBeginningTo(ms); }
static void WriteHead(IOMemoryStream ms, DotArkFile f, DotArkSerializerInstance si, DotArkGameObject go, long propertyOffset) { //Write data according to https://us-central.assets-static-2.romanport.com/ark/#gameobject+base_header ms.WriteBytes(go.guid.ToByteArray()); //Write the GUID ms.WriteArkClassname(go.classname, si); //Write classname ms.WriteIntBool(go.isItem); //Write classname array ms.WriteInt(go.names.Count); foreach (var n in go.names) { ms.WriteArkClassname(n, si); } //Write unknowns ms.WriteIntBool(go.unknownData1); ms.WriteInt(go.unknownData2); //Write position data if it exists. ms.WriteIntBool(go.locationData != null); if (go.locationData != null) { ms.WriteLocationData(go.locationData); } //Write the offset to the properties data ms.WriteInt((int)propertyOffset); //Write last unknown data ms.WriteInt(go.unknownData3); }
public static IOMemoryStream WriteNameTable(DotArkFile f, DotArkSerializerInstance si) { //name table for props. Spec is here: https://us-central.assets-static-2.romanport.com/ark/#binary+class+name+table_header //Create stream IOMemoryStream ms = new IOMemoryStream(true); //Write into it DotArkWriter.WriteStringArray(ms, si.nameTable.ToArray()); return(ms); }
public static IOMemoryStream WriteBinaryDataNames(DotArkFile f, DotArkSerializerInstance si) { //Binary data names are showing map parts. Spec is here: https://us-central.assets-static-2.romanport.com/ark/#binary+data+names_header //Create stream IOMemoryStream ms = new IOMemoryStream(true); //Write into it DotArkWriter.WriteStringArray(ms, f.meta.binaryDataNames); return(ms); }
public static void WriteGameObjectHeads(IOMemoryStream ms, DotArkFile f, DotArkSerializerInstance si, long[] propertyOffsets) { //Write all of the GameObject headers //First, write the number of GameObjects ms.WriteInt(f.gameObjects.Count); //Loop through gameObjects and write their heads for (int i = 0; i < f.gameObjects.Count; i++) { WriteHead(ms, f, si, f.gameObjects[i], propertyOffsets[i]); } }
public static IOMemoryStream WriteEmbeddedBinaryDataArray(DotArkFile f, DotArkSerializerInstance si) { //I'm really not sure what this is. Spec: https://us-central.assets-static-2.romanport.com/ark/#embeded+binary+data_header //Open straem IOMemoryStream ms = new IOMemoryStream(true); //Get source data var s = f.meta.embededBinaryData; //Write number of blobs ms.WriteInt(s.Length); //Write each for (int i = 0; i < s.Length; i++) { var ss = s[i]; //Write path ms.WriteUEString(ss.path); //Write number of parts ms.WriteInt(ss.data.Length); //Write parts for (int j = 0; j < ss.data.Length; j++) { var ssb = ss.data[j]; //Write number of inner blobs ms.WriteInt(ssb.Length); //Write each inner blob for (int n = 0; n < ssb.Length; n++) { var ssbb = ssb[i]; ms.WriteInt(ssbb.Length / 4); ms.WriteBytes(ssbb); } } } //Return stream return(ms); }
public static long[] WriteGameObjectBodies(IOMemoryStream ms, DotArkFile f, DotArkSerializerInstance si) { //Start writing properties at the current location. long startPos = ms.position; //Allocate an array for storing the offsets to each long[] offsets = new long[f.gameObjects.Count]; //Loop through all GameObjects for (int i = 0; i < f.gameObjects.Count; i++) { offsets[i] = ms.position - startPos; WriteSingleGameObjectBody(ms, f, f.gameObjects[i], si); } //Return offsets return(offsets); }
public static IOMemoryStream WriteArkUnknownFlags(DotArkFile f, DotArkSerializerInstance si) { //Create stream and get the data IOMemoryStream ms = new IOMemoryStream(true); var d = f.meta.mysteryFlagData; //Write array ms.WriteInt(d.Length); for (int i = 0; i < d.Length; i++) { var ds = d[i]; ms.WriteInt(ds.flags); ms.WriteInt(ds.objectCount); ms.WriteUEString(ds.nameString); } //Respond with stream return(ms); }
static void WriteSingleGameObjectBody(IOMemoryStream ms, DotArkFile f, DotArkGameObject o, DotArkSerializerInstance si) { //Just start writing properties foreach (var prop in o.props) { prop.WriteProp(si, o, f, ms); } //Finally, write a None name to tell Ark that this is the end of the list of props. ms.WriteArkClassname(new ArkClassName { classname = "None", index = 0 }, si); }