High Level Peripherals
This is a fork of the mod Tom's Peripherals with minor additions and fixes
介绍
High Level Peripherals
A CC:Tweaked monitor peripheral that actually keeps up with what you want to build.
A fork of Tom’s Peripherals, rebuilt to be far more usable, stable, and complete —
bigger screens, real GPU-rendered shaders, full mouse/touch input, and a cleaner API
that doesn’t fight you.
✨ Features
🖥️ Big, sharp monitors
Build arrays up to 32×32 blocks (admin-adjustable up to 64×64), with per-block
resolution up to 4096×4096. Draw with a full 2D API — filled shapes, gradients, text
with custom fonts, image loading, double buffering — all running server-side, synced
to every client automatically.
⚡ Real GPU shaders, not Lua math
Write a small GLSL-like shader once and it renders **live on every viewer’s own
graphics card**, at their own framerate, completely decoupled from the server tick.
No more choking the game with per-pixel Lua raymarching — the shader engine handles
that with zero Lua involved per pixel. Includes first-class raytracing primitives
(sphere/plane/box intersection) so you’re not hand-rolling ray math from scratch.
gpu.compileShader([[
color = vec3(uv.x, uv.y, sin(time));
]])
That’s it — it’s already rendering.
🖱️ Full mouse input
Click, right-click, drag, and scroll directly on a monitor’s screen face, with
pixel-accurate coordinates delivered straight to your script. Respects whatever
controls the player has configured — no hardcoded key assumptions. Perfect for
building actual interactive UIs, not just static displays.
🎮 3D immediate-mode rendering
An OpenGL-1-style API (glBegin/glVertex/glTranslate/glRotate/lighting) for
building real 3D scenes on a monitor without writing a shader — great for models,
diagrams, or simple games.
🔆 Brightness control
Scale a monitor’s output brightness in nits, from dim ambient displays to
eye-searingly bright — applies to both drawn pixels and live shaders.
🧠 Room to build big
Generous default VRAM budget (~2 GiB per screen) shared across framebuffers, images,
and shader textures, with server-configurable limits for bigger builds.
Why this fork?
Tom’s Peripherals gave monitors and a GPU peripheral, but hit real ceilings fast —
low resolution limits, no shader rendering, no mouse input, and a handful of
long-standing multiblock/sync bugs. High Level Peripherals keeps the same familiar
peripheral.find("tm_monitor") API you already know, and pushes every one of those
ceilings out — so your builds stop being limited by the peripheral and start being
limited by your imagination.
Getting started
local gpu = peripheral.find("tm_monitor")
gpu.fill(0x000000)
gpu.drawText(10, 10, "Hello, HLPS!", 0xFFFFFF)
Full API reference below.
Docs
tm_monitor Lua API Reference
Complete reference for the monitor peripheral: 2D drawing, text, images, the 3D
immediate-mode API, mouse/scroll input, and the shader engine.
1. Limits
| Limit | Value |
|—|—|
| Grid size | Up to 32×32 blocks by default (maxScreenSize, 1-64). Over limit → every call throws. |
| gpu.setSize(n) | 64–4096 px/axis, default 1024. |
| gpu.setGpuResolution(w, h) | 64–4096 px/axis, or (0,0) for auto. |
| VRAM budget | ~2 GiB default (maxVRAMSize), shared across framebuffer/images/buffers/textures. |
2. Color format
Packed 0xRRGGBB ints, or (r,g,b[,a]) 0-255 each.
- Alpha
0or255→ opaque. - Alpha
1..254→ source-over blend:out = (src*a + dst*(255-a)) / 255. getPixel/getpxreturn0xRRGGBB(alpha stripped).
3. Sizing
| Call | Effect |
|—|—|
| gpu.setSize(n) | Per-block resolution, one axis. Total canvas is (blocksWide*n) x (blocksTall*n). |
| gpu.getSize() | → width, height, cols, rows, blockSize. |
| gpu.getResolution() | → width, height. |
| gpu.refreshSize() | Forces a re-scan of the array’s grid layout. |
| gpu.debugTiling() | → string dump of live server-side tiling state, for diagnosing a wrong-looking array. |
Keep setSize low (64-256) if drawing per-pixel in Lua — use the shader engine
(section 8) instead for anything procedural.
4. Basic 2D drawing
All coordinates are 1-based.
| Call | Notes |
|—|—|
| gpu.fill([color]) | Fills the canvas. Default black. |
| gpu.clear([color]) | Alias of fill. |
| gpu.setPixel(x, y, color) | Out-of-bounds writes ignored. |
| gpu.getPixel(x, y) | → int, 0 if out of bounds. |
| gpu.filledRectangle(x, y, w, h, [color]) | Throws if out of bounds. |
| gpu.rectangle(x, y, w, h, [color]) | Outline only. |
| gpu.line(x1, y1, x2, y2, [color]) | Bresenham. |
| gpu.lineS(x1, y1, x2, y2, [color]) | Alternate algorithm. |
| gpu.circle(cx, cy, r, [color]) | Outline. |
| gpu.fillCircle(cx, cy, r, [color]) | Filled. |
| gpu.triangle(x1,y1, x2,y2, x3,y3, [color]) | Outline. |
| gpu.fillTriangle(x1,y1, x2,y2, x3,y3, [color]) | Filled. |
| gpu.gradientRectangle(x, y, w, h, c1, c2, [vertical]) | Linear interpolation between two colors. |
| gpu.copy(srcX, srcY, w, h, dstX, dstY) | Overlap-safe. Capped at 64M px. |
| gpu.scroll(dx, dy, [fillColor]) | Shifts canvas; exposed area filled. Same cap. |
| gpu.drawBuffer(x, y, w, scale, ...pixels) | Row-major pixels as vararg numbers, not a table. |
5. Double buffering
gpu.setDoubleBuffered(true)
-- ... draw calls ...
gpu.flush() -- presents + syncs
gpu.sync() pushes the framebuffer directly (throttled internally) — not usually
needed outside double-buffering/shader flows.
6. Text
| Call | Notes |
|—|—|
| gpu.drawText(x, y, text, [fg=-1], [bg=-1], [size=1], [pad=1]) | -1 skips that layer. |
| gpu.drawTextSmart(x, y, text, [fg], [bg], [forceUnicode=false], [size=1], [pad=1]) | Auto ASCII/unicode fonts (ASCII draws at 2x size). |
| gpu.getTextLength(text, [size=1], [pad=1]) | → pixel width. |
| gpu.getFont() | → name, editable. |
| gpu.setFont(name) | No-op if font doesn’t exist. |
| gpu.drawChar(x, y, charIndex, [fg], [bg], [size=1]) | Draws one glyph, 1-based index. |
| gpu.addNewChar(char, width, ...16 numbers) | → int. Font must be editable. |
| gpu.delChar(char) / gpu.freeChars() / gpu.clearChars() | Glyph management. |
| gpu.setFontDefaultCharID(id) / gpu.getFontDefaultCharID() | Fallback glyph. |
7. Images and buffers
| Call | Returns |
|—|—|
| gpu.newImage(w, h) | Blank LuaImage. |
| gpu.imageFromBuffer(w, ...pixels) | LuaImage from raw pixel data. |
| gpu.decodeImage(bufferRef) / gpu.decodeImage(...bytes) | Decodes PNG/etc. |
| gpu.newBuffer([initialCapacity=32]) | Growable LuaByteBuffer. |
| gpu.drawImage(x, y, image) | Draws, clipped to canvas. |
All charge VRAM (w*h*4 bytes) up front and throw if over budget.
8. The shader engine
Write a small GLSL-like program once; it runs per-pixel on the real GPU, no Lua
involved.
gpu.compileShader([[
float sdSphere(vec3 p, float r) { return length(p) - r; }
uniform float speed;
color = vec3(uv.x, uv.y, sin(time * speed));
]])
gpu.setUniform("speed", 2.0)
There’s no main — code after the function defs runs top-to-bottom; color is the
pixel output. gpu.clearShader() returns to normal 2D drawing.
gpu.isGpuMode()→truewhile a shader is live.gpu.setUniform(name, value)/gpu.setUniform3(name, x, y, z)— live-update, no recompile.gpu.setGpuResolution(w, h)— resolution the shader renders at (independent ofsetSize). Match your array’scols:rowsshape or don’t call it.
A live shader has no ongoing tie to the computer that started it — it stops only if
the last attached computer disconnects, or you call gpu.clearShader().
texture() isn’t GPU-accelerated yet — a texture-sampling shader compiles fine
but won’t auto-render. Drive it yourself:
gpu.compileShader(src)
gpu.uploadTexture(0, w, h, pixels)
while true do
gpu.runShader(os.clock())
gpu.sync()
sleep(0)
end
Shader language
- Two types:
float,vec3. - Predefined:
color(write this),uv(.x/.y0..1,.y=0at top),res,time. uniform <float|vec3> name;- Functions:
<float|vec3> name(params) { ...; return expr; }. No recursion. Must appear before any other top-level statement, includinguniformdeclarations. - Control flow:
if/else,for (init; cond; update) {},break;,return expr;. - Operators:
+ - * /, unary- !, comparisons,&& ||,.x .y .zswizzle.vec3 * floatworks;float * vec3does not. - Built-ins:
vec3(f,f,f),sin cos tan sqrt abs floor fract exp pow mod min max step clamp mix smoothstep length dot cross normalize reflect,texture(slot, u, v). - Raytracing builtins (return nearest positive hit distance, or
-1.0for a miss):intersectSphere(ro, rd, center, radius),intersectPlane(ro, rd, planeY),intersectBox(ro, rd, center, halfSize).
9. Memory
| Call | Returns |
|—|—|
| gpu.getUsedMemory() | Bytes currently used. |
| gpu.getMaxMemory() | VRAM budget for this peripheral. |
10. Mouse & scroll input
Fires only while looking at the screen face with no GUI open. Sneaking has no effect.
Keyboard input isn’t captured here — that’s a separate keyboard peripheral.
| Event | Args | Trigger |
|—|—|—|
| tm_monitor_touch | side, x, y, soft | Whichever button is bound to “use” (right-click by default). soft is always false. |
| tm_monitor_mouse | side, x, y, button, action | Mouse button press/release. |
| tm_monitor_scroll | side, x, y, dir | dir is 1 (up) or -1 (down). |
| tm_monitor_drag | side, x, y, button | Cursor moved this tick while held. Once per client tick. |
x, y are screen-absolute (1-based) across the whole array.
while true do
local ev, side, x, y, button, action = os.pullEvent("tm_monitor_mouse")
gpu.setPixel(x, y, 0xFF0000)
gpu.sync()
end
11. 3D immediate-mode API
gpu3d = gpu.createWindow3D(...)
gpu3d.glFrustum(70, 0.1, 100)
gpu3d.glLoadIdentity()
gpu3d.glTranslate(0, 0, -5)
gpu3d.glDirLight(0, -1, 0)
gpu3d.glBegin(4) -- triangles
gpu3d.glColor(0xFF0000)
gpu3d.glVertex(-1, -1, 0)
gpu3d.glVertex( 1, -1, 0)
gpu3d.glVertex( 0, 1, 0)
gpu3d.glEnd()
gpu3d.render()
gpu3d.sync()
| Call | Notes |
|—|—|
| glFrustum(fov, near, far) | Perspective projection. |
| glDirLight(x, y, z) | Directional light. |
| glLoadIdentity() / glPushMatrix() / glPopMatrix() | Model matrix stack. |
| glTranslate / glScale / glRotate(angleDeg, x,y,z) | |
| glBegin([mode=4]) / glEnd() | Start/finish a primitive. |
| glVertex(x,y,z) | Appends a vertex with current color/UV. |
| glTexCoord(u,v) | UV for the next vertex. |
| glColor(color) | Packed int or (r,g,b[,a]). |
| glEnable(3553) / glDisable(3553) | Only GL_TEXTURE_2D supported. |
| glGenTextures() / glDeleteTextures / glBindTexture / glTexImage | Texture management. |
| getConstants() | GL constant name→value table. |
| render() | Culls, lights, clips, projects, sorts, blits since last clear(). |
| clear() | Wipes canvas + triangles + resets matrix/depth buffer. |
12. Performance
All drawing is server-side Java, always — singleplayer, LAN, or dedicated. Pushing
pixels to the client is the one real client cost, done via a bulk memory copy.
Per-pixel Lua drawing (raymarching, plasma, etc.) will choke a client — use the shader
engine instead, which runs on the GPU with zero Lua per pixel.
13. Brightness (nits)
gpu.setBrightness(200) -- 2x normal
print(gpu.getBrightness())
nits / 100 scales final pixel output — 100 is default (1.0x). Applies to both CPU
drawing and GPU shaders. Values that would exceed 255 clip instead of wrapping. Range
is server-configurable (minBrightnessNits/maxBrightnessNits, default 10–400).
常见问题
High Level Peripherals 支持哪些 Minecraft 版本?
High Level Peripherals 支持 Minecraft Java 版 1.21.1,可用的加载器:NeoForge。下载时注意选择和你游戏版本一致的文件。
High Level Peripherals 怎么安装?
先用 PCL2 或 HMCL 启动器安装对应版本的 NeoForge,再把下载的 .jar 文件放进游戏目录的 mods 文件夹,重新启动游戏即可。开启了版本隔离的,mods 文件夹在 versions/版本名 下面。运行环境:客户端和服务端都要装。
评论
登录后评论和评分