Intial Commit

This commit is contained in:
2026-02-16 11:54:35 -05:00
parent a738551e6b
commit 2bb6fe4f86
38 changed files with 585 additions and 2 deletions

View 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)

View 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

View File

@@ -0,0 +1,3 @@
name=Update PLZ
id=UpdatePlz
description=Restart the (empty) dedicated server if mods are outdated

View File

@@ -0,0 +1,3 @@
name=Update PLZ
id=UpdatePlz
description=Restart the (empty) dedicated server if mods are outdated

View 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)

View 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/mod.info Normal file
View File

@@ -0,0 +1,3 @@
name=Update PLZ
id=UpdatePlz
description=Restart the (empty) dedicated server if mods are outdated

View File

@@ -0,0 +1,3 @@
require "updateplz.lua"
if not getCore():isDedicated() then return end
UpdatePLZ.setRestartDelaySeconds(60)

View File

@@ -0,0 +1,4 @@
name=Update PLZ (1 minute)
id=UpdatePlz1
description=Restart the dedicated server if mods are outdated after 1 minute
require=UpdatePlz

View File

@@ -0,0 +1,4 @@
name=Update PLZ (1 minute)
id=UpdatePlz1
description=Restart the dedicated server if mods are outdated after 1 minute
require=UpdatePlz

View File

@@ -0,0 +1,3 @@
require "updateplz.lua"
if not getCore():isDedicated() then return end
UpdatePLZ.setRestartDelaySeconds(60)

4
mods/updateplz1/mod.info Normal file
View File

@@ -0,0 +1,4 @@
name=Update PLZ (1 minute)
id=UpdatePlz1
description=Restart the dedicated server if mods are outdated after 1 minute
require=UpdatePlz

View File

@@ -0,0 +1,3 @@
require "updateplz.lua"
if not getCore():isDedicated() then return end
UpdatePLZ.setRestartDelaySeconds(10 * 60)

View File

@@ -0,0 +1,4 @@
name=Update PLZ (10 minutes)
id=UpdatePlz10
description=Restart the dedicated server if mods are outdated after 10 minutes
require=UpdatePlz

View File

@@ -0,0 +1,4 @@
name=Update PLZ (10 minutes)
id=UpdatePlz10
description=Restart the dedicated server if mods are outdated after 10 minutes
require=UpdatePlz

View File

@@ -0,0 +1,3 @@
require "updateplz.lua"
if not getCore():isDedicated() then return end
UpdatePLZ.setRestartDelaySeconds(10 * 60)

View File

@@ -0,0 +1,4 @@
name=Update PLZ (10 minutes)
id=UpdatePlz10
description=Restart the dedicated server if mods are outdated after 10 minutes
require=UpdatePlz

View File

@@ -0,0 +1,3 @@
require "updateplz.lua"
if not getCore():isDedicated() then return end
UpdatePLZ.setRestartDelaySeconds(15 * 60)

View File

@@ -0,0 +1,4 @@
name=Update PLZ (15 minutes)
id=UpdatePlz15
description=Restart the dedicated server if mods are outdated after 15 minutes
require=UpdatePlz

View File

@@ -0,0 +1,4 @@
name=Update PLZ (15 minutes)
id=UpdatePlz15
description=Restart the dedicated server if mods are outdated after 15 minutes
require=UpdatePlz

View File

@@ -0,0 +1,3 @@
require "updateplz.lua"
if not getCore():isDedicated() then return end
UpdatePLZ.setRestartDelaySeconds(15 * 60)

View File

@@ -0,0 +1,4 @@
name=Update PLZ (15 minutes)
id=UpdatePlz15
description=Restart the dedicated server if mods are outdated after 15 minutes
require=UpdatePlz

View File

@@ -0,0 +1,3 @@
require "updateplz.lua"
if not getCore():isDedicated() then return end
UpdatePLZ.setRestartDelaySeconds(30 * 60)

View File

@@ -0,0 +1,4 @@
name=Update PLZ (30 minutes)
id=UpdatePlz30
description=Restart the dedicated server if mods are outdated after 30 minutes
require=UpdatePlz

View File

@@ -0,0 +1,4 @@
name=Update PLZ (30 minutes)
id=UpdatePlz30
description=Restart the dedicated server if mods are outdated after 30 minutes
require=UpdatePlz

View File

@@ -0,0 +1,3 @@
require "updateplz.lua"
if not getCore():isDedicated() then return end
UpdatePLZ.setRestartDelaySeconds(30 * 60)

View File

@@ -0,0 +1,4 @@
name=Update PLZ (30 minutes)
id=UpdatePlz30
description=Restart the dedicated server if mods are outdated after 30 minutes
require=UpdatePlz

View File

@@ -0,0 +1,3 @@
require "updateplz.lua"
if not getCore():isDedicated() then return end
UpdatePLZ.setRestartDelaySeconds(5 * 60)

View File

@@ -0,0 +1,4 @@
name=Update PLZ (5 minutes)
id=UpdatePlz5
description=Restart the dedicated server if mods are outdated after 5 minutes
require=UpdatePlz

View File

@@ -0,0 +1,4 @@
name=Update PLZ (5 minutes)
id=UpdatePlz5
description=Restart the dedicated server if mods are outdated after 5 minutes
require=UpdatePlz

View File

@@ -0,0 +1,3 @@
require "updateplz.lua"
if not getCore():isDedicated() then return end
UpdatePLZ.setRestartDelaySeconds(5 * 60)

4
mods/updateplz5/mod.info Normal file
View File

@@ -0,0 +1,4 @@
name=Update PLZ (5 minutes)
id=UpdatePlz5
description=Restart the dedicated server if mods are outdated after 5 minutes
require=UpdatePlz

View File

@@ -0,0 +1,3 @@
require "updateplz.lua"
if not getCore():isDedicated() then return end
UpdatePLZ.setRestartDelaySeconds(60 * 60)

View File

@@ -0,0 +1,4 @@
name=Update PLZ (60 minutes)
id=UpdatePlz60
description=Restart the dedicated server if mods are outdated after 60 minutes
require=UpdatePlz

View File

@@ -0,0 +1,4 @@
name=Update PLZ (60 minutes)
id=UpdatePlz60
description=Restart the dedicated server if mods are outdated after 60 minutes
require=UpdatePlz

View File

@@ -0,0 +1,3 @@
require "updateplz.lua"
if not getCore():isDedicated() then return end
UpdatePLZ.setRestartDelaySeconds(60 * 60)

View File

@@ -0,0 +1,4 @@
name=Update PLZ (60 minutes)
id=UpdatePlz60
description=Restart the dedicated server if mods are outdated after 60 minutes
require=UpdatePlz