Skip to content

About

Typewriter extension for client-side puzzle objectives: lever orders, laser grids, memory sequences

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

Puzzle Extension

Java Version Build Status Target Typewriter

Puzzle Extension adds nine reusable puzzle objectives to TypeWriter. Each puzzle renders its board client-side, tracks progress per player, and drives the usual TypeWriter surface: facts, triggers and objective chains.

The public build uses only official TypeWriter and Paper APIs. It never mutates the world: every visual is a packet sent to one player, and the real blocks stay untouched.


Puzzle types

Entry What the player does
puzzle_block_push Pushes blocks into target holes, Sokoban style.
puzzle_memory Watches a highlighted sequence, then repeats it.
puzzle_laser_grid Rotates mirrors until each beam reaches its receiver.
puzzle_lever_order Flips levers in the configured order.
puzzle_pattern Places blocks to reproduce a displayed pattern.
puzzle_coop_pressure Several players hold pressure plates at the same time.
puzzle_item_frame Fills an item frame, then rotates it to the target angle.
puzzle_combination_lock Presses buttons in the order of a code.
puzzle_pedestal Offers a required item on a pedestal.

Five support entries complete the surface: puzzle_chain (complete a set of puzzles), puzzle_artifact (persistent progress, statistics and shared completions), puzzle_menu (an in-game menu listing the configured puzzles), and the facts puzzle_solved_fact and puzzle_active_fact.

Commands

Puzzle commands live under TypeWriter's own command tree (/typewriter or /tw):

Command Permission Description
/typewriter puzzle none Open the puzzle menu (needs a puzzle_menu entry).
/typewriter puzzle list none List the configured puzzles.
/typewriter puzzle start <id> / join <id> none Start or join a puzzle.
/typewriter puzzle chain <id> none Start a puzzle chain.
/typewriter puzzle leaderboard <id> none Show the leaderboard of a puzzle.
/typewriter puzzle status none Show your puzzle status.
/typewriter puzzle stop [id] none Stop one puzzle, or all of yours.
/typewriter puzzle close none Close the open menu.
/typewriter puzzle admin reset <player> <id> puzzle.admin Reset a puzzle for a player. For a shared puzzle it reopens it for the whole group.
/typewriter puzzle admin reload puzzle.admin Clear the runtime states of puzzles and chains.

There is no standalone /puzzle command.

Shared options

Every puzzle entry shares the objective options below.

Option Meaning
amount Number of steps the puzzle counts as progress.
timeLimit Seconds before the puzzle times out. 0 disables it.
cooldownOnFail Seconds the player must wait after a failure.
maxAttempts Wrong attempts allowed per session. 0 disables the limit.
resetOnWrong Whether a wrong step clears the progress.
showHints / hintMessage Progress hints, with {progress} and {total} placeholders.
completionMessage Message sent once the puzzle is completed. Blank disables it.
onStart / onComplete / onFail / onTimeout / onLifespanExpire TriggerableEntry refs.
fact Fact incremented by amount on completion.
lifespan Seconds before the puzzle expires regardless of activity.
isShared Shares the progression of a group, the group set on the puzzle's fact. See below.
activationRadius Detection radius in blocks around the puzzle positions. 0 keeps the world check only.

Behaviour worth knowing

A puzzle belongs to one world, and to the ground around it. Being in the audience is not enough: the puzzle only renders and runs for a player standing in the world of its own positions, within activationRadius blocks of at least one of them. This is not cosmetic — a client-side block or a particle carries coordinates and no world, so without the gate a board configured in one dimension was drawn in every dimension the player visited.

A session starts when the player reaches the puzzle. Arriving clears the progress, the attempt budget and the failure cooldown, and arms timeLimit and lifespan. maxAttempts is therefore a per-session budget, not a lifetime one — a player who exhausted it simply restarts the puzzle. Walking away clears the board on the client and cancels the pending animations. A puzzle that is already solved is never reopened, so completion stays idempotent.

Completion fires once. completionMessage, the fact write, onComplete and the chain progress are all emitted from a single accepted transition, so a duplicated interaction event cannot trigger them twice. The message goes to the player who completed the puzzle.

Shared puzzles (isShared). The group is the one of the puzzle's fact: a step, a mistake or the solve by one member applies to the others, so the fact needs a group and has no effect without one (puzzle_coop_pressure is never shared this way). The first solve counts for the group: the fact is raised once, and each member gets the completion message, onComplete and the chain step once; a member who was away gets them on return. Boards stay per player. A player gets the completion of a puzzle at most once, even when changing group, until an admin reset concerns them (/typewriter puzzle admin reset <player> <id>).

A shared puzzle needs a Puzzle Artifact. Group completions are stored in puzzle_artifact. Without it, a restart pays the completion again, and going back to an older build loses the shared record. Create one puzzle_artifact entry and keep its artifactId stable after publication.

Client-side visuals are replayed, not assumed. A block change sent to a client that has not received the chunk yet is discarded, and a chunk delivered afterwards carries the real world state. The renderer tracks what it sent and replays it after chunk delivery, after a respawn or world change, and shortly after any render burst. Without that replay a board is registered server-side but invisible in game until an unrelated block update refreshes the section.

Coop pressure requires real players. requiredPlayers counts distinct Player entities on distinct plates. A dropped item standing on a plate never satisfies the requirement — this is deliberate, not a limitation.

Laser beams are bounded. puzzle_laser_grid draws each beam through the centre of the blocks, with a corner on every mirror. maxReflections (default 16) and maxBeamLength (blocks counted from the emitter, default 64) cap it; a maxBeamLength of 0 or less means the default, never unlimited. A beam also stops at a wall, at a receiver and at the edge of the loaded world: it never loads a chunk.

Item frames are driven, not created. puzzle_item_frame expects an item frame to already exist at the configured position. An empty frame only accepts the required item; a filled frame only rotates, one step per interaction, and never asks for the item again. If no frame exists at the position the player is told, and the position is logged as a warning.

Requirements

  • Paper, Minecraft 1.21.x (API 1.21.11)
  • Java 21
  • TypeWriter engine 0.9.0-beta-177

Documentation

Full documentation available at BTC Studio Docs.

Building

./gradlew :TypeWriter-PuzzleExtension:build

Run it from the ExtensionsPublics checkout (this module has no Gradle wrapper of its own). The extension jar is produced in build/libs/.


📜 Licence

GNU General Public License v3.0 or later — LICENSE — with a linking exception for the Typewriter engine — LICENSE-EXCEPTION.md.

You may Run it anywhere, including on a monetised server. Study it, modify it, use it as a base, and redistribute it — even for a fee. GPLv3 §4 explicitly allows charging for a copy.
You must Publish the complete corresponding source of your version under GPLv3, preserve the copyright notices, and state that you modified it and when (§5(a)).
You may not Ship a closed-source or proprietary version, relicense under stricter terms, or strip the attribution and present this work as your own — §8 terminates your rights automatically.
Marks "Born To Craft" and "BTC Studio" are not covered by the GPL. Fork it freely, sell your fork if you like — but rebrand it.

Reselling this code is legally allowed and practically pointless: whoever buys a copy from you receives, under the GPL, the right to redistribute it for free. That is the protection — not a clause forbidding sale, which the GPL does not permit us to add.

About Typewriter

This is a third-party extension. It uses the public extension API of the Typewriter engine by gabber235 and contains none of its source. Born To Craft Studio is not affiliated with or endorsed by the Typewriter project.

The engine itself is not free software — its licence forbids redistributing it. Get it from the Typewriter project, and never redistribute it, including inside a fork of this repository.

Full attribution, the statement of modifications required by §5(a), and the trademark reservation are in NOTICE.md. Read it before redistributing.

© 2026 Born To Craft Studio.

About

Typewriter extension for client-side puzzle objectives: lever orders, laser grids, memory sequences

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages