๐ Stores
Stores are the core of Coppermind โ they represent individual data entries that can be loaded, saved, and managed.
๐ฅ Loading a Storeโ
Use loadStore to load data for a specific key:
local store = Coppermind.loadStore(PlayerSchema, tostring(player.UserId), {
sessionLocked = true,
autoSave = 60,
})
Parametersโ
| Parameter | Type | Description |
|---|---|---|
schema | Schema | The registered schema to use |
key | string | Unique identifier for this data entry |
config | StoreConfig? | Optional configuration |
Configuration Optionsโ
{
sessionLocked = true, -- ๐ Lock data to this server
autoSave = 60, -- โฑ๏ธ Auto-save interval in seconds
}
๐ Store Propertiesโ
local store = Coppermind.loadStore(schema, key, config)
print(store.key) -- "123456789" (identifier)
print(store.data) -- { coins = 100, ... } (nil while loading)
print(store.state) -- "READY" (current state)
print(store.sessionId) -- "abc-123-def" (if session locked)
print(store.version) -- 2 (migration version)
print(store.lastSaved) -- 1703712000 (timestamp)
๐ฆ Store Statesโ
| State | Icon | Description |
|---|---|---|
LOADING | ๐ | Fetching data from DataStore |
READY | โ | Data loaded and available for use |
SAVING | ๐พ | Currently saving to DataStore |
UNLOADING | ๐ค | Saving and releasing the store |
UNLOADED | โฌ | Store has been released |
ERROR | โ | Failed to load or save |
SESSION_LOCKED | ๐ | Another server owns this data |
๐ก Store Eventsโ
Each store has its own events:
-- โ
Fires when data is loaded and ready
store.onReady:Connect(function(store)
print("Store ready:", store.key)
end)
-- ๐พ Fires after each successful save
store.onSaved:Connect(function(store)
print("Store saved:", store.key)
end)
-- โ Fires on any error
store.onError:Connect(function(store, errorMessage)
warn("Store error:", store.key, errorMessage)
end)
-- ๐ฑ Fires when a transaction is completed
store.onTransaction:Connect(function(store, transactionId)
print("Transaction completed:", transactionId)
end)
๐ Checking Store Statusโ
Is Loadedโ
if Coppermind.isLoaded(PlayerSchema, key) then
print("Store is loaded")
end
Get Store Referenceโ
local store = Coppermind.getStore(PlayerSchema, key)
if store and store.state == "READY" then
print("Store is ready")
end
๐พ Saving a Storeโ
- Manual Save
- Auto-Save
local success = Coppermind.saveStore(PlayerSchema, key)
if success then
print("Save queued")
end
Configure when loading:
local store = Coppermind.loadStore(schema, key, {
autoSave = 30, -- Save every 30 seconds
})
Auto-Save Behavior
Auto-save automatically pauses during manual saves and resumes after.
๐ค Unloading a Storeโ
Always Unload
Always unload stores when no longer needed to prevent data loss!
local success = Coppermind.unloadStore(PlayerSchema, key)
Unloading performs these steps:
- โน๏ธ Cancels any pending auto-save
- ๐พ Saves current data
- ๐ Releases the session lock
- ๐๏ธ Removes the store from memory
Typical Usageโ
game.Players.PlayerRemoving:Connect(function(player)
local key = tostring(player.UserId)
if Coppermind.isLoaded(PlayerSchema, key) then
Coppermind.unloadStore(PlayerSchema, key)
end
end)
๐ Session Lockingโ
Session locking prevents multiple servers from modifying the same data:
local store = Coppermind.loadStore(schema, key, {
sessionLocked = true,
})
How It Worksโ
graph LR
A[Server A requests load] --> B{Lock available?}
B -->|Yes| C[Acquire lock]
B -->|No| D[SESSION_LOCKED state]
C --> E[Load data]
E --> F[Use data...]
F --> G[Unload store]
G --> H[Release lock]
- When loading, Coppermind checks if another server owns the lock
- If locked, the store enters
SESSION_LOCKEDstate - If available, this server acquires the lock
- The lock is released when the store is unloaded
โฐ Lock Expirationโ
Automatic Expiration
Locks automatically expire after 30 minutes. This handles cases where a server crashes without properly unloading.
Handling Lock Conflictsโ
store.onError:Connect(function(store, errorMessage)
if store.state == "SESSION_LOCKED" then
warn("Data is locked by another server")
-- Optionally kick the player or retry later
end
end)
๐ Complete Exampleโ
local Coppermind = require(path.to.Coppermind)
local PlayerSchema = Coppermind.registerSchema({
name = "PlayerData",
dataTemplate = {
coins = 0,
playtime = 0,
},
migrations = {},
})
local function onPlayerAdded(player)
local key = tostring(player.UserId)
local store = Coppermind.loadStore(PlayerSchema, key, {
sessionLocked = true,
autoSave = 60,
})
store.onReady:Connect(function()
print(`{player.Name}'s data loaded!`)
end)
store.onError:Connect(function(_, errorMessage)
warn(`Failed to load {player.Name}'s data: {errorMessage}`)
player:Kick("Failed to load your data. Please rejoin.")
end)
end
local function onPlayerRemoving(player)
local key = tostring(player.UserId)
if Coppermind.isLoaded(PlayerSchema, key) then
Coppermind.unloadStore(PlayerSchema, key)
end
end
game.Players.PlayerAdded:Connect(onPlayerAdded)
game.Players.PlayerRemoving:Connect(onPlayerRemoving)
-- Handle existing players (for late script execution)
for _, player in game.Players:GetPlayers() do
task.spawn(onPlayerAdded, player)
end