2019-06-30 22:01:19 +00:00
|
|
|
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 =
|
|
|
|
{
|
2019-12-23 03:23:06 +00:00
|
|
|
Terrain = workspace:WaitForChild("Terrain", 1000);
|
2019-06-30 22:01:19 +00:00
|
|
|
StarterPlayerScripts = StarterPlayer:WaitForChild("StarterPlayerScripts");
|
|
|
|
StarterCharacterScripts = StarterPlayer:WaitForChild("StarterCharacterScripts");
|
|
|
|
}
|
|
|
|
|
2020-06-30 00:06:14 +00:00
|
|
|
local numberTypes =
|
|
|
|
{
|
|
|
|
int = true;
|
|
|
|
long = true;
|
2020-07-06 00:04:20 +00:00
|
|
|
int64 = true;
|
2020-06-30 00:06:14 +00:00
|
|
|
float = true;
|
|
|
|
double = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
local stringTypes =
|
|
|
|
{
|
|
|
|
string = true;
|
|
|
|
Content = true;
|
2020-07-06 00:04:20 +00:00
|
|
|
BinaryString = true;
|
2020-06-30 00:06:14 +00:00
|
|
|
ProtectedString = true;
|
|
|
|
}
|
|
|
|
|
2019-06-30 22:01:19 +00:00
|
|
|
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
|
2020-12-06 22:04:49 +00:00
|
|
|
export.Parent = workspace
|
2019-06-30 22:01:19 +00:00
|
|
|
|
|
|
|
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
|
|
|
|
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
|
2019-12-23 03:23:06 +00:00
|
|
|
local formatting = require(script.Formatting)
|
2019-06-30 22:01:19 +00:00
|
|
|
|
|
|
|
local formatLinks =
|
|
|
|
{
|
|
|
|
["int"] = "Int";
|
|
|
|
["nil"] = "Null";
|
|
|
|
["long"] = "Int";
|
|
|
|
|
2020-08-14 17:35:27 +00:00
|
|
|
["float"] = "Float";
|
|
|
|
["byte[]"] = "Bytes";
|
|
|
|
["double"] = "Double";
|
|
|
|
["boolean"] = "Bool";
|
2019-06-30 22:01:19 +00:00
|
|
|
|
|
|
|
["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
|
|
|
|
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
|
2019-12-23 03:23:06 +00:00
|
|
|
local patches = require(script.PropertyPatches)
|
2019-06-30 22:01:19 +00:00
|
|
|
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/"
|
2020-08-14 17:35:27 +00:00
|
|
|
local toolbar, button
|
2019-06-30 22:01:19 +00:00
|
|
|
|
|
|
|
if plugin then
|
|
|
|
toolbar = plugin:CreateToolbar("C# API Dump")
|
|
|
|
|
2020-08-14 17:35:27 +00:00
|
|
|
button = toolbar:CreateButton(
|
|
|
|
"Dump API",
|
|
|
|
"Generates a C# dump of Roblox's Class/Enum API.",
|
2019-06-30 22:01:19 +00:00
|
|
|
"rbxasset://textures/Icon_Stream_Off@2x.png"
|
|
|
|
)
|
|
|
|
|
2020-08-14 17:35:27 +00:00
|
|
|
button.ClickableWhenViewportHidden = true
|
2019-06-30 22:01:19 +00:00
|
|
|
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()
|
2020-06-30 00:06:14 +00:00
|
|
|
local env = getfenv()
|
2019-06-30 22:01:19 +00:00
|
|
|
local version = getAsync(baseUrl .. "version.txt")
|
|
|
|
|
|
|
|
local apiDump = getAsync(baseUrl .. "API-Dump.json")
|
|
|
|
apiDump = HttpService:JSONDecode(apiDump)
|
|
|
|
|
|
|
|
local classNames = {}
|
|
|
|
classes = {}
|
2020-08-14 17:35:27 +00:00
|
|
|
|
|
|
|
local enumMap =
|
|
|
|
{
|
|
|
|
Axis = true;
|
|
|
|
FontSize = true;
|
|
|
|
}
|
2019-06-30 22:01:19 +00:00
|
|
|
|
|
|
|
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 ()
|
2020-08-14 17:35:27 +00:00
|
|
|
class.Object = game:GetService(className)
|
2019-06-30 22:01:19 +00:00
|
|
|
end)
|
|
|
|
elseif not classTags.NotCreatable then
|
|
|
|
pcall(function ()
|
|
|
|
class.Object = Instance.new(className)
|
|
|
|
|
2020-06-30 00:06:14 +00:00
|
|
|
if game:FindFirstChild("DumpFolder") then
|
2019-06-30 22:01:19 +00:00
|
|
|
class.Object.Name = className
|
2020-06-30 00:06:14 +00:00
|
|
|
class.Object.Parent = game.DumpFolder
|
2019-06-30 22:01:19 +00:00
|
|
|
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()
|
|
|
|
|
2020-08-14 17:35:27 +00:00
|
|
|
writeLine("#pragma warning disable CA1041 // Provide ObsoleteAttribute message")
|
|
|
|
writeLine("#pragma warning disable CA1051 // Do not declare visible instance fields")
|
|
|
|
writeLine("#pragma warning disable CA1707 // Identifiers should not contain underscores")
|
|
|
|
writeLine("#pragma warning disable CA1716 // Identifiers should not match keywords")
|
|
|
|
writeLine("#pragma warning disable IDE1006 // Naming Styles")
|
2020-06-22 01:02:36 +00:00
|
|
|
writeLine()
|
|
|
|
|
2019-06-30 22:01:19 +00:00
|
|
|
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
|
|
|
|
|
2019-10-01 18:47:56 +00:00
|
|
|
if class.Name == "PackageLink" then
|
|
|
|
registerClass = true
|
|
|
|
end
|
|
|
|
|
2019-06-30 22:01:19 +00:00
|
|
|
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
|
2020-07-06 00:04:20 +00:00
|
|
|
local prop = propMap[propName]
|
|
|
|
|
|
|
|
if prop then
|
|
|
|
local serial = prop.Serialization
|
|
|
|
serial.CanSave = true
|
|
|
|
serial.CanLoad = true
|
|
|
|
else
|
2019-06-30 22:01:19 +00:00
|
|
|
propMap[propName] = createProperty(propName, propType)
|
|
|
|
table.insert(propNames, propName)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
local firstLine = true
|
|
|
|
table.sort(propNames)
|
|
|
|
|
|
|
|
if classTags.Service then
|
|
|
|
writeLine("public %s()", className)
|
|
|
|
openStack()
|
|
|
|
|
|
|
|
writeLine("IsService = true;")
|
|
|
|
closeStack()
|
|
|
|
end
|
|
|
|
|
|
|
|
for i, propName in ipairs(propNames) do
|
|
|
|
local prop = propMap[propName]
|
2020-06-22 01:02:36 +00:00
|
|
|
local propTags = getTags(prop)
|
2019-06-30 22:01:19 +00:00
|
|
|
|
|
|
|
local serial = prop.Serialization
|
|
|
|
local valueType = prop.ValueType.Name
|
|
|
|
|
2020-06-22 01:02:36 +00:00
|
|
|
local redirect = redirectProps[propName]
|
|
|
|
local couldSave = (serial.CanSave or propTags.Deprecated or redirect)
|
|
|
|
|
|
|
|
if serial.CanLoad and couldSave then
|
|
|
|
if firstLine and classTags.Service then
|
|
|
|
writeLine()
|
|
|
|
end
|
2019-06-30 22:01:19 +00:00
|
|
|
|
|
|
|
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
|
2020-06-22 01:02:36 +00:00
|
|
|
local get, set, flag
|
2019-06-30 22:01:19 +00:00
|
|
|
|
|
|
|
if typeof(redirect) == "string" then
|
|
|
|
get = redirect
|
|
|
|
set = redirect .. " = value"
|
2020-06-22 01:02:36 +00:00
|
|
|
|
|
|
|
if redirect == "value" then
|
|
|
|
set = "this." .. set
|
|
|
|
end
|
2019-06-30 22:01:19 +00:00
|
|
|
else
|
2020-06-22 01:02:36 +00:00
|
|
|
get = redirect.Get
|
|
|
|
set = redirect.Set
|
|
|
|
flag = redirect.Flag
|
2019-06-30 22:01:19 +00:00
|
|
|
end
|
|
|
|
|
2019-10-24 20:17:36 +00:00
|
|
|
if not firstLine and set then
|
2019-06-30 22:01:19 +00:00
|
|
|
writeLine()
|
|
|
|
end
|
|
|
|
|
|
|
|
if propTags.Deprecated then
|
|
|
|
writeLine("[Obsolete]")
|
|
|
|
end
|
|
|
|
|
2019-10-24 20:17:36 +00:00
|
|
|
if set then
|
2020-06-22 01:02:36 +00:00
|
|
|
if flag then
|
|
|
|
writeLine("public %s %s %s", flag, valueType, name)
|
|
|
|
else
|
|
|
|
writeLine("public %s %s", valueType, name)
|
|
|
|
end
|
|
|
|
|
2019-10-24 20:17:36 +00:00
|
|
|
openStack()
|
2020-09-25 00:38:30 +00:00
|
|
|
writeLine("get => %s;", get)
|
2020-06-22 01:02:36 +00:00
|
|
|
|
|
|
|
if set:find('\n') then
|
|
|
|
writeLine()
|
|
|
|
|
|
|
|
writeLine("set")
|
|
|
|
openStack()
|
|
|
|
|
|
|
|
for line in set:gmatch("[^\r\n]+") do
|
|
|
|
writeLine(line)
|
|
|
|
end
|
|
|
|
|
|
|
|
closeStack()
|
|
|
|
else
|
2020-09-25 00:38:30 +00:00
|
|
|
writeLine("set => %s;", set)
|
2020-06-22 01:02:36 +00:00
|
|
|
end
|
|
|
|
|
2019-10-24 20:17:36 +00:00
|
|
|
closeStack()
|
|
|
|
else
|
|
|
|
writeLine("public %s %s => %s;", valueType, name, get)
|
|
|
|
end
|
2019-06-30 22:01:19 +00:00
|
|
|
|
2019-10-24 20:17:36 +00:00
|
|
|
if i ~= #propNames and set then
|
2019-06-30 22:01:19 +00:00
|
|
|
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
|
|
|
|
|
2020-06-30 00:06:14 +00:00
|
|
|
local typeData = prop.ValueType
|
|
|
|
local category = typeData.Category
|
|
|
|
|
|
|
|
if not gotValue and category ~= "Class" then
|
|
|
|
-- Fallback to implicit defaults
|
|
|
|
local typeName = typeData.Name
|
|
|
|
|
|
|
|
if numberTypes[typeName] then
|
|
|
|
value = 0
|
|
|
|
gotValue = true
|
|
|
|
elseif stringTypes[typeName] then
|
|
|
|
value = ""
|
|
|
|
gotValue = true
|
|
|
|
elseif category == "DataType" then
|
|
|
|
local DataType = env[typeName]
|
|
|
|
|
|
|
|
if DataType and typeof(DataType) == "table" and not rawget(env, typeName) then
|
|
|
|
pcall(function ()
|
|
|
|
value = DataType.new()
|
|
|
|
gotValue = true
|
|
|
|
end)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
local id = string.format("%s.%s", className, propName)
|
|
|
|
local src = string.format("[%s]", script.Parent:GetFullName())
|
|
|
|
|
|
|
|
if gotValue then
|
|
|
|
warn(src, "Fell back to implicit value for property:", id)
|
|
|
|
else
|
|
|
|
warn(src, "!! Could not figure out default value for property:", id)
|
|
|
|
end
|
|
|
|
end
|
2019-06-30 22:01:19 +00:00
|
|
|
|
|
|
|
if gotValue then
|
|
|
|
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
|
|
|
|
|
2020-08-14 17:35:27 +00:00
|
|
|
if result ~= nil then
|
|
|
|
default = " = " .. result
|
|
|
|
end
|
|
|
|
|
|
|
|
if formatFunc == formatting.EnumItem then
|
|
|
|
local enumName = tostring(value.EnumType)
|
|
|
|
enumMap[enumName] = true
|
|
|
|
end
|
2019-06-30 22:01:19 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
if propTags.Deprecated then
|
|
|
|
if not firstLine then
|
|
|
|
writeLine()
|
|
|
|
end
|
|
|
|
|
|
|
|
writeLine("[Obsolete]")
|
|
|
|
end
|
|
|
|
|
2020-06-30 00:06:14 +00:00
|
|
|
writeLine("public %s %s%s;", valueType, name, default)
|
2019-06-30 22:01:19 +00:00
|
|
|
|
|
|
|
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")
|
2020-08-14 17:35:27 +00:00
|
|
|
|
|
|
|
return enumMap
|
2019-06-30 22:01:19 +00:00
|
|
|
end
|
|
|
|
|
2020-08-14 17:35:27 +00:00
|
|
|
local function generateEnums(whiteList)
|
2019-06-30 22:01:19 +00:00
|
|
|
local version = getfenv().version():gsub("%. ", ".")
|
|
|
|
clearStream()
|
|
|
|
|
|
|
|
writeLine("// Auto-generated list of Roblox enums.")
|
|
|
|
writeLine("// Updated as of %s", version)
|
|
|
|
writeLine()
|
2020-08-14 17:35:27 +00:00
|
|
|
|
2019-06-30 22:01:19 +00:00
|
|
|
writeLine("namespace RobloxFiles.Enums")
|
|
|
|
openStack()
|
|
|
|
|
|
|
|
local enums = Enum:GetEnums()
|
|
|
|
|
|
|
|
for i, enum in ipairs(enums) do
|
2020-08-14 17:35:27 +00:00
|
|
|
local enumName = tostring(enum)
|
|
|
|
|
|
|
|
if whiteList and not whiteList[enumName] then
|
|
|
|
continue
|
|
|
|
end
|
|
|
|
|
|
|
|
writeLine("public enum %s", enumName)
|
2019-06-30 22:01:19 +00:00
|
|
|
openStack()
|
|
|
|
|
|
|
|
local enumItems = enum:GetEnumItems()
|
|
|
|
local lastValue = -1
|
2020-08-14 17:35:27 +00:00
|
|
|
local mapped = {}
|
2019-06-30 22:01:19 +00:00
|
|
|
|
|
|
|
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
|
|
|
|
|
2020-08-14 17:35:27 +00:00
|
|
|
if not mapped[value] then
|
|
|
|
if (value - lastValue) ~= 1 then
|
|
|
|
text = " = " .. value;
|
|
|
|
end
|
|
|
|
|
|
|
|
if i == #enumItems then
|
|
|
|
comma = ""
|
|
|
|
end
|
|
|
|
|
|
|
|
lastValue = value
|
|
|
|
mapped[value] = true
|
|
|
|
|
|
|
|
writeLine("%s%s%s", name, text, comma)
|
2019-06-30 22:01:19 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
closeStack()
|
|
|
|
|
|
|
|
if i ~= #enums then
|
|
|
|
writeLine()
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
closeStack()
|
|
|
|
exportStream("Enums")
|
|
|
|
end
|
|
|
|
|
2020-08-14 17:35:27 +00:00
|
|
|
local function generateAll()
|
|
|
|
local enumList = generateClasses()
|
|
|
|
generateEnums(enumList)
|
|
|
|
end
|
|
|
|
|
2019-06-30 22:01:19 +00:00
|
|
|
if plugin then
|
2020-08-14 17:35:27 +00:00
|
|
|
button.Click:Connect(generateAll)
|
2019-06-30 22:01:19 +00:00
|
|
|
else
|
2020-08-14 17:35:27 +00:00
|
|
|
generateAll()
|
2019-06-30 22:01:19 +00:00
|
|
|
end
|