-
Notifications
You must be signed in to change notification settings - Fork 0
/
pdScoreboards.lua
187 lines (174 loc) · 6.7 KB
/
pdScoreboards.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
local scoreboards_file, scoreboards = nil, nil
local function _save()
playdate.datastore.write(scoreboards, scoreboards_file)
end
local function _callback(callback, result)
callback({ code = "OK", message = "OK" }, result)
end
local function _update_ranks(boardId)
for board_index = 1, #scoreboards.boards do
if scoreboards.boards[board_index].boardID == boardId then
local board = scoreboards.boards[board_index]
local scores = {}
for index = 1, #board.scores do
board.scores[index].rank = index
table.insert(scores, board.scores[index])
end
end
end
end
local function _init_scoreboards(boards)
if scoreboards == nil then
scoreboards = {
player = "",
lastUpdated = playdate.getSecondsSinceEpoch(),
boards = {}
}
for index = 1, #boards do
local b = { scores = {} }
table.shallowcopy(boards[index], b)
table.insert(scoreboards.boards, b)
end
_save()
end
function playdate.scoreboards.setPlayer(username)
-- Set scoreboard player name, not in official sdk
scoreboards.player = username
_save()
end
function playdate.scoreboards.getScoreboards(callback)
-- Get a list of available scoreboards
local result = {
lastUpdated = scoreboards.lastUpdated,
boards = {}
}
for id, board in pairs(scoreboards.boards) do
table.insert(result.boards, {
boardID = id,
name = board.name,
})
end
_callback(callback, result)
end
function playdate.scoreboards.getScores(boardID, callback)
local result = {
lastUpdated = scoreboards.lastUpdated,
scores = {}
}
for board_index = 1, #scoreboards.boards do
if scoreboards.boards[board_index].boardID == boardID then
local board = scoreboards.boards[board_index]
local found = false
for score_index = 1, #board.scores do
local score = board.scores[score_index]
-- Always insert to 10
if score_index <= 10 then
table.insert(result.scores, score)
-- If we found the player, we won't have to do any more checks
if score.player == scoreboards.player then
found = true
end
-- If we haven't found the player's score, find it
elseif not found and score.player == scoreboards.player then
table.insert(result.scores, score)
found = true
-- If both conditions are met, we can stop
elseif score_index > 10 and found then
break
end
end
break
end
end
_callback(callback, result)
end
function playdate.scoreboards.addScore(boardID, value, callback)
local result = {
player = scoreboards.player,
value = value,
rank = 1
}
for board_index = 1, #scoreboards.boards do
if scoreboards.boards[board_index].boardID == boardID then
local board = scoreboards.boards[board_index]
local order = board.order or "descending"
for index, score in ipairs(board.scores) do
if order == "descending" then
result.rank = index
if value > score.value then
break
end
-- Check if we should be after the last entry
if board.scores[#board.scores].value >= value then
result.rank = index + 1
end
elseif order == "ascending" then
result.rank = index
if value < score.value then
break
end
-- Check if we should be after the last entry
if board.scores[#board.scores].value <= value then
result.rank = index + 1
end
end
end
table.insert(board.scores, result.rank, {
player = scoreboards.player,
value = value,
rank = result.rank or 1
})
_update_ranks(boardID)
_save()
break
end
end
_save()
_callback(callback, result)
end
function playdate.scoreboards.getPersonalBest(boardID, callback)
local result = nil
for board_index = 1, #scoreboards.boards do
if scoreboards.boards[board_index].boardID == boardID then
local board = scoreboards.boards[board_index]
for index = 1, #board.scores do
if board.scores[index].player == scoreboards.player then
result = board.scores[index]
break
end
end
end
if result ~= nil then
break
end
end
_callback(callback, result)
end
end
function playdate.scoreboards.initialize(boards, callback, path)
-- Check panic's servers for a leaderboard, if none then initialize locally
-- Defaults save location to Data/scoreboards.json
-- playdate.scoreboards.initialize({
-- { boardID = "highscores", name = "High Scores" },
-- { boardID = "lowscores", name = "Low Scores", order="ascending" }
-- })
playdate._scoreboards = playdate.scoreboards -- Store a backup of the functions
scoreboards_file = path or "scoreboards" -- Default to Data/scoreboards.json
scoreboards = playdate.datastore.read(scoreboards_file)
playdate.scoreboards.getScoreboards(function(status, _)
if status.code == "OK" then
callback(status, nil)
return
end
if status.message == "Wi-Fi not available" then
if scoreboards ~= nil then -- Only use offline if we've already created them online
_init_scoreboards(boards)
end
else
-- Other errors, e.g. "A game with the provided bundle_id .* does not exist", "Bad response from server" etc.
print(status.message)
_init_scoreboards(boards)
end
callback(status, nil)
end)
end