Large scale refactor to add class support!

Instance classes are now strongly typed with real property fields that
are derived from the JSON API Dump! This required a lot of reworking
across the board:

- Classes and Enums are auto-generated in the 'Generated' folder now.
This is done using a custom built-in plugin, which can be found in
the Plugins folder of this project.
- Property objects are now tied to .NET's reflection system. Reading
and writing from them will try to redirect into a field of the
Instance they are bound to.
- Property types that were loosely defined now have proper data types
(such as Color3uint8, Content, ProtectedString, SharedString, etc)
- Fixed an error with the CFrame directional vectors.
- The binary PRNT chunk now writes instances in child->parent order.
- Enums are now generated correctly, with up-to-date values.
- INST chunks are now referred to as 'Classes' instead of 'Types'.
- Unary operator added to Vector2 and Vector3.
- CollectionService tags can now be manipulated per-instance using
the Instance.Tags member.
- The Instance.Archivable property now works correctly.
- XML files now save/load metadata correctly.
- Cleaned up the property tokens directory.

I probably missed a few things, but that's a general overview of
everything that changed.
This commit is contained in:
CloneTrooper1019
2019-06-30 17:01:19 -05:00
parent 8e01f33d6b
commit de8df15d3f
67 changed files with 6297 additions and 667 deletions

View File

@ -0,0 +1,607 @@
local HttpService = game:GetService("HttpService")
local ServerStorage = game:GetService("ServerStorage")
local StarterPlayer = game:GetService("StarterPlayer")
local StudioService = game:GetService("StudioService")
local classes = {}
local outStream = ""
local stackLevel = 0
local singletons =
{
Terrain = workspace:WaitForChild("Terrain");
StarterPlayerScripts = StarterPlayer:WaitForChild("StarterPlayerScripts");
StarterCharacterScripts = StarterPlayer:WaitForChild("StarterCharacterScripts");
}
local isCoreScript = pcall(function ()
local restricted = game:GetService("RobloxPluginGuiService")
return tostring(restricted)
end)
local function write(formatString, ...)
local tabs = string.rep(' ', stackLevel * 4)
local fmt = formatString or ""
local value = tabs .. fmt:format(...)
outStream = outStream .. value
end
local function writeLine(formatString, ...)
if not formatString then
outStream = outStream .. '\n'
return
end
write(formatString .. '\n', ...)
end
local function openStack()
writeLine('{')
stackLevel = stackLevel + 1
end
local function closeStack()
stackLevel = stackLevel - 1
writeLine('}')
end
local function clearStream()
stackLevel = 0
outStream = ""
end
local function exportStream(label)
local results = outStream:gsub("\n\n\n", "\n\n")
if plugin then
local export = Instance.new("Script")
export.Archivable = false
export.Source = results
export.Name = label
plugin:OpenScript(export)
end
if isCoreScript then
StudioService:CopyToClipboard(results)
elseif not plugin then
warn(label)
print(results)
end
end
local function getTags(object)
local tags = {}
if object.Tags ~= nil then
for _,tag in pairs(object.Tags) do
tags[tag] = true
end
end
if object.Name == "Terrain" then
tags.NotCreatable = nil
end
return tags
end
local function upcastInheritance(class, root)
local superClass = classes[class.Superclass]
if not superClass then
return
end
if not root then
root = class
end
if not superClass.Inherited then
superClass.Inherited = root
end
upcastInheritance(superClass, root)
end
local function canCreateClass(class)
local tags = getTags(class)
local canCreate = true
if tags.NotCreatable then
canCreate = false
end
if tags.Service then
canCreate = true
end
if tags.Settings then
canCreate = false
end
if singletons[class.Name] then
canCreate = true
end
return canCreate
end
local function collectProperties(class)
local propMap = {}
for _,member in ipairs(class.Members) do
if member.MemberType == "Property" then
local propName = member.Name
propMap[propName] = member
end
end
return propMap
end
local function createProperty(propName, propType)
local category = "DataType";
local name = propType
if propType:find(':') then
local data = string.split(propType, ':')
category = data[1]
name = data[2]
end
return
{
Name = propName;
Serialization =
{
CanSave = true;
CanLoad = true;
};
ValueType =
{
Category = category;
Name = name;
};
Security = "None";
}
end
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- Formatting
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
local formatting = require(script.Parent.Formatting)
local formatLinks =
{
["int"] = "Int";
["nil"] = "Null";
["long"] = "Int";
["float"] = "Float";
["byte[]"] = "Bytes";
["double"] = "Double";
["string"] = "String";
["Content"] = "String";
["Instance"] = "Null";
["Color3uint8"] = "Color3";
["ProtectedString"] = "String";
}
local function getFormatFunction(valueType)
if not formatting[valueType] then
valueType = formatLinks[valueType]
end
return formatting[valueType]
end
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- Property Patches
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
local patches = require(script.Parent.PropertyPatches)
local patchIndex = {}
function patchIndex:__index(key)
if not rawget(self, key) then
rawset(self, key, {})
end
return self[key]
end
local function getPatches(className)
local classPatches = patches[className]
return setmetatable(classPatches, patchIndex)
end
setmetatable(patches, patchIndex)
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- Main
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
local baseUrl = "https://raw.githubusercontent.com/CloneTrooper1019/Roblox-Client-Tracker/roblox/"
local toolbar, classButton, enumButton
if plugin then
toolbar = plugin:CreateToolbar("C# API Dump")
classButton = toolbar:CreateButton(
"Dump Classes",
"Generates a C# dump of Roblox's Class API.",
"rbxasset://textures/Icon_Stream_Off@2x.png"
)
enumButton = toolbar:CreateButton(
"Dump Enums",
"Generates a C# dump of Roblox's Enum API.",
"rbxasset://textures/Icon_Stream_Off@2x.png"
)
end
local function getAsync(url)
local enabled
if isCoreScript then
enabled = HttpService:GetHttpEnabled()
HttpService:SetHttpEnabled(true)
end
local result = HttpService:GetAsync(url)
if isCoreScript then
HttpService:SetHttpEnabled(enabled)
end
return result
end
local function generateClasses()
local version = getAsync(baseUrl .. "version.txt")
local apiDump = getAsync(baseUrl .. "API-Dump.json")
apiDump = HttpService:JSONDecode(apiDump)
local classNames = {}
classes = {}
for _,class in ipairs(apiDump.Classes) do
local className = class.Name
local superClass = classes[class.Superclass]
if singletons[className] then
class.Singleton = true
class.Object = singletons[className]
end
if superClass and canCreateClass(class) then
local classTags = getTags(class)
if classTags.Service then
pcall(function ()
if not className:find("Network") then
class.Object = game:GetService(className)
end
end)
elseif not classTags.NotCreatable then
pcall(function ()
class.Object = Instance.new(className)
if ServerStorage:FindFirstChild("DumpFolder") then
class.Object.Name = className
class.Object.Parent = ServerStorage.DumpFolder
end
end)
end
upcastInheritance(class)
end
classes[className] = class
table.insert(classNames, className)
end
outStream = ""
writeLine("// Auto-generated list of creatable Roblox classes.")
writeLine("// Updated as of %s", version)
writeLine()
writeLine("using System;")
writeLine()
writeLine("using RobloxFiles.DataTypes;")
writeLine("using RobloxFiles.Enums;")
writeLine("using RobloxFiles.Utility;")
writeLine()
writeLine("namespace RobloxFiles")
openStack()
for i,className in ipairs(classNames) do
local class = classes[className]
local classTags = getTags(class)
local registerClass = canCreateClass(class)
if class.Inherited then
registerClass = true
end
if class.Name == "Instance" or class.Name == "Studio" then
registerClass = false
end
local object = class.Object
if not object then
if class.Inherited then
object = class.Inherited.Object
elseif singletons[className] then
object = singletons[className]
else
registerClass = false
end
end
if registerClass then
local objectType
if classTags.NotCreatable and class.Inherited and not class.Singleton then
objectType = "abstract class"
else
objectType = "class"
end
writeLine("public %s %s : %s", objectType, className, class.Superclass)
openStack()
local classPatches = getPatches(className)
local redirectProps = classPatches.Redirect
local propMap = collectProperties(class)
local propNames = {}
for _,propName in pairs(classPatches.Remove) do
propMap[propName] = nil
end
for propName in pairs(propMap) do
table.insert(propNames, propName)
end
for propName, propType in pairs(classPatches.Add) do
if not propMap[propName] then
propMap[propName] = createProperty(propName, propType)
table.insert(propNames, propName)
else
propMap[propName].Serialization.CanLoad = true
end
end
local firstLine = true
table.sort(propNames)
if classTags.Service then
writeLine("public %s()", className)
openStack()
writeLine("IsService = true;")
closeStack()
if #propNames > 0 then
writeLine()
end
end
for i, propName in ipairs(propNames) do
local prop = propMap[propName]
local serial = prop.Serialization
local valueType = prop.ValueType.Name
if serial.CanLoad then
local propTags = getTags(prop)
local redirect = redirectProps[propName]
local name = propName
local default = ""
if propName == className then
name = name .. '_'
end
if valueType == "int64" then
valueType = "long"
elseif valueType == "BinaryString" then
valueType = "byte[]"
end
local first = name:sub(1, 1)
if first == first:lower() then
local pascal = first:upper() .. name:sub(2)
if propMap[pascal] ~= nil and propTags.Deprecated then
redirect = pascal
end
end
if redirect then
local get, set
if typeof(redirect) == "string" then
get = redirect
set = redirect .. " = value"
else
get = redirect.Get
set = redirect.Set
end
if not firstLine then
writeLine()
end
if propTags.Deprecated then
writeLine("[Obsolete]")
end
writeLine("public %s %s", valueType, name)
openStack()
writeLine("get { return %s; }", get)
writeLine("set { %s; }", set)
closeStack()
if (i ~= #propNames) then
writeLine()
end
else
local value = classPatches.Defaults[propName]
local gotValue = (value ~= nil)
if not gotValue then
gotValue, value = pcall(function ()
return object[propName]
end)
end
local comment = " // Default missing!"
local category = prop.ValueType.Category
if gotValue then
local category = prop.ValueType.Category
local formatFunc = getFormatFunction(valueType)
if not formatFunc then
local literal = typeof(value)
formatFunc = getFormatFunction(literal)
end
if not formatFunc then
formatFunc = tostring
end
local result
if typeof(formatFunc) == "string" then
result = formatFunc
else
result = formatFunc(value)
end
if not serial.CanSave and not propTags.Deprecated then
comment = " // [Load-only]"
else
comment = ""
end
default = " = " .. result
end
if propTags.Deprecated then
if not firstLine then
writeLine()
end
writeLine("[Obsolete]")
end
if category == "Class" then
default = " = null"
comment = ""
end
writeLine("public %s %s%s;%s", valueType, name, default, comment)
if propTags.Deprecated and i ~= #propNames then
writeLine()
end
end
firstLine = false
end
end
closeStack()
if (i ~= #classNames) then
writeLine()
end
end
end
closeStack()
exportStream("Classes")
end
local function generateEnums()
local version = getfenv().version():gsub("%. ", ".")
clearStream()
writeLine("// Auto-generated list of Roblox enums.")
writeLine("// Updated as of %s", version)
writeLine()
writeLine("namespace RobloxFiles.Enums")
openStack()
local enums = Enum:GetEnums()
for i, enum in ipairs(enums) do
writeLine("public enum %s", tostring(enum))
openStack()
local enumItems = enum:GetEnumItems()
local lastValue = -1
table.sort(enumItems, function (a, b)
return a.Value < b.Value
end)
for i, enumItem in ipairs(enumItems) do
local text = ""
local comma = ','
local name = enumItem.Name
local value = enumItem.Value
if (value - lastValue) ~= 1 then
text = " = " .. value;
end
if i == #enumItems then
comma = ""
end
lastValue = value
writeLine("%s%s%s", name, text, comma)
end
closeStack()
if i ~= #enums then
writeLine()
end
end
closeStack()
exportStream("Enums")
end
if plugin then
classButton.Click:Connect(generateClasses)
enumButton.Click:Connect(generateEnums)
else
generateClasses()
generateEnums()
end

View File

@ -0,0 +1,273 @@
local Format = {}
function Format.Null(value)
return "null"
end
function Format.Bytes(value)
if #value > 0 then
local fmt = "Convert.FromBase64String(%q)"
return fmt:format(value)
else
return "new byte[0]"
end
end
function Format.String(value)
return string.format("%q", value)
end
function Format.Int(value)
return string.format("%i", value)
end
function Format.Number(value)
local int = math.floor(value)
if math.abs(value - int) < 0.001 then
return Format.Int(int)
end
local result = string.format("%.5f", value)
result = result:gsub("%.?0+$", "")
return result
end
function Format.Double(value)
local result = Format.Number(value)
if result == "inf" then
return "double.MaxValue"
elseif result == "-inf" then
return "double.MinValue"
else
return result
end
end
function Format.Float(value)
local result = Format.Number(value)
if result == "inf" then
return "float.MaxValue"
elseif result == "-inf" then
return "float.MinValue"
else
if result:find("%.") then
result = result .. 'f'
end
return result
end
end
function Format.Flags(flag, enum)
local value = 0
for _,item in pairs(enum:GetEnumItems()) do
if flag[item.Name] then
value = value + (2 ^ item.Value)
end
end
return value
end
function Format.Axes(axes)
return "(Axes)" .. Format.Flags(axes, Enum.Axis)
end
function Format.Faces(faces)
return "(Faces)" .. Format.Flags(faces, Enum.NormalId)
end
function Format.EnumItem(item)
local enum = tostring(item.EnumType)
return enum .. '.' .. item.Name
end
function Format.BrickColor(brickColor)
local fmt = "BrickColor.FromNumber(%i)"
return fmt:format(brickColor.Number)
end
function Format.Color3(color)
if color == Color3.new() then
return "new Color3()"
end
local r = Format.Float(color.r)
local g = Format.Float(color.g)
local b = Format.Float(color.b)
local fmt = "%s(%s, %s, %s)";
local constructor = "new Color3";
if string.find(r .. g .. b, 'f') then
r = Format.Int(color.r * 255)
g = Format.Int(color.g * 255)
b = Format.Int(color.b * 255)
constructor = "Color3.FromRGB"
end
return fmt:format(constructor, r, g, b)
end
function Format.UDim(udim)
if udim == UDim.new() then
return "new UDim()"
end
local scale = Format.Float(udim.Scale)
local offset = Format.Int(udim.Offset)
local fmt = "new UDim(%s, %s)"
return fmt:format(scale, offset)
end
function Format.UDim2(udim2)
if udim2 == UDim2.new() then
return "new UDim2()"
end
local xScale = Format.Float(udim2.X.Scale)
local yScale = Format.Float(udim2.Y.Scale)
local xOffset = Format.Int(udim2.X.Offset)
local yOffset = Format.Int(udim2.Y.Offset)
local fmt = "new UDim2(%s, %s, %s, %s)"
return fmt:format(xScale, xOffset, yScale, yOffset)
end
function Format.Vector2(v2)
if v2.Magnitude < 0.001 then
return "new Vector2()"
end
local x = Format.Float(v2.X)
local y = Format.Float(v2.Y)
local fmt = "new Vector2(%s, %s)"
return fmt:format(x, y)
end
function Format.Vector3(v3)
if v3.Magnitude < 0.001 then
return "new Vector3()"
end
local x = Format.Float(v3.X)
local y = Format.Float(v3.Y)
local z = Format.Float(v3.Z)
local fmt = "new Vector3(%s, %s, %s)"
return fmt:format(x, y, z)
end
function Format.CFrame(cf)
local blankCF = CFrame.new()
if cf == blankCF then
return "new CFrame()"
end
local rot = cf - cf.p
if rot == blankCF then
local fmt = "new CFrame(%s, %s, %s)"
local x = Format.Float(cf.X)
local y = Format.Float(cf.Y)
local z = Format.Float(cf.Z)
return fmt:format(x, y, z)
else
local comp = { cf:GetComponents() }
for i = 1,12 do
comp[i] = Format.Float(comp[i])
end
local fmt = "new CFrame(%s)"
local matrix = table.concat(comp, ", ")
return fmt:format(matrix)
end
end
function Format.NumberRange(nr)
local min = nr.Min
local max = nr.Max
local fmt = "new NumberRange(%s)"
local value = Format.Float(min)
if min ~= max then
value = value .. ", " .. Format.Float(max)
end
return fmt:format(value)
end
function Format.Ray(ray)
if ray == Ray.new() then
return "new Ray()"
end
local fmt = "new Ray(%s, %s)"
local origin = Format.Vector3(ray.Origin)
local direction = Format.Vector3(ray.Direction)
return fmt:format(origin, direction)
end
function Format.Rect(rect)
local fmt = "new Rect(%s, %s)"
local min = Format.Vector2(rect.Min)
local max = Format.Vector2(rect.Max)
return fmt:format(min, max)
end
function Format.ColorSequence(cs)
local csKey = cs.Keypoints[1]
local fmt = "new ColorSequence(%s)"
local value = Format.Color3(csKey.Value)
return fmt:format(value)
end
function Format.NumberSequence(ns)
local nsKey = ns.Keypoints[1]
local fmt = "new NumberSequence(%s)"
local value = Format.Float(nsKey.Value)
return fmt:format(value)
end
function Format.Vector3int16(v3)
if v3 == Vector3int16.new() then
return "new Vector3int16()"
end
local x = Format.Int(v3.X)
local y = Format.Int(v3.Y)
local z = Format.Int(v3.Z)
local fmt = "new Vector3int16(%s, %s, %s)"
return fmt:format(x, y, z)
end
function Format.SharedString(str)
local fmt = "SharedString.FromBase64(%q)"
return fmt:format(str)
end
return Format

View File

@ -0,0 +1,674 @@
local function UseColor3(propName)
return
{
Get = "BrickColor.FromColor3(" .. propName .. ')';
Set = propName .. " = value.Color";
}
end
local GuiTextMixIn =
{
Redirect =
{
FontSize =
{
Get = "FontUtility.GetFontSize(TextSize)";
Set = "TextSize = FontUtility.GetFontSize(value)";
};
TextColor = UseColor3("TextColor3");
TextWrap = "TextWrapped";
};
}
return
{
Accoutrement =
{
Remove =
{
"AttachmentUp";
"AttachmentPos";
"AttachmentRight";
"AttachmentForward";
};
};
AnalyticsService =
{
Defaults = { ApiKey = "" }
};
Attachment =
{
Remove =
{
"Axis";
"Orientation";
"Position";
"SecondaryAxis";
"WorldAxis";
"WorldCFrame";
"WorldOrientation";
"WorldPosition";
"WorldSecondaryAxis";
};
};
BasePart =
{
Add =
{
Color3uint8 = "Color3uint8";
size = "Vector3";
};
Redirect =
{
Position = "CFrame.Position";
BrickColor = UseColor3("Color");
Color = "Color3uint8";
Size = "size";
};
Defaults =
{
Color3uint8 = Color3.fromRGB(163, 162, 165);
size = Vector3.new(4, 1.2, 2);
};
Remove =
{
"Orientation";
"Rotation";
}
};
BinaryStringValue =
{
Add =
{
Value = "BinaryString";
};
Defaults =
{
Value = "";
};
};
BodyColors =
{
Redirect =
{
HeadColor = UseColor3("HeadColor3");
LeftArmColor = UseColor3("LeftArmColor3");
RightArmColor = UseColor3("RightArmColor3");
LeftLegColor = UseColor3("LeftLegColor3");
RightLegColor = UseColor3("RightLegColor3");
TorsoColor = UseColor3("TorsoColor3");
}
};
BodyAngularVelocity =
{
Redirect = { angularvelocity = "AngularVelocity" };
};
BodyGyro =
{
Redirect = { cframe = "CFrame" };
};
Camera =
{
Redirect = { CoordinateFrame = "CFrame" }
};
DataModelMesh =
{
Add =
{
LODX = "Enum:LevelOfDetailSetting";
LODY = "Enum:LevelOfDetailSetting";
};
Defaults =
{
LODX = Enum.LevelOfDetailSetting.High;
LODY = Enum.LevelOfDetailSetting.High;
};
};
DataStoreService =
{
Defaults =
{
AutomaticRetry = true;
LegacyNamingScheme = false;
}
};
DebuggerWatch =
{
Defaults = { Expression = "" };
};
DoubleConstrainedValue =
{
Redirect = { ConstrainedValue = "Value" }
};
Fire =
{
Add =
{
heat_xml = "float";
size_xml = "float";
};
Defaults =
{
heat_xml = 9;
size_xml = 5;
};
Redirect =
{
Heat = "heat_xml";
Size = "size_xml";
};
};
FormFactorPart =
{
Add =
{
formFactorRaw = "Enum:FormFactor";
};
Defaults =
{
formFactorRaw = Enum.FormFactor.Brick;
};
Redirect =
{
FormFactor = "formFactorRaw";
};
};
GuiBase2d =
{
Redirect = { Localize = "AutoLocalize" }
};
GuiBase3d =
{
Redirect = { Color = UseColor3("Color3") }
};
GuiObject =
{
Redirect =
{
BackgroundColor = UseColor3("BackgroundColor3");
BorderColor = UseColor3("BorderColor3");
Transparency = "BackgroundTransparency";
}
};
HttpService =
{
Defaults = { HttpEnabled = false }
};
Humanoid =
{
Add =
{
Health_XML = "float";
InternalHeadScale = "float";
InternalBodyScale = "Vector3";
};
Defaults =
{
Health_XML = 100;
InternalHeadScale = 1;
InternalBodyScale = Vector3.new(1, 1, 1);
};
Redirect =
{
Health = "Health_XML";
};
Remove =
{
"Jump";
"Torso";
"LeftLeg";
"RightLeg";
};
};
HumanoidDescription =
{
Add =
{
EmotesDataInternal = "string";
EquippedEmotesDataInternal = "string";
};
Defaults =
{
EmotesDataInternal = "";
EquippedEmotesDataInternal = "";
};
};
InsertService =
{
Add = { AllowClientInsertModels = "bool" };
Defaults = { AllowClientInsertModels = false };
};
IntConstrainedValue =
{
Redirect = { ConstrainedValue = "Value" }
};
JointInstance =
{
Add = { IsAutoJoint = "bool" };
Defaults = { IsAutoJoint = true };
};
Lighting =
{
Add =
{
Technology = "Enum:Technology";
};
Defaults =
{
LegacyOutlines = false;
Technology = Enum.Technology.Compatibility;
};
Redirect =
{
Outlines = "LegacyOutlines";
};
Remove =
{
"ClockTime";
};
};
LocalizationService =
{
Remove =
{
"ForcePlayModeGameLocaleId";
"ForcePlayModeRobloxLocaleId";
"RobloxForcePlayModeGameLocaleId";
"RobloxForcePlayModeRobloxLocaleId";
}
};
LocalizationTable =
{
Add = { Contents = "string" };
Defaults = { Contents = "[]" };
Redirect =
{
DevelopmentLanguage = "SourceLocaleId";
}
};
ManualSurfaceJointInstance =
{
Add =
{
Surface0 = "int";
Surface1 = "int";
};
Defaults =
{
Surface0 = -1;
Surface1 = -1;
}
};
MeshPart =
{
Redirect = { MeshID = "MeshId" }
};
Model =
{
Add = { ModelInPrimary = "CFrame" };
Defaults = { ModelInPrimary = CFrame.new() };
};
NotificationService =
{
Remove = {"SelectedTheme"}
};
Part =
{
Add = { shape = "Enum:PartType" };
Redirect = { Shape = "shape" };
};
ParticleEmitter =
{
Redirect =
{
VelocitySpread =
{
Get = "SpreadAngle.X";
Set = "SpreadAngle = new Vector2(value, value)";
}
}
};
PartOperation =
{
Add =
{
AssetId = "Content";
ChildData = "BinaryString";
MeshData = "BinaryString";
};
Defaults =
{
AssetId = "";
ChildData = "";
MeshData = "";
};
};
PartOperationAsset =
{
Add =
{
ChildData = "BinaryString";
MeshData = "BinaryString";
};
Defaults =
{
ChildData = "";
MeshData = "";
};
};
Players =
{
Defaults =
{
MaxPlayersInternal = 16;
PreferredPlayersInternal = 0;
}
};
RenderingTest =
{
Remove =
{
"Position";
"Orientation";
};
};
ScriptContext =
{
Remove = { "ScriptsDisabled" }
};
SelectionBox =
{
Redirect = { SurfaceColor = UseColor3("SurfaceColor3") }
};
SelectionSphere =
{
Redirect = { SurfaceColor = UseColor3("SurfaceColor3") }
};
ServerScriptService =
{
Defaults = { LoadStringEnabled = false }
};
Smoke =
{
Add =
{
size_xml = "float";
opacity_xml = "float";
riseVelocity_xml = "float";
};
Defaults =
{
size_xml = 1;
opacity_xml = 0.5;
riseVelocity_xml = 1;
};
Redirect =
{
Size = "size_xml";
Opacity = "opacity_xml";
RiseVelocity = "riseVelocity_xml";
};
};
Sound =
{
Add =
{
MaxDistance = "float"; -- ?!
xmlRead_MaxDistance_3 = "float";
xmlRead_MinDistance_3 = "float";
};
Defaults =
{
xmlRead_MinDistance_3 = 10;
xmlRead_MaxDistance_3 = 10000;
};
Redirect =
{
EmitterSize = "xmlRead_MinDistance_3";
MaxDistance = "xmlRead_MaxDistance_3";
MinDistance = "EmitterSize";
Pitch = "PlaybackSpeed";
};
};
Sparkles =
{
Redirect = { Color = "SparkleColor" };
};
StudioData =
{
Defaults =
{
SrcPlaceId = 0;
SrcUniverseId = 0;
};
};
TextBox = GuiTextMixIn;
TextLabel = GuiTextMixIn;
TextButton = GuiTextMixIn;
Terrain =
{
Add =
{
ClusterGrid = "string";
ClusterGridV2 = "string";
ClusterGridV3 = "BinaryString";
SmoothGrid = "BinaryString";
PhysicsGrid = "BinaryString";
};
Defaults =
{
ClusterGrid = "";
ClusterGridV2 = "";
ClusterGridV3 = "";
SmoothGrid = "AQU=";
PhysicsGrid = "AgMAAAAAAAAAAAAAAAA=";
MaterialColors = "AAAAAAAAan8/P39rf2Y/ilY+j35fi21PZmxvZbDqw8faiVpHOi4kHh4lZlw76JxKc3trhHtagcLgc4RKxr21zq2UlJSM";
};
};
TerrainRegion =
{
Add =
{
ExtentsMax = "Vector3int16";
ExtentsMin = "Vector3int16";
GridV3 = "BinaryString";
SmoothGrid = "BinaryString";
};
Defaults =
{
ExtentsMax = Vector3int16.new();
ExtentsMin = Vector3int16.new();
GridV3 = "";
SmoothGrid = "AQU=";
};
};
Tool =
{
Remove =
{
"GripForward";
"GripPos";
"GripRight";
"GripUp";
};
};
TriangleMeshPart =
{
Add =
{
InitialSize = "Vector3";
LODData = "BinaryString";
PhysicsData = "BinaryString";
PhysicalConfigData = "SharedString";
};
Defaults =
{
LODData = "";
PhysicsData = "";
InitialSize = Vector3.new(1, 1, 1);
PhysicalConfigData = "1B2M2Y8AsgTpgAmY7PhCfg==";
};
};
TrussPart =
{
Add = { style = "Enum:Style" };
Redirect = { Style = "style" };
};
ViewportFrame =
{
Add =
{
CameraCFrame = "CFrame";
CameraFieldOfView = "float";
};
Defaults =
{
CameraCFrame = CFrame.new();
CameraFieldOfView = 70;
};
Remove = {"CurrentCamera"};
};
WeldConstraint =
{
Add =
{
Part0Internal = "Class:BasePart";
Part1Internal = "Class:BasePart";
CFrame0 = "CFrame";
CFrame1 = "CFrame";
};
Defaults =
{
CFrame0 = CFrame.new();
CFrame1 = CFrame.new();
Part0 = Instance.new("Part");
Part1 = Instance.new("Part");
};
Redirect =
{
Part0 = "Part0Internal";
Part1 = "Part1Internal";
};
};
Workspace =
{
Add =
{
AutoJointsMode = "Enum:AutoJointsMode";
CollisionGroups = "string";
ExplicitAutoJoints = "bool";
StreamingMinRadius = "int";
StreamingTargetRadius = "int";
StreamingPauseMode = "Enum:StreamingPauseMode";
TerrainWeldsFixed = "bool";
};
Defaults =
{
AutoJointsMode = Enum.AutoJointsMode.Default;
CollisionGroups = "Default^0^1";
ExplicitAutoJoints = true;
StreamingMinRadius = 64;
StreamingTargetRadius = 1024;
StreamingPauseMode = Enum.StreamingPauseMode.Default;
TerrainWeldsFixed = true;
}
}
}