Satchel Fork Open-source modern backpack system

This is a fork of Satchel by RyanLua / WinnersTakesAll. All credit for the original UI, layout, and drag-and-drop system goes to them go check out the original resource and give it a like if you haven’t already. This fork just tweaks two things I needed for my own game and figured others might want too.

Why fork it

Satchel ships with a TopbarPlus-bound icon and a fixed number of hotbar slots decided once at startup. I needed:

  • A topbar button I control myself (custom styling, different position, no TopbarPlus dependency)
  • The ability to change the number of hotbar slots while the game is running (settings menu, gamepass, per-device tuning), without a client rejoin

What changed

Topbar button decoupled from the module
The module no longer creates its own icon. It exposes three BindableEvents so any button script you write can hook in:

  • StateChanged — fires when the inventory opens/closes
  • IconEnabledChanged — fires when the Roblox menu opens/closes, so your button can hide itself
  • DraggingChanged — fires while a slot is being dragged, so your button can ignore clicks mid-drag
Backpack:GetStateChangedEvent().Event:Connect(function(isNowOpen: boolean)
	MyButton.Image = isNowOpen and OPEN_IMAGE or CLOSED_IMAGE
end)

Backpack:GetIconEnabledChangedEvent().Event:Connect(function(isEnabled: boolean)
	MyButton.Visible = isEnabled
end)

Backpack:GetDraggingChangedEvent().Event:Connect(function(isDragging: boolean)
	MyButton.Active = not isDragging
end)

OpenClose() was already exposed on the original module — it’s just a toggle, so call it once per click:

MyButton.Activated:Connect(function()
	if not GuiService.MenuIsOpen then
		Backpack.OpenClose()
	end
end)

UserInputService.InputBegan:Connect(function(input: InputObject, gameProcessedEvent: boolean)
	if gameProcessedEvent then return end
	if input.KeyCode ~= Enum.KeyCode.Backquote then return end
	if GuiService.MenuIsOpen then return end 
	if UserInputService:GetFocusedTextBox() then return end
	Backpack.OpenClose()
end)

Runtime hotbar resizing

Backpack:SetMaxHotbarSlots(8)             -- raw number
Backpack:SetMaxHotbarSlots("VR")          -- apply a named preset (FULL / VR / MINI)
Backpack:SetMaxHotbarSlots(8, "FULL")     -- redefine a preset's value; only rebuilds
                                            -- live if that preset matches the player's
                                            -- current context (desktop / VR / mobile)
Backpack:GetMaxHotbarSlots()              -- read the current count

Internally this fully rebuilds the slot list (tools get saved and re-filled, hotkeys 1-9/0 get reassigned, tooltips get recreated) rather than trying to patch things in place — a bit more work per call, but it avoids inconsistent slot state after a resize.

Not changed

Everything else — drag & drop, search, gamepad support, VR selector, tool tooltips — is untouched from the original.

Installation

https://create.roblox.com/store/asset/101523137945054/Satchel-Fork

2 Likes