kjjjkjpro V2
Key RequiredUniversal

kjjjkjpro V2

Universal Scriptkjjjkjprokjjjkjpro 1.3K views 2.7K executesUpdated Oct 5, 2026
4.2/ 5(6 votes)
5183% Positive
Lua Script•1069 lines (36774 chars)
--[[
    TUBERS HUB - 99 NIGHTS IN THE FOREST EDITION
    Password: 1234      Hotkeys: RightShift = hide/show   F = fly
    Tabs: Bring · Campfire · Tools · Player · Settings
    Only item bringing + player features. No chat, no spam, no remotes.
]]

local Players = game:GetService("Players")
local UserInputService = game:GetService("UserInputService")
local CoreGui = game:GetService("CoreGui")
local lp = Players.LocalPlayer

-- =========================================================
-- CONFIG
-- =========================================================
local function toSet(list)
    local s = {}
    for _, w in ipairs(list) do s[w] = true end
    return s
end

local CATEGORY_ORDER = { "diamonds", "valuables", "fuel", "food", "healing", "weapons", "armor", "tools", "materials", "magic", "chests" }

local CATEGORIES = {
    diamonds = toSet({
        "diamond", "gem", "gemstone", "crystal", "jewel", "shard", "geode", "quartz", "amethyst",
        "sapphire", "topaz", "opal", "obsidian", "prism", "stardust",
    }),
    valuables = toSet({
        "coin", "cash", "money", "gold", "silver", "bullion", "treasure", "relic", "artifact",
        "idol", "statue", "trophy", "necklace", "amulet", "pearl", 
        "orb", "essence", "scroll", "tome", "keycard", 
        "blueprint",
    }),
    fuel = toSet({
        "log", "wood", "plank", "stick", "branch", "coal", "charcoal", "fuel", "petrol",
        "gas", "gasoline", "diesel", "kerosene", "oil", "canister", "jerrycan", "barrel",
        "drum", "tank", "cylinder",
        "torch", "match", "lighter", "tinder", "kindling", "firewood",
    }),
    food = toSet({
        "meat", "steak", "rib", "jerky", "bacon", "ham", "pork", "beef", "venison", "morsel",
        "fish", "mackerel", "salmon", "eel", "tuna", "cod", "trout", "carrot", "corn",
        "pumpkin", "potato", "tomato", "onion", "mushroom", "cabbage", "berry", "apple",
        "banana", "orange", "coconut", "melon", "mango", "peach", "pear", "bread", "cake",
        "pie", "cookie", "soup", "stew", "chili", "egg", "cheese", "honey", "ration", "meal",
        "snack",
    }),
    healing = toSet({
        "bandage", "medkit", "medicine", "pill", "syrup", "antibiotic", "potion",
        "herb", "aloe", "tonic", "antidote", "firstaid",
    }),
    weapons = toSet({
        "axe", "hatchet", "pickaxe", "sword", "katana", "blade", "dagger", "knife", "machete",
        "spear", "hammer", "club", "mace", "staff", "bow", "crossbow", "arrow", "bolt", "gun",
        "revolver", "pistol", "rifle", "shotgun", "sniper", "grenade", "bomb", "dynamite",
        "tnt", "ammo", "bullet", "shell", "cartridge", "magazine",
    }),
    tools = toSet({
        "shovel", "spade", "hoe", "saw", "chainsaw", "wrench", "pliers", "screwdriver",
        "crowbar", "trap", "lantern", "lamp", "candle", "compass",
        "flashlight", "bucket",
    }),
    materials = toSet({
        "boulder", "ore", "iron", "copper", "tin", "gold", "silver", "ingot",
        "nugget", "crystal", "gem", "diamond", "ruby", "emerald", "leather", "cloth",
        "wool", "rope", "scrap", 
        "steel", "bottle", "jar", "glue",
    }),
    armor = toSet({
        "armor", "armour", "helmet", "helm", "shield", "chestplate", "breastplate", "gauntlet",
        "greaves", "pauldron", "vest", "cloak", "cape", "boots", "gloves", "mask", "hat",
    }),
    magic = toSet({
        "talisman", "amulet", "charm", "rune", "runestone", "sigil", "scroll", "tome", "grimoire",
        "relic", "artifact", "artefact", "orb", "potion", "elixir", "wand",
    }),
    chests = toSet({
        "chest", "crate", "sack", "satchel", "backpack", "coffer", "trunk",
        "strongbox", "safe", "loot", "lootbox", "cache", "treasure",
    }),
}

local EXCLUDED = toSet({
    "part", "model", "meshpart", "union", "unionoperation", "wedge", "wedgepart", "cornerwedgepart",
    "trusspart", "seat", "vehicleseat", "decal", "texture", "folder", "effect", "hitbox", "trigger",
    "zone", "region", "collider", "invisible",
    "terrain", "baseplate", "spawn", "spawnlocation", "camera", "sky", "handle",
    "rootjoint", "torso", "head", "limb", "humanoidrootpart",
})

local CAP_OPTIONS = { 25, 50, 150, 300, 600, 1500 }
local MAX_ITEM_SIZE = 60 -- anything bigger is treated as map geometry
local SKIP_NEAR = 12     -- items already this close to you are skipped

local S = {
    capIndex = 2,
    includeAnchored = false,
    autoCategory = "all",
    autoDelay = 3,
    perf = false,
    campOffset = 3,
}

-- =========================================================
-- NAME MATCHING (whole words only)
-- =========================================================
local tokenCache, tokenCacheCount = {}, 0
local function tokenize(name)
    local cached = tokenCache[name]
    if cached then return cached end
    -- "StrongAxe" -> "strong axe", "raw_meat" -> "raw meat"
    local s = name:gsub("(%l)(%u)", "%1 %2"):gsub("[^%w]+", " "):lower()
    local tokens = {}
    for w in s:gmatch("%S+") do tokens[#tokens + 1] = w end
    if tokenCacheCount > 20000 then tokenCache, tokenCacheCount = {}, 0 end
    tokenCache[name] = tokens
    tokenCacheCount += 1
    return tokens
end

local function matchesSet(name, set)
    for _, t in ipairs(tokenize(name)) do
        if set[t] then return true end
        if t:sub(-1) == "s" and set[t:sub(1, -2)] then return true end -- plurals
    end
    return false
end

local function matchesCategory(name, cat)
    if cat == "all" then
        for _, c in ipairs(CATEGORY_ORDER) do
            if matchesSet(name, CATEGORIES[c]) then return true end
        end
        return false
    end
    return matchesSet(name, CATEGORIES[cat])
end

-- =========================================================
-- ITEM LOGIC
-- =========================================================
local moved = setmetatable({}, { __mode = "k" })
local npcCache = setmetatable({}, { __mode = "k" })
lp.CharacterAdded:Connect(function()
    moved = setmetatable({}, { __mode = "k" })
end)

local function getHRP()
    local c = lp.Character
    return c and c:FindFirstChild("HumanoidRootPart")
end

-- true if this belongs to a player or an NPC/animal (anything with a Humanoid)
local function isLiving(inst)
    local cached = npcCache[inst]
    if cached ~= nil then return cached end
    local result = false
    -- player characters (yours and others')
    if Players:GetPlayerFromCharacter(inst) or inst:FindFirstAncestorWhichIsA("Model") and Players:GetPlayerFromCharacter(inst:FindFirstAncestorWhichIsA("Model")) then
        result = true
    end
    local char = lp.Character
    if char and (inst == char or inst:IsDescendantOf(char)) then result = true end
    -- NPCs, animals, pets, followers: anything rigged or animated
    local m = inst:IsA("Model") and inst or inst:FindFirstAncestorOfClass("Model")
    local depth = 0
    while not result and m and m ~= workspace and depth < 6 do
        if m:FindFirstChildOfClass("Humanoid")
            or m:FindFirstChildOfClass("AnimationController")
            or m:FindFirstChildWhichIsA("Motor6D", true)
            or m:FindFirstChildWhichIsA("Animator", true) then
            result = true
            break
        end
        m = m:FindFirstAncestorOfClass("Model")
        depth += 1
    end
    -- things attached to or chasing a character (pets, companions)
    if not result then
        local parts = inst:IsA("BasePart") and { inst } or inst:GetDescendants()
        for _, p in ipairs(parts) do
            if p:IsA("BasePart") then
                for _, j in ipairs(p:GetJoints()) do
                    local other = (j.Part0 == p) and j.Part1 or j.Part0
                    if other and other:FindFirstAncestorOfClass("Model")
                        and Players:GetPlayerFromCharacter(other:FindFirstAncestorOfClass("Model")) then
                        result = true
                        break
                    end
                end
                if p:FindFirstChildWhichIsA("AlignPosition") or p:FindFirstChildWhichIsA("BodyPosition")
                    or p:FindFirstChildWhichIsA("BodyGyro") or p:FindFirstChildWhichIsA("AlignOrientation") then
                    result = true
                end
            end
            if result then break end
        end
    end
    npcCache[inst] = result
    return result
end

local function isMovable(d)
    if d:IsA("BasePart") then
        return (S.includeAnchored or not d.Anchored) and d.Size.Magnitude <= MAX_ITEM_SIZE
    end
    if d:GetExtentsSize().Magnitude > MAX_ITEM_SIZE then return false end
    if S.includeAnchored then return true end
    for _, p in ipairs(d:GetDescendants()) do
        if p:IsA("BasePart") and not p.Anchored then return true end
    end
    return false
end

-- if a parent Model already matches, we move that Model instead of its parts
local function ancestorModelMatches(d, matcher)
    local m = d.Parent
    while m and m ~= workspace do
        if m:IsA("Model") and matcher(m.Name) then return true end
        m = m.Parent
    end
    return false
end

local function itemPosition(d)
    return d:IsA("Model") and d:GetPivot().Position or d.Position
end

-- extra text a game may use to label an item (ProximityPrompt text, Attributes)
local labelCache = setmetatable({}, { __mode = "k" })
local function labelText(d)
    local cached = labelCache[d]
    if cached then return cached end
    local parts = {}
    for _, c in ipairs(d:GetChildren()) do
        if c:IsA("ProximityPrompt") or c:IsA("ClickDetector") then
            if c:IsA("ProximityPrompt") then
                parts[#parts + 1] = c.ObjectText
                parts[#parts + 1] = c.ActionText
            end
        elseif c:IsA("StringValue") then
            parts[#parts + 1] = c.Value
        end
    end
    for _, key in ipairs({ "ItemName", "Item", "Name", "DisplayName", "Type" }) do
        local v = d:GetAttribute(key)
        if type(v) == "string" then parts[#parts + 1] = v end
    end
    local text = table.concat(parts, " ")
    labelCache[d] = text
    return text
end

local function isVisible(d)
    if d:IsA("BasePart") then return d.Transparency < 0.9 end
    for _, p in ipairs(d:GetDescendants()) do
        if p:IsA("BasePart") and p.Transparency < 0.9 then return true end
    end
    return false
end

local function isCandidate(d, matcher, hrpPos)
    if moved[d] then return false end
    if EXCLUDED[d.Name:lower()] then return false end
    if not (matcher(d.Name) or matcher(labelText(d))) then return false end
    if isLiving(d) then return false end
    if ancestorModelMatches(d, matcher) then return false end
    if not isMovable(d) then return false end
    if not isVisible(d) then return false end
    if (itemPosition(d) - hrpPos).Magnitude < SKIP_NEAR then return false end
    return true
end

local function moveItem(item, cf)
    return pcall(function()
        if item:IsA("Model") then
            item:PivotTo(cf)
            for _, p in ipairs(item:GetDescendants()) do
                if p:IsA("BasePart") then
                    p.AssemblyLinearVelocity = Vector3.zero
                    p.AssemblyAngularVelocity = Vector3.zero
                end
            end
        else
            item.CFrame = cf
            item.AssemblyLinearVelocity = Vector3.zero
            item.AssemblyAngularVelocity = Vector3.zero
        end
    end)
end

-- Let the executor give us physics ownership of nearby parts (if supported)
pcall(function()
    if sethiddenproperty then
        sethiddenproperty(lp, "SimulationRadius", math.huge)
        sethiddenproperty(lp, "MaxSimulationRadius", math.huge)
    end
end)

-- ---------------------------------------------------------
-- INDEX: scan the workspace once, then keep it updated with events,
-- so we never re-walk every descendant on each bring / auto tick.
-- ---------------------------------------------------------
local idxList, idxSet = {}, setmetatable({}, { __mode = "k" })
local idxReady, idxBuilding = false, false

local function indexAdd(d)
    if (d:IsA("Model") or d:IsA("BasePart")) and not idxSet[d] then
        idxSet[d] = true
        idxList[#idxList + 1] = d
    end
end

workspace.DescendantAdded:Connect(indexAdd)

local function ensureIndex()
    if idxReady then return end
    if idxBuilding then
        while not idxReady do task.wait(0.1) end
        return
    end
    idxBuilding = true
    local n = 0
    for _, d in ipairs(workspace:GetDescendants()) do
        indexAdd(d)
        n += 1
        if n % 2000 == 0 then task.wait() end
    end
    idxReady, idxBuilding = true, false
end

-- iterate the index in small slices, dropping destroyed instances
local function forEachIndexed(fn)
    ensureIndex()
    local write = 0
    local read = 0
    local total = #idxList
    while read < total do
        read += 1
        local d = idxList[read]
        if d.Parent then
            write += 1
            idxList[write] = d
            if fn(d) == false then
                -- stop early: keep the rest of the list intact
                for i = read + 1, total do
                    write += 1
                    idxList[write] = idxList[i]
                end
                read = total
            end
        end
        if read % 250 == 0 then task.wait() end
    end
    -- anything added while we yielded sits after `total`
    for i = total + 1, #idxList do
        write += 1
        idxList[write] = idxList[i]
    end
    for i = #idxList, write + 1, -1 do idxList[i] = nil end
end

local toCampfire = false
local function findCampfire()
    for _, d in ipairs(workspace:GetDescendants()) do
        local n = d.Name:lower()
        if n:find("campfire", 1, true) or n:find("bonfire", 1, true) or n:find("firepit", 1, true) or n:find("fire_pit", 1, true) then
            if d:IsA("BasePart") then return d end
            if d:IsA("Model") then
                local p = d.PrimaryPart or d:FindFirstChildWhichIsA("BasePart", true)
                if p then return p end
            end
        end
    end
end

-- where items land: next to you, or on top of the campfire
local function getTargetCF(hrp)
    if toCampfire then
        local cf = findCampfire()
        if cf then return cf.CFrame * CFrame.new(0, S.campOffset, 0), true end
    end
    return hrp.CFrame, false
end

local busy = false
local function bring(matcher, cap)
    local hrp = getHRP()
    if not hrp then return 0 end
    local brought = 0

    forEachIndexed(function(d)
        if brought >= cap then return false end
        local ok, good = pcall(isCandidate, d, matcher, hrp.Position)
        if ok and good then
            local base = getTargetCF(hrp)
            local offset = CFrame.new(math.random(-6, 6), 2, math.random(-6, 6))
            if moveItem(d, base * offset) then
                moved[d] = true
                brought += 1
            end
        end
    end)
    return brought
end

-- Brings every chest and lines them up in a grid in front of you
local function bringChestsInFront()
    local hrp = getHRP()
    if not hrp then return 0 end
    local matcher = function(name) return matchesCategory(name, "chests") end
    local hrpPos = hrp.Position

    local found = {}
    forEachIndexed(function(d)
        local ok, good = pcall(isCandidate, d, matcher, hrpPos)
        if ok and good then found[#found + 1] = d end
    end)

    local COLUMNS, SPACING, DISTANCE = 6, 6, 12
    local origin = hrp.CFrame
    local brought = 0
    for i, chest in ipairs(found) do
        local col = (i - 1) % COLUMNS
        local row = math.floor((i - 1) / COLUMNS)
        local x = (col - (COLUMNS - 1) / 2) * SPACING
        local z = -(DISTANCE + row * SPACING)
        -- ground-level spot in front of you, chest turned to face you
        local pos = (origin * CFrame.new(x, -2, z)).Position
        local cf = CFrame.lookAt(pos, Vector3.new(origin.Position.X, pos.Y, origin.Position.Z))
        if moveItem(chest, cf) then
            moved[chest] = true
            brought += 1
        end
        if i % 20 == 0 then task.wait() end
    end
    return brought
end


local function currentCap()
    local c = CAP_OPTIONS[S.capIndex]
    return S.perf and math.min(c, 50) or c
end

-- bring the N closest items of any category
local function bringNearest(count)
    local hrp = getHRP()
    if not hrp then return 0 end
    local matcher = function(name) return matchesCategory(name, "all") end
    local found = {}
    forEachIndexed(function(d)
        local ok, good = pcall(isCandidate, d, matcher, hrp.Position)
        if ok and good then
            found[#found + 1] = { inst = d, dist = (itemPosition(d) - hrp.Position).Magnitude }
        end
    end)
    table.sort(found, function(a, b) return a.dist < b.dist end)
    local brought = 0
    for i = 1, math.min(count, #found) do
        local base = getTargetCF(hrp)
        local offset = CFrame.new(math.random(-6, 6), 2, math.random(-6, 6))
        if moveItem(found[i].inst, base * offset) then
            moved[found[i].inst] = true
            brought += 1
        end
    end
    return brought
end

-- =========================================================
-- GUI
-- =========================================================
local THEME = {
    BG = Color3.fromRGB(15, 15, 20),
    PANEL = Color3.fromRGB(22, 22, 30),
    BTN = Color3.fromRGB(32, 32, 42),
    ACCENT = Color3.fromRGB(220, 40, 40),
    TEXT = Color3.fromRGB(240, 240, 245),
    DIM = Color3.fromRGB(150, 150, 160),
    OK = Color3.fromRGB(60, 200, 120),
}

local gui = Instance.new("ScreenGui")
gui.Name = "TubersHub"
gui.ResetOnSpawn = false
gui.DisplayOrder = 999
local parented = pcall(function() gui.Parent = (gethui and gethui()) or CoreGui end)
if not parented or not gui.Parent then gui.Parent = lp:WaitForChild("PlayerGui") end

local function round(inst, r)
    local c = Instance.new("UICorner")
    c.CornerRadius = UDim.new(0, r or 6)
    c.Parent = inst
end

local root = Instance.new("Frame")
root.Size = UDim2.new(0, 320, 0, 500)
root.Position = UDim2.new(0.5, -160, 0.5, -250)
root.BackgroundColor3 = THEME.BG
root.BorderSizePixel = 0
root.Active = true
root.Draggable = true
root.Visible = false
root.Parent = gui
round(root, 10)

local title = Instance.new("TextLabel")
title.Size = UDim2.new(1, -44, 0, 34)
title.Position = UDim2.new(0, 12, 0, 0)
title.BackgroundTransparency = 1
title.Text = "Tubers Hub · 99 Nights"
title.TextColor3 = THEME.TEXT
title.Font = Enum.Font.GothamBold
title.TextSize = 14
title.TextXAlignment = Enum.TextXAlignment.Left
title.Parent = root

local close = Instance.new("TextButton")
close.Size = UDim2.new(0, 26, 0, 26)
close.Position = UDim2.new(1, -34, 0, 4)
close.BackgroundColor3 = THEME.ACCENT
close.Text = "×"
close.TextColor3 = Color3.new(1, 1, 1)
close.Font = Enum.Font.GothamBold
close.TextSize = 16
close.Parent = root
round(close, 6)

local status = Instance.new("TextLabel")
status.Size = UDim2.new(1, -24, 0, 18)
status.Position = UDim2.new(0, 12, 1, -22)
status.BackgroundTransparency = 1
status.Text = "Ready."
status.TextColor3 = THEME.DIM
status.Font = Enum.Font.Gotham
status.TextSize = 11
status.TextXAlignment = Enum.TextXAlignment.Left
status.Parent = root
local function setStatus(t) status.Text = t end

-- tabs
local tabBar = Instance.new("Frame")
tabBar.Size = UDim2.new(1, -20, 0, 26)
tabBar.Position = UDim2.new(0, 10, 0, 36)
tabBar.BackgroundTransparency = 1
tabBar.Parent = root
local tabLayout = Instance.new("UIListLayout")
tabLayout.FillDirection = Enum.FillDirection.Horizontal
tabLayout.Padding = UDim.new(0, 4)
tabLayout.Parent = tabBar

local pages, tabButtons = {}, {}
local cur -- the page new buttons are added to

local function showPage(name)
    for n, p in pairs(pages) do p.Visible = (n == name) end
    for n, b in pairs(tabButtons) do
        b.BackgroundColor3 = (n == name) and THEME.ACCENT or THEME.BTN
    end
end

local TAB_NAMES = { "Bring", "Campfire", "Tools", "Player", "Settings" }
for _, name in ipairs(TAB_NAMES) do
    local b = Instance.new("TextButton")
    b.Size = UDim2.new(0.2, -4, 1, 0)
    b.BackgroundColor3 = THEME.BTN
    b.BorderSizePixel = 0
    b.Text = name
    b.TextColor3 = THEME.TEXT
    b.Font = Enum.Font.GothamMedium
    b.TextSize = 10
    b.Parent = tabBar
    round(b, 5)
    tabButtons[name] = b
    b.MouseButton1Click:Connect(function() showPage(name) end)

    local list = Instance.new("ScrollingFrame")
    list.Size = UDim2.new(1, -20, 1, -96)
    list.Position = UDim2.new(0, 10, 0, 68)
    list.BackgroundColor3 = THEME.PANEL
    list.BorderSizePixel = 0
    list.ScrollBarThickness = 4
    list.CanvasSize = UDim2.new(0, 0, 0, 0)
    list.AutomaticCanvasSize = Enum.AutomaticSize.Y
    list.Visible = false
    list.Parent = root
    round(list, 8)
    local layout = Instance.new("UIListLayout")
    layout.Padding = UDim.new(0, 4)
    layout.SortOrder = Enum.SortOrder.LayoutOrder
    layout.Parent = list
    local pad = Instance.new("UIPadding")
    pad.PaddingTop, pad.PaddingBottom = UDim.new(0, 6), UDim.new(0, 6)
    pad.PaddingLeft, pad.PaddingRight = UDim.new(0, 6), UDim.new(0, 6)
    pad.Parent = list
    pages[name] = list
end

local function mkHeader(text)
    local l = Instance.new("TextLabel")
    l.Size = UDim2.new(1, 0, 0, 20)
    l.BackgroundTransparency = 1
    l.Text = "──  " .. text .. "  ──"
    l.TextColor3 = THEME.ACCENT
    l.Font = Enum.Font.GothamBold
    l.TextSize = 11
    l.Parent = cur
end

local function mkButton(text, onClick)
    local b = Instance.new("TextButton")
    b.Size = UDim2.new(1, 0, 0, 30)
    b.BackgroundColor3 = THEME.BTN
    b.BorderSizePixel = 0
    b.Text = text
    b.TextColor3 = THEME.TEXT
    b.Font = Enum.Font.GothamMedium
    b.TextSize = 12
    b.Parent = cur
    round(b, 6)
    b.MouseButton1Click:Connect(function() onClick(b) end)
    return b
end

local function runBring(label, matcher)
    if busy then setStatus("Busy, wait a moment...") return end
    busy = true
    task.spawn(function()
        local ok, result = pcall(bring, matcher, currentCap())
        busy = false
        setStatus(ok and ("%s: brought %d"):format(label, result) or ("Error: " .. tostring(result)))
    end)
end

local function runTask(label, fn)
    if busy then setStatus("Busy, wait a moment...") return end
    busy = true
    task.spawn(function()
        local ok, result = pcall(fn)
        busy = false
        setStatus(ok and ("%s: %s"):format(label, tostring(result)) or ("Error: " .. tostring(result)))
    end)
end

-- ---------------- BRING ----------------
cur = pages.Bring
mkHeader("BRING BY CATEGORY")
for _, cat in ipairs(CATEGORY_ORDER) do
    mkButton("Bring " .. cat, function()
        runBring(cat, function(name) return matchesCategory(name, cat) end)
    end)
end
mkButton("Bring ALL categories", function()
    runBring("all", function(name) return matchesCategory(name, "all") end)
end)
mkButton("Bring ALL chests in front of me", function()
    runTask("Chests lined up", bringChestsInFront)
end)
mkHeader("KEYWORDS")
local box = Instance.new("TextBox")
box.Size = UDim2.new(1, 0, 0, 30)
box.BackgroundColor3 = THEME.BTN
box.BorderSizePixel = 0
box.TextColor3 = THEME.TEXT
box.PlaceholderText = "keywords: coal, oil, barrel"
box.PlaceholderColor3 = THEME.DIM
box.Text = ""
box.Font = Enum.Font.Code
box.TextSize = 12
box.ClearTextOnFocus = false
box.Parent = cur
round(box, 6)
box.FocusLost:Connect(function(enter)
    if not enter then return end
    local keywords = {}
    for raw in box.Text:lower():gmatch("[^,]+") do
        local kw = raw:match("^%s*(.-)%s*$")
        if #kw > 0 then keywords[#keywords + 1] = kw end
    end
    if #keywords == 0 then return end
    runBring(table.concat(keywords, "/"), function(name)
        local n = name:lower()
        for _, kw in ipairs(keywords) do
            if n:find(kw, 1, true) then return true end
        end
        return false
    end)
end)

-- ---------------- CAMPFIRE ----------------
cur = pages.Campfire
mkHeader("DESTINATION")
mkButton("Bring to: ME", function(b)
    toCampfire = not toCampfire
    b.Text = "Bring to: " .. (toCampfire and "CAMPFIRE" or "ME")
    b.BackgroundColor3 = toCampfire and THEME.OK or THEME.BTN
end)
mkButton("Drop height: " .. S.campOffset .. " studs", function(b)
    S.campOffset = (S.campOffset == 1 and 3) or (S.campOffset == 3 and 5) or 1
    b.Text = "Drop height: " .. S.campOffset .. " studs"
end)
mkButton("Find campfire (report position)", function()
    local cf = findCampfire()
    if cf then
        local p = cf.Position
        setStatus(("Campfire at %.0f, %.0f, %.0f"):format(p.X, p.Y, p.Z))
    else
        setStatus("No campfire found")
    end
end)
mkHeader("QUICK FEED")
for _, cat in ipairs({ "fuel", "food" }) do
    mkButton("Bring " .. cat .. " to campfire", function()
        if busy then setStatus("Busy, wait a moment...") return end
        if not findCampfire() then setStatus("No campfire found") return end
        local old = toCampfire
        toCampfire = true
        busy = true
        task.spawn(function()
            local ok, n = pcall(bring, function(name) return matchesCategory(name, cat) end, currentCap())
            busy = false
            toCampfire = old
            setStatus(ok and ("Sent %d %s to campfire"):format(n, cat) or ("Error: " .. tostring(n)))
        end)
    end)
end
mkButton("Test: bring 1 fuel to campfire", function()
    if busy then setStatus("Busy, wait a moment...") return end
    if not findCampfire() then setStatus("No campfire found") return end
    local old = toCampfire
    toCampfire = true
    busy = true
    task.spawn(function()
        local ok, n = pcall(bring, function(name) return matchesCategory(name, "fuel") end, 1)
        busy = false
        toCampfire = old
        setStatus(ok and ("Sent %d fuel to campfire"):format(n) or ("Error: " .. tostring(n)))
    end)
end)

-- ---------------- TOOLS ----------------
cur = pages.Tools
mkHeader("QUICK BRING")
mkButton("Bring Strong Axe", function()
    runBring("strong axe", function(name)
        local n = name:lower()
        return n:find("strong axe", 1, true) or n:find("strongaxe", 1, true) or n:find("strong_axe", 1, true)
    end)
end)
for _, n in ipairs({ 10, 25, 50 }) do
    mkButton("Bring nearest " .. n .. " items", function()
        runTask("Nearest " .. n, function() return bringNearest(n) end)
    end)
end
mkHeader("INFO")
mkButton("Scan and print item names (console)", function()
    task.spawn(function()
        local counts, n = {}, 0
        for _, d in ipairs(workspace:GetDescendants()) do
            n += 1
            if n % 400 == 0 then task.wait() end
            if (d:IsA("Model") or d:IsA("BasePart")) and not isLiving(d) then
                counts[d.Name] = (counts[d.Name] or 0) + 1
            end
        end
        local sorted = {}
        for name, c in pairs(counts) do sorted[#sorted + 1] = { name = name, count = c } end
        table.sort(sorted, function(a, b) return a.count > b.count end)
        print("=== TOP 60 NAMES ===")
        for i = 1, math.min(60, #sorted) do
            print(("%2d. %s x%d"):format(i, sorted[i].name, sorted[i].count))
        end
        setStatus("Printed top names to console (F9)")
    end)
end)
mkButton("Clear moved cache", function()
    moved = setmetatable({}, { __mode = "k" })
    setStatus("Moved cache cleared")
end)
mkHeader("AUTO-BRING")
local autoOn = false
local autoGen = 0
mkButton("Auto category: " .. S.autoCategory, function(b)
    local order = { table.unpack(CATEGORY_ORDER) }
    table.insert(order, "all")
    local idx = table.find(order, S.autoCategory) or 0
    S.autoCategory = order[idx % #order + 1]
    b.Text = "Auto category: " .. S.autoCategory
end)
mkButton("Auto-bring: OFF", function(b)
    autoOn = not autoOn
    b.Text = "Auto-bring: " .. (autoOn and "ON" or "OFF")
    b.BackgroundColor3 = autoOn and THEME.OK or THEME.BTN
    autoGen += 1
    if not autoOn then setStatus("Auto-bring stopped") return end
    local myGen = autoGen
    setStatus("Auto-bring started (" .. S.autoCategory .. ")")
    task.spawn(function()
        local total = 0
        while autoOn and myGen == autoGen do
            if busy then
                task.wait(0.5)
            else
                local cat = S.autoCategory
                busy = true
                local ok, result = pcall(bring, function(name) return matchesCategory(name, cat) end, currentCap())
                busy = false
                if autoOn and myGen == autoGen then
                    if ok then
                        total += result
                        setStatus(("Auto [%s]: +%d (total %d)"):format(cat, result, total))
                    else
                        setStatus("Auto error: " .. tostring(result))
                    end
                end
                task.wait(S.perf and math.max(S.autoDelay, 6) or S.autoDelay)
            end
        end
    end)
end)

-- ---------------- PLAYER ----------------
cur = pages.Player
mkHeader("MOVEMENT")
local plr = { fly = false, noclip = false, infJump = false, speed = 16, jump = 50, flySpeed = 60 }
local function getHum()
    local c = lp.Character
    return c and c:FindFirstChildOfClass("Humanoid")
end

-- FLY (WASD move, Space up, LeftControl down)
local flyConn, flyBV, flyBG
local function stopFly()
    plr.fly = false
    if flyConn then flyConn:Disconnect() flyConn = nil end
    if flyBV then flyBV:Destroy() flyBV = nil end
    if flyBG then flyBG:Destroy() flyBG = nil end
    local h = getHum()
    if h then h.PlatformStand = false end
end
local function startFly()
    local hrp, hum = getHRP(), getHum()
    if not hrp or not hum then return end
    stopFly()
    plr.fly = true
    hum.PlatformStand = true
    flyBV = Instance.new("BodyVelocity")
    flyBV.MaxForce = Vector3.new(1e9, 1e9, 1e9)
    flyBV.Velocity = Vector3.zero
    flyBV.Parent = hrp
    flyBG = Instance.new("BodyGyro")
    flyBG.MaxTorque = Vector3.new(1e9, 1e9, 1e9)
    flyBG.P = 9000
    flyBG.CFrame = hrp.CFrame
    flyBG.Parent = hrp
    flyConn = game:GetService("RunService").RenderStepped:Connect(function()
        local cam = workspace.CurrentCamera
        if not (flyBV and flyBV.Parent and cam) then return end
        local dir = Vector3.zero
        local UIS = UserInputService
        if UIS:IsKeyDown(Enum.KeyCode.W) then dir += cam.CFrame.LookVector end
        if UIS:IsKeyDown(Enum.KeyCode.S) then dir -= cam.CFrame.LookVector end
        if UIS:IsKeyDown(Enum.KeyCode.D) then dir += cam.CFrame.RightVector end
        if UIS:IsKeyDown(Enum.KeyCode.A) then dir -= cam.CFrame.RightVector end
        if UIS:IsKeyDown(Enum.KeyCode.Space) then dir += Vector3.yAxis end
        if UIS:IsKeyDown(Enum.KeyCode.LeftControl) then dir -= Vector3.yAxis end
        flyBV.Velocity = dir.Magnitude > 0 and dir.Unit * plr.flySpeed or Vector3.zero
        flyBG.CFrame = cam.CFrame
    end)
end
local flyBtn
local function toggleFly()
    if plr.fly then stopFly() else startFly() end
    if flyBtn then
        flyBtn.Text = "Fly (F): " .. (plr.fly and "ON" or "OFF")
        flyBtn.BackgroundColor3 = plr.fly and THEME.OK or THEME.BTN
    end
end
flyBtn = mkButton("Fly (F): OFF", toggleFly)

local flySpeeds = { 30, 60, 120, 250 }
local flyIdx = 2
mkButton("Fly speed: 60", function(b)
    flyIdx = flyIdx % #flySpeeds + 1
    plr.flySpeed = flySpeeds[flyIdx]
    b.Text = "Fly speed: " .. plr.flySpeed
end)

local speeds = { 16, 32, 50, 80, 120 }
local speedIdx = 1
mkButton("Walk speed: 16", function(b)
    speedIdx = speedIdx % #speeds + 1
    plr.speed = speeds[speedIdx]
    b.Text = "Walk speed: " .. plr.speed
    local h = getHum()
    if h then h.WalkSpeed = plr.speed end
end)

local jumps = { 50, 80, 120, 200 }
local jumpIdx = 1
mkButton("Jump power: 50", function(b)
    jumpIdx = jumpIdx % #jumps + 1
    plr.jump = jumps[jumpIdx]
    b.Text = "Jump power: " .. plr.jump
    local h = getHum()
    if h then
        h.UseJumpPower = true
        h.JumpPower = plr.jump
    end
end)

mkButton("Noclip: OFF", function(b)
    plr.noclip = not plr.noclip
    b.Text = "Noclip: " .. (plr.noclip and "ON" or "OFF")
    b.BackgroundColor3 = plr.noclip and THEME.OK or THEME.BTN
end)
game:GetService("RunService").Stepped:Connect(function()
    if not plr.noclip then return end
    local c = lp.Character
    if not c then return end
    for _, p in ipairs(c:GetDescendants()) do
        if p:IsA("BasePart") then p.CanCollide = false end
    end
end)

mkButton("Infinite jump: OFF", function(b)
    plr.infJump = not plr.infJump
    b.Text = "Infinite jump: " .. (plr.infJump and "ON" or "OFF")
    b.BackgroundColor3 = plr.infJump and THEME.OK or THEME.BTN
end)
UserInputService.JumpRequest:Connect(function()
    if plr.infJump then
        local h = getHum()
        if h then h:ChangeState(Enum.HumanoidStateType.Jumping) end
    end
end)

-- re-apply settings after respawn
lp.CharacterAdded:Connect(function(char)
    stopFly()
    if flyBtn then
        flyBtn.Text = "Fly (F): OFF"
        flyBtn.BackgroundColor3 = THEME.BTN
    end
    local h = char:WaitForChild("Humanoid", 10)
    if h then
        h.WalkSpeed = plr.speed
        h.UseJumpPower = true
        h.JumpPower = plr.jump
    end
end)


-- ---------------- SETTINGS ----------------
cur = pages.Settings
mkHeader("SETTINGS")
mkButton("Cap: " .. CAP_OPTIONS[S.capIndex], function(b)
    S.capIndex = S.capIndex % #CAP_OPTIONS + 1
    b.Text = "Cap: " .. CAP_OPTIONS[S.capIndex]
end)
mkButton("Auto delay: " .. S.autoDelay .. "s", function(b)
    S.autoDelay = (S.autoDelay == 1 and 3) or (S.autoDelay == 3 and 6) or 1
    b.Text = "Auto delay: " .. S.autoDelay .. "s"
end)
mkButton("Include anchored: OFF", function(b)
    S.includeAnchored = not S.includeAnchored
    b.Text = "Include anchored: " .. (S.includeAnchored and "ON (client-only)" or "OFF")
end)
mkButton("Performance mode: OFF", function(b)
    S.perf = not S.perf
    b.Text = "Performance mode: " .. (S.perf and "ON (cap 50, slower auto)" or "OFF")
    b.BackgroundColor3 = S.perf and THEME.OK or THEME.BTN
end)

-- =========================================================
-- CONTROLS
-- =========================================================
close.MouseButton1Click:Connect(function()
    autoOn = false
    stopFly()
    plr.noclip, plr.infJump = false, false
    gui:Destroy()
end)

UserInputService.InputBegan:Connect(function(input, processed)
    if processed then return end
    if input.KeyCode == Enum.KeyCode.RightShift then
        root.Visible = not root.Visible
    elseif input.KeyCode == Enum.KeyCode.F and not UserInputService:GetFocusedTextBox() then
        toggleFly()
    end
end)

-- =========================================================
-- PASSWORD GATE
-- =========================================================
local PASSWORD = "1234"
local gate = Instance.new("Frame")
gate.Size = UDim2.new(0, 300, 0, 170)
gate.Position = UDim2.new(0.5, -150, 0.5, -85)
gate.BackgroundColor3 = THEME.BG
gate.BorderSizePixel = 0
gate.Active = true
gate.Draggable = true
gate.Parent = gui
round(gate, 10)

local gt = Instance.new("TextLabel")
gt.Size = UDim2.new(1, -24, 0, 30)
gt.Position = UDim2.new(0, 12, 0, 10)
gt.BackgroundTransparency = 1
gt.Text = "Tubers Hub · Enter password"
gt.TextColor3 = THEME.TEXT
gt.Font = Enum.Font.GothamBold
gt.TextSize = 14
gt.TextXAlignment = Enum.TextXAlignment.Left
gt.Parent = gate

local pw = Instance.new("TextBox")
pw.Size = UDim2.new(1, -24, 0, 36)
pw.Position = UDim2.new(0, 12, 0, 50)
pw.BackgroundColor3 = THEME.BTN
pw.BorderSizePixel = 0
pw.TextColor3 = THEME.TEXT
pw.PlaceholderText = "Password"
pw.PlaceholderColor3 = THEME.DIM
pw.Text = ""
pw.Font = Enum.Font.Code
pw.TextSize = 14
pw.ClearTextOnFocus = false
pw.Parent = gate
round(pw, 6)

local unlockBtn = Instance.new("TextButton")
unlockBtn.Size = UDim2.new(1, -24, 0, 36)
unlockBtn.Position = UDim2.new(0, 12, 0, 94)
unlockBtn.BackgroundColor3 = THEME.ACCENT
unlockBtn.BorderSizePixel = 0
unlockBtn.Text = "UNLOCK"
unlockBtn.TextColor3 = Color3.new(1, 1, 1)
unlockBtn.Font = Enum.Font.GothamBold
unlockBtn.TextSize = 13
unlockBtn.Parent = gate
round(unlockBtn, 6)

local gmsg = Instance.new("TextLabel")
gmsg.Size = UDim2.new(1, -24, 0, 18)
gmsg.Position = UDim2.new(0, 12, 0, 140)
gmsg.BackgroundTransparency = 1
gmsg.Text = ""
gmsg.TextColor3 = THEME.ACCENT
gmsg.Font = Enum.Font.Gotham
gmsg.TextSize = 11
gmsg.TextXAlignment = Enum.TextXAlignment.Left
gmsg.Parent = gate

local function tryUnlock()
    if pw.Text == PASSWORD then
        gate:Destroy()
        showPage("Bring")
        root.Visible = true
    else
        gmsg.Text = "Wrong password"
    end
end
unlockBtn.MouseButton1Click:Connect(tryUnlock)
pw.FocusLost:Connect(function(enter) if enter then tryUnlock() end end)

Features & Information

Features: 99 nights in the forest stuff ONLY use on 99 nights in the forest or u get banned if u try on other games like (the strongest battlegrounds) hint:Dont use 99 nights in the forest scripts on other games you may get banned from that game
#cheats#nights in the forest#Op

Community Comments (8)

the_scoutthe_scoutOct 11, 2026

where to get password

Replying to @the_scout
railmila2railmila2Oct 11, 2026

@the_scout 1234

Replying to @railmila2
kjjjkjprokjjjkjproOct 12, 2026(edited)

@railmila2 1234 is the password,yes its correct

kjjjkjprokjjjkjproOct 12, 2026

@ralphcook9946 is correct the password is 1234

kjjjkjprokjjjkjproOct 12, 2026

Dont say it dont work,unless u see the password and put it in

kjjjkjprokjjjkjproOct 12, 2026

https://jumpshare.com/share/nGwe096Y3U8HiVOCsW6J?b=NJUbBLnX5O1Iirv3dYRT

Replying to @kjjjkjpro
kjjjkjprokjjjkjproOct 12, 2026

This is a. Another script i made do not Attempt to Copy

Replying to @kjjjkjpro
kjjjkjprokjjjkjproOct 12, 2026

U will be suied if u do

More Scripts for Universal Scripts