Archives
Trending
Support
Login
clear text
XML
Django
JavaScript
MATLAB
C
C++
C#
Python
SQL
Shell
Bash
Markdown
YAML
JSON
HTML
CSS
PHP
Java
Ruby
Go
Rust
Swift
Kotlin
Arduino
TypeScript
Perl
Autohotkey
Lua
SQF
R
Scala
Haskell
Groovy
Dart
Clojure
VB.NET
Objective-C
PowerShell
Bash
CoffeeScript
Verilog
-- 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
Mark as private (unlisted)
for 30 minutes
for 6 hours
for 1 day
for 1 week
for 1 month
for 1 year
everlasting (like CCCP)