mirror of
https://github.com/ComfyFactory/ComfyFactorio.git
synced 2025-01-04 00:15:45 +02:00
f72a577b7d
Changes: - Players now can create private runs protected by a password. This run becomes public if the crew is empty or inactive for 24 horus (Limit is currently 1 private run at a time).
639 lines
25 KiB
Lua
639 lines
25 KiB
Lua
-- This file is part of thesixthroc's Pirate Ship softmod, licensed under GPLv3 and stored at https://github.com/danielmartin0/ComfyFactorio-Pirates.
|
|
|
|
|
|
-- == This code is mostly a fork of the file from Mountain Fortress
|
|
|
|
local Event = require 'utils.event'
|
|
local Global = require 'utils.global'
|
|
local Server = require 'utils.server'
|
|
local Gui = require 'utils.gui'
|
|
local Math = require 'maps.pirates.math'
|
|
local Token = require 'utils.token'
|
|
require 'utils.core'
|
|
local _inspect = require 'utils.inspect'.inspect
|
|
local SpamProtection = require 'utils.spam_protection'
|
|
-- local Memory = require 'maps.pirates.memory'
|
|
local Utils = require 'maps.pirates.utils_local'
|
|
local CoreData = require 'maps.pirates.coredata'
|
|
local Common = require 'maps.pirates.common'
|
|
|
|
local module_name = Gui.uid_name()
|
|
-- local module_name = 'Highscore'
|
|
local score_dataset = 'highscores'
|
|
local score_key = 'pirate_ship_scores'
|
|
local score_key_debug = 'pirate_ship_scores_debug'
|
|
local score_key_modded = 'pirate_ship_scores_modded'
|
|
|
|
|
|
|
|
local Public = {}
|
|
local insert = table.insert
|
|
local this = {
|
|
score_table = {player = {}},
|
|
sort_by = {}
|
|
}
|
|
|
|
Global.register(
|
|
this,
|
|
function(t)
|
|
this = t
|
|
end
|
|
)
|
|
|
|
local function sort_list(method, column_name, score_list)
|
|
local comparators = {
|
|
['ascending'] = function(a, b)
|
|
if column_name == 'completion_time' then
|
|
return ((a[column_name] < b[column_name]) and not (a[column_name] == 0 and b[column_name] ~= 0)) or (a[column_name] ~= 0 and b[column_name] == 0) --put all 0s at the end
|
|
elseif column_name == 'version' then
|
|
return Common.version_greater_than(b[column_name], a[column_name])
|
|
elseif type(a[column_name]) == 'string' then
|
|
return a[column_name] > b[column_name]
|
|
elseif a[column_name] then
|
|
return a[column_name] < b[column_name]
|
|
end
|
|
end,
|
|
--nosort
|
|
['descending'] = function(a, b)
|
|
if column_name == 'completion_time' then
|
|
return ((b[column_name] < a[column_name]) and not (a[column_name] == 0 and b[column_name] ~= 0)) or (a[column_name] ~= 0 and b[column_name] == 0) --put all 0s at the end
|
|
elseif column_name == 'version' then
|
|
return Common.version_greater_than(a[column_name], b[column_name])
|
|
elseif type(a[column_name]) == 'string' then
|
|
return a[column_name] < b[column_name]
|
|
elseif a[column_name] then
|
|
return a[column_name] > b[column_name]
|
|
end
|
|
end
|
|
}
|
|
Utils.stable_sort(score_list, comparators[method])
|
|
-- table.sort(score_list, comparators[method])
|
|
return score_list
|
|
end
|
|
|
|
|
|
|
|
local function get_tables_of_scores_by_type(scores)
|
|
|
|
local completion_times = {}
|
|
local leagues_travelled = {}
|
|
local completion_times_mediump_latestv = {}
|
|
local leagues_travelled_mediump_latestv = {}
|
|
local completion_times_hard = {}
|
|
local leagues_travelled_hard = {}
|
|
local completion_times_nightmare = {}
|
|
local leagues_travelled_nightmare = {}
|
|
local completion_times_latestv = {}
|
|
local leagues_travelled_latestv = {}
|
|
local versions = {}
|
|
|
|
for _, score in pairs(scores) do
|
|
if score.version then
|
|
versions[#versions + 1] = score.version
|
|
end
|
|
if score.completion_time and score.completion_time > 0 then
|
|
completion_times[#completion_times + 1] = score.completion_time
|
|
end
|
|
if score.leagues_travelled and score.leagues_travelled > 0 then
|
|
leagues_travelled[#leagues_travelled + 1] = score.leagues_travelled
|
|
end
|
|
if score.difficulty and score.difficulty > 1 then
|
|
if score.completion_time and score.completion_time > 0 then
|
|
completion_times_hard[#completion_times_hard + 1] = score.completion_time
|
|
end
|
|
if score.leagues_travelled and score.leagues_travelled > 0 then
|
|
leagues_travelled_hard[#leagues_travelled_hard + 1] = score.leagues_travelled
|
|
end
|
|
end
|
|
if score.difficulty and score.difficulty > 2 then
|
|
if score.completion_time and score.completion_time > 0 then
|
|
completion_times_nightmare[#completion_times_nightmare + 1] = score.completion_time
|
|
end
|
|
if score.leagues_travelled and score.leagues_travelled > 0 then
|
|
leagues_travelled_nightmare[#leagues_travelled_nightmare + 1] = score.leagues_travelled
|
|
end
|
|
end
|
|
end
|
|
|
|
local latest_version = 0
|
|
for _, v in pairs(versions) do
|
|
if Common.version_greater_than(v, latest_version) then latest_version = v end
|
|
end
|
|
|
|
for _, score in pairs(scores) do
|
|
if score.version and type(score.version) == type(latest_version) and score.version == latest_version then
|
|
if score.completion_time and score.completion_time > 0 then
|
|
completion_times_latestv[#completion_times_latestv + 1] = score.completion_time
|
|
end
|
|
if score.leagues_travelled and score.leagues_travelled > 0 then
|
|
leagues_travelled_latestv[#leagues_travelled_latestv + 1] = score.leagues_travelled
|
|
end
|
|
if score.difficulty and score.difficulty >= 1 then
|
|
if score.completion_time and score.completion_time > 0 then
|
|
completion_times_mediump_latestv[#completion_times_mediump_latestv + 1] = score.completion_time
|
|
end
|
|
if score.leagues_travelled and score.leagues_travelled > 0 then
|
|
leagues_travelled_mediump_latestv[#leagues_travelled_mediump_latestv + 1] = score.leagues_travelled
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
table.sort(completion_times)
|
|
table.sort(leagues_travelled)
|
|
table.sort(completion_times_mediump_latestv)
|
|
table.sort(leagues_travelled_mediump_latestv)
|
|
table.sort(completion_times_hard)
|
|
table.sort(leagues_travelled_hard)
|
|
table.sort(completion_times_nightmare)
|
|
table.sort(leagues_travelled_nightmare)
|
|
table.sort(completion_times_latestv)
|
|
table.sort(leagues_travelled_latestv)
|
|
|
|
return {
|
|
latest_version = latest_version,
|
|
completion_times = completion_times,
|
|
leagues_travelled = leagues_travelled,
|
|
completion_times_mediump_latestv = completion_times_mediump_latestv,
|
|
leagues_travelled_mediump_latestv = leagues_travelled_mediump_latestv,
|
|
completion_times_hard = completion_times_hard,
|
|
leagues_travelled_hard = leagues_travelled_hard,
|
|
completion_times_nightmare = completion_times_nightmare,
|
|
leagues_travelled_nightmare = leagues_travelled_nightmare,
|
|
completion_times_latestv = completion_times_latestv,
|
|
leagues_travelled_latestv = leagues_travelled_latestv,
|
|
}
|
|
end
|
|
|
|
|
|
local function get_score_cuttofs(tables_of_scores_by_type)
|
|
|
|
local completion_times_cutoff = #tables_of_scores_by_type.completion_times > 8 and tables_of_scores_by_type.completion_times[8] or 9999999
|
|
local completion_times_mediump_latestv_cutoff = #tables_of_scores_by_type.completion_times_mediump_latestv > 4 and tables_of_scores_by_type.completion_times_mediump_latestv[4] or 9999999
|
|
local completion_times_hard_cutoff = #tables_of_scores_by_type.completion_times_hard > 4 and tables_of_scores_by_type.completion_times_hard[4] or 9999999
|
|
local completion_times_nightmare_cutoff = #tables_of_scores_by_type.completion_times_hard > 2 and tables_of_scores_by_type.completion_times_hard[2] or 9999999
|
|
local completion_times_latestv_cutoff = #tables_of_scores_by_type.completion_times_latestv > 8 and tables_of_scores_by_type.completion_times_latestv[8] or 9999999
|
|
|
|
local leagues_travelled_cutoff = #tables_of_scores_by_type.leagues_travelled > 8 and tables_of_scores_by_type.leagues_travelled[-8] or 0
|
|
local leagues_travelled_mediump_latestv_cutoff = #tables_of_scores_by_type.leagues_travelled_mediump_latestv > 4 and tables_of_scores_by_type.leagues_travelled_mediump_latestv[-4] or 0
|
|
local leagues_travelled_hard_cutoff = #tables_of_scores_by_type.leagues_travelled_hard > 4 and tables_of_scores_by_type.leagues_travelled_hard[-4] or 0
|
|
local leagues_travelled_nightmare_cutoff = #tables_of_scores_by_type.leagues_travelled_hard > 2 and tables_of_scores_by_type.leagues_travelled_hard[-2] or 0
|
|
local leagues_travelled_latestv_cutoff = #tables_of_scores_by_type.leagues_travelled_latestv > 86 and tables_of_scores_by_type.leagues_travelled_latestv[-8] or 0
|
|
|
|
return {
|
|
completion_times_cutoff = completion_times_cutoff,
|
|
completion_times_mediump_latestv_cutoff = completion_times_mediump_latestv_cutoff,
|
|
completion_times_hard_cutoff = completion_times_hard_cutoff,
|
|
completion_times_nightmare_cutoff = completion_times_nightmare_cutoff,
|
|
completion_times_latestv_cutoff = completion_times_latestv_cutoff,
|
|
leagues_travelled_cutoff = leagues_travelled_cutoff,
|
|
leagues_travelled_mediump_latestv_cutoff = leagues_travelled_mediump_latestv_cutoff,
|
|
leagues_travelled_hard_cutoff = leagues_travelled_hard_cutoff,
|
|
leagues_travelled_nightmare_cutoff = leagues_travelled_nightmare_cutoff,
|
|
leagues_travelled_latestv_cutoff = leagues_travelled_latestv_cutoff,
|
|
}
|
|
end
|
|
|
|
local function saved_scores_trim(scores)
|
|
-- the goal here is to trim away highscores so we don't have too many.
|
|
|
|
local tables_of_scores_by_type = get_tables_of_scores_by_type(scores)
|
|
|
|
local cutoffs = get_score_cuttofs(tables_of_scores_by_type)
|
|
|
|
-- log(_inspect{completion_times_cutoff,completion_times_mediump_latestv_cutoff,completion_times_hard_cutoff,completion_times_latestv_cutoff,leagues_travelled_cutoff,leagues_travelled_mediump_latestv_cutoff,leagues_travelled_hard_cutoff,leagues_travelled_latestv_cutoff})
|
|
|
|
local delete = {}
|
|
|
|
for secs_id, score in pairs(scores) do
|
|
local include = false
|
|
|
|
if cutoffs.completion_times_cutoff and score.completion_time and score.completion_time < cutoffs.completion_times_cutoff then include = true
|
|
elseif cutoffs.completion_times_mediump_latestv_cutoff and score.completion_time and score.completion_time < cutoffs.completion_times_mediump_latestv_cutoff and type(score.version) == type(cutoffs.latest_version) and score.version == cutoffs.latest_version and score.difficulty >= 1 then include = true
|
|
elseif cutoffs.completion_times_hard_cutoff and score.completion_time and score.completion_time < cutoffs.completion_times_hard_cutoff and score.difficulty > 1 then include = true
|
|
elseif cutoffs.completion_times_nightmare_cutoff and score.completion_time and score.completion_time < cutoffs.completion_times_nightmare_cutoff and score.difficulty > 2 then include = true
|
|
elseif cutoffs.completion_times_latestv_cutoff and score.completion_time and score.completion_time < cutoffs.completion_times_latestv_cutoff and type(score.version) == type(cutoffs.latest_version) and score.version == cutoffs.latest_version then include = true
|
|
|
|
elseif cutoffs.leagues_travelled_cutoff and score.leagues_travelled and score.leagues_travelled > cutoffs.leagues_travelled_cutoff then include = true
|
|
elseif cutoffs.leagues_travelled_mediump_latestv_cutoff and score.leagues_travelled and score.leagues_travelled > cutoffs.leagues_travelled_mediump_latestv_cutoff and type(score.version) == type(cutoffs.latest_version) and score.version == cutoffs.latest_version and score.difficulty >= 1 then include = true
|
|
elseif cutoffs.leagues_travelled_hard_cutoff and score.leagues_travelled and score.leagues_travelled > cutoffs.leagues_travelled_hard_cutoff and score.difficulty > 1 then include = true
|
|
elseif cutoffs.leagues_travelled_nightmare_cutoff and score.leagues_travelled and score.leagues_travelled > cutoffs.leagues_travelled_nightmare_cutoff and score.difficulty > 2 then include = true
|
|
elseif cutoffs.leagues_travelled_latestv_cutoff and score.leagues_travelled and score.leagues_travelled > cutoffs.leagues_travelled_latestv_cutoff and type(score.version) == type(cutoffs.latest_version) and score.version == cutoffs.latest_version then include = true
|
|
end
|
|
|
|
if not include then delete[#delete + 1] = secs_id end
|
|
end
|
|
-- log(_inspect(delete))
|
|
|
|
for _, secs_id in pairs(delete) do
|
|
scores[secs_id] = nil
|
|
end
|
|
|
|
return scores
|
|
end
|
|
|
|
|
|
|
|
|
|
local function local_highscores_write_stats(crew_secs_id, name, captain_name, completion_time, leagues_travelled, version, difficulty, max_players)
|
|
|
|
if not this.score_table['player'] then this.score_table['player'] = {} end
|
|
if not this.score_table['player'].runs then this.score_table['player'].runs = {} end
|
|
|
|
local t = this.score_table['player']
|
|
|
|
if t then
|
|
-- if name then
|
|
-- t.name = name
|
|
-- end
|
|
-- if version then
|
|
-- t.version = version
|
|
-- end
|
|
-- if completion_time then
|
|
-- t.completion_time = completion_time
|
|
-- end
|
|
-- if leagues_travelled then
|
|
-- t.leagues_travelled = leagues_travelled
|
|
-- end
|
|
-- if difficulty then
|
|
-- t.difficulty = difficulty
|
|
-- end
|
|
-- if max_players then
|
|
-- t.max_players = max_players
|
|
-- end
|
|
|
|
if crew_secs_id then
|
|
t.runs[crew_secs_id] = {name = name, captain_name = captain_name, version = version, completion_time = completion_time, leagues_travelled = leagues_travelled, difficulty = difficulty, max_players = max_players}
|
|
|
|
-- log(_inspect(t))
|
|
|
|
saved_scores_trim(t.runs)
|
|
end
|
|
end
|
|
|
|
this.score_table['player'] = t
|
|
-- log(_inspect(t))
|
|
end
|
|
|
|
|
|
local load_in_scores =
|
|
Token.register(
|
|
function(data)
|
|
local value = data.value
|
|
if not this.score_table['player'] then
|
|
this.score_table['player'] = {}
|
|
end
|
|
|
|
this.score_table['player'] = value
|
|
end
|
|
)
|
|
function Public.load_in_scores()
|
|
local secs = Server.get_current_time()
|
|
-- if secs then game.print('secs2: ' .. secs) else game.print('secs: false') end
|
|
if not secs then
|
|
return
|
|
else
|
|
-- FULL CLEAN task (erases everything...):
|
|
-- server_set_data(score_dataset, score_key, {})
|
|
|
|
if is_game_modded() then
|
|
Server.try_get_data(score_dataset, score_key_modded, load_in_scores)
|
|
elseif _DEBUG then
|
|
Server.try_get_data(score_dataset, score_key_debug, load_in_scores)
|
|
else
|
|
Server.try_get_data(score_dataset, score_key, load_in_scores)
|
|
end
|
|
end
|
|
end
|
|
|
|
function Public.dump_highscores()
|
|
log(_inspect(this.score_table['player']))
|
|
end
|
|
|
|
function Public.overwrite_scores_specific()
|
|
-- the correct format is to put _everything_ from a dump into the third argument:
|
|
-- Server.set_data(score_dataset, score_key, )
|
|
-- return true
|
|
return true
|
|
end
|
|
|
|
function Public.write_score(crew_secs_id, name, captain_name, completion_time, leagues_travelled, version, difficulty, max_players)
|
|
local secs = Server.get_current_time()
|
|
-- if secs then game.print('secs1: ' .. secs) else game.print('secs: false') end
|
|
if not secs then
|
|
return
|
|
else
|
|
local_highscores_write_stats(crew_secs_id, name, captain_name, completion_time, leagues_travelled, version, difficulty, max_players)
|
|
|
|
if is_game_modded() then
|
|
Server.set_data(score_dataset, score_key_modded, this.score_table['player'])
|
|
elseif _DEBUG then
|
|
Server.set_data(score_dataset, score_key_debug, this.score_table['player'])
|
|
else
|
|
Server.set_data(score_dataset, score_key, this.score_table['player'])
|
|
end
|
|
end
|
|
end
|
|
|
|
local function on_init()
|
|
local secs = Server.get_current_time()
|
|
if not secs then
|
|
local_highscores_write_stats() --just to init tables presumably
|
|
return
|
|
end
|
|
end
|
|
|
|
|
|
local sorting_symbol = {ascending = '▲', descending = '▼'}
|
|
|
|
local function get_saved_scores_for_displaying()
|
|
local score_data = this.score_table['player']
|
|
local score_list = {}
|
|
|
|
if score_data and score_data.runs then
|
|
for _, score in pairs(score_data.runs or {}) do
|
|
insert(
|
|
score_list,
|
|
{
|
|
name = score and score.name,
|
|
captain_name = score and score.captain_name,
|
|
completion_time = score and score.completion_time or 99999,
|
|
leagues_travelled = score and score.leagues_travelled or 0,
|
|
version = score and score.version or 0,
|
|
difficulty = score and score.difficulty or 0,
|
|
max_players = score and score.max_players or 0,
|
|
}
|
|
)
|
|
end
|
|
else
|
|
score_list[#score_list + 1] = {
|
|
name = 'Nothing here yet',
|
|
captain_name = '',
|
|
completion_time = 0,
|
|
leagues_travelled = 0,
|
|
version = 0,
|
|
difficulty = 0,
|
|
max_players = 0,
|
|
}
|
|
end
|
|
|
|
return score_list
|
|
end
|
|
|
|
local function score_gui(data)
|
|
local player = data.player
|
|
local frame = data.frame
|
|
frame.clear()
|
|
|
|
local columnwidth = 96
|
|
|
|
-- local flow = frame.add {type = 'flow'}
|
|
-- local sFlow = flow.style
|
|
-- sFlow.horizontally_stretchable = true
|
|
-- sFlow.horizontal_align = 'center'
|
|
-- sFlow.vertical_align = 'center'
|
|
|
|
-- local stats = flow.add {type = 'label', caption = 'Highest score so far:'}
|
|
-- local s_stats = stats.style
|
|
-- s_stats.font = 'heading-1'
|
|
-- s_stats.font_color = {r = 0.98, g = 0.66, b = 0.22}
|
|
-- s_stats.horizontal_align = 'center'
|
|
-- s_stats.vertical_align = 'center'
|
|
|
|
-- -- Global stats : rockets, biters kills
|
|
-- add_global_stats(frame)
|
|
|
|
-- -- Separator
|
|
-- local line = frame.add {type = 'line'}
|
|
-- line.style.top_margin = 8
|
|
-- line.style.bottom_margin = 8
|
|
|
|
-- Score per player
|
|
local t = frame.add {type = 'table', column_count = 7}
|
|
|
|
-- Score headers
|
|
local headers = {
|
|
{name = '_name', caption = {'pirates.highscore_heading_crew'}},
|
|
{column = 'captain_name', name = '_captain_name', caption = {'pirates.highscore_heading_captain'}, tooltip = {'pirates.highscore_heading_captain_tooltip'}},
|
|
{column = 'completion_time', name = '_completion_time', caption = {'pirates.highscore_heading_completion'}},
|
|
{column = 'leagues_travelled', name = '_leagues_travelled', caption = {'pirates.highscore_heading_leagues'}},
|
|
{column = 'version', name = '_version', caption = {'pirates.highscore_heading_version'}},
|
|
{column = 'difficulty', name = '_difficulty', caption = {'pirates.highscore_heading_difficulty'}},
|
|
{column = 'max_players', name = '_max_players', caption = {'pirates.highscore_heading_peak_players'}},
|
|
}
|
|
|
|
local sorting_pref = this.sort_by[player.index] or {}
|
|
for _, header in ipairs(headers) do
|
|
local cap = header.caption
|
|
|
|
-- log(header.caption)
|
|
|
|
-- Add sorting symbol if any
|
|
if header.column and sorting_pref[1] and sorting_pref[1].column == header.column then
|
|
local symbol = sorting_symbol[sorting_pref[1].method]
|
|
cap = {'', symbol, cap}
|
|
end
|
|
|
|
-- Header
|
|
local label =
|
|
t.add {
|
|
type = 'label',
|
|
caption = cap,
|
|
name = header.name
|
|
}
|
|
if header.tooltip then label.tooltip = header.tooltip end
|
|
label.style.font = 'default-listbox'
|
|
label.style.font_color = {r = 0.98, g = 0.66, b = 0.22} -- yellow
|
|
label.style.minimal_width = columnwidth
|
|
label.style.horizontal_align = 'right'
|
|
end
|
|
|
|
-- Score list
|
|
local score_list = get_saved_scores_for_displaying()
|
|
-- log(_inspect(score_list))
|
|
|
|
for i = #sorting_pref, 1, -1 do
|
|
local sort = sorting_pref[i]
|
|
if sort then
|
|
-- log(_inspect(score_list))
|
|
score_list = sort_list(sort.method, sort.column, score_list)
|
|
end
|
|
end
|
|
|
|
-- New pane for scores (while keeping headers at same position)
|
|
local scroll_pane =
|
|
frame.add(
|
|
{
|
|
type = 'scroll-pane',
|
|
name = 'score_scroll_pane',
|
|
direction = 'vertical',
|
|
horizontal_scroll_policy = 'never',
|
|
vertical_scroll_policy = 'auto'
|
|
}
|
|
)
|
|
scroll_pane.style.maximal_height = 400
|
|
t = scroll_pane.add {type = 'table', column_count = 7}
|
|
|
|
-- Score entries
|
|
for _, entry in pairs(score_list) do
|
|
local p = {color = {r = Math.random(1, 255), g = Math.random(1, 255), b = Math.random(1, 255)}}
|
|
-- local p
|
|
-- if not (entry and entry.name) then
|
|
-- p = {color = {r = random(1, 255), g = random(1, 255), b = random(1, 255)}}
|
|
-- else
|
|
-- p = game.players[entry.name]
|
|
-- if not p then
|
|
-- p = {color = {r = random(1, 255), g = random(1, 255), b = random(1, 255)}}
|
|
-- end
|
|
-- end
|
|
local special_color = {
|
|
r = p.color.r * 0.6 + 0.4,
|
|
g = p.color.g * 0.6 + 0.4,
|
|
b = p.color.b * 0.6 + 0.4,
|
|
a = 1,
|
|
}
|
|
|
|
-- displayforms:
|
|
local n = entry.completion_time > 0 and Utils.time_mediumform(entry.completion_time or 0) or 'N/A'
|
|
local l = entry.leagues_travelled > 0 and entry.leagues_travelled or '?'
|
|
local v = entry.version and entry.version or '?'
|
|
local d = entry.difficulty > 0 and CoreData.difficulty_options[CoreData.get_difficulty_option_from_value(entry.difficulty)].text or '?'
|
|
local c = entry.max_players > 0 and entry.max_players or '?'
|
|
local line = {
|
|
{caption = entry.name, color = special_color},
|
|
{caption = entry.captain_name or '?'},
|
|
{caption = tostring(n)},
|
|
{caption = tostring(l)},
|
|
{caption = tostring(v)},
|
|
{caption = d},
|
|
{caption = tostring(c)},
|
|
}
|
|
local default_color = {r = 0.9, g = 0.9, b = 0.9}
|
|
|
|
for _, column in ipairs(line) do
|
|
local label =
|
|
t.add {
|
|
type = 'label',
|
|
caption = column.caption,
|
|
color = column.color or default_color,
|
|
}
|
|
label.style.font = 'default'
|
|
label.style.minimal_width = columnwidth
|
|
label.style.maximal_width = columnwidth
|
|
label.style.horizontal_align = 'right'
|
|
end -- foreach column
|
|
end -- foreach entry
|
|
end
|
|
|
|
local score_gui_token = Token.register(score_gui)
|
|
|
|
local function on_gui_click(event)
|
|
if not event.element then return end
|
|
if not event.element.valid then return end
|
|
|
|
local player = game.get_player(event.element.player_index)
|
|
|
|
local frame = Gui.get_player_active_frame(player)
|
|
if not frame then
|
|
return
|
|
end
|
|
if frame.name ~= 'Highscore' then
|
|
return
|
|
end
|
|
|
|
local is_spamming = SpamProtection.is_spamming(player, nil, 'HighScore Gui Click')
|
|
if is_spamming then
|
|
return
|
|
end
|
|
|
|
local name = event.element.name
|
|
|
|
-- Handles click on a score header
|
|
local element_to_column = {
|
|
['_captain_name'] = 'captain_name',
|
|
['_version'] = 'version',
|
|
['_completion_time'] = 'completion_time',
|
|
['_leagues_travelled'] = 'leagues_travelled',
|
|
['_difficulty'] = 'difficulty',
|
|
['_max_players'] = 'max_players',
|
|
}
|
|
if element_to_column[name] then
|
|
--@TODO: Extend
|
|
local sorting_pref = this.sort_by[player.index]
|
|
local found_index = nil
|
|
local new_method = 'descending'
|
|
|
|
for i, sort in ipairs(sorting_pref) do
|
|
if sort.column == element_to_column[name] then
|
|
found_index = i
|
|
if sort.method == 'descending' and i==1 then new_method = 'ascending' end
|
|
end
|
|
end
|
|
if found_index then
|
|
--remove this and shuffle everything before it up by 1:
|
|
for j = found_index, 2, -1 do
|
|
sorting_pref[j] = Utils.deepcopy(sorting_pref[j-1]) --deepcopy just as I'm slightly unsure about refernces here
|
|
end
|
|
else
|
|
--prepend:
|
|
for j = #sorting_pref + 1, 2, -1 do
|
|
sorting_pref[j] = Utils.deepcopy(sorting_pref[j-1]) --deepcopy just as I'm slightly unsure about references here
|
|
end
|
|
end
|
|
sorting_pref[1] = {column = element_to_column[name], method = new_method}
|
|
|
|
score_gui({player = player, frame = frame})
|
|
return
|
|
end
|
|
end
|
|
|
|
local function on_player_joined_game(event)
|
|
local player = game.players[event.player_index]
|
|
if player.index and this.sort_by and (not this.sort_by[player.index]) then
|
|
this.sort_by[player.index] = {{method = 'ascending', column = 'completion_time'}, {method = 'descending', column = 'leagues_travelled'}, {method = 'descending', column = 'version'}, {method = 'descending', column = 'difficulty'}, {method = 'ascending', column = 'captain_name'}}
|
|
end
|
|
end
|
|
|
|
local function on_player_left_game(event)
|
|
local player = game.players[event.player_index]
|
|
if this.sort_by[player.index] then
|
|
this.sort_by[player.index] = nil
|
|
end
|
|
end
|
|
|
|
Server.on_data_set_changed(
|
|
score_dataset,
|
|
function(data)
|
|
local key
|
|
if is_game_modded() then
|
|
key = score_key_modded
|
|
elseif _DEBUG then
|
|
key = score_key_debug
|
|
else
|
|
key = score_key
|
|
end
|
|
if data.key == key then
|
|
if data.value then
|
|
this.score_table['player'] = data.value
|
|
end
|
|
end
|
|
end
|
|
)
|
|
|
|
Gui.add_tab_to_gui({name = module_name, caption = 'Highscore', id = score_gui_token, admin = false, only_server_sided = true})
|
|
|
|
Gui.on_click(
|
|
module_name,
|
|
function(event)
|
|
local player = event.player
|
|
Gui.reload_active_tab(player)
|
|
end
|
|
)
|
|
|
|
Event.on_init(on_init)
|
|
Event.add(defines.events.on_player_left_game, on_player_left_game)
|
|
Event.add(defines.events.on_player_joined_game, on_player_joined_game)
|
|
Event.add(defines.events.on_gui_click, on_gui_click)
|
|
Event.add(Server.events.on_server_started, Public.load_in_scores)
|
|
|
|
return Public |