メインコンテンツへスキップ
paste
bin
.ca
type · paste · share
⌘
K
ファミリー
bin ファミリー
pastebin.ca
ハブ
Share text and code with expiry and privacy controls.
imagebin.ca
Upload and share images with direct links.
filebin.ca
Drop a file and get a shareable link.
notebin.ca
Write Markdown notes with durable links.
turl.ca
Short, reputation-checked links.
attn.ca
Notifications and alerts for your services.
voicebin.ca
Record and share short voice clips.
dnsbin.ca
Inspect DNS and debug records.
ドキュメント
サインイン
?
← ペーストに戻る
›
編集 / フォーク
無題のペースト
#4c45AdjCXW
public / public
新しいバージョン
匿名
作成日 1 day ago
失効まで 6 days
12.1 KB
構文:
text
変更により、このペーストにリンクされた新しいペーストが作成されます — 元のペーストは変更されません。
新しいバージョン
変更により、このペーストにリンクされた新しいペーストが作成されます — 元のペーストは変更されません。
タイトル(任意)
ファイル名
構文
text
text
bash
c
cpp
css
diff
dockerfile
go
html
ini
java
javascript
json
kotlin
lua
makefile
markdown
nginx
php
python
ruby
rust
shellscript
sql
swift
toml
typescript
xml
yaml
可視性
パブリックフィード
アクセス
public
失効
7日
10分
1時間
1日
7日
30日
90日
カスタム…
カスタム失効
変更メモ
(任意)
このペーストはパブリックフィードに表示されます。リンクを知っている人だけに見せたい場合は可視性を変更してください。
新しいバージョンを作成
キャンセル
貼り付けるか入力…
-- ============================================================================ -- Online Player Viewer -- Requires: monitor + playerDetector peripherals -- Dependencies: CC:Tweaked + Advanced Peripherals -- ============================================================================ -- ============================================================================ -- Configuration -- ============================================================================ local REFRESH_INTERVAL = 1 -- Refresh interval in seconds local TEXT_SCALE = 0.5 -- Text scale (0.5 = smallest / most room) -- ============================================================================ -- Color Theme -- ============================================================================ local CLR = { bg = colors.black, title = colors.yellow, header = colors.cyan, text = colors.white, white = colors.white, dim = colors.lightGray, online = colors.lime, offline = colors.red, warn = colors.orange, highlight = colors.green, accent = colors.pink, border = colors.gray, } -- Dimension short names local DIM_NAMES = { ["minecraft:overworld"] = "Overworld", ["minecraft:the_nether"] = "Nether", ["minecraft:the_end"] = "End", } -- ============================================================================ -- Utility Functions -- ============================================================================ --- Format dimension name local function formatDimension(dim) return DIM_NAMES[dim] or dim or "???" end --- Format coordinates local function formatPos(x, y, z) if not x then return "---, ---, ---" end return string.format("%d, %d, %d", math.floor(x), math.floor(y), math.floor(z)) end --- Format health local function formatHealth(health, maxHealth) if not health then return "?/?" end return string.format("%.0f/%.0f", health, maxHealth) end --- Draw centered text local function drawCentered(mon, y, text, color) local w = mon.getSize() mon.setTextColor(color or CLR.text) local x = math.floor((w - #text) / 2) + 1 if x < 1 then x = 1 end mon.setCursorPos(x, y) mon.write(text) end --- Draw horizontal separator local function drawSeparator(mon, y, char, color) local w = mon.getSize() char = char or "-" mon.setTextColor(color or CLR.border) mon.setCursorPos(1, y) mon.write(string.rep(char, w)) end --- Truncate text to fit width local function truncate(text, maxLen) if #text <= maxLen then return text end return text:sub(1, maxLen - 1) .. "." end -- ============================================================================ -- Peripheral Setup -- ============================================================================ local function findPeripherals() local monitor = nil local detector = nil local names = peripheral.getNames() for _, name in ipairs(names) do local ptype = peripheral.getType(name) if ptype == "monitor" and not monitor then monitor = peripheral.wrap(name) elseif ptype == "player_detector" and not detector then detector = peripheral.wrap(name) end end return monitor, detector end -- ============================================================================ -- Data Fetching -- ============================================================================ local function getPlayerData(detector) local players = {} local ok, onlineList = pcall(detector.getOnlinePlayers, detector) if not ok then return nil, "Failed to get player list: " .. tostring(onlineList) end if not onlineList or #onlineList == 0 then return {}, nil end for _, name in ipairs(onlineList) do local info = detector.getPlayer(name) if info then table.insert(players, { name = name, x = info.x, y = info.y, z = info.z, dimension = info.dimension, health = info.health, maxHealth = info.maxHealth, }) else -- Still show player even if detail fetch fails table.insert(players, { name = name, x = nil, y = nil, z = nil, dimension = nil, health = nil, maxHealth = nil, }) end end -- Sort alphabetically table.sort(players, function(a, b) return a.name:lower() < b.name:lower() end) return players, nil end -- ============================================================================ -- Rendering -- ============================================================================ -- Fixed row layout (the static frame is drawn once; only dynamic rows update) local ROW_STATS = 4 -- player count / refresh rate / timestamp local ROW_HEADER = 6 -- column headers local ROW_FIRST = 8 -- first player row --- Blank a vertical region with the background color. Used instead of --- clearing the whole monitor so a refresh never flashes the entire screen. local function clearRows(mon, y1, y2) local w = mon.getSize() for y = y1, y2 do mon.setBackgroundColor(CLR.bg) mon.setCursorPos(1, y) mon.write(string.rep(" ", w)) end end --- Draw the static frame (title bar, separators, column header) once. --- It stays on screen; only the dynamic rows are rewritten afterwards. local function drawStaticFrame(mon) local w = mon.getSize() mon.setBackgroundColor(CLR.bg) mon.clear() -- Title bar mon.setTextColor(CLR.title) drawSeparator(mon, 1, "=", CLR.title) drawCentered(mon, 2, "** Online Player Viewer **", CLR.title) drawSeparator(mon, 3, "=", CLR.title) -- Column header local nameW = math.min(18, math.floor(w * 0.22)) local dimW = math.min(10, math.floor(w * 0.12)) local posW = math.min(24, math.floor(w * 0.35)) local hpW = math.min(10, math.floor(w * 0.12)) mon.setTextColor(CLR.header) mon.setCursorPos(2, ROW_HEADER) local headerFmt = "%-" .. nameW .. "s %-" .. dimW .. "s %-" .. posW .. "s %" .. hpW .. "s" mon.write(string.format(headerFmt, "Name", "Dimension", "Position (X, Y, Z)", "Health")) drawSeparator(mon, ROW_HEADER + 1, "-", CLR.border) end --- Redraw only the stats row (no full clear, so no flicker) local function renderStats(mon, playerCount, timestamp) local w = mon.getSize() mon.setBackgroundColor(CLR.bg) mon.setCursorPos(1, ROW_STATS) mon.write(string.rep(" ", w)) mon.setTextColor(CLR.text) mon.setCursorPos(2, ROW_STATS) mon.write("Online: ") mon.setTextColor(CLR.online) mon.write(tostring(playerCount)) mon.setTextColor(CLR.dim) mon.setCursorPos(math.floor(w / 2) + 1, ROW_STATS) mon.write("Refresh: " .. REFRESH_INTERVAL .. "s") -- Timestamp on the right local timeStr = "Updated: " .. timestamp mon.setCursorPos(w - #timeStr, ROW_STATS) mon.write(timeStr) end local function renderPlayerTable(mon, players) local w, h = mon.getSize() local lastRow = h - 2 if #players == 0 then clearRows(mon, ROW_FIRST, lastRow) drawCentered(mon, ROW_FIRST, "(No players online)", CLR.dim) return end -- Column widths local nameW = math.min(18, math.floor(w * 0.22)) local dimW = math.min(10, math.floor(w * 0.12)) local posW = math.min(24, math.floor(w * 0.35)) local hpW = math.min(10, math.floor(w * 0.12)) local row = ROW_FIRST for i, p in ipairs(players) do if row > lastRow then mon.setTextColor(CLR.dim) mon.setCursorPos(2, lastRow) mon.write("... +" .. (#players - i + 1) .. " more players") break end -- Alternating row colors if i % 2 == 0 then mon.setTextColor(CLR.text) else mon.setTextColor(CLR.white) end mon.setCursorPos(2, row) -- Name local name = truncate(p.name, nameW) mon.write(string.format("%-" .. nameW .. "s", name)) mon.setCursorPos(2 + nameW + 2, row) -- Dimension local dim = truncate(formatDimension(p.dimension), dimW) if p.dimension == "minecraft:the_nether" then mon.setTextColor(CLR.warn) elseif p.dimension == "minecraft:the_end" then mon.setTextColor(CLR.accent) end mon.write(string.format("%-" .. dimW .. "s", dim)) -- Position if i % 2 == 0 then mon.setTextColor(CLR.text) else mon.setTextColor(CLR.white) end mon.setCursorPos(2 + nameW + 2 + dimW + 2, row) local pos = formatPos(p.x, p.y, p.z) mon.write(string.format("%-" .. posW .. "s", pos)) -- Health mon.setCursorPos(2 + nameW + 2 + dimW + 2 + posW + 2, row) local hp = formatHealth(p.health, p.maxHealth) if p.health and p.maxHealth then local ratio = p.health / p.maxHealth if ratio < 0.25 then mon.setTextColor(CLR.offline) elseif ratio < 0.5 then mon.setTextColor(CLR.warn) else mon.setTextColor(CLR.highlight) end end mon.write(string.format("%" .. hpW .. "s", hp)) row = row + 1 end -- Blank the rows left over when the new list is shorter clearRows(mon, row, lastRow) end local function renderFooter(mon, errorMsg) local w, h = mon.getSize() mon.setBackgroundColor(CLR.bg) mon.setCursorPos(1, h - 1) mon.write(string.rep(" ", w)) mon.setCursorPos(1, h) mon.write(string.rep(" ", w)) if errorMsg then drawSeparator(mon, h - 1, "-", CLR.warn) mon.setTextColor(CLR.warn) mon.setCursorPos(2, h) mon.write("! " .. truncate(errorMsg, w - 4)) else drawSeparator(mon, h - 1, "-", CLR.border) mon.setTextColor(CLR.dim) mon.setCursorPos(2, h) mon.write("CC:Tweaked + Advanced Peripherals") end end -- ============================================================================ -- Main Loop -- ============================================================================ local function main() local monitor, detector = findPeripherals() if not monitor then print("Error: Monitor peripheral not found!") print("Available: " .. table.concat(peripheral.getNames(), ", ")) return end if not detector then print("Error: Player detector peripheral not found!") print("Available: " .. table.concat(peripheral.getNames(), ", ")) -- Show error on monitor too monitor.setTextScale(TEXT_SCALE) monitor.setBackgroundColor(CLR.bg) monitor.clear() monitor.setTextColor(CLR.warn) drawCentered(monitor, math.floor(monitor.getSize() / 2), "! Player detector not found !", CLR.warn) return end -- Init monitor monitor.setTextScale(TEXT_SCALE) print("Online Player Viewer started!") print("Monitor size: " .. monitor.getSize()) print("Press Ctrl+T to stop") -- Draw the static frame once; only dynamic rows are redrawn each tick drawStaticFrame(monitor) -- Main loop while true do local timestamp = os.date("%H:%M:%S") local players, err = getPlayerData(detector) renderStats(monitor, players and #players or 0, timestamp) if players then renderPlayerTable(monitor, players) else local _, h = monitor.getSize() clearRows(monitor, ROW_FIRST, h - 2) end renderFooter(monitor, err) sleep(REFRESH_INTERVAL) end end -- ============================================================================ -- Entry Point -- ============================================================================ local ok, err = pcall(main) if not ok then local monitor = peripheral.find("monitor") if monitor then monitor.setTextScale(TEXT_SCALE) monitor.setBackgroundColor(colors.black) monitor.clear() monitor.setTextColor(colors.red) monitor.setCursorPos(1, 1) monitor.write("Crash:\n" .. tostring(err)) end print("Error: " .. tostring(err)) end