M
Description
auto buy auto craft and AUTO MINE EMERALDS (genuinely the most op feature i thought of)
GAMEMiners World [Neptune]
UPDATEDOct 17, 2026
ACCESSKeyless
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 ]]
--[[ Miners World - Auto Buy (Pickaxes, Backpacks, Luck, Speed, Jump, Jackhammer, Explosions + Mining Speed)
Buys the next pickaxe, backpack, luck, speed, and jump levels as soon as you can afford them.
Uses the game's own cost formulas and the same call the shop buttons make.
Also includes unlocked lobby teleports and native upgrade-screen shortcuts.
Includes recipe tracking and native auto-crafting when materials are ready.
Includes an opt-in mode that adds Emeralds to native AutoMine targeting.
The Speed Hub X UI sources are pinned to the inspected GitHub revisions.
RightShift = hide / show × = unload (or getgenv().__MWG_UNLOAD())
Settings are remembered in minersworld_autobuy_test.json
]]
local PLACE_ID = 9404223526
print("[MWG] Test script started in place", game.PlaceId)
if game.PlaceId ~= PLACE_ID then
warn("[MWG] This script only runs in Miners World (place " .. PLACE_ID .. ")")
return
end
if not game:IsLoaded() then game.Loaded:Wait() end
local env = (getgenv and getgenv()) or _G
if env.__MWG_UNLOAD then pcall(env.__MWG_UNLOAD) end
if env.__MW_UNLOAD then pcall(env.__MW_UNLOAD) end -- older all-in-one version
local RS = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")
local UIS = game:GetService("UserInputService")
local Http = game:GetService("HttpService")
local TweenService = game:GetService("TweenService")
local RunService = game:GetService("RunService")
local Stats = game:GetService("Stats")
local Workspace = game:GetService("Workspace")
local lp = Players.LocalPlayer
local uiLibrary
local libraryGuis = {}
local libraryWindowGui
----------------------------------------------------------------------
-- Game modules + data
----------------------------------------------------------------------
local Modules = RS:WaitForChild("Modules")
local DataModule = require(Modules:WaitForChild("DataModule"))
local Networking = require(Modules:WaitForChild("Networking"))
local GD = require(Modules:WaitForChild("GameDefinition"))
local FH = require(Modules:WaitForChild("FormulaHandler"))
local GuiHandler = require(Modules:WaitForChild("GuiHandler"))
local Translator = require(Modules:WaitForChild("Translator"))
local data
for _ = 1, 120 do
local ok, d = pcall(DataModule.GetData, lp)
if ok and d and d:FindFirstChild("Others") and d.Others:FindFirstChild("Loaded") and d.Others.Loaded.Value then
data = d
break
end
task.wait(0.5)
end
if not data then
warn("[MWG] player data never finished loading")
return
end
local gameFrames = lp:WaitForChild("PlayerGui"):WaitForChild("Game"):WaitForChild("Frames")
----------------------------------------------------------------------
-- Settings
----------------------------------------------------------------------
local FILE = "minersworld_autobuy_test.json"
local S = {
master = true,
Pickaxe = true,
Backpack = true,
Luck = true,
Speed = true,
Jump = true,
Jackhammer = true,
Explosions = true,
MiningSpeed = true,
AutoCraft = false,
AutoPinNextCraft = true,
HideExplosiveEffects = true,
WalkSpeed = 16,
IncludeEmeraldsInAutoMine = false,
}
pcall(function()
if isfile and isfile(FILE) then
local saved = Http:JSONDecode(readfile(FILE))
for k in pairs(S) do
if type(saved[k]) == type(S[k]) then
S[k] = saved[k]
end
end
if type(saved.IncludeEmeraldsInAutoMine) ~= "boolean"
and type(saved.EmeraldOnlyAutoMine) == "boolean" then
S.IncludeEmeraldsInAutoMine = saved.EmeraldOnlyAutoMine
end
end
end)
S.WalkSpeed = math.clamp(S.WalkSpeed, 16, 90)
local function save()
pcall(function()
if writefile then writefile(FILE, Http:JSONEncode(S)) end
end)
end
local EMERALD_BLOCK_ID = 863
local emeraldTargetingActive = false
local emeraldTargetingOriginals
local function restoreEmeraldTargeting()
emeraldTargetingActive = false
local originals = emeraldTargetingOriginals
if not originals then return end
local ok, err = pcall(function()
GD.RarityMap[EMERALD_BLOCK_ID] = originals.rarity
GD.Unobtainable[EMERALD_BLOCK_ID] = originals.unobtainable
end)
if ok then
emeraldTargetingOriginals = nil
else
warn("[MWG] could not restore Emerald AutoMine eligibility:", err)
end
end
local function enableEmeraldTargeting()
if type(GD.RarityMap) ~= "table" or type(GD.Unobtainable) ~= "table" then
error("[MWG] Emerald AutoMine unavailable: game eligibility maps are missing", 0)
end
local originalRarity = GD.RarityMap[EMERALD_BLOCK_ID]
local originalUnobtainable = GD.Unobtainable[EMERALD_BLOCK_ID]
emeraldTargetingOriginals = {
rarity = originalRarity,
unobtainable = originalUnobtainable,
}
local eligibilityOk, eligibilityError = pcall(function()
-- Preserve every native candidate; only add Emerald to the eligible rarity pool.
GD.RarityMap[EMERALD_BLOCK_ID] = 5
GD.Unobtainable[EMERALD_BLOCK_ID] = nil
end)
if not eligibilityOk then
restoreEmeraldTargeting()
error(
"[MWG] could not enable Emerald AutoMine eligibility: " .. tostring(eligibilityError),
0
)
end
emeraldTargetingActive = true
end
local function setIncludeEmeraldsInAutoMine(enabled)
if enabled then
if not emeraldTargetingActive then
enableEmeraldTargeting()
end
S.IncludeEmeraldsInAutoMine = true
print("[MWG] Emerald added to native AutoMine targets")
else
S.IncludeEmeraldsInAutoMine = false
restoreEmeraldTargeting()
print("[MWG] Emerald removed from native AutoMine targets")
end
save()
end
----------------------------------------------------------------------
-- Buying logic
----------------------------------------------------------------------
local ITEMS = {
{ cat = "Pickaxe", title = "Pickaxe" },
{ cat = "Backpack", title = "Backpack" },
{ cat = "Luck", title = "Luck" },
{ cat = "Speed", title = "Speed" },
{ cat = "Jump", title = "Jump" },
}
local UPGRADE_GROUPS = {
{ setting = "Jackhammer", title = "Jackhammer", ids = { "2_1", "2_2", "2_3" } },
{ setting = "Explosions", title = "Explosions", ids = { "4_1", "4_2", "4_3" } },
{ setting = "MiningSpeed", title = "Mining Speed", ids = { "3_1", "3_2" } },
}
local UPGRADE_ITEMS = {}
for _, group in ipairs(UPGRADE_GROUPS) do
for _, upgradeId in ipairs(group.ids) do
UPGRADE_ITEMS[#UPGRADE_ITEMS + 1] = {
setting = group.setting,
title = group.title,
id = upgradeId,
}
end
end
local bought = { Pickaxe = 0, Backpack = 0, Luck = 0, Speed = 0, Jump = 0 }
local lastAction = nil
local lastNetworkAction = -math.huge
local BASE_ACTION_DELAY = 0.4
local MAX_ACTION_DELAY = 2.5
local function canSendAutomaticAction()
local delay = BASE_ACTION_DELAY
local ok, ping = pcall(function()
return Stats.Network.ServerStatsItem["Data Ping"]:GetValue()
end)
if ok and type(ping) == "number" then
delay = math.clamp(ping / 1000 * 2.5, BASE_ACTION_DELAY, MAX_ACTION_DELAY)
end
return os.clock() - lastNetworkAction >= delay
end
local function noteNetworkAction()
lastNetworkAction = os.clock()
end
local function removeExplosiveEffect(instance)
if S.HideExplosiveEffects and instance:IsA("Explosion") then
instance:Destroy()
end
end
local function setExplosiveEffectsHidden(hidden)
S.HideExplosiveEffects = hidden
if hidden then
for _, instance in ipairs(Workspace:GetDescendants()) do
removeExplosiveEffect(instance)
end
end
save()
end
local function parts(cat)
local def = GD.Formulas.Equipables[cat]
local ul = data.Equipables.Unlocked:FindFirstChild(cat)
local wallet = def and data.NumberValues:FindFirstChild(def.Currency)
return def, ul, wallet
end
-- how many levels (1-5) we can afford right now; the shop lets you buy up to 5 ahead
local function decide(cat, have)
local def, ul = parts(cat)
if not (def and ul) or def.FirstBuyable then return nil end
local lvl = ul.Value
for n = 5, 1, -1 do
local idx = lvl + n
if not def.MaxLevel or idx <= def.MaxLevel then
local ok, cost = pcall(FH.GetEquipableCostForMultiple, data, cat, n)
if ok and type(cost) == "number" and cost <= have then
return n, idx, cost, lvl
end
end
end
end
env.__MWG_DECIDE = decide -- debug helper
-- if a purchase doesn't change the level, back off (the server said no)
local attempts = {}
local function blocked(key, level)
local a = attempts[key]
if not a or a.level ~= level then return false end
return os.clock() - a.t < math.min(5 * 2 ^ a.fails, 30)
end
local function noteAttempt(key, level)
local a = attempts[key]
if a and a.level == level then
a.fails += 1
a.t = os.clock()
else
attempts[key] = { level = level, fails = 0, t = os.clock() }
end
end
local function stepItem(item)
if not S[item.cat] then return false end
local _, _, wallet = parts(item.cat)
if not wallet then return false end
local n, idx, _, lvl = decide(item.cat, wallet.Value)
if not n or blocked(item.cat, lvl) or not canSendAutomaticAction() then return false end
noteAttempt(item.cat, lvl)
noteNetworkAction()
Networking.Fire("Equip", item.cat, idx)
bought[item.cat] += n
lastAction = string.format("Bought %s %d → %d", item.title, lvl, idx)
return true
end
local function stepUpgrade(item)
if not S[item.setting] then return false end
local definition = GD.Formulas.Upgrades[item.id]
if not definition or type(definition.Cost) ~= "function" then
warn("[MWG] missing upgrade formula for", item.id)
return false
end
local okLevel, levelValue = pcall(FH.GetUpgrade, data, item.id)
if not okLevel then
warn("[MWG] could not read upgrade level " .. item.id .. ":", levelValue)
return false
end
local level = levelValue and levelValue.Value
if type(level) ~= "number" or type(definition.MaxLevel) ~= "number" or level >= definition.MaxLevel then
return false
end
local currencyName = type(definition.Currency) == "string"
and string.match(definition.Currency, "^NumberValues%.(.+)$")
local wallet = currencyName and data.NumberValues:FindFirstChild(currencyName)
if not wallet then
warn("[MWG] missing upgrade currency for", item.id, definition.Currency)
return false
end
local okCost, cost = pcall(definition.Cost, level)
if not okCost then
warn("[MWG] could not calculate upgrade cost " .. item.id .. ":", cost)
return false
end
local attemptKey = "Upgrade:" .. item.id
if type(cost) ~= "number" or cost > wallet.Value or blocked(attemptKey, level)
or not canSendAutomaticAction() then
return false
end
local ok, err = pcall(Networking.Fire, "BuyUpgrade", item.id)
if not ok then
warn("[MWG] native upgrade request failed for " .. item.id .. ":", err)
return false
end
noteAttempt(attemptKey, level)
noteNetworkAction()
lastAction = string.format("Bought %s upgrade %d → %d", item.title, level, level + 1)
return true
end
local function step(tick)
-- Rotate all purchase types through the shared action throttle.
local totalItems = #ITEMS + #UPGRADE_ITEMS
local first = tick % totalItems + 1
for i = 0, totalItems - 1 do
local index = ((first - 1 + i) % totalItems) + 1
if index <= #ITEMS then
if stepItem(ITEMS[index]) then return end
elseif stepUpgrade(UPGRADE_ITEMS[index - #ITEMS]) then
return
end
end
end
----------------------------------------------------------------------
-- Number formatting
----------------------------------------------------------------------
local SUFFIX = { "", "K", "M", "B", "T", "Qa", "Qi", "Sx", "Sp", "Oc", "No", "Dc" }
local function abbr(n)
if type(n) ~= "number" or n ~= n then return "?" end
if n == math.huge then return "∞" end
if n < 1000 then
if n == math.floor(n) then return tostring(n) end
return string.format("%.1f", n)
end
local e = math.min(math.floor(math.log10(n) / 3), #SUFFIX - 1)
local v = n / 10 ^ (e * 3)
local s = string.format((v >= 100 and "%.0f") or (v >= 10 and "%.1f") or "%.2f", v)
if s:find(".", 1, true) then
s = s:gsub("0+$", "")
s = s:gsub("%.$", "")
end
return s .. SUFFIX[e + 1]
end
----------------------------------------------------------------------
-- UI helpers
----------------------------------------------------------------------
local C = {
bgTop = Color3.fromRGB(28, 31, 43),
bgBot = Color3.fromRGB(17, 19, 26),
card = Color3.fromRGB(30, 34, 46),
track = Color3.fromRGB(15, 17, 23),
text = Color3.fromRGB(236, 239, 247),
muted = Color3.fromRGB(131, 139, 162),
accent = Color3.fromRGB(242, 65, 65),
ok = Color3.fromRGB(96, 214, 148),
off = Color3.fromRGB(58, 63, 82),
danger = Color3.fromRGB(235, 96, 112),
}
local animateButton
local function new(class, props, parent)
local o = Instance.new(class)
for k, v in pairs(props) do o[k] = v end
if class == "TextLabel" or class == "TextButton" or class == "TextBox" then
local fontName = o.Font.Name
if string.find(fontName, "ExtraBold") or string.find(fontName, "Black") then
o.Font = Enum.Font.BuilderSansExtraBold
elseif string.find(fontName, "Bold") then
o.Font = Enum.Font.BuilderSansBold
elseif string.find(fontName, "Medium") or string.find(fontName, "Semibold") then
o.Font = Enum.Font.BuilderSansMedium
else
o.Font = Enum.Font.BuilderSans
end
if type(props.TextSize) == "number" then
o.TextSize = props.TextSize + 1
end
end
if parent then o.Parent = parent end
if animateButton and o:IsA("GuiButton") then animateButton(o) end
return o
end
local function corner(o, r) return new("UICorner", { CornerRadius = UDim.new(0, r) }, o) end
local function outline(o, transparency)
return new("UIStroke", {
Color = Color3.new(1, 1, 1), Transparency = transparency or 0.92, Thickness = 1,
ApplyStrokeMode = Enum.ApplyStrokeMode.Border,
}, o)
end
local function label(parent, props)
local p = {
BackgroundTransparency = 1, Font = Enum.Font.GothamMedium, TextColor3 = C.text, TextSize = 13,
TextXAlignment = Enum.TextXAlignment.Left, TextYAlignment = Enum.TextYAlignment.Center, Text = "",
}
for k, v in pairs(props) do p[k] = v end
return new("TextLabel", p, parent)
end
local function tween(o, t, props)
local animation = TweenService:Create(o, TweenInfo.new(t, Enum.EasingStyle.Quad, Enum.EasingDirection.Out), props)
animation:Play()
return animation
end
local conns = {}
local function track(c) conns[#conns + 1] = c return c end
track(Workspace.DescendantAdded:Connect(removeExplosiveEffect))
local switchRenders = {}
animateButton = function(button)
local scale = new("UIScale", { Scale = 1 }, button)
button.InputBegan:Connect(function(input)
if input.UserInputType == Enum.UserInputType.MouseButton1
or input.UserInputType == Enum.UserInputType.Touch then
tween(scale, 0.08, { Scale = 0.94 })
end
end)
button.InputEnded:Connect(function(input)
if input.UserInputType == Enum.UserInputType.MouseButton1
or input.UserInputType == Enum.UserInputType.Touch then
tween(scale, 0.12, { Scale = 1 })
end
end)
end
local function makeSwitch(parent, pos, get, set)
local sw = new("TextButton", {
Size = UDim2.fromOffset(40, 22), Position = pos, Text = "", AutoButtonColor = false,
BackgroundColor3 = C.off, BorderSizePixel = 0,
}, parent)
corner(sw, 11)
local knob = new("Frame", {
Size = UDim2.fromOffset(16, 16), Position = UDim2.fromOffset(3, 3),
BackgroundColor3 = Color3.new(1, 1, 1), BorderSizePixel = 0,
}, sw)
corner(knob, 8)
local function render(animate)
local on = get()
local t = animate and 0.16 or 0
tween(sw, t, { BackgroundColor3 = on and C.accent or C.off })
tween(knob, t, { Position = UDim2.fromOffset(on and 21 or 3, 3) })
end
sw.MouseButton1Click:Connect(function()
set(not get())
render(true)
save()
end)
render(false)
switchRenders[#switchRenders + 1] = function() render(false) end
return sw
end
----------------------------------------------------------------------
-- UI
----------------------------------------------------------------------
local uiRoot
do
local ok, r = pcall(function() return (gethui and gethui()) or game:GetService("CoreGui") end)
uiRoot = (ok and r) or lp:WaitForChild("PlayerGui")
end
local gui = new("ScreenGui", {
Name = "MWG" .. math.random(1000, 9999), ResetOnSpawn = false,
ZIndexBehavior = Enum.ZIndexBehavior.Sibling, DisplayOrder = 1000,
})
pcall(function() if syn and syn.protect_gui then syn.protect_gui(gui) end end)
gui.Parent = uiRoot
gui.Enabled = false
local win
local function colorSequence()
local tinted = C.bgBot:Lerp(C.accent, 0.12)
return ColorSequence.new({
ColorSequenceKeypoint.new(0, C.bgTop),
ColorSequenceKeypoint.new(0.52, tinted),
ColorSequenceKeypoint.new(1, C.bgBot),
})
end
local function addSurfaceGradient(surface)
return new("UIGradient", {
Rotation = 25,
Color = ColorSequence.new(C.card, C.card:Lerp(C.accent, 0.08)),
}, surface)
end
win = new("Frame", {
Name = "Window", AnchorPoint = Vector2.new(0, 0.5), Position = UDim2.new(0, 40, 0.5, 0),
Size = UDim2.fromOffset(420, 0), AutomaticSize = Enum.AutomaticSize.Y,
BackgroundColor3 = Color3.new(1, 1, 1), BorderSizePixel = 0, Active = true,
}, gui)
corner(win, 14)
outline(win, 0.86)
new("UIGradient", { Rotation = 90, Color = colorSequence() }, win)
new("UIPadding", {
PaddingTop = UDim.new(0, 14), PaddingBottom = UDim.new(0, 14),
PaddingLeft = UDim.new(0, 14), PaddingRight = UDim.new(0, 14),
}, win)
new("UIListLayout", { Padding = UDim.new(0, 12), SortOrder = Enum.SortOrder.LayoutOrder }, win)
-- header ------------------------------------------------------------
local header = new("Frame", { Size = UDim2.new(1, 0, 0, 40), BackgroundTransparency = 1, LayoutOrder = 1 }, win)
local headerAccent = new("Frame", {
Size = UDim2.new(0, 250, 0, 2), Position = UDim2.fromOffset(0, 38),
BackgroundColor3 = C.accent, BorderSizePixel = 0,
}, header)
new("UIGradient", {
Transparency = NumberSequence.new({
NumberSequenceKeypoint.new(0, 0.08),
NumberSequenceKeypoint.new(1, 1),
}),
}, headerAccent)
local dragArea = new("Frame", {
Size = UDim2.fromOffset(160, 40), BackgroundTransparency = 1, Active = true,
}, header)
label(dragArea, {
Text = "MINERS WORLD", Font = Enum.Font.GothamBold, TextSize = 10, TextColor3 = C.accent,
Size = UDim2.new(1, 0, 0, 12), Position = UDim2.fromOffset(0, 3),
})
label(dragArea, {
Text = "Auto Buy", Font = Enum.Font.GothamBold, TextSize = 17,
Size = UDim2.new(1, 0, 0, 24), Position = UDim2.fromOffset(0, 15),
})
local function headerButton(text, x, color)
local b = new("TextButton", {
Size = UDim2.fromOffset(22, 22), Position = UDim2.fromOffset(x, 9), BackgroundColor3 = C.card,
Text = text, TextColor3 = color or C.muted, Font = Enum.Font.GothamBold, TextSize = 15,
AutoButtonColor = false, BorderSizePixel = 0,
}, header)
corner(b, 6)
b.MouseEnter:Connect(function() tween(b, 0.12, { BackgroundColor3 = C.off }) end)
b.MouseLeave:Connect(function() tween(b, 0.12, { BackgroundColor3 = C.card }) end)
return b
end
local closeBtn = headerButton("×", 366)
local collapseBtn = headerButton("–", 338)
makeSwitch(header, UDim2.fromOffset(286, 9), function() return S.master end, function(v) S.master = v end)
-- body --------------------------------------------------------------
local PAGE_HEIGHT = 524
local body = new("Frame", {
Size = UDim2.new(1, 0, 0, 0), AutomaticSize = Enum.AutomaticSize.Y, BackgroundTransparency = 1, LayoutOrder = 2,
}, win)
local sidebar = new("Frame", {
Size = UDim2.new(0, 76, 0, 226), BackgroundTransparency = 1,
}, body)
local mainPage = new("ScrollingFrame", {
Size = UDim2.new(1, -86, 0, PAGE_HEIGHT), Position = UDim2.fromOffset(86, 0),
BackgroundTransparency = 1, BorderSizePixel = 0, ScrollBarThickness = 5,
CanvasSize = UDim2.new(0, 0, 0, 0), AutomaticCanvasSize = Enum.AutomaticSize.Y,
}, body)
new("UIListLayout", { Padding = UDim.new(0, 10), SortOrder = Enum.SortOrder.LayoutOrder }, mainPage)
local teleportPage = new("Frame", {
Size = UDim2.new(1, -86, 0, PAGE_HEIGHT), Position = UDim2.fromOffset(86, 0),
BackgroundTransparency = 1, Visible = false,
}, body)
label(teleportPage, {
Text = "Lobbies", Font = Enum.Font.GothamBold, TextSize = 15,
Size = UDim2.new(1, 0, 0, 20), Position = UDim2.fromOffset(0, 0),
})
label(teleportPage, {
Text = "Only lobbies unlocked by the game are available.",
TextSize = 11, TextColor3 = C.muted, TextWrapped = true,
Size = UDim2.new(1, 0, 0, 32), Position = UDim2.fromOffset(0, 24),
})
local lobbyList = new("ScrollingFrame", {
Size = UDim2.new(1, 0, 0, PAGE_HEIGHT - 68), Position = UDim2.fromOffset(0, 62),
BackgroundTransparency = 1, BorderSizePixel = 0, ScrollBarThickness = 5,
CanvasSize = UDim2.new(0, 0, 0, 0), AutomaticCanvasSize = Enum.AutomaticSize.Y,
}, teleportPage)
new("UIListLayout", { Padding = UDim.new(0, 6), SortOrder = Enum.SortOrder.LayoutOrder }, lobbyList)
local function makeTab(text, order)
local button = new("TextButton", {
Size = UDim2.new(1, 0, 0, 36), Position = UDim2.fromOffset(0, (order - 1) * 44),
BackgroundColor3 = C.off, Text = text, TextColor3 = C.text,
Font = Enum.Font.GothamBold, TextSize = 10, AutoButtonColor = false, BorderSizePixel = 0,
}, sidebar)
corner(button, 8)
return button
end
local mainTab = makeTab("Main", 1)
local teleportsTab = makeTab("Teleports", 2)
local upgradesTab = makeTab("Upgrades", 3)
local profileImage = new("ImageLabel", {
Name = "ProfileAvatar", AnchorPoint = Vector2.new(0.5, 0),
Size = UDim2.fromOffset(30, 30), Position = UDim2.new(0.5, 0, 0, 174),
BackgroundColor3 = C.card, BorderSizePixel = 0, Image = "",
ScaleType = Enum.ScaleType.Crop,
}, sidebar)
corner(profileImage, 15)
outline(profileImage, 0.35)
label(sidebar, {
Name = "ProfileUsername", Text = lp.Name, TextSize = 10,
TextXAlignment = Enum.TextXAlignment.Center, TextTruncate = Enum.TextTruncate.AtEnd,
Size = UDim2.new(1, -4, 0, 16), Position = UDim2.fromOffset(2, 206),
})
task.spawn(function()
local ok, image = pcall(function()
return Players:GetUserThumbnailAsync(lp.UserId, Enum.ThumbnailType.HeadShot, Enum.ThumbnailSize.Size48x48)
end)
if not ok then
warn("[MWG] could not load player profile image:", image)
return
end
if profileImage.Parent then
profileImage.Image = image
end
end)
local upgradeScreens = {
{ frame = "Upgrades", title = "Upgrades" },
{ frame = "Gauntlets", title = "Gauntlets" },
{ frame = "Crafting", title = "Crafting" },
{ frame = "Explosion", title = "Explosions" },
{ frame = "Jackhammer", title = "Jackhammer" },
{ frame = "MiningSpeed", title = "Mining Speed" },
{ frame = "Prestige", title = "Prestige" },
{ frame = "Range", title = "Range" },
{ frame = "Sacrifice", title = "Sacrifice" },
}
local function loadPinnedModule(url, label)
local source = game:HttpGet(url)
local chunk, compileError = loadstring(source, "@MWG/" .. label)
if not chunk then
error("[MWG] failed to compile " .. label .. ": " .. tostring(compileError))
end
return chunk()
end
local rootOk, libraryRoot = pcall(function()
return (gethui and gethui()) or game:GetService("CoreGui")
end)
if not rootOk or not libraryRoot then
error("[MWG] could not access the UI root for Speed Hub X")
end
local previousGuiInstances = {}
for _, child in ipairs(libraryRoot:GetChildren()) do
previousGuiInstances[child] = true
end
loadPinnedModule(
"https://raw.githubusercontent.com/AhmadV99/Speed-Hub-X/main/Settings.lua",
"Settings.lua"
)
local FuncsV3 = loadPinnedModule(
"https://raw.githubusercontent.com/AhmadV99/Main/main/Library/Example/FuncsV3",
"FuncsV3"
)
-- The selected library revision enables its own anti-AFK behavior on initialization.
local SpeedHubLibrary = loadPinnedModule(
"https://raw.githubusercontent.com/mamafoni281/Speed-hub-x-V5.0-Library/refs/heads/main/Speed-Hub-X-5.0-Library-Source",
"Speed-Hub-X-5.0-Library"
)
FuncsV3:SetTable(S)
uiLibrary = SpeedHubLibrary:CreateWindow({
["Tab Width"] = 160,
["Description"] = "",
["Title"] = "Speed Hub X | Miners World",
["SizeUi"] = UDim2.fromOffset(650, 520),
})
for _, child in ipairs(libraryRoot:GetChildren()) do
if not previousGuiInstances[child] and child:IsA("ScreenGui") then
libraryGuis[#libraryGuis + 1] = child
if child:FindFirstChild("DropShadowHolder") then
libraryWindowGui = child
end
end
end
if not libraryWindowGui then
warn("[MWG] could not find the Speed Hub window for the Emerald counter")
else
local emeraldCounterHolder = libraryWindowGui:FindFirstChild("DropShadowHolder")
local minimizeButton
for _, descendant in ipairs(libraryWindowGui:GetDescendants()) do
if descendant:IsA("TextButton") and descendant.Name == "Min" then
minimizeButton = descendant
break
end
end
local counterScreenGui = new("ScreenGui", {
Name = "MWGEmeraldCounter",
ResetOnSpawn = false,
DisplayOrder = libraryWindowGui.DisplayOrder + 1,
}, libraryRoot)
libraryGuis[#libraryGuis + 1] = counterScreenGui
local emeraldCounter = new("Frame", {
Name = "EmeraldCounter",
AnchorPoint = Vector2.new(1, 0),
Position = UDim2.new(1, -16, 0, 16),
Size = UDim2.fromOffset(190, 42),
BackgroundColor3 = C.card,
BackgroundTransparency = 0.08,
BorderSizePixel = 0,
Visible = false,
ZIndex = 100,
}, counterScreenGui)
corner(emeraldCounter, 9)
outline(emeraldCounter, 0.82)
local emeraldCountLabel = label(emeraldCounter, {
Name = "EmeraldCount",
Text = "Emeralds broken today: --",
Font = Enum.Font.GothamBold,
TextSize = 12,
TextColor3 = C.text,
TextXAlignment = Enum.TextXAlignment.Center,
Size = UDim2.new(1, -16, 1, 0),
Position = UDim2.fromOffset(8, 0),
ZIndex = 101,
})
local dailyEmeralds = data.Others:FindFirstChild("EmeraldsMinedDaily")
if dailyEmeralds and dailyEmeralds:IsA("ValueBase") then
local function updateEmeraldCount()
emeraldCountLabel.Text = "Emeralds broken today: " .. tostring(dailyEmeralds.Value)
end
updateEmeraldCount()
track(dailyEmeralds:GetPropertyChangedSignal("Value"):Connect(updateEmeraldCount))
else
warn("[MWG] Emerald counter unavailable: daily mined count was not found")
end
local function updateEmeraldCounterVisibility()
emeraldCounter.Visible = libraryWindowGui.Enabled
and emeraldCounterHolder ~= nil
and not emeraldCounterHolder.Visible
end
if emeraldCounterHolder then
track(emeraldCounterHolder:GetPropertyChangedSignal("Visible"):Connect(updateEmeraldCounterVisibility))
end
track(libraryWindowGui:GetPropertyChangedSignal("Enabled"):Connect(updateEmeraldCounterVisibility))
if minimizeButton then
track(minimizeButton.Activated:Connect(function()
task.defer(updateEmeraldCounterVisibility)
end))
end
updateEmeraldCounterVisibility()
end
local homeTab = uiLibrary:CreateTab({ Name = "Home", Icon = "rbxassetid://10723407389" })
local mainBuySection = homeTab:AddSection("Auto Buy (Pickaxe, Backpack)", false)
local function bindToggle(section, title, description, key)
FuncsV3:Toggle(section, title, description, S[key], function(value)
S[key] = value
save()
end)
end
bindToggle(mainBuySection, "Auto Buy", "Master switch for automation", "master")
bindToggle(mainBuySection, "Pickaxe", "Automatically buy pickaxe upgrades", "Pickaxe")
bindToggle(mainBuySection, "Backpack", "Automatically buy backpack upgrades", "Backpack")
local movementBuySection = homeTab:AddSection("Auto Buy (Luck, Jump, Speed)", false)
bindToggle(movementBuySection, "Luck", "Automatically buy Luck upgrades", "Luck")
bindToggle(movementBuySection, "Jump", "Automatically buy Jump upgrades", "Jump")
bindToggle(movementBuySection, "Speed", "Automatically buy Speed upgrades", "Speed")
local autoMineTargetSection = homeTab:AddSection("AutoMine Targeting", false)
local function updateIncludeEmeraldsInAutoMine(enabled)
local ok, err = pcall(setIncludeEmeraldsInAutoMine, enabled)
if not ok then
S.IncludeEmeraldsInAutoMine = false
restoreEmeraldTargeting()
save()
warn("[MWG] adding Emeralds to AutoMine failed:", err)
end
end
if S.IncludeEmeraldsInAutoMine then
updateIncludeEmeraldsInAutoMine(true)
end
FuncsV3:Toggle(
autoMineTargetSection,
"Include Emeralds in AutoMine",
"Adds Emeralds to native AutoMine candidates; other normal targets remain enabled",
S.IncludeEmeraldsInAutoMine,
updateIncludeEmeraldsInAutoMine
)
local playerMovementSection = homeTab:AddSection("Player Movement", false)
local function applyWalkSpeed(character)
local humanoid = character and character:FindFirstChildOfClass("Humanoid")
if humanoid then
humanoid.WalkSpeed = S.WalkSpeed
end
end
track(lp.CharacterAdded:Connect(function(character)
task.spawn(function()
local humanoid = character:WaitForChild("Humanoid", 10)
if humanoid then
humanoid.WalkSpeed = S.WalkSpeed
elseif character.Parent then
warn("[MWG] could not apply walk speed: character has no Humanoid")
end
end)
end))
playerMovementSection:AddSlider({
Title = "Player Walk Speed",
Content = "Normal speed is 16; adjust up to 90",
Increment = 1,
Min = 16,
Max = 90,
Default = S.WalkSpeed,
Callback = function(value)
S.WalkSpeed = math.clamp(value, 16, 90)
applyWalkSpeed(lp.Character)
save()
end,
})
local advancedBuySection = homeTab:AddSection("Auto Buy (Jackhammer, Explosions, Mining Speed)", false)
bindToggle(advancedBuySection, "Jackhammer", "Automatically buy Jackhammer upgrades", "Jackhammer")
bindToggle(advancedBuySection, "Explosions", "Automatically buy Explosive upgrades", "Explosions")
bindToggle(advancedBuySection, "Mining Speed", "Automatically buy Mining Speed upgrades", "MiningSpeed")
local craftSection = homeTab:AddSection("Auto Crafter", false)
local craftableAccessoryIds = {}
for accessoryId, accessory in pairs(GD.Accessories) do
for _, level in pairs(accessory.Levels or {}) do
if type(level.Recipe) == "table" and #level.Recipe > 0 then
craftableAccessoryIds[#craftableAccessoryIds + 1] = accessoryId
break
end
end
end
table.sort(craftableAccessoryIds, function(a, b)
local aNumber, bNumber = tonumber(a), tonumber(b)
if aNumber and bNumber then return aNumber < bNumber end
return tostring(a) < tostring(b)
end)
local observedCraftLevels = {}
local pendingCraftCompletions = {}
local function resetCraftCompletionTracking()
table.clear(pendingCraftCompletions)
for _, accessoryId in ipairs(craftableAccessoryIds) do
local level = data.Accessories.Levels[accessoryId]
observedCraftLevels[accessoryId] = level and level.Value or nil
end
end
resetCraftCompletionTracking()
for _, accessoryId in ipairs(craftableAccessoryIds) do
local level = data.Accessories.Levels[accessoryId]
if level then
track(level:GetPropertyChangedSignal("Value"):Connect(function()
local previousLevel = observedCraftLevels[accessoryId]
local currentLevel = level.Value
if S.AutoPinNextCraft and type(previousLevel) == "number"
and type(currentLevel) == "number" and currentLevel > previousLevel then
for completedLevel = previousLevel + 1, currentLevel do
pendingCraftCompletions[#pendingCraftCompletions + 1] = {
accessoryId = accessoryId,
level = completedLevel,
}
end
end
observedCraftLevels[accessoryId] = currentLevel
end))
end
end
local craftReadout = craftSection:AddParagraph({
Title = "Recipe Status",
Content = "Auto Craft checks every accessory recipe. Auto Pin selects another recipe after a craft completes.",
})
bindToggle(craftSection, "Auto Craft", "Automatically craft any accessory whose recipe materials are ready", "AutoCraft")
FuncsV3:Toggle(
craftSection,
"Pin Next Recipe",
"After a craft, pin another ready recipe or the next unpinned recipe; replaces the oldest pin if full",
S.AutoPinNextCraft,
function(value)
S.AutoPinNextCraft = value
resetCraftCompletionTracking()
save()
end
)
local function getCraftPlan(accessoryId)
local accessoryLevel = data.Accessories.Levels[accessoryId]
if not accessoryLevel then
return nil
end
local recipe = FH.GetRecipe(data, accessoryId)
if type(recipe) ~= "table" or #recipe == 0 then
return nil
end
local ready = true
for _, ingredient in ipairs(recipe) do
local blockId, required = ingredient[1], ingredient[2]
local currentBlock = data.Blocks[blockId]
local archivedBlock = data.ArchivedBlocks[blockId]
local owned = (currentBlock and currentBlock.Value or 0)
+ (archivedBlock and archivedBlock.Value or 0)
if owned < required then
ready = false
break
end
end
if not ready then return nil end
return {
accessoryId = accessoryId,
name = tostring(Translator.Get("Accessories." .. tostring(accessoryId) .. ".1.Name")),
level = accessoryLevel.Value,
}
end
local craftAttempts = {}
local readyCraftPlans = {}
local nextCraftPlanIndex = 1
local craftScanIndex = 1
local craftScanReadyPlans = {}
local cachedCraftStatus
local CRAFT_SCAN_BATCH_SIZE = 20
local function refreshCraftReadout()
if not S.AutoCraft and not S.AutoPinNextCraft and not (libraryWindowGui and libraryWindowGui.Enabled) then return end
local scanEnd = math.min(craftScanIndex + CRAFT_SCAN_BATCH_SIZE - 1, #craftableAccessoryIds)
for index = craftScanIndex, scanEnd do
local accessoryId = craftableAccessoryIds[index]
local plan = getCraftPlan(accessoryId)
if plan then
craftScanReadyPlans[#craftScanReadyPlans + 1] = plan
end
end
craftScanIndex = scanEnd + 1
if craftScanIndex <= #craftableAccessoryIds then return end
readyCraftPlans = craftScanReadyPlans
craftScanReadyPlans = {}
craftScanIndex = 1
local status
if #readyCraftPlans == 0 then
status = "No accessory recipes are ready. Auto Craft will craft any recipe once its materials are available."
else
local readyRecipes = {}
for _, plan in ipairs(readyCraftPlans) do
readyRecipes[#readyRecipes + 1] = string.format("%s (level %d)", plan.name, plan.level + 1)
end
status = (#readyRecipes == 1 and "Ready: " or "Ready recipes: ")
.. table.concat(readyRecipes, "\n")
.. (S.AutoCraft and "\nAuto Craft is enabled." or "\nEnable Auto Craft to craft these.")
end
if status ~= cachedCraftStatus then
cachedCraftStatus = status
craftReadout:Set({ Title = "Recipe Status", Content = status })
end
end
local function pinnedRecipes()
local pinned = {}
local order = {}
local raw = data.Others.PinnedRecipes.Value
local count = 0
for value in string.gmatch(raw, "[^,]+") do
local id = tonumber(value)
if id then
local key = tostring(id)
if not pinned[key] then
pinned[key] = true
order[#order + 1] = id
count += 1
end
end
end
return pinned, count, order
end
local function nextRecipeToPin(completedAccessoryId, readyPlans, pinned)
local ready = {}
for _, plan in ipairs(readyPlans) do
ready[tostring(plan.accessoryId)] = true
end
local completedIndex = 0
for index, accessoryId in ipairs(craftableAccessoryIds) do
if tostring(accessoryId) == tostring(completedAccessoryId) then
completedIndex = index
break
end
end
for pass = 1, 2 do
for offset = 1, #craftableAccessoryIds do
local index = ((completedIndex + offset - 1) % #craftableAccessoryIds) + 1
local accessoryId = craftableAccessoryIds[index]
local key = tostring(accessoryId)
local accessoryLevel = data.Accessories.Levels[accessoryId]
local recipeCanBePinned = accessoryLevel ~= nil
local hasNextRecipe = false
if pass == 2 then
local recipe = FH.GetRecipe(data, accessoryId)
hasNextRecipe = type(recipe) == "table" and #recipe > 0
end
if recipeCanBePinned and key ~= tostring(completedAccessoryId) and not pinned[key]
and (pass == 1 and ready[key] or pass == 2 and hasNextRecipe) then
return accessoryId
end
end
end
end
local function stepPinNextRecipe()
if not S.AutoPinNextCraft or #pendingCraftCompletions == 0 then return false end
local completion = pendingCraftCompletions[1]
local pinned, pinnedCount, pinnedOrder = pinnedRecipes()
if completion.targetId and pinned[tostring(completion.targetId)] then
table.remove(pendingCraftCompletions, 1)
return false
end
if not completion.targetId then
completion.targetId = nextRecipeToPin(completion.accessoryId, readyCraftPlans, pinned)
if not completion.targetId then
table.remove(pendingCraftCompletions, 1)
return false
end
end
if completion.awaitingPin then
if os.clock() - completion.requestedAt < 5 then return false end
completion.awaitingPin = false
end
if pinnedCount >= 5 then
local completedKey = tostring(completion.accessoryId)
local unpinId = pinned[completedKey] and completion.accessoryId or pinnedOrder[1]
if not unpinId then
return false
end
if completion.unpinRequested then
if pinned[tostring(completion.unpinId)]
and os.clock() - completion.unpinRequestedAt < 5 then
return false
end
completion.unpinRequested = false
end
if not canSendAutomaticAction() then return false end
local ok, err = pcall(Networking.Fire, "PinAccessory", unpinId, false)
if not ok then
warn("[MWG] could not unpin recipe to make room:", err)
return false
end
completion.unpinRequested = true
completion.unpinId = unpinId
completion.unpinRequestedAt = os.clock()
noteNetworkAction()
lastAction = "Unpinned recipe to make room for the next one"
return true
end
if not canSendAutomaticAction() then return false end
local ok, err = pcall(Networking.Fire, "PinAccessory", completion.targetId, true)
if not ok then
warn("[MWG] could not pin next recipe:", err)
return false
end
completion.awaitingPin = true
completion.requestedAt = os.clock()
noteNetworkAction()
lastAction = "Pinned next recipe: "
.. tostring(Translator.Get("Accessories." .. tostring(completion.targetId) .. ".1.Name"))
return true
end
local function stepCraft()
local planCount = #readyCraftPlans
if not S.AutoCraft or planCount == 0 or not canSendAutomaticAction() then return false end
if nextCraftPlanIndex > planCount then nextCraftPlanIndex = 1 end
local plan = readyCraftPlans[nextCraftPlanIndex]
nextCraftPlanIndex = nextCraftPlanIndex % planCount + 1
local attempt = craftAttempts[plan.accessoryId]
local alreadyAttempted = attempt
and attempt.level == plan.level
and os.clock() - attempt.time < 15
if alreadyAttempted then return false end
craftAttempts[plan.accessoryId] = { level = plan.level, time = os.clock() }
local ok, err = pcall(Networking.Fire, "CraftAccessory", plan.accessoryId)
if not ok then
warn("[MWG] native craft request failed for " .. tostring(plan.accessoryId) .. ":", err)
return false
end
noteNetworkAction()
lastAction = string.format("Requested native craft for %s", plan.name)
return true
end
local lobbyActions = homeTab:AddSection("Available Lobbies", false)
local teleportingToLobby = false
local lobbyInfo = GD.LobbyInfo
local function canTeleportToLobby(depth)
return depth <= data.NumberValues.HighestDepth.Value
and data.NumberValues.LowestDepth.Value <= depth + 10
end
for depth = lobbyInfo.Highest, lobbyInfo.Lowest, -lobbyInfo.Step do
local targetDepth = depth
FuncsV3:Button(lobbyActions, "Lobby at " .. tostring(targetDepth), "", function()
if teleportingToLobby then return end
if not canTeleportToLobby(targetDepth) then
return
end
teleportingToLobby = true
local ok, err = pcall(function()
Networking.Fire("Teleport", targetDepth)
end)
if not ok then
teleportingToLobby = false
warn("[MWG] lobby teleport failed:", err)
return
end
lastAction = string.format("Requested teleport to lobby %s", tostring(targetDepth))
task.delay(2, function() teleportingToLobby = false end)
end)
end
local upgradeActions = homeTab:AddSection("Available Upgrades", false)
for _, entry in ipairs(upgradeScreens) do
FuncsV3:Button(upgradeActions, entry.title, "", function()
if not gameFrames:FindFirstChild(entry.frame) then
warn("[MWG] upgrade screen is unavailable:", entry.frame)
return
end
local ok, err = pcall(GuiHandler, entry.frame, 1)
if not ok then
warn("[MWG] could not open upgrade screen " .. entry.frame .. ":", err)
return
end
end)
end
local visualSection = homeTab:AddSection("Visual Options", false)
FuncsV3:Toggle(
visualSection,
"Hide Explosive Effects",
"Hide the local explosion visual when explosives are activated",
S.HideExplosiveEffects,
setExplosiveEffectsHidden
)
local upgradesPage = new("Frame", {
Size = UDim2.new(1, -86, 0, PAGE_HEIGHT), Position = UDim2.fromOffset(86, 0),
BackgroundTransparency = 1, Visible = false,
}, body)
label(upgradesPage, {
Text = "Upgrade screens", Font = Enum.Font.GothamBold, TextSize = 15,
Size = UDim2.new(1, 0, 0, 20), Position = UDim2.fromOffset(0, 0),
})
local upgradesHint = label(upgradesPage, {
Text = "Open the game's native upgrade screen. Emerald upgrades are not included.",
TextSize = 11, TextColor3 = C.muted, TextWrapped = true,
Size = UDim2.new(1, 0, 0, 32), Position = UDim2.fromOffset(0, 24),
})
local upgradeList = new("ScrollingFrame", {
Size = UDim2.new(1, 0, 0, PAGE_HEIGHT - 68), Position = UDim2.fromOffset(0, 62),
BackgroundTransparency = 1, BorderSizePixel = 0, ScrollBarThickness = 5,
CanvasSize = UDim2.new(0, 0, 0, 0), AutomaticCanvasSize = Enum.AutomaticSize.Y,
}, upgradesPage)
new("UIListLayout", { Padding = UDim.new(0, 6), SortOrder = Enum.SortOrder.LayoutOrder }, upgradeList)
for order, entry in ipairs(upgradeScreens) do
local button = new("TextButton", {
Size = UDim2.new(1, -8, 0, 34), BackgroundColor3 = C.card, BorderSizePixel = 0,
Text = entry.title, TextColor3 = C.text, Font = Enum.Font.GothamMedium, TextSize = 12,
AutoButtonColor = false, LayoutOrder = order,
}, upgradeList)
corner(button, 7)
outline(button, 0.93)
track(button.MouseButton1Click:Connect(function()
if not gameFrames:FindFirstChild(entry.frame) then
upgradesHint.Text = entry.title .. " is not available in this game version."
warn("[MWG] upgrade screen is unavailable:", entry.frame)
return
end
local ok, err = pcall(GuiHandler, entry.frame, 1)
if not ok then
upgradesHint.Text = "Could not open " .. entry.title .. ". See console for details."
warn("[MWG] could not open upgrade screen " .. entry.frame .. ":", err)
return
end
upgradesHint.Text = "Opened " .. entry.title .. "."
end))
end
local pages = {
main = { page = mainPage, tab = mainTab },
teleports = { page = teleportPage, tab = teleportsTab },
upgrades = { page = upgradesPage, tab = upgradesTab },
}
local pageTransition
local pageBodyTransition
local pageTransitionId = 0
local function selectPage(page, animate)
local selectedPage = pages[page]
if not selectedPage then return end
pageTransitionId += 1
local transitionId = pageTransitionId
if pageTransition then
pageTransition:Cancel()
pageTransition = nil
end
if pageBodyTransition then
pageBodyTransition:Cancel()
pageBodyTransition = nil
end
local currentWindowHeight = win.AbsoluteSize.Y
local currentBodyHeight = body.AbsoluteSize.Y
win.AutomaticSize = Enum.AutomaticSize.None
win.Size = UDim2.new(0, 420, 0, currentWindowHeight)
body.AutomaticSize = Enum.AutomaticSize.None
body.Size = UDim2.new(1, 0, 0, currentBodyHeight)
for name, entry in pairs(pages) do
local selected = name == page
entry.page.Visible = selected
entry.tab.BackgroundColor3 = selected and C.accent or C.off
entry.tab.TextColor3 = C.text
end
body.AutomaticSize = Enum.AutomaticSize.Y
if not animate or currentWindowHeight <= 0 then
win.AutomaticSize = Enum.AutomaticSize.Y
body.Size = UDim2.new(1, 0, 0, 0)
body.AutomaticSize = Enum.AutomaticSize.Y
return
end
body.ClipsDescendants = true
task.spawn(function()
RunService.Heartbeat:Wait()
if transitionId ~= pageTransitionId then return end
local targetBodyHeight = body.AbsoluteSize.Y
body.AutomaticSize = Enum.AutomaticSize.None
body.Size = UDim2.new(1, 0, 0, currentBodyHeight)
local targetWindowHeight = 80 + targetBodyHeight
pageTransition = tween(win, 0.28, {
Size = UDim2.new(0, 420, 0, targetWindowHeight),
})
pageBodyTransition = tween(body, 0.28, {
Size = UDim2.new(1, 0, 0, targetBodyHeight),
})
pageTransition.Completed:Connect(function(playbackState)
if transitionId ~= pageTransitionId then return end
pageTransition = nil
pageBodyTransition = nil
if playbackState == Enum.PlaybackState.Completed then
body.Size = UDim2.new(1, 0, 0, 0)
body.AutomaticSize = Enum.AutomaticSize.Y
body.ClipsDescendants = false
win.Size = UDim2.fromOffset(420, 0)
win.AutomaticSize = Enum.AutomaticSize.Y
end
end)
pageBodyTransition.Completed:Connect(function(playbackState)
if playbackState == Enum.PlaybackState.Completed and transitionId == pageTransitionId then
body.Size = UDim2.new(1, 0, 0, targetBodyHeight)
end
end)
end)
end
track(mainTab.MouseButton1Click:Connect(function() selectPage("main", true) end))
track(teleportsTab.MouseButton1Click:Connect(function() selectPage("teleports", true) end))
track(upgradesTab.MouseButton1Click:Connect(function() selectPage("upgrades", true) end))
selectPage("main", false)
local lobbyTeleports = {}
for depth = lobbyInfo.Highest, lobbyInfo.Lowest, -lobbyInfo.Step do
local targetDepth = depth
local button = new("TextButton", {
Size = UDim2.new(1, -8, 0, 34), BackgroundColor3 = C.card, BorderSizePixel = 0,
Text = "", TextColor3 = C.text, Font = Enum.Font.GothamMedium, TextSize = 12,
AutoButtonColor = false, LayoutOrder = #lobbyTeleports + 1,
}, lobbyList)
corner(button, 7)
outline(button, 0.93)
lobbyTeleports[#lobbyTeleports + 1] = { depth = targetDepth, button = button }
track(button.MouseButton1Click:Connect(function()
if teleportingToLobby or not canTeleportToLobby(targetDepth) then return end
teleportingToLobby = true
local ok, err = pcall(function()
Networking.Fire("Teleport", targetDepth)
end)
if not ok then
teleportingToLobby = false
warn("[MWG] lobby teleport failed:", err)
return
end
lastAction = string.format("Requested teleport to lobby %s", tostring(targetDepth))
task.delay(2, function() teleportingToLobby = false end)
end))
end
local function refreshLobbyButtons()
for _, entry in ipairs(lobbyTeleports) do
local unlocked = canTeleportToLobby(entry.depth)
entry.button.Active = unlocked
entry.button.TextColor3 = unlocked and C.text or C.muted
entry.button.BackgroundColor3 = unlocked and C.card or C.track
entry.button.Text = unlocked
and string.format("Lobby at %s", tostring(entry.depth))
or string.format("Lobby at %s · Undiscovered", tostring(entry.depth))
end
end
refreshLobbyButtons()
local mainLayoutOrder = 0
local autoBuyExpanded = true
local autoBuyCards = {}
local autoBuySection
for order, item in ipairs(ITEMS) do
if item.cat == "Luck" then
mainLayoutOrder += 1
autoBuySection = new("TextButton", {
Text = "Auto Buy (Luck, Jump, Speed) −", Font = Enum.Font.GothamBold, TextSize = 13,
TextColor3 = C.accent, TextXAlignment = Enum.TextXAlignment.Left,
Size = UDim2.new(1, -4, 0, 28), BackgroundColor3 = C.card,
AutoButtonColor = false, BorderSizePixel = 0, LayoutOrder = mainLayoutOrder,
}, mainPage)
corner(autoBuySection, 7)
new("UIPadding", { PaddingLeft = UDim.new(0, 10) }, autoBuySection)
end
mainLayoutOrder += 1
local card = new("Frame", {
Size = UDim2.new(1, 0, 0, 86), BackgroundColor3 = C.card, BorderSizePixel = 0, LayoutOrder = mainLayoutOrder,
}, mainPage)
corner(card, 10)
outline(card, 0.93)
addSurfaceGradient(card)
local ui = { card = card }
ui.name = label(card, {
Text = item.title, Font = Enum.Font.GothamBold, TextSize = 15,
Size = UDim2.fromOffset(150, 20), Position = UDim2.fromOffset(14, 10),
})
ui.sub = label(card, {
TextSize = 12, TextColor3 = C.muted,
Size = UDim2.fromOffset(180, 16), Position = UDim2.fromOffset(14, 31),
})
makeSwitch(card, UDim2.fromOffset(218, 12), function() return S[item.cat] end, function(v) S[item.cat] = v end)
ui.amount = label(card, {
TextSize = 12, TextXAlignment = Enum.TextXAlignment.Right,
Size = UDim2.new(1, -28, 0, 14), Position = UDim2.fromOffset(14, 50),
})
local track_ = new("Frame", {
Size = UDim2.new(1, -28, 0, 6), Position = UDim2.fromOffset(14, 68),
BackgroundColor3 = C.track, BorderSizePixel = 0,
}, card)
corner(track_, 3)
ui.fill = new("Frame", { Size = UDim2.fromScale(0, 1), BackgroundColor3 = C.accent, BorderSizePixel = 0 }, track_)
corner(ui.fill, 3)
item.ui = ui
if item.cat == "Luck" or item.cat == "Jump" or item.cat == "Speed" then
autoBuyCards[#autoBuyCards + 1] = card
end
end
track(autoBuySection.MouseButton1Click:Connect(function()
autoBuyExpanded = not autoBuyExpanded
autoBuySection.Text = "Auto Buy (Luck, Jump, Speed) " .. (autoBuyExpanded and "−" or "+")
for _, card in ipairs(autoBuyCards) do
card.Visible = autoBuyExpanded
end
end))
mainLayoutOrder += 1
local footerOrder = mainLayoutOrder + 1
local footer = new("Frame", { Size = UDim2.new(1, 0, 0, 34), BackgroundTransparency = 1, LayoutOrder = footerOrder }, mainPage)
local lastLbl = label(footer, {
Text = "Waiting for cash…", TextSize = 12,
Size = UDim2.new(1, 0, 0, 16), Position = UDim2.fromOffset(2, 0),
})
label(footer, {
Text = "RightShift hides · drag the title to move", TextSize = 10, TextColor3 = C.muted,
Size = UDim2.new(1, 0, 0, 14), Position = UDim2.fromOffset(2, 19),
})
-- live refresh --------------------------------------------------------
local function refresh()
if gui.Enabled then
for _, item in ipairs(ITEMS) do
local ui = item.ui
local def, ul, wallet = parts(item.cat)
local enabled = S.master and S[item.cat]
ui.name.TextColor3 = enabled and C.text or C.muted
ui.card.BackgroundTransparency = S.master and 0 or 0.45
if not (def and ul and wallet) then
ui.sub.Text = "Unavailable"
else
local lvl, have = ul.Value, wallet.Value
if def.MaxLevel and lvl >= def.MaxLevel then
ui.sub.Text = string.format("Level %d · max", lvl)
ui.amount.Text = "Maxed out"
if ui.fillTarget ~= 1 or ui.fillColor ~= C.muted then
ui.fillTarget, ui.fillColor = 1, C.muted
tween(ui.fill, 0.25, { Size = UDim2.fromScale(1, 1), BackgroundColor3 = C.muted })
end
else
local ok, cost = pcall(FH.GetEquipableCostForMultiple, data, item.cat, 1)
ui.sub.Text = string.format("Level %d → %d", lvl, lvl + 1)
if ok and type(cost) == "number" then
ui.amount.Text = abbr(have) .. " / " .. abbr(cost)
local frac = cost > 0 and math.clamp(have / cost, 0, 1) or 1
local fillColor = (have >= cost) and C.ok or C.accent
if ui.fillTarget ~= frac or ui.fillColor ~= fillColor then
ui.fillTarget, ui.fillColor = frac, fillColor
tween(ui.fill, 0.25, { Size = UDim2.fromScale(frac, 1), BackgroundColor3 = fillColor })
end
end
end
end
end
if not S.master then
lastLbl.Text = "Paused"
lastLbl.TextColor3 = C.muted
elseif lastAction then
lastLbl.Text = lastAction
lastLbl.TextColor3 = C.text
else
lastLbl.Text = "Waiting for cash…"
lastLbl.TextColor3 = C.muted
end
refreshLobbyButtons()
end
end
-- drag --------------------------------------------------------------
local dragging, dragStart, startPos
dragArea.InputBegan:Connect(function(i)
if i.UserInputType == Enum.UserInputType.MouseButton1 or i.UserInputType == Enum.UserInputType.Touch then
dragging, dragStart, startPos = true, i.Position, win.Position
end
end)
track(UIS.InputChanged:Connect(function(i)
if dragging and (i.UserInputType == Enum.UserInputType.MouseMovement or i.UserInputType == Enum.UserInputType.Touch) then
local d = i.Position - dragStart
win.Position = UDim2.new(startPos.X.Scale, startPos.X.Offset + d.X, startPos.Y.Scale, startPos.Y.Offset + d.Y)
end
end))
track(UIS.InputEnded:Connect(function(i)
if i.UserInputType == Enum.UserInputType.MouseButton1 or i.UserInputType == Enum.UserInputType.Touch then dragging = false end
end))
-- collapse / hide / unload ---------------------------------------------
local collapsed = false
local expandedBodyHeight
local collapseTween
collapseBtn.MouseButton1Click:Connect(function()
if collapseTween then
collapseTween:Cancel()
collapseTween = nil
end
if not collapsed then
expandedBodyHeight = body.AbsoluteSize.Y
body.AutomaticSize = Enum.AutomaticSize.None
body.Size = UDim2.new(1, 0, 0, expandedBodyHeight)
body.ClipsDescendants = true
collapsed = true
collapseBtn.Text = "+"
collapseTween = tween(body, 0.28, { Size = UDim2.new(1, 0, 0, 0) })
collapseTween.Completed:Connect(function(playbackState)
if playbackState == Enum.PlaybackState.Completed and collapsed then
body.Visible = false
collapseTween = nil
end
end)
else
collapsed = false
local currentHeight = body.AbsoluteSize.Y
body.Visible = true
body.AutomaticSize = Enum.AutomaticSize.None
body.Size = UDim2.new(1, 0, 0, currentHeight)
body.ClipsDescendants = true
collapseBtn.Text = "–"
collapseTween = tween(body, 0.28, {
Size = UDim2.new(1, 0, 0, expandedBodyHeight or 0),
})
collapseTween.Completed:Connect(function(playbackState)
if playbackState == Enum.PlaybackState.Completed and not collapsed then
body.AutomaticSize = Enum.AutomaticSize.Y
body.Size = UDim2.new(1, 0, 0, 0)
body.ClipsDescendants = false
collapseTween = nil
end
end)
end
end)
track(UIS.InputBegan:Connect(function(i)
if i.KeyCode == Enum.KeyCode.RightShift and not UIS:GetFocusedTextBox() and libraryWindowGui then
libraryWindowGui.Enabled = not libraryWindowGui.Enabled
end
end))
local running = true
closeBtn.MouseButton1Click:Connect(function() if env.__MWG_UNLOAD then env.__MWG_UNLOAD() end end)
env.__MWG_UNLOAD = function()
running = false
restoreEmeraldTargeting()
pageTransitionId += 1
if pageTransition then pageTransition:Cancel() pageTransition = nil end
if pageBodyTransition then pageBodyTransition:Cancel() pageBodyTransition = nil end
if collapseTween then collapseTween:Cancel() collapseTween = nil end
for _, c in ipairs(conns) do pcall(function() c:Disconnect() end) end
pcall(function() gui:Destroy() end)
for _, libraryGui in ipairs(libraryGuis) do
if libraryGui.Parent then
libraryGui:Destroy()
end
end
libraryGuis = {}
env.__MWG_UNLOAD = nil
env.__MWG_DECIDE = nil
print("[MWG] Auto Buy unloaded")
end
----------------------------------------------------------------------
-- Loops
----------------------------------------------------------------------
task.spawn(function()
local tick = 0
while running and not (SpeedHubLibrary and SpeedHubLibrary.Unloaded) do
task.wait(0.4)
if S.master then
local pinOk, pinSent = pcall(stepPinNextRecipe)
if not pinOk then
warn("[MWG] auto-pin error:", pinSent)
pinSent = false
end
if not pinSent then
tick += 1
local ok, err = pcall(step, tick)
if not ok then warn("[MWG] step error:", err) end
local craftOk, craftErr = pcall(stepCraft)
if not craftOk then warn("[MWG] auto-craft error:", craftErr) end
end
end
end
end)
task.spawn(function()
while running and not (SpeedHubLibrary and SpeedHubLibrary.Unloaded) do
local ok, err = pcall(refreshCraftReadout)
if not ok then warn("[MWG] recipe scan error:", err) end
task.wait(0.25)
end
end)
task.spawn(function()
while running and not (SpeedHubLibrary and SpeedHubLibrary.Unloaded) do
local ok, err = pcall(refresh)
if not ok then warn("[MWG] refresh error:", err) end
task.wait(2)
end
end)
task.spawn(function()
while running and SpeedHubLibrary and not SpeedHubLibrary.Unloaded do
task.wait(0.25)
end
if running and SpeedHubLibrary and SpeedHubLibrary.Unloaded and env.__MWG_UNLOAD then
env.__MWG_UNLOAD()
end
end)
print("[MWG] Auto Buy loaded with Speed Hub X UI")
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