Omahub
← All plugins
L

Neon Cadet

by Luo Tao <luotao@hey.com>

A full pinball table on the shell overlay: plunger, flippers, ramps, missions and ranks in the spirit of 3D Pinball Space Cadet, rebuilt in neon.

Security review

No obvious issues detected

Deterministic scan — not a security guarantee

None
Risk level
None
Analyzed commit
442a8c8
Scanned
1 month ago

No potentially dangerous behavior detected in the analyzed commit.

Automated analysis only — not a security guarantee.

AI advisory review

No obvious issues detected

Language-model assessment · ~deepseek/deepseek-v4-flash-latest — advisory only

None
AI risk level
None
Recommendation
install
Model
~deepseek/deepseek-v4-flash-latest
Analyzed commit
442a8c8
Reviewed
1 month ago

The plugin is a self-contained pinball game with no network access, no destructive commands, and no hidden persistence. It reads a local stats file through a bounded, sanitized helper and plays sounds via standard players. The deterministic scan found no issues, and manual review confirms the code is transparent and safe.

How this check works

This review combines the deterministic scan (the rule-based results above) with an independent look at the plugin's code by a language model. The model reads a trimmed sample of the repository's files, the manifest, and the README, then gives a plain-language risk level and a recommendation: install (no notable danger), review (look closer first), or avoid (clearly dangerous).

It runs on the same analyzed commit as the deterministic scan and is strictly advisory — it is not a security guarantee and never blocks a plugin by itself. A human moderator still reviews plugins before they are listed.

AI advisory only — automated analysis, not a security guarantee.

Install
$ omarchy plugin add https://github.com/ya-luotao/omarchy-pinball --enable
Other #bar #quickshell

Neon Cadet

A full pinball table on the Omarchy shell overlay (Omarchy 4 "Quattro" or later) — plunger, flippers, ramps, missions and nine ranks, in the spirit of 3D Pinball for Windows – Space Cadet, rebuilt in neon.

<p align="center"> <img src="screenshots/table.png" alt="The playfield" width="44%" /> <img src="screenshots/hud.png" alt="Score, mission and rank ladder" width="31%" /> </p>

Summon it, play a ball, press ESC. The game is left exactly where you stopped, so the next summon picks the same ball back up — it is a break from work, not another thing to finish.

  • A real table, not a toy — a shooter lane with a one-way gate, an orbit around the arch, the hyperspace kickout under its spill, four attack bumpers, the black hole below them, the gravity well dead centre, a wormhole that teleports when lit, three mission targets, two fuel targets at the head of the right return rail, re-entry kickers and return rails down both sides, the launch ramp up the right wall, slingshots, in- and outlanes, and a drain between the flippers.
  • Physics in table units — a 22-unit ball, a playfield tilted about six degrees, flipper tips that sweep at six metres a second. Contact points carry the flipper's own velocity, so a ball met at the tip leaves harder than one met at the base, and aiming off the tip is a thing you can learn. The stroke is asymmetric like a real machine's: the solenoid snaps the flipper up at full speed and gravity brings it back at less than half that, so trapping is something you do rather than something that happens. No coil fires the same twice: every kickout leaves with a few degrees of spread and a few percent of strength on it, which is both how a real one behaves and the only thing that keeps a hole from becoming the fixed point of a loop.
  • Ball save — the first eight seconds of every ball are on the house. A drain in the window comes straight back out of the lane at three-quarter power, and the mission you were flying carries on through it.
  • Shot lights — a pulsing ring marks every shot the table is asking for right now: the mission targets when none is selected, the launch ramp once one is, the mission's remaining goals, the wormhole while multiball is paying jackpots.
  • Nine missions, nine ranks — hit a mission target to select one of three on offer, shoot the launch ramp to accept it, finish it to be promoted. Cadet to Fleet Admiral, with an extra ball at the top of the hyperspace ladder.
  • Skill shot, combos, D-A-T-A lanes, multiball and jackpots — and a tilt that goes dead if you shove the cabinet three times, same as leaning on the real thing. One of the four top lanes is always lit: the flipper keys walk the lamp along, a lit pass pays triple, and the plunge that drops into it is the skill shot. A drained ball tallies its bonus with the lights ticking, and a tilt forfeits it.
  • Bar widget — the table in eight strokes; the tooltip carries your best score and highest rank, the panel sets balls per game and sound.

Install

omarchy plugin add https://github.com/ya-luotao/omarchy-pinball.git --enable

Everything it needs is already on an Omarchy box: head from coreutils for the bounded stats read, and omarchy-notification-send for the game-over notice. Sound is optional — the table carries its own synthesized retro effects in sounds/ (rebuild them any time with node tools/gen-sounds.js) and plays them through pw-play or paplay, falling back to the freedesktop system sounds when the wavs are missing, and staying quiet if neither player is installed.

Uninstall

omarchy plugin remove luotao.pinball

That removes the plugin and its bar widget. Two things it does not touch, both yours to delete if you want them gone:

# the keybinding, if you added one
$EDITOR ~/.config/hypr/bindings.lua

# high scores, best rank and games played
rm -rf ~/.local/state/omarchy/pinball

Keybinding

Add to ~/.config/hypr/bindings.lua:

o.bind("SUPER + SHIFT + P", "Pinball",
  [[omarchy-shell shell summon luotao.pinball '{}']])

The payload takes balls (1–9) and sound, and {"restart": true} forces a fresh game:

omarchy-shell shell summon luotao.pinball '{"balls": 5, "sound": false}'

Controls

Key
SPACE hold to charge the plunger, release to launch
Z / / left and right flipper — each press also walks the lit D-A-T-A lamp one lane over
X / . nudge the cabinet — three hard shoves and it tilts
F2 new game
P pause
F3 show the collision geometry
ESC leave the game where it stands

Shots

Shot
SKILL drop the plunge into the lit D-A-T-A lane — walk the lamp with the flipper keys before you let go of SPACE
ORBIT all the way round the arch and off the left spill
MISSION the three standups on the left wall. Each selects a mission — your rank's, one above, or two above — and the launch ramp accepts it
LAUNCH the ramp. The cylinder at mid-right scoops up a climbing shot and lifts it onto the wire, up the right wall and over the arch. A soft shot rolls back out — the rejection is part of the shot
HYPERSPACE the corner saucer under the orbit's spill. A four-lamp ladder: score, jackpot, ball save, extra ball
BLACK HOLE the kickout below the bumpers; swallows and throws the ball back up among them
GRAVITY WELL the galaxy dead centre — its mouth is as wide as it looks, and a ball crossing at speed skips the lip while one wandering down the middle is caught and thrown back out to the right
WORMHOLE lit by a mission, multiball or a D-A-T-A set. Teleports across the table; worth a jackpot during multiball. Dark, the ball rolls past into the re-entry kicker
D-A-T-A the four lanes under the arch. A full set steps the bonus multiplier and lights the wormholes; the lit lane pays triple
FUEL two standup targets, angled into the right return rail so a falling ball glances off down the lane and a rising one scores; three hits step the multiplier (caps at x4)

Missions

# Mission
1 Practice Mission wake the attack bumpers up
2 Launch Training one more climb of the launch ramp
3 Reentry Training two re-entry lane roll-overs
4 Science Mission three fuel targets
5 Rescue Mission spell D-A-T-A, then find the wormhole
6 Satellite Rescue two trips into the black hole
7 Reconnaissance three full orbits of the arch
8 Time Warp two hyperspace jumps against the clock
9 Alien Menace two gravity wells and a wormhole, with two balls

A mission survives the drain: lose the ball mid-mission and it is still running when the next one is served, with its clock stopped in between. Collected progress — the D-A-T-A letters — carries across balls too. Selecting a mission above your rank and finishing it promotes you past every rank it covered.

Scores

High scores, best rank and games played live in ~/.local/state/omarchy/pinball/stats.json.

It is the one document this plugin reads that it may not have written, and both surfaces that read it — a bar widget and a keepLoaded overlay — are resident for the whole session. So it is not read with QML's FileView, which hands the whole file to the shell before any cap could apply: reads go through head -c (Safe.readCommand), which cannot produce more than 64 KiB + 1, and the FileView stays only as a change notifier with preload: false and blockAllReads. One byte past the cap is asked for deliberately — that is what tells an at-the-limit file from an oversized one, and an oversized one is refused whole rather than truncated. Every field that survives is clamped to the range the game can produce, since a rank of 1e9 indexes past the ladder and a NaN score sorts the board into garbage. Summon payloads are bounded the same way, and every Text in the plugin is Text.PlainText.

How the table was built

Physics.js, Table.js and Game.js are plain ECMAScript with no Qt in them; the QML only draws and takes input. That is deliberate. It means the table can be played headlessly, and every number in it was set by measurement rather than by eye:

node tests/sim.js 80 30      # escapes, NaNs, stuck balls, is every shot reachable
node tests/game.js 12        # full games; SKILL=0..1 sets how good the bot is, CAP= caps ball time
node tests/shots.js          # shot chart: what each flipper can actually reach
node tests/lifecycle.js      # extra balls, multiball, tilt, game over, stats round-trip
node tests/bounds.js         # the caps on the stats file and the summon payload

The simulator is what found the things playing could not: a slingshot geometry that swallowed the ball and fired it two hundred times a second, an outlane a unit narrower than the ball, friction that welded a resting ball to a slope, two lane rollovers that no ball ever reached — which quietly made one mission impossible to finish — and a multiball spawn point inside a bumper.

It keeps finding them. Playing tells you a table feels wrong; only counting tells you why. Two fuel targets standing in the descent corridor turned out to be flinging 87% of the falling balls that touched them straight across the centre into the drain. The mission targets and the platform edge behind them formed a resonance worth eight target hits a ball, spamming mission selection with a rattle. Every eject fired identically, which made each hole the fixed point of a cycle — the black hole threw the ball onto the left kicker, which threw it back, nine ejects a ball. The two inlane rollovers had never fired once in any ball ever served, thirty-two units off a twelve-unit sensor, which is the same bug as the one above and it came back. And the launch ramp — the one shot the whole rank ladder hangs off, because a mission is accepted with it and nothing else — was reachable on one swing in five and found by two balls in ninety.

So there is a number for each of them now. tests/game.js prints the mission funnel and the drain split, and a mission whose goal the table cannot supply shows up as a funnel that narrows to nothing rather than as a table that is merely hard.

Licence

MIT