0.454.0.413308

This commit is contained in:
CloneTrooper1019 2020-10-30 15:07:11 -05:00
parent c4a3145007
commit 988469ac04
13 changed files with 1063 additions and 222 deletions

View File

@ -28,6 +28,17 @@ namespace RobloxFiles.BinaryFormat.Chunks
NumInstances = reader.ReadInt32(); NumInstances = reader.ReadInt32();
InstanceIds = reader.ReadInstanceIds(NumInstances); InstanceIds = reader.ReadInstanceIds(NumInstances);
Type instType = Type.GetType($"RobloxFiles.{ClassName}");
file.Classes[ClassIndex] = this;
if (instType == null)
{
if (RobloxFile.LogErrors)
Console.Error.WriteLine($"INST - Unknown class: {ClassName} while reading INST chunk.");
return;
}
if (IsService) if (IsService)
{ {
RootedServices = new List<bool>(); RootedServices = new List<bool>();
@ -42,7 +53,6 @@ namespace RobloxFiles.BinaryFormat.Chunks
for (int i = 0; i < NumInstances; i++) for (int i = 0; i < NumInstances; i++)
{ {
int instId = InstanceIds[i]; int instId = InstanceIds[i];
Type instType = Type.GetType($"RobloxFiles.{ClassName}") ?? typeof(Instance);
var inst = Activator.CreateInstance(instType) as Instance; var inst = Activator.CreateInstance(instType) as Instance;
inst.Referent = instId.ToString(); inst.Referent = instId.ToString();
@ -56,8 +66,6 @@ namespace RobloxFiles.BinaryFormat.Chunks
file.Instances[instId] = inst; file.Instances[instId] = inst;
} }
file.Classes[ClassIndex] = this;
} }
public void Save(BinaryRobloxFileWriter writer) public void Save(BinaryRobloxFileWriter writer)

View File

@ -29,6 +29,24 @@ namespace RobloxFiles.BinaryFormat.Chunks
int parentId = parentIds[i]; int parentId = parentIds[i];
Instance child = file.Instances[childId]; Instance child = file.Instances[childId];
Instance parent = (parentId >= 0 ? file.Instances[parentId] : file);
if (child == null)
{
if (RobloxFile.LogErrors)
Console.Error.WriteLine($"PRNT: could not parent {childId} to {parentId} because child {childId} was null.");
continue;
}
if (parentId >= 0 && parent == null)
{
if (RobloxFile.LogErrors)
Console.Error.WriteLine($"PRNT: could not parent {childId} to {parentId} because parent {parentId} was null.");
continue;
}
child.Parent = (parentId >= 0 ? file.Instances[parentId] : file); child.Parent = (parentId >= 0 ? file.Instances[parentId] : file);
} }
} }

View File

@ -56,6 +56,14 @@ namespace RobloxFiles.BinaryFormat.Chunks
int id = ids[i]; int id = ids[i];
Instance instance = file.Instances[id]; Instance instance = file.Instances[id];
if (instance == null)
{
if (RobloxFile.LogErrors)
Console.Error.WriteLine($"PROP: No instance @{id} for property {ClassName}.{Name}");
continue;
}
Property prop = new Property(instance, this); Property prop = new Property(instance, this);
props[i] = prop; props[i] = prop;
@ -71,6 +79,10 @@ namespace RobloxFiles.BinaryFormat.Chunks
for (int i = 0; i < instCount; i++) for (int i = 0; i < instCount; i++)
{ {
var prop = props[i]; var prop = props[i];
if (prop == null)
continue;
prop.Value = read(i); prop.Value = read(i);
} }
}); });
@ -593,9 +605,9 @@ namespace RobloxFiles.BinaryFormat.Chunks
foreach (int instId in inst.InstanceIds) foreach (int instId in inst.InstanceIds)
{ {
Instance instance = file.Instances[instId]; Instance instance = file.Instances[instId];
Property prop = instance.Properties[Name]; var instProps = instance.Properties;
if (prop == null) if (!instProps.TryGetValue(Name, out Property prop))
throw new Exception($"Property {Name} must be defined in {instance.GetFullName()}!"); throw new Exception($"Property {Name} must be defined in {instance.GetFullName()}!");
else if (prop.Type != Type) else if (prop.Type != Type)
throw new Exception($"Property {Name} is not using the correct type in {instance.GetFullName()}!"); throw new Exception($"Property {Name} is not using the correct type in {instance.GetFullName()}!");

View File

@ -1,5 +1,5 @@
// Auto-generated list of creatable Roblox classes. // Auto-generated list of creatable Roblox classes.
// Updated as of 0.450.0.411923 // Updated as of 0.454.0.413308
using System; using System;
@ -410,13 +410,11 @@ namespace RobloxFiles
set => CFrame = value; set => CFrame = value;
} }
public float DiagonalFieldOfView;
public float FieldOfView = 70; public float FieldOfView = 70;
public FieldOfViewMode FieldOfViewMode = FieldOfViewMode.Vertical; public FieldOfViewMode FieldOfViewMode = FieldOfViewMode.Vertical;
public CFrame Focus = new CFrame(0, 0, -5); public CFrame Focus = new CFrame(0, 0, -5);
public bool HeadLocked = true; public bool HeadLocked = true;
public float HeadScale = 1; public float HeadScale = 1;
public float MaxAxisFieldOfView;
[Obsolete] [Obsolete]
public CFrame focus public CFrame focus
@ -1471,6 +1469,7 @@ namespace RobloxFiles
public abstract class HandleAdornment : PVAdornment public abstract class HandleAdornment : PVAdornment
{ {
public AdornCullingMode AdornCullingMode = AdornCullingMode.Automatic;
public bool AlwaysOnTop; public bool AlwaysOnTop;
public CFrame CFrame = new CFrame(); public CFrame CFrame = new CFrame();
public Vector3 SizeRelativeOffset = new Vector3(); public Vector3 SizeRelativeOffset = new Vector3();
@ -1693,6 +1692,22 @@ namespace RobloxFiles
public float WidthScale = 1; public float WidthScale = 1;
} }
public abstract class ILegacyStudioBridge : Instance
{
public ILegacyStudioBridge()
{
IsService = true;
}
}
public class LegacyStudioBridge : ILegacyStudioBridge
{
public LegacyStudioBridge()
{
IsService = true;
}
}
public class InsertService : Instance public class InsertService : Instance
{ {
public InsertService() public InsertService()
@ -2497,6 +2512,33 @@ namespace RobloxFiles
public float Spread = 1; public float Spread = 1;
} }
public class ProximityPrompt : Instance
{
public string ActionText = "Interact";
public bool ClickablePrompt = true;
public bool Enabled = true;
public ProximityPromptExclusivity Exclusivity = ProximityPromptExclusivity.OnePerButton;
public KeyCode GamepadKeyCode = KeyCode.ButtonX;
public float HoldDuration;
public KeyCode KeyboardKeyCode = KeyCode.E;
public float MaxActivationDistance = 10;
public string ObjectText = "";
public bool RequiresLineOfSight = true;
public ProximityPromptStyle Style = ProximityPromptStyle.Default;
public Vector2 UIOffset = new Vector2();
}
public class ProximityPromptService : Instance
{
public ProximityPromptService()
{
IsService = true;
}
public bool Enabled = true;
public int MaxPromptsVisible = 16;
}
public class RbxAnalyticsService : Instance public class RbxAnalyticsService : Instance
{ {
public RbxAnalyticsService() public RbxAnalyticsService()
@ -3092,6 +3134,14 @@ namespace RobloxFiles
} }
} }
public class TracerService : Instance
{
public TracerService()
{
IsService = true;
}
}
public class Trail : Instance public class Trail : Instance
{ {
public Attachment Attachment0; public Attachment Attachment0;
@ -3434,5 +3484,6 @@ namespace RobloxFiles
} }
public BasePart Part1Internal; public BasePart Part1Internal;
public int State = 3;
} }
} }

View File

@ -1,5 +1,5 @@
// Auto-generated list of Roblox enums. // Auto-generated list of Roblox enums.
// Updated as of 0.450.0.411923 // Updated as of 0.454.0.413308
namespace RobloxFiles.Enums namespace RobloxFiles.Enums
{ {
@ -17,6 +17,12 @@ namespace RobloxFiles.Enums
Servo Servo
} }
public enum AdornCullingMode
{
Automatic,
Never
}
public enum AlignType public enum AlignType
{ {
Parallel, Parallel,
@ -383,6 +389,264 @@ namespace RobloxFiles.Enums
Enabled Enabled
} }
public enum KeyCode
{
Unknown,
Backspace = 8,
Tab,
Clear = 12,
Return,
Pause = 19,
Escape = 27,
Space = 32,
QuotedDouble = 34,
Hash,
Dollar,
Percent,
Ampersand,
Quote,
LeftParenthesis,
RightParenthesis,
Asterisk,
Plus,
Comma,
Minus,
Period,
Slash,
Zero,
One,
Two,
Three,
Four,
Five,
Six,
Seven,
Eight,
Nine,
Colon,
Semicolon,
LessThan,
Equals,
GreaterThan,
Question,
At,
LeftBracket = 91,
BackSlash,
RightBracket,
Caret,
Underscore,
Backquote,
A,
B,
C,
D,
E,
F,
G,
H,
I,
J,
K,
L,
M,
N,
O,
P,
Q,
R,
S,
T,
U,
V,
W,
X,
Y,
Z,
LeftCurly,
Pipe,
RightCurly,
Tilde,
Delete,
World0 = 160,
World1,
World2,
World3,
World4,
World5,
World6,
World7,
World8,
World9,
World10,
World11,
World12,
World13,
World14,
World15,
World16,
World17,
World18,
World19,
World20,
World21,
World22,
World23,
World24,
World25,
World26,
World27,
World28,
World29,
World30,
World31,
World32,
World33,
World34,
World35,
World36,
World37,
World38,
World39,
World40,
World41,
World42,
World43,
World44,
World45,
World46,
World47,
World48,
World49,
World50,
World51,
World52,
World53,
World54,
World55,
World56,
World57,
World58,
World59,
World60,
World61,
World62,
World63,
World64,
World65,
World66,
World67,
World68,
World69,
World70,
World71,
World72,
World73,
World74,
World75,
World76,
World77,
World78,
World79,
World80,
World81,
World82,
World83,
World84,
World85,
World86,
World87,
World88,
World89,
World90,
World91,
World92,
World93,
World94,
World95,
KeypadZero,
KeypadOne,
KeypadTwo,
KeypadThree,
KeypadFour,
KeypadFive,
KeypadSix,
KeypadSeven,
KeypadEight,
KeypadNine,
KeypadPeriod,
KeypadDivide,
KeypadMultiply,
KeypadMinus,
KeypadPlus,
KeypadEnter,
KeypadEquals,
Up,
Down,
Right,
Left,
Insert,
Home,
End,
PageUp,
PageDown,
F1,
F2,
F3,
F4,
F5,
F6,
F7,
F8,
F9,
F10,
F11,
F12,
F13,
F14,
F15,
NumLock = 300,
CapsLock,
ScrollLock,
RightShift,
LeftShift,
RightControl,
LeftControl,
RightAlt,
LeftAlt,
RightMeta,
LeftMeta,
LeftSuper,
RightSuper,
Mode,
Compose,
Help,
Print,
SysReq,
Break,
Menu,
Power,
Euro,
Undo,
ButtonX = 1000,
ButtonY,
ButtonA,
ButtonB,
ButtonR1,
ButtonL1,
ButtonR2,
ButtonL2,
ButtonR3,
ButtonL3,
ButtonStart,
ButtonSelect,
DPadLeft,
DPadRight,
DPadUp,
DPadDown,
Thumbstick1,
Thumbstick2
}
public enum LeftRight public enum LeftRight
{ {
Left, Left,
@ -515,6 +779,19 @@ namespace RobloxFiles.Enums
Bounce Bounce
} }
public enum ProximityPromptExclusivity
{
OnePerButton,
OneGlobally,
AlwaysShow
}
public enum ProximityPromptStyle
{
Default,
Custom
}
public enum R15CollisionType public enum R15CollisionType
{ {
OuterBox, OuterBox,

Binary file not shown.

View File

@ -612,7 +612,9 @@ return
{ {
Part0Internal = "Class:BasePart"; Part0Internal = "Class:BasePart";
Part1Internal = "Class:BasePart"; Part1Internal = "Class:BasePart";
EnabledInternal = "bool"; EnabledInternal = "bool";
State = "int";
CFrame0 = "CFrame"; CFrame0 = "CFrame";
CFrame1 = "CFrame"; CFrame1 = "CFrame";
@ -622,7 +624,9 @@ return
{ {
CFrame0 = CFrame.new(); CFrame0 = CFrame.new();
CFrame1 = CFrame.new(); CFrame1 = CFrame.new();
EnabledInternal = true; EnabledInternal = true;
State = 3;
Part0 = Instance.new("Part"); Part0 = Instance.new("Part");
Part1 = Instance.new("Part"); Part1 = Instance.new("Part");

Binary file not shown.

View File

@ -214,7 +214,7 @@ namespace RobloxFiles
if (!RobloxFile.LogErrors) if (!RobloxFile.LogErrors)
return false; return false;
Console.Error.WriteLine($"RobloxFiles.Property - No defined member for {Instance.ClassName}.{Name}"); Console.Error.WriteLine($"RobloxFiles.Property - Property {Instance.ClassName}.{Name} does not exist!");
} }
} }
} }

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@ -108,6 +108,8 @@ namespace RobloxFiles.UnitTest
[STAThread] [STAThread]
static void Main(string[] args) static void Main(string[] args)
{ {
RobloxFile.LogErrors = true;
if (args.Length > 0) if (args.Length > 0)
{ {
string path = args[0]; string path = args[0];

View File

@ -11,7 +11,7 @@ namespace RobloxFiles.XmlFormat
{ {
var errorHandler = new Func<string, Exception>((message) => var errorHandler = new Func<string, Exception>((message) =>
{ {
string contents = $"XmlRobloxFileReader.{label}: {message}"; string contents = $"{nameof(XmlRobloxFileReader)}.{label} - {message}";
return new Exception(contents); return new Exception(contents);
}); });
@ -20,10 +20,10 @@ namespace RobloxFiles.XmlFormat
public static void ReadSharedStrings(XmlNode sharedStrings, XmlRobloxFile file) public static void ReadSharedStrings(XmlNode sharedStrings, XmlRobloxFile file)
{ {
var error = CreateErrorHandler("ReadSharedStrings"); var error = CreateErrorHandler(nameof(ReadSharedStrings));
if (sharedStrings.Name != "SharedStrings") if (sharedStrings.Name != "SharedStrings")
throw error("Provided XmlNode's class should be 'SharedStrings'!"); throw error("Provided XmlNode's class must be 'SharedStrings'!");
foreach (XmlNode sharedString in sharedStrings) foreach (XmlNode sharedString in sharedStrings)
{ {
@ -41,7 +41,7 @@ namespace RobloxFiles.XmlFormat
var record = SharedString.FromBase64(value); var record = SharedString.FromBase64(value);
if (hash.Length != 16) if (hash.Length != 16)
throw error($"SharedString base64 key '{key}' must decode to byte[16]!"); throw error($"SharedString base64 key '{key}' must align to byte[16]!");
if (key != record.Key) if (key != record.Key)
{ {
@ -56,7 +56,7 @@ namespace RobloxFiles.XmlFormat
public static void ReadMetadata(XmlNode meta, XmlRobloxFile file) public static void ReadMetadata(XmlNode meta, XmlRobloxFile file)
{ {
var error = CreateErrorHandler("ReadMetadata"); var error = CreateErrorHandler(nameof(ReadMetadata));
if (meta.Name != "Meta") if (meta.Name != "Meta")
throw error("Provided XmlNode's class should be 'Meta'!"); throw error("Provided XmlNode's class should be 'Meta'!");
@ -74,7 +74,7 @@ namespace RobloxFiles.XmlFormat
public static void ReadProperties(Instance instance, XmlNode propsNode) public static void ReadProperties(Instance instance, XmlNode propsNode)
{ {
var error = CreateErrorHandler("ReadProperties"); var error = CreateErrorHandler(nameof(ReadProperties));
if (propsNode.Name != "Properties") if (propsNode.Name != "Properties")
throw error("Provided XmlNode's class should be 'Properties'!"); throw error("Provided XmlNode's class should be 'Properties'!");
@ -106,35 +106,48 @@ namespace RobloxFiles.XmlFormat
XmlToken = propType XmlToken = propType
}; };
if (!tokenHandler.ReadProperty(prop, propNode)) if (!tokenHandler.ReadProperty(prop, propNode) && RobloxFile.LogErrors)
if (RobloxFile.LogErrors) {
Console.Error.WriteLine("Could not read property: " + prop.GetFullName() + '!'); var readError = error($"Could not read property: {prop.GetFullName()}!");
Console.Error.WriteLine(readError.Message);
}
instance.AddProperty(ref prop); instance.AddProperty(ref prop);
} }
else if (RobloxFile.LogErrors) else if (RobloxFile.LogErrors)
{ {
Console.Error.WriteLine("No IXmlPropertyToken found for property type: " + propType + '!'); var tokenError = error($"No {nameof(IXmlPropertyToken)} found for property type: {propType}!");
Console.Error.WriteLine(tokenError.Message);
} }
} }
} }
public static Instance ReadInstance(XmlNode instNode, XmlRobloxFile file) public static Instance ReadInstance(XmlNode instNode, XmlRobloxFile file)
{ {
var error = CreateErrorHandler("ReadInstance"); var error = CreateErrorHandler(nameof(ReadInstance));
// Process the instance itself // Process the instance itself
if (instNode.Name != "Item") if (instNode.Name != "Item")
throw error("Provided XmlNode's name should be 'Item'!"); throw error("Provided XmlNode's name should be 'Item'!");
XmlNode classToken = instNode.Attributes.GetNamedItem("class"); XmlNode classToken = instNode.Attributes.GetNamedItem("class");
if (classToken == null) if (classToken == null)
throw error("Got an Item without a defined 'class' attribute!"); throw error("Got an Item without a defined 'class' attribute!");
string className = classToken.InnerText; string className = classToken.InnerText;
Type instType = Type.GetType($"RobloxFiles.{className}");
if (instType == null)
{
if (RobloxFile.LogErrors)
{
var typeError = error($"Unknown class {className} while reading Item.");
Console.Error.WriteLine(typeError.Message);
}
return null;
}
Type instType = Type.GetType($"RobloxFiles.{className}") ?? typeof(Instance);
Instance inst = Activator.CreateInstance(instType) as Instance; Instance inst = Activator.CreateInstance(instType) as Instance;
// The 'referent' attribute is optional, but should be defined if a Ref property needs to link to this Instance. // The 'referent' attribute is optional, but should be defined if a Ref property needs to link to this Instance.
@ -154,14 +167,19 @@ namespace RobloxFiles.XmlFormat
// Process the child nodes of this instance. // Process the child nodes of this instance.
foreach (XmlNode childNode in instNode.ChildNodes) foreach (XmlNode childNode in instNode.ChildNodes)
{ {
if (childNode.Name == "Properties") switch (childNode.Name)
{ {
ReadProperties(inst, childNode); case "Item":
} Instance child = ReadInstance(childNode, file);
else if (childNode.Name == "Item")
{ if (child != null)
Instance child = ReadInstance(childNode, file); child.Parent = inst;
child.Parent = inst;
break;
case "Properties":
ReadProperties(inst, childNode);
break;
default: break;
} }
} }