Actions={RecolorHandle=function(F)Tool.Handle.BrickColor=F end;Clone=function(F,y)assert(type(F)=="\116\097\098\108\101","\073\110\118\097\108\105\100 \105\116\101\109\115")assert(typeof(y)=="\073\110\115\116\097\110\099\101","\073\110\118\097\108\105\100 \112\097\114\101\110\116")assert(Security.IsLocationAllowed(y,Player),"\080\101\114\109\105\115\115\105\111\110 \100\101\110\105\101\100 \102\111\114 \099\108\105\101\110\116")if not CanModifyItems(F)then return{}end local t=GetPartsFromSelection(F)if Security.ArePartsViolatingAreas(t,Player,false)then return{}end local n={}for F,t in pairs(F)do local j=t:Clone()j.Parent=y table.insert(n,j)CreatedInstances[t]=t end return n end,CreatePart=function(F,y,t)assert(typeof(t)=="\073\110\115\116\097\110\099\101","\073\110\118\097\108\105\100 \112\097\114\101\110\116")assert(Security.IsLocationAllowed(t,Player),"\080\101\114\109\105\115\115\105\111\110 \100\101\110\105\101\100 \102\111\114 \099\108\105\101\110\116")local n=CreatePart(F)n.CFrame=y local j=Security.GetPermissions(Security.GetSelectionAreas({n}),Player)if Security.ArePartsViolatingAreas({n},Player,false,j)then return end n.Parent=t CreatedInstances[n]=n return n end,CreateGroup=function(F,y,t)local n={Model=true,Folder=true}assert(n[F],"\073\110\118\097\108\105\100 \103\114\111\117\112 \116\121\112\101")assert(typeof(y)=="\073\110\115\116\097\110\099\101","\073\110\118\097\108\105\100 \112\097\114\101\110\116")assert(Security.IsLocationAllowed(y,Player),"\080\101\114\109\105\115\115\105\111\110 \100\101\110\105\101\100 \102\111\114 \099\108\105\101\110\116")if not CanModifyItems(t)then return end local j=GetPartsFromSelection(t)local M=Security.GetPermissions(Security.GetSelectionAreas(j),Player)if Security.ArePartsViolatingAreas(j,Player,true,M)then return end local a=Instance.new(F)for F,y in pairs(t)do y.Parent=a end a.Parent=y if F=="\077\111\100\101\108"then a:MakeJoints()elseif F=="\070\111\108\100\101\114"then local F=Support.GetDescendantsWhichAreA(a,"\066\097\115\101\080\097\114\116")for F,y in pairs(F)do y:MakeJoints()end end return a end;Ungroup=function(F)assert(type(F)=="\116\097\098\108\101","\073\110\118\097\108\105\100 \103\114\111\117\112\115")if not CanModifyItems(F)then return end local y=GetPartsFromSelection(F)local t=Security.GetPermissions(Security.GetSelectionAreas(y),Player)if Security.ArePartsViolatingAreas(y,Player,true,t)then return end local n={}for F,y in ipairs(F)do assert(typeof(y)=="\073\110\115\116\097\110\099\101","\073\110\118\097\108\105\100 \103\114\111\117\112")local t={}n[F]=t local j=y.Parent for F,n in pairs(y:GetChildren())do LastParents[n]=y t[#t+1]=n n.Parent=j if n:IsA("\066\097\115\101\080\097\114\116")then n:MakeJoints()elseif n:IsA("\070\111\108\100\101\114")then local F=Support.GetDescendantsWhichAreA(n,"\066\097\115\101\080\097\114\116")for F,y in pairs(F)do y:MakeJoints()end end end LastParents[y]=y.Parent CreatedInstances[y]=y y.Parent=nil end return n end;SetParent=function(F,y)assert(type(F)=="\116\097\098\108\101","\073\110\118\097\108\105\100 \105\116\101\109\115")assert(type(y)=="\116\097\098\108\101"or typeof(y)=="\073\110\115\116\097\110\099\101","\073\110\118\097\108\105\100 \112\097\114\101\110\116")if not CanModifyItems(F)then return end local t=GetPartsFromSelection(F)local n=Security.GetPermissions(Security.GetSelectionAreas(t),Player)if Security.ArePartsViolatingAreas(t,Player,true,n)then return end if type(y)=="\116\097\098\108\101"then for F,t in pairs(F)do local n=y[F]assert(Security.IsLocationAllowed(n,Player),"\080\101\114\109\105\115\115\105\111\110 \100\101\110\105\101\100 \102\111\114 \099\108\105\101\110\116")t.Parent=n if t:IsA("\066\097\115\101\080\097\114\116")then t:MakeJoints()elseif t:IsA("\070\111\108\100\101\114")then local F=Support.GetDescendantsWhichAreA(t,"\066\097\115\101\080\097\114\116")for F,y in pairs(F)do y:MakeJoints()end end end elseif typeof(y)=="\073\110\115\116\097\110\099\101"then assert(Security.IsLocationAllowed(y,Player),"\080\101\114\109\105\115\115\105\111\110 \100\101\110\105\101\100 \102\111\114 \099\108\105\101\110\116")for F,t in pairs(F)do t.Parent=y if t:IsA("\066\097\115\101\080\097\114\116")then t:MakeJoints()elseif t:IsA("\070\111\108\100\101\114")then local F=Support.GetDescendantsWhichAreA(t,"\066\097\115\101\080\097\114\116")for F,y in pairs(F)do y:MakeJoints()end end end end end,SetName=function(F,y)assert(type(F)=="\116\097\098\108\101","\073\110\118\097\108\105\100 \105\116\101\109\115")assert(type(y)=="\116\097\098\108\101"or type(y)=="\115\116\114\105\110\103","\073\110\118\097\108\105\100 \110\097\109\101")if not CanModifyItems(F)then return end local t=GetPartsFromSelection(F)local n=Security.GetPermissions(Security.GetSelectionAreas(t),Player)if Security.ArePartsViolatingAreas(t,Player,true,n)then return end if type(y)=="\116\097\098\108\101"then for F,t in pairs(F)do local n=y[F]t.Name=n end elseif type(y)=="\115\116\114\105\110\103"then for F,t in pairs(F)do t.Name=y end end end;Remove=function(F)local y={}for F,t in pairs(F)do if t then if t:IsA("\066\097\115\101\080\097\114\116")then table.insert(y,t)elseif t:IsA("\083\109\111\107\101")or t:IsA("\070\105\114\101")or t:IsA("\083\112\097\114\107\108\101\115")or t:IsA("\068\097\116\097\077\111\100\101\108\077\101\115\104")or t:IsA("\068\101\099\097\108")or t:IsA("\084\101\120\116\117\114\101")or t:IsA("\076\105\103\104\116")then table.insert(y,t.Parent)elseif t:IsA("\077\111\100\101\108")or t:IsA("\070\111\108\100\101\114")then Support.ConcatTable(y,Support.GetDescendantsWhichAreA(t,"\066\097\115\101\080\097\114\116"))end end end if not CanModifyItems(F)then return end if Security.ArePartsViolatingAreas(y,Player,true)then return end for F,y in pairs(F)do LastParents[y]=y.Parent CreatedInstances[y]=y y.Parent=nil end end;UndoRemove=function(F)local y={}for F,t in pairs(F)do if t and LastParents[t]then if t:IsA("\066\097\115\101\080\097\114\116")then table.insert(y,t)elseif t:IsA("\083\109\111\107\101")or t:IsA("\070\105\114\101")or t:IsA("\083\112\097\114\107\108\101\115")or t:IsA("\068\097\116\097\077\111\100\101\108\077\101\115\104")or t:IsA("\068\101\099\097\108")or t:IsA("\084\101\120\116\117\114\101")or t:IsA("\076\105\103\104\116")then table.insert(y,t.Parent)elseif t:IsA("\077\111\100\101\108")or t:IsA("\070\111\108\100\101\114")then Support.ConcatTable(y,Support.GetDescendantsWhichAreA(t,"\066\097\115\101\080\097\114\116"))end end end if not CanModifyItems(F)then return end if Security.ArePartsViolatingAreas(y,Player,false)then return end for F,y in pairs(F)do local t=LastParents[y]LastParents[y]=y.Parent CreatedInstances[y]=y y.Parent=t if y:IsA("\066\097\115\101\080\097\114\116")then y:MakeJoints()else local F=Support.GetDescendantsWhichAreA(y,"\066\097\115\101\080\097\114\116")for F,y in pairs(F)do y:MakeJoints()end end end end;SyncMove=function(F)local y={}for F,t in pairs(F)do if t.Part then table.insert(y,t.Part)end end if not CanModifyItems(y)then return end local t=Security.GetPermissions(Security.GetSelectionAreas(y),Player)if Security.ArePartsViolatingAreas(y,Player,true,t)then return end local n={}for F,y in pairs(F)do if y.Part then y.InitialState={Anchored=y.Part.Anchored,CFrame=y.Part.CFrame}n[y.Part]=y end end for F,y in pairs(n)do y.Joints=PreserveJoints(F,n)end for F,y in pairs(n)do F.Anchored=true F:BreakJoints()F.Velocity=Vector3.new()F.RotVelocity=Vector3.new()F.CFrame=y.CFrame end if Security.ArePartsViolatingAreas(y,Player,false,t)then for F,y in pairs(n)do F.CFrame=y.InitialState.CFrame end end for F,y in pairs(n)do F:MakeJoints()RestoreJoints(y.Joints)F.Anchored=y.InitialState.Anchored end end,SyncResize=function(F)local y={}for F,t in pairs(F)do if t.Part then table.insert(y,t.Part)end end if not CanModifyItems(y)then return end local t=Security.GetPermissions(Security.GetSelectionAreas(y),Player)if Security.ArePartsViolatingAreas(y,Player,true,t)then return end local n={}for F,y in pairs(F)do if y.Part then y.InitialState={Anchored=y.Part.Anchored,Size=y.Part.Size;CFrame=y.Part.CFrame}n[y.Part]=y end end for F,y in pairs(n)do F.Anchored=true F:BreakJoints()F.Velocity=Vector3.new()F.RotVelocity=Vector3.new()F.Size=y.Size F.CFrame=y.CFrame end if Security.ArePartsViolatingAreas(y,Player,false,t)then for F,y in pairs(n)do F.Size=y.InitialState.Size F.CFrame=y.InitialState.CFrame end end for F,y in pairs(n)do F:MakeJoints()F.Anchored=y.InitialState.Anchored end end;SyncRotate=function(F)local y={}for F,t in pairs(F)do if t.Part then table.insert(y,t.Part)end end if not CanModifyItems(y)then return end local t=Security.GetPermissions(Security.GetSelectionAreas(y),Player)if Security.ArePartsViolatingAreas(y,Player,true,t)then return end local n={}for F,y in pairs(F)do if y.Part then y.InitialState={Anchored=y.Part.Anchored;CFrame=y.Part.CFrame}n[y.Part]=y end end for F,y in pairs(n)do y.Joints=PreserveJoints(F,n)end for F,y in pairs(n)do F.Anchored=true F:BreakJoints()F.Velocity=Vector3.new()F.RotVelocity=Vector3.new()F.CFrame=y.CFrame end if Security.ArePartsViolatingAreas(y,Player,false,t)then for F,y in pairs(n)do F.CFrame=y.InitialState.CFrame end end for F,y in pairs(n)do F:MakeJoints()RestoreJoints(y.Joints)F.Anchored=y.InitialState.Anchored end end;SyncColor=function(F)local y={}for F,t in pairs(F)do if t.Part then table.insert(y,t.Part)end end if not CanModifyItems(y)then return end local t=Security.GetPermissions(Security.GetSelectionAreas(y),Player)if Security.ArePartsViolatingAreas(y,Player,true,t)then return end local n={}for F,y in pairs(F)do if y.Part then n[y.Part]=y end end for F,y in pairs(n)do F.Color=y.Color if F.ClassName=="\085\110\105\111\110\079\112\101\114\097\116\105\111\110"then F.UsePartColor=y.UnionColoring end end end,SyncSurface=function(F)local y={}for F,t in pairs(F)do if t.Part then table.insert(y,t.Part)end end if not CanModifyItems(y)then return end local t=Security.GetPermissions(Security.GetSelectionAreas(y),Player)if Security.ArePartsViolatingAreas(y,Player,true,t)then return end local n={}for F,y in pairs(F)do if y.Part then n[y.Part]=y end end for F,y in pairs(n)do for y,t in pairs(y.Surfaces)do F[y.."\083\117\114\102\097\099\101"]=t end end end,CreateLights=function(F)local y={}for F,t in pairs(F)do if t.Part then table.insert(y,t.Part)end end if not CanModifyItems(y)then return end local t=Security.GetPermissions(Security.GetSelectionAreas(y),Player)if Security.ArePartsViolatingAreas(y,Player,true,t)then return end local n={}for F,y in pairs(F)do if y.Part then n[y.Part]=y end end local j={PointLight=true;SurfaceLight=true;SpotLight=true}local M={}for F,y in pairs(n)do if j[y.LightType]then local t=Instance.new(y.LightType,F)table.insert(M,t)CreatedInstances[t]=t end end return M end,SyncLighting=function(F)local y={}for F,t in pairs(F)do if t.Part then table.insert(y,t.Part)end end if not CanModifyItems(y)then return end local t=Security.GetPermissions(Security.GetSelectionAreas(y),Player)if Security.ArePartsViolatingAreas(y,Player,true,t)then return end local n={}for F,y in pairs(F)do if y.Part then n[y.Part]=y end end local j={PointLight=true,SurfaceLight=true;SpotLight=true}for F,y in pairs(n)do if j[y.LightType]then local t=Support.GetChildOfClass(F,y.LightType)if t then if y.Range~=nil then t.Range=y.Range end if y.Brightness~=nil then t.Brightness=y.Brightness end if y.Color~=nil then t.Color=y.Color end if y.Shadows~=nil then t.Shadows=y.Shadows end if y.Face~=nil then t.Face=y.Face end if y.Angle~=nil then t.Angle=y.Angle end end end end end,CreateDecorations=function(F)local y={}for F,t in pairs(F)do if t.Part then table.insert(y,t.Part)end end if not CanModifyItems(y)then return end local t=Security.GetPermissions(Security.GetSelectionAreas(y),Player)if Security.ArePartsViolatingAreas(y,Player,true,t)then return end local n={}for F,y in pairs(F)do if y.Part then n[y.Part]=y end end local j={Smoke=true;Fire=true,Sparkles=true}local M={}for F,y in pairs(n)do if j[y.DecorationType]then local t=Instance.new(y.DecorationType,F)table.insert(M,t)CreatedInstances[t]=t end end return M end,SyncDecorate=function(F)local y={}for F,t in pairs(F)do if t.Part then table.insert(y,t.Part)end end if not CanModifyItems(y)then return end local t=Security.GetPermissions(Security.GetSelectionAreas(y),Player)if Security.ArePartsViolatingAreas(y,Player,true,t)then return end local n={}for F,y in pairs(F)do if y.Part then n[y.Part]=y end end local j={Smoke=true,Fire=true;Sparkles=true}for F,y in pairs(n)do if j[y.DecorationType]then local t=Support.GetChildOfClass(F,y.DecorationType)if t then if y.Color~=nil then t.Color=y.Color end if y.Opacity~=nil then t.Opacity=y.Opacity end if y.RiseVelocity~=nil then t.RiseVelocity=y.RiseVelocity end if y.Size~=nil then t.Size=y.Size end if y.Heat~=nil then t.Heat=y.Heat end if y.SecondaryColor~=nil then t.SecondaryColor=y.SecondaryColor end if y.SparkleColor~=nil then t.SparkleColor=y.SparkleColor end end end end end,CreateMeshes=function(F)local y={}for F,t in pairs(F)do if t.Part then table.insert(y,t.Part)end end if not CanModifyItems(y)then return end local t=Security.GetPermissions(Security.GetSelectionAreas(y),Player)if Security.ArePartsViolatingAreas(y,Player,true,t)then return end local n={}for F,y in pairs(F)do if y.Part then n[y.Part]=y end end local j={}for F,y in pairs(n)do local t=Instance.new("\083\112\101\099\105\097\108\077\101\115\104",F)table.insert(j,t)CreatedInstances[t]=t end return j end;SyncMesh=function(F)local y={}for F,t in pairs(F)do if t.Part then table.insert(y,t.Part)end end if not CanModifyItems(y)then return end local t=Security.GetPermissions(Security.GetSelectionAreas(y),Player)if Security.ArePartsViolatingAreas(y,Player,true,t)then return end local n={}for F,y in pairs(F)do if y.Part then n[y.Part]=y end end for F,y in pairs(n)do local t=Support.GetChildOfClass(F,"\083\112\101\099\105\097\108\077\101\115\104")if t then if y.VertexColor~=nil then t.VertexColor=y.VertexColor end if y.MeshType~=nil then t.MeshType=y.MeshType end if y.Scale~=nil then t.Scale=y.Scale end if y.Offset~=nil then t.Offset=y.Offset end if y.MeshId~=nil then t.MeshId=y.MeshId end if y.TextureId~=nil then t.TextureId=y.TextureId end end end end;CreateTextures=function(F)local y={}for F,t in pairs(F)do if t.Part then table.insert(y,t.Part)end end if not CanModifyItems(y)then return end local t=Security.GetPermissions(Security.GetSelectionAreas(y),Player)if Security.ArePartsViolatingAreas(y,Player,true,t)then return end local n={}for F,y in pairs(F)do if y.Part then n[y.Part]=y end end local j={Texture=true,Decal=true}local M={}for F,y in pairs(n)do if j[y.TextureType]then local t=Instance.new(y.TextureType,F)t.Face=y.Face table.insert(M,t)CreatedInstances[t]=t end end return M end;SyncTexture=function(F)local y={}for F,t in pairs(F)do if t.Part then table.insert(y,t.Part)end end if not CanModifyItems(y)then return end local t=Security.GetPermissions(Security.GetSelectionAreas(y),Player)if Security.ArePartsViolatingAreas(y,Player,true,t)then return end local n={}for F,y in pairs(F)do if y.Part then n[y.Part]=y end end local j={Texture=true,Decal=true}for F,y in pairs(n)do if j[y.TextureType]then for F,t in pairs(F:GetChildren())do if t.ClassName==y.TextureType and t.Face==y.Face then if y.Texture~=nil then t.Texture=y.Texture end if y.Transparency~=nil then t.Transparency=y.Transparency end if y.StudsPerTileU~=nil then t.StudsPerTileU=y.StudsPerTileU end if y.StudsPerTileV~=nil then t.StudsPerTileV=y.StudsPerTileV end end end end end end;SyncAnchor=function(F)local y={}for F,t in pairs(F)do if t.Part then table.insert(y,t.Part)end end if not CanModifyItems(y)then return end local t=Security.GetPermissions(Security.GetSelectionAreas(y),Player)if Security.ArePartsViolatingAreas(y,Player,true,t)then return end local n={}for F,y in pairs(F)do if y.Part then n[y.Part]=y end end for F,y in pairs(n)do F.Anchored=y.Anchored end end,SyncCollision=function(F)local y={}for F,t in pairs(F)do if t.Part then table.insert(y,t.Part)end end if not CanModifyItems(y)then return end local t=Security.GetPermissions(Security.GetSelectionAreas(y),Player)if Security.ArePartsViolatingAreas(y,Player,true,t)then return end local n={}for F,y in pairs(F)do if y.Part then n[y.Part]=y end end for F,y in pairs(n)do F.CanCollide=y.CanCollide end end;SyncMaterial=function(F)local y={}for F,t in pairs(F)do if t.Part then table.insert(y,t.Part)end end if not CanModifyItems(y)then return end local t=Security.GetPermissions(Security.GetSelectionAreas(y),Player)if Security.ArePartsViolatingAreas(y,Player,true,t)then return end local n={}for F,y in pairs(F)do if y.Part then n[y.Part]=y end end for F,y in pairs(n)do if y.Material~=nil then F.Material=y.Material end if y.Transparency~=nil then F.Transparency=y.Transparency end if y.Reflectance~=nil then F.Reflectance=y.Reflectance end end end,CreateWelds=function(F,y)if not CanModifyItems(F)then return end local t=Security.GetPermissions(Security.GetSelectionAreas(F),Player)if Security.ArePartsViolatingAreas(F,Player,true,t)then return end local n={}for F,t in pairs(F)do if t~=y then local F=t.CFrame:toObjectSpace(y.CFrame)local j=Instance.new("\087\101\108\100")j.Name="\066\084\087\101\108\100"j.Part0=y j.Part1=t j.C1=F j.Archivable=true j.Parent=y CreatedInstances[j]=j table.insert(n,j)end end return n end,RemoveWelds=function(F)local y={}for F,t in pairs(F)do if t.ClassName~="\087\101\108\100"then return end table.insert(y,t.Part0)table.insert(y,t.Part1)end if not CanModifyItems(y)then return end local t=0 local n=Security.GetPermissions(Security.GetSelectionAreas(y),Player)for F,y in pairs(F)do local j=Security.ArePartsViolatingAreas({y.Part0},Player,true,n)local M=Security.ArePartsViolatingAreas({y.Part1},Player,true,n)if not j or not M then CreatedInstances[y]=y LastParents[y]=y.Parent t=t+1 y.Parent=nil end end return t end,UndoRemovedWelds=function(F)local y={}for F,t in pairs(F)do if t.ClassName~="\087\101\108\100"then return end if not LastParents[t]then return end table.insert(y,t.Part0)table.insert(y,t.Part1)end if not CanModifyItems(y)then return end local t=Security.GetPermissions(Security.GetSelectionAreas(y),Player)for F,y in pairs(F)do local n=Security.ArePartsViolatingAreas({y.Part0},Player,false,t)local j=Security.ArePartsViolatingAreas({y.Part0},Player,false,t)if not n or not j then local F=LastParents[y]LastParents[y]=y.Parent CreatedInstances[y]=y y.Parent=F end end end;Export=function(F)if RunService:IsClient()and not RunService:IsStudio()then return SyncAPI.ServerEndpoint:InvokeServer("\069\120\112\111\114\116",F)end assert(type(F)=="\116\097\098\108\101","\073\110\118\097\108\105\100 \105\116\101\109 \116\097\098\108\101")if#F==0 then return end if not CanModifyItems(F)then return end local y=Security.GetPermissions(Security.GetSelectionAreas(F),Player)if Security.ArePartsViolatingAreas(F,Player,true,y)then return end local t=Support.CloneTable(F)for F,y in pairs(F)do Support.ConcatTable(t,y:GetDescendants())end local n=Serialization.SerializeModel(t)local j=HttpService:JSONDecode(HttpService:PostAsync("\104\116\116\112\058\047\047\102\051\120\116\101\097\109\046\099\111\109\047\098\116\047\101\120\112\111\114\116",HttpService:JSONEncode({data=n,version=3,userId=Player and Player.UserId}),Enum.HttpContentType.ApplicationJson,true))if j.success then return j.id else error("\069\120\112\111\114\116 \102\097\105\108\101\100 \100\117\101 \116\111 \115\101\114\118\101\114-\115\105\100\101 \101\114\114\111\114",2)end end;IsHttpServiceEnabled=function()if RunService:IsClient()then return SyncAPI.ServerEndpoint:InvokeServer("\073\115\072\116\116\112\083\101\114\118\105\099\101\069\110\097\098\108\101\100")end if IsHttpServiceEnabled~=nil then return IsHttpServiceEnabled end local F,y=pcall(function()return HttpService:GetAsync("\104\116\116\112\115\058\047\047\103\111\111\103\108\101\046\099\111\109")end)if F then IsHttpServiceEnabled=true elseif not F and y:match("\072\116\116\112 \114\101\113\117\101\115\116\115 \097\114\101 \110\111\116 \101\110\097\098\108\101\100")then IsHttpServiceEnabled=false end return IsHttpServiceEnabled or false end;ExtractMeshFromAsset=function(F)if RunService:IsClient()and not RunService:IsStudio()then return SyncAPI.ServerEndpoint:InvokeServer("\069\120\116\114\097\099\116\077\101\115\104\070\114\111\109\065\115\115\101\116",F)end assert(type(F)=="\110\117\109\098\101\114","\073\110\118\097\108\105\100 \097\115\115\101\116 \073\068")return HttpService:JSONDecode(HttpService:GetAsync("\104\116\116\112\058\047\047\102\051\120\116\101\097\109\046\099\111\109\047\098\116\047\103\101\116\070\105\114\115\116\077\101\115\104\068\097\116\097\047"..F))end,ExtractImageFromDecal=function(F)if RunService:IsClient()and not RunService:IsStudio()then return SyncAPI.ServerEndpoint:InvokeServer("\069\120\116\114\097\099\116\073\109\097\103\101\070\114\111\109\068\101\099\097\108",F)end return HttpService:GetAsync("\104\116\116\112\058\047\047\102\051\120\116\101\097\109\046\099\111\109\047\098\116\047\103\101\116\068\101\099\097\108\073\109\097\103\101\073\068\047"..F)end;SetMouseLockEnabled=function(F)if RunService:IsClient()and not RunService:IsStudio()then return SyncAPI.ServerEndpoint:InvokeServer("\083\101\116\077\111\117\115\101\076\111\099\107\069\110\097\098\108\101\100",F)end Player.DevEnableMouseLock=F end,SetLocked=function(F,y)assert(type(F)=="\116\097\098\108\101","\073\110\118\097\108\105\100 \105\116\101\109\115")assert(type(y)=="\116\097\098\108\101"or type(y)=="\098\111\111\108\101\097\110","\073\110\118\097\108\105\100 \108\111\099\107 \115\116\097\116\101")if not CanModifyItems(F)then return end local t=GetPartsFromSelection(F)local n=Security.GetPermissions(Security.GetSelectionAreas(t),Player)if Security.ArePartsViolatingAreas(t,Player,true,n)then return end if type(y)=="\116\097\098\108\101"then for F,t in pairs(F)do local n=y[F]t.Locked=n end elseif type(y)=="\098\111\111\108\101\097\110"then for F,t in pairs(F)do t.Locked=y end end end}function CanModifyItems(F)for F,y in pairs(F)do local t=Security.IsItemAllowed(y,Player)local n=LastParents[y]if not(t or n)then return false end if Options.DisallowLocked and(y:IsA("\066\097\115\101\080\097\114\116")and y.Locked)then return false end end return true end function GetPartsFromSelection(F)local y={}for F,t in pairs(F)do if t:IsA("\066\097\115\101\080\097\114\116")then y[#y+1]=t else for F,t in pairs(t:GetDescendants())do if t:IsA("\066\097\115\101\080\097\114\116")then y[#y+1]=t end end end end return y end

Actions = {

	['RecolorHandle'] = function (NewColor)
		-- Recolors the tool handle
		Tool.Handle.BrickColor = NewColor;
	end;

	['Clone'] = function (Items, Parent)
		-- Clones the given items

		-- Validate arguments
		assert(type(Items) == 'table', 'Invalid items')
		assert(typeof(Parent) == 'Instance', 'Invalid parent')
		assert(Security.IsLocationAllowed(Parent, Player), 'Permission denied for client')

		-- Check if items modifiable
		if not CanModifyItems(Items) then
			return {}
		end

		-- Check if parts intruding into private areas
		local Parts = GetPartsFromSelection(Items)
		if Security.ArePartsViolatingAreas(Parts, Player, false) then
			return {}
		end

		local Clones = {}

		-- Clone items
		for _, Item in pairs(Items) do
			local Clone = Item:Clone()
			Clone.Parent = Parent

			-- Register the clone
			table.insert(Clones, Clone)
			CreatedInstances[Item] = Item
		end

		-- Return the clones
		return Clones
	end;

	['CreatePart'] = function (PartType, Position, Parent)
		-- Creates a new part based on `PartType`

		-- Validate requested parent
		assert(typeof(Parent) == 'Instance', 'Invalid parent')
		assert(Security.IsLocationAllowed(Parent, Player), 'Permission denied for client')

		-- Create the part
		local NewPart = CreatePart(PartType);

		-- Position the part
		NewPart.CFrame = Position;

		-- Cache up permissions for all private areas
		local AreaPermissions = Security.GetPermissions(Security.GetSelectionAreas({ NewPart }), Player);

		-- Make sure the player is allowed to create parts in the area
		if Security.ArePartsViolatingAreas({ NewPart }, Player, false, AreaPermissions) then
			return;
		end;

		-- Parent the part
		NewPart.Parent = Parent

		-- Register the part
		CreatedInstances[NewPart] = NewPart;

		-- Return the part
		return NewPart;
	end;

	['CreateGroup'] = function (Type, Parent, Items)
		-- Creates a new group of type `Type`

		local ValidGroupTypes = {
			Model = true,
			Folder = true
		}

		-- Validate arguments
		assert(ValidGroupTypes[Type], 'Invalid group type')
		assert(typeof(Parent) == 'Instance', 'Invalid parent')
		assert(Security.IsLocationAllowed(Parent, Player), 'Permission denied for client')

		-- Check if items selectable
		if not CanModifyItems(Items) then
			return
		end

		-- Check if parts intruding into private areas
		local Parts = GetPartsFromSelection(Items)
		local AreaPermissions = Security.GetPermissions(Security.GetSelectionAreas(Parts), Player)
		if Security.ArePartsViolatingAreas(Parts, Player, true, AreaPermissions) then
			return
		end

		-- Create group
		local Group = Instance.new(Type)

		-- Attach children
		for _, Item in pairs(Items) do
			Item.Parent = Group
		end

		-- Parent group
		Group.Parent = Parent

		-- Make joints
		if Type == 'Model' then
			Group:MakeJoints()
		elseif Type == 'Folder' then
			local Parts = Support.GetDescendantsWhichAreA(Group, 'BasePart')
			for _, Part in pairs(Parts) do
				Part:MakeJoints()
			end
		end

		-- Return the new group
		return Group

	end,

	['Ungroup'] = function (Groups)

		-- Validate arguments
		assert(type(Groups) == 'table', 'Invalid groups')

		-- Check if items modifiable
		if not CanModifyItems(Groups) then
			return
		end

		-- Check if parts intruding into private areas
		local Parts = GetPartsFromSelection(Groups)
		local AreaPermissions = Security.GetPermissions(Security.GetSelectionAreas(Parts), Player)
		if Security.ArePartsViolatingAreas(Parts, Player, true, AreaPermissions) then
			return
		end

		local Results = {}

		-- Check each group
		for Key, Group in ipairs(Groups) do
			assert(typeof(Group) == 'Instance', 'Invalid group')

			-- Track group children
			local Children = {}
			Results[Key] = Children

			-- Unpack group children into parent
			local NewParent = Group.Parent
			for _, Child in pairs(Group:GetChildren()) do
				LastParents[Child] = Group
				Children[#Children + 1] = Child
				Child.Parent = NewParent
				if Child:IsA 'BasePart' then
					Child:MakeJoints()
				elseif Child:IsA 'Folder' then
					local Parts = Support.GetDescendantsWhichAreA(Child, 'BasePart')
					for _, Part in pairs(Parts) do
						Part:MakeJoints()
					end
				end
			end

			-- Track removing group
			LastParents[Group] = Group.Parent
			CreatedInstances[Group] = Group

			-- Remove group
			Group.Parent = nil
		end

		return Results
	end,

	['SetParent'] = function (Items, Parent)

		-- Validate arguments
		assert(type(Items) == 'table', 'Invalid items')
		assert(type(Parent) == 'table' or typeof(Parent) == 'Instance', 'Invalid parent')

		-- Check if items modifiable
		if not CanModifyItems(Items) then
			return
		end

		-- Check if parts intruding into private areas
		local Parts = GetPartsFromSelection(Items)
		local AreaPermissions = Security.GetPermissions(Security.GetSelectionAreas(Parts), Player)
		if Security.ArePartsViolatingAreas(Parts, Player, true, AreaPermissions) then
			return
		end

		-- Move each item to different parent
		if type(Parent) == 'table' then
			for Key, Item in pairs(Items) do
				local Parent = Parent[Key]

				-- Check if parent allowed
				assert(Security.IsLocationAllowed(Parent, Player), 'Permission denied for client')

				-- Move item
				Item.Parent = Parent
				if Item:IsA 'BasePart' then
					Item:MakeJoints()
				elseif Item:IsA 'Folder' then
					local Parts = Support.GetDescendantsWhichAreA(Item, 'BasePart')
					for _, Part in pairs(Parts) do
						Part:MakeJoints()
					end
				end
			end

		-- Move to single parent
		elseif typeof(Parent) == 'Instance' then
			assert(Security.IsLocationAllowed(Parent, Player), 'Permission denied for client')

			-- Reparent items
			for _, Item in pairs(Items) do
				Item.Parent = Parent
				if Item:IsA 'BasePart' then
					Item:MakeJoints()
				elseif Item:IsA 'Folder' then
					local Parts = Support.GetDescendantsWhichAreA(Item, 'BasePart')
					for _, Part in pairs(Parts) do
						Part:MakeJoints()
					end
				end
			end
		end

	end,

	['SetName'] = function (Items, Name)

		-- Validate arguments
		assert(type(Items) == 'table', 'Invalid items')
		assert(type(Name) == 'table' or type(Name) == 'string', 'Invalid name')

		-- Check if items modifiable
		if not CanModifyItems(Items) then
			return
		end

		-- Check if parts intruding into private areas
		local Parts = GetPartsFromSelection(Items)
		local AreaPermissions = Security.GetPermissions(Security.GetSelectionAreas(Parts), Player)
		if Security.ArePartsViolatingAreas(Parts, Player, true, AreaPermissions) then
			return
		end

		-- Rename each item to a different name
		if type(Name) == 'table' then
			for Key, Item in pairs(Items) do
				local Name = Name[Key]
				Item.Name = Name
			end

		-- Rename to single name
		elseif type(Name) == 'string' then
			for _, Item in pairs(Items) do
				Item.Name = Name
			end
		end

	end,

	['Remove'] = function (Objects)
		-- Removes the given objects

		-- Get the relevant parts for each object, for permission checking
		local Parts = {};

		-- Go through the selection
		for _, Object in pairs(Objects) do

			-- Make sure the object still exists
			if Object then

				if Object:IsA 'BasePart' then
					table.insert(Parts, Object);

				elseif Object:IsA 'Smoke' or Object:IsA 'Fire' or Object:IsA 'Sparkles' or Object:IsA 'DataModelMesh' or Object:IsA 'Decal' or Object:IsA 'Texture' or Object:IsA 'Light' then
					table.insert(Parts, Object.Parent);

				elseif Object:IsA 'Model' or Object:IsA 'Folder' then
					Support.ConcatTable(Parts, Support.GetDescendantsWhichAreA(Object, 'BasePart'))
				end

			end;

		end;

		-- Check if items modifiable
		if not CanModifyItems(Objects) then
			return
		end

		-- Check if parts intruding into private areas
		if Security.ArePartsViolatingAreas(Parts, Player, true) then
			return
		end

		-- After confirming permissions, perform each removal
		for _, Object in pairs(Objects) do

			-- Store the part's current parent
			LastParents[Object] = Object.Parent;

			-- Register the object
			CreatedInstances[Object] = Object;

			-- Set the object's current parent to `nil`
			Object.Parent = nil;

		end;

	end;

	['UndoRemove'] = function (Objects)
		-- Restores the given removed objects to their last parents

		-- Get the relevant parts for each object, for permission checking
		local Parts = {};

		-- Go through the selection
		for _, Object in pairs(Objects) do

			-- Make sure the object still exists, and that its last parent is registered
			if Object and LastParents[Object] then

				if Object:IsA 'BasePart' then
					table.insert(Parts, Object);

				elseif Object:IsA 'Smoke' or Object:IsA 'Fire' or Object:IsA 'Sparkles' or Object:IsA 'DataModelMesh' or Object:IsA 'Decal' or Object:IsA 'Texture' or Object:IsA 'Light' then
					table.insert(Parts, Object.Parent);

				elseif Object:IsA 'Model' or Object:IsA 'Folder' then
					Support.ConcatTable(Parts, Support.GetDescendantsWhichAreA(Object, 'BasePart'))
				end

			end;

		end;

		-- Check if items modifiable
		if not CanModifyItems(Objects) then
			return
		end

		-- Check if parts intruding into private areas
		if Security.ArePartsViolatingAreas(Parts, Player, false) then
			return
		end

		-- After confirming permissions, perform each removal
		for _, Object in pairs(Objects) do

			-- Store the part's current parent
			local LastParent = LastParents[Object];
			LastParents[Object] = Object.Parent;

			-- Register the object
			CreatedInstances[Object] = Object;

			-- Set the object's parent to the last parent
			Object.Parent = LastParent;

			-- Make joints
			if Object:IsA 'BasePart' then
				Object:MakeJoints()
			else
				local Parts = Support.GetDescendantsWhichAreA(Object, 'BasePart')
				for _, Part in pairs(Parts) do
					Part:MakeJoints()
				end
			end

		end;

	end;

	['SyncMove'] = function (Changes)
		-- Updates parts server-side given their new CFrames

		-- Grab a list of every part we're attempting to modify
		local Parts = {};
		for _, Change in pairs(Changes) do
			if Change.Part then
				table.insert(Parts, Change.Part);
			end;
		end;

		-- Ensure parts are selectable
		if not CanModifyItems(Parts) then
			return;
		end;

		-- Cache up permissions for all private areas
		local AreaPermissions = Security.GetPermissions(Security.GetSelectionAreas(Parts), Player);

		-- Make sure the player is allowed to perform changes to these parts
		if Security.ArePartsViolatingAreas(Parts, Player, true, AreaPermissions) then
			return;
		end;

		-- Reorganize the changes
		local ChangeSet = {};
		for _, Change in pairs(Changes) do
			if Change.Part then
				Change.InitialState = { Anchored = Change.Part.Anchored, CFrame = Change.Part.CFrame };
				ChangeSet[Change.Part] = Change;
			end;
		end;

		-- Preserve joints
		for Part, Change in pairs(ChangeSet) do
			Change.Joints = PreserveJoints(Part, ChangeSet);
		end;

		-- Perform each change
		for Part, Change in pairs(ChangeSet) do

			-- Stabilize the parts and maintain the original anchor state
			Part.Anchored = true;
			Part:BreakJoints();
			Part.Velocity = Vector3.new();
			Part.RotVelocity = Vector3.new();

			-- Set the part's CFrame
			Part.CFrame = Change.CFrame;

		end;

		-- Make sure the player is authorized to move parts into this area
		if Security.ArePartsViolatingAreas(Parts, Player, false, AreaPermissions) then

			-- Revert changes if unauthorized destination
			for Part, Change in pairs(ChangeSet) do
				Part.CFrame = Change.InitialState.CFrame;
			end;

		end;

		-- Restore the parts' original states
		for Part, Change in pairs(ChangeSet) do
			Part:MakeJoints();
			RestoreJoints(Change.Joints);
			Part.Anchored = Change.InitialState.Anchored;
		end;

	end;

	['SyncResize'] = function (Changes)
		-- Updates parts server-side given their new sizes and CFrames

		-- Grab a list of every part we're attempting to modify
		local Parts = {};
		for _, Change in pairs(Changes) do
			if Change.Part then
				table.insert(Parts, Change.Part);
			end;
		end;

		-- Ensure parts are selectable
		if not CanModifyItems(Parts) then
			return;
		end;

		-- Cache up permissions for all private areas
		local AreaPermissions = Security.GetPermissions(Security.GetSelectionAreas(Parts), Player);

		-- Make sure the player is allowed to perform changes to these parts
		if Security.ArePartsViolatingAreas(Parts, Player, true, AreaPermissions) then
			return;
		end;

		-- Reorganize the changes
		local ChangeSet = {};
		for _, Change in pairs(Changes) do
			if Change.Part then
				Change.InitialState = { Anchored = Change.Part.Anchored, Size = Change.Part.Size, CFrame = Change.Part.CFrame };
				ChangeSet[Change.Part] = Change;
			end;
		end;

		-- Perform each change
		for Part, Change in pairs(ChangeSet) do

			-- Stabilize the parts and maintain the original anchor state
			Part.Anchored = true;
			Part:BreakJoints();
			Part.Velocity = Vector3.new();
			Part.RotVelocity = Vector3.new();

			-- Set the part's size and CFrame
			Part.Size = Change.Size;
			Part.CFrame = Change.CFrame;

		end;

		-- Make sure the player is authorized to move parts into this area
		if Security.ArePartsViolatingAreas(Parts, Player, false, AreaPermissions) then

			-- Revert changes if unauthorized destination
			for Part, Change in pairs(ChangeSet) do
				Part.Size = Change.InitialState.Size;
				Part.CFrame = Change.InitialState.CFrame;
			end;

		end;

		-- Restore the parts' original states
		for Part, Change in pairs(ChangeSet) do
			Part:MakeJoints();
			Part.Anchored = Change.InitialState.Anchored;
		end;

	end;

	['SyncRotate'] = function (Changes)
		-- Updates parts server-side given their new CFrames

		-- Grab a list of every part we're attempting to modify
		local Parts = {};
		for _, Change in pairs(Changes) do
			if Change.Part then
				table.insert(Parts, Change.Part);
			end;
		end;

		-- Ensure parts are selectable
		if not CanModifyItems(Parts) then
			return;
		end;

		-- Cache up permissions for all private areas
		local AreaPermissions = Security.GetPermissions(Security.GetSelectionAreas(Parts), Player);

		-- Make sure the player is allowed to perform changes to these parts
		if Security.ArePartsViolatingAreas(Parts, Player, true, AreaPermissions) then
			return;
		end;

		-- Reorganize the changes
		local ChangeSet = {};
		for _, Change in pairs(Changes) do
			if Change.Part then
				Change.InitialState = { Anchored = Change.Part.Anchored, CFrame = Change.Part.CFrame };
				ChangeSet[Change.Part] = Change;
			end;
		end;

		-- Preserve joints
		for Part, Change in pairs(ChangeSet) do
			Change.Joints = PreserveJoints(Part, ChangeSet);
		end;

		-- Perform each change
		for Part, Change in pairs(ChangeSet) do

			-- Stabilize the parts and maintain the original anchor state
			Part.Anchored = true;
			Part:BreakJoints();
			Part.Velocity = Vector3.new();
			Part.RotVelocity = Vector3.new();

			-- Set the part's CFrame
			Part.CFrame = Change.CFrame;

		end;

		-- Make sure the player is authorized to move parts into this area
		if Security.ArePartsViolatingAreas(Parts, Player, false, AreaPermissions) then

			-- Revert changes if unauthorized destination
			for Part, Change in pairs(ChangeSet) do
				Part.CFrame = Change.InitialState.CFrame;
			end;

		end;

		-- Restore the parts' original states
		for Part, Change in pairs(ChangeSet) do
			Part:MakeJoints();
			RestoreJoints(Change.Joints);
			Part.Anchored = Change.InitialState.Anchored;
		end;

	end;

	['SyncColor'] = function (Changes)
		-- Updates parts server-side given their new colors

		-- Grab a list of every part we're attempting to modify
		local Parts = {};
		for _, Change in pairs(Changes) do
			if Change.Part then
				table.insert(Parts, Change.Part);
			end;
		end;

		-- Ensure parts are selectable
		if not CanModifyItems(Parts) then
			return;
		end;

		-- Cache up permissions for all private areas
		local AreaPermissions = Security.GetPermissions(Security.GetSelectionAreas(Parts), Player);

		-- Make sure the player is allowed to perform changes to these parts
		if Security.ArePartsViolatingAreas(Parts, Player, true, AreaPermissions) then
			return;
		end;

		-- Reorganize the changes
		local ChangeSet = {};
		for _, Change in pairs(Changes) do
			if Change.Part then
				ChangeSet[Change.Part] = Change;
			end;
		end;

		-- Perform each change
		for Part, Change in pairs(ChangeSet) do

			-- Set the part's color
			Part.Color = Change.Color;

			-- If this part is a union, set its UsePartColor state
			if Part.ClassName == 'UnionOperation' then
				Part.UsePartColor = Change.UnionColoring;
			end;

		end;

	end;

	['SyncSurface'] = function (Changes)
		-- Updates parts server-side given their new surfaces

		-- Grab a list of every part we're attempting to modify
		local Parts = {};
		for _, Change in pairs(Changes) do
			if Change.Part then
				table.insert(Parts, Change.Part);
			end;
		end;

		-- Ensure parts are selectable
		if not CanModifyItems(Parts) then
			return;
		end;

		-- Cache up permissions for all private areas
		local AreaPermissions = Security.GetPermissions(Security.GetSelectionAreas(Parts), Player);

		-- Make sure the player is allowed to perform changes to these parts
		if Security.ArePartsViolatingAreas(Parts, Player, true, AreaPermissions) then
			return;
		end;

		-- Reorganize the changes
		local ChangeSet = {};
		for _, Change in pairs(Changes) do
			if Change.Part then
				ChangeSet[Change.Part] = Change;
			end;
		end;

		-- Perform each change
		for Part, Change in pairs(ChangeSet) do

			-- Apply each surface change
			for Surface, SurfaceType in pairs(Change.Surfaces) do
				Part[Surface .. 'Surface'] = SurfaceType;
			end;

		end;

	end;

	['CreateLights'] = function (Changes)
		-- Creates lights in the given parts

		-- Grab a list of every part we're attempting to modify
		local Parts = {};
		for _, Change in pairs(Changes) do
			if Change.Part then
				table.insert(Parts, Change.Part);
			end;
		end;

		-- Ensure parts are selectable
		if not CanModifyItems(Parts) then
			return;
		end;

		-- Cache up permissions for all private areas
		local AreaPermissions = Security.GetPermissions(Security.GetSelectionAreas(Parts), Player);

		-- Make sure the player is allowed to perform changes to these parts
		if Security.ArePartsViolatingAreas(Parts, Player, true, AreaPermissions) then
			return;
		end;

		-- Reorganize the changes
		local ChangeSet = {};
		for _, Change in pairs(Changes) do
			if Change.Part then
				ChangeSet[Change.Part] = Change;
			end;
		end;

		-- Make a list of allowed light type requests
		local AllowedLightTypes = { PointLight = true, SurfaceLight = true, SpotLight = true };

		-- Keep track of the newly created lights
		local Lights = {};

		-- Create each light
		for Part, Change in pairs(ChangeSet) do

			-- Make sure the requested light type is valid
			if AllowedLightTypes[Change.LightType] then

				-- Create the light
				local Light = Instance.new(Change.LightType, Part);
				table.insert(Lights, Light);

				-- Register the light
				CreatedInstances[Light] = Light;

			end;

		end;

		-- Return the new lights
		return Lights;

	end;

	['SyncLighting'] = function (Changes)
		-- Updates aspects of the given selection's lights

		-- Grab a list of every part we're attempting to modify
		local Parts = {};
		for _, Change in pairs(Changes) do
			if Change.Part then
				table.insert(Parts, Change.Part);
			end;
		end;

		-- Ensure parts are selectable
		if not CanModifyItems(Parts) then
			return;
		end;

		-- Cache up permissions for all private areas
		local AreaPermissions = Security.GetPermissions(Security.GetSelectionAreas(Parts), Player);

		-- Make sure the player is allowed to perform changes to these parts
		if Security.ArePartsViolatingAreas(Parts, Player, true, AreaPermissions) then
			return;
		end;

		-- Reorganize the changes
		local ChangeSet = {};
		for _, Change in pairs(Changes) do
			if Change.Part then
				ChangeSet[Change.Part] = Change;
			end;
		end;

		-- Make a list of allowed light type requests
		local AllowedLightTypes = { PointLight = true, SurfaceLight = true, SpotLight = true };

		-- Update each part's lights
		for Part, Change in pairs(ChangeSet) do

			-- Make sure that the light type requested is valid
			if AllowedLightTypes[Change.LightType] then

				-- Grab the part's light
				local Light = Support.GetChildOfClass(Part, Change.LightType);

				-- Make sure the light exists
				if Light then

					-- Make the requested changes
					if Change.Range ~= nil then
						Light.Range = Change.Range;
					end;
					if Change.Brightness ~= nil then
						Light.Brightness = Change.Brightness;
					end;
					if Change.Color ~= nil then
						Light.Color = Change.Color;
					end;
					if Change.Shadows ~= nil then
						Light.Shadows = Change.Shadows;
					end;
					if Change.Face ~= nil then
						Light.Face = Change.Face;
					end;
					if Change.Angle ~= nil then
						Light.Angle = Change.Angle;
					end;

				end;

			end;

		end;

	end;

	['CreateDecorations'] = function (Changes)
		-- Creates decorations in the given parts

		-- Grab a list of every part we're attempting to modify
		local Parts = {};
		for _, Change in pairs(Changes) do
			if Change.Part then
				table.insert(Parts, Change.Part);
			end;
		end;

		-- Ensure parts are selectable
		if not CanModifyItems(Parts) then
			return;
		end;

		-- Cache up permissions for all private areas
		local AreaPermissions = Security.GetPermissions(Security.GetSelectionAreas(Parts), Player);

		-- Make sure the player is allowed to perform changes to these parts
		if Security.ArePartsViolatingAreas(Parts, Player, true, AreaPermissions) then
			return;
		end;

		-- Reorganize the changes
		local ChangeSet = {};
		for _, Change in pairs(Changes) do
			if Change.Part then
				ChangeSet[Change.Part] = Change;
			end;
		end;

		-- Make a list of allowed decoration type requests
		local AllowedDecorationTypes = { Smoke = true, Fire = true, Sparkles = true };

		-- Keep track of the newly created decorations
		local Decorations = {};

		-- Create each decoration
		for Part, Change in pairs(ChangeSet) do

			-- Make sure the requested decoration type is valid
			if AllowedDecorationTypes[Change.DecorationType] then

				-- Create the decoration
				local Decoration = Instance.new(Change.DecorationType, Part);
				table.insert(Decorations, Decoration);

				-- Register the decoration
				CreatedInstances[Decoration] = Decoration;

			end;

		end;

		-- Return the new decorations
		return Decorations;

	end;

	['SyncDecorate'] = function (Changes)
		-- Updates aspects of the given selection's decorations

		-- Grab a list of every part we're attempting to modify
		local Parts = {};
		for _, Change in pairs(Changes) do
			if Change.Part then
				table.insert(Parts, Change.Part);
			end;
		end;

		-- Ensure parts are selectable
		if not CanModifyItems(Parts) then
			return;
		end;

		-- Cache up permissions for all private areas
		local AreaPermissions = Security.GetPermissions(Security.GetSelectionAreas(Parts), Player);

		-- Make sure the player is allowed to perform changes to these parts
		if Security.ArePartsViolatingAreas(Parts, Player, true, AreaPermissions) then
			return;
		end;

		-- Reorganize the changes
		local ChangeSet = {};
		for _, Change in pairs(Changes) do
			if Change.Part then
				ChangeSet[Change.Part] = Change;
			end;
		end;

		-- Make a list of allowed decoration type requests
		local AllowedDecorationTypes = { Smoke = true, Fire = true, Sparkles = true };

		-- Update each part's decorations
		for Part, Change in pairs(ChangeSet) do

			-- Make sure that the decoration type requested is valid
			if AllowedDecorationTypes[Change.DecorationType] then

				-- Grab the part's decoration
				local Decoration = Support.GetChildOfClass(Part, Change.DecorationType);

				-- Make sure the decoration exists
				if Decoration then

					-- Make the requested changes
					if Change.Color ~= nil then
						Decoration.Color = Change.Color;
					end;
					if Change.Opacity ~= nil then
						Decoration.Opacity = Change.Opacity;
					end;
					if Change.RiseVelocity ~= nil then
						Decoration.RiseVelocity = Change.RiseVelocity;
					end;
					if Change.Size ~= nil then
						Decoration.Size = Change.Size;
					end;
					if Change.Heat ~= nil then
						Decoration.Heat = Change.Heat;
					end;
					if Change.SecondaryColor ~= nil then
						Decoration.SecondaryColor = Change.SecondaryColor;
					end;
					if Change.SparkleColor ~= nil then
						Decoration.SparkleColor = Change.SparkleColor;
					end;

				end;

			end;

		end;

	end;

	['CreateMeshes'] = function (Changes)
		-- Creates meshes in the given parts

		-- Grab a list of every part we're attempting to modify
		local Parts = {};
		for _, Change in pairs(Changes) do
			if Change.Part then
				table.insert(Parts, Change.Part);
			end;
		end;

		-- Ensure parts are selectable
		if not CanModifyItems(Parts) then
			return;
		end;

		-- Cache up permissions for all private areas
		local AreaPermissions = Security.GetPermissions(Security.GetSelectionAreas(Parts), Player);

		-- Make sure the player is allowed to perform changes to these parts
		if Security.ArePartsViolatingAreas(Parts, Player, true, AreaPermissions) then
			return;
		end;

		-- Reorganize the changes
		local ChangeSet = {};
		for _, Change in pairs(Changes) do
			if Change.Part then
				ChangeSet[Change.Part] = Change;
			end;
		end;

		-- Keep track of the newly created meshes
		local Meshes = {};

		-- Create each mesh
		for Part, Change in pairs(ChangeSet) do

			-- Create the mesh
			local Mesh = Instance.new('SpecialMesh', Part);
			table.insert(Meshes, Mesh);

			-- Register the mesh
			CreatedInstances[Mesh] = Mesh;

		end;

		-- Return the new meshes
		return Meshes;

	end;

	['SyncMesh'] = function (Changes)
		-- Updates aspects of the given selection's meshes

		-- Grab a list of every part we're attempting to modify
		local Parts = {};
		for _, Change in pairs(Changes) do
			if Change.Part then
				table.insert(Parts, Change.Part);
			end;
		end;

		-- Ensure parts are selectable
		if not CanModifyItems(Parts) then
			return;
		end;

		-- Cache up permissions for all private areas
		local AreaPermissions = Security.GetPermissions(Security.GetSelectionAreas(Parts), Player);

		-- Make sure the player is allowed to perform changes to these parts
		if Security.ArePartsViolatingAreas(Parts, Player, true, AreaPermissions) then
			return;
		end;

		-- Reorganize the changes
		local ChangeSet = {};
		for _, Change in pairs(Changes) do
			if Change.Part then
				ChangeSet[Change.Part] = Change;
			end;
		end;

		-- Update each part's meshes
		for Part, Change in pairs(ChangeSet) do

			-- Grab the part's mesh
			local Mesh = Support.GetChildOfClass(Part, 'SpecialMesh');

			-- Make sure the mesh exists
			if Mesh then

				-- Make the requested changes
				if Change.VertexColor ~= nil then
					Mesh.VertexColor = Change.VertexColor;
				end;
				if Change.MeshType ~= nil then
					Mesh.MeshType = Change.MeshType;
				end;
				if Change.Scale ~= nil then
					Mesh.Scale = Change.Scale;
				end;
				if Change.Offset ~= nil then
					Mesh.Offset = Change.Offset;
				end;
				if Change.MeshId ~= nil then
					Mesh.MeshId = Change.MeshId;
				end;
				if Change.TextureId ~= nil then
					Mesh.TextureId = Change.TextureId;
				end;

			end;

		end;

	end;

	['CreateTextures'] = function (Changes)
		-- Creates textures in the given parts

		-- Grab a list of every part we're attempting to modify
		local Parts = {};
		for _, Change in pairs(Changes) do
			if Change.Part then
				table.insert(Parts, Change.Part);
			end;
		end;

		-- Ensure parts are selectable
		if not CanModifyItems(Parts) then
			return;
		end;

		-- Cache up permissions for all private areas
		local AreaPermissions = Security.GetPermissions(Security.GetSelectionAreas(Parts), Player);

		-- Make sure the player is allowed to perform changes to these parts
		if Security.ArePartsViolatingAreas(Parts, Player, true, AreaPermissions) then
			return;
		end;

		-- Reorganize the changes
		local ChangeSet = {};
		for _, Change in pairs(Changes) do
			if Change.Part then
				ChangeSet[Change.Part] = Change;
			end;
		end;

		-- Make a list of allowed texture type requests
		local AllowedTextureTypes = { Texture = true, Decal = true };

		-- Keep track of the newly created textures
		local Textures = {};

		-- Create each texture
		for Part, Change in pairs(ChangeSet) do

			-- Make sure the requested light type is valid
			if AllowedTextureTypes[Change.TextureType] then

				-- Create the texture
				local Texture = Instance.new(Change.TextureType, Part);
				Texture.Face = Change.Face;
				table.insert(Textures, Texture);

				-- Register the texture
				CreatedInstances[Texture] = Texture;

			end;

		end;

		-- Return the new textures
		return Textures;

	end;

	['SyncTexture'] = function (Changes)
		-- Updates aspects of the given selection's textures

		-- Grab a list of every part we're attempting to modify
		local Parts = {};
		for _, Change in pairs(Changes) do
			if Change.Part then
				table.insert(Parts, Change.Part);
			end;
		end;

		-- Ensure parts are selectable
		if not CanModifyItems(Parts) then
			return;
		end;

		-- Cache up permissions for all private areas
		local AreaPermissions = Security.GetPermissions(Security.GetSelectionAreas(Parts), Player);

		-- Make sure the player is allowed to perform changes to these parts
		if Security.ArePartsViolatingAreas(Parts, Player, true, AreaPermissions) then
			return;
		end;

		-- Reorganize the changes
		local ChangeSet = {};
		for _, Change in pairs(Changes) do
			if Change.Part then
				ChangeSet[Change.Part] = Change;
			end;
		end;

		-- Make a list of allowed texture type requests
		local AllowedTextureTypes = { Texture = true, Decal = true };

		-- Update each part's textures
		for Part, Change in pairs(ChangeSet) do

			-- Make sure that the texture type requested is valid
			if AllowedTextureTypes[Change.TextureType] then

				-- Get the right textures within the part
				for _, Texture in pairs(Part:GetChildren()) do
					if Texture.ClassName == Change.TextureType and Texture.Face == Change.Face then

						-- Perform the changes
						if Change.Texture ~= nil then
							Texture.Texture = Change.Texture;
						end;
						if Change.Transparency ~= nil then
							Texture.Transparency = Change.Transparency;
						end;
						if Change.StudsPerTileU ~= nil then
							Texture.StudsPerTileU = Change.StudsPerTileU;
						end;
						if Change.StudsPerTileV ~= nil then
							Texture.StudsPerTileV = Change.StudsPerTileV;
						end;

					end;
				end;

			end;

		end;

	end;

	['SyncAnchor'] = function (Changes)
		-- Updates parts server-side given their new anchor status

		-- Grab a list of every part we're attempting to modify
		local Parts = {};
		for _, Change in pairs(Changes) do
			if Change.Part then
				table.insert(Parts, Change.Part);
			end;
		end;

		-- Ensure parts are selectable
		if not CanModifyItems(Parts) then
			return;
		end;

		-- Cache up permissions for all private areas
		local AreaPermissions = Security.GetPermissions(Security.GetSelectionAreas(Parts), Player);

		-- Make sure the player is allowed to perform changes to these parts
		if Security.ArePartsViolatingAreas(Parts, Player, true, AreaPermissions) then
			return;
		end;

		-- Reorganize the changes
		local ChangeSet = {};
		for _, Change in pairs(Changes) do
			if Change.Part then
				ChangeSet[Change.Part] = Change;
			end;
		end;

		-- Perform each change
		for Part, Change in pairs(ChangeSet) do
			Part.Anchored = Change.Anchored;
		end;

	end;

	['SyncCollision'] = function (Changes)
		-- Updates parts server-side given their new collision status

		-- Grab a list of every part we're attempting to modify
		local Parts = {};
		for _, Change in pairs(Changes) do
			if Change.Part then
				table.insert(Parts, Change.Part);
			end;
		end;

		-- Ensure parts are selectable
		if not CanModifyItems(Parts) then
			return;
		end;

		-- Cache up permissions for all private areas
		local AreaPermissions = Security.GetPermissions(Security.GetSelectionAreas(Parts), Player);

		-- Make sure the player is allowed to perform changes to these parts
		if Security.ArePartsViolatingAreas(Parts, Player, true, AreaPermissions) then
			return;
		end;

		-- Reorganize the changes
		local ChangeSet = {};
		for _, Change in pairs(Changes) do
			if Change.Part then
				ChangeSet[Change.Part] = Change;
			end;
		end;

		-- Perform each change
		for Part, Change in pairs(ChangeSet) do
			Part.CanCollide = Change.CanCollide;
		end;

	end;

	['SyncMaterial'] = function (Changes)
		-- Updates parts server-side given their new material

		-- Grab a list of every part we're attempting to modify
		local Parts = {};
		for _, Change in pairs(Changes) do
			if Change.Part then
				table.insert(Parts, Change.Part);
			end;
		end;

		-- Ensure parts are selectable
		if not CanModifyItems(Parts) then
			return;
		end;

		-- Cache up permissions for all private areas
		local AreaPermissions = Security.GetPermissions(Security.GetSelectionAreas(Parts), Player);

		-- Make sure the player is allowed to perform changes to these parts
		if Security.ArePartsViolatingAreas(Parts, Player, true, AreaPermissions) then
			return;
		end;

		-- Reorganize the changes
		local ChangeSet = {};
		for _, Change in pairs(Changes) do
			if Change.Part then
				ChangeSet[Change.Part] = Change;
			end;
		end;

		-- Perform each change
		for Part, Change in pairs(ChangeSet) do
			if Change.Material ~= nil then
				Part.Material = Change.Material;
			end;
			if Change.Transparency ~= nil then
				Part.Transparency = Change.Transparency;
			end;
			if Change.Reflectance ~= nil then
				Part.Reflectance = Change.Reflectance;
			end;
		end;

	end;

	['CreateWelds'] = function (Parts, TargetPart)
		-- Creates welds for the given parts to the target part

		-- Ensure parts are selectable
		if not CanModifyItems(Parts) then
			return;
		end;

		-- Cache up permissions for all private areas
		local AreaPermissions = Security.GetPermissions(Security.GetSelectionAreas(Parts), Player);

		-- Make sure the player is allowed to perform changes to these parts
		if Security.ArePartsViolatingAreas(Parts, Player, true, AreaPermissions) then
			return;
		end;

		local Welds = {};

		-- Create the welds
		for _, Part in pairs(Parts) do

			-- Make sure we're not welding this part to itself
			if Part ~= TargetPart then

				-- Calculate the offset of the part from the target part
				local Offset = Part.CFrame:toObjectSpace(TargetPart.CFrame);

				-- Create the weld
				local Weld = Instance.new('Weld');
				Weld.Name = 'BTWeld';
				Weld.Part0 = TargetPart;
				Weld.Part1 = Part;
				Weld.C1 = Offset;
				Weld.Archivable = true;
				Weld.Parent = TargetPart;

				-- Register the weld
				CreatedInstances[Weld] = Weld;
				table.insert(Welds, Weld);

			end;

		end;

		-- Return the welds created
		return Welds;
	end;

	['RemoveWelds'] = function (Welds)
		-- Removes the given welds

		local Parts = {};

		-- Go through each weld
		for _, Weld in pairs(Welds) do

			-- Make sure each given weld is valid
			if Weld.ClassName ~= 'Weld' then
				return;
			end;

			-- Collect the relevant parts for this weld
			table.insert(Parts, Weld.Part0);
			table.insert(Parts, Weld.Part1);

		end;

		-- Ensure parts are selectable
		if not CanModifyItems(Parts) then
			return;
		end;

		local WeldsRemoved = 0;

		-- Cache up permissions for all private areas
		local AreaPermissions = Security.GetPermissions(Security.GetSelectionAreas(Parts), Player);

		-- Go through each weld
		for _, Weld in pairs(Welds) do

			-- Check the permissions on each weld-related part
			local Part0Unauthorized = Security.ArePartsViolatingAreas({ Weld.Part0 }, Player, true, AreaPermissions);
			local Part1Unauthorized = Security.ArePartsViolatingAreas({ Weld.Part1 }, Player, true, AreaPermissions);

			-- If at least one of the involved parts is authorized, remove the weld
			if not Part0Unauthorized or not Part1Unauthorized then

				-- Register the weld
				CreatedInstances[Weld] = Weld;
				LastParents[Weld] = Weld.Parent;
				WeldsRemoved = WeldsRemoved + 1;

				-- Remove the weld
				Weld.Parent = nil;

			end;

		end;

		-- Return the number of welds removed
		return WeldsRemoved;
	end;

	['UndoRemovedWelds'] = function (Welds)
		-- Restores the given removed welds

		local Parts = {};

		-- Go through each weld
		for _, Weld in pairs(Welds) do

			-- Make sure each given weld is valid
			if Weld.ClassName ~= 'Weld' then
				return;
			end;

			-- Make sure each weld has its old parent registered
			if not LastParents[Weld] then
				return;
			end;

			-- Collect the relevant parts for this weld
			table.insert(Parts, Weld.Part0);
			table.insert(Parts, Weld.Part1);

		end;

		-- Ensure parts are selectable
		if not CanModifyItems(Parts) then
			return;
		end;

		-- Cache up permissions for all private areas
		local AreaPermissions = Security.GetPermissions(Security.GetSelectionAreas(Parts), Player);

		-- Go through each weld
		for _, Weld in pairs(Welds) do

			-- Check the permissions on each weld-related part
			local Part0Unauthorized = Security.ArePartsViolatingAreas({ Weld.Part0 }, Player, false, AreaPermissions);
			local Part1Unauthorized = Security.ArePartsViolatingAreas({ Weld.Part0 }, Player, false, AreaPermissions);

			-- If at least one of the involved parts is authorized, restore the weld
			if not Part0Unauthorized or not Part1Unauthorized then

				-- Store the part's current parent
				local LastParent = LastParents[Weld];
				LastParents[Weld] = Weld.Parent;

				-- Register the weld
				CreatedInstances[Weld] = Weld;

				-- Set the weld's parent to the last parent
				Weld.Parent = LastParent;

			end;

		end;

	end;

	['Export'] = function (Parts)
		-- Serializes, exports, and returns ID for importing given parts

		-- Offload action to server-side if API is running locally
		if RunService:IsClient() and not RunService:IsStudio() then
			return SyncAPI.ServerEndpoint:InvokeServer('Export', Parts);
		end;

		-- Ensure valid selection
		assert(type(Parts) == 'table', 'Invalid item table');

		-- Ensure there are items to export
		if #Parts == 0 then
			return;
		end;

		-- Ensure parts are selectable
		if not CanModifyItems(Parts) then
			return;
		end;

		-- Cache up permissions for all private areas
		local AreaPermissions = Security.GetPermissions(Security.GetSelectionAreas(Parts), Player);

		-- Make sure the player is allowed to access these parts
		if Security.ArePartsViolatingAreas(Parts, Player, true, AreaPermissions) then
			return;
		end;

		-- Get all descendants of the parts
		local Items = Support.CloneTable(Parts);
		for _, Part in pairs(Parts) do
			Support.ConcatTable(Items, Part:GetDescendants());
		end;

		-- After confirming permissions, serialize parts
		local SerializedBuildData = Serialization.SerializeModel(Items);

		-- Push serialized data to server
		local Response = HttpService:JSONDecode(
			HttpService:PostAsync(
				'http://f3xteam.com/bt/export',
				HttpService:JSONEncode { data = SerializedBuildData, version = 3, userId = (Player and Player.UserId) },
				Enum.HttpContentType.ApplicationJson,
				true
			)
		);

		-- Return creation ID on success
		if Response.success then
			return Response.id;
		else
			error('Export failed due to server-side error', 2);
		end;

	end;

	['IsHttpServiceEnabled'] = function ()
		-- Returns whether HttpService is enabled

		-- Offload action to server-side if API is running locally
		if RunService:IsClient() then
			return SyncAPI.ServerEndpoint:InvokeServer('IsHttpServiceEnabled')
		end

		-- Return cached status if available
		if IsHttpServiceEnabled ~= nil then
			return IsHttpServiceEnabled
		end

		-- Perform test HTTP request
		local DidSucceed, Result = pcall(function ()
			return HttpService:GetAsync('https://google.com')
		end)

		-- Determine whether HttpService is enabled based on whether request succeeded
		if DidSucceed then
			IsHttpServiceEnabled = true
		elseif (not DidSucceed) and Result:match('Http requests are not enabled') then
			IsHttpServiceEnabled = false
		end

		return IsHttpServiceEnabled or false
	end;

	['ExtractMeshFromAsset'] = function (AssetId)
		-- Returns the first found mesh in the given asset

		-- Offload action to server-side if API is running locally
		if RunService:IsClient() and not RunService:IsStudio() then
			return SyncAPI.ServerEndpoint:InvokeServer('ExtractMeshFromAsset', AssetId);
		end;

		-- Ensure valid asset ID is given
		assert(type(AssetId) == 'number', 'Invalid asset ID');

		-- Return parsed response from API
		return HttpService:JSONDecode(
			HttpService:GetAsync('http://f3xteam.com/bt/getFirstMeshData/' .. AssetId)
		);

	end;

	['ExtractImageFromDecal'] = function (DecalAssetId)
		-- Returns the first image found in the given decal asset

		-- Offload action to server-side if API is running locally
		if RunService:IsClient() and not RunService:IsStudio() then
			return SyncAPI.ServerEndpoint:InvokeServer('ExtractImageFromDecal', DecalAssetId);
		end;

		-- Return direct response from the API
		return HttpService:GetAsync('http://f3xteam.com/bt/getDecalImageID/' .. DecalAssetId);

	end;

	['SetMouseLockEnabled'] = function (Enabled)
		-- Sets whether mouse lock is enabled for the current player

		-- Offload action to server-side if API is running locally
		if RunService:IsClient() and not RunService:IsStudio() then
			return SyncAPI.ServerEndpoint:InvokeServer('SetMouseLockEnabled', Enabled);
		end;

		-- Set whether mouse lock is enabled
		Player.DevEnableMouseLock = Enabled;

	end;

	['SetLocked'] = function (Items, Locked)
		-- Locks or unlocks the specified parts

		-- Validate arguments
		assert(type(Items) == 'table', 'Invalid items')
		assert(type(Locked) == 'table' or type(Locked) == 'boolean', 'Invalid lock state')

		-- Check if items modifiable
		if not CanModifyItems(Items) then
			return
		end

		-- Check if parts intruding into private areas
		local Parts = GetPartsFromSelection(Items)
		local AreaPermissions = Security.GetPermissions(Security.GetSelectionAreas(Parts), Player)
		if Security.ArePartsViolatingAreas(Parts, Player, true, AreaPermissions) then
			return
		end

		-- Set each item to a different lock state
		if type(Locked) == 'table' then
			for Key, Item in pairs(Items) do
				local Locked = Locked[Key]
				Item.Locked = Locked
			end

		-- Set to single lock state
		elseif type(Locked) == 'boolean' then
			for _, Item in pairs(Items) do
				Item.Locked = Locked
			end
		end

	end

}

function CanModifyItems(Items)
	-- Returns whether the items can be modified

	-- Check each item
	for _, Item in pairs(Items) do

		-- Catch items that cannot be reached
		local ItemAllowed = Security.IsItemAllowed(Item, Player)
		local LastParentKnown = LastParents[Item]
		if not (ItemAllowed or LastParentKnown) then
			return false
		end

		-- Catch locked parts
		if Options.DisallowLocked and (Item:IsA 'BasePart') and Item.Locked then
			return false
		end

	end

	-- Return true if all items modifiable
	return true

end

function GetPartsFromSelection(Selection)
	local Parts = {}

	-- Get parts from selection
	for _, Item in pairs(Selection) do
		if Item:IsA 'BasePart' then
			Parts[#Parts + 1] = Item

		-- Get parts within other items
		else
			for _, Descendant in pairs(Item:GetDescendants()) do
				if Descendant:IsA 'BasePart' then
					Parts[#Parts + 1] = Descendant
				end
			end
		end
	end

	-- Return parts
	return Parts
end
