Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- server_stats.lua (CC:Tweaked / ATM10)
- -- Estimates TPS/MSPT by comparing in-game time to real time.
- -- Works on ANY monitor size; auto-scales text and keeps layout tight.
- -- ===== Helpers =====
- local function pickTextScale(w, h)
- -- Try to fit 5 lines comfortably: title + tps + mspt + age + footer
- -- Larger monitors get smaller scale (more pixels, more columns)
- if w >= 60 and h >= 20 then return 0.5 end
- if w >= 28 and h >= 10 then return 0.75 end
- return 1 -- tiny monitor
- end
- local function findMonitor()
- local mon = peripheral.find("monitor")
- if not mon then error("No monitor attached. Place any monitor touching the computer.", 0) end
- return mon
- end
- local function setColors(mon)
- -- If not advanced, colors.* still exist but only white/black will show.
- if term.isColor() then
- mon.setTextColor(colors.white)
- mon.setBackgroundColor(colors.black)
- else
- mon.setTextColor(colors.white)
- mon.setBackgroundColor(colors.black)
- end
- end
- local function center(mon, y, s)
- local w, _ = mon.getSize()
- local x = math.max(1, math.floor((w - #s)/2) + 1)
- mon.setCursorPos(x, y)
- mon.write(s)
- end
- local function right(mon, y, s)
- local w, _ = mon.getSize()
- local x = math.max(1, w - #s + 1)
- mon.setCursorPos(x, y)
- mon.write(s)
- end
- local function avg(a)
- local s=0
- for i=1,#a do s = s + a[i] end
- return (#a > 0) and (s/#a) or 0
- end
- -- Estimate from clocks
- -- os.epoch("ingame") advances ~50 ms per game tick at 20 TPS when healthy.
- local function estimate(sample_ms)
- local r0 = os.epoch("utc")
- local g0 = os.epoch("ingame")
- sleep(sample_ms/1000)
- local r1 = os.epoch("utc")
- local g1 = os.epoch("ingame")
- local dR = math.max(1, r1 - r0)
- local dG = math.max(1, g1 - g0)
- -- If server is healthy: dG ≈ dR; TPS ≈ 20*(dG/dR), MSPT ≈ 50*(dR/dG)
- local tps = 20 * (dG / dR)
- if tps < 0 then tps = 0 end
- if tps > 20 then tps = 20 end
- local mspt = 50 * (dR / dG)
- return tps, mspt
- end
- local function worldAgeText()
- local ms = os.epoch("ingame")
- local ticks = math.floor(ms / 50)
- local days = math.floor(ticks / 24000)
- local hrs = math.floor((ticks % 24000) / 1000) -- ~1000 ticks ≈ 1 in-game hour
- return ("%dd %dh"):format(days, hrs)
- end
- -- ===== Setup =====
- local mon = findMonitor()
- setColors(mon)
- mon.clear()
- -- Choose a text scale that actually fits the content
- local w, h = mon.getSize()
- local scale = pickTextScale(w, h)
- mon.setTextScale(scale)
- w, h = mon.getSize() -- refresh after scale change
- -- Precompute line positions (keep it tight for small displays)
- -- Layout (5 rows total):
- -- 1: TITLE
- -- 2: TPS line
- -- 3: MSPT line
- -- 4: WORLD AGE line
- -- h: FOOTER
- local rowTitle = 1
- local rowTPS = math.min(2, h-3)
- local rowMSPT = math.min(3, h-2)
- local rowAge = math.min(4, h-1)
- local rowFooter = h
- local samples = {} -- rolling TPS average
- local keepSamples = 6 -- ~6 seconds smoothing with 1s sample
- -- ===== Main loop =====
- while true do
- -- Take a 1s sample
- local tps, mspt = estimate(1000)
- table.insert(samples, tps)
- if #samples > keepSamples then table.remove(samples, 1) end
- local tpsAvg = avg(samples)
- -- Draw
- setColors(mon)
- mon.clear()
- center(mon, rowTitle, "SERVER STATS")
- -- TPS line
- local tpsStr = ("TPS: %.2f"):format(tpsAvg)
- local tpsHint = (tpsAvg >= 19.5 and "OK") or (tpsAvg >= 15 and "WARN") or "LAG"
- local tpsLine = tpsStr .. " [" .. tpsHint .. "]"
- center(mon, rowTPS, tpsLine)
- -- MSPT line
- local msptLine = ("MSPT: %.2f ms"):format(mspt)
- center(mon, rowMSPT, msptLine)
- -- World Age
- local ageLine = "World age: " .. worldAgeText()
- center(mon, rowAge, ageLine)
- -- Footer heartbeat + monitor size (debug on right so you can tell it's updating)
- mon.setCursorPos(1, rowFooter)
- mon.write("Ctrl+T to stop")
- right(mon, rowFooter, ("%dx%d x%.2f"):format(w, h, scale))
- end
Advertisement