Run it
Copy the script and paste it into your executor.
Players = :()
RunService = :()
StarterGui = :()
UserInputService = :()
HttpService = :()
Workspace = :()
player = Players.LocalPlayer
UI_URL =
.PlaceId ~=
()
() ~=
()
playerGui = player:(, )
playerGui
()
cfg = {
Farm = ,
TravelTime = ,
Height = ,
SpawnDelay = ,
ChestWait = ,
Dashboard = ,
SoccerMode = ,
}
state = {
Alive = ,
Status = ,
Job = ,
Motion = ,
Connections = {},
ValueConnections = {},
ChestCharacters = ({}, { __mode = }),
ClaimedFrames = ({}, { __mode = }),
Started = .(),
Arrivals = ,
Deaths = ,
GoldEarned = ,
BlocksEarned = ,
QuestCooldown = ,
GlueRequests = ,
}
ui = {}
library, window
setDashboard, updateDashboard, buildImporterUi, openBrowser, clearPreview, removeSoccerGlue
syncingToggle =
(root, ...)
_, name ({ ... })
root = root root:(name)
root
()
Workspace:((player.TeamColor) .. )
()
value = ((), )
value value.Value
(id)
key = .. (id)
id ==
key ..= (.().year)
(player, , key) ~=
(id)
(
player,
,
,
,
,
,
,
.. id
) (StarterGui, , , , , , .. id)
(id)
card = (id)
card ~= card.Visible
(folder, name)
value = (player, folder, name)
value (value.Value) == value.Value
()
character = player.Character
root = character character:()
humanoid = character character:()
character character.Parent root humanoid humanoid.Health >
character, root, humanoid
(job)
state.Alive state.Job == job
(job)
(job)
player.Character == job.Character
job.Character.Parent ~=
job.Root.Parent == job.Character
job.Humanoid.Health >
(job, seconds, requireCharacter)
deadline = .() + seconds
(job) (requireCharacter (job))
.(.(, .(, deadline - .())))
.() >= deadline
(job) ( requireCharacter (job))
()
state.BuildBusy == state.GlueRequests > state.PendingGlue ~=
()
syncingToggle =
ui.Farm
ui.Farm:(cfg.Farm, )
ui.Quests
ui.Quests:(state.Job ~= state.Job.Kind == , )
ui.Build
ui.Build:(state.Job ~= ())
ui.StopBuild
ui.StopBuild:( state.BuildBusy (state.Job state.Job.Kind == ))
ui.Preview
ui.Preview:(state.Job ~= ())
syncingToggle =
(job)
motion = state.Motion
job motion motion.Job ~= job
state.Motion =
motion
motion.Glue
(motion)
_, connection (motion.Connections)
connection:()
_, object (motion.Objects)
object:()
motion.Ball motion.Ball.Parent
motion.Ball.CanCollide = motion.BallCollision
part, collision (motion.Collisions)
part.Parent
part.CanCollide = collision
motion.Humanoid.Parent
motion.Humanoid.AutoRotate = motion.AutoRotate
motion.Humanoid.PlatformStand = motion.PlatformStand
motion.Root.Parent
motion.Root.AssemblyLinearVelocity = .zero
motion.Root.AssemblyAngularVelocity = .zero
(message)
job = state.Job
state.Job =
cfg.Farm =
job job.Kind == job.Thread job.Thread ~= .()
(.cancel, job.Thread)
(job)
()
message
state.Status = message
(job)
(job)
(, )
(job)
job.Root.Anchored
(, )
motion = {
Job = job,
Root = job.Root,
Humanoid = job.Humanoid,
AutoRotate = job.Humanoid.AutoRotate,
PlatformStand = job.Humanoid.PlatformStand,
Collisions = {},
Connections = {},
Objects = {},
}
state.Motion = motion
(part)
part:() motion.Collisions[part] ==
motion.Collisions[part] = part.CanCollide
part.CanCollide =
_, part (job.Character:())
(part)
.(motion.Connections, job.Character.DescendantAdded:(trackPart))
attachment = .()
.(motion.Objects, attachment)
attachment.Name =
attachment.Parent = job.Root
velocity = .()
.(motion.Objects, velocity)
velocity.Attachment0 = attachment
velocity.RelativeTo = .ActuatorRelativeTo.World
velocity.VelocityConstraintMode = .VelocityConstraintMode.Vector
velocity.ForceLimitsEnabled =
velocity.VectorVelocity = .zero
velocity.Parent = job.Root
motion.Velocity = velocity
job.Humanoid.Sit =
job.Humanoid.AutoRotate =
job.Humanoid.PlatformStand =
job.Root.AssemblyLinearVelocity = .zero
.(
motion.Connections,
RunService.Stepped:(()
state.Motion ~= motion
(job)
(job)
part (motion.Collisions)
part.Parent
part.CanCollide =
motion.Collisions[part] =
job.Root.AssemblyAngularVelocity = .zero
)
)
(job, target, duration)
(job) state.Motion
motion = state.Motion
motion.Ball
duration = .(duration, (job.Root.Position - target.Position).Magnitude / )
speed = .((job.Root.Position - target.Position).Magnitude / .(, duration), , )
deadline = .() + duration +
(job) state.Motion == motion .() < deadline
job.Kind == job.QuestId (() ~= job.QuestZone () ~= job.QuestId)
motion.Ball
motion.Ball.Parent motion.Ball.Anchored motion.Glue motion.Glue.Parent
destination = job.Root.CFrame:(motion.BallLocal)
(motion.Ball.Position - destination).Magnitude >
delta = target.Position - job.Root.Position
delta.Magnitude <
motion.Velocity.VectorVelocity = .zero
job.Root.AssemblyLinearVelocity = .zero
motion.Velocity.VectorVelocity = delta.Unit * .(speed, delta.Magnitude * )
RunService.Heartbeat:()
state.Motion == motion
motion.Velocity.VectorVelocity = .zero
(job, previousCharacter, timeout)
deadline = .() + timeout
(job) .() < deadline
character, root, humanoid = ()
character character ~= previousCharacter root.Anchored
job.Character, job.Root, job.Humanoid = character, root, humanoid
(job, cfg.SpawnDelay, )
.()
()
stages = (Workspace, , )
trigger = (stages, , , )
(trigger trigger:())
(, )
gates = {}
_, model (stages:())
model.Name:()
gate = model:()
gate gate:()
.(gates, gate)
#gates ~=
(, )
.(gates, (a, b)
a.Position.Z < b.Position.Z
)
gates, trigger
()
gui = (player, , )
frame = gui gui:()
gui gui.Enabled frame frame.Visible state.ClaimedFrames[frame]
remote = Workspace:()
remote remote:()
state.ClaimedFrames[frame] =
remote:()
frame.Visible =
cfg.Dashboard
(StarterGui.SetCoreGuiEnabled, StarterGui, .CoreGuiType.Backpack, )
(job)
goldBlocks = (, )
endValue = (player, , )
(goldBlocks job.GoldBlocks goldBlocks > job.GoldBlocks)
(endValue endValue.Value ~= endValue.Value ~= job.EndValue)
job.Character:(, ) ~=
(job)
gates, trigger = ()
first, last = gates[].Position, gates[#gates].Position
start = .(first.X, cfg.Height, first.Z - )
finish = .(last.X, cfg.Height, last.Z + )
state.Status =
(job)
(job, .(start), )
distance, previousZ = finish.Z - start.Z, start.Z
index, gate (gates)
state.Status = .(, index, #gates)
target = .(gate.Position.X, cfg.Height, gate.Position.Z)
duration = cfg.TravelTime * (target.Z - previousZ) / distance
(job, .(target), .(, duration))
previousZ = target.Z
(job, .(finish), cfg.TravelTime * (finish.Z - previousZ) / distance)
(trigger.Parent state.ChestCharacters[job.Character])
(, )
state.Status =
approach = trigger.CFrame * .(, , trigger.Size.Z / + )
(job, approach, ) (job)
job.GoldBlocks = (, )
endValue = (player, , )
job.EndValue = endValue endValue.Value
state.ChestCharacters[job.Character] =
state.Status =
() ==
ok, problem = (, job.Root, trigger, )
(, job.Root, trigger, )
ok
((problem), )
(job, trigger.CFrame, )
(job)
state.Arrivals +=
state.Arrivals +=
deadline = .() + cfg.ChestWait
(job) .() < deadline
(job)
state.Status =
(job)
.()
(job)
(job)
state.Status =
job.Humanoid.Health =
(job)
previousCharacter
(job) cfg.Farm
state.Status =
((job, previousCharacter, ))
(, )
state.ChestCharacters[job.Character] job.Root.Position.Z >
(, )
() ~=
(, )
reached = (job)
(job)
(job)
previousCharacter = job.Character
reached
(job)
(, )
state.Deaths +=
()
leader = (player.Team, )
leader leader.Value == player.Name
(id)
()
(, )
.() < state.QuestCooldown
(, )
id ~=
() ~=
(, )
(id)
(, )
blocks = Workspace:()
blocks
(, )
_, teammate (player.Team:())
folder = blocks:(teammate.Name)
folder
_, block (folder:())
block:() block.PrimaryPart block.PrimaryPart.Position.Z <
()
remote = Workspace:()
(remote remote:())
(, )
state.QuestCooldown = .() +
remote:(id)
state.Status =
(job, id)
deadline = .() +
(job) () ~= id .() < deadline
.()
((job) () == id)
(, )
(object, root)
names = {}
object object ~= root
.(names, object.Name:())
object = object.Parent
.(names, )
(name, id, height)
_, word ({ , , , , , , , , })
name:(word, , )
hint = id == id ==
( name:(hint, , ) ) + .(height, , )
(id, root)
candidates, seen = {}, {}
plot = ()
_, object (root:())
part
id == object:() object.MaxActivationDistance >
parent = object.Parent
part = parent:() parent parent:() parent.PrimaryPart
id ~= object:() object.Parent:()
part = object.Parent
part (id == part.CanTouch) seen[part]
seen[part] =
name = (part, root)
score = (name, id, part.Position.Y - ( plot plot.Position.Y ))
score
.(candidates, { Part = part, Interaction = object, Score = score, Name = name })
.(candidates, (a, b)
a.Score == b.Score
a.Name < b.Name
a.Score > b.Score
)
candidates
(first, second)
() ~=
ok, problem = (, first, second, )
(, first, second, )
ok
( .. (problem))
(job, id, seconds)
deadline = .() + seconds
(job) () ~= job.QuestZone
(id)
() ~= () ~= id
.()
.() >= deadline
(job) () == job.QuestZone (id)
(job, id)
(job, , )
(, )
origin = job.Root.CFrame
deadline, emptySince = .() + , .()
tried, lastNames = {}, {}
(job) () == job.QuestZone .() < deadline
(id)
() ~= id
root = (job.QuestZone, )
candidates = root (id, root) {}
selected, leastAttempts
index, candidate (candidates)
index >
previous = tried[candidate.Part]
previous (candidate.Part.Position - previous.Position).Magnitude >
previous =
count = previous previous.Count
count < (leastAttempts == count < leastAttempts)
selected = candidate
leastAttempts = count
selected
(job)
#candidates > .() - emptySince >
state.Status =
(job, , )
emptySince = .()
part, interaction = selected.Part, selected.Interaction
.(lastNames, selected.Name)
state.Motion
(job)
state.Status = ( id == id == ) .. .. part.Name
position = part.Position
previous = tried[part]
attempts = previous (position - previous.Position).Magnitude < previous.Count
tried[part] = { Position = position, Count = attempts + }
approach = part.CFrame
* (
id ==
.(, , .(, interaction.MaxActivationDistance / ))
.(, part.Size.Y / + , )
)
duration = .((job.Root.Position - approach.Position).Magnitude / , , )
reached = (job, approach, duration)
reached part.Parent (job) () == id
id ==
(interaction, (job.Root.Position - part.Position).Magnitude, )
reached = (job, part.CFrame, )
reached (job) part.Parent () == id
(job.Root, part)
(job, id, )
job.QuestId =
(job) () == job.QuestZone state.Motion
(job, origin, .((job.Root.Position - origin.Position).Magnitude / , , ))
(job)
(job, id, )
( .. id .. .. .(lastNames, ), )
state.Status =
(root)
best, bestScore, tied
_, part (root:())
part:() part.Anchored
assembly = part.AssemblyRootPart
assembly assembly.Anchored
name = (part, root)
kick = part:()
round = part:() part.Shape == .PartType.Ball
mesh = part:()
round = round (mesh mesh.MeshType == .MeshType.Sphere)
score = ( kick kick:() )
+ ( name:(, , ) )
+ ( round )
score ==
bestScore score > bestScore
best, bestScore, tied = part, score,
score == bestScore part.AssemblyRootPart ~= best.AssemblyRootPart
tied =
tied best
(root, ball)
best, bestScore
_, object (root:())
object:() object == ball object.AssemblyRootPart == ball.AssemblyRootPart
name = (object, root)
(name:(, , ) name:(, , ))
trigger = object:() ~=
trigger
score = ( object.Name:():(, , ) )
+ ( object.Transparency > )
+ .(object.Size.Magnitude, )
bestScore score > bestScore
best, bestScore = object, score
best
{ Frame = best.CFrame, Part = best }
_, object (root:())
name = object.Name:()
object:() (name == name == name == )
frame = object:()
{ Frame = frame }
(name)
tool = (player, , name) (player.Character, name)
remote = (tool, )
remote remote:()
( .. name, )
remote
removeSoccerGlue = (motion)
glue = motion.Glue
motion.GlueDeleting glue
glue.Parent
motion.Glue =
state.PendingGlue == motion
state.PendingGlue =
motion.GlueDeleting =
state.PendingGlue = motion
state.GlueRequests +=
.(()
problem
_ = ,
glue.Parent ~= motion.GlueFolder
ok, failure = (()
motion.GlueDelete:(glue)
)
ok
problem = failure
deadline = .() +
glue.Parent == motion.GlueFolder .() < deadline
.()
motion.GlueDeleting =
state.GlueRequests -=
glue.Parent ~= motion.GlueFolder
motion.Glue =
state.PendingGlue == motion
state.PendingGlue =
(
.. (problem )
)
state.Alive
state.Status =
state.Alive
()
)
(plot, ball, size)
center = plot.CFrame:(ball.Position)
margin = size.Magnitude / +
maxX, maxZ = plot.Size.X / - margin, plot.Size.Z / - margin
minX = + margin
maxX < minX maxZ <=
position = plot.CFrame:(
.(.(center.X, minX, maxX), center.Y, .(center.Z, -maxZ, maxZ))
)
relative = ball.CFrame:(position)
radii = ball.Size /
(relative / radii).Magnitude >
position
(glue, root, ball)
part = glue glue.Parent glue.PrimaryPart
part
characterConnected, ballConnected = ,
_, connected (part:())
connected == root
characterConnected =
connected == ball
ballConnected =
characterConnected ballConnected
(job, ball)
(job) ball.Parent ball.Anchored () ~=
job.GlueAttempted
(, )
plot = job.QuestZone
folder = (Workspace, , player.Name)
data = (player, , )
used = (data, )
template = (:(), , )
folder template template.PrimaryPart
(, )
data data.Value - ( used used.Value ) <
(, )
ball:() job.Root:()
(, )
build, delete = (), ()
point = (plot, ball, template.PrimaryPart.Size)
point
(, )
state.Motion
(job)
state.Status =
(job, .(point), ) (job, , )
point = (plot, ball, template.PrimaryPart.Size)
point (job.Root.Position - point).Magnitude >
(, )
motion = state.Motion
frame = .(point)
before = {}
_, model (folder:())
before[model] =
motion.GlueDelete, motion.GlueFolder = delete, folder
job.GlueAttempted =
state.GlueRequests +=
ok, problem = (()
sent, response = (()
build:(
,
data.Value,
ball,
ball.CFrame:(frame),
,
frame,
,
)
)
deadline = .() +
match
_, model (folder:())
before[model] model:() model.Name == model.PrimaryPart
model == response (model.PrimaryPart.Position - point).Magnitude <=
match
(, )
match = model
match
motion.Glue = match
.()
.() >= deadline
sent
((response), )
(, )
)
state.GlueRequests -=
state.Alive
()
(job) state.Motion ~= motion
(motion)
ok
(problem, )
deadline = .() +
(job) () == .() < deadline
(motion.Glue, job.Root, ball)
.()
(job) state.Motion ~= motion
(motion.Glue, job.Root, ball)
(, )
motion.Ball, motion.BallCollision = ball, ball.CanCollide
motion.BallOffset = job.Root.Position - ball.Position
motion.BallLocal = job.Root.CFrame:(ball.Position)
ball.CanCollide =
start = ball.Position
state.Status =
(job, .(job.Root.Position + .(, , )), )
(job) () ==
(, )
(job, , )
ball.Parent ball.Position.Y < start.Y + (motion.Glue, job.Root, ball)
(, )
(job, root, ball)
goal = (root, ball)
goal
state.Status =
kick = ball:()
kick kick:()
(job)
_ = ,
(job) ball:(root) () ~=
delta = goal.Frame.Position - ball.Position
delta.Magnitude <
direction = delta.Unit
(job, .(ball.Position - direction * ), )
(job.Root.Position - ball.Position).Magnitude <
kick:((direction + .(, , )).Unit)
(job, , )
(job) () ~=
(job, ball)
motion = state.Motion
delta = goal.Frame.Position - ball.Position
direction = delta.Magnitude > delta.Unit goal.Frame.LookVector
target = goal.Frame.Position + motion.BallOffset
(job, .(target), .(, delta.Magnitude / ))
()
(job, , )
goal.Part
goal.Part.Parent
(ball.Position - goal.Part.Position).Magnitude < goal.Part.Size.Magnitude / + ball.Size.Magnitude /
(ball, goal.Part)
(job, , )
(job, .(target + direction * (ball.Size.Magnitude / + )), )
(job, , )
(job, ball)
state.Status =
state.Motion state.Motion.Ball ~= ball
(job, ball)
(, )
motion = state.Motion
gates, trigger = ()
height = .(cfg.Height, ball.Size.Y / + ) + motion.BallOffset.Y
(job, .(job.Root.Position.X, height, job.Root.Position.Z), )
index, gate (gates)
state.Status = .(, index, #gates)
target = .(gate.Position.X, height, gate.Position.Z)
(job, .(target), (target - job.Root.Position).Magnitude / )
()
target = trigger.Position + motion.BallOffset
(job, .(target), (target - job.Root.Position).Magnitude / )
()
(job, , )
(ball.Position - trigger.Position).Magnitude >
(ball, trigger)
(job, , )
(job) () ~=
(motion)
(job) state.GlueRequests >
.()
(job)
_, connected (job.Root:())
connected == ball
(, )
ball.CanCollide = motion.BallCollision
motion.Ball =
state.ChestCharacters[job.Character]
state.ChestCharacters[job.Character] =
(job, trigger.CFrame, ) (job)
(job.Root, trigger)
(job, , )
(job)
(job, , )
(, )
root, ball
deadline = .() +
(job) () ~=
root = (job.QuestZone, )
ball = root (root)
ball
.()
.() >= deadline
ball
(, )
mode = cfg.SoccerMode
completed =
mode ~=
completed = (job, root, ball)
completed mode ~= (job) () == ball:(root)
completed = (job, ball)
(job)
(job)
completed ()
(, )
state.Status =
(job)
()
(, )
plot = ()
supported = { [] = , [] = , [] = () == , [] = , [] = }
queue, completed, skipped = {}, ,
active = ()
active ~=
supported[active]
state.Status =
.(queue, active)
_, id ({ , , , , })
id ~= active (id)
.(queue, id)
_, id (queue)
(job) () ~= plot ()
supported[id] (id)
skipped +=
job.QuestId, job.QuestZone = id, plot
owned = () == id
ok, problem = (()
owned
(job, .(, state.QuestCooldown - .()))
(id)
owned =
(job, id)
(id)
id ==
(job, , )
(, )
state.ChestCharacters[job.Character]
previous = job.Character
job.Humanoid.Health =
(job, previous, )
(, )
(job)
id ==
(job)
(job, id)
)
(job)
(job) state.GlueRequests >
.()
(job) state.PendingGlue
(, )
(job) () ~= plot ()
(id) owned
(job, )
(id)
completed +=
skipped +=
ok
( .. id .. .. (problem))
() ~=
owned () ~= id
(job, .(, state.QuestCooldown - .()))
()
(job, )
(job, )
state.Status = .(, completed, skipped)
(kind, callback)
state.Alive
(, )
state.Job ()
(, )
job = { Kind = kind }
state.Job = job
()
job.Thread = .(()
ok, problem = (callback, debug.traceback, job)
(job)
(job)
state.Job =
cfg.Farm =
()
ok
( .. (problem))
state.Status =
)
(callback)
(...)
state.Alive
ok, problem = (callback, debug.traceback, ...)
ok
( .. (problem))
dashboardCore = {}
()
gui = .()
ui.Dashboard = gui
gui.Name =
gui.ResetOnSpawn =
gui.IgnoreGuiInset =
gui.DisplayOrder =
gui.Enabled =
gui.Parent = playerGui
backdrop = .()
backdrop.Size = .(, )
backdrop.BackgroundColor3 = .(, , )
backdrop.BorderSizePixel =
backdrop.Parent = gui
stats = .()
stats.AnchorPoint = .(, )
stats.Position = .(, , , -)
stats.Size = .(, -, , )
stats.BackgroundTransparency =
stats.Parent = backdrop
(y, height, size, muted)
object = .()
object.Position = .(, y)
object.Size = .(, , , height)
object.BackgroundTransparency =
object.Font = .Font.Gotham
object.TextColor3 = muted .(, , ) .(, , )
object.Text =
object.TextSize = size
object.TextXAlignment = .TextXAlignment.Left
object.TextYAlignment = .TextYAlignment.Top
object.Parent = stats
object
ui.DashboardStatus = (, , , )
ui.DashboardTime = (, , , )
ui.DashboardRates = (, , , )
ui.DashboardTotals = (, , , )
.(
state.Connections,
UserInputService.InputBegan:((input, processed)
input.KeyCode == .KeyCode.F8 processed
( cfg.Dashboard)
)
)
setDashboard = (enabled)
cfg.Dashboard = enabled
ui.Dashboard
ui.Dashboard.Enabled = enabled
enabled
_, kind (.CoreGuiType:())
kind ~= .CoreGuiType.All dashboardCore[kind] ==
ok, value = (StarterGui.GetCoreGuiEnabled, StarterGui, kind)
ok
dashboardCore[kind] = value
(StarterGui.SetCoreGuiEnabled, StarterGui, kind, )
kind, value (dashboardCore)
(StarterGui.SetCoreGuiEnabled, StarterGui, kind, value)
.(dashboardCore)
ui.DashboardToggle
ui.DashboardToggle:(enabled, )
updateDashboard = ()
elapsed = .(, .() - state.Started)
ui.DashboardStatus
ui.DashboardStatus.Text = state.Status
ui.DashboardTime.Text = .(
,
.(elapsed / ),
.(elapsed / ) % ,
.(elapsed) %
)
ui.DashboardRates.Text = .(
,
state.GoldEarned * / elapsed,
state.GoldEarned * / elapsed,
state.BlocksEarned * / elapsed
)
ui.DashboardTotals.Text = .(
,
state.GoldEarned,
state.BlocksEarned,
state.Arrivals,
state.Deaths
)
()
library = (:(UI_URL))()
window = library.({
Name = ,
Title = ,
Parent = playerGui,
Personal = ,
AutoInitialize = ,
AutoSave = ,
LoadSettings = ,
})
ui.Window = window.Gui
ui.Window.DisplayOrder =
window.Overview.Page:()
window.Overview =
main = window:({ Name = , Icon = })
section = main:({ Title = , Collapsible = })
ui.Farm = section:({
Name = ,
Persist = ,
Callback = ((enabled)
syncingToggle
enabled
state.Job state.Job.Kind ==
()
state.Job () () ~=
()
cfg.Farm =
(, farm)
),
})
ui.DashboardToggle = section:({
Name = ,
Persist = ,
Callback = ((enabled)
syncingToggle
(enabled)
),
})
ui.Quests = section:({
Name = ,
Persist = ,
Callback = ((enabled)
syncingToggle
enabled
state.Job state.Job.Kind ==
()
state.Job ()
()
(, autoQuests)
),
})
section:({
Name = ,
Options = { , , },
Default = cfg.SoccerMode,
Persist = ,
Callback = (value)
cfg.SoccerMode = value
,
})
ui.Activity = section:({ Name = , RawText = })
()
(window)
main:()
.(
state.Connections,
ui.Window.Destroying:(()
state.Alive =
()
()
ui.Dashboard
ui.Dashboard:()
ui.Browser
ui.Browser:()
clearPreview
()
_, connection (state.Connections)
connection:()
_, entry (state.ValueConnections)
entry.Connection:()
.(state.Connections)
.(state.ValueConnections)
)
)
importer = {
Path = ,
Rows = {},
Created = {},
Declared = {},
Delay = ,
Pending = ,
Origin = ,
Plot = ,
}
(text)
state.Alive
state.Status = text
(value)
(value) == value == value .(value) < .huge
(value, label)
(value) ~=
(label .. , )
components = .(value, )
#components ~=
(label .. , )
index, component (components)
components[index] = (component)
(components[index])
(label .. , )
.(components[], components[], components[])
(value, label)
(value) ~=
(label .. , )
count =
key (value)
(key) key % ~= key < key > #value
(label .. , )
count +=
count ~= #value
(label .. , )
()
() state.Job
(, )
importer.Pending (importer.Created)
(, )
importer.Origin, importer.Plot = ,
(name, remoteName)
tool = (player, , name) (player.Character, name)
remote = (tool, remoteName )
remote remote:()
(name .. , )
remote
(record, material)
properties = {}
key, name ({ ss = , cc = })
record[key] ~=
(record[key]) ~=
(material .. .. key, )
properties[name] = record[key]
record.a ~= (record.a) ~=
(material .. , )
record.tr ~=
(record.tr) record.tr < record.tr >
(material .. , )
properties.Transparency = record.tr
unsupported =
numberNames = {
Piston = { ExtendLength = , Speed = },
Servo = { TargetAngle = },
Motor = { MaxSpeed = },
JetTurbine = { MaxSpeed = },
}
booleanNames = { ReverseRotation = , ShowCrosshairs = }
_, field ({ , })
record[field] ~= (record[field]) ~=
(material .. .. field, )
key, value (record[field] {})
(field == (value)) (field == (value) ~= )
(material .. .. (key), )
name = field == (numberNames[material] {})[key] booleanNames[key]
name
properties[name] = value
unsupported +=
record.c ~=
(record.c) ~=
(material .. , )
key, values (record.c)
key == (material == material == )
(values, )
#values ~=
(, )
_, value (values)
(value)
(, )
torque = values[ material == ]
torque < torque >
(, )
level = .(torque / ) +
.(level - .(level)) >
(, )
properties[ material == ] = .(level)
material ==
properties[] = values[]
unsupported +=
material == record.nv record.nv.MaxForce
level = .(record.nv.MaxForce / ) +
(level) level < level > .(level - .(level)) >
(, )
properties[] = .(level)
unsupported -=
properties, unsupported
(source)
#source > * *
(, )
source = source:(, )
body = source
declared = {}
source:()
source:() source:(, , )
(, )
body = source:()
body
(, )
header = source:()
header
decoded = HttpService:(header)
(decoded) ~= (decoded.Blocks) ~=
(, )
declared = decoded.Blocks
data = HttpService:(body)
(data) ~= (data.v ~= data.v ~= ) (data.b) ~=
(, )
data, declared
()
()
importer.Path ==
(, )
data, declared = ((importer.Path))
templates = (:(), )
templates
(, )
rows, ids, unresolved, unsupported = {}, {}, ,
material, records (data.b)
(material) ~=
(, )
template = templates:(material)
template template:() template.PrimaryPart
( .. material, )
material ==
material ==
material ==
material ==
material:()
( .. material, )
(records, material)
_, record (records)
(record) ~=
(record.i)
record.i % ~=
record.i <
ids[record.i]
( .. material, )
ids[record.i] =
position = (record.p, material .. )
rotation = (record.r, material .. )
position.Magnitude > rotation.Magnitude >
(, )
size = record.sz (record.sz, material .. ) template.PrimaryPart.Size
.(size.X, size.Y, size.Z) < .(size.X, size.Y, size.Z) >
(, )
record.sz material:(, , )
( .. material, )
color
record.cl
rgb = (record.cl, material .. )
.(rgb.X, rgb.Y, rgb.Z) < .(rgb.X, rgb.Y, rgb.Z) >
(, )
color = .(rgb.X, rgb.Y, rgb.Z)
record.tx ~= (material ~= (record.tx) ~= )
(, )
record.bd ~=
(record.bd, )
unresolved += #record.bd
properties, omitted = (record, material)
unsupported += omitted
baseSize = template.PrimaryPart.Size
cost = .(, size.X * size.Y * size.Z / (baseSize.X * baseSize.Y * baseSize.Z))
.(rows, {
Id = record.i,
Material = material,
Size = size,
Color = color,
Properties = properties,
Text = record.tx,
Cost = cost,
BaseVolume = baseSize.X * baseSize.Y * baseSize.Z,
Scaled = record.sz ~= ,
Frame = .(position)
* .(.(rotation.X), .(rotation.Y), .(rotation.Z)),
})
#rows >
(, )
#rows ==
(, )
material, amount (declared)
(material) ~=
data.b[material]
(amount)
amount <
amount % ~=
(, )
.(rows, (a, b)
a.Id < b.Id
)
importer.Rows, importer.Declared = rows, declared
importer.Unresolved = unresolved
(.(, #rows, unresolved))
(
.(
,
importer.Path,
#rows
)
)
unresolved > unsupported >
(
.(
,
unresolved,
unsupported
)
)
()
#importer.Rows ==
(, )
plot = ()
plot plot:()
(, )
importer.Plot importer.Plot ~= plot
(, )
importer.Origin plot.CFrame, plot
()
needs, committed = {}, {}
_, row (importer.Rows)
entry = importer.Created[row.Id]
part = entry entry.Model.Parent entry.Model.PrimaryPart
consumed = part .(, part.Size.X * part.Size.Y * part.Size.Z / row.BaseVolume)
committed[row.Material] = (committed[row.Material] ) + consumed
needs[row.Material] = (needs[row.Material] ) + .(, row.Cost - consumed)
material, amount (importer.Declared)
needs[material] = .(needs[material] , amount - (committed[material] ))
missing = {}
material, amount (needs)
data = (player, , material)
used = (data, )
available = data (data.Value)
data.Value - ( used (used.Value) used.Value )
available + < amount
.(missing, material .. .. .(amount - available) .. )
.(missing)
missing
(origin, plot)
_, row (importer.Rows)
relative = plot.CFrame:(origin * row.Frame)
_, x ({ -, })
_, y ({ -, })
_, z ({ -, })
point = relative * (row.Size * .(x, y, z) / )
.(point.X) >= plot.Size.X / .(point.Z) >= plot.Size.Z /
( .. row.Id .. , )
(actual, expected)
(actual.Position - expected.Position).Magnitude <=
actual.RightVector:(expected.RightVector) >=
actual.UpVector:(expected.UpVector) >=
()
pending = importer.Pending
pending
deadline = .() +
match
_, model (pending.Folder:())
pending.Before[model]
model:()
model.Name == pending.Row.Material
model.PrimaryPart
(model.PrimaryPart.CFrame, pending.Frame)
match
(
.. pending.Row.Id .. ,
)
match = model
match
importer.Created[pending.Row.Id] = { Model = match, Done = }
importer.Pending =
.()
.() >= deadline
(
.. pending.Row.Id .. ,
)
(job)
(job)
() ~= importer.Plot () ~=
(, )
launched = (importer.Plot, )
launched launched.Value
(, )
(job, predicate)
deadline = .() +
(job)
()
.()
.() >= deadline
(, )
(job, model, descriptor, desired, remote)
(value)
(desired) ==
(value) == .(value - desired) <
value == desired
_ = ,
(job)
previous = descriptor.(model)
(previous)
descriptor.ValueType ==
text = descriptor.Name == (desired * ) .. (desired)
remote:(descriptor.Name, { model }, text)
remote:(descriptor.Name, { model })
(job, ()
descriptor.(model) ~= previous
)
(descriptor.(model))
( .. descriptor.Name, )
(job, row, entry, tools, descriptors)
model, frame = entry.Model, importer.Origin * row.Frame
model.Parent model.PrimaryPart
( .. row.Id .. , )
(job)
model.PrimaryPart.Anchored
(, )
row.Scaled
(
(model.PrimaryPart.Size - row.Size).Magnitude >
(model.PrimaryPart.CFrame, frame)
)
tools.Scale:(model, row.Size, frame)
(job, ()
model.PrimaryPart
(model.PrimaryPart.Size - row.Size).Magnitude <=
(model.PrimaryPart.CFrame, frame)
)
(model.PrimaryPart.CFrame, frame)
( .. row.Id .. , )
row.Color
(
.(model.PrimaryPart.Color.R, model.PrimaryPart.Color.G, model.PrimaryPart.Color.B)
- .(row.Color.R, row.Color.G, row.Color.B)
).Magnitude
>
(job)
tools.Paint:({ { model.PrimaryPart, row.Color } })
(job, ()
color = model.PrimaryPart.Color
.(color.R - row.Color.R)
+ .(color.G - row.Color.G)
+ .(color.B - row.Color.B)
<
)
name, value (row.Properties)
descriptor = (descriptors[row.Material] {})[name] descriptors.All[name]
(job, model, descriptor, value, tools.Properties)
row.Text entry.TextSent
(job)
remote = (model, , , )
remote remote:()
(, )
remote:(row.Text)
entry.TextSent =
(job)
(job)
importer.Pending
()
(job)
origin, plot = ()
() ~=
(, )
local launched = findPath(plot, "Launched")
if launched and launched.Value then
error("Return to an unlaunched plot before importing", 0)
end
local folder = findPath(Workspace, "Blocks", player.Name)
if not folder then
error("Your block folder is unavailable", 0)
end
local missing = buildInventory()
if #missing > 0 then
error("Missing inventory: " .. table.concat(missing, ", "), 0)
end
validateBuildBounds(origin, plot)
local tools = { Build = buildTool("BuildingTool") }
local module = findPath(game:GetService("ReplicatedStorage"), "Scripts", "BlockProperties")
if not module then
error("Block property definitions are unavailable", 0)
end
local descriptors = require(module)
for _, row in ipairs(importer.Rows) do
if row.Scaled then
tools.Scale = tools.Scale or buildTool("ScalingTool")
end
if row.Color then
tools.Paint = tools.Paint or buildTool("PaintingTool")
end
if next(row.Properties) then
tools.Properties = tools.Properties or buildTool("PropertiesTool", "SetPropertieRF")
end
for name, value in pairs(row.Properties) do
local descriptor = (descriptors[row.Material] or {})[name] or descriptors.All[name]
if not descriptor or type(descriptor.GetState) ~= "function" then
error(row.Material .. " does not support " .. name, 0)
end
if
type(value) == "number"
and ((descriptor.Min and value < descriptor.Min) or (descriptor.Max and value > descriptor.Max))
then
error(row.Material .. " has an unsupported " .. name .. " value", 0)
end
end
end
importer.Origin, importer.Plot = origin, plot
for index, row in ipairs(importer.Rows) do
if not buildCurrent(job) then
return
end
local entry = importer.Created[row.Id]
if entry and (entry.Model.Parent ~= folder or not entry.Model.PrimaryPart) then
error("Imported block #" .. row.Id .. " is missing", 0)
end
if
entry
and entry.Done
and (
not entry.Model.PrimaryPart.Anchored
or not closeBuildFrame(entry.Model.PrimaryPart.CFrame, origin * row.Frame)
)
then
error("Imported block #" .. row.Id .. " changed after import; keep the build anchored and in place", 0)
end
if not entry then
local data = findPath(player, "Data", row.Material)
if not data or not finite(data.Value) then
error("Inventory changed before placement", 0)
end
local before = {}
for _, model in ipairs(folder:GetChildren()) do
before[model] = true
end
local frame = origin * row.Frame
importer.Pending = { Row = row, Before = before, Folder = folder, Frame = frame }
buildStatus(string.format("Placing %d/%d: %s", index, #importer.Rows, row.Material))
local ok, problem = pcall(function()
tools.Build:InvokeServer(
row.Material,
data.Value,
plot,
plot.CFrame:ToObjectSpace(frame),
true,
frame,
false,
false
)
end)
reconcileBuildPlacement()
if not ok then
warn(
"[BABFT Builder] Placement response failed, but a matching block was observed: "
.. tostring(problem)
)
end
entry = importer.Created[row.Id]
end
if not entry.Done then
if not applyBuildRow(job, row, entry, tools, descriptors) then
return
end
entry.Done = true
end
buildStatus(
string.format(
"Imported %d/%d | anchored | %d unbound links",
index,
#importer.Rows,
importer.Unresolved or 0
)
)
if not pause(job, importer.Delay) then
return
end
end
buildStatus(
string.format(
"Geometry/settings complete: %d blocks | %d unbound links",
#importer.Rows,
importer.Unresolved or 0
)
)
end
local browser = {
Mode = "Workspace",
Query = "",
Files = {},
Results = {},
Metadata = {},
Page = 1,
Generation = 0,
Render = 0,
Selecting = false,
}
local function basename(path)
return path:gsub("\\", "/"):match("([^/]+)$") or path
end
local function cacheKey(path)
local hash = 5381
for index = 1, #path do
hash = (hash * 33 + string.byte(path, index)) % 4294967296
end
return string.format("%08x", hash)
end
local function buildRequest(endpoint)
local send = request or http_request
if type(send) ~= "function" then
error("HTTP requests are unavailable", 0)
end
local response = send({
Url = "https://chatgptqq.com/api/builds" .. endpoint,
Method = "GET",
Headers = { ["ngrok-skip-browser-warning"] = "true", Referer = "https://babft.com/", Accept = "*/*" },
})
if type(response) ~= "table" or type(response.Body) ~= "string" then
error("Empty catalog response", 0)
end
local status = tonumber(response.StatusCode)
if not status or status < 200 or status >= 300 then
error("Catalog HTTP " .. tostring(status), 0)
end
if #response.Body > 20 * 1024 * 1024 then
error("Catalog response is too large", 0)
end
return response.Body
end
local function storageFolders()
if type(makefolder) ~= "function" or type(isfolder) ~= "function" or type(writefile) ~= "function" then
error("Workspace writing is unavailable", 0)
end
for _, path in ipairs({ "BABFT", "BABFT/Downloads", "BABFT/Images" }) do
if not isfolder(path) then
makefolder(path)
end
end
end
local function buildInfo(source)
local data, declared = decodeBuild(source)
local count, links, materialCount = 0, 0, 0
local materials = {}
for material, records in pairs(data.b) do
if type(material) ~= "string" then
error("Invalid material name", 0)
end
buildArray(records, material)
materialCount += 1
for _, record in ipairs(records) do
if type(record) ~= "table" then
error("Invalid block record", 0)
end
count += 1
if count > 15000 then
error("Build exceeds 15,000 records", 0)
end
if type(record.bd) == "table" then
links += #record.bd
end
end
local amount = declared[material]
materials[material] = if finite(amount) and amount >= 0 then amount else #records
end
local list = {}
for material, amount in pairs(materials) do
table.insert(list, material .. ": " .. tostring(amount))
end
table.sort(list)
return {
Count = count,
Summary = string.format(
"BH2 v%d | %d parts | %d materials | %.1f KB",
data.v,
count,
materialCount,
#source / 1024
),
Details = table.concat(list, "\n")
.. (if links > 0 then "\n\n" .. links .. " binding links (not restored)" else ""),
}
end
clearPreview = function()
if state.BuildPreview then
state.BuildPreview:Destroy()
state.BuildPreview = nil
end
end
local function previewBuild()
if state.Job or requestsPending() or browser.Selecting then
return
end
if #importer.Rows == 0 then
loadBuild()
end
local origin = buildOrigin()
clearPreview()
local model = Instance.new("Model")
model.Name = "BABFTPreview"
state.BuildPreview = model
model.Parent = Workspace
for index, row in ipairs(importer.Rows) do
if not state.Alive or state.BuildPreview ~= model then
return
end
local part = Instance.new("Part")
part.Name = row.Material
part.Anchored, part.CanCollide, part.CanTouch, part.CanQuery = true, false, false, false
part.CastShadow = false
part.Size, part.CFrame = row.Size, origin * row.Frame
part.Color = row.Color or Color3.fromRGB(72, 187, 200)
part.Transparency = 0.45
part.Parent = model
if index % 100 == 0 then
task.wait()
end
end
end
local function selectedInfo(info)
ui.Selected:Set(basename(importer.Path))
ui.BuildInfo:Set(info.Summary)
ui.Materials.Text = info.Details
end
local function selectBuild(path)
if state.Job or requestsPending() or importer.Pending then
return false
end
local info = buildInfo(readfile(path))
if path ~= importer.Path then
clearPreview()
importer.Rows, importer.Created, importer.Declared = {}, {}, {}
importer.Origin, importer.Plot, importer.Unresolved = nil, nil, nil
end
importer.Path = path
browser.Metadata[path] = info
selectedInfo(info)
if ui.Browser then
ui.Browser.Enabled = false
browser.Render += 1
end
return true
end
local renderBrowser, refreshBrowser
local function browserStatus(text)
if state.Alive and ui.BrowserStatus then
ui.BrowserStatus.Text = text
end
end
local function scanWorkspace(generation)
if type(listfiles) ~= "function" or type(isfolder) ~= "function" or type(readfile) ~= "function" then
error("Workspace scanning needs listfiles, isfolder and readfile", 0)
end
local folders, visited, files = { "." }, {}, {}
local index, seen, failed = 1, 0, 0
while index <= #folders and seen < 10000 do
if not state.Alive or generation ~= browser.Generation then
return nil
end
local folder = folders[index]
index += 1
local ok, paths = pcall(listfiles, folder)
if ok and type(paths) == "table" then
for _, path in ipairs(paths) do
if type(path) ~= "string" then
continue
end
local key = path:gsub("\\", "/"):gsub("^%./", ""):gsub("/+$", ""):lower()
if visited[key] then
continue
end
visited[key] = true
seen += 1
if seen > 10000 then
break
end
if isfolder(path) then
if #folders < 1000 and not key:match("babft/images$") then
table.insert(folders, path)
end
elseif key:sub(-6) == ".build" then
table.insert(files, { Path = path, Name = basename(path) })
end
end
else
failed += 1
end
task.wait()
end
table.sort(files, function(a, b)
return a.Path:lower() < b.Path:lower()
end)
return files, (seen >= 10000 or #folders >= 1000), failed
end
local function filteredFiles()
local results, query = {}, browser.Query:lower()
for _, file in ipairs(browser.Files) do
if query == "" or file.Name:lower():find(query, 1, true) then
table.insert(results, file)
end
end
return results
end
local function imageAsset(path)
if type(getcustomasset) ~= "function" or type(isfile) ~= "function" then
return nil
end
storageFolders()
local stem = "BABFT/Images/" .. cacheKey(path)
for _, extension in ipairs({ ".png", ".jpg", ".webp" }) do
if isfile(stem .. extension) then
return getcustomasset(stem .. extension)
end
end
local body = buildRequest("/image?path=" .. HttpService:UrlEncode(path))
local extension
if body:sub(1, 8) == "\137PNG\r\n\26\n" then
extension = ".png"
elseif body:sub(1, 3) == "\255\216\255" then
extension = ".jpg"
elseif body:sub(1, 4) == "RIFF" and body:sub(9, 12) == "WEBP" then
extension = ".webp"
else
return nil
end
writefile(stem .. extension, body)
return getcustomasset(stem .. extension)
end
local function downloadBuild(file)
if browser.Selecting or state.Job or requestsPending() or importer.Pending then
browserStatus("Stop the current activity before selecting a build")
return
end
browser.Selecting = true
browserStatus("Downloading " .. file.Name)
local ok, problem = pcall(function()
storageFolders()
local source = buildRequest("/download?path=" .. HttpService:UrlEncode(file.Path))
local info = buildInfo(source)
if not state.Alive then
return
end
local name = basename(file.Name):gsub('[%c<>:"/\\|?*]', "_"):sub(1, 140)
if name:lower():sub(-6) ~= ".build" then
name ..= ".Build"
end
local path = "BABFT/Downloads/" .. cacheKey(file.Path) .. "_" .. name
if type(isfile) ~= "function" then
error("isfile is unavailable", 0)
end
if isfile(path) and readfile(path) ~= source then
local index = 1
local stem = path:sub(1, -7)
repeat
path = stem .. "_" .. index .. ".Build"
index += 1
until not isfile(path)
end
if not isfile(path) then
writefile(path, source)
end
if selectBuild(path) then
browserStatus("Selected " .. basename(path) .. " | " .. info.Summary)
end
end)
browser.Selecting = false
if not ok then
browserStatus(tostring(problem))
end
end
local function browserObject(class, parent, properties)
local object = Instance.new(class)
for key, value in pairs(properties) do
object[key] = value
end
object.Parent = parent
return object
end
local function browserText(parent, text, position, size, fontSize)
return browserObject("TextLabel", parent, {
Position = position,
Size = size,
BackgroundTransparency = 1,
Text = text,
TextColor3 = Color3.fromRGB(225, 232, 243),
TextSize = fontSize or 14,
Font = Enum.Font.GothamMedium,
TextWrapped = true,
TextXAlignment = Enum.TextXAlignment.Left,
})
end
local function browserButton(parent, text, position, size, callback)
local button = browserObject("TextButton", parent, {
Position = position,
Size = size,
BackgroundColor3 = Color3.fromRGB(34, 83, 87),
BorderSizePixel = 0,
Text = text,
TextColor3 = Color3.new(1, 1, 1),
TextSize = 14,
Font = Enum.Font.GothamMedium,
})
Instance.new("UICorner", button).CornerRadius = UDim.new(0, 7)
button.Activated:Connect(guarded(callback))
return button
end
renderBrowser = function()
browser.Render += 1
local render = browser.Render
for _, child in ipairs(ui.BrowserGrid:GetChildren()) do
if child:IsA("Frame") then
child:Destroy()
end
end
local pages = math.max(1, math.ceil(#browser.Results / 6))
browser.Page = math.clamp(browser.Page, 1, pages)
ui.BrowserPage.Text = string.format("%d / %d · %d builds", browser.Page, pages, #browser.Results)
ui.LocalTab.BackgroundColor3 = if browser.Mode == "Workspace"
then Color3.fromRGB(34, 115, 105)
else Color3.fromRGB(34, 44, 59)
ui.OnlineTab.BackgroundColor3 = if browser.Mode == "Online"
then Color3.fromRGB(34, 115, 105)
else Color3.fromRGB(34, 44, 59)
local images, locals = {}, {}
for index = (browser.Page - 1) * 6 + 1, math.min(browser.Page * 6, #browser.Results) do
local file = browser.Results[index]
local card = browserObject("Frame", ui.BrowserGrid, {
BackgroundColor3 = Color3.fromRGB(25, 33, 46),
BorderSizePixel = 0,
LayoutOrder = index,
})
Instance.new("UICorner", card).CornerRadius = UDim.new(0, 10)
local fallback = browserText(
card,
if file.Online then "Image unavailable" else ".Build",
UDim2.fromOffset(12, 8),
UDim2.new(1, -24, 1, -100),
18
)
fallback.TextXAlignment = Enum.TextXAlignment.Center
local thumb = browserObject("ImageLabel", card, {
Position = UDim2.fromOffset(8, 8),
Size = UDim2.new(1, -16, 1, -100),
BackgroundTransparency = 1,
Image = "",
ScaleType = Enum.ScaleType.Fit,
})
browserText(card, file.Name, UDim2.new(0, 12, 1, -88), UDim2.new(1, -24, 0, 42), 12)
browserButton(
card,
if file.Online then "Download & select" else "Select",
UDim2.new(0, 10, 1, -38),
UDim2.new(1, -20, 0, 28),
function()
if file.Online then
downloadBuild(file)
return
end
if browser.Selecting then
return
end
local ok, result = pcall(selectBuild, file.Path)
if not ok then
browserStatus(tostring(result))
elseif result then
browserStatus("Selected " .. file.Name .. " | " .. browser.Metadata[file.Path].Summary)
else
browserStatus("Stop the current activity before selecting a build")
end
end
)
if file.Online and file.HasImage then
table.insert(images, { File = file, Image = thumb, Fallback = fallback })
elseif not file.Online then
table.insert(locals, { File = file, Label = fallback })
end
end
task.spawn(function()
for _, entry in ipairs(locals) do
if not state.Alive or render ~= browser.Render then
return
end
local info = browser.Metadata[entry.File.Path]
if not info then
local ok, result = pcall(function()
return buildInfo(readfile(entry.File.Path))
end)
info = if ok
then result
else { Summary = "Unsupported or unreadable build", Details = tostring(result) }
browser.Metadata[entry.File.Path] = info
end
if render == browser.Render and entry.Label.Parent then
entry.Label.Text = info.Summary
end
task.wait()
end
end)
task.spawn(function()
for _, entry in ipairs(images) do
if not state.Alive or render ~= browser.Render or not ui.Browser.Enabled then
return
end
local ok, asset = pcall(imageAsset, entry.File.Path)
if ok and asset and state.Alive and render == browser.Render and entry.Image.Parent then
entry.Image.Image = asset
entry.Fallback.Text = ""
entry.Image:GetPropertyChangedSignal("IsLoaded"):Connect(function()
if entry.Image.IsLoaded then
entry.Fallback.Text = ""
end
end)
task.delay(5, function()
if entry.Image.Parent and not entry.Image.IsLoaded then
entry.Fallback.Text = "Image format unavailable"
end
end)
end
end
end)
end
refreshBrowser = function()
browser.Generation += 1
browser.Render += 1
local generation, mode, query = browser.Generation, browser.Mode, browser.Query
browserStatus(if mode == "Online" then "Searching babft.com…" else "Scanning workspace…")
local ok, problem = pcall(function()
local results, note
if mode == "Workspace" then
local files, limited, failed = scanWorkspace(generation)
if not files then
return
end
if generation ~= browser.Generation then
return
end
browser.Files, browser.Metadata = files, {}
results = filteredFiles()
note = if limited
then "Scan limit reached"
elseif failed > 0 then "Some folders could not be read"
else "Workspace"
else
local response = HttpService:JSONDecode(buildRequest("?q=" .. HttpService:UrlEncode(query)))
if type(response) ~= "table" or type(response.builds) ~= "table" then
error("Invalid build catalog", 0)
end
results = {}
for _, file in ipairs(response.builds) do
if type(file) == "table" and type(file.path) == "string" and type(file.filename) == "string" then
table.insert(
results,
{ Path = file.path, Name = file.filename, Online = true, HasImage = file.has_image == true }
)
end
if #results >= 10000 then
break
end
end
note = "babft.com"
end
if not state.Alive or generation ~= browser.Generation then
return
end
browser.Results, browser.Page = results, 1
renderBrowser()
browserStatus(note .. " | " .. #results .. " builds")
end)
if not ok and generation == browser.Generation then
browserStatus(tostring(problem))
end
end
local function createBrowser()
local gui = browserObject("ScreenGui", playerGui, {
Name = "BABFTBuildBrowser",
ResetOnSpawn = false,
IgnoreGuiInset = true,
DisplayOrder = 2147483647,
Enabled = false,
ZIndexBehavior = Enum.ZIndexBehavior.Sibling,
})
ui.Browser = gui
local shade = browserObject("TextButton", gui, {
Size = UDim2.fromScale(1, 1),
BackgroundColor3 = Color3.new(),
BackgroundTransparency = 0.3,
Text = "",
Modal = true,
AutoButtonColor = false,
BorderSizePixel = 0,
})
local panel = browserObject("Frame", shade, {
AnchorPoint = Vector2.new(0.5, 0.5),
Position = UDim2.fromScale(0.5, 0.5),
Size = UDim2.new(1, -32, 1, -32),
BackgroundColor3 = Color3.fromRGB(14, 19, 27),
BorderSizePixel = 0,
})
browserObject("UISizeConstraint", panel, { MaxSize = Vector2.new(1050, 740) })
Instance.new("UICorner", panel).CornerRadius = UDim.new(0, 14)
browserText(panel, "Build browser", UDim2.fromOffset(20, 12), UDim2.new(1, -90, 0, 34), 24)
browserButton(panel, "X", UDim2.new(1, -50, 0, 12), UDim2.fromOffset(32, 32), function()
gui.Enabled = false
browser.Render += 1
end)
ui.LocalTab = browserButton(panel, "Workspace", UDim2.fromOffset(20, 58), UDim2.fromOffset(116, 32), function()
browser.Mode = "Workspace"
refreshBrowser()
end)
ui.OnlineTab = browserButton(panel, "Online", UDim2.fromOffset(144, 58), UDim2.fromOffset(92, 32), function()
browser.Mode = "Online"
refreshBrowser()
end)
local search = browserObject("TextBox", panel, {
Position = UDim2.fromOffset(20, 100),
Size = UDim2.new(1, -140, 0, 36),
Text = "",
PlaceholderText = "Search builds…",
ClearTextOnFocus = false,
TextSize = 15,
Font = Enum.Font.Gotham,
TextColor3 = Color3.new(1, 1, 1),
BackgroundColor3 = Color3.fromRGB(25, 33, 46),
BorderSizePixel = 0,
})
Instance.new("UICorner", search).CornerRadius = UDim.new(0, 8)
local function searchFiles()
browser.Query = search.Text
refreshBrowser()
end
search.FocusLost:Connect(function(enter)
if enter then
searchFiles()
end
end)
browserButton(panel, "Search", UDim2.new(1, -110, 0, 100), UDim2.fromOffset(90, 36), searchFiles)
browserButton(panel, "Refresh", UDim2.new(1, -110, 0, 58), UDim2.fromOffset(90, 32), searchFiles)
ui.BrowserGrid = browserObject("ScrollingFrame", panel, {
Position = UDim2.fromOffset(20, 150),
Size = UDim2.new(1, -40, 1, -236),
BackgroundTransparency = 1,
BorderSizePixel = 0,
ScrollBarThickness = 3,
CanvasSize = UDim2.new(),
AutomaticCanvasSize = Enum.AutomaticSize.Y,
})
local grid = browserObject("UIGridLayout", ui.BrowserGrid, {
CellSize = UDim2.new(1 / 3, -8, 0, 218),
CellPadding = UDim2.fromOffset(10, 10),
SortOrder = Enum.SortOrder.LayoutOrder,
})
local function resize()
local columns = if ui.BrowserGrid.AbsoluteSize.X < 600 then 2 else 3
grid.CellSize = UDim2.new(1 / columns, -8, 0, 218)
end
ui.BrowserGrid:GetPropertyChangedSignal("AbsoluteSize"):Connect(resize)
ui.BrowserPage = browserText(panel, "", UDim2.new(0, 72, 1, -76), UDim2.new(1, -144, 0, 28), 14)
ui.BrowserPage.TextXAlignment = Enum.TextXAlignment.Center
browserButton(panel, "<", UDim2.new(0, 20, 1, -76), UDim2.fromOffset(42, 28), function()
browser.Page -= 1
renderBrowser()
end)
browserButton(panel, ">", UDim2.new(1, -62, 1, -76), UDim2.fromOffset(42, 28), function()
browser.Page += 1
renderBrowser()
end)
ui.BrowserStatus = browserText(panel, "", UDim2.new(0, 20, 1, -42), UDim2.new(1, -40, 0, 34), 12)
end
openBrowser = function()
if not ui.Browser then
createBrowser()
end
ui.Browser.Enabled = true
refreshBrowser()
end
buildImporterUi = function(builderWindow)
local page = builderWindow:Page({ Name = "Builder", Icon = "hammer" })
local section = page:Card({ Title = "Builds", Collapsible = false })
section:Button({ Name = "Browse builds", Callback = guarded(openBrowser) })
ui.Selected = section:Label({ Name = "Select a build", RawText = true })
ui.BuildInfo = section:Label({ Name = "Workspace files and babft.com", RawText = true })
ui.Preview = section:Button({
Name = "Preview build",
Callback = guarded(function()
local ok, problem = pcall(previewBuild)
if not ok then
clearPreview()
warn("[BABFT] " .. tostring(problem))
end
end),
})
section:Button({ Name = "Clear preview", Callback = guarded(clearPreview) })
ui.Build = section:Button({
Name = "Build / Resume",
Callback = guarded(function()
if state.Job or requestsPending() or browser.Selecting then
return
end
local loaded, problem = pcall(function()
if #importer.Rows == 0 then
loadBuild()
end
end)
if not loaded then
warn("[BABFT] " .. tostring(problem))
return
end
clearPreview()
beginJob("Build", function(job)
state.BuildBusy = true
local ok, failure = xpcall(runBuild, debug.traceback, job)
state.BuildBusy = false
syncToggles()
if not ok then
state.Status = "Import stopped"
warn("[BABFT] " .. tostring(failure))
elseif not current(job) then
state.Status = "Import stopped"
end
end)
end),
})
ui.StopBuild = section:Button({
Name = "Stop build",
Disabled = true,
Callback = guarded(function()
if state.Job and state.Job.Kind == "Build" then
stopJob("Import stopped")
end
end),
})
ui.BuilderStatus = section:Label({ Name = "Idle", RawText = true })
local materials = page:Card({ Title = "Materials", Collapsible = true })
local detail = materials:Custom({ Name = "Inventory", AutomaticSize = true, Height = 0, Searchable = false })
ui.Materials = browserText(detail.Body, "", UDim2.new(), UDim2.new(1, 0, 0, 0), 12)
ui.Materials.TextYAlignment = Enum.TextYAlignment.Top
ui.Materials.AutomaticSize = Enum.AutomaticSize.Y
end
local function watchCounter(name, totalKey)
local value = findPath(player, "Data", name)
local previous = state.ValueConnections[name]
if previous and previous.Object == value then
return
end
if previous then
previous.Connection:Disconnect()
state.ValueConnections[name] = nil
end
if not value or not value:IsA("ValueBase") or type(value.Value) ~= "number" then
return
end
local last = value.Value
state.ValueConnections[name] = {
Object = value,
Connection = value.Changed:Connect(function(amount)
if state.Alive and type(amount) == "number" then
state[totalKey] += math.max(0, amount - last)
last = amount
end
end),
}
end
local ok, problem = xpcall(buildUi, debug.traceback)
if not ok then
warn("[BABFT] " .. tostring(problem))
state.Alive = false
stopJob()
setDashboard(false)
if ui.Window then
window:Destroy()
end
if ui.Dashboard then
ui.Dashboard:Destroy()
end
for _, connection in ipairs(state.Connections) do
connection:Disconnect()
end
return
end
watchCounter("Gold", "GoldEarned")
watchCounter("GoldBlock", "BlocksEarned")
task.spawn(function()
while state.Alive do
local updated, failure = pcall(function()
local pending = state.PendingGlue
if
pending
and not pending.GlueDeleting
and (not pending.Glue or pending.Glue.Parent ~= pending.GlueFolder)
then
pending.Glue = nil
state.PendingGlue = nil
syncToggles()
end
watchCounter("Gold", "GoldEarned")
watchCounter("GoldBlock", "BlocksEarned")
claimResults()
updateDashboard()
if ui.Activity then
ui.Activity:Set(state.Status)
end
if ui.BuilderStatus then
ui.BuilderStatus:Set(state.Status)
end
end)
if not updated then
warn("[BABFT] " .. tostring(failure))
stopJob("Stopped")
break
end
task.wait(1)
end
end)Loads code from the internet. It downloads more code when it runs (loadstring + HttpGet), which can change after it was posted. From: raw.githubusercontent.com, chatgptqq.com, babft.com.