Skip to content

Instantly share code, notes, and snippets.

@Tomloyo
Last active August 19, 2024 10:36
Show Gist options
  • Save Tomloyo/2c54424956729b0aabed3bc00bf6b926 to your computer and use it in GitHub Desktop.
Save Tomloyo/2c54424956729b0aabed3bc00bf6b926 to your computer and use it in GitHub Desktop.
tsb_map_convert.lua
local function dec2(x)
return math.round(x*100)/100
end
local defaultSettings = {
pretty = false;
robloxFullName = false;
robloxProperFullName = true;
robloxClassName = true;
tabs = false;
semicolons = false;
spaces = 0;
sortKeys = false;
}
-- lua keywords
local keywords = {["and"]=true, ["break"]=true, ["do"]=true, ["else"]=true,
["elseif"]=true, ["end"]=true, ["false"]=true, ["for"]=true, ["function"]=true,
["if"]=true, ["in"]=true, ["local"]=true, ["nil"]=true, ["not"]=true, ["or"]=true,
["repeat"]=true, ["return"]=true, ["then"]=true, ["true"]=true, ["until"]=true, ["while"]=true}
local function isLuaIdentifier(str)
if type(str) ~= "string" then return false end
-- must be nonempty
if str:len() == 0 then return false end
-- can only contain a-z, A-Z, 0-9 and underscore
if str:find("[^%d%a_]") then return false end
-- cannot begin with digit
if tonumber(str:sub(1, 1)) then return false end
-- cannot be keyword
if keywords[str] then return false end
return true
end
-- works like Instance:GetFullName(), but invalid Lua identifiers are fixed (e.g. workspace["The Dude"].Humanoid)
local function properFullName(object, usePeriod)
if object == nil or object == game then return "" end
local s = object.Name
local usePeriod = true
if not isLuaIdentifier(s) then
s = ("[%q]"):format(s)
usePeriod = false
end
if not object.Parent or object.Parent == game then
return s
else
return properFullName(object.Parent) .. (usePeriod and "." or "") .. s
end
end
local depth = 0
local shown
local INDENT
local reprSettings
local function repr(value, reprSettings)
reprSettings = reprSettings or defaultSettings
INDENT = (" "):rep(reprSettings.spaces or defaultSettings.spaces)
if reprSettings.tabs then
INDENT = "\t"
end
local v = value --args[1]
local tabs = INDENT:rep(depth)
if depth == 0 then
shown = {}
end
if type(v) == "string" then
return ("%q"):format(v)
elseif type(v) == "number" then
if v == math.huge then return "math.huge" end
if v == -math.huge then return "-math.huge" end
return tonumber(v)
elseif type(v) == "boolean" then
return tostring(v)
elseif type(v) == "nil" then
return "nil"
elseif type(v) == "table" and type(v.__tostring) == "function" then
return tostring(v.__tostring(v))
elseif type(v) == "table" and getmetatable(v) and type(getmetatable(v).__tostring) == "function" then
return tostring(getmetatable(v).__tostring(v))
elseif type(v) == "table" then
if shown[v] then return "{CYCLIC}" end
shown[v] = true
local str = "{" .. (reprSettings.pretty and ("\n" .. INDENT .. tabs) or "")
local isArray = true
for k, v in pairs(v) do
if type(k) ~= "number" then
isArray = false
break
end
end
if isArray then
for i = 1, #v do
if i ~= 1 then
str = str .. (reprSettings.semicolons and ";" or ",") .. (reprSettings.pretty and ("\n" .. INDENT .. tabs) or "")
end
depth = depth + 1
str = str .. repr(v[i], reprSettings)
depth = depth - 1
end
else
local keyOrder = {}
local keyValueStrings = {}
for k, v in pairs(v) do
depth = depth + 1
local kStr = isLuaIdentifier(k) and k or ("[" .. repr(k, reprSettings) .. "]")
local vStr = repr(v, reprSettings)
--[[str = str .. ("%s = %s"):format(
isLuaIdentifier(k) and k or ("[" .. repr(k, reprSettings) .. "]"),
repr(v, reprSettings)
)]]
table.insert(keyOrder, kStr)
keyValueStrings[kStr] = vStr
depth = depth - 1
end
if reprSettings.sortKeys then table.sort(keyOrder) end
local first = true
for _, kStr in pairs(keyOrder) do
if not first then
str = str .. (reprSettings.semicolons and ";" or ",") .. (reprSettings.pretty and ("\n" .. INDENT .. tabs) or "")
end
str = str .. ("%s=%s"):format(kStr, keyValueStrings[kStr])
first = false
end
end
shown[v] = false
if reprSettings.pretty then
str = str .. "\n" .. tabs
end
str = str .. "}"
return str
elseif typeof then
-- Check Roblox types
if typeof(v) == "Instance" then
return (reprSettings.robloxFullName
and (reprSettings.robloxProperFullName and properFullName(v) or v:GetFullName())
or v.Name) .. (reprSettings.robloxClassName and ((" (%s)"):format(v.ClassName)) or "")
elseif typeof(v) == "Axes" then
local s = {}
if v.X then table.insert(s, repr(Enum.Axis.X, reprSettings)) end
if v.Y then table.insert(s, repr(Enum.Axis.Y, reprSettings)) end
if v.Z then table.insert(s, repr(Enum.Axis.Z, reprSettings)) end
return ("Axes.new(%s)"):format(table.concat(s, ", "))
elseif typeof(v) == "BrickColor" then
return ("BrickColor.new(%q)"):format(v.Name)
elseif typeof(v) == "CFrame" then
return ("CFrame.new(%s)"):format(table.concat({v:GetComponents()}, ","))
elseif typeof(v) == "Color3" then
return ("Color3.fromRGB("..dec2(v.R*255)..","..dec2(v.G*255)..","..dec2(v.B*255)..")")
elseif typeof(v) == "ColorSequence" then
if #v.Keypoints > 2 then
return ("ColorSequence.new(%s)"):format(repr(v.Keypoints, reprSettings))
else
if v.Keypoints[1].Value == v.Keypoints[2].Value then
return ("ColorSequence.new(%s)"):format(repr(v.Keypoints[1].Value, reprSettings))
else
return ("ColorSequence.new(%s, %s)"):format(
repr(v.Keypoints[1].Value, reprSettings),
repr(v.Keypoints[2].Value, reprSettings)
)
end
end
elseif typeof(v) == "ColorSequenceKeypoint" then
return ("ColorSequenceKeypoint.new(%d, %s)"):format(v.Time, repr(v.Value, reprSettings))
elseif typeof(v) == "DockWidgetPluginGuiInfo" then
return ("DockWidgetPluginGuiInfo.new(%s, %s, %s, %s, %s, %s, %s)"):format(
repr(v.InitialDockState, reprSettings),
repr(v.InitialEnabled, reprSettings),
repr(v.InitialEnabledShouldOverrideRestore, reprSettings),
repr(v.FloatingXSize, reprSettings),
repr(v.FloatingYSize, reprSettings),
repr(v.MinWidth, reprSettings),
repr(v.MinHeight, reprSettings)
)
elseif typeof(v) == "Enums" then
return "Enums"
elseif typeof(v) == "Enum" then
return ("Enum.%s"):format(tostring(v))
elseif typeof(v) == "EnumItem" then
return ("Enum.%s.%s"):format(tostring(v.EnumType), v.Name)
elseif typeof(v) == "Faces" then
local s = {}
for _, enumItem in pairs(Enum.NormalId:GetEnumItems()) do
if v[enumItem.Name] then
table.insert(s, repr(enumItem, reprSettings))
end
end
return ("Faces.new(%s)"):format(table.concat(s, ", "))
elseif typeof(v) == "NumberRange" then
if v.Min == v.Max then
return ("NumberRange.new(%d)"):format(v.Min)
else
return ("NumberRange.new(%d, %d)"):format(v.Min, v.Max)
end
elseif typeof(v) == "NumberSequence" then
if #v.Keypoints > 2 then
return ("NumberSequence.new(%s)"):format(repr(v.Keypoints, reprSettings))
else
if v.Keypoints[1].Value == v.Keypoints[2].Value then
return ("NumberSequence.new(%d)"):format(v.Keypoints[1].Value)
else
return ("NumberSequence.new(%d, %d)"):format(v.Keypoints[1].Value, v.Keypoints[2].Value)
end
end
elseif typeof(v) == "NumberSequenceKeypoint" then
if v.Envelope ~= 0 then
return ("NumberSequenceKeypoint.new(%d, %d, %d)"):format(v.Time, v.Value, v.Envelope)
else
return ("NumberSequenceKeypoint.new(%d, %d)"):format(v.Time, v.Value)
end
elseif typeof(v) == "PathWaypoint" then
return ("PathWaypoint.new(%s, %s)"):format(
repr(v.Position, reprSettings),
repr(v.Action, reprSettings)
)
elseif typeof(v) == "PhysicalProperties" then
return ("PhysicalProperties.new(%d, %d, %d, %d, %d)"):format(
v.Density, v.Friction, v.Elasticity, v.FrictionWeight, v.ElasticityWeight
)
elseif typeof(v) == "Random" then
return "<Random>"
elseif typeof(v) == "Ray" then
return ("Ray.new(%s, %s)"):format(
repr(v.Origin, reprSettings),
repr(v.Direction, reprSettings)
)
elseif typeof(v) == "RBXScriptConnection" then
return "<RBXScriptConnection>"
elseif typeof(v) == "RBXScriptSignal" then
return "<RBXScriptSignal>"
elseif typeof(v) == "Rect" then
return ("Rect.new(%d, %d, %d, %d)"):format(
v.Min.X, v.Min.Y, v.Max.X, v.Max.Y
)
elseif typeof(v) == "Region3" then
local min = v.CFrame.p + v.Size * -.5
local max = v.CFrame.p + v.Size * .5
return ("Region3.new(%s, %s)"):format(
repr(min, reprSettings),
repr(max, reprSettings)
)
elseif typeof(v) == "Region3int16" then
return ("Region3int16.new(%s, %s)"):format(
repr(v.Min, reprSettings),
repr(v.Max, reprSettings)
)
elseif typeof(v) == "TweenInfo" then
return ("TweenInfo.new(%d, %s, %s, %d, %s, %d)"):format(
v.Time, repr(v.EasingStyle, reprSettings), repr(v.EasingDirection, reprSettings),
v.RepeatCount, repr(v.Reverses, reprSettings), v.DelayTime
)
elseif typeof(v) == "UDim" then
return ("UDim.new(%d, %d)"):format(
v.Scale, v.Offset
)
elseif typeof(v) == "UDim2" then
return ("UDim2.new(%d, %d, %d, %d)"):format(
v.X.Scale, v.X.Offset, v.Y.Scale, v.Y.Offset
)
elseif typeof(v) == "Vector2" then
return ("Vector2.new(%d, %d)"):format(v.X, v.Y)
elseif typeof(v) == "Vector2int16" then
return ("Vector2int16.new(%d, %d)"):format(v.X, v.Y)
elseif typeof(v) == "Vector3" then
return ("Vector3.new(%d, %d, %d)"):format(v.X, v.Y, v.Z)
elseif typeof(v) == "Vector3int16" then
return ("Vector3int16.new(%d, %d, %d)"):format(v.X, v.Y, v.Z)
elseif typeof(v) == "DateTime" then
return ("DateTime.fromIsoDate(%q)"):format(v:ToIsoDate())
else
return "<Roblox:" .. typeof(v) .. ">"
end
else
return "<" .. type(v) .. ">"
end
end
local b = "local a={"
local i = 0
-- Making parts variable
for c, d in game.Workspace:GetDescendants() do
if d:IsA("Part") or d:IsA("SpawnLocation") then
local e =
repr(unpack({{
["Color"] = d.Color,
["Class"] = d.ClassName,
["CFrame"] = d.CFrame + Vector3.new(0, 800, 0),
["Properties"] = {
["Client"] = true,
["Anchored"] = true,
["Collision"] = d.CanCollide,
["Shadow"] = d.CastShadow,
["Transparency"] = d.Transparency
},
["Material"] = d.Material,
["Serial"] = "Map"..tostring(i)..string.rep("0", 7-#tostring(i)),
["Size"] = d.Size
}}))
b = b .. e .. ","
i = i + 1
end
end
game:GetService("StarterGui"):SetCore("SendNotification",{
Title = "TSB Map Convert",
Text = "There are in total "..tostring(i).."parts"
})
local function splitByChunk(text, chunkSize)
local s = {}
for i=1, #text, chunkSize do
s[#s+1] = text:sub(i,i+chunkSize - 1)
end
return s
end
local text = string.sub(b, 1, string.len(b) - 2)..'}} game:GetService("StarterGui"):SetCore("SendNotification",{Title="TSB Map Load",Text="Loading map with "..tostring(#a).." parts"})for b,c in a do wait(0.01)local d={[1]={["Color"]=c.Color,["Class"]=c.Class,["Todo"]="Place",["Goal"]="PS Build",["CFrame"]=c.CFrame,["Properties"]={["Anchored"]=true,["Shadow"]=c.Properties.Shadow,["Collision"]=c.Properties.Collision,["Client"]=true},["Material"]=c.Material,["Serial"]=c.Serial,["Size"]=c.Size}}game:GetService("Players").LocalPlayer.Character.Communicate:FireServer(unpack(d))if c.Properties.Transparency~=0 then wait(0.01)local e={[1]={["Todo"]="Property Change",["Goal"]="PS Build",["List"]={[1]={["Serial"]=c.Serial}},["Property"]="Transparency",["New"]=tostring(c.Properties.Transparency)}}game:GetService("Players").LocalPlayer.Character.Communicate:FireServer(unpack(e))end end;game:GetService("StarterGui"):SetCore("SendNotification",{Title="TSB Map Load",Text="Map loaded"})'
request({
Url = url,
Method = "POST",
Body = text
})
game:GetService("StarterGui"):SetCore("SendNotification",{
Title = "TSB Map Convert",
Text = "Sent lua to "..url.." successfully"
})
@Tomloyo
Copy link
Author

Tomloyo commented Aug 18, 2024

@Tomloyo
Copy link
Author

Tomloyo commented Aug 19, 2024

local url = "" --https://webhook.site/ is good for it
local str = "local url = '"..url.."'"
loadstring(url..game:HttpGet('https://gist.githubusercontent.com/Tomloyo/2c54424956729b0aabed3bc00bf6b926/raw/8f318133cd4f07a5320940d4c7ff7bf088d23156/tsb_map_convert.lua'))()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment