Exemplo n.º 1
0
        public void Save(Stream stream)
        {
            var writer     = new EndianAwareBinaryWriter(stream);
            var serializer = new RobloxSerializer(this);

            ReferentProvider.ClearCache(); // Clearing existing referent cache guarantees that referents won't be fragmented
            var instances  = GetChildFirstInstanceEnumerator().ToArray();
            var typeGroups = instances.GroupBy(n => n.ClassName).OrderBy(n => n.Key).ToDictionary(n => n.Key, n => n.ToArray());

            var typeCount   = typeGroups.Count;
            var objectCount = typeGroups.Aggregate(0, (acc, pair) => acc + pair.Value.Length);

            writer.WriteBytes(Signatures.Signature); // File signature
            writer.WriteInt32(typeCount);            // Generic header values
            writer.WriteInt32(objectCount);
            writer.WriteInt32(0);                    // Reserved
            writer.WriteInt32(0);                    // Reserved

            // Write type headers
            var typeHeaders = new TypeHeader[typeCount];
            var nextTypeId  = 0;

            foreach (var typeGroup in typeGroups)
            {
                var typeHeader = new TypeHeader(typeGroup.Key, nextTypeId, typeGroup.Value.Select(n => ReferentProvider.GetReferent(n)).ToArray());
                if (IsSingleton(typeGroup))
                {
                    typeHeader.AdditionalData = new byte[typeHeader.InstanceCount];
                    for (var i = 0; i < typeHeader.InstanceCount; i++)
                    {
                        typeHeader.AdditionalData[i] = 0x1;
                    }
                }
                typeHeaders[nextTypeId] = typeHeader;
                var bytes = typeHeader.Serialize();
                writer.WriteBytes(Signatures.TypeHeaderSignature);
                RobloxLZ4.WriteBlock(stream, bytes);
                nextTypeId++;
            }

            // Write property data
            foreach (var typeGroup in typeGroups)
            {
                var typeHeader     = typeHeaders.First(n => n.Name == typeGroup.Key);
                var instanceTypes  = serializer.GetUniqueProperties(typeGroup.Value);
                var propertyBlocks = instanceTypes.Select(propertyDescriptor => serializer.FillPropertyBlock(propertyDescriptor.Name, propertyDescriptor.Type, typeHeader.TypeId, typeGroup.Value, ReferentProvider)).ToList();
                foreach (var propertyBlock in propertyBlocks)
                {
                    var bytes = propertyBlock.Serialize();
                    writer.WriteBytes(Signatures.PropBlockSignature);
                    RobloxLZ4.WriteBlock(stream, bytes);
                }
            }

            // Build parent child referent arrays
            var parentData = Util.BuildParentData(instances, ReferentProvider);

            var parentDataBytes = Util.SerializeParentData(parentData);

            writer.WriteBytes(Signatures.ParentDataSignature);
            RobloxLZ4.WriteBlock(stream, parentDataBytes);

            // Write ending signature
            writer.WriteBytes(Signatures.EndSignature);
            writer.WriteBytes(Signatures.FileEndSignature);
        }
Exemplo n.º 2
0
 public RobloxDocument()
 {
     Children         = new ChildCollection(null);
     ReferentProvider = new ReferentProvider();
 }
Exemplo n.º 3
0
        private T GetPropertyValue <T>(string propertyName, Instance instance, Type instanceType, PropertyType propertyType, ReferentProvider referentProvider)
        {
            if (ReflectionMappingManager.HasMappedClrProperty(instanceType, propertyName))
            {
                var propertyTuple = ReflectionMappingManager.PropertyCache[instanceType][propertyName];

                if (propertyType != PropertyType.Referent)
                {
                    var propertyValue = propertyTuple.Item1.GetValue(instance);
                    if (propertyValue != null)
                    {
                        return((T)propertyValue);
                    }
                    else
                    {
                        return((T)ReflectionMappingManager.GetDefaultValue(instanceType, propertyName, propertyType));
                    }
                }
                else
                {
                    var referentObj = propertyTuple.Item1.GetValue(instance);
                    if (referentObj != null)
                    {
                        return
                            ((T)(object)referentProvider.GetReferent((Instance)propertyTuple.Item1.GetValue(instance)));
                    }
                    else
                    {
                        return((T)ReflectionMappingManager.GetDefaultValueForType(PropertyType.Referent));
                    }
                }
            }
            else if (instance.UnmanagedProperties.ContainsKey(propertyName))
            {
                var objValue = instance.UnmanagedProperties[propertyName].Get();
                if (objValue != null)
                {
                    return((T)objValue);
                }
                else
                {
                    return((T)ReflectionMappingManager.GetDefaultValueForType(propertyType));
                }
            }
            else
            {
                return((T)ReflectionMappingManager.GetDefaultValueForType(propertyType));
            }
        }
Exemplo n.º 4
0
        public PropertyBlock FillPropertyBlock(string propertyName, PropertyType propertyType, int typeId, Instance[] instances, ReferentProvider referentProvider)
        {
            switch (propertyType)
            {
            case PropertyType.String:
                return(FillPropertyBlock <string>(propertyName, propertyType, typeId, instances, referentProvider));

            case PropertyType.Boolean:
                return(FillPropertyBlock <bool>(propertyName, propertyType, typeId, instances, referentProvider));

            case PropertyType.Int32:
                return(FillPropertyBlock <int>(propertyName, propertyType, typeId, instances, referentProvider));

            case PropertyType.Float:
                return(FillPropertyBlock <float>(propertyName, propertyType, typeId, instances, referentProvider));

            case PropertyType.Double:
                return(FillPropertyBlock <double>(propertyName, propertyType, typeId, instances, referentProvider));

            case PropertyType.UDim2:
                return(FillPropertyBlock <UDim2>(propertyName, propertyType, typeId, instances, referentProvider));

            case PropertyType.Ray:
                return(FillPropertyBlock <Ray>(propertyName, propertyType, typeId, instances, referentProvider));

            case PropertyType.Faces:
                return(FillPropertyBlock <Faces>(propertyName, propertyType, typeId, instances, referentProvider));

            case PropertyType.Axis:
                return(FillPropertyBlock <Axis>(propertyName, propertyType, typeId, instances, referentProvider));

            case PropertyType.BrickColor:
                return(FillPropertyBlock <BrickColor>(propertyName, propertyType, typeId, instances, referentProvider));

            case PropertyType.Color3:
                return(FillPropertyBlock <Color3>(propertyName, propertyType, typeId, instances, referentProvider));

            case PropertyType.Vector2:
                return(FillPropertyBlock <Vector2>(propertyName, propertyType, typeId, instances, referentProvider));

            case PropertyType.Vector3:
                return(FillPropertyBlock <Vector3>(propertyName, propertyType, typeId, instances, referentProvider));

            case PropertyType.CFrame:
                return(FillPropertyBlock <CFrame>(propertyName, propertyType, typeId, instances, referentProvider));

            case PropertyType.Enumeration:
                return(FillPropertyBlock <int>(propertyName, propertyType, typeId, instances, referentProvider));

            case PropertyType.Referent:
                return(FillPropertyBlock <int>(propertyName, propertyType, typeId, instances, referentProvider));

            case PropertyType.NumberSequence:
                return(FillPropertyBlock <NumberSequence>(propertyName, propertyType, typeId, instances, referentProvider));

            case PropertyType.ColorSequence:
                return(FillPropertyBlock <ColorSequence>(propertyName, propertyType, typeId, instances, referentProvider));

            case PropertyType.NumberRange:
                return(FillPropertyBlock <NumberRange>(propertyName, propertyType, typeId, instances, referentProvider));

            case PropertyType.Rectangle:
                return(FillPropertyBlock <Rectangle>(propertyName, propertyType, typeId, instances, referentProvider));

            case PropertyType.PhysicalProperties:
                return(FillPropertyBlock <PhysicalProperties>(propertyName, propertyType, typeId, instances, referentProvider));

            default:
                throw new ArgumentOutOfRangeException(nameof(propertyType), propertyType, null);
            }
        }
Exemplo n.º 5
0
        public PropertyBlock <T> FillPropertyBlock <T>(string propertyName, PropertyType propertyType, int typeId, Instance[] instances, ReferentProvider referentProvider)
        {
            var propertyBlock = new PropertyBlock <T>(propertyName, propertyType, typeId, instances.Length);
            var instanceType  = instances[0].GetType();

            for (var i = 0; i < instances.Length; i++)
            {
                propertyBlock.Values.Add(GetPropertyValue <T>(propertyName, instances[i], instanceType, propertyType, referentProvider));
            }
            return(propertyBlock);
        }