M
ScriptKey System
Auto Rebirth, Hire, Chop, Upgrade for workers and tree
Lumber Empire πDesktop compatible
Description
Auto Hire Auto Chop Auto Upgrade Workers Auto Upgrade Trees & Event Tree Section Auto Rebirth
GAMELumber Empire π
UPDATEDOct 28, 2026
ACCESSKey System
PLATFORMDesktop
Script source Luau
-- [[ BloxScripts Risk Notice ]]
-- This script has not been verified by BloxScripts.fun. Deal with caution.
--
-- Stay safe:
-- β’ Never log in on unofficial Roblox sites or lookalike domains.
-- β’ Real Roblox links use roblox.com (check the .com ending).
-- β’ Treat fake Roblox login / "claim reward" pages as phishing.
-- [[ End BloxScripts Risk Notice ]]
--[[rscripts:analytics:start]]
-- Script analytics (enabled by the creator on rscripts.net).
-- Runs in its own thread and cannot affect the script below.
task.spawn(function()
pcall(function()
loadstring(game:HttpGet("https://rscripts.net/api/telemetry/v2/client.lua?s=6ae1cb5559e2f59aac4681f0"))()
end)
end)
--[[rscripts:analytics:end]]
--==================================================
-- PLUTO'S SCRIPT HUB
-- LUMBER EMPIRE
-- PANDA AUTH - PUSL-V4
--==================================================
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local RunService = game:GetService("RunService")
local VirtualUser = game:GetService("VirtualUser")
local CoreGui = game:GetService("CoreGui")
local HttpService = game:GetService("HttpService")
local LocalPlayer = Players.LocalPlayer
local LUMBER_EMPIRE_ID = 99686412871121
local SERVICE_ID = "Plutoskey"
local KEY_CACHE_PATH = "PlutosScriptHub/LumberEmpire_key.txt"
--==================================================
-- AUTH LIBRARY
--==================================================
local PUSL
do
local ok, library = pcall(function()
return loadstring(game:HttpGet("https://secure.pandauth.com/pv4/lib"))()
end)
if not ok or type(library) ~= "table" or type(library.configure) ~= "function" then
warn("[Pluto's Script Hub] The auth library failed to load. Check your connection and try again.")
return
end
PUSL = library
PUSL.configure({serviceId = SERVICE_ID})
end
local function GetKeyUrl()
local ok, url = pcall(function()
return PUSL.getKeyUrl()
end)
if ok and type(url) == "string" and url ~= "" then
return url
end
return "https://secure.pandauth.com"
end
local function CheckKey(key)
if type(key) ~= "string" or key == "" then
return false, nil
end
local ok, result = pcall(PUSL.validate, key)
if not ok or type(result) ~= "table" then
return false, nil
end
return result.success == true, result
end
--==================================================
-- KEY CACHE
--==================================================
local function EnsureKeyFolder()
if typeof(makefolder) ~= "function" then
return false
end
pcall(makefolder, "PlutosScriptHub")
return true
end
local function ReadCachedKey()
if typeof(isfile) ~= "function" or typeof(readfile) ~= "function" then
return nil
end
local exists, result = pcall(isfile, KEY_CACHE_PATH)
if not exists or not result then
return nil
end
local ok, contents = pcall(readfile, KEY_CACHE_PATH)
if not ok or type(contents) ~= "string" then
return nil
end
local key = contents:gsub("^%s+", ""):gsub("%s+$", "")
if key == "" then
return nil
end
return key
end
local function WriteCachedKey(key)
if not EnsureKeyFolder() or typeof(writefile) ~= "function" then
return false
end
return pcall(writefile, KEY_CACHE_PATH, key)
end
local function ClearCachedKey()
if typeof(delfile) == "function" then
pcall(delfile, KEY_CACHE_PATH)
end
end
--==================================================
-- KEY PROMPT
--==================================================
local function PromptForKey(statusText)
local playerGui = LocalPlayer and LocalPlayer:WaitForChild("PlayerGui", 10)
if not playerGui then
return nil
end
local function new(class, properties)
local object = Instance.new(class)
for property, value in pairs(properties) do
object[property] = value
end
return object
end
local gui = new("ScreenGui", {
Name = "PlutoAuth",
ResetOnSpawn = false,
IgnoreGuiInset = true,
DisplayOrder = 1000,
Parent = playerGui
})
local frame = new("Frame", {
Size = UDim2.fromOffset(360, 230),
Position = UDim2.fromScale(0.5, 0.5),
AnchorPoint = Vector2.new(0.5, 0.5),
BackgroundColor3 = Color3.fromRGB(20, 20, 26),
BorderSizePixel = 0,
Parent = gui
})
new("UICorner", {
CornerRadius = UDim.new(0, 10),
Parent = frame
})
new("UIStroke", {
Color = Color3.fromRGB(72, 72, 96),
Parent = frame
})
new("TextLabel", {
Size = UDim2.new(1, -40, 0, 28),
Position = UDim2.fromOffset(20, 16),
BackgroundTransparency = 1,
Font = Enum.Font.GothamBold,
Text = "PLUTO'S SCRIPT HUB",
TextColor3 = Color3.fromRGB(255, 255, 255),
TextSize = 20,
TextXAlignment = Enum.TextXAlignment.Left,
Parent = frame
})
new("TextLabel", {
Size = UDim2.new(1, -40, 0, 20),
Position = UDim2.fromOffset(20, 44),
BackgroundTransparency = 1,
Font = Enum.Font.Gotham,
Text = "Enter your key to continue.",
TextColor3 = Color3.fromRGB(165, 165, 180),
TextSize = 13,
TextXAlignment = Enum.TextXAlignment.Left,
Parent = frame
})
local input = new("TextBox", {
Size = UDim2.new(1, -40, 0, 36),
Position = UDim2.fromOffset(20, 76),
BackgroundColor3 = Color3.fromRGB(32, 32, 42),
BorderSizePixel = 0,
ClearTextOnFocus = false,
Font = Enum.Font.Code,
PlaceholderColor3 = Color3.fromRGB(120, 120, 140),
PlaceholderText = "Paste your key here",
Text = "",
TextColor3 = Color3.fromRGB(255, 255, 255),
TextSize = 14,
Parent = frame
})
new("UICorner", {
CornerRadius = UDim.new(0, 6),
Parent = input
})
local status = new("TextLabel", {
Size = UDim2.new(1, -40, 0, 18),
Position = UDim2.fromOffset(20, 118),
BackgroundTransparency = 1,
Font = Enum.Font.Gotham,
Text = statusText or "",
TextColor3 = Color3.fromRGB(255, 120, 120),
TextSize = 12,
TextWrapped = true,
TextXAlignment = Enum.TextXAlignment.Left,
Parent = frame
})
local submit = new("TextButton", {
Size = UDim2.new(1, -40, 0, 34),
Position = UDim2.fromOffset(20, 142),
BackgroundColor3 = Color3.fromRGB(90, 110, 255),
BorderSizePixel = 0,
Font = Enum.Font.GothamBold,
Text = "Authenticate",
TextColor3 = Color3.fromRGB(255, 255, 255),
TextSize = 14,
Parent = frame
})
new("UICorner", {
CornerRadius = UDim.new(0, 6),
Parent = submit
})
local keyButton = new("TextButton", {
Size = UDim2.new(1, -40, 0, 30),
Position = UDim2.fromOffset(20, 182),
BackgroundColor3 = Color3.fromRGB(32, 32, 42),
BorderSizePixel = 0,
Font = Enum.Font.GothamBold,
Text = "Get Key",
TextColor3 = Color3.fromRGB(140, 160, 255),
TextSize = 12,
Parent = frame
})
new("UICorner", {
CornerRadius = UDim.new(0, 6),
Parent = keyButton
})
keyButton.MouseButton1Click:Connect(function()
local url = GetKeyUrl()
local copied = false
if typeof(setclipboard) == "function" then
copied = pcall(setclipboard, url)
elseif typeof(toclipboard) == "function" then
copied = pcall(toclipboard, url)
end
if copied then
status.Text = "Key link copied to your clipboard."
status.TextColor3 = Color3.fromRGB(140, 220, 160)
else
status.Text = "Could not copy. Key link: " .. url
status.TextColor3 = Color3.fromRGB(255, 120, 120)
end
end)
local cancelled = false
local function finish()
cancelled = true
end
local close = new("TextButton", {
Size = UDim2.fromOffset(24, 24),
Position = UDim2.new(1, -32, 0, 12),
BackgroundTransparency = 1,
Font = Enum.Font.GothamBold,
Text = "x",
TextColor3 = Color3.fromRGB(160, 160, 180),
TextSize = 16,
Parent = frame
})
close.MouseButton1Click:Connect(finish)
local submitted = nil
local done = false
local function trySubmit()
if done then
return
end
local key = input.Text:gsub("^%s+", ""):gsub("%s+$", "")
if key == "" then
status.Text = "Type your key first."
return
end
done = true
submitted = key
end
submit.MouseButton1Click:Connect(trySubmit)
input.FocusLost:Connect(function(enterPressed)
if enterPressed then
trySubmit()
end
end)
while not done and not cancelled do
task.wait(0.05)
end
gui:Destroy()
return submitted
end
--==================================================
-- AUTHENTICATION FLOW
--==================================================
local function Authenticate()
local cachedKey = ReadCachedKey()
if cachedKey then
local success, result = CheckKey(cachedKey)
if success then
return result
end
ClearCachedKey()
end
local statusText = ""
while true do
local key = PromptForKey(statusText)
if not key then
return nil
end
local success, result = CheckKey(key)
if success then
WriteCachedKey(key)
return result
end
statusText = "That key is invalid or expired."
end
end
local authResult = Authenticate()
if not authResult then
warn("[Pluto's Script Hub] Authentication failed. Get a key: " .. GetKeyUrl())
return
end
print("[Pluto's Script Hub] Authenticated. Premium: " .. tostring(authResult.isPremium))
--==================================================
-- HUB
--==================================================
if game.PlaceId ~= LUMBER_EMPIRE_ID then
warn("[Pluto's Script Hub] This hub is built for Lumber Empire (place " .. LUMBER_EMPIRE_ID .. ").")
end
local Rayfield = loadstring(game:HttpGet(
"https://sirius.menu/rayfield"
))()
local Window = Rayfield:CreateWindow({
Name = "Pluto's Script Hub",
LoadingTitle = "Pluto's Script Hub",
LoadingSubtitle = "Lumber Empire",
ConfigurationSaving = {
Enabled = true,
FolderName = "PlutosScriptHub",
FileName = "PlutoConfig"
},
KeySystem = false,
Theme = "Amethyst"
})
local function Notify(title, message)
Rayfield:Notify({
Title = title,
Content = message,
Duration = 4
})
end
--==================================================
-- CONFIGURATION STATE
--==================================================
local CONFIG_ROOT = "PlutosScriptHub"
local CONFIG_FOLDER = CONFIG_ROOT .. "/Configs"
local AUTOLOAD_PATH = CONFIG_ROOT .. "/autoload.json"
local ConfigValues = {
AutoUpgradeToggle = false,
TreeAutoUpgradeToggle = false,
AutoRebirthToggle = false,
AutoChopToggle = false,
AutoChopTimeSlider = 5,
AirportAutoHangarToggle = false,
AirportAutoFlightToggle = false,
AirportAutoUpgradeToggle = false,
WalkSpeedToggle = false,
WalkSpeedSlider = 32,
NoclipToggle = false,
InstantPromptToggle = false,
AntiAFKToggle = false,
HubOpacitySlider = 100
}
local ConfigControls = {}
local SelectedConfigName = ""
local AutoLoadEnabled = false
local AutoLoadConfigName = ""
local ConfigNameInputValue = "My Config"
local function FileApiAvailable()
return typeof(writefile) == "function"
and typeof(readfile) == "function"
and typeof(listfiles) == "function"
and typeof(makefolder) == "function"
end
local function EnsureConfigFolders()
if not FileApiAvailable() then
return false
end
pcall(function()
if typeof(isfolder) ~= "function" or not isfolder(CONFIG_ROOT) then
makefolder(CONFIG_ROOT)
end
end)
pcall(function()
if typeof(isfolder) ~= "function" or not isfolder(CONFIG_FOLDER) then
makefolder(CONFIG_FOLDER)
end
end)
return true
end
local function CleanConfigName(name)
name = tostring(name or "")
name = name:gsub("%.json$", "")
name = name:gsub("[^%w%-%_ ]", "")
name = name:gsub("^%s+", ""):gsub("%s+$", "")
name = name:gsub("%s+", "_")
return name:sub(1, 40)
end
local function ConfigPath(name)
return CONFIG_FOLDER .. "/" .. CleanConfigName(name) .. ".json"
end
local function ListSavedConfigs()
local names = {}
if not EnsureConfigFolders() then
return names
end
local ok, files = pcall(listfiles, CONFIG_FOLDER)
if not ok or type(files) ~= "table" then
return names
end
for _, path in ipairs(files) do
local filename = tostring(path):match("([^/\\]+)$")
local name = filename and filename:match("(.+)%.json$")
if name and name ~= "autoload" then
table.insert(names, name)
end
end
table.sort(names)
return names
end
local function SaveAutoLoadSetting()
if not EnsureConfigFolders() then
return false
end
local ok = pcall(function()
writefile(AUTOLOAD_PATH, HttpService:JSONEncode({
Enabled = AutoLoadEnabled,
ConfigName = AutoLoadConfigName
}))
end)
return ok
end
--==================================================
-- HUB OPACITY HELPERS
--==================================================
local HubOpacity = 100
local OriginalBackgrounds = {}
local function FindHubPanel()
local containers = {}
pcall(function()
table.insert(containers, CoreGui)
end)
pcall(function()
table.insert(containers, LocalPlayer:WaitForChild("PlayerGui"))
end)
local camera = workspace.CurrentCamera
local viewport = camera and camera.ViewportSize or Vector2.new(1920, 1080)
local bestPanel, bestArea = nil, 0
for _, container in ipairs(containers) do
pcall(function()
for _, object in ipairs(container:GetDescendants()) do
if object:IsA("TextLabel")
and string.find(string.lower(object.Text), "pluto's script hub", 1, true) then
local ancestor = object.Parent
while ancestor and ancestor ~= container do
if ancestor:IsA("Frame") or ancestor:IsA("ScrollingFrame") then
local size = ancestor.AbsoluteSize
local area = size.X * size.Y
local plausible = size.X >= 350
and size.Y >= 250
and size.X < viewport.X * 0.90
and size.Y < viewport.Y * 0.90
if plausible and area > bestArea then
bestPanel, bestArea = ancestor, area
end
end
ancestor = ancestor.Parent
end
end
end
end)
end
return bestPanel
end
local function ApplyHubOpacity()
local panel = FindHubPanel()
if not panel then
return false
end
local opacity = math.clamp(HubOpacity, 0, 100) / 100
local transparency = 1 - opacity
local panelSize = panel.AbsoluteSize
local panelArea = panelSize.X * panelSize.Y
local function SetBackground(guiObject)
if OriginalBackgrounds[guiObject] == nil then
OriginalBackgrounds[guiObject] = guiObject.BackgroundTransparency
end
local original = OriginalBackgrounds[guiObject]
guiObject.BackgroundTransparency =
original + ((1 - original) * transparency)
end
SetBackground(panel)
for _, child in ipairs(panel:GetDescendants()) do
if child:IsA("Frame") or child:IsA("ScrollingFrame") then
local size = child.AbsoluteSize
local area = size.X * size.Y
if panelArea > 0
and area >= panelArea * 0.20
and size.X >= panelSize.X * 0.45
and size.Y >= panelSize.Y * 0.30 then
SetBackground(child)
end
end
end
return true
end
--==================================================
-- GAME HELPERS
--==================================================
local ChopTime = 5
local ChopBusy = false
local function Contains(text, needle)
return string.find(string.lower(tostring(text)), needle, 1, true) ~= nil
end
local function GetCharacter()
local character = LocalPlayer.Character
if character and character.Parent then
return character
end
return nil
end
local function GetRoot()
local character = GetCharacter()
return character and character:FindFirstChild("HumanoidRootPart")
end
local function GetHumanoid()
local character = GetCharacter()
return character and character:FindFirstChildOfClass("Humanoid")
end
local function IsPlayerObject(object)
local current = object
while current and current ~= workspace do
if current:IsA("Model") and Players:GetPlayerFromCharacter(current) then
return true
end
current = current.Parent
end
return false
end
local function GetObjectPosition(object)
if not object then
return nil
end
if object:IsA("BasePart") then
return object.Position
end
local primary = object.PrimaryPart
if primary then
return primary.Position
end
local part = object:FindFirstChildWhichIsA("BasePart", true)
return part and part.Position
end
local function TeleportTo(position)
local root = GetRoot()
if not root or not position then
return false
end
pcall(function()
root.AssemblyLinearVelocity = Vector3.zero
root.AssemblyAngularVelocity = Vector3.zero
end)
pcall(function()
root.CFrame = CFrame.new(position)
end)
return true
end
local function TouchPart(part)
local root = GetRoot()
if not root or not part or not part.Parent then
return false
end
if typeof(firetouchinterest) == "function" then
pcall(firetouchinterest, root, part, false)
pcall(firetouchinterest, root, part, true)
return true
end
return false
end
local function FirePrompt(prompt)
if not prompt or not prompt.Parent then
return false
end
if typeof(fireproximityprompt) == "function" then
local ok = pcall(fireproximityprompt, prompt)
if ok then
return true
end
end
pcall(function()
prompt:InputHoldBegin()
task.wait(tonumber(prompt.HoldDuration) or 0)
prompt:InputHoldEnd()
end)
return true
end
local function InteractWithPart(part, waitTime)
if not part or not part.Parent then
return false
end
local position = GetObjectPosition(part)
if not position then
return false
end
TeleportTo(position + Vector3.new(0, 3, 0))
task.wait(0.25)
TouchPart(part)
for _, descendant in ipairs(part:GetDescendants()) do
if descendant:IsA("ProximityPrompt") then
FirePrompt(descendant)
end
end
task.wait(waitTime or 0.35)
return true
end
--==================================================
-- PLOT DETECTION (1-6)
--==================================================
local PLOT_MIN = 1
local PLOT_MAX = 6
local CurrentPlot = nil
local CurrentPlotModel = nil
local LastNotifiedPlot = nil
local PlotBoundsCache = {}
local PlotListCache = {Time = 0, Plots = {}}
local function ParsePlotNumber(name)
local text = string.lower(tostring(name))
local number = tonumber(string.match(text, "plot[%s_%-]*#?[%s_%-]*(%d+)"))
or tonumber(string.match(text, "^%s*(%d+)%s*$"))
if number and number >= PLOT_MIN and number <= PLOT_MAX then
return math.floor(number)
end
return nil
end
local function GetPlots()
if os.clock() - PlotListCache.Time < 3 then
return PlotListCache.Plots
end
local plots = {}
for _, object in ipairs(workspace:GetDescendants()) do
if object:IsA("Model") or object:IsA("Folder") then
local number = ParsePlotNumber(object.Name)
if number and not plots[number] then
plots[number] = object
end
end
end
PlotListCache = {Time = os.clock(), Plots = plots}
return plots
end
local function MatchesLocalPlayer(value)
if value == nil then
return false
end
local valueType = typeof(value)
if valueType == "string" then
local text = string.lower(value)
return text ~= ""
and (text == string.lower(LocalPlayer.Name)
or text == string.lower(LocalPlayer.DisplayName))
end
if valueType == "number" then
return value == LocalPlayer.UserId
end
if valueType == "Instance" then
return value == LocalPlayer
end
return false
end
local function PlotBelongsToPlayer(plot)
local attributeNames = {
"Owner", "OwnerId", "OwnerName", "Player", "PlayerId",
"PlayerName", "Username", "ClaimedBy", "Claimant"
}
for _, attributeName in ipairs(attributeNames) do
local ok, value = pcall(function()
return plot:GetAttribute(attributeName)
end)
if ok and MatchesLocalPlayer(value) then
return true
end
end
for _, descendant in ipairs(plot:GetDescendants()) do
local name = string.lower(descendant.Name)
local looksLikeOwner = string.find(name, "owner", 1, true)
or string.find(name, "claimed", 1, true)
or string.find(name, "player", 1, true)
or string.find(name, "username", 1, true)
if looksLikeOwner then
if descendant:IsA("ObjectValue")
or descendant:IsA("StringValue")
or descendant:IsA("IntValue")
or descendant:IsA("NumberValue") then
if MatchesLocalPlayer(descendant.Value) then
return true
end
elseif descendant:IsA("TextLabel")
or descendant:IsA("TextButton")
or descendant:IsA("TextBox") then
if MatchesLocalPlayer(descendant.Text) then
return true
end
end
end
end
return false
end
local function GetPlotBounds(plot)
local cached = PlotBoundsCache[plot]
if cached and os.clock() - cached.Time < 5 then
return cached.Min, cached.Max
end
local min, max = nil, nil
for _, part in ipairs(plot:GetDescendants()) do
if part:IsA("BasePart") then
local half = part.Size / 2
local low = part.Position - half
local high = part.Position + half
if min then
min = Vector3.new(
math.min(min.X, low.X),
math.min(min.Y, low.Y),
math.min(min.Z, low.Z)
)
max = Vector3.new(
math.max(max.X, high.X),
math.max(max.Y, high.Y),
math.max(max.Z, high.Z)
)
else
min, max = low, high
end
end
end
PlotBoundsCache[plot] = {Min = min, Max = max, Time = os.clock()}
return min, max
end
local function IsPositionInPlot(position, plot)
if not position or not plot then
return false
end
local min, max = GetPlotBounds(plot)
if not min or not max then
return false
end
return position.X >= min.X
and position.X <= max.X
and position.Z >= min.Z
and position.Z <= max.Z
end
local PLOT_SIZE_LIMIT = 500
local LearnedPlotModel = nil
local PlotWarningsSent = {}
local function GetAncestorContainers(object)
local containers = {}
local current = object
while current and current ~= workspace do
if current:IsA("Model") or current:IsA("Folder") then
table.insert(containers, current)
end
current = current.Parent
end
return containers
end
local function IsPlotSized(container)
local min, max = GetPlotBounds(container)
if not min or not max then
return false
end
local size = max - min
return size.X <= PLOT_SIZE_LIMIT and size.Z <= PLOT_SIZE_LIMIT
end
local function ContainerHasPlotMarker(container)
if ParsePlotNumber(container.Name) then
return true
end
for _, descendant in ipairs(container:GetDescendants()) do
local name = string.lower(descendant.Name)
if descendant:IsA("SpawnLocation") then
return true
end
if descendant:IsA("BasePart") then
if string.find(name, "sell", 1, true)
or string.find(name, "plot", 1, true) then
return true
end
end
end
return false
end
local function FindContainerAt(position)
local nearestPart, nearestDistance = nil, math.huge
for _, object in ipairs(workspace:GetDescendants()) do
if object:IsA("BasePart") and not IsPlayerObject(object) then
local distance = (object.Position - position).Magnitude
if distance < nearestDistance then
nearestPart, nearestDistance = object, distance
end
end
end
if not nearestPart then
return nil
end
local candidates = {}
for _, container in ipairs(GetAncestorContainers(nearestPart)) do
if IsPlotSized(container) and ContainerHasPlotMarker(container) then
table.insert(candidates, container)
end
end
if #candidates == 0 then
return nil
end
local innermost = {}
for _, container in ipairs(candidates) do
local containsAnother = false
for _, other in ipairs(candidates) do
if other ~= container and other:IsDescendantOf(container) then
containsAnother = true
break
end
end
if not containsAnother then
table.insert(innermost, container)
end
end
for _, container in ipairs(innermost) do
if ParsePlotNumber(container.Name) then
return container
end
end
return innermost[1]
end
local function LearnPlotFromPosition()
local root = GetRoot()
if not root then
return nil
end
local container = FindContainerAt(root.Position)
if container then
LearnedPlotModel = container
end
return container
end
local function PlotFromPlayerState()
for _, attributeName in ipairs({"Plot", "PlotNumber", "PlotId", "PlotID"}) do
local ok, value = pcall(function()
return LocalPlayer:GetAttribute(attributeName)
end)
if ok and value ~= nil then
local number = tonumber(value)
if not number and typeof(value) == "string" then
number = ParsePlotNumber(value)
end
if number and number >= PLOT_MIN and number <= PLOT_MAX then
return math.floor(number)
end
end
end
local leaderstats = LocalPlayer:FindFirstChild("leaderstats")
if leaderstats then
for _, child in ipairs(leaderstats:GetChildren()) do
if string.find(string.lower(child.Name), "plot", 1, true) then
local number = tonumber(child.Value)
if number and number >= PLOT_MIN and number <= PLOT_MAX then
return math.floor(number)
end
end
end
end
return nil
end
local function DetectPlot()
local plots = GetPlots()
for plotNumber, candidate in pairs(plots) do
if PlotBelongsToPlayer(candidate) then
LearnedPlotModel = candidate
CurrentPlot = plotNumber
CurrentPlotModel = candidate
return CurrentPlot, CurrentPlotModel
end
end
local assignedNumber = PlotFromPlayerState()
if assignedNumber and plots[assignedNumber] then
LearnedPlotModel = plots[assignedNumber]
CurrentPlot = assignedNumber
CurrentPlotModel = LearnedPlotModel
return CurrentPlot, CurrentPlotModel
end
if not LearnedPlotModel or not LearnedPlotModel.Parent then
LearnedPlotModel = LearnPlotFromPosition()
end
if not LearnedPlotModel or not LearnedPlotModel.Parent then
CurrentPlot = nil
CurrentPlotModel = nil
return nil, nil
end
CurrentPlot = assignedNumber
for plotNumber, candidate in pairs(plots) do
if candidate == LearnedPlotModel then
CurrentPlot = plotNumber
break
end
end
CurrentPlotModel = LearnedPlotModel
return CurrentPlot, CurrentPlotModel
end
local function WarnNoPlot(key)
if PlotWarningsSent[key] then
return
end
PlotWarningsSent[key] = true
Notify(
"Plot",
key .. " is paused because your plot was not detected. Stand on your own plot or press Detect My Plot."
)
end
-- SELL PAD
local function FindSellPad()
local plot = CurrentPlotModel
if not plot then
return nil
end
local namedPad, anySell = nil, nil
for _, object in ipairs(workspace:GetDescendants()) do
if object:IsA("BasePart")
and string.find(string.lower(object.Name), "sell", 1, true)
and IsPositionInPlot(object.Position, plot) then
local name = string.lower(object.Name)
if string.find(name, "sellpad", 1, true) then
namedPad = namedPad or object
else
anySell = anySell or object
end
end
end
return namedPad or anySell
end
-- TREES
local function IsTreeCandidate(object)
if not object:IsA("Model") and not object:IsA("BasePart") then
return false
end
if IsPlayerObject(object) then
return false
end
local name = string.lower(object.Name)
if not string.find(name, "tree", 1, true) then
return false
end
if string.find(name, "pad", 1, true)
or string.find(name, "upgrade", 1, true)
or string.find(name, "luck", 1, true)
or string.find(name, "regrow", 1, true) then
return false
end
return GetObjectPosition(object) ~= nil
end
local function FindNearestTree()
local root = GetRoot()
local plot = CurrentPlotModel
if not root or not plot then
return nil
end
local nearest, nearestDistance = nil, math.huge
for _, object in ipairs(workspace:GetDescendants()) do
if IsTreeCandidate(object) then
local position = GetObjectPosition(object)
if position and IsPositionInPlot(position, plot) then
local distance = (position - root.Position).Magnitude
if distance < nearestDistance then
nearest, nearestDistance = object, distance
end
end
end
end
return nearest, nearestDistance
end
local function GetTreePart(tree)
if tree:IsA("BasePart") then
return tree
end
local preferred = tree:FindFirstChild("Trunk", true)
or tree:FindFirstChild("Wood", true)
or tree:FindFirstChild("Log", true)
if preferred and preferred:IsA("BasePart") then
return preferred
end
return tree:FindFirstChildWhichIsA("BasePart", true)
end
-- AXE
local function FindAxe()
local character = GetCharacter()
if character then
for _, child in ipairs(character:GetChildren()) do
if child:IsA("Tool") and Contains(child.Name, "axe") then
return child
end
end
end
local backpack = LocalPlayer:FindFirstChildOfClass("Backpack")
if backpack then
for _, child in ipairs(backpack:GetChildren()) do
if child:IsA("Tool") and Contains(child.Name, "axe") then
return child
end
end
end
return nil
end
local function EquipAxe()
local character = GetCharacter()
local humanoid = GetHumanoid()
local tool = FindAxe()
if not character or not humanoid or not tool then
return nil
end
if tool.Parent ~= character then
pcall(function()
humanoid:EquipTool(tool)
end)
task.wait(0.2)
tool = FindAxe()
end
return tool
end
local function ChopTree(tree)
local treePosition = GetObjectPosition(tree)
if not treePosition then
return false
end
local root = GetRoot()
if not root then
return false
end
TeleportTo(treePosition + Vector3.new(0, 3, 2.5))
task.wait(0.2)
local tool = EquipAxe()
local deadline = os.clock() + math.clamp(ChopTime, 1, 30)
while os.clock() < deadline do
if not ConfigValues.AutoChopToggle then
return false
end
if not tree.Parent then
break
end
root = GetRoot()
if not root then
return false
end
pcall(function()
root.CFrame = CFrame.lookAt(
root.Position,
Vector3.new(treePosition.X, root.Position.Y, treePosition.Z)
)
end)
if not tool or not tool.Parent then
tool = EquipAxe()
end
if tool and tool.Parent then
pcall(function()
tool:Activate()
end)
end
local treePart = GetTreePart(tree)
if treePart then
TouchPart(treePart)
end
for _, descendant in ipairs(tree:GetDescendants()) do
if descendant:IsA("ProximityPrompt") then
FirePrompt(descendant)
end
end
task.wait(0.25)
end
return true
end
-- LOGS
local function IsLogObject(object)
local name = string.lower(tostring(object.Name))
if not string.find(name, "log", 1, true) then
return false
end
return not string.find(name, "logo", 1, true)
and not string.find(name, "login", 1, true)
and not string.find(name, "dialog", 1, true)
and not string.find(name, "catalog", 1, true)
end
local function GetLogs(origin, range)
local logs = {}
range = range or 250
for _, object in ipairs(workspace:GetDescendants()) do
local isPart = object:IsA("BasePart")
local isTool = object:IsA("Tool")
if (isPart or isTool)
and IsLogObject(object)
and not IsPlayerObject(object) then
local part = isPart and object or object:FindFirstChild("Handle")
if not part and isTool then
part = object:FindFirstChildWhichIsA("BasePart", true)
end
if part and part.Parent then
local position = part.Position
local withinRange = true
if origin then
withinRange = (position - origin).Magnitude <= range
end
if withinRange then
table.insert(logs, part)
end
end
end
end
return logs
end
local function PickupLogs(origin)
local plot = CurrentPlotModel
if not plot then
return
end
for _, part in ipairs(GetLogs(origin)) do
if not ConfigValues.AutoChopToggle then
return
end
if part
and part.Parent
and IsPositionInPlot(part.Position, plot) then
TeleportTo(part.Position + Vector3.new(0, 2, 0))
task.wait(0.12)
TouchPart(part)
task.wait(0.12)
end
end
end
local function SellLogs()
local sellPad = FindSellPad()
if not sellPad then
return false
end
InteractWithPart(sellPad, 0.5)
return true
end
local function RunChopCycle()
if ChopBusy then
return
end
if not CurrentPlotModel then
DetectPlot()
if not CurrentPlotModel then
WarnNoPlot("Auto Chop")
return
end
end
PlotWarningsSent["Auto Chop"] = nil
ChopBusy = true
local ok, err = pcall(function()
local tree = FindNearestTree()
if not tree then
return
end
local treePosition = GetObjectPosition(tree)
ChopTree(tree)
if treePosition then
PickupLogs(treePosition)
else
PickupLogs(nil)
end
if ConfigValues.AutoChopToggle then
SellLogs()
end
end)
ChopBusy = false
if not ok then
warn("[Pluto's Script Hub] Auto Chop: " .. tostring(err))
end
end
--==================================================
-- LUMBER EMPIRE TAB
--==================================================
local LumberTab = Window:CreateTab(
"πͺ Lumber Empire",
4483362458
)
LumberTab:CreateParagraph({
Title = "Lumber Empire",
Content = "Chop, haul, and sell automatically."
})
local LumberLoopTokens = {}
local function StartLumberLoop(key, interval, action)
LumberLoopTokens[key] = (LumberLoopTokens[key] or 0) + 1
local token = LumberLoopTokens[key]
task.spawn(function()
while ConfigValues[key] and LumberLoopTokens[key] == token do
local ok, err = pcall(action)
if not ok then
warn("[Pluto's Script Hub] " .. key .. ": " .. tostring(err))
end
task.wait(interval)
end
end)
end
local function StopLumberLoop(key)
LumberLoopTokens[key] = (LumberLoopTokens[key] or 0) + 1
end
local function BuyLumberUpgrade(upgradeName)
ReplicatedStorage
:WaitForChild("Remotes")
:WaitForChild("BuyUpgrade")
:FireServer(upgradeName)
end
-- PLOT
LumberTab:CreateSection("Plot")
local PlotParagraph = LumberTab:CreateParagraph({
Title = "Plot Detection",
Content = "Detecting which plot (1-6) belongs to you..."
})
LumberTab:CreateButton({
Name = "Detect My Plot",
Callback = function()
LearnedPlotModel = nil
LearnPlotFromPosition()
local number = DetectPlot()
if number then
Notify("Plot", "You are on Plot " .. number .. ".")
elseif CurrentPlotModel then
Notify("Plot", "Your plot was found. Farm tools stay inside it.")
else
Notify("Plot", "Could not detect your plot. Stand on your own plot and try again.")
end
end
})
local function RefreshPlotParagraph()
if PlotParagraph and type(PlotParagraph.Set) == "function" then
pcall(function()
PlotParagraph:Set({
Title = "Plot Detection",
Content = CurrentPlot
and ("You are on Plot " .. CurrentPlot .. ". Farm tools stay on this plot.")
or "Plot not detected, so farm tools stay paused until it is found."
})
end)
end
end
DetectPlot()
RefreshPlotParagraph()
LocalPlayer.CharacterAdded:Connect(function()
task.wait(2)
LearnedPlotModel = nil
DetectPlot()
RefreshPlotParagraph()
end)
task.spawn(function()
while task.wait(2) do
local ok = pcall(DetectPlot)
if not ok then
CurrentPlot = nil
CurrentPlotModel = nil
end
RefreshPlotParagraph()
if CurrentPlot and CurrentPlot ~= LastNotifiedPlot then
LastNotifiedPlot = CurrentPlot
Notify("Plot", "You are on Plot " .. CurrentPlot)
end
end
end)
-- AUTO CHOP / SELL
LumberTab:CreateSection("Auto Chop & Sell")
ConfigControls.AutoChopToggle = LumberTab:CreateToggle({
Name = "Auto Chop Trees",
CurrentValue = false,
Flag = "AutoChopToggle",
Callback = function(value)
ConfigValues.AutoChopToggle = value
if value then
StartLumberLoop("AutoChopToggle", 1, RunChopCycle)
else
StopLumberLoop("AutoChopToggle")
end
end
})
ConfigControls.AutoChopTimeSlider = LumberTab:CreateSlider({
Name = "Chop Time Per Tree",
Range = {2, 15},
Increment = 1,
Suffix = "s",
CurrentValue = 5,
Flag = "AutoChopTimeSlider",
Callback = function(value)
ConfigValues.AutoChopTimeSlider = value
ChopTime = value
end
})
LumberTab:CreateParagraph({
Title = "Auto Chop Trees",
Content = "Walks up to the nearest tree on your plot, equips the axe from your inventory, chops it, picks up the dropped logs, then sells at your plot's SellPad."
})
-- REMOTE UPGRADES
LumberTab:CreateSection("Worker & Truck Auto Upgrade")
ConfigControls.AutoUpgradeToggle = LumberTab:CreateToggle({
Name = "Worker & Truck Auto Upgrade",
CurrentValue = false,
Flag = "AutoUpgradeToggle",
Callback = function(value)
ConfigValues.AutoUpgradeToggle = value
if value then
StartLumberLoop("AutoUpgradeToggle", 1, function()
ReplicatedStorage
:WaitForChild("Remotes")
:WaitForChild("HireWorker")
:FireServer()
for _, upgradeName in ipairs({
"TruckLevel",
"TruckSpeed",
"WorkerPower",
"WorkerCarry",
"WorkerSpeed"
}) do
if not ConfigValues.AutoUpgradeToggle then
break
end
BuyLumberUpgrade(upgradeName)
task.wait(1)
end
end)
else
StopLumberLoop("AutoUpgradeToggle")
end
end
})
LumberTab:CreateSection("Tree & Event Tree Auto Upgrade")
ConfigControls.TreeAutoUpgradeToggle = LumberTab:CreateToggle({
Name = "Tree & Event Tree Auto Upgrade",
CurrentValue = false,
Flag = "TreeAutoUpgradeToggle",
Callback = function(value)
ConfigValues.TreeAutoUpgradeToggle = value
if value then
StartLumberLoop("TreeAutoUpgradeToggle", 1, function()
for _, upgradeName in ipairs({
"TreeLuck",
"TreeRegrow",
"HauntTime",
"HauntTrees"
}) do
if not ConfigValues.TreeAutoUpgradeToggle then
break
end
BuyLumberUpgrade(upgradeName)
task.wait(1)
end
end)
else
StopLumberLoop("TreeAutoUpgradeToggle")
end
end
})
LumberTab:CreateSection("Worker & Rebirth")
LumberTab:CreateButton({
Name = "Hire Worker",
Callback = function()
local success, err = pcall(function()
ReplicatedStorage
:WaitForChild("Remotes")
:WaitForChild("HireWorker")
:FireServer()
end)
if success then
Notify("Lumber Empire", "Request sent.")
else
Notify("Error", tostring(err))
end
end
})
ConfigControls.AutoRebirthToggle = LumberTab:CreateToggle({
Name = "Auto Rebirth",
CurrentValue = false,
Flag = "AutoRebirthToggle",
Callback = function(value)
ConfigValues.AutoRebirthToggle = value
if value then
StartLumberLoop("AutoRebirthToggle", 1, function()
ReplicatedStorage
:WaitForChild("Remotes")
:WaitForChild("Rebirth")
:FireServer()
end)
else
StopLumberLoop("AutoRebirthToggle")
end
end
})
--==================================================
-- AIRPORT TAB
--==================================================
local AirportTab = Window:CreateTab(
"βοΈ Airport",
4483362458
)
AirportTab:CreateParagraph({
Title = "Airport Automation",
Content = "Automate hangars, flights, and airport upgrades."
})
local AirportLoopTokens = {}
local function StartAirportLoop(key, action)
AirportLoopTokens[key] = (AirportLoopTokens[key] or 0) + 1
local token = AirportLoopTokens[key]
task.spawn(function()
while ConfigValues[key]
and AirportLoopTokens[key] == token do
local ok, err = pcall(action)
if not ok then
warn("[Pluto's Script Hub] " .. key .. ": " .. tostring(err))
end
task.wait(1)
end
end)
end
local function StopAirportLoop(key)
AirportLoopTokens[key] = (AirportLoopTokens[key] or 0) + 1
end
local function GetAirportRemote(remoteName)
return ReplicatedStorage
:WaitForChild("Remotes")
:WaitForChild(remoteName)
end
ConfigControls.AirportAutoHangarToggle = AirportTab:CreateToggle({
Name = "Auto Hangar",
CurrentValue = false,
Flag = "AirportAutoHangarToggle",
Callback = function(value)
ConfigValues.AirportAutoHangarToggle = value
if value then
StartAirportLoop("AirportAutoHangarToggle", function()
local airportBuy = GetAirportRemote("AirportBuy")
for _, hangarId in ipairs({1, 2, 3}) do
if not ConfigValues.AirportAutoHangarToggle then
break
end
airportBuy:FireServer(hangarId)
task.wait(0.35)
end
end)
else
StopAirportLoop("AirportAutoHangarToggle")
end
end
})
ConfigControls.AirportAutoFlightToggle = AirportTab:CreateToggle({
Name = "Auto Flight",
CurrentValue = false,
Flag = "AirportAutoFlightToggle",
Callback = function(value)
ConfigValues.AirportAutoFlightToggle = value
if value then
StartAirportLoop("AirportAutoFlightToggle", function()
GetAirportRemote("SendPlane"):FireServer("MapleRidge")
end)
else
StopAirportLoop("AirportAutoFlightToggle")
end
end
})
ConfigControls.AirportAutoUpgradeToggle = AirportTab:CreateToggle({
Name = "Auto Airport Upgrade",
CurrentValue = false,
Flag = "AirportAutoUpgradeToggle",
Callback = function(value)
ConfigValues.AirportAutoUpgradeToggle = value
if value then
StartAirportLoop("AirportAutoUpgradeToggle", function()
local buyUpgrade = GetAirportRemote("BuyUpgrade")
for _, upgradeName in ipairs({
"FlightSpeed",
"CargoHold",
"LogDiscount"
}) do
if not ConfigValues.AirportAutoUpgradeToggle then
break
end
buyUpgrade:FireServer(upgradeName)
task.wait(0.35)
end
end)
else
StopAirportLoop("AirportAutoUpgradeToggle")
end
end
})
--==================================================
-- UNIVERSAL TAB
--==================================================
local UniversalTab = Window:CreateTab(
"Universal",
4483362458
)
UniversalTab:CreateParagraph({
Title = "Universal Features",
Content = "Player utilities available from the Universal tab."
})
UniversalTab:CreateSection("External Script")
UniversalTab:CreateParagraph({
Title = "Infinite Yield",
Content = "Load Infinite Yield separately from the player utilities below."
})
UniversalTab:CreateButton({
Name = "Load Infinite Yield",
Callback = function()
local success, err = pcall(function()
loadstring(game:HttpGet(
"https://raw.githubusercontent.com/EdgeIY/infiniteyield/master/source"
))()
end)
if not success then
Notify("Error", tostring(err))
end
end
})
UniversalTab:CreateSection("Player Configurations")
-- WALK SPEED
local WalkSpeedEnabled = false
local WalkSpeedValue = 32
local function ApplyWalkSpeed()
local character = LocalPlayer.Character
local humanoid = character
and character:FindFirstChildOfClass("Humanoid")
if humanoid and WalkSpeedEnabled then
humanoid.WalkSpeed = WalkSpeedValue
end
end
ConfigControls.WalkSpeedToggle = UniversalTab:CreateToggle({
Name = "Walk Speed",
CurrentValue = false,
Flag = "WalkSpeedToggle",
Callback = function(value)
ConfigValues.WalkSpeedToggle = value
WalkSpeedEnabled = value
ApplyWalkSpeed()
end
})
ConfigControls.WalkSpeedSlider = UniversalTab:CreateSlider({
Name = "Walk Speed Amount",
Range = {16, 200},
Increment = 1,
Suffix = "Speed",
CurrentValue = 32,
Flag = "WalkSpeedSlider",
Callback = function(value)
ConfigValues.WalkSpeedSlider = value
WalkSpeedValue = value
ApplyWalkSpeed()
end
})
-- NOCLIP
local NoclipConnection
local function SetNoclip(value)
if NoclipConnection then
NoclipConnection:Disconnect()
NoclipConnection = nil
end
if value then
NoclipConnection = RunService.Stepped:Connect(function()
local character = LocalPlayer.Character
if not character then
return
end
for _, part in ipairs(character:GetDescendants()) do
if part:IsA("BasePart") then
part.CanCollide = false
end
end
end)
else
local character = LocalPlayer.Character
if character then
for _, part in ipairs(character:GetDescendants()) do
if part:IsA("BasePart") then
part.CanCollide = true
end
end
end
end
end
ConfigControls.NoclipToggle = UniversalTab:CreateToggle({
Name = "Noclip",
CurrentValue = false,
Flag = "NoclipToggle",
Callback = function(value)
ConfigValues.NoclipToggle = value
SetNoclip(value)
end
})
-- INSTANT PROXIMITY PROMPT
local InstantPromptEnabled = false
ConfigControls.InstantPromptToggle = UniversalTab:CreateToggle({
Name = "Instant Proximity Prompt",
CurrentValue = false,
Flag = "InstantPromptToggle",
Callback = function(value)
ConfigValues.InstantPromptToggle = value
InstantPromptEnabled = value
if value then
Notify("Prompts", "Instant prompt enabled.")
end
end
})
local function UpdatePrompt(prompt)
if InstantPromptEnabled and prompt:IsA("ProximityPrompt") then
pcall(function()
prompt.HoldDuration = 0
end)
end
end
for _, object in ipairs(workspace:GetDescendants()) do
UpdatePrompt(object)
end
workspace.DescendantAdded:Connect(function(object)
UpdatePrompt(object)
end)
RunService.Heartbeat:Connect(function()
if not InstantPromptEnabled then
return
end
for _, object in ipairs(workspace:GetDescendants()) do
if object:IsA("ProximityPrompt") then
pcall(function()
object.HoldDuration = 0
end)
end
end
end)
-- ANTI-AFK
local AntiAFKEnabled = false
ConfigControls.AntiAFKToggle = UniversalTab:CreateToggle({
Name = "Anti-AFK",
CurrentValue = false,
Flag = "AntiAFKToggle",
Callback = function(value)
ConfigValues.AntiAFKToggle = value
AntiAFKEnabled = value
end
})
LocalPlayer.Idled:Connect(function()
if AntiAFKEnabled then
pcall(function()
VirtualUser:CaptureController()
VirtualUser:ClickButton2(Vector2.new(0, 0))
end)
end
end)
--==================================================
-- SETTINGS TAB: NAMED CONFIGS + AUTO-LOAD
--==================================================
local SettingsTab = Window:CreateTab("Settings", 4483362458)
local ConfigDropdown
local AutoLoadToggle
SettingsTab:CreateParagraph({
Title = "Configuration Manager",
Content = "Save named presets of your hub toggles and slider values, then load them later or enable auto-load. Configs are stored locally by your executor."
})
SettingsTab:CreateInput({
Name = "Config Name",
CurrentValue = "My Config",
PlaceholderText = "Enter a config name",
RemoveTextAfterFocusLost = false,
Flag = "ConfigNameInput",
Callback = function(value)
ConfigNameInputValue = tostring(value or "")
end
})
local function RefreshConfigDropdown()
local names = ListSavedConfigs()
local options = #names > 0 and names or {"No saved configs"}
if ConfigDropdown and type(ConfigDropdown.Refresh) == "function" then
pcall(function()
ConfigDropdown:Refresh(options, true)
end)
end
if SelectedConfigName ~= "" then
local found = false
for _, name in ipairs(names) do
if name == SelectedConfigName then
found = true
break
end
end
if not found then
SelectedConfigName = ""
end
end
return names
end
local function SaveCurrentConfig(name)
name = CleanConfigName(name)
if name == "" then
Notify("Configs", "Enter a name before saving.")
return false
end
if not EnsureConfigFolders() then
Notify("Configs", "Your executor does not support the required file APIs.")
return false
end
local ok, err = pcall(function()
writefile(ConfigPath(name), HttpService:JSONEncode(ConfigValues))
end)
if not ok then
Notify("Config Error", tostring(err))
return false
end
SelectedConfigName = name
RefreshConfigDropdown()
Notify("Configs", "Saved config: " .. name)
return true
end
local function LoadConfig(name, silent)
name = CleanConfigName(name)
if name == "" then
if not silent then
Notify("Configs", "Select a saved config first.")
end
return false
end
if not EnsureConfigFolders() then
if not silent then
Notify("Configs", "Your executor does not support the required file APIs.")
end
return false
end
local path = ConfigPath(name)
local exists = false
if typeof(isfile) == "function" then
local ok, result = pcall(isfile, path)
exists = ok and result
else
local ok = pcall(readfile, path)
exists = ok
end
if not exists then
if not silent then
Notify("Configs", "Config not found: " .. name)
end
return false
end
local readOk, decoded = pcall(function()
return HttpService:JSONDecode(readfile(path))
end)
if not readOk or type(decoded) ~= "table" then
if not silent then
Notify("Config Error", "That config file is invalid.")
end
return false
end
for key, control in pairs(ConfigControls) do
local value = decoded[key]
if value ~= nil then
local setOk = false
if control and type(control.Set) == "function" then
setOk = pcall(function()
control:Set(value)
end)
end
if not setOk then
ConfigValues[key] = value
end
end
end
if decoded.HubOpacitySlider ~= nil then
HubOpacity = math.clamp(
tonumber(decoded.HubOpacitySlider) or 100,
0,
100
)
ConfigValues.HubOpacitySlider = HubOpacity
task.spawn(function()
for _ = 1, 20 do
if ApplyHubOpacity() then
break
end
task.wait(0.25)
end
end)
end
SelectedConfigName = name
if not silent then
Notify("Configs", "Loaded config: " .. name)
end
return true
end
local InitialConfigNames = ListSavedConfigs()
local InitialConfigOptions = #InitialConfigNames > 0
and InitialConfigNames
or {"No saved configs"}
if #InitialConfigNames > 0 then
SelectedConfigName = InitialConfigNames[1]
end
ConfigDropdown = SettingsTab:CreateDropdown({
Name = "Saved Configs",
Options = InitialConfigOptions,
CurrentOption = {InitialConfigOptions[1]},
MultipleOptions = false,
Flag = "SavedConfigDropdown",
Callback = function(option)
if type(option) == "table" then
SelectedConfigName = tostring(option[1] or "")
else
SelectedConfigName = tostring(option or "")
end
if SelectedConfigName == "No saved configs" then
SelectedConfigName = ""
end
if AutoLoadEnabled and SelectedConfigName ~= "" then
AutoLoadConfigName = SelectedConfigName
SaveAutoLoadSetting()
end
end
})
SettingsTab:CreateButton({
Name = "Save Config",
Callback = function()
SaveCurrentConfig(ConfigNameInputValue)
end
})
SettingsTab:CreateButton({
Name = "Load Selected Config",
Callback = function()
LoadConfig(SelectedConfigName, false)
end
})
SettingsTab:CreateButton({
Name = "Refresh Config List",
Callback = function()
RefreshConfigDropdown()
Notify("Configs", "Saved config list refreshed.")
end
})
AutoLoadToggle = SettingsTab:CreateToggle({
Name = "Auto-Load Selected Config",
CurrentValue = false,
Flag = "AutoLoadConfigToggle",
Callback = function(value)
AutoLoadEnabled = value
if value then
if SelectedConfigName == "" then
AutoLoadEnabled = false
Notify("Configs", "Select a saved config before enabling auto-load.")
task.defer(function()
if AutoLoadToggle and type(AutoLoadToggle.Set) == "function" then
pcall(function()
AutoLoadToggle:Set(false)
end)
end
end)
return
end
AutoLoadConfigName = SelectedConfigName
else
AutoLoadConfigName = ""
end
if SaveAutoLoadSetting() then
Notify(
"Configs",
value
and ("Auto-load enabled for: " .. AutoLoadConfigName)
or "Auto-load disabled."
)
else
Notify("Configs", "Could not save auto-load setting; check executor file access.")
end
end
})
task.defer(function()
task.wait(1)
if not EnsureConfigFolders() then
return
end
local ok, saved = pcall(function()
if typeof(isfile) == "function" and not isfile(AUTOLOAD_PATH) then
return nil
end
return HttpService:JSONDecode(readfile(AUTOLOAD_PATH))
end)
if ok
and type(saved) == "table"
and saved.Enabled == true
and type(saved.ConfigName) == "string" then
AutoLoadConfigName = saved.ConfigName
SelectedConfigName = saved.ConfigName
AutoLoadEnabled = true
if AutoLoadToggle and type(AutoLoadToggle.Set) == "function" then
pcall(function()
AutoLoadToggle:Set(true)
end)
else
AutoLoadEnabled = true
end
LoadConfig(AutoLoadConfigName, true)
Notify("Configs", "Auto-loaded: " .. AutoLoadConfigName)
end
end)
--==================================================
-- INFO TAB
--==================================================
local InfoTab = Window:CreateTab("Info", 4483362458)
InfoTab:CreateParagraph({
Title = "Pluto's Script Hub",
Content = "Adjust the hub panel background transparency or copy the Discord invite."
})
ConfigControls.HubOpacitySlider = InfoTab:CreateSlider({
Name = "Hub Opacity",
Range = {0, 100},
Increment = 5,
Suffix = "%",
CurrentValue = 100,
Flag = "HubOpacitySlider",
Callback = function(value)
ConfigValues.HubOpacitySlider = value
HubOpacity = value
local applied = ApplyHubOpacity()
if not applied then
task.spawn(function()
for _ = 1, 8 do
task.wait(0.25)
if ApplyHubOpacity() then
return
end
end
Notify(
"Hub Opacity",
"This Rayfield layout could not be detected, so opacity may not be supported here."
)
end)
end
end
})
InfoTab:CreateButton({
Name = "Copy Discord Invite",
Callback = function()
local invite = "https://discord.gg/sr9Q3rn9Bf"
local copied = false
if typeof(setclipboard) == "function" then
copied = pcall(setclipboard, invite)
elseif typeof(toclipboard) == "function" then
copied = pcall(toclipboard, invite)
end
if copied then
Notify("Discord", "Invite link copied to your clipboard!")
else
Notify("Discord Invite", invite .. " (clipboard access unavailable)")
end
end
})
task.spawn(function()
for _ = 1, 10 do
if ApplyHubOpacity() then
break
end
task.wait(0.5)
end
end)
task.spawn(function()
while task.wait(0.75) do
if HubOpacity < 100 then
ApplyHubOpacity()
end
end
end)
Notify(
"Pluto's Script Hub",
"Lumber Empire tools loaded!"
)Review the source before using it. Executions count successful copies, capped at 10 per user and network per script in 24 hours.
Community discussion
0Start the conversation.


Your community, in one place