跳到正文

High Level Peripherals

作者:Arthurus36

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 0 or 255 → opaque.
  • Alpha 1..254 → source-over blend: out = (src*a + dst*(255-a)) / 255.
  • getPixel/getpx return 0xRRGGBB (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() → true while 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 of setSize). Match your array’s cols:rows shape 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/.y 0..1, .y=0 at top), res, time.
  • uniform <float|vec3> name;
  • Functions: <float|vec3> name(params) { ...; return expr; }. No recursion. Must appear before any other top-level statement, including uniform declarations.
  • Control flow: if/else, for (init; cond; update) {}, break;, return expr;.
  • Operators: + - * /, unary - !, comparisons, && ||, .x .y .z swizzle. vec3 * float works; float * vec3 does 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.0 for 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/版本名 下面。运行环境:客户端和服务端都要装。

评论

登录后评论和评分

Arthurus36 的其他作品

查看全部 →