Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
cb75a3c
update .gitignore
KingJayan Jul 12, 2026
0026d25
extract subsystems from KeybindsClient into com.example.keybinds.*
KingJayan Jul 12, 2026
2ea91d8
add macro data model with versioned macros.json persistence
KingJayan Jul 12, 2026
12cb619
add tick-based macro execution engine and re-express legacy features …
KingJayan Jul 12, 2026
21a7807
match legacy vanilla-mode timing in compiled macros and drop dead code
KingJayan Jul 12, 2026
9e41797
rename example package, add macro manager screen, finish mod menu int…
KingJayan Jul 12, 2026
0494d73
add trigger index and expand trigger catalog with release, slot, ridi…
KingJayan Jul 12, 2026
ee6fd74
add retained-mode ui framework foundations: layouts, scroll panel, mo…
KingJayan Jul 12, 2026
97ee17d
replace legacy config screens with full macro editor and retire keybi…
KingJayan Jul 13, 2026
4dc5d17
add drag reorder, multi-select, copy/paste, and undo/redo to the macr…
KingJayan Jul 13, 2026
1f7907a
rewrite readme for the macro editor
KingJayan Jul 13, 2026
b64d284
fix trigger index dropping macros without key or button inputs and re…
KingJayan Jul 13, 2026
aea37ad
add serialization stress and trigger index tests
KingJayan Jul 13, 2026
7c73a66
ignore fabric test logs directory
KingJayan Jul 13, 2026
76c9034
add macro script dsl with compiler, gated script runtime, and tests
KingJayan Jul 13, 2026
27ae58f
add one-way text editing mode with syntax highlighting, autocomplete,…
KingJayan Jul 13, 2026
55cfdfb
add key combo trigger, camera, movement, and random wait actions
KingJayan Jul 13, 2026
27dd65a
support combos, floats, and new actions in the script dsl
KingJayan Jul 13, 2026
0343431
bump version
KingJayan Jul 13, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,13 @@ bin/
# fabric

run/
logs/

# java

hs_err_*.log
replay_*.log
*.hprof
*.jfr

docs/
44 changes: 44 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
## Principles

- Write production-ready, scalable, idiomatic code.
- Prefer simple, maintainable solutions.
- Optimize for correctness, readability, and performance.
- Never over-engineer.

## Code

- No code comments unless requested.
- Use descriptive names.
- Reuse existing code before adding new abstractions.
- Modify the smallest possible surface area.
- Match the project's existing style.

## Performance

- Prefer efficient algorithms over micro-optimizations.
- Avoid unnecessary allocations, work, and dependencies.
- Measure before optimizing.

## Workflow

- Understand the codebase before making changes.
- Search before creating.
- Batch related edits.
- Validate with the smallest relevant formatter, linter, typecheck, or tests.
- Never guess APIs or project structure.

## Tools

- Minimize tool calls and tokens.
- Read only the files needed.
- Prefer targeted edits over full rewrites.
- Keep responses concise unless more detail is requested.

## Git

- Use small, atomic commits.
- Write clear conventional commit messages.
- Never commit secrets, generated files, or broken code.
- Use `gh` for GitHub operations whenever possible.
- Inspect diffs before committing or opening a PR.
- Never force-push or merge without explicit instruction.
114 changes: 33 additions & 81 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,108 +1,60 @@
# keybinds

A **fully client-side** Fabric mod for Minecraft **26.2** built around configurable **Use Item** binds and combat helpers.
A **fully client-side** Fabric mod for Minecraft **26.2**: a tick-based macro engine with a full in-game macro editor.

Each **Use Item** bind right-clicks any item you choose (anything with a right-click action) when one or more configurable triggers activate. Every bind can either **tap** once or **hold** right-click until released.
Every macro pairs a composable **trigger** with an ordered list of tick-scheduled **actions**. Macros are stored in `config/macros.json`; press **Right Shift** in-game (or use the Mod Menu config button) to open the macro editor.

## Triggers

Each bind has one **primary trigger** (chosen in the config UI):
Triggers compose freely with **AND / OR / NOT** groups, nested to any depth:

- **Keyboard key**
- **Left-click** or **right-click**, optionally restricted to specific held item(s). Your normal click still happens—the item use is added on top.
- **Key press** / **key release** — any GLFW key
- **Mouse press** / **mouse release** — any mouse button
- **Holding item** — the held item matches a list of ids
- **Hotbar slot selected**
- **Riding a mount**
- **Held durability** — the held item's remaining durability drops to a threshold
- **Player condition** — fires the moment it becomes true: low health, hurt, on fire, in lava, falling, in water, submerged, sneaking, sprinting

Binds can also activate when an environment condition first becomes true:
Key and click triggers are edge-based (they fire once per press, not every tick) and are only evaluated while their input is down, so idle macros cost nothing.

- Low health
- Hurt
- On fire
- In lava
- Falling
- In water
- Submerged
- Sneaking
- Sprinting
## Actions

Additional options:
Actions run in order within a tick until a **Wait** yields, giving tick-perfect sequences:

- **Hotbar filter** — always fire, only while the item is on your hotbar, or only while it's buried in your inventory.
- **Vanilla swap** — for buried items, visibly swap the item into your hand, use it, then swap it back (with configurable delays) instead of using an instant silent swap.
- **Wait** — pause the macro for N ticks
- **Use specific item** — locate an item (hand → hotbar → buried in inventory) and right-click it; optional hotbar gate, and a **vanilla swap** mode that visibly brings a buried item to hand, uses it, and swaps it back over configurable tick delays
- **Use held item** / **Attack** (optionally swinging)
- **Select hotbar slot** / **Restore starting slot**
- **Select item on hotbar** — by id list or item tag
- **Require item** — abort the macro unless the item is in the inventory
- **Swap to item** / **Swap back** — inventory-wide swap, optionally ranking candidates by an enchantment level (e.g. the best **lunge** spear)
- **Shield/totem offhand swap**

### Tap vs Hold
Classic combos like a mace stun slam (axe attack, wait 1 tick, mace attack) or a lunge spear swap are just short macros built from these actions.

**Tap** performs a single right-click.

Examples: ender pearls, wind charges, snowballs, eggs, splash potions, buckets, flint & steel, placing blocks, firing a loaded crossbow.

**Hold** keeps right-click held until released.

Examples: drawing a bow, loading a crossbow, eating food, spyglass, and other multi-tick items.
Everything uses vanilla item-use and inventory packets, so **no server-side mod is required**. Works in singleplayer and vanilla multiplayer.

## Combat helpers
## Editor

- **Swap Shield / Totem** *(default H)* — toggles your offhand between a shield and a Totem of Undying.
- **Mace Stun Slam** *(default V)* — performs a two-tick axe → mace combo (requires both on your hotbar).
- **Lunge Swap** *(unbound by default)* — swaps to your best spear (the one with the highest **lunge** enchantment level), left-clicks with it, then returns to your original slot. Triggers from a key **and/or** left-click **and/or** right-click, each optional, gated by a held-item filter (a specific item, any item, or an empty hand via `minecraft:air`). Configure the extra triggers, filter, spear ids, and enchantment id from the ⚙ next to its key.
Right Shift opens the macro list: create, enable/disable, duplicate, and delete macros (right-click a row for the context menu). Inside a macro:

Each helper has a **Vanilla** toggle: when on, its swap is spread over a few ticks so it looks like a manual slot change instead of an instant same-tick action. The shared tick spacing lives in `combatSwapToDelay` / `combatUseDelay` / `combatSwapBackDelay`.
- searchable action palette and per-action parameter forms with key/mouse capture
- a visual trigger tree editor for AND/OR/NOT nesting
- drag **≡** to reorder actions, **Ctrl+click** to multi-select
- **Ctrl+C / Ctrl+V** copy/paste (also across macros), **Ctrl+Z / Ctrl+Y** undo/redo, **Del** deletes the selection

Everything uses vanilla item-use and inventory packets, so **no server-side mod is required**. Works in singleplayer and vanilla multiplayer.
Changes are saved to `config/macros.json` when a screen closes.

## Dependencies

Configuration is done through the Mod Menu config screen.

- [Mod Menu v20.0.0+](https://modrinth.com/mod/modmenu)
- [Mod Menu v20.0.0+](https://modrinth.com/mod/modmenu) *(optional)*
- [Fabric API v0.154.0+26.2](https://modrinth.com/mod/fabric-api)
- [Fabric Loader v0.19.3+](https://fabricmc.net)

## How Use Item works

When triggered, the mod searches for the configured item in this order:

1. Main hand or offhand → use immediately.
2. Hotbar → briefly switch to the slot, use it, then switch back.
3. Main inventory → swap it into your selected slot, use it, then restore your inventory layout *(Tap mode only).*

If the item isn't found, nothing happens.

**Hold** mode only works from your hand or hotbar, since the item must stay selected while being held. It intentionally leaves the item selected afterward.

Items that target blocks (placing blocks, buckets, flint & steel, etc.) still require looking at a valid block, just like vanilla.

## Configuration

Settings are stored in `config/keybinds.json` (created on first launch). Editing it manually is optional—the Mod Menu UI is recommended.

```json
{
"itemUses": [
{ "item": "minecraft:wind_charge", "hold": false, "key": 82 },
{ "item": "minecraft:ender_pearl", "hold": false, "key": 71 },
{ "item": "minecraft:white_wool", "hold": false, "key": 88 },
{ "item": "minecraft:bow", "hold": true, "key": 66 }
],
"shieldTotemKey": 72,
"maceStunSlamKey": 86,
"returnToStartSlotAfterSlam": false,
"shieldTotemVanilla": false,
"maceStunSlamVanilla": false,
"lungeSwapKey": -1,
"lungeSwapLeftClick": false,
"lungeSwapRightClick": false,
"lungeSwapHeldItems": [],
"spearItems": ["minecraft:wooden_spear", "minecraft:stone_spear", "minecraft:iron_spear", "minecraft:golden_spear", "minecraft:diamond_spear", "minecraft:netherite_spear"],
"lungeEnchant": "minecraft:lunge",
"lungeSwapVanilla": false,
"combatSwapToDelay": 2,
"combatUseDelay": 3,
"combatSwapBackDelay": 2
}
```

`key` values are raw [GLFW key codes](https://www.glfw.org/docs/latest/group__keys.html) (`82` = R, `71` = G, `72` = H, `86` = V), though you'll normally configure them through Mod Menu instead.

Supports **up to 32 Use Item binds**.
Macros live in `config/macros.json` (`formatVersion: 1`); triggers and actions are type-tagged JSON objects. Editing the file manually is optional — the in-game editor is recommended. Key values are raw [GLFW key codes](https://www.glfw.org/docs/latest/group__keys.html), captured for you by the editor.

## Building

Expand All @@ -122,4 +74,4 @@ To launch a development client:

## License

Released under **CC0**. Feel free to learn from it or incorporate it into your own projects.
Released under **CC0**. Feel free to learn from it or incorporate it into your own projects.
32 changes: 8 additions & 24 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,6 @@ version = project.mod_version
group = project.maven_group

repositories {
// Add repositories to retrieve artifacts from in here.
// You should only use this when depending on other mods because
// Loom adds the essential maven repositories to download Minecraft and libraries from automatically.
// See https://docs.gradle.org/current/userguide/declaring_repositories.html
// for more information about repositories.

// Mod Menu is distributed through Modrinth's maven.
exclusiveContent {
forRepository {
Expand All @@ -25,18 +19,21 @@ repositories {
}

dependencies {
// To change the versions see the gradle.properties file
minecraft "com.mojang:minecraft:${project.minecraft_version}"
implementation "net.fabricmc:fabric-loader:${project.loader_version}"

// Fabric API. This is technically optional, but you probably want it anyway.
implementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_api_version}"

// Mod Menu — provides the in-game config button. Optional at runtime (the modmenu
// entrypoint only loads when it is present), but needed on the compile classpath.
// 26.2 ships official mappings, so no remap configuration is needed — plain implementation
// puts the (already officially-mapped) jar on the classpath and Fabric loads it in dev.
// 26.2 ships official mappings, so no remap configuration is needed.
implementation "maven.modrinth:modmenu:${project.modmenu_version}"

testImplementation "net.fabricmc:fabric-loader-junit:${project.loader_version}"
testImplementation "org.junit.jupiter:junit-jupiter:5.11.4"
}

test {
useJUnitPlatform()
}

processResources {
Expand All @@ -53,11 +50,7 @@ tasks.withType(JavaCompile).configureEach {
}

java {
// Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task
// if it is present.
// If you remove this line, sources will not be generated.
withSourcesJar()

sourceCompatibility = JavaVersion.VERSION_25
targetCompatibility = JavaVersion.VERSION_25
}
Expand All @@ -71,19 +64,10 @@ jar {
}
}

// configure the maven publication
publishing {
publications {
create("mavenJava", MavenPublication) {
from components.java
}
}

// See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing.
repositories {
// Add repositories to publish to here.
// Notice: This block does NOT have the same function as the block in the top level.
// The repositories here will be used for publishing your artifact, not for
// retrieving dependencies.
}
}
6 changes: 3 additions & 3 deletions gradle.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Done to increase the memory available to gradle.
org.gradle.jvmargs=-Xmx1G
org.gradle.jvmargs=-Xmx2G
org.gradle.parallel=true

# IntelliJ IDEA is not yet fully compatible with configuration cache, see: https://github.com/FabricMC/fabric-loom/issues/1349
Expand All @@ -12,8 +12,8 @@ loader_version=0.19.3
loom_version=1.17-SNAPSHOT

# Mod Properties
mod_version=1.1.0
maven_group=com.example
mod_version=2.1.0-beta.0
maven_group=com.kingjayan

# Dependencies
fabric_api_version=0.154.0+26.2
Expand Down
Loading