126 lines
3.1 KiB
Python
Executable File
126 lines
3.1 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
import sys
|
|
from os import path
|
|
linesep = "\n"
|
|
|
|
if len(sys.argv) != 3 or not sys.argv[1] or not sys.argv[2]:
|
|
print("Usage: coldstore.py <game_directory> <leaderboard_records.lua>")
|
|
print("\t<game_directory>\t\tthe game directory where wads and luafiles reside. Usually at '$HOME/.srb2kart'.")
|
|
print("\t<leaderboard_records.lua>\tthe output name for the records packed lua file. It will be saved within <game_directory>.")
|
|
quit()
|
|
|
|
if not sys.argv[2].endswith(".lua"):
|
|
print("{} must end with .lua".format(sys.argv[2]))
|
|
quit()
|
|
|
|
game_dir = sys.argv[1]
|
|
leaderboard_txt = path.join(game_dir, "luafiles", "leaderboard.txt")
|
|
coldstore_txt = path.join(game_dir, "luafiles", "leaderboard.coldstore.txt")
|
|
records_lua = path.join(game_dir, sys.argv[2])
|
|
|
|
def ParseScore(score):
|
|
# Map Name Skin Color Time Splits Flags Stat
|
|
split = score.split("\t")
|
|
|
|
checksum = ""
|
|
if len(split) > 8:
|
|
checksum = split[8]
|
|
|
|
return {
|
|
"map": split[0],
|
|
"name": split[1],
|
|
"skin": split[2],
|
|
"color": split[3],
|
|
"time": int(split[4]),
|
|
"splits": split[5],
|
|
"flags": int(split[6]),
|
|
"stat": split[7],
|
|
"checksum": checksum
|
|
}
|
|
|
|
# Compare scores
|
|
def CompareScore(a, b):
|
|
return a["time"] < b["time"]
|
|
|
|
F_SEP = 0xF
|
|
def SameScore(a, b):
|
|
return a["name"] == b["name"] and a["checksum"] == b["checksum"] and (a["flags"] & F_SEP) == (b["flags"] & F_SEP)
|
|
|
|
def LoadRecordsFromFile(path):
|
|
records = []
|
|
try:
|
|
with open(path, "r") as f:
|
|
for line in f.readlines():
|
|
line = line.strip()
|
|
if line != "":
|
|
records.append(ParseScore(line))
|
|
except FileNotFoundError:
|
|
pass
|
|
|
|
return records
|
|
|
|
def AddScore(records, score):
|
|
mapid = score["map"]
|
|
mapTable = records.get(mapid) or []
|
|
|
|
for i in range(len(mapTable)):
|
|
scoreb = mapTable[i]
|
|
if SameScore(score, scoreb):
|
|
if CompareScore(score, scoreb):
|
|
mapTable[i] = score
|
|
records[mapid] = mapTable
|
|
return
|
|
mapTable.append(score)
|
|
records[mapid] = mapTable
|
|
|
|
# load leaderboard.txt and coldstore.txt
|
|
recordsList = LoadRecordsFromFile(leaderboard_txt)
|
|
recordsList.extend(LoadRecordsFromFile(coldstore_txt))
|
|
|
|
|
|
# construct the map tables
|
|
records = {}
|
|
for score in recordsList:
|
|
AddScore(records, score)
|
|
|
|
# convert records to flat list
|
|
recordsList = []
|
|
rejected = []
|
|
for mapTable in records.values():
|
|
for score in mapTable:
|
|
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
|
|
with open(coldstore_txt, "w") as f:
|
|
for score in recordsList:
|
|
f.write(score + linesep)
|
|
|
|
luaA = """do
|
|
local AddColdStore = lb_add_coldstore_record_string
|
|
local records = {
|
|
"""
|
|
luaB = """ }
|
|
for _, str in ipairs(records) do
|
|
AddColdStore(str)
|
|
end
|
|
end
|
|
"""
|
|
# pack the records.lua file
|
|
with open(records_lua, "w") as f:
|
|
f.write(luaA)
|
|
for score in recordsList:
|
|
score = score.replace("\\", "\\\\")
|
|
score = score.replace("\"", "\\\"")
|
|
f.write("\t\t\"{}\",{}".format(score, linesep))
|
|
f.write(luaB)
|
|
|
|
# truncate and rewrite rejected scores to leaderboard.txt
|
|
with open(leaderboard_txt, "w") as f:
|
|
for score in rejected:
|
|
f.write(score + linesep)
|