Compare commits

...

2 Commits

Author SHA1 Message Date
Not 34da7e2929 reject records missing checksum 2022-11-14 22:18:01 +01:00
Not 08c1af3073 insert checksums 2022-11-14 22:17:30 +01:00
2 changed files with 64 additions and 22 deletions

View File

@ -122,6 +122,26 @@ local function stat_str(stat)
return "0" return "0"
end end
local function djb2(message)
local digest = 5381
for c in message:gmatch(".") do
digest = (($ << 5) + $) + string.byte(c)
end
return digest
end
-- Produce a checksum by using the maps title, subtitle and zone
local function mapChecksum(mapnum)
local mh = mapheaderinfo[mapnum]
if not mh then
return nil
end
local digest = string.format("%04x", djb2(mh.lvlttl..mh.subttl..mh.zonttl))
return string.sub(digest, #digest - 3)
end
-- GLOBAL -- GLOBAL
-- Save a record to the LiveStore and write to disk -- Save a record to the LiveStore and write to disk
-- SaveRecord will replace the record holders previous record but it will not compare any record times -- SaveRecord will replace the record holders previous record but it will not compare any record times
@ -141,6 +161,11 @@ local function SaveRecord(score, map, modeSep)
for mapid, records in pairs(LiveStore) do for mapid, records in pairs(LiveStore) do
for _, record in ipairs(records) do for _, record in ipairs(records) do
-- Insert checksum if missing
if (not record.checksum) or record.checksum == "" then
record.checksum = mapChecksum(mapid)
end
f:write( f:write(
mapid, "\t", mapid, "\t",
record.name, "\t", record.name, "\t",
@ -149,7 +174,8 @@ local function SaveRecord(score, map, modeSep)
record.time, "\t", record.time, "\t",
table.concat(record.splits, " "), "\t", table.concat(record.splits, " "), "\t",
record.flags, "\t", record.flags, "\t",
stat_str(record.stat), "\n" stat_str(record.stat), "\t",
record.checksum or "", "\n"
) )
end end
end end
@ -164,7 +190,7 @@ end
addHook("NetVars", netvars) addHook("NetVars", netvars)
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 { return {
["map"] = map, ["map"] = map,
["name"] = name, ["name"] = name,
@ -173,7 +199,8 @@ local function score_t(map, name, skin, color, time, splits, flags, stat)
["time"] = time, ["time"] = time,
["splits"] = splits, ["splits"] = splits,
["flags"] = flags, ["flags"] = flags,
["stat"] = stat ["stat"] = stat,
["checksum"] = checksum
} }
end end
@ -206,6 +233,8 @@ local function parseScore(str)
end end
end end
local checksum = t[9]
return score_t( return score_t(
tonumber(t[1]), -- Map tonumber(t[1]), -- Map
t[2], -- Name t[2], -- Name
@ -214,25 +243,24 @@ local function parseScore(str)
tonumber(t[5]), -- Time tonumber(t[5]), -- Time
splits, splits,
flags, flags,
stats stats,
checksum
) )
end end
rawset(_G, "lb_parse_score", parseScore) rawset(_G, "lb_parse_score", parseScore)
-- Load the livestore -- Load the livestore
do if isserver then
if isserver then local f = assert(
local f = assert( io.open(LEADERBOARD_FILE, "r"),
io.open(LEADERBOARD_FILE, "r"), "Failed to open file: "..LEADERBOARD_FILE
"Failed to open file: "..LEADERBOARD_FILE )
)
for l in f:lines() do for l in f:lines() do
local score = parseScore(l) local score = parseScore(l)
LiveStore[score.map] = $ or {} LiveStore[score.map] = $ or {}
table.insert(LiveStore[score.map], score) table.insert(LiveStore[score.map], score)
end
f:close()
end end
f:close()
end end

View File

@ -13,6 +13,11 @@ records_lua = sys.argv[3]
def ParseScore(score): def ParseScore(score):
# Map Name Skin Color Time Splits Flags Stat # Map Name Skin Color Time Splits Flags Stat
split = score.split("\t") split = score.split("\t")
checksum = ""
if len(split) > 8:
checksum = split[8]
return { return {
"map": split[0], "map": split[0],
"name": split[1], "name": split[1],
@ -21,7 +26,8 @@ def ParseScore(score):
"time": int(split[4]), "time": int(split[4]),
"splits": split[5], "splits": split[5],
"flags": int(split[6]), "flags": int(split[6]),
"stat": split[7] "stat": split[7],
"checksum": checksum
} }
# Compare scores # Compare scores
@ -65,14 +71,20 @@ for score in recordsList:
# convert records to flat list # convert records to flat list
recordsList = [] recordsList = []
rejected = []
for mapTable in records.values(): for mapTable in records.values():
for score in mapTable: for score in mapTable:
recordsList.append("\t".join([str(v) for v in list(score.values())])) scoreStr = "\t".join([str(v) for v in list(score.values())])
# only allow records with checksums
if score["checksum"] != "":
recordsList.append(scoreStr)
else:
rejected.append(scoreStr)
# truncate and write records to coldstore # truncate and write records to coldstore
with open(coldstore_txt, "w") as f: with open(coldstore_txt, "w") as f:
for score in recordsList: for score in recordsList:
f.write(score + linesep) f.write(score + linesep)
luaA = """local ParseScore = lb_parse_score luaA = """local ParseScore = lb_parse_score
local AddColdStore = lb_add_coldstore_record local AddColdStore = lb_add_coldstore_record
@ -90,5 +102,7 @@ with open(records_lua, "w") as f:
f.write("\"{}\",{}".format(score, linesep)) f.write("\"{}\",{}".format(score, linesep))
f.write(luaB) f.write(luaB)
# truncate leaderboard.txt # truncate and rewrite rejected scores to leaderboard.txt
with open(leaderboard_txt, "w"): pass with open(leaderboard_txt, "w") as f:
for score in rejected:
f.write(score + linesep)