General Misc Patches

This commit is contained in:
CloneTrooper1019 2020-08-17 20:12:24 -05:00
parent 297426bdb5
commit f4899b4ce6
18 changed files with 267 additions and 47 deletions

View File

@ -29,8 +29,8 @@ namespace RobloxFiles.BinaryFormat.Chunks
byte[] data = reader.ReadBuffer();
SharedString value = SharedString.FromBuffer(data);
Lookup.Add(key, id);
Strings.Add(id, value);
Lookup[key] = id;
Strings[id] = value;
}
file.SSTR = this;

View File

@ -170,6 +170,25 @@ namespace RobloxFiles.DataTypes
}
}
public override bool Equals(object obj)
{
if (obj is CFrame)
{
CFrame other = obj as CFrame;
float[] a = GetComponents();
float[] b = other.GetComponents();
for (int i = 0; i < 12; i++)
if (!a[i].FuzzyEquals(b[i]))
return false;
return true;
}
return base.Equals(obj);
}
public static CFrame operator +(CFrame a, Vector3 b)
{
float[] ac = a.GetComponents();

View File

@ -14,6 +14,15 @@ namespace RobloxFiles.DataTypes
B = b;
}
public override int GetHashCode()
{
int r = R.GetHashCode(),
g = G.GetHashCode(),
b = B.GetHashCode();
return (r ^ g ^ b);
}
internal Color3(Attribute attr)
{
R = attr.readFloat();

View File

@ -16,6 +16,11 @@
B = b;
}
public override int GetHashCode()
{
return (R << 24) | (G << 8) | B;
}
public static implicit operator Color3(Color3uint8 color)
{
float r = color.R / 255f;

View File

@ -21,10 +21,11 @@ namespace RobloxFiles.DataTypes
public ColorSequence(Color3 c0, Color3 c1)
{
ColorSequenceKeypoint a = new ColorSequenceKeypoint(0, c0);
ColorSequenceKeypoint b = new ColorSequenceKeypoint(1, c1);
Keypoints = new ColorSequenceKeypoint[2] { a, b };
Keypoints = new ColorSequenceKeypoint[2]
{
new ColorSequenceKeypoint(0, c0),
new ColorSequenceKeypoint(1, c1)
};
}
public ColorSequence(ColorSequenceKeypoint[] keypoints)

View File

@ -3,12 +3,13 @@
public class ColorSequenceKeypoint
{
public readonly float Time;
public readonly Color3 Value;
public readonly Color3uint8 Value;
public readonly int Envelope;
public override string ToString()
{
return $"{Time} {Value.R} {Value.G} {Value.B} {Envelope}";
Color3 Color = Value;
return $"{Time} {Color.R} {Color.G} {Color.B} {Envelope}";
}
public ColorSequenceKeypoint(float time, Color3 value, int envelope = 0)

View File

@ -59,7 +59,7 @@ namespace RobloxFiles.DataTypes
public static SharedString FromBuffer(byte[] buffer)
{
return new SharedString(buffer);
return new SharedString(buffer ?? Array.Empty<byte>());
}
public static SharedString FromString(string value)

View File

@ -1,4 +1,5 @@
using System;
using System.Text;
using RobloxFiles.Enums;
namespace RobloxFiles.DataTypes
@ -65,6 +66,36 @@ namespace RobloxFiles.DataTypes
return new Vector3(coords);
}
public override bool Equals(object obj)
{
if (obj is Vector3)
{
Vector3 other = obj as Vector3;
if (!X.FuzzyEquals(other.X))
return false;
if (!Y.FuzzyEquals(other.Y))
return false;
if (!Z.FuzzyEquals(other.Z))
return false;
return true;
}
return base.Equals(obj);
}
public override int GetHashCode()
{
int x = X.GetHashCode(),
y = Y.GetHashCode(),
z = Z.GetHashCode();
return x ^ y ^ z;
}
private delegate Vector3 Operator(Vector3 a, Vector3 b);
private static Vector3 upcastFloatOp(Vector3 vec, float num, Operator upcast)

View File

@ -2251,7 +2251,9 @@ namespace RobloxFiles
{
public ModelLevelOfDetail LevelOfDetail = ModelLevelOfDetail.Automatic;
public CFrame ModelInPrimary = new CFrame();
public CFrame ModelMeshCFrame = new CFrame();
public byte[] ModelMeshData = Array.Empty<byte>();
public Vector3 ModelMeshSize = new Vector3();
public BasePart PrimaryPart;
}

View File

@ -121,6 +121,7 @@
<Compile Include="DataTypes\UDim2.cs" />
<Compile Include="DataTypes\Vector2.cs" />
<Compile Include="DataTypes\Vector3.cs" />
<Compile Include="Utility\DefaultProperty.cs" />
<Compile Include="Utility\Formatting.cs" />
<Compile Include="Utility\FontUtility.cs" />
<Compile Include="Utility\ImplicitMember.cs" />

Binary file not shown.

View File

@ -530,11 +530,44 @@ namespace RobloxFiles
if (fieldName.EndsWith("_"))
fieldName = instType.Name;
string xmlToken = fieldType.Name;
if (fieldType.IsEnum)
xmlToken = "token";
switch (xmlToken)
{
case "String":
case "Double":
xmlToken = xmlToken.ToLowerInvariant();
break;
case "Boolean":
xmlToken = "bool";
break;
case "Single":
xmlToken = "float";
break;
case "Int32":
xmlToken = "int";
break;
case "Int64":
xmlToken = "int64";
break;
case "Rect":
xmlToken = "Rect2D";
break;
case "CFrame":
xmlToken = "CoordinateFrame";
break;
default: break;
}
if (!props.ContainsKey(fieldName))
{
Property newProp = new Property()
{
Value = field.GetValue(this),
XmlToken = xmlToken,
Name = fieldName,
Type = propType,
Instance = this
@ -546,6 +579,7 @@ namespace RobloxFiles
{
Property prop = props[fieldName];
prop.Value = field.GetValue(this);
prop.XmlToken = xmlToken;
prop.Type = propType;
}
}

View File

@ -100,35 +100,45 @@ namespace RobloxFiles
private void ImproviseRawBuffer()
{
if (RawValue is SharedString)
{
var sharedString = CastValue<SharedString>();
RawBuffer = sharedString.SharedValue;
return;
}
else if (RawValue is ProtectedString)
{
var protectedString = CastValue<ProtectedString>();
RawBuffer = protectedString.RawBuffer;
return;
}
else if (RawValue is byte[])
if (RawValue is byte[])
{
RawBuffer = RawValue as byte[];
return;
}
if (RawValue is SharedString)
{
var sharedString = CastValue<SharedString>();
if (sharedString != null)
{
RawBuffer = sharedString.SharedValue;
return;
}
}
if (RawValue is ProtectedString)
{
var protectedString = CastValue<ProtectedString>();
if (protectedString != null)
{
RawBuffer = protectedString.RawBuffer;
return;
}
}
switch (Type)
{
case PropertyType.Int:
RawBuffer = BitConverter.GetBytes((int)Value);
break;
case PropertyType.Int64:
RawBuffer = BitConverter.GetBytes((long)Value);
break;
case PropertyType.Bool:
RawBuffer = BitConverter.GetBytes((bool)Value);
break;
case PropertyType.Int64:
RawBuffer = BitConverter.GetBytes((long)Value);
break;
case PropertyType.Float:
RawBuffer = BitConverter.GetBytes((float)Value);
break;

View File

@ -0,0 +1,63 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
namespace RobloxFiles.Utility
{
static class DefaultProperty
{
private static Dictionary<string, Instance> ClassMap;
private static HashSet<Instance> Refreshed = new HashSet<Instance>();
static DefaultProperty()
{
var Instance = typeof(Instance);
var assembly = Assembly.GetExecutingAssembly();
var classes = assembly.GetTypes()
.Where(type => !type.IsAbstract && Instance.IsAssignableFrom(type))
.Select(type => Activator.CreateInstance(type))
.Cast<Instance>();
ClassMap = classes.ToDictionary(inst => inst.ClassName);
}
public static object Get(string className, string propName)
{
if (!ClassMap.ContainsKey(className))
return null;
Instance inst = ClassMap[className];
if (!Refreshed.Contains(inst))
{
inst.RefreshProperties();
Refreshed.Add(inst);
}
var props = inst.Properties;
if (!props.ContainsKey(propName))
return null;
var prop = props[propName];
return prop.Value;
}
public static object Get(Instance inst, string propName)
{
return Get(inst.ClassName, propName);
}
public static object Get(Instance inst, Property prop)
{
return Get(inst.ClassName, prop.Name);
}
public static object Get(string className, Property prop)
{
return Get(className, prop.Name);
}
}
}

View File

@ -6,6 +6,7 @@ using System.Text;
using System.Xml;
using RobloxFiles.DataTypes;
using RobloxFiles.Utility;
using RobloxFiles.XmlFormat.PropertyTokens;
namespace RobloxFiles.XmlFormat
@ -41,12 +42,11 @@ namespace RobloxFiles.XmlFormat
internal static void RecordInstances(XmlRobloxFile file, Instance inst)
{
inst.Referent = "RBX" + file.RefCounter++;
foreach (Instance child in inst.GetChildren())
RecordInstances(file, child);
if (inst.Referent == null || inst.Referent.Length < 35)
inst.Referent = CreateReferent();
file.Instances.Add(inst.Referent, inst);
}
@ -100,15 +100,21 @@ namespace RobloxFiles.XmlFormat
if (prop.Type == PropertyType.SharedString)
{
SharedString value = prop.CastValue<SharedString>();
SharedString str = prop.CastValue<SharedString>();
if (value.ComputedKey == null)
if (str == null)
{
var newShared = SharedString.FromBuffer(value.SharedValue);
value.Key = newShared.ComputedKey;
byte[] value = prop.CastValue<byte[]>();
str = SharedString.FromBuffer(value);
}
file.SharedStrings.Add(value.Key);
if (str.ComputedKey == null)
{
var newShared = SharedString.FromBuffer(str.SharedValue);
str.Key = newShared.ComputedKey;
}
file.SharedStrings.Add(str.Key);
}
XmlElement propElement = doc.CreateElement(propType);
@ -148,6 +154,36 @@ namespace RobloxFiles.XmlFormat
foreach (string propName in orderedKeys)
{
Property prop = props[propName];
bool isDefault = false;
object a = DefaultProperty.Get(instance, prop);
object b = prop.Value;
if (a is float)
{
float f0 = (float)a,
f1 = (float)b;
isDefault = f0.FuzzyEquals(f1);
}
else if (a is double)
{
double d0 = (double)a,
d1 = (double)b;
isDefault = d0.FuzzyEquals(d1);
}
else if (b != null)
{
isDefault = b.Equals(a);
}
else if (a == b)
{
isDefault = true;
}
if (!isDefault)
{
XmlNode propNode = WriteProperty(prop, doc, file);
if (propNode == null)
@ -155,6 +191,7 @@ namespace RobloxFiles.XmlFormat
propsNode.AppendChild(propNode);
}
}
foreach (Instance child in instance.GetChildren())
{

View File

@ -18,7 +18,10 @@ namespace RobloxFiles.XmlFormat.PropertyTokens
public void WriteProperty(Property prop, XmlDocument doc, XmlNode node)
{
var value = prop.CastValue<SharedString>();
var value = prop.Value as SharedString;
if (value != null)
{
string key = value.Key;
if (value.ComputedKey == null)
@ -31,3 +34,4 @@ namespace RobloxFiles.XmlFormat.PropertyTokens
}
}
}
}

View File

@ -20,6 +20,7 @@ namespace RobloxFiles
private Dictionary<string, string> RawMetadata = new Dictionary<string, string>();
public Dictionary<string, string> Metadata => RawMetadata;
internal int RefCounter = 0;
public XmlRobloxFile()
{
@ -126,6 +127,7 @@ namespace RobloxFiles
roblox.SetAttribute("version", "4");
doc.AppendChild(roblox);
RefCounter = 0;
Instances.Clear();
SharedStrings.Clear();

View File

@ -4,5 +4,6 @@
<package id="Fody" version="6.2.0" targetFramework="net472" developmentDependency="true" />
<package id="Konscious.Security.Cryptography.Blake2" version="1.0.9" targetFramework="net472" />
<package id="lz4net" version="1.0.15.93" targetFramework="net452" />
<package id="Newtonsoft.Json" version="12.0.3" targetFramework="net472" />
<package id="System.Numerics.Vectors" version="4.5.0" targetFramework="net472" />
</packages>