I've got most of it to work. However I can't get it to automatically set it's parent. I have to add it manually and that's a pain in the butt. Example of the generated script.
local function Create(ty)
return function(data)
local obj = Instance.new(ty)
for k, v in pairs(data) do
if type(k) == 'number' then
v.Parent = obj
else
obj[k] = v
end
end
return obj
end
end
Create'Part'{
Anchored = true;
BrickColor = BrickColor.new(199);
Locked = true;
Size = Vector3.new(512, 1.20000005, 512);
CFrame = CFrame.new(0, -0.610000014, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1);
Name = "BasePlate";
Position = Vector3.new(0, -0.610000014, 0);
};
And the actual source code.
local tablename = "ref"
local n = "\n"
local t = "\t"
function IsVarName(name)
return name:match("^[%a_][%w_]-$") == name
end
local makeinstance = [[%s = Instance.new(%q)]]
local makeservice = [[%s = game:GetService(%q)]]
local ObjectMemory = {}
local function FormatInstance(s,o,p)
if not ObjectMemory[o] then
ObjectMemory[o] = {}
end
ObjectMemory[o][p] = s
return nil
end
local function FormatProtectedString(s)
return string.format("%q",s)
-- local eq = s:match("=+")
-- eq = eq and #eq or 0
-- return "["..string.rep("=",eq+1).."["..s.."]"..string.rep("=",eq+1).."]"
end
local function FormatUDim(s)
return string.format([[UDim.new(%g, %g)]],s.Scale,s.Offset)
end
local function FormatUDim2(s)
return string.format([[UDim2.new(%g, %g, %g, %g)]],s.X.Scale,s.X.Offset,s.Y.Scale,s.Y.Offset)
end
local function FormatBrickColor(s)
return [[BrickColor.new(]]..s.Number..[[)]]
end
local function FormatRay(s)
return [[Ray.new(]]..table.concat({s.Origin,s.Direction},", ")..[[)]]
end
local function FormatRegion3(s)
return [[Region3.new(]]..table.concat({s.CFrame.p+s.Size/2,s.CFrame.p-s.Size/2},", ")..[[)]]
end
local function FormatVector2int16(s)
return nil
end
local typeconvert = {
["*default"] = [[%s]];
["*enum"] = [[%s]];
["void"] = nil;
["bool"] = [[%s]];
["float"] = [[%s]];
["Float"] = [[%s]];
["int"] = [[%s]];
["double"] = [[%s]];
["number"] = [[%s]];
["string"] = [[%q]];
["Content"] = [[%q]];
["ProtectedString"] = FormatProtectedString;
["Vector2"] = [[Vector2.new(%s)]];
["Vector3"] = [[Vector3.new(%s)]];
["CFrame"] = [[CFrame.new(%s)]];
["CoordinateFrame"] = [[CFrame.new(%s)]];
["Color3"] = [[Color3.new(%s)]];
["Vector2int16"] = FormatVector2int16;
["Instance"] = FormatInstance;
["Object"] = FormatInstance;
["UDim"] = FormatUDim;
["UDim2"] = FormatUDim2;
["BrickColor"] = FormatBrickColor;
["Ray"] = FormatRay;
["Region3"] = FormatRegion3;
}
local Properties = {}
-----------------------------------------------------------------------------------------------------
local function count(t)
local c = 0
for _ in pairs(t) do
c = c + 1
end
return c
end
local Properties = {}
local enums = {}
local ex = {
["DataCost"]=true;
["Parent"]=true;
["RobloxLocked"]=true;
["Archivable"]=true;
["ClassName"]=true;
}
function FillProperties(class,up)
if class.type == "enum" then
enums[class.name] = true
end
if class.properties and #class.properties > 0 or (up and count(up) > 0) then
Properties[class.name] = {}
if up then
for name,type in pairs(up) do
Properties[class.name][name] = type
end
end
if class.properties then
for n,prop in pairs(class.properties) do
if not ex[prop.name] and not prop.deprecated then
Properties[class.name][prop.name] = prop.type
end
end
end
end
if class.subclasses then
for n,sub in pairs(class.subclasses) do
FillProperties(sub,Properties[class.name])
end
end
end
-----------------------------------------------------------------------------------------------------
local refmem = {}
local mem = {}
local off = 1
local function recurse(object, parent, tab)
local output,tab = "",tab or 0
if not object.Archivable then
return output
end
if not mem[object.ClassName] then
local e,o = pcall(game.GetService,game,object.ClassName)
if not e or not o then
local e,o = pcall(Instance.new,object.ClassName)
if e then
mem[object.ClassName] = {o,false}
end
else
mem[object.ClassName] = {o,true}
end
end
if mem[object.ClassName] then
local default,isservice = mem[object.ClassName][1],mem[object.ClassName][2]
if isservice then return output end
output=output..string.rep(t,tab)..string.format([[Create'%s'{]],object.ClassName)..n
tab = tab + 1
if Properties[object.ClassName] then
for p,m in pairs(Properties[object.ClassName]) do
if pcall(function() default[p] = default[p] return default[p] end) then
if object[p] ~= default[p] or isservice then
if type(m) == "function" then
m = m(object[p],off,p)
end
if m ~= nil then
if IsVarName(p) then
output = output..string.rep(t,tab)..p.." = "..string.format(m,tostring(object[p]))..";"..n
else
output = output..string.rep(t,tab).."['"..p.."'] = "..string.format(m,tostring(object[p]))..";"..n
end
end
refmem[object] = off
end
end
end
end
if pcall(function() object:GetChildren() end) then
local p = off
for _,item in pairs(object:GetChildren()) do
off = off + 1
local o = recurse(item,p,tab)
if #o > 0 then
output=output..o
else
off = off - 1
end
end
end
tab = tab - 1
output = output .. string.rep(t,tab) .. "};"..n
end
return output
end
function serialize(object)
off = 0
local out = ""
if type(object) == "table" then
for i,v in pairs(object) do
out = out..recurse(v)
end
else
out = out..recurse(object)
end
--[[
for o,prop in pairs(ObjectMemory) do
for name,value in pairs(prop) do
if refmem[value] then
if IsVarName(name) then
out = out..tablename.."["..o.."]."..name.." = "..tablename.."["..refmem[value].."]"..n
else
out = out..tablename.."["..o.."][\""..name.."\"] = "..tablename.."["..refmem[value].."]"..n
end
end
end
end]]
for i in pairs(ObjectMemory) do
ObjectMemory[i] = nil
end
for i in pairs(refmem) do
refmem[i] = nil
end
local v = Instance.new("Script")
v.Name = "Serialization Output"
v.Archivable = false
v.Disabled = true
v.Source = [[local function Create(ty)
return function(data)
local obj = Instance.new(ty)
for k, v in pairs(data) do
if type(k) == 'number' then
v.Parent = obj
else
obj[k] = v
end
end
return obj
end
end
]] .. out
return v
end
Scrgui = Instance.new("ScreenGui", game.Players.LocalPlayer.PlayerGui);
Scrgui.Name = "Scrgui"
Textbt = Instance.new("TextButton", game.Players.LocalPlayer.PlayerGui.Scrgui);
Textbt.Name = "Serialize";
Textbt.Position = UDim2.new(0,202,0,250);
Textbt.Size = UDim2.new(0,100,0,25);
Textbt.Text = "Chat";
function onClick(mouse)
if not Properties then print("Serialization: external database has not yet loaded") return end
local root = game:GetService("Selection"):Get()
local output = serialize(root)
output.Parent = workspace
game:GetService("Selection"):Set{output}
end
Textbt.MouseButton1Click:connect(onClick)
coroutine.wrap(function()
local tries = 3
while tries > 0 do
local asset = game:GetObjects("rbxassetid://63856918")
if asset and #asset > 0 then
local ClassDatabase = asset[1]
if ClassDatabase then
local GetDB = loadstring(ClassDatabase.Value)
if GetDB then
local db = GetDB()
for n,class in pairs(db) do
FillProperties(class)
end
for name,set in pairs(Properties) do
for prop,type in pairs(set) do
if enums[type] then
set[prop] = typeconvert["*enum"]
elseif typeconvert[type] then
set[prop] = typeconvert[type]
else
set[prop] = typeconvert["*default"]
end
end
end
break
end
end
end
tries = tries - 1
end
if tries <= 0 then
error("Serialization: could not access external database",0)
end
end)()
Here's an example output.
As you can see it's missing it's parent.
