Attribute -> RbxAttribute

This commit is contained in:
Max 2021-06-05 17:21:12 -05:00
parent 71cd85513e
commit 5dc65e2184
23 changed files with 76 additions and 133 deletions

View File

@ -18,13 +18,6 @@
Envelope = envelope; Envelope = envelope;
} }
internal NumberSequenceKeypoint(Attribute attr)
{
Envelope = attr.ReadFloat();
Time = attr.ReadFloat();
Value = attr.ReadFloat();
}
public override int GetHashCode() public override int GetHashCode()
{ {
int hash = Time.GetHashCode() int hash = Time.GetHashCode()

View File

@ -37,16 +37,6 @@ namespace RobloxFiles.DataTypes
ElasticityWeight = elasticityWeight; ElasticityWeight = elasticityWeight;
} }
internal PhysicalProperties(Attribute attr)
{
Density = attr.ReadFloat();
Friction = attr.ReadFloat();
Elasticity = attr.ReadFloat();
FrictionWeight = attr.ReadFloat();
ElasticityWeight = attr.ReadFloat();
}
public override int GetHashCode() public override int GetHashCode()
{ {
int hash = Density.GetHashCode() int hash = Density.GetHashCode()

View File

@ -11,12 +11,6 @@
Max = max ?? new Vector3int16(); Max = max ?? new Vector3int16();
} }
internal Region3int16(Attribute attr)
{
Min = new Vector3int16(attr);
Max = new Vector3int16(attr);
}
public override int GetHashCode() public override int GetHashCode()
{ {
int hash = Min.GetHashCode() int hash = Min.GetHashCode()

View File

@ -19,12 +19,6 @@ namespace RobloxFiles.DataTypes
Y = (short)y; Y = (short)y;
} }
internal Vector2int16(Attribute attr)
{
X = attr.ReadShort();
Y = attr.ReadShort();
}
private delegate Vector2int16 Operator(Vector2int16 a, Vector2int16 b); private delegate Vector2int16 Operator(Vector2int16 a, Vector2int16 b);
private static Vector2int16 upcastShortOp(Vector2int16 vec, short num, Operator upcast) private static Vector2int16 upcastShortOp(Vector2int16 vec, short num, Operator upcast)

View File

@ -25,13 +25,6 @@ namespace RobloxFiles.DataTypes
Z = (short)z; Z = (short)z;
} }
internal Vector3int16(Attribute attr)
{
X = attr.ReadShort();
Y = attr.ReadShort();
Z = attr.ReadShort();
}
private delegate Vector3int16 Operator(Vector3int16 a, Vector3int16 b); private delegate Vector3int16 Operator(Vector3int16 a, Vector3int16 b);
private static Vector3int16 upcastShortOp(Vector3int16 vec, short num, Operator upcast) private static Vector3int16 upcastShortOp(Vector3int16 vec, short num, Operator upcast)

View File

@ -4,7 +4,7 @@
{ {
AttributeType AttributeType { get; } AttributeType AttributeType { get; }
T ReadAttribute(Attribute attribute); T ReadAttribute(RbxAttribute attribute);
void WriteAttribute(Attribute attribute, T value); void WriteAttribute(RbxAttribute attribute, T value);
} }
} }

Binary file not shown.

View File

@ -8,8 +8,8 @@ namespace RobloxFiles.Tokens
public string XmlPropertyToken => "bool"; public string XmlPropertyToken => "bool";
public AttributeType AttributeType => AttributeType.Bool; public AttributeType AttributeType => AttributeType.Bool;
public bool ReadAttribute(Attribute attr) => attr.ReadBool(); public bool ReadAttribute(RbxAttribute attr) => attr.ReadBool();
public void WriteAttribute(Attribute attr, bool value) => attr.WriteBool(value); public void WriteAttribute(RbxAttribute attr, bool value) => attr.WriteBool(value);
public bool ReadProperty(Property prop, XmlNode token) public bool ReadProperty(Property prop, XmlNode token)
{ {

View File

@ -12,8 +12,8 @@ namespace RobloxFiles.Tokens
public string XmlPropertyToken => "BrickColor"; public string XmlPropertyToken => "BrickColor";
public AttributeType AttributeType => AttributeType.BrickColor; public AttributeType AttributeType => AttributeType.BrickColor;
public BrickColor ReadAttribute(Attribute attr) => attr.ReadInt(); public BrickColor ReadAttribute(RbxAttribute attr) => attr.ReadInt();
public void WriteAttribute(Attribute attr, BrickColor value) => attr.WriteInt(value.Number); public void WriteAttribute(RbxAttribute attr, BrickColor value) => attr.WriteInt(value.Number);
public bool ReadProperty(Property prop, XmlNode token) public bool ReadProperty(Property prop, XmlNode token)
{ {

View File

@ -10,10 +10,10 @@ namespace RobloxFiles.Tokens
private readonly string[] XmlFields = new string[3] { "R", "G", "B" }; private readonly string[] XmlFields = new string[3] { "R", "G", "B" };
public AttributeType AttributeType => AttributeType.Color3; public AttributeType AttributeType => AttributeType.Color3;
public Color3 ReadAttribute(Attribute attr) => ReadColor3(attr); public Color3 ReadAttribute(RbxAttribute attr) => ReadColor3(attr);
public void WriteAttribute(Attribute attr, Color3 value) => WriteColor3(attr, value); public void WriteAttribute(RbxAttribute attr, Color3 value) => WriteColor3(attr, value);
public static Color3 ReadColor3(Attribute attr) public static Color3 ReadColor3(RbxAttribute attr)
{ {
float r = attr.ReadFloat(), float r = attr.ReadFloat(),
g = attr.ReadFloat(), g = attr.ReadFloat(),
@ -22,7 +22,7 @@ namespace RobloxFiles.Tokens
return new Color3(r, g, b); return new Color3(r, g, b);
} }
public static void WriteColor3(Attribute attr, Color3 value) public static void WriteColor3(RbxAttribute attr, Color3 value)
{ {
attr.WriteFloat(value.R); attr.WriteFloat(value.R);
attr.WriteFloat(value.G); attr.WriteFloat(value.G);

View File

@ -52,7 +52,7 @@ namespace RobloxFiles.Tokens
node.InnerText = value.ToString() + ' '; node.InnerText = value.ToString() + ' ';
} }
public ColorSequence ReadAttribute(Attribute attr) public ColorSequence ReadAttribute(RbxAttribute attr)
{ {
int numKeys = attr.ReadInt(); int numKeys = attr.ReadInt();
var keypoints = new ColorSequenceKeypoint[numKeys]; var keypoints = new ColorSequenceKeypoint[numKeys];
@ -69,7 +69,7 @@ namespace RobloxFiles.Tokens
return new ColorSequence(keypoints); return new ColorSequence(keypoints);
} }
public void WriteAttribute(Attribute attr, ColorSequence value) public void WriteAttribute(RbxAttribute attr, ColorSequence value)
{ {
attr.WriteInt(value.Keypoints.Length); attr.WriteInt(value.Keypoints.Length);

View File

@ -8,8 +8,8 @@ namespace RobloxFiles.Tokens
public string XmlPropertyToken => "double"; public string XmlPropertyToken => "double";
public AttributeType AttributeType => AttributeType.Double; public AttributeType AttributeType => AttributeType.Double;
public double ReadAttribute(Attribute attr) => attr.ReadDouble(); public double ReadAttribute(RbxAttribute attr) => attr.ReadDouble();
public void WriteAttribute(Attribute attr, double value) => attr.WriteDouble(value); public void WriteAttribute(RbxAttribute attr, double value) => attr.WriteDouble(value);
public bool ReadProperty(Property prop, XmlNode token) public bool ReadProperty(Property prop, XmlNode token)
{ {

View File

@ -8,8 +8,8 @@ namespace RobloxFiles.Tokens
public string XmlPropertyToken => "float"; public string XmlPropertyToken => "float";
public AttributeType AttributeType => AttributeType.Float; public AttributeType AttributeType => AttributeType.Float;
public float ReadAttribute(Attribute attr) => attr.ReadFloat(); public float ReadAttribute(RbxAttribute attr) => attr.ReadFloat();
public void WriteAttribute(Attribute attr, float value) => attr.WriteFloat(value); public void WriteAttribute(RbxAttribute attr, float value) => attr.WriteFloat(value);
public bool ReadProperty(Property prop, XmlNode token) public bool ReadProperty(Property prop, XmlNode token)
{ {

View File

@ -40,7 +40,7 @@ namespace RobloxFiles.Tokens
node.InnerText = value.ToString() + ' '; node.InnerText = value.ToString() + ' ';
} }
public NumberRange ReadAttribute(Attribute attr) public NumberRange ReadAttribute(RbxAttribute attr)
{ {
float min = attr.ReadFloat(); float min = attr.ReadFloat();
float max = attr.ReadFloat(); float max = attr.ReadFloat();
@ -48,7 +48,7 @@ namespace RobloxFiles.Tokens
return new NumberRange(min, max); return new NumberRange(min, max);
} }
public void WriteAttribute(Attribute attr, NumberRange value) public void WriteAttribute(RbxAttribute attr, NumberRange value)
{ {
attr.WriteFloat(value.Min); attr.WriteFloat(value.Min);
attr.WriteFloat(value.Max); attr.WriteFloat(value.Max);

View File

@ -49,7 +49,7 @@ namespace RobloxFiles.Tokens
node.InnerText = value.ToString() + ' '; node.InnerText = value.ToString() + ' ';
} }
public NumberSequence ReadAttribute(Attribute attr) public NumberSequence ReadAttribute(RbxAttribute attr)
{ {
int numKeys = attr.ReadInt(); int numKeys = attr.ReadInt();
var keypoints = new NumberSequenceKeypoint[numKeys]; var keypoints = new NumberSequenceKeypoint[numKeys];
@ -66,7 +66,7 @@ namespace RobloxFiles.Tokens
return new NumberSequence(keypoints); return new NumberSequence(keypoints);
} }
public void WriteAttribute(Attribute attr, NumberSequence value) public void WriteAttribute(RbxAttribute attr, NumberSequence value)
{ {
attr.WriteInt(value.Keypoints.Length); attr.WriteInt(value.Keypoints.Length);

View File

@ -51,7 +51,7 @@ namespace RobloxFiles.Tokens
node.AppendChild(max); node.AppendChild(max);
} }
public Rect ReadAttribute(Attribute attr) public Rect ReadAttribute(RbxAttribute attr)
{ {
Vector2 min = Vector2Token.ReadVector2(attr); Vector2 min = Vector2Token.ReadVector2(attr);
Vector2 max = Vector2Token.ReadVector2(attr); Vector2 max = Vector2Token.ReadVector2(attr);
@ -59,7 +59,7 @@ namespace RobloxFiles.Tokens
return new Rect(min, max); return new Rect(min, max);
} }
public void WriteAttribute(Attribute attr, Rect value) public void WriteAttribute(RbxAttribute attr, Rect value)
{ {
Vector2Token.WriteVector2(attr, value.Min); Vector2Token.WriteVector2(attr, value.Min);
Vector2Token.WriteVector2(attr, value.Max); Vector2Token.WriteVector2(attr, value.Max);

View File

@ -7,8 +7,8 @@ namespace RobloxFiles.Tokens
public string XmlPropertyToken => "string"; public string XmlPropertyToken => "string";
public AttributeType AttributeType => AttributeType.String; public AttributeType AttributeType => AttributeType.String;
public string ReadAttribute(Attribute attr) => attr.ReadString(); public string ReadAttribute(RbxAttribute attr) => attr.ReadString();
public void WriteAttribute(Attribute attr, string value) => attr.WriteString(value); public void WriteAttribute(RbxAttribute attr, string value) => attr.WriteString(value);
public bool ReadProperty(Property prop, XmlNode token) public bool ReadProperty(Property prop, XmlNode token)
{ {

View File

@ -9,8 +9,8 @@ namespace RobloxFiles.Tokens
public string XmlPropertyToken => "UDim"; public string XmlPropertyToken => "UDim";
public AttributeType AttributeType => AttributeType.UDim; public AttributeType AttributeType => AttributeType.UDim;
public UDim ReadAttribute(Attribute attr) => ReadUDim(attr); public UDim ReadAttribute(RbxAttribute attr) => ReadUDim(attr);
public void WriteAttribute(Attribute attr, UDim value) => WriteUDim(attr, value); public void WriteAttribute(RbxAttribute attr, UDim value) => WriteUDim(attr, value);
public static UDim ReadUDim(XmlNode token, string prefix = "") public static UDim ReadUDim(XmlNode token, string prefix = "")
{ {
@ -41,7 +41,7 @@ namespace RobloxFiles.Tokens
node.AppendChild(offset); node.AppendChild(offset);
} }
public static UDim ReadUDim(Attribute attr) public static UDim ReadUDim(RbxAttribute attr)
{ {
float scale = attr.ReadFloat(); float scale = attr.ReadFloat();
int offset = attr.ReadInt(); int offset = attr.ReadInt();
@ -49,7 +49,7 @@ namespace RobloxFiles.Tokens
return new UDim(scale, offset); return new UDim(scale, offset);
} }
public static void WriteUDim(Attribute attr, UDim value) public static void WriteUDim(RbxAttribute attr, UDim value)
{ {
float scale = value.Scale; float scale = value.Scale;
attr.WriteFloat(scale); attr.WriteFloat(scale);

View File

@ -8,7 +8,7 @@ namespace RobloxFiles.Tokens
public string XmlPropertyToken => "UDim2"; public string XmlPropertyToken => "UDim2";
public AttributeType AttributeType => AttributeType.UDim2; public AttributeType AttributeType => AttributeType.UDim2;
public UDim2 ReadAttribute(Attribute attr) public UDim2 ReadAttribute(RbxAttribute attr)
{ {
UDim x = UDimToken.ReadUDim(attr); UDim x = UDimToken.ReadUDim(attr);
UDim y = UDimToken.ReadUDim(attr); UDim y = UDimToken.ReadUDim(attr);
@ -16,7 +16,7 @@ namespace RobloxFiles.Tokens
return new UDim2(x, y); return new UDim2(x, y);
} }
public void WriteAttribute(Attribute attr, UDim2 value) public void WriteAttribute(RbxAttribute attr, UDim2 value)
{ {
UDimToken.WriteUDim(attr, value.X); UDimToken.WriteUDim(attr, value.X);
UDimToken.WriteUDim(attr, value.Y); UDimToken.WriteUDim(attr, value.Y);

View File

@ -9,8 +9,8 @@ namespace RobloxFiles.Tokens
private static readonly string[] XmlCoords = new string[2] { "X", "Y" }; private static readonly string[] XmlCoords = new string[2] { "X", "Y" };
public AttributeType AttributeType => AttributeType.Vector2; public AttributeType AttributeType => AttributeType.Vector2;
public Vector2 ReadAttribute(Attribute attr) => ReadVector2(attr); public Vector2 ReadAttribute(RbxAttribute attr) => ReadVector2(attr);
public void WriteAttribute(Attribute attr, Vector2 value) => WriteVector2(attr, value); public void WriteAttribute(RbxAttribute attr, Vector2 value) => WriteVector2(attr, value);
public static Vector2 ReadVector2(XmlNode token) public static Vector2 ReadVector2(XmlNode token)
{ {
@ -46,7 +46,7 @@ namespace RobloxFiles.Tokens
node.AppendChild(y); node.AppendChild(y);
} }
public static Vector2 ReadVector2(Attribute attr) public static Vector2 ReadVector2(RbxAttribute attr)
{ {
float x = attr.ReadFloat(), float x = attr.ReadFloat(),
y = attr.ReadFloat(); y = attr.ReadFloat();
@ -54,7 +54,7 @@ namespace RobloxFiles.Tokens
return new Vector2(x, y); return new Vector2(x, y);
} }
public static void WriteVector2(Attribute attr, Vector2 value) public static void WriteVector2(RbxAttribute attr, Vector2 value)
{ {
attr.WriteFloat(value.X); attr.WriteFloat(value.X);
attr.WriteFloat(value.Y); attr.WriteFloat(value.Y);

View File

@ -9,8 +9,8 @@ namespace RobloxFiles.Tokens
private static readonly string[] XmlCoords = new string[3] { "X", "Y", "Z" }; private static readonly string[] XmlCoords = new string[3] { "X", "Y", "Z" };
public AttributeType AttributeType => AttributeType.Vector3; public AttributeType AttributeType => AttributeType.Vector3;
public Vector3 ReadAttribute(Attribute attr) => ReadVector3(attr); public Vector3 ReadAttribute(RbxAttribute attr) => ReadVector3(attr);
public void WriteAttribute(Attribute attr, Vector3 value) => WriteVector3(attr, value); public void WriteAttribute(RbxAttribute attr, Vector3 value) => WriteVector3(attr, value);
public static Vector3 ReadVector3(XmlNode token) public static Vector3 ReadVector3(XmlNode token)
{ {
@ -49,7 +49,7 @@ namespace RobloxFiles.Tokens
node.AppendChild(z); node.AppendChild(z);
} }
public static Vector3 ReadVector3(Attribute attr) public static Vector3 ReadVector3(RbxAttribute attr)
{ {
float x = attr.ReadFloat(), float x = attr.ReadFloat(),
y = attr.ReadFloat(), y = attr.ReadFloat(),
@ -58,7 +58,7 @@ namespace RobloxFiles.Tokens
return new Vector3(x, y, z); return new Vector3(x, y, z);
} }
public static void WriteVector3(Attribute attr, Vector3 value) public static void WriteVector3(RbxAttribute attr, Vector3 value)
{ {
attr.WriteFloat(value.X); attr.WriteFloat(value.X);
attr.WriteFloat(value.Y); attr.WriteFloat(value.Y);

View File

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Runtime.Serialization;
using System.Text; using System.Text;
namespace RobloxFiles namespace RobloxFiles
@ -45,7 +46,7 @@ namespace RobloxFiles
// Region3int16 = 32 // Region3int16 = 32
} }
public class Attribute : IDisposable public class RbxAttribute : IDisposable
{ {
private static readonly IReadOnlyDictionary<AttributeType, Tokenizer> AttributeSupport; private static readonly IReadOnlyDictionary<AttributeType, Tokenizer> AttributeSupport;
private static readonly IReadOnlyDictionary<Type, AttributeType> SupportedTypes; private static readonly IReadOnlyDictionary<Type, AttributeType> SupportedTypes;
@ -70,20 +71,20 @@ namespace RobloxFiles
Writer = support.GetMethod("WriteAttribute"); Writer = support.GetMethod("WriteAttribute");
} }
public object ReadAttribute(Attribute attr) public object ReadAttribute(RbxAttribute attr)
{ {
var args = new object[1] { attr }; var args = new object[1] { attr };
return Reader.Invoke(Token, args); return Reader.Invoke(Token, args);
} }
public void WriteAttribute(Attribute attr, object value) public void WriteAttribute(RbxAttribute attr, object value)
{ {
var args = new object[2] { attr, value }; var args = new object[2] { attr, value };
Writer.Invoke(Token, args); Writer.Invoke(Token, args);
} }
} }
static Attribute() static RbxAttribute()
{ {
var attributeSupport = new Dictionary<AttributeType, Tokenizer>(); var attributeSupport = new Dictionary<AttributeType, Tokenizer>();
var supportedTypes = new Dictionary<Type, AttributeType>(); var supportedTypes = new Dictionary<Type, AttributeType>();
@ -193,19 +194,19 @@ namespace RobloxFiles
Writer = null; Writer = null;
} }
internal Attribute(BinaryReader reader) internal RbxAttribute(BinaryReader reader)
{ {
Reader = reader; Reader = reader;
Read(); Read();
} }
internal Attribute(MemoryStream stream) internal RbxAttribute(MemoryStream stream)
{ {
Reader = new BinaryReader(stream); Reader = new BinaryReader(stream);
Read(); Read();
} }
internal Attribute(object value) internal RbxAttribute(object value)
{ {
Type type = value.GetType(); Type type = value.GetType();
@ -217,44 +218,31 @@ namespace RobloxFiles
} }
} }
public class Attributes : SortedDictionary<string, Attribute> public class RbxAttributes : SortedDictionary<string, RbxAttribute>
{ {
private void Initialize(BinaryReader reader) internal void Load(byte[] buffer)
{ {
Stream stream = reader.BaseStream; Clear();
if (stream.Length - stream.Position < 4) if (buffer == null || buffer.Length < 4)
// Not enough room to read the entry count, possibly empty? // Not enough room to read the entry count, possibly empty?
return; return;
int numEntries = reader.ReadInt32(); using (var input = new MemoryStream(buffer))
using (var reader = new BinaryReader(input))
for (int i = 0; i < numEntries; i++)
{ {
string key = reader.ReadString(true); int numEntries = reader.ReadInt32();
var attribute = new Attribute(reader);
Add(key, attribute); for (int i = 0; i < numEntries; i++)
{
string key = reader.ReadString(true);
var attribute = new RbxAttribute(reader);
Add(key, attribute);
}
} }
} }
public Attributes() : base() internal byte[] Save()
{
}
internal Attributes(BinaryReader reader)
{
Initialize(reader);
}
internal Attributes(MemoryStream stream)
{
using (var reader = new BinaryReader(stream))
Initialize(reader);
stream.Dispose();
}
internal byte[] Serialize()
{ {
if (Count == 0) if (Count == 0)
return Array.Empty<byte>(); return Array.Empty<byte>();

View File

@ -1,7 +1,5 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.IO;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Text; using System.Text;
@ -61,26 +59,16 @@ namespace RobloxFiles
public bool Destroyed { get; internal set; } public bool Destroyed { get; internal set; }
/// <summary>A hashset of CollectionService tags assigned to this Instance.</summary> /// <summary>A hashset of CollectionService tags assigned to this Instance.</summary>
public HashSet<string> Tags { get; } = new HashSet<string>(); public readonly HashSet<string> Tags = new HashSet<string>();
/// <summary>The attributes defined for this Instance.</summary>
private Attributes AttributesImpl = new Attributes();
/// <summary>The public readonly access point of the attributes on this Instance.</summary> /// <summary>The public readonly access point of the attributes on this Instance.</summary>
public IReadOnlyDictionary<string, Attribute> Attributes => AttributesImpl; public readonly RbxAttributes Attributes = new RbxAttributes();
/// <summary>The internal serialized data of this Instance's attributes</summary> /// <summary>The internal serialized data of this Instance's attributes</summary>
internal byte[] AttributesSerialize internal byte[] AttributesSerialize
{ {
get get => Attributes.Save();
{ set => Attributes.Load(value);
return AttributesImpl?.Serialize() ?? Array.Empty<byte>();
}
set
{
var data = new MemoryStream(value);
AttributesImpl = new Attributes(data);
}
} }
/// <summary> /// <summary>
@ -134,7 +122,7 @@ namespace RobloxFiles
/// <returns>True if the attribute could be read and the out value was set, false otherwise.</returns> /// <returns>True if the attribute could be read and the out value was set, false otherwise.</returns>
public bool GetAttribute<T>(string key, out T value) public bool GetAttribute<T>(string key, out T value)
{ {
if (AttributesImpl.TryGetValue(key, out Attribute attr)) if (Attributes.TryGetValue(key, out RbxAttribute attr))
{ {
if (attr.Value is T result) if (attr.Value is T result)
{ {
@ -161,13 +149,16 @@ namespace RobloxFiles
if (key.Length > 100) if (key.Length > 100)
return false; return false;
Type type = value.GetType(); if (key.StartsWith("RBX", StringComparison.InvariantCulture))
if (!Attribute.SupportsType(type))
return false; return false;
var attr = new Attribute(value); Type type = value.GetType();
AttributesImpl[key] = attr;
if (!RbxAttribute.SupportsType(type))
return false;
var attr = new RbxAttribute(value);
Attributes[key] = attr;
return true; return true;
} }
@ -474,8 +465,8 @@ namespace RobloxFiles
Parent = null; Parent = null;
ParentLocked = true; ParentLocked = true;
Tags?.Clear(); Tags.Clear();
AttributesImpl?.Clear(); Attributes.Clear();
while (Children.Any()) while (Children.Any())
{ {