Skip to content

Commit

Permalink
Merge branch 'master' into patch-7
Browse files Browse the repository at this point in the history
  • Loading branch information
LoneWolfHT authored Aug 17, 2024
2 parents 846bcd3 + 911b741 commit e4eeefe
Show file tree
Hide file tree
Showing 16 changed files with 248 additions and 77 deletions.
2 changes: 1 addition & 1 deletion mods/ctf/ctf_modebase/features.lua
Original file line number Diff line number Diff line change
Expand Up @@ -831,7 +831,7 @@ return {
local rank = rankings:get(pname)
local player = minetest.get_player_by_name(pname)
local pro_chest = player and player:get_meta():get_int("ctf_rankings:pro_chest:"..
(ctf_modebase.current_mode or "")) == 1
(ctf_modebase.current_mode or "")) >= 1
local deny_pro = "You need to have more than 1.4 kills per death, "..
"5 captures, and at least 8,000 score to access the pro section."
if rank then
Expand Down
12 changes: 11 additions & 1 deletion mods/ctf/ctf_modebase/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,17 @@ minetest.register_on_mods_loaded(function()
player:set_nametag_attributes({color = {a = 0, r = 255, g = 255, b = 255}, text = ""})
end)
elseif ctf_core.settings.server_mode == "play" then
minetest.after(3, ctf_modebase.start_new_match)
minetest.chat_send_all("[CTF] Sorting rankings...")
local function check()
if not ctf_rankings:rankings_sorted() then
return minetest.after(1, check)
end

minetest.chat_send_all("[CTF] Rank sorting done. Starting new match...")
ctf_modebase.start_new_match()
end

check()
end

for _, name in pairs(ctf_modebase.modelist) do
Expand Down
2 changes: 1 addition & 1 deletion mods/ctf/ctf_modebase/player.lua
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ if minetest.register_on_item_pickup then

if cprio and cprio < priority then
local item, typ = simplify_for_saved_stuff(compare:get_name())
minetest.log(dump(item)..dump(typ))
--minetest.log(dump(item)..dump(typ))
inv:set_stack("main", i, itemstack)

if item == "sword" and typ == "stone" and
Expand Down
2 changes: 1 addition & 1 deletion mods/ctf/ctf_modes/ctf_mode_classes/init.lua
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
local rankings = ctf_rankings.init()
local rankings = ctf_rankings:init()
local recent_rankings = ctf_modebase.recent_rankings(rankings)
local features = ctf_modebase.features(rankings, recent_rankings)

Expand Down
2 changes: 1 addition & 1 deletion mods/ctf/ctf_modes/ctf_mode_classic/init.lua
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
local rankings = ctf_rankings.init()
local rankings = ctf_rankings:init()
local recent_rankings = ctf_modebase.recent_rankings(rankings)
local features = ctf_modebase.features(rankings, recent_rankings)

Expand Down
2 changes: 1 addition & 1 deletion mods/ctf/ctf_modes/ctf_mode_nade_fight/init.lua
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
local rankings = ctf_rankings.init()
local rankings = ctf_rankings:init()
local recent_rankings = ctf_modebase.recent_rankings(rankings)
local features = ctf_modebase.features(rankings, recent_rankings)

Expand Down
55 changes: 48 additions & 7 deletions mods/ctf/ctf_rankings/default.lua
Original file line number Diff line number Diff line change
@@ -1,22 +1,63 @@
return function(prefix, top)
return function(prefix, top, sorting_finished)

local modstorage = assert(minetest.get_mod_storage(), "Can only init rankings at runtime!")

local function op_all(operation)
for k, v in pairs(modstorage:to_table()["fields"]) do
operation(k, v)
-- If callback isn't passed then coroutine will never yield
local function op_all(operation, callback)
if not callback then
minetest.log("warning", "op_all() called without callback, it will block the server step until it finishes")
end

local TARGET_INTERVAL = 0.1
local interval = 0.05
local time = minetest.get_us_time()
local times = 0
local keys = modstorage:to_table()["fields"]
local c = coroutine.wrap(function()
for k, v in pairs(keys) do
times = times + 1
operation(k, v)

if callback and ((minetest.get_us_time()-time) / 1e6) >= interval then
coroutine.yield()
end
end
end)

local function rep()
if ((minetest.get_us_time()-time) / 1e6) > TARGET_INTERVAL then
interval = interval - 0.01
else
interval = interval + 0.01
end
time = minetest.get_us_time()

if c() ~= "done" then
minetest.after(0, rep)
elseif callback then
assert(times == #keys, dump(#keys - times).." | "..dump(times).." | "..dump(#keys))
callback()
end
end

rep()
end

local timer = minetest.get_us_time()
op_all(function(key, value)
op_all(function(noprefix_key, value)
local rank = minetest.parse_json(value)

if rank ~= nil and rank.score then
top:set(key, rank.score)
top:set(noprefix_key, rank.score)
end
end,
function()
minetest.log(
"action",
"Sorted rankings by score '"..prefix:sub(1, -2).."'. Took "..((minetest.get_us_time()-timer) / 1e6)
)
sorting_finished()
end)
minetest.log("action", "Sorted rankings database. Took "..((minetest.get_us_time()-timer) / 1e6))

return {
backend = "default",
Expand Down
43 changes: 41 additions & 2 deletions mods/ctf/ctf_rankings/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,34 @@ else
end

ctf_rankings = {
init = function()
return rankings(minetest.get_current_modname() .. '|', top:new())
sorted = {},

rankings_sorted = function(self)
return false -- Returning false, since not all rankings are sorted yet. See below for full func
end,

init = function(self)
local modname = minetest.get_current_modname()

if self then
self.sorted[modname] = false
else
minetest.log(
"error",
"[ctf_rankings] The mode "..modname.." is calling the init() function wrong. Use ':' instead of '.'"
)
end

return rankings(modname .. '|', top:new(), function()
if self then
self.sorted[modname] = true
else
minetest.log(
"error",
"[ctf_rankings] The mode "..modname.." is calling the init() function wrong. Use ':' instead of '.'"
)
end
end)
end,

registered_on_rank_reset = {},
Expand Down Expand Up @@ -64,8 +90,21 @@ end
---@param func function
--- * pname
--- * rank
--- * mode name
function ctf_rankings.register_on_rank_reset(func)
table.insert(ctf_rankings.registered_on_rank_reset, func)
end

minetest.register_on_mods_loaded(function()
ctf_rankings.rankings_sorted = function(self)
for _, sorted in pairs(self.sorted) do
if not sorted then
return false
end
end

return true
end
end)

ctf_core.include_files("leagues.lua", "ranking_reset.lua")
10 changes: 9 additions & 1 deletion mods/ctf/ctf_rankings/leagues.lua
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,16 @@ minetest.register_on_joinplayer(function(player)
end
end

if not rank.place or not leagues[mode] then
mods:set_string("rank:"..pname, "")
end

if rank._pro_chest then
meta:set_int("ctf_rankings:pro_chest:"..mode, 1)
if rank._pro_chest == true then
meta:set_int("ctf_rankings:pro_chest:"..mode, 1)
else
meta:set_int("ctf_rankings:pro_chest:"..mode, rank._pro_chest)
end
end
end

Expand Down
124 changes: 77 additions & 47 deletions mods/ctf/ctf_rankings/ranking_reset.lua
Original file line number Diff line number Diff line change
Expand Up @@ -23,77 +23,105 @@ ctf_rankings.do_reset = mods:get_int("_do_reset") == 1
-- Resets taking place on the same month will overwrite each other
local PLAYER_RANKING_PREFIX = "rank:"

if ctf_rankings.do_reset then
local after_timer = 0
local function do_reset()
local finish_count = 0
local function finish()
finish_count = finish_count - 1

minetest.after(5, function()
for mode, def in pairs(ctf_modebase.modes) do
local top = def.rankings.top
local time = minetest.get_us_time()
def.rankings.op_all(function(pname, value)
if value ~= "null" then
local rank = minetest.parse_json(value)
if finish_count == 0 then
mods:set_int("_do_reset", 0)
mods:set_int("_current_reset", mods:get_int("_current_reset") + 1)

rank.place = top:get_place(pname)
minetest.request_shutdown("Ranking reset done. Thank you for your patience", true, 5)
end
end

RunCallbacks(ctf_rankings.registered_on_rank_reset, pname, rank)
for mode, def in pairs(ctf_modebase.modes) do
local top = def.rankings.top
local time = minetest.get_us_time()

if (rank.score or 0) >= 8000 and
(rank.kills or 0) / (rank.deaths or 1) >= 1.4 and
(rank.flag_captures or 0) >= 5 then
rank._pro_chest = true
end
finish_count = finish_count + 1

def.rankings.op_all(function(pname, value)
local rank = minetest.parse_json(value)

if rank then
rank.place = top:get_place(pname)

local current = mods:get_string(PLAYER_RANKING_PREFIX..pname)
RunCallbacks(ctf_rankings.registered_on_rank_reset, pname, table.copy(rank), mode)

if current and current ~= "" then
current = minetest.parse_json(current)
if (rank.score or 0) >= 8000 and
(rank.kills or 0) / (rank.deaths or 1) >= 1.4 and
(rank.flag_captures or 0) >= 5 then
rank._pro_chest = os.time()
end

local current = mods:get_string(PLAYER_RANKING_PREFIX..pname)

if current and current ~= "" then
current = minetest.parse_json(current)

current._last_reset = os.date("%m/%Y")
current[os.date("%m/%Y")][mode] = rank
current._last_reset = os.date("%m/%Y")

mods:set_string(PLAYER_RANKING_PREFIX..pname, minetest.write_json(current))
else
mods:set_string(PLAYER_RANKING_PREFIX..pname, minetest.write_json({
_last_reset = os.date("%m/%Y"),
[os.date("%m/%Y")] = {[mode] = rank},
}))
if not current[os.date("%m/%Y")] then
current[os.date("%m/%Y")] = {}
end

minetest.chat_send_all(string.format("[%s] %d: %s with %d score", mode, rank.place, pname, rank.score or 0))
current[os.date("%m/%Y")][mode] = rank

mods:set_string(PLAYER_RANKING_PREFIX..pname, minetest.write_json(current))
else
mods:set_string(PLAYER_RANKING_PREFIX..pname, minetest.write_json({
_last_reset = os.date("%m/%Y"),
[os.date("%m/%Y")] = {[mode] = rank},
}))
end
end)

after_timer = after_timer + ((minetest.get_us_time()-time) / 1e6)
minetest.chat_send_all(string.format("[%s] %d: %s with %d score", mode, rank.place, pname, rank.score or 0))
end
end,
function()
time = ((minetest.get_us_time()-time) / 1e6).."s"

minetest.chat_send_all("Saved old rankings for mode "..mode..". Took "..time)
minetest.log("action", "Saved old rankings for mode "..mode..". Took "..time)
end

for mode, def in pairs(ctf_modebase.modes) do
local time = minetest.get_us_time()
def.rankings.op_all(function(pname, value)
def.rankings:del(pname)
local t = minetest.get_us_time()
def.rankings.op_all(
function(pname, value)
def.rankings:del(pname)

minetest.chat_send_all(string.format("[%s] Reset rankings of player %s", mode, pname))
end)
minetest.chat_send_all(string.format("[%s] Reset rankings of player %s", mode, pname))
end,
function()
t = ((minetest.get_us_time()-t) / 1e6).."s"

after_timer = after_timer + ((minetest.get_us_time()-time) / 1e6)
time = ((minetest.get_us_time()-time) / 1e6).."s"
minetest.chat_send_all("Reset rankings for mode "..mode..". Took "..t)
minetest.log("action", "Reset rankings for mode "..mode..". Took "..t)

minetest.chat_send_all("Reset rankings for mode "..mode..". Took "..time)
minetest.log("action", "Reset rankings for mode "..mode..". Took "..time)
end
minetest.after(1, finish) -- wait in case for some reason not all the resets were queued
end
)
end)
end
end

local function check()
if ctf_rankings:rankings_sorted() then
do_reset()
else
minetest.after(1, check)
end
end

mods:set_int("_do_reset", 0)
mods:set_int("_current_reset", mods:get_int("_current_reset") + 1)
minetest.request_shutdown("Ranking reset done. Thank you for your patience", true, after_timer + 5)
if ctf_rankings.do_reset then
minetest.register_on_mods_loaded(function()
check()
end)
end

if mods:get_int("_reset_date") ~= 0 and os.date("*t", mods:get_int("_reset_date")).month == os.date("*t").month then
local CHECK_INTERVAL = 60 * 50 -- 50 minutes
local CHECK_INTERVAL = 60 * 30 -- 30 minutes
local timer = CHECK_INTERVAL
minetest.register_globalstep(function(dtime)
timer = timer + dtime
Expand All @@ -110,8 +138,10 @@ if mods:get_int("_reset_date") ~= 0 and os.date("*t", mods:get_int("_reset_date"
if hours_left > 0 then
if hours_left == 6 then
ctf_report.send_report("[RANKING RESET] The queued ranking reset will happen in ~6 hours")
minetest.chat_send_all("[RANKING RESET] The queued ranking reset will happen in ~6 hours")
elseif hours_left == 1 then
ctf_report.send_report("[RANKING RESET] The queued ranking reset will happen in 1 hour")
minetest.chat_send_all("[RANKING RESET] The queued ranking reset will happen in 1 hour")

CHECK_INTERVAL = (61 - current.min) * 60

Expand All @@ -126,7 +156,7 @@ if mods:get_int("_reset_date") ~= 0 and os.date("*t", mods:get_int("_reset_date"
ctf_rankings.do_reset = true

minetest.registered_chatcommands["queue_restart"].func("[RANKING RESET]",
"There will be another restart once the ranking reset is done."
"Ranking Reset"
)
end
end
Expand Down
Loading

0 comments on commit e4eeefe

Please sign in to comment.