⚙ Settings Configuration
Understand the two-layer settings system: global defaults and per-player overrides. Learn when to use each and how to modify them at runtime.
The Two Layers
Global defaults vs per-player overrides
Stoway uses a two-layer settings system to provide flexibility:
Global Settings
File: Settings.luauDefault values applied to all players. Set once, affects everyone.
- Game-wide defaults
- Static configuration
- Changed in code
- Requires server restart to apply
Per-Player Settings
Property: state.SettingsIndividual overrides per player. Can change at runtime.
- Player-specific values
- Runtime modifiable
- Synced to client automatically
- VIP, permissions, game modes
Global Settings
Configuration in src/shared/Settings.luau
-- src/shared/Settings.luau
-- Hotbar Configuration
Settings.Hotbar = {
Type = "Static", -- Static or Dynamic
MaxSlots = 10, -- Number of hotbar slots
}
-- Storage/Backpack Configuration
Settings.Storage = {
Limit = 15, -- Weight limit (0 = infinite)
CanStack = true, -- Enable stacking
Sorting = true, -- Enable sorting
MaxStackSize = 5, -- Max items per stack
SortOrder = "None" -- Name, Rarity, ItemType, None
}
-- Stacking Rules
Settings.Stacking = {
RequiredFields = { "Rarity", "Type" }, -- Must match to stack
Blacklist = { -- Never stack these
["Legendary"] = true,
["Mythic"] = true,
},
Rarity = true, -- Show rarity colors
}
-- Gameplay Settings
Settings.Gameplay = {
Droppable = true, -- Can items be dropped
DropDistance = 10, -- Drop range
}
-- UI Configuration
Settings.DifferentUIs = {
Default = {
FolderName = "StowayGui",
GuiName = "Stoway",
HookPresetName = "DefaultHooks"
},
Admin = {
FolderName = "StowayAdmin",
GuiName = "AdminGui",
HookPresetName = "AdminHooks"
}
}
| Setting | Type | Default | Description |
|---|---|---|---|
Hotbar.MaxSlots |
number | 10 | Number of fixed hotbar slots (1-9 standard) |
Storage.Limit |
number | 15 | Weight limit, 0 = unlimited |
Storage.CanStack |
boolean | true | Enable item stacking |
Storage.MaxStackSize |
number | 5 | Max items per stack |
Gameplay.Droppable |
boolean | true | Allow dropping items to world |
Per-Player Settings
Runtime configuration per player
Each player has a state.Settings table that inherits from global defaults but can be overridden:
-- src/server/StowayServerV1_2/Core/InventoryState.luau
export type PlayerSettings = {
Limit: number, -- Weight limit (0 = infinite)
CanStack: boolean, -- Allow stacking
MaxStackSize: number, -- Max items per stack
MaxHotbarSlots: number, -- Number of hotbar slots
Droppable: boolean, -- Allow dropping
UiType: string, -- Interface version
}
-- Constructor applies defaults
function InventoryState.new(player: Player): InventoryStateType
-- ...
self.Settings = {
Droppable = Settings.Gameplay.Droppable,
Limit = Settings.Storage.Limit,
CanStack = Settings.Storage.CanStack,
MaxStackSize = Settings.Storage.MaxStackSize,
MaxHotbarSlots = Settings.Hotbar.MaxSlots,
UiType = "Default"
}
return self
end
Modifying Per-Player Settings
Change settings at runtime
Direct Modification
Modify state.Settings directly and sync:
local state = InventoryService.GetState(player)
-- Give VIP players more inventory space
if player.GetRankInGroup(12345) > 254 then
state.Settings.Limit = 50 -- VIP gets 50 slots
end
-- Disable dropping for new players
state.Settings.Droppable = false
-- Sync to client
InventoryService.SyncSettings(player)
Change UI Type
Switch a player's UI skin:
-- Switch to admin UI
InventoryService.ReloadClient(player, {
configSettingName = "Admin"
})
-- The client will:
-- 1. Destroy old UI
-- 2. Load new GUI from DifferentUIs.Admin
-- 3. Load new hooks from DifferentUIs.Admin.HookPresetName
-- 4. Rebuild all slots
Adding More Hotbar Slots
Give players extra hotbar slots (e.g., admins get 12 slots)
Stoway supports up to 12 hotbar slots. The recommended maximum is 12 because:
- PC: Keys 1-0 plus - and = (= is Shift+)
- Console: R1/R2 modifier combos for easy thumb access
- Simple mental mapping: 1-10 on number row, 11-12 on the keys next to it
-- src/shared/Binds.luau
-- Slot 11 (Minus key)
Binds.HotbarSlots[11] = {
Display = "-",
PC = { {Main = Enum.KeyCode.Minus} },
Console = { {Main = Enum.KeyCode.ButtonX, Modifiers = {Enum.KeyCode.ButtonR2}} } -- R2 + X
}
-- Slot 12 (Equals key)
Binds.HotbarSlots[12] = {
Display = "=",
PC = { {Main = Enum.KeyCode.Equals} },
Console = { {Main = Enum.KeyCode.ButtonY, Modifiers = {Enum.KeyCode.ButtonR2}} } -- R2 + Y
}
Modify Per-Player Settings
In OnPlayerAdded, override state.Settings.MaxHotbarSlots:
-- src/server/StowayServerV1_2/init.luau
local ADMIN_GROUP_ID = 12345
local ADMIN_RANK = 255
local OnPlayerAdded = function(player)
local state = InventoryState.new(player)
PlayerInventories[player] = state
-- Give admins 12 slots
local rank = player:GetRankInGroup(ADMIN_GROUP_ID)
if rank >= ADMIN_RANK then
state.Settings.MaxHotbarSlots = 12
end
InventoryService.SyncSettings(player)
end
Check Client Hotbar Binds
Ensure your client code reads the correct number of binds from Binds.HotbarSlots based on state.Settings.MaxHotbarSlots.
- Maximum supported slots: 12
- Slots 11-12 use - and = keys on keyboard
- Console uses R2 modifier (left trigger) for slots 11-12
- Always sync settings after modifying:
InventoryService.SyncSettings(player)
Global Settings For:
- Game balance constants
- Default stacking rules
- Standard hotbar size
- Base weight limits
Per-Player Settings For:
- VIP/member bonuses
- Permission-based limits
- Game mode restrictions
- Temporary effects
Example: VIP Inventory Bonus
Complete example with global and per-player settings
-- src/server/StowayServerV1_2/init.luau
local VIP_GROUP_ID = 12345
local VIP_RANK = 255
local VIP_LIMIT = 50 -- VIPs get 50 slots
local NORMAL_LIMIT = 15 -- Normal players get 15
local OnPlayerAdded = function(player)
local state = InventoryState.new(player)
PlayerInventories[player] = state
-- Apply VIP bonus
local rank = player:GetRankInGroup(VIP_GROUP_ID)
if rank >= VIP_RANK then
print("[Stoway] " .. player.Name .. " is a VIP!")
state.Settings.Limit = VIP_LIMIT
state.Settings.MaxStackSize = 10 -- VIPs stack higher
else
state.Settings.Limit = NORMAL_LIMIT
end
-- Sync settings to client
InventoryService.SyncSettings(player)
end
Example: Restricted Slots (Disabled Backpack)
Block specific hotbar slots globally when backpack is disabled
This example shows how to prevent items from entering specific slots (e.g., 7 and 8) when the backpack is disabled. We implement this as a Global Setting that applies to all players.
Configure Settings
Define which slots are limited in src/shared/Settings.luau.
Settings.Hotbar = {
MaxSlots = 10,
-- Custom table of restricted slots (Global)
LimitedSlots = {
[7] = true,
[8] = true,
}
}
Modify AddOperation (Server)
In src/server/StowayServerV1_2/Operations/AddOperation.luau, require the global settings and check limits.
local Settings = require(game:GetService("ReplicatedStorage").Shared.Settings)
-- Inside the BackpackDisabled block
if Settings.Storage.BackpackEnabled == false then
local emptySlot = SlotManager.FindEmptyHotbarSlot(state)
if emptySlot then
-- CHECK: Is this slot limited?
local limited = Settings.Hotbar.LimitedSlots
if limited and limited[emptySlot] then
return {
success = false,
reason = emptySlot .. " is limited"
}
end
-- ... Standard add logic ...
end
end
Modify SwapOperation (Server)
In src/server/StowayServerV1_2/Operations/SwapOperation.luau, prevent swapping into limited slots.
local Settings = require(game:GetService("ReplicatedStorage").Shared.Settings)
-- Inside ValidateSwap function
if not Settings.Storage.BackpackEnabled then
local limited = Settings.Hotbar.LimitedSlots
if limited then
if from.type == "Hotbar" and limited[from.slot] then
return false, from.slot .. " is limited"
end
if to.type == "Hotbar" and limited[to.slot] then
return false, to.slot .. " is limited"
end
end
end
Modify Client Controller
In src/client/StowayClientv1_2/Operations/InventoryController.luau, check global settings to block dragging.
local GlobalSettings = require(ReplicatedStorage.Shared.Settings)
-- Inside Swap function
if not GlobalSettings.Storage.BackpackEnabled then
local limited = GlobalSettings.Hotbar.LimitedSlots
if limited then
if fromType == "Hotbar" and limited[fromSlot] then
warn(fromSlot .. " is limited")
return "Slot is limited"
end
if toType == "Hotbar" and limited[toSlot] then
warn(toSlot .. " is limited")
return "Slot is limited"
end
end
end
Settings Reference
Quick reference for all settings
| Setting | Layer | Type | Default | Syncs to Client |
|---|---|---|---|---|
Limit |
Both | number | 15 | ✔ Yes |
CanStack |
Both | boolean | true | ✔ Yes |
MaxStackSize |
Both | number | 5 | ✔ Yes |
MaxHotbarSlots |
Both | number | 10 | ✔ Yes |
Droppable |
Both | boolean | true | ✔ Yes |
UiType |
Player only | string | "Default" | ✔ Yes |
Hotbar.Type |
Global only | string | "Static" | ✔ Yes |
Storage.Sorting |
Global only | boolean | true | ✖ No |
Use Cases
When to use each settings layer