local CollectionService = game:GetService('CollectionService') local httpservice = game:GetService("HttpService") local Player = game:GetService("Players").LocalPlayer -------- SETTINGS ---------- local F3X_ImportCode = "" --Leave blank for UI local Parent = workspace local RealativeCFrame = nil local Group = false -- Slow :v local ForcedAnchor = true ------ END SETTINGS -------- local Log = print local function print(...) if Log and type(Log) == 'function' then Log(...) end end local cccc = coroutine.running() function STOP() task.defer(task.cancel, cccc) end local function assert(cond, ...) if not cond then if Log and type(Log) == 'function' then Log(...) end STOP() task.defer(task.cancel, coroutine.running()) wait() end end local Types = { Part = 0, WedgePart = 1, CornerWedgePart = 2, VehicleSeat = 3, Seat = 4, TrussPart = 5, SpecialMesh = 6, Texture = 7, Decal = 8, PointLight = 9, SpotLight = 10, SurfaceLight = 11, Smoke = 12, Fire = 13, Sparkles = 14, Model = 15, Folder = 18 }; local PartTypes = { [Enum.PartType.Block.Value] = "Normal", [Enum.PartType.Ball.Value] = "Ball", [Enum.PartType.Wedge.Value] = "Wedge", [Enum.PartType.Cylinder.Value] = "Cylinder", [Enum.PartType.CornerWedge.Value] = "Corner", FromTypes = { [Types.WedgePart] = "Wedge", [Types.CornerWedgePart] = "Corner", [Types.VehicleSeat] = "Vehicle Seat", [Types.Seat] = "Seat", [Types.TrussPart] = "Truss", } } local Events = {} local MaxThreads = 1000 local ThreadWatch = {Threads = {}} function ThreadWatch:Add(Thread:thread) if typeof(Thread) == 'thread' then table.insert(ThreadWatch.Threads,Thread) end end local GabrageDebounce = false function ThreadWatch:GarbageCollect() if GabrageDebounce then return end GabrageDebounce = true local NList = {} for Index,Thread in ipairs(ThreadWatch.Threads) do if typeof(Thread) == 'thread' and coroutine.status(Thread) ~= "dead" then table.insert(NList,Thread) end end ThreadWatch.Threads = NList GabrageDebounce = false end function tcall(func,...) if #ThreadWatch.Threads > MaxThreads then repeat task.wait(); ThreadWatch:GarbageCollect() until #ThreadWatch.Threads < MaxThreads end ThreadWatch:Add(task.spawn(func,...)) end local Support = { Slice = function (Table, Start, End) -- Returns values from `Start` to `End` in `Table` local Slice = {}; -- Go through the given indices for Index = Start, End do table.insert(Slice, Table[Index]); end; -- Return the slice return Slice; end; } function filterProperties(tbl, ...) local newtbl = {} for i,iv in pairs(tbl) do for _,v in ipairs({...}) do if iv[v] then if not newtbl[i] then newtbl[i] = {} end newtbl[i][v] = tbl[i][v] end end end return newtbl end if not F3X_ImportCode or F3X_ImportCode == "" then local BTImportUI = Instance.new("ScreenGui") local Boarder = Instance.new("Frame",BTImportUI) local UICorner = Instance.new("UICorner",Boarder) local AspectRatio = Instance.new("UIAspectRatioConstraint",Boarder) local TextBox = Instance.new("TextBox",Boarder) local ButtonBGDecor = Instance.new("Frame",Boarder) local ImportButton = Instance.new("TextButton",ButtonBGDecor) local ToggleAnchor = Instance.new("ImageButton",ButtonBGDecor) local ToggleGroups = Instance.new("ImageButton",ButtonBGDecor) local txt = Instance.new("TextLabel",Boarder) local function t(I) if I.Rotation == 0 then I.Rotation = 21 I.BackgroundColor3 = Color3.new(0.2, 1, 0.3) else I:ResetPropertyToDefault("BackgroundColor3") I:ResetPropertyToDefault("Rotation") end end BTImportUI.Parent = game.Players.LocalPlayer.PlayerGui Boarder.AnchorPoint = Vector2.one/2 Boarder.Position = UDim2.fromScale(.5,.5) Boarder:TweenSize(UDim2.fromOffset(300,300)) Boarder.BackgroundColor3 = Color3.new() Boarder.Transparency = 0.3 UICorner.CornerRadius = UDim.new(.15,0) AspectRatio.AspectRatio = 2 TextBox.Size = UDim2.fromScale(0.8,0.3) TextBox.Position = UDim2.fromScale(0.1,0.1) TextBox.TextScaled = true TextBox.BackgroundColor3 = Color3.new(1, 1, 1) TextBox.Text = "" TextBox.PlaceholderText = "Whats your Creation ID?\nLeave blank to cancel" UICorner:Clone().Parent = TextBox ButtonBGDecor.Size = UDim2.fromScale(0.5,0.3) ButtonBGDecor.Position = UDim2.fromScale(0.25,0.55) ButtonBGDecor.BackgroundColor3 = Color3.new(1, .5) ImportButton.Size = UDim2.fromScale(1,0.9) ImportButton.BackgroundColor3 = Color3.new(1, 1) ImportButton.TextScaled = true ImportButton.Text = "Import" ToggleAnchor.Image = "rbxasset://textures/TagEditor/famfamfam.png" ToggleAnchor.ImageRectSize = Vector2.one*16 ToggleAnchor.ImageRectOffset = Vector2.yAxis*16 ToggleAnchor.Size = UDim2.fromOffset(16,16) ToggleAnchor.Position = UDim2.fromScale(1.05,0) ToggleAnchor.MouseButton1Click:Connect(function() t(ToggleAnchor) end) if ForcedAnchor then t(ToggleAnchor) end ToggleGroups.Image = "rbxasset://textures/ClassImages.png" ToggleGroups.ImageRectSize = Vector2.one*16 ToggleGroups.ImageRectOffset = Vector2.xAxis*2*16 ToggleGroups.Size = ToggleAnchor.Size ToggleGroups.Position = ToggleAnchor.Position + UDim2.fromOffset(0,16) ToggleGroups.MouseButton1Click:Connect(function() t(ToggleGroups) end) if Group then t(ToggleGroups) end txt.Text = "This wont work on all F3X Building Tools." txt.TextXAlignment = Enum.TextXAlignment.Left txt.TextYAlignment = Enum.TextYAlignment.Bottom txt.TextColor3 = Color3.new(1,1,1) txt.TextStrokeTransparency = 0.5 local function CloseUI() Boarder:TweenSizeAndPosition(UDim2.fromScale(0,0),UDim2.fromScale(.5,.5),nil,nil,0.5) wait(1) BTImportUI:Destroy() end repeat ImportButton.MouseButton1Click:Wait() F3X_ImportCode = TextBox.Text if F3X_ImportCode == "" then TextBox.Text = "Are you sure you want to cancel?" end until F3X_ImportCode ~= "" if F3X_ImportCode == "Are you sure you want to cancel?" then CloseUI() return end ImportButton.Text = "Close GUI" ImportButton.MouseButton1Click:Once(CloseUI) TextBox.ClearTextOnFocus = false TextBox.TextEditable = false ToggleAnchor.Visible = false ToggleGroups.Visible = false Log = function(...) TextBox.Text = "" for _,v in ipairs{...} do TextBox.Text = TextBox.Text.. tostring(v) end end Group = ToggleGroups == 21 ForcedAnchor = ToggleAnchor == 21 end print("FETCHING F3X SERVER...") local build if isfile("f3x/"..F3X_ImportCode) then build = readfile("f3x/"..F3X_ImportCode) else build = game:HttpGet('http://www.f3xteam.com/bt/export/'..F3X_ImportCode) writefile("f3x/"..F3X_ImportCode, build) end local success, Data = pcall(httpservice.JSONDecode,httpservice,build) assert(success, "ERROR: FAILED TO DECODE JSON STRING\nDid You write the correct code?") assert(Data.Version == 3, "ERROR: ONLY SUPPORTED SerializationV3.") build = nil function GetSyncAPI() return if Player.Character and Player.Character:FindFirstChildOfClass("Tool") and Player.Character:FindFirstChildOfClass("Tool"):FindFirstChildOfClass("BindableFunction") then Player.Character:FindFirstChildOfClass("Tool"):FindFirstChildOfClass("BindableFunction") else Player.Backpack:FindFirstChild("SyncAPI",true) end local SyncAPI print("Grabbing SyncAPI...") repeat SyncAPI = GetSyncAPI(); wait() until SyncAPI if not SyncAPI.Parent.Loaded.value then SyncAPI.Parent.Loaded.Changed:wait() end local function f(...) return { SyncAPI:Invoke(...) } end function Invoke(...) local s, r = pcall(f,...) if not s then warn(r) end assert(s,"ERROR: The server returned an error.") return table.unpack(r) end local MappingInstances = {} local Parts = {} Parent.ChildAdded:Connect(function(Part) if Part:IsA("BasePart") and not Part:IsA("MeshPart") then table.insert(Parts,Part) end end) function GetSparePart(PartType) for i,Part in ipairs(Parts) do if not table.find(MappingInstances,Part) then if (Part:IsA("Seat") and PartTypes.FromTypes[Types.Seat]) == PartType or (Part:IsA("VehicleSeat") and PartTypes.FromTypes[Types.VehicleSeat]) == PartType or (Part:IsA("TrussPart") and PartTypes.FromTypes[Types.TrussPart]) == PartType or PartTypes[Part.Shape.Value] == PartType then return Part end end end end function CreatePart(PartType, CF, Parent) CF = CF or RealativeCFrame local Part, replicationTag = Invoke('CreatePart', PartType, CF, Parent) if (Part == nil) and replicationTag then local existingMarker = CollectionService:GetTagged(replicationTag)[1] if existingMarker then Part = existingMarker.Parent else Part = CollectionService:GetInstanceAddedSignal(replicationTag):Wait().Parent if not Part then repeat wait((tick()%0.000001) / 0.000001); Part = GetSparePart(PartType) until Part end end end return Part end function IsAPart(Id) local Datum = Data.Items[Id] if Datum and (Datum[1] == Types.Part or Datum[1] == Types.WedgePart or Datum[1] == Types.CornerWedgePart or Datum[1] == Types.VehicleSeat or Datum[1] == Types.Seat or Datum[1] == Types.TrussPart) then return true else return false end end print("Checking Configuration") if not Parent then Parent = workspace end if not RealativeCFrame then RealativeCFrame = (Parent:FindFirstChild(F3X_ImportCode) and Parent[F3X_ImportCode]:IsA("BasePart") and Parent[F3X_ImportCode].CFrame) or CFrame.new() + (Player.Character or Player.CharacterAdded:Wait()).PrimaryPart.Position end Parts[1] = CreatePart("Normal",RealativeCFrame,Parent) print("Generating Parts...") local PartCount = 0 local FinPart = 0 for Index,Datum in ipairs(Data.Items) do if IsAPart(Index) then PartCount += 1 local PartType = PartTypes.FromTypes[Datum[1]] or PartTypes[Datum[33]] tcall(function() local Item = CreatePart(PartType,RealativeCFrame,Parent) MappingInstances[Index] = Item FinPart += 1 end) end end repeat wait(); ThreadWatch:GarbageCollect() until #ThreadWatch.Threads <= 0 --Update Part Properties function ChangeSet(Table,Value) if not Table.ns then Table.ns = {} end local Offset = Table.ns[Value.Part] or 0 Offset += 1 if not Table[Offset] then Table[Offset] = {} end Table.ns[Value.Part] = Offset table.insert(Table[Offset],Value) end function ApplyChange(Call,Table,Filter) if Filter then for _,v in ipairs(Table) do Invoke(Call,filterProperties(v,table.unpack(Filter))) end else for _,v in ipairs(Table) do Invoke(Call,v) end end end print("Grouping...") local Childrens = {} -- "buffer"? for Index,Datum in ipairs(Data.Items) do if IsAPart(Index) or Datum[1] == Types.Model or Datum[1] == Types.Folder then if not Childrens[Datum[2]] then Childrens[Datum[2]] = {Index} else table.insert(Childrens[Datum[2]],Index) end end end function Proc(Index) if not Childrens[Index] then return end local Object = MappingInstances[Index] local Instances = {} if Index == 0 then Object = Parent end for _,v in ipairs(Childrens[Index]) do table.insert(Instances,MappingInstances[v]) end if Object then tcall(Invoke,"SetParent",Instances,Object) else local Datum = Data.Items[Index] local P = MappingInstances[Datum[2]] if Datum[2] == 0 then P = Parent end local groupType if Datum[1] == Types.Model then groupType = "Model" elseif Datum[1] == Types.Folder then groupType = "Folder" end local Model = Invoke("CreateGroup",groupType,P,Instances) MappingInstances[Index] = Model end for _,v in ipairs(Childrens[Index]) do tcall(Proc,v) end end if Group then Proc(0) end repeat wait(); ThreadWatch:GarbageCollect() until #ThreadWatch.Threads <= 0 print("Updating Part Properties...") local Meshes = {} local Textures = {} local Lights = {} local Decorations = {} local Parts = {} local naming = {} for Index,Datum in ipairs(Data.Items) do if IsAPart(Index) then local Anchored = ForcedAnchor or Datum[23] == 1 ChangeSet(Parts,{ ["Part"] = MappingInstances[Index]; ["Size"] = Vector3.new(unpack(Support.Slice(Datum, 4, 6))); ["CFrame"] = RealativeCFrame:ToWorldSpace(CFrame.new(unpack(Support.Slice(Datum, 7, 18)))); ["Color"] = Color3.new(Datum[19], Datum[20], Datum[21]); ["Material"] = Enum.Material:FromValue(Datum[22]); ["Anchored"] = Anchored; ["CanCollide"] = Datum[24] == 1; ["Reflectance"] = Datum[25]; ["Transparency"] = Datum[26]; ["Surfaces"]={ ["Top"] = Enum.SurfaceType:FromValue(Datum[27]); ["Bottom"] = Enum.SurfaceType:FromValue(Datum[28]); ["Front"] = Enum.SurfaceType:FromValue(Datum[29]); ["Back"] = Enum.SurfaceType:FromValue(Datum[30]); ["Left"] = Enum.SurfaceType:FromValue(Datum[31]); ["Right"] = Enum.SurfaceType:FromValue(Datum[32]); }; }) end if not MappingInstances[Datum[2]] then continue end local Part = MappingInstances[Datum[2]] --MESHES if Datum[1] == Types.SpecialMesh then ChangeSet(Meshes,{ ["Part"] = Part; ["VertexColor"] = Vector3.new(unpack(Support.Slice(Datum, 13, 15))); ["MeshType"] = Enum.MeshType:FromValue(Datum[4]); ["Scale"] = Vector3.new(unpack(Support.Slice(Datum, 10, 12))); ["Offset"] = Vector3.new(unpack(Support.Slice(Datum, 7, 9))); ["MeshId"] = Datum[5]; ["TextureId"] = Datum[6]; }) end --TEXTURES & DECALS if (Datum[1] == Types.Texture or Datum[1] == Types.Decal) then ChangeSet(Textures,{ ["Part"] = Part; ["TextureType"] = if Datum[1] == Types.Texture then "Texture" else "Decal"; ["Texture"] = Datum[4]; ["Transparency"] = Datum[5]; ["Face"] = Enum.NormalId:FromValue(Datum[6]); ["StudsPerTileU"] = Datum[7]; ["StudsPerTileV"] = Datum[8]; }) end -- Lights if (Datum[1] == Types.PointLight or Datum[1] == Types.SpotLight or Datum[1] == Types.SurfaceLight) then local LightTypeFromTypes = { [Types.PointLight] = "PointLight", [Types.SpotLight] = "SpotLight", [Types.SurfaceLight] = "SurfaceLight" } ChangeSet(Lights,{ ["Part"] = Part; ["LightType"] = LightTypeFromTypes[Datum[1]]; ["Brightness"] = Datum[4]; ["Color"] = Color3.new(unpack(Support.Slice(Datum, 5, 7))); ["Enabled"] = Datum[8] == 1; ["Shadows"] = Datum[9] == 1; ["Range"] = Datum[10]; ["Angle"] = Datum[11]; ["Face"] = if Datum[12] then Enum.NormalId:FromValue(Datum[12]) else nil; }) end --DECORATIONS if Datum[1] == Types.Smoke then ChangeSet(Decorations,{ ["Part"] = Part; ["DecorationType"] = "Smoke"; ["Enabled"] = Datum[4] == 1; ["Color"] = Color3.new(unpack(Support.Slice(Datum, 5, 7))); ["Size"] = Datum[8]; ["RiseVelocity"] = Datum[9]; ["Opacity"] = Datum[10]; }) end; if Datum[1] == Types.Fire then ChangeSet(Decorations,{ ["Part"] = Part; ["DecorationType"] = "Fire"; ["Enabled"] = Datum[4] == 1; ["Color"] = Color3.new(unpack(Support.Slice(Datum, 5, 7))); ["SecondaryColor"] = Color3.new(unpack(Support.Slice(Datum, 8, 10))); ["Heat"] = Datum[11]; ["Size"] = Datum[12]; }) end; if Datum[1] == Types.Sparkles then ChangeSet(Decorations,{ ["Part"] = Part; ["DecorationType"] = "Sparkles"; ["Enabled"] = Datum[4] == 1; ["SparkleColor"] = Color3.new(unpack(Support.Slice(Datum, 5, 7))); }) end; if IsAPart(Index) or Datum[1] == Types.Model or Datum[1] == Types.Folder then if Datum[3] ~= '' and MappingInstances[Index] then if not naming[Datum[3]] then naming[Datum[3]] = {} end table.insert(naming[Datum[3]],MappingInstances[Index]) end end end tcall(function() ApplyChange("CreateMeshes",Meshes,{"Part"}) ApplyChange("SyncMesh",Meshes) end) tcall(function() ApplyChange("CreateTextures",Textures,{"Part","TextureType","Face"}) ApplyChange("SyncTexture",Textures) end) tcall(function() ApplyChange("CreateLights",Lights,{"Part","LightType"}) ApplyChange("SyncLighting",Lights) end) tcall(function() ApplyChange("CreateDecorations",Decorations,{"Part","DecorationType"}) ApplyChange("SyncDecorate",Decorations,{"Part","Enabled","SparkleColor","Color","SecondaryColor","Heat","Size","RiseVelocity","Opacity"}) end) do local function T(...) tcall(ApplyChange,...) end T("SyncColor",Parts,{"Part","Color"}) T("SyncMaterial",Parts,{"Part","Material","Transparency","Reflectance"}) T("SyncCollision",Parts,{"Part","CanCollide"}) T("SyncSurface",Parts,{"Part","Surfaces"}) T("SyncResize",Parts,{"Part","Size","CFrame"}) T("SyncAnchor",Parts,{"Part","Anchored"}) end for i,v in pairs(naming) do tcall(Invoke,"SetName", v, i) end repeat wait(); ThreadWatch:GarbageCollect() until #ThreadWatch.Threads <= 0 print("Done!")