use checksums to identify maps

This commit is contained in:
Not 2022-07-10 20:29:05 +02:00
parent d7955feaf8
commit 00aa2060f3
1 changed files with 72 additions and 23 deletions

View File

@ -35,7 +35,7 @@ local StatTrack = false
local UNCLAIMED = "Unclaimed Record"
local HELP_MESSAGE = "\x89Leaderboard Commands:\nretry exit findmap changelevel spba_clearcheats lb_gui rival scroll encore"
local FILENAME = "leaderboard.txt"
local FILENAME = "leaderboard"
-- Retry / changelevel map
local nextMap = nil
@ -150,15 +150,36 @@ local cv_interrupt = CV_RegisterVar({
end
})
local function djb2(message)
local digest = 5381
for c in message:gmatch(".") do
digest = (($ << 5) + $) + string.byte(c)
end
return digest
end
local function mapChecksum(mapnum)
local mh = mapheaderinfo[mapnum]
if not mh then
return nil
end
local digest = string.format("%02x", djb2(mh.lvlttl+mh.subttl+mh.zonttl))
return string.sub(digest, #digest - 3)
end
local function setST(t, map, flags, scoreTable)
local mode = flags & ST_SEP
local cks = mapChecksum(map)
t[mode] = t[mode] or {}
t[mode][map] = scoreTable
t[mode][map + (cks or "")] = scoreTable
end
local function getST(t, map, flags)
local mode = flags & ST_SEP
return t[mode] and t[mode][map] or nil
local cks = mapChecksum(map)
return t[mode] and t[mode][map + (cks or "")] or nil
end
local function setScoreTable(map, flags, scoreTable)
@ -222,7 +243,7 @@ local cv_spb_separate = CV_RegisterVar({
end
})
local function score_t(map, name, skin, color, time, splits, flags, stat)
local function score_t(map, name, skin, color, time, splits, flags, stat, checksum)
return {
["map"] = map,
["name"] = name,
@ -231,7 +252,8 @@ local function score_t(map, name, skin, color, time, splits, flags, stat)
["time"] = time,
["splits"] = splits,
["flags"] = flags,
["stat"] = stat
["stat"] = stat,
["checksum"] = checksum
}
end
@ -253,12 +275,26 @@ local function stat_str(stat)
return "0"
end
local function writeScore(fh, score)
fh:write(
score["map"], "\t",
score["name"], "\t",
score["skin"], "\t",
score["color"], "\t",
score["time"], "\t",
table.concat(score["splits"], " "), "\t",
score["flags"], "\t",
stat_str(score["stat"]), "\t",
score["checksum"], "\n"
)
end
-- Read the leaderboard
local f = io.open(FILENAME, "r")
local f = io.open(FILENAME + ".txt", "r")
if f then
for l in f:lines() do
-- Leaderboard is stored in the following tab separated format
-- mapnum, name, skin, color, time, splits, flags, stat
-- mapnum, name, skin, color, time, splits, flags, stat, map_checksum
local t = {}
for word in (l+"\t"):gmatch("(.-)\t") do
table.insert(t, word)
@ -287,17 +323,38 @@ if f then
end
end
local mapnum = tonumber(t[1])
-- Checksums
local cks = t[9] or mapChecksum(mapnum)
-- We have no previous recognition of this map
-- remove it
if cks == nil then
if cks == nil then
local rsfh = io.open(FILENAME + "_removed_scores.txt", "a")
if not rsfh then
print("Failed to open file: ", FILENAME + "_removed_scores.txt")
continue
end
rsfh:write(l, "\n")
rsfh:close()
continue
end
end
table.insert(
scoreTable,
score_t(
tonumber(t[1]),
mapnum,
t[2],
t[3],
t[4],
tonumber(t[5]),
spl,
flags,
stats
stats,
cks
)
)
@ -307,7 +364,7 @@ if f then
sortScores()
f:close()
else
print("Failed to open file: ", FILENAME)
print("Failed to open file: ", FILENAME + ".txt")
end
function allowJoin(v)
@ -1129,7 +1186,8 @@ local function saveTime(player)
timeFinished,
splits,
Flags,
stat_t(player.HMRs or pskin.kartspeed, player.HMRw or pskin.kartweight)
stat_t(player.HMRs or pskin.kartspeed, player.HMRw or pskin.kartweight),
mapChecksum(gamemap)
)
-- Check if you beat your previous best
@ -1174,25 +1232,16 @@ local function saveTime(player)
StatTrack = true
end
local f = assert(io.open(FILENAME, "w"))
local f = assert(io.open(FILENAME + ".txt", "w"))
if f == nil then
print("Failed to open file for writing: " + FILENAME)
print("Failed to open file for writing: " + FILENAME + ".txt")
return
end
for _, tbl in pairs(lb) do
for _, scoreTable in pairs(tbl) do
for _, score in ipairs(scoreTable) do
f:write(
score["map"], "\t",
score["name"], "\t",
score["skin"], "\t",
score["color"], "\t",
score["time"], "\t",
table.concat(score["splits"], " "), "\t",
score["flags"], "\t",
stat_str(score["stat"]), "\n"
)
writeScore(f, score)
end
end
end