Intial Commit
This commit is contained in:
132
mods/updateplz/42.13/media/lua/server/updateplz.lua
Normal file
132
mods/updateplz/42.13/media/lua/server/updateplz.lua
Normal file
@@ -0,0 +1,132 @@
|
||||
local getTimestamp = getTimestamp
|
||||
local querySteamWorkshopItemDetails = querySteamWorkshopItemDetails
|
||||
local getSteamWorkshopItemIDs = getSteamWorkshopItemIDs
|
||||
local getOnlinePlayers = getOnlinePlayers
|
||||
local getCore = getCore
|
||||
|
||||
if not getCore():isDedicated() then
|
||||
print("[UpdatePLZ] Refusing to load (this is not a dedicated server)")
|
||||
return
|
||||
end
|
||||
|
||||
UpdatePLZ = UpdatePLZ or {}
|
||||
|
||||
local serverStarted = getTimestamp()
|
||||
local pendingReboot = false
|
||||
|
||||
function UpdatePLZ.setRestartDelaySeconds(delay)
|
||||
print("[UpdatePLZ] Restart delay set to " .. delay .. " seconds")
|
||||
UpdatePLZ.restartDelay = delay
|
||||
end
|
||||
|
||||
local function isServerEmpty()
|
||||
return getOnlinePlayers():size() == 0
|
||||
end
|
||||
|
||||
local rebootServer do
|
||||
local rebootingNow = false
|
||||
function rebootServer()
|
||||
if rebootingNow then return end
|
||||
rebootingNow = true
|
||||
|
||||
print("[UpdatePLZ] Saving...")
|
||||
saveGame()
|
||||
|
||||
print("[UpdatePLZ] Quitting...")
|
||||
getCore():quit()
|
||||
end
|
||||
end
|
||||
|
||||
local restartingAt
|
||||
local scheduleServerRestart do
|
||||
ModData.remove("UpdatePLZ")
|
||||
|
||||
Events.OnInitGlobalModData.Add(function()
|
||||
if restartingAt then
|
||||
ModData.add("UpdatePLZ", { restartingAt = restartingAt })
|
||||
ModData.transmit("UpdatePLZ")
|
||||
else
|
||||
ModData.remove("UpdatePLZ")
|
||||
end
|
||||
end)
|
||||
|
||||
function scheduleServerRestart(timestamp)
|
||||
restartingAt = timestamp
|
||||
ModData.add("UpdatePLZ", { restartingAt = timestamp })
|
||||
ModData.transmit("UpdatePLZ")
|
||||
UpdatePLZ.startRestartCountdown(timestamp)
|
||||
end
|
||||
end
|
||||
|
||||
local function rebootWhenEmpty()
|
||||
if pendingReboot and isServerEmpty() then
|
||||
rebootServer()
|
||||
Events.OnTickEvenPaused.Remove(rebootWhenEmpty)
|
||||
end
|
||||
end
|
||||
|
||||
local function workshopOutdated()
|
||||
if pendingReboot then return end
|
||||
pendingReboot = true
|
||||
|
||||
if isServerEmpty() then
|
||||
print("[UpdatePLZ] Restarting the server (server empty and outdated Workshop items were detected)")
|
||||
rebootServer()
|
||||
return
|
||||
end
|
||||
|
||||
if UpdatePLZ.restartDelay then
|
||||
print("[UpdatePLZ] Detected outdated Workshop item - restarting server in " .. UpdatePLZ.minutes(UpdatePLZ.restartDelay))
|
||||
scheduleServerRestart(getTimestamp() + UpdatePLZ.restartDelay)
|
||||
else
|
||||
print("[UpdatePLZ] Restarting the server when it becomes empty... (outdated Workshop items were detected)")
|
||||
Events.OnTickEvenPaused.Add(rebootWhenEmpty)
|
||||
end
|
||||
end
|
||||
|
||||
local pollWorkshop do
|
||||
local fakeTable = {}
|
||||
function pollWorkshop()
|
||||
if pendingReboot then return end
|
||||
|
||||
print("[UpdatePLZ] Checking for outdated Workshop items...")
|
||||
|
||||
querySteamWorkshopItemDetails(getSteamWorkshopItemIDs(), function(_, status, info)
|
||||
if status ~= "Completed" then return end
|
||||
for i = 0, info:size() - 1 do
|
||||
local details = info:get(i)
|
||||
local updated = details:getTimeUpdated()
|
||||
if updated >= serverStarted then
|
||||
workshopOutdated()
|
||||
return
|
||||
end
|
||||
end
|
||||
end, fakeTable)
|
||||
end
|
||||
end
|
||||
Events.OnDisconnect.Add(pollWorkshop)
|
||||
|
||||
local nextPoll
|
||||
Events.OnTickEvenPaused.Add(function()
|
||||
if restartingAt then
|
||||
if isServerEmpty() then
|
||||
print("[UpdatePLZ] Restarting the server now! (Outdated Workshop items were detected and server is empty)")
|
||||
rebootServer()
|
||||
elseif restartingAt - getTimestamp() <= 0 then
|
||||
print("[UpdatePLZ] Restarting the server now! (Outdated Workshop items were detected)")
|
||||
rebootServer()
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
if pendingReboot then return end
|
||||
|
||||
-- Don't bother checking for outdated Workshop items if there's no restart delay and the server has players on it
|
||||
if not UpdatePLZ.restartDelay and not isServerEmpty() then return end
|
||||
|
||||
local timestamp = getTimestamp()
|
||||
if not nextPoll or getTimestamp() >= nextPoll then
|
||||
nextPoll = timestamp + 60
|
||||
return pollWorkshop()
|
||||
end
|
||||
end)
|
||||
88
mods/updateplz/42.13/media/lua/shared/updateplz.lua
Normal file
88
mods/updateplz/42.13/media/lua/shared/updateplz.lua
Normal file
@@ -0,0 +1,88 @@
|
||||
local getTimestamp = getTimestamp
|
||||
local isServer = getCore():isDedicated()
|
||||
|
||||
UpdatePLZ = UpdatePLZ or {}
|
||||
|
||||
local chat do
|
||||
if isServer then
|
||||
chat = print
|
||||
else
|
||||
require "client/Chat/ISChat.lua"
|
||||
|
||||
local chatMsg = {
|
||||
getTextWithPrefix = function(self)
|
||||
return self.msg
|
||||
end,
|
||||
|
||||
getText = function(self)
|
||||
return self.msg
|
||||
end,
|
||||
|
||||
isServerAlert = function() return true end,
|
||||
isShowAuthor = function() return false end,
|
||||
getAuthor = function() return "SERVER" end
|
||||
}
|
||||
|
||||
chatMsg.__index = chatMsg
|
||||
|
||||
function chat(...)
|
||||
local msg = table.concat({...}, "\t")
|
||||
ISChat.addLineInChat(setmetatable({ msg = msg }, chatMsg), 0)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function UpdatePLZ.minutes(secs)
|
||||
if secs < 60 then
|
||||
if secs == 1 then
|
||||
return secs .. " second"
|
||||
else
|
||||
return secs .. " seconds"
|
||||
end
|
||||
else
|
||||
if secs / 60 == 1 then
|
||||
return "1 minute"
|
||||
else
|
||||
return (string.gsub(string.gsub(string.format("%.2f", secs / 60), "(%.%d-)0*$", "%1"), "%.$", "")) .. " minutes"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local restartingAt
|
||||
local nextChatPrint
|
||||
local function countdown()
|
||||
local time = getTimestamp()
|
||||
local delta = restartingAt - time
|
||||
if not nextChatPrint or nextChatPrint - time <= 0 then
|
||||
nextChatPrint = time + math.min(delta / 2, 60 * 15)
|
||||
|
||||
if math.floor(delta / 60) <= 0 then
|
||||
chat("WARNING: Server is restarting to update Workshop mods!")
|
||||
Events.OnTickEvenPaused.Remove(countdown)
|
||||
else
|
||||
chat("WARNING: Server is restarting in " .. UpdatePLZ.minutes(delta) .. " to update Workshop mods")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function UpdatePLZ.startRestartCountdown(__restartingAt)
|
||||
nextChatPrint = nil
|
||||
restartingAt = __restartingAt
|
||||
if restartingAt then
|
||||
Events.OnTickEvenPaused.Add(countdown)
|
||||
else
|
||||
Events.OnTickEvenPaused.Remove(countdown)
|
||||
end
|
||||
end
|
||||
|
||||
if not isServer then
|
||||
Events.OnInitGlobalModData.Add(function()
|
||||
Events.OnReceiveGlobalModData.Add(function(key, modData)
|
||||
if key == "UpdatePLZ" then
|
||||
UpdatePLZ.startRestartCountdown(modData and modData.restartingAt or nil)
|
||||
end
|
||||
end)
|
||||
|
||||
ModData.request("UpdatePLZ")
|
||||
end)
|
||||
end
|
||||
3
mods/updateplz/42.13/mod.info
Normal file
3
mods/updateplz/42.13/mod.info
Normal file
@@ -0,0 +1,3 @@
|
||||
name=Update PLZ
|
||||
id=UpdatePlz
|
||||
description=Restart the (empty) dedicated server if mods are outdated
|
||||
Reference in New Issue
Block a user