Lưu dữ liệu
data giữ giá trị giữa các lần chơi: xu của người chơi, túi đồ, thời gian tốt nhất trên một đường đua. Chỉ dành cho Script trên server.
Một kho (store)
local store = data.store("PlayerData") -- một kho có tên, riêng cho mỗi game| Phương thức | Làm gì |
|---|---|
store:get(key) | Giá trị đã lưu dưới key, hoặc nil |
store:set(key, value) | Lưu value dưới key (nil thì xoá) |
store:update(key, fn) | Đọc giá trị, đưa cho fn, lưu thứ fn trả về |
store:increment(key, delta) | Cộng delta (1 nếu bỏ trống) vào một số và trả về tổng mới |
store:remove(key) | Xoá key |
Giá trị có thể là nil, boolean, số, chuỗi, kiểu giá trị (vec3, màu...) và bảng chứa những thứ đó - không có part hay đối tượng - tối đa 16 KB mỗi key.
Mỗi lần gọi đều chờ câu trả lời mà không làm đứng game, và báo lỗi khi thất bại (mạng, cơ sở dữ liệu). Luôn bọc trong pcall.
Lưu xu của người chơi
local store = data.store("PlayerData")
players.joined:connect(function(player)
player.stats.Coins = 0 -- trước khi có gì được lưu
if player.userId <= 0 then return end -- khách (userId -1) không bao giờ được lưu
local ok, saved = pcall(function()
return store:get("user_" .. player.userId)
end)
if ok and saved then
player.stats.Coins = saved
end
end)
players.left:connect(function(player)
if player.userId <= 0 then return end
pcall(function()
store:set("user_" .. player.userId, player.stats.Coins)
end)
end)Gõ savedata ở đầu dòng trong trình soạn để có snippet này.
Dùng userId làm key, đừng dùng tên
Người chơi có thể đổi tên. userId của họ không bao giờ đổi. Khách có userId -1, nên kiểm tra userId > 0 trước khi lưu.
Lưu một bảng
local profile = {
coins = 120,
level = 4,
inventory = {"Sword", "Shield"},
}
pcall(function() store:set("user_" .. player.userId, profile) end)Mỗi người chơi lưu một bảng thay vì nhiều key: một yêu cầu thay vì nhiều, và không bao giờ bị lưu dở dang.
Thay đổi an toàn: update và increment
update và increment an toàn khi nhiều server cùng đụng vào một key (hai server của cùng game, một bộ đếm chung). update chỉ ghi đè lên đúng giá trị nó đã đọc; nếu trong lúc đó giá trị thay đổi, nó đọc lại và chạy lại fn - nên đừng để fn có tác dụng phụ:
local stats = data.store("Global")
pcall(function() stats:increment("totalWins") end)
pcall(function()
stats:update("bestTime", function(old)
if old == nil or myTime < old then return myTime end
return old
end)
end)Khi server tắt
Khi một server đóng - cập nhật, khởi động lại, người chơi cuối cùng rời đi - game.closing chạy trước, lúc mọi người chơi vẫn còn trong game, rồi từng người rời đi, nên các hàm players.left của bạn chạy và lưu. Server chờ chúng tối đa 20 giây.
game.closing:connect(function()
-- lưu những gì game giữ chung cho mọi người (kỷ lục thế giới, ngân hàng chung)
end)Đọc trước khi chờ
Sau một task.wait trong players.left, người chơi đã đi: hãy đọc những gì cần (player.userId, player.stats.Coins) trước khi chờ.
Lưu ở đâu
Game chạy từ KHIM lưu lên KHIM, riêng từng game: game khác không đọc được.
Giới hạn
- 16 KB mỗi giá trị.
- 64 yêu cầu đang chờ cùng lúc trên một server.
updatebỏ cuộc và báo lỗi nếu key cứ thay đổi mười hai lần liên tiếp.
JSON
json.encode(value, pretty?) đổi một bảng thành chuỗi JSON, json.decode(text) đổi ngược lại - cho cài đặt viết bằng JSON, hoặc một bảng lưu thành một chuỗi:
local text = json.encode({coins = 5, items = {"Sword"}}) -- '{"coins":5,"items":["Sword"]}'
local back = json.decode(text)
print(back.items[1]) -- Sword