Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --[[
- WebCopy 1.0.0 with Union & MeshPart support
- THIS IS A SAVEINSTANCE CORE NOT A SAVEINSTANCE SCRIPT. THINK OF THIS AS A MOCK OF THE BUILT IN FUNCTION. ALL THIS DOES IT MAKE THE FUNCTION
- YOU NEED A COPIER SCRIPT THAT CALLS _G.SInstance(Instance, Name) FOR THIS TO WORK.
- Made by Moon ok
- --]]
- -- You need your host with the php set up on it for this to work. Make sure read/write permissions are enabled for php.
- -- You don't need it if you have a writefile function. Actually no setup if you have writefile ahaha.
- local host = "https://novaexcile.000webhostapp.com/Master.php" -- Your php file url
- local splitSize = 800000 -- If your host supports bigger post size then change this (1mb default)
- local debugMessages = true -- Debug messages
- ------------------------------------------------------------------------------------------------------
- local http = game:GetService("HttpService")
- local API = {}
- local APIJson
- local instanceCount = 0
- local saveString = ""
- local totalInstances = 1
- local savedProps = {}
- local instanceRefs = {}
- local storedInstances = {}
- local splits = 0
- local globalName = ""
- local consoleFunc = printconsole or writeconsole
- local success,err = ypcall(function()
- APIJson = game:HttpGetAsync("http://anaminus.github.io/rbx/json/api/latest.json")
- end)
- if err then
- if script:FindFirstChild("API") then
- APIJson = require(script.API)
- end
- end
- APIJson = http:JSONDecode(APIJson)
- for i,v in pairs(APIJson) do
- if v.type == "Class" then
- API[v.Name] = v
- API[v.Name].Properties = {}
- elseif v.type == "Property" then
- local dontuse = false
- for i2,v2 in pairs(v.tags) do
- if v2 == "deprecated" or v2 == "hidden" then
- dontuse = true
- end
- end
- if not dontuse then
- table.insert(API[v.Class].Properties,v)
- end
- end
- end
- local function getProperties(obj)
- if savedProps[obj.ClassName] then return savedProps[obj.ClassName] end
- local tempProps = {}
- local currentClass = obj.ClassName
- while currentClass do
- for i,v in pairs(API[currentClass].Properties) do
- table.insert(tempProps,v)
- end
- currentClass = API[currentClass].Superclass
- end
- savedProps[obj.ClassName] = tempProps
- return tempProps
- end
- local function appendToHost()
- game:HttpPostAsync(host,table.concat(storedInstances)) --http:PostAsync(host,http:JSONEncode({Option = "Append",Name = globalName,Data = table.concat(storedInstances)}))
- splits = splits + 1
- if debugMessages then
- if consoleFunc then -- Stealth option is always better af
- consoleFunc("SaveAmounts: "..tostring(splits).." Progress = "..tostring(instanceCount/totalInstances*100).."%")
- else
- print("SaveAmounts: "..tostring(splits),"Progress = "..tostring(instanceCount/totalInstances*100).."%")
- end
- end
- end
- local function submitSave()
- game:HttpPostAsync(host,http:JSONEncode({Option = "Submit",Name = globalName}))
- end
- local function clearAll()
- game:HttpPostAsync(host,http:JSONEncode({Option = "Clear"}))
- end
- local function checkRef(obj)
- local check = instanceRefs[obj]
- if check then
- return tostring(check)
- end
- return tostring(instanceCount)
- end
- local function setRef(obj)
- if obj == nil then return "null" end
- local check = instanceRefs[obj]
- if check then
- return "RBX"..tostring(check)
- end
- instanceCount = instanceCount + 1
- instanceRefs[obj] = instanceCount
- return "RBX"..tostring(instanceCount)
- end
- local function cleanUglyAf(str)
- if #str == 0 then return "" end
- local firstChar = str:sub(1,1)
- local firstByte = string.byte(firstChar)
- if firstByte >= 32 and firstByte <= 126 then
- return firstChar..cleanUglyAf(str:sub(2))
- elseif firstByte == 9 or firstByte == 10 then
- return firstChar..cleanUglyAf(str:sub(2))
- else
- return cleanUglyAf(str:sub(2))
- end
- end
- local function writeInstance(inst)
- for i,v in pairs(inst:GetChildren()) do
- if string.len(table.concat(storedInstances)) >= splitSize and not writefile then
- appendToHost()
- storedInstances = {}
- end
- instanceCount = instanceCount + 1
- local props = getProperties(v)
- saveString = saveString..'\n<Item class="'..v.ClassName..'" referent="RBX'..checkRef(v)..'">'
- instanceRefs[v] = instanceCount
- saveString = saveString.."\n<Properties>"
- for i2,v2 in pairs(props) do
- ypcall(function()
- if v2.Name == "Archivable" or v2.Name == "DataCost" or v2.Name == "ClassName" or v2.Name == "RobloxLocked" or v2.Name == "Parent" then return end
- if v2.ValueType == "bool" then
- saveString = saveString..'\n<bool name="'..v2.Name..'">'..tostring(v[v2.Name])..'</bool>'
- elseif v2.ValueType == "float" then
- saveString = saveString..'\n<float name="'..v2.Name..'">'..tostring(v[v2.Name])..'</float>'
- elseif v2.ValueType == "int" then
- saveString = saveString..'\n<int name="'..v2.Name..'">'..tostring(v[v2.Name])..'</int>'
- elseif v2.ValueType == "string" then
- local cleanName = v[v2.Name]
- cleanName = string.gsub(cleanName,"&","&")
- cleanName = string.gsub(cleanName,"<","<")
- cleanName = string.gsub(cleanName,">",">")
- --local success,err = pcall(function()http:JSONEncode({t = cleanName})end)
- --if err then cleanName = cleanUglyAf(cleanName) end
- saveString = saveString..'\n<string name="'..v2.Name..'">'..cleanName..'</string>'
- elseif v2.ValueType == "BrickColor" then
- saveString = saveString..'\n<int name="'..v2.Name..'">'..tostring(v[v2.Name].Number)..'</int>'
- elseif v2.ValueType == "Vector2" then
- saveString = saveString..'\n<Vector2 name="'..v2.Name..'">'
- saveString = saveString..'\n<X>'..v[v2.Name].x..'</X>'
- saveString = saveString..'\n<Y>'..v[v2.Name].y..'</Y>'
- saveString = saveString..'\n</Vector2>'
- elseif v2.ValueType == "Vector3" then
- saveString = saveString..'\n<Vector3 name="'..v2.Name..'">'
- saveString = saveString..'\n<X>'..v[v2.Name].x..'</X>'
- saveString = saveString..'\n<Y>'..v[v2.Name].y..'</Y>'
- saveString = saveString..'\n<Z>'..v[v2.Name].z..'</Z>'
- saveString = saveString..'\n</Vector3>'
- elseif v2.ValueType == "CoordinateFrame" then
- saveString = saveString..'\n<CoordinateFrame name="'..v2.Name..'">'
- local X,Y,Z,R00,R01,R02,R10,R11,R12,R20,R21,R22 = v[v2.Name]:components()
- saveString = saveString..'\n<X>'..X..'</X>'
- saveString = saveString..'\n<Y>'..Y..'</Y>'
- saveString = saveString..'\n<Z>'..Z..'</Z>'
- saveString = saveString..'\n<R00>'..R00..'</R00>'
- saveString = saveString..'\n<R01>'..R01..'</R01>'
- saveString = saveString..'\n<R02>'..R02..'</R02>'
- saveString = saveString..'\n<R10>'..R10..'</R10>'
- saveString = saveString..'\n<R11>'..R11..'</R11>'
- saveString = saveString..'\n<R12>'..R12..'</R12>'
- saveString = saveString..'\n<R20>'..R20..'</R20>'
- saveString = saveString..'\n<R21>'..R21..'</R21>'
- saveString = saveString..'\n<R22>'..R22..'</R22>'
- saveString = saveString..'\n</CoordinateFrame>'
- elseif v2.ValueType == "Content" then
- local cleanName = tostring(v[v2.Name])
- cleanName = string.gsub(cleanName,"&","&")
- cleanName = string.gsub(cleanName,"<","<")
- cleanName = string.gsub(cleanName,">",">")
- --local success,err = pcall(function()http:JSONEncode({t = cleanName})end)
- --if err then cleanName = cleanUglyAf(cleanName) end
- saveString = saveString..'\n<Content name="'..v2.Name..'"><url>'..cleanName..'</url></Content>'
- elseif v2.ValueType == "UDim2" then
- saveString = saveString..'\n<UDim2 name="'..v2.Name..'">'
- saveString = saveString..'\n<XS>'..v[v2.Name].X.Scale..'</XS>'
- saveString = saveString..'\n<XO>'..v[v2.Name].X.Offset..'</XO>'
- saveString = saveString..'\n<YS>'..v[v2.Name].Y.Scale..'</YS>'
- saveString = saveString..'\n<YO>'..v[v2.Name].Y.Offset..'</YO>'
- saveString = saveString..'\n</UDim2>'
- elseif v2.ValueType == "Color3" then
- saveString = saveString..'\n<Color3 name="'..v2.Name..'">'
- saveString = saveString..'\n<R>'..v[v2.Name].r..'</R>'
- saveString = saveString..'\n<G>'..v[v2.Name].g..'</G>'
- saveString = saveString..'\n<B>'..v[v2.Name].b..'</B>'
- saveString = saveString..'\n</Color3>'
- elseif v2.ValueType == "NumberRange" then
- saveString = saveString..'\n<NumberRange name="'..v2.Name..'">'..tostring(v[v2.Name].Min).." "..tostring(v[v2.Name].Max).." "..'</NumberRange>'
- elseif v2.ValueType == "NumberSequence" then
- saveString = saveString..'\n<NumberSequence name="'..v2.Name..'">'
- for i3,v3 in pairs(v[v2.Name].Keypoints) do
- saveString = saveString..tostring(v3.Time).." "..tostring(v3.Value).." "..tostring(v3.Envelope).." "
- end
- saveString = saveString..'</NumberSequence>'
- elseif v2.ValueType == "ColorSequence" then
- saveString = saveString..'\n<ColorSequence name="'..v2.Name..'">'
- for i3,v3 in pairs(v[v2.Name].Keypoints) do
- saveString = saveString..tostring(v3.Time).." "..tostring(v3.Value.r).." "..tostring(v3.Value.g).." "..tostring(v3.Value.b).." 0 "
- end
- saveString = saveString..'</ColorSequence>'
- elseif v2.ValueType == "Rect2D" then
- saveString = saveString..'\n<Rect2D name="'..v2.Name..'">'
- saveString = saveString..'\n<min>'
- saveString = saveString..'\n<X>'..tostring(v[v2.Name].Min.X)..'</X>'
- saveString = saveString..'\n<Y>'..tostring(v[v2.Name].Min.Y)..'</Y>'
- saveString = saveString..'\n</min>'
- saveString = saveString..'\n<max>'
- saveString = saveString..'\n<X>'..tostring(v[v2.Name].Max.X)..'</X>'
- saveString = saveString..'\n<Y>'..tostring(v[v2.Name].Max.Y)..'</Y>'
- saveString = saveString..'\n</max>'
- saveString = saveString..'\n</Rect2D>'
- elseif v2.ValueType == "ProtectedString" then
- saveString = saveString..'\n<ProtectedString name="'..v2.Name..'"><![CDATA['..v[v2.Name]..']]></ProtectedString>'
- elseif v2.ValueType == "Object" then
- saveString = saveString..'\n<Ref name="'..v2.Name..'">'..setRef(v[v2.Name])..'</Ref>'
- elseif v[v2.Name].Value then
- saveString = saveString..'\n<token name="'..v2.Name..'">'..v[v2.Name].Value..'</token>'
- end
- end)
- end
- if v:IsA("UnionOperation") and ypcall(function()local lolaf = v.AssetId end) then -- Had to do this, "BinaryString" type values were not in the API dump.
- local cleanName = tostring(v.AssetId)
- cleanName = string.gsub(cleanName,"&","&")
- cleanName = string.gsub(cleanName,"<","<")
- cleanName = string.gsub(cleanName,">",">")
- --local success,err = pcall(function()http:JSONEncode({t = cleanName})end)
- --if err then cleanName = cleanUglyAf(cleanName) end
- saveString = saveString..'\n<Content name="AssetId"><url>'..cleanName..'</url></Content>'
- saveString = saveString..'\n<Vector3 name="InitialSize">'
- saveString = saveString..'\n<X>'..v.InitialSize.x..'</X>'
- saveString = saveString..'\n<Y>'..v.InitialSize.y..'</Y>'
- saveString = saveString..'\n<Z>'..v.InitialSize.z..'</Z>'
- saveString = saveString..'\n</Vector3>'
- elseif v:IsA("MeshPart") and ypcall(function()local lolaf = v.MeshID end) then
- local cleanName = tostring(v.MeshID)
- cleanName = string.gsub(cleanName,"&","&")
- cleanName = string.gsub(cleanName,"<","<")
- cleanName = string.gsub(cleanName,">",">")
- --local success,err = pcall(function()http:JSONEncode({t = cleanName})end)
- --if err then cleanName = cleanUglyAf(cleanName) end
- saveString = saveString..'\n<Content name="MeshID"><url>'..cleanName..'</url></Content>'
- saveString = saveString..'\n<Vector3 name="InitialSize">'
- saveString = saveString..'\n<X>'..v.InitialSize.x..'</X>'
- saveString = saveString..'\n<Y>'..v.InitialSize.y..'</Y>'
- saveString = saveString..'\n<Z>'..v.InitialSize.z..'</Z>'
- saveString = saveString..'\n</Vector3>'
- elseif v:IsA("Terrain") and ypcall(function()local lolaf = workspace.Terrain.SmoothGrid end) then
- saveString = saveString..'\n<BinaryString name="SmoothGrid"><![CDATA['..v.SmoothGrid..']]></BinaryString>'
- end
- saveString = saveString.."\n</Properties>"
- writeInstance(v)
- saveString = saveString.."\n</Item>"
- table.insert(storedInstances,saveString)
- saveString = ""
- end
- end
- local function removeExtension(str)
- if string.find(str,".rbxm") then
- return string.sub(str,1,string.find(str,".rbxm")-1)
- elseif string.find(str,".rbxmx") then
- return string.sub(str,1,string.find(str,".rbxmx")-1)
- else
- return str
- end
- end
- local function countTotal(obj)
- for i,v in pairs(obj:GetChildren()) do
- totalInstances = totalInstances + 1
- countTotal(v)
- end
- end
- function _G.SInstance(inst,name)
- name = removeExtension(name)
- if not writefile then
- clearAll()
- end
- instanceCount = 0
- totalInstances = 1
- countTotal(inst)
- instanceRefs = {}
- storedInstances = {}
- globalName = name
- splits = 0
- saveString = [[<roblox xmlns:xmime="http://www.w3.org/2005/05/xmlmime" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://www.roblox.com/roblox.xsd" version="4">
- <External>null</External>
- <External>nil</External>]]
- if debugMessages then
- if not ypcall(function()local lolaf = Instance.new("UnionOperation").AssetId end) then
- if consoleFunc then
- consoleFunc("RUNNING WITH NO UNSCRIPTABLE PATCH")
- else
- print("RUNNING WITH NO UNSCRIPTABLE PATCH")
- end
- else
- if consoleFunc then
- consoleFunc("RUNNING WITH UNSCRIPTABLE PATCH c:")
- else
- print("RUNNING WITH UNSCRIPTABLE PATCH c:")
- end
- end
- if not ypcall(function()local lolaf = workspace.Terrain.SmoothGrid end) then
- if consoleFunc then
- consoleFunc("RUNNING WITH NO BINARYSTRING TRANSLATE")
- else
- print("RUNNING WITH NO BINARYSTRING TRANSLATE")
- end
- else
- if consoleFunc then
- consoleFunc("RUNNING WITH BINARYSTRING TRANSLATE HOLY")
- else
- print("RUNNING WITH BINARYSTRING TRANSLATE HOLY")
- end
- end
- end
- local snapshot = inst:Clone()
- local snapshotFolder = Instance.new("Folder")
- snapshot.Parent = snapshotFolder
- writeInstance(snapshotFolder)
- table.insert(storedInstances,"\n</roblox>")
- if writefile then
- writefile(name..".rbxmx",table.concat(storedInstances))
- else
- appendToHost()
- submitSave()
- end
- if debugMessages then
- if consoleFunc then
- consoleFunc("Saved with "..tostring(splits).." splits.")
- else
- print("Saved with "..tostring(splits).." splits.")
- end
- end
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement