Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- Player tracker for ComputerCraft (America/Sao_Paulo)
- -- • Requires HTTP
- -- • Smooth play-time updates via os.clock()
- -- • Auto-sync login/logout times when HTTP recovers
- -- • Persists data across restarts
- -- • Color-codes online (green) / offline (gray/red)
- local detector = peripheral.find("playerDetector")
- if not detector then error("Player Detector not found") end
- local monitor = peripheral.find("monitor")
- if not monitor then error("Monitor not found") end
- -- storage
- local dataFile = "player_data"
- local data = {}
- if fs.exists(dataFile) then
- local f = fs.open(dataFile, "r")
- data = textutils.unserialize(f.readAll()) or {}
- f.close()
- end
- local function saveData()
- local f = fs.open(dataFile, "w")
- f.write(textutils.serialize(data))
- f.close()
- end
- -- parse unixtime and datetime from the Sao_Paulo endpoint
- local function fetchTime()
- local resp = http.get("http://worldtimeapi.org/api/timezone/America/Sao_Paulo.txt")
- if not resp then return nil, nil end
- local unixtime, datetime
- for line in resp.readAll():gmatch("[^\r\n]+") do
- local k,v = line:match("^(%w+):%s*(.+)$")
- if k == "unixtime" then
- unixtime = tonumber(v)
- elseif k == "datetime" then
- datetime = v
- end
- end
- resp.close()
- if not unixtime or not datetime then return nil, nil end
- return unixtime, datetime
- end
- -- format "2025-07-07T16:00:00.123456-03:00" → "16:00 - 07/07/25"
- local function formatTimestamp(dt)
- local Y,M,D,h,m = dt:match("^(%d+)%-(%d+)%-(%d+)T(%d+):(%d+)")
- return h .. ":" .. m .. " - " .. D .. "/" .. M .. "/" .. Y:sub(3)
- end
- -- format seconds → "Xh Ym Zs"
- local function formatDuration(s)
- s = math.floor(s)
- local h = math.floor(s/3600)
- local m = math.floor((s%3600)/60)
- local sec = s%60
- return string.format("%dh %dm %ds", h, m, sec)
- end
- -- track real‐time clock deltas
- local lastClock = os.clock()
- local loopDelay = 1 -- seconds per cycle (updated to 1s)
- while true do
- local nowClock = os.clock()
- local dt = nowClock - lastClock
- lastClock = nowClock
- -- 1) Tick up every online player's play time
- for _, info in pairs(data) do
- if info.lastState == "online" then
- info.totalPlayTime = info.totalPlayTime + dt
- end
- end
- -- 2) Try to fetch real UTC now
- local nowEpoch, nowDT = fetchTime()
- -- 3) Build current online set
- local onlineSet = {}
- for _, name in ipairs(detector.getOnlinePlayers()) do
- onlineSet[name] = true
- end
- -- 4) Detect logouts
- for name, info in pairs(data) do
- if info.lastState == "online" and not onlineSet[name] then
- info.lastState = "offline"
- -- buffer the clock-time of this change
- info.pendingClock = nowClock
- info.pendingType = "logout"
- end
- end
- -- 5) Detect logins
- for name, info in pairs(data) do
- if info.lastState == "offline" and onlineSet[name] then
- info.lastState = "online"
- info.pendingClock = nowClock
- info.pendingType = "login"
- end
- end
- -- 6) New players
- for name in pairs(onlineSet) do
- if not data[name] then
- data[name] = {
- totalPlayTime = 0,
- lastState = "online",
- -- treat initial login as pending until we sync
- pendingClock = nowClock,
- pendingType = "login"
- }
- end
- end
- -- 7) If we got a valid epoch, replay any pending events
- if nowEpoch then
- for _, info in pairs(data) do
- if info.pendingType then
- -- how long ago (in real seconds) the event happened?
- local age = nowClock - info.pendingClock
- -- compute the true unixtime of that event
- info.lastChangeTime = nowEpoch - age
- info.lastChangeLabel = formatTimestamp(nowDT)
- info.pendingClock = nil
- info.pendingType = nil
- end
- end
- end
- saveData()
- -- 8) Redraw monitor
- monitor.setTextScale(1)
- monitor.clear()
- monitor.setCursorPos(1,1)
- local names = {}
- for n in pairs(data) do table.insert(names, n) end
- table.sort(names)
- local y = 1
- for _, name in ipairs(names) do
- local info = data[name]
- -- name
- monitor.setCursorPos(1, y)
- monitor.setTextColor(info.lastState == "online" and colors.green or colors.gray)
- monitor.write(name)
- y = y + 1
- -- status & since
- monitor.setCursorPos(3, y)
- if info.lastState == "online" then
- monitor.setTextColor(colors.green)
- monitor.write("Online since " .. (info.lastChangeLabel or "…"))
- else
- monitor.setTextColor(colors.red)
- monitor.write("Offline since " .. (info.lastChangeLabel or "…"))
- end
- y = y + 1
- -- total played
- monitor.setCursorPos(3, y)
- monitor.setTextColor(colors.white)
- monitor.write("Total played " .. formatDuration(info.totalPlayTime))
- y = y + 2
- end
- sleep(loopDelay)
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement