private void readJson(JToken node, ReadingOptions options)
        {
            X        = node.Value <float>("x");
            Y        = node.Value <float>("y");
            Z        = node.Value <float>("z");
            UnkByte  = node.Value <byte>("unkByte");
            UnkFloat = node.Value <float>("unkFloat");

            ZoneVolumes.Clear();
            JArray zones = node.Value <JArray>("zones");

            if (zones != null && zones.Type != JTokenType.Null)
            {
                foreach (JToken zone in zones)
                {
                    ZoneVolumes.Add(ArkName.From(zone.Value <string>()));
                }
            }

            Objects.Clear();
            ObjectMap.Clear();
            JArray objectsNode = node.Value <JArray>("objects");

            if (objectsNode != null && objectsNode.Type != JTokenType.Null)
            {
                foreach (var jsonNode in objectsNode)
                {
                    addObject(new GameObject((JObject)jsonNode, options.HibernationObjectProperties), options.BuildComponentTree);
                }
            }

            UnkInt1    = node.Value <int>("unkInt1");
            ClassIndex = node.Value <int>("classIndex");
        }
        public int GetSizeAndCollectNames()
        {
            // x y z unkFloat, unkByte, unkInt1 classIndex nameTableSize objectsSize
            const int size = sizeof(float) * 4 + 1 + sizeof(int) * 4;

            HashSet <string> names = new HashSet <string>();

            foreach (GameObject gameObject in Objects)
            {
                gameObject.CollectPropertyNames(name => names.Add(name.ToString()));
            }

            NameSizeCalculator objectSizer     = ArkArchive.GetNameSizer(false);
            NameSizeCalculator propertiesSizer = ArkArchive.GetNameSizer(true, true);

            nameTableSize = sizeof(int) * 3;
            nameTable     = new List <string>(names);

            nameTableSize += nameTable.Sum(ArkArchive.GetStringLength);
            nameTableSize += ZoneVolumes.Sum(name => objectSizer(name));

            objectsSize = sizeof(int);

            objectsSize += Objects.Sum(go => go.Size(objectSizer));

            propertiesStart = objectsSize;

            objectsSize += Objects.Sum(go => go.PropertiesSize(propertiesSizer));

            return(size + nameTableSize + objectsSize);
        }
        private void readBinaryNameTable(ArkArchive archive)
        {
            int version = archive.ReadInt();

            if (version != 3)
            {
                archive.DebugMessage($"Found unknown Version {version}", -4);
                throw new NotSupportedException();
            }

            int count = archive.ReadInt();

            nameTable = new List <string>(count);

            for (int index = 0; index < count; index++)
            {
                nameTable.Add(archive.ReadString());
            }

            int zoneCount = archive.ReadInt();

            for (int index = 0; index < zoneCount; index++)
            {
                ZoneVolumes.Add(archive.ReadName());
            }
        }
        public void WriteBinary(ArkArchive archive)
        {
            archive.WriteFloat(X);
            archive.WriteFloat(Y);
            archive.WriteFloat(Z);
            archive.WriteByte(UnkByte);
            archive.WriteFloat(UnkFloat);

            archive.WriteInt(nameTableSize);
            ArkArchive nameArchive = archive.Slice(nameTableSize);

            nameArchive.WriteInt(3);

            nameArchive.WriteInt(nameTable.Count);
            nameTable.ForEach(nameArchive.WriteString);

            nameArchive.WriteInt(ZoneVolumes.Count);
            ZoneVolumes.ForEach(nameArchive.WriteName);

            archive.WriteInt(objectsSize);
            ArkArchive objectArchive = archive.Slice(objectsSize);

            objectArchive.WriteInt(Objects.Count);

            int currentOffset = propertiesStart;

            foreach (GameObject gameObject in Objects)
            {
                currentOffset = gameObject.WriteBinary(objectArchive, currentOffset);
            }

            objectArchive.SetNameTable(nameTable, 0, true);
            foreach (GameObject gameObject in Objects)
            {
                gameObject.WriteProperties(objectArchive, 0);
            }

            archive.WriteInt(UnkInt1);
            archive.WriteInt(ClassIndex);
        }