124 lines
4.7 KiB
Markdown
124 lines
4.7 KiB
Markdown
|
|
# Carpet Bot Manager (`cbot`)
|
||
|
|
|
||
|
|
Fabric mod that adds player-owned bot management on top of Fabric Carpet's `/player` command.
|
||
|
|
|
||
|
|
The mod can run server-side only for command-based management. If the same jar is installed on both the server and the client, players can also manage their own bots through a GUI.
|
||
|
|
|
||
|
|
## Dependencies
|
||
|
|
|
||
|
|
- Minecraft `1.21.11` (Yarn mapped)
|
||
|
|
- Fabric Loader
|
||
|
|
- Fabric API
|
||
|
|
- Fabric Carpet (for `/player`-based spawn/actions)
|
||
|
|
|
||
|
|
Build system: Gradle + Fabric Loom (project files included).
|
||
|
|
|
||
|
|
If Carpet is missing, `/cbot` still registers, but Carpet-backed actions (`spawn` and forwarded actions) return:
|
||
|
|
`Carpet mod is not installed`.
|
||
|
|
|
||
|
|
## Client GUI
|
||
|
|
|
||
|
|
Install `cbot` on both the server and client to enable the GUI.
|
||
|
|
|
||
|
|
- `/cbot gui`
|
||
|
|
- Opens the client GUI when the player has the client mod installed.
|
||
|
|
- Without the client mod, the server returns `Install cbot on your client to use the GUI`.
|
||
|
|
- Keybind: `Open Carpet Bot Manager`
|
||
|
|
- Default is unbound.
|
||
|
|
- Configure it in Minecraft controls under `Carpet Bot Manager`.
|
||
|
|
|
||
|
|
The GUI is personal bot management only. Admin configuration remains command-only.
|
||
|
|
|
||
|
|
GUI actions are still server-authoritative:
|
||
|
|
|
||
|
|
- The client sends only bot IDs and action parameters.
|
||
|
|
- The server resolves bot ownership from the executing player.
|
||
|
|
- Bot actions still dispatch only restricted `player <ownedBotName> ...` or `tp <ownedBotName> ...` commands.
|
||
|
|
|
||
|
|
## Commands
|
||
|
|
|
||
|
|
- `/cbot list`
|
||
|
|
- Shows owned bot IDs, names, and online status.
|
||
|
|
- `/cbot buy`
|
||
|
|
- Buys one additional bot using the configured price.
|
||
|
|
- `/cbot gui`
|
||
|
|
- Opens the client GUI if the client also has cbot installed.
|
||
|
|
- `/cbot <id> spawn`
|
||
|
|
- Runs `player <botName> spawn` as server source.
|
||
|
|
- `/cbot <id> tp`
|
||
|
|
- Runs `tp <botName> <playerName>`.
|
||
|
|
- `/cbot <id> tp <x> <y> <z>`
|
||
|
|
- Runs `tp <botName> <x> <y> <z>`.
|
||
|
|
- `/cbot <id> <carpetAction...>`
|
||
|
|
- Forwards to `player <botName> <carpetAction...>`.
|
||
|
|
- Provides autocomplete hints for common Carpet actions while still forwarding the action text unchanged.
|
||
|
|
|
||
|
|
Admin-only config commands require permission level 4:
|
||
|
|
|
||
|
|
- `/cbot config show`
|
||
|
|
- Shows the current bot name pattern, free bot count, price, and cap.
|
||
|
|
- `/cbot config botname "<pattern>"`
|
||
|
|
- Sets the bot name pattern and renames saved bot identities.
|
||
|
|
- Supported placeholders: `{player}`, `{id}`, `{uuid}`.
|
||
|
|
- Generated bot names are sanitized and deterministically shortened to Minecraft's 16-character player-name limit.
|
||
|
|
- `/cbot config starting-free <count>`
|
||
|
|
- Sets how many free bots players are topped up to on next join or `/cbot` use.
|
||
|
|
- `/cbot config price <item> <count>`
|
||
|
|
- Sets the buy price, for example `minecraft:diamond 2`.
|
||
|
|
- A count of `0` makes buying free.
|
||
|
|
- `/cbot config cap <count>`
|
||
|
|
- Sets the maximum total bots per player.
|
||
|
|
- `/cbot config cap none`
|
||
|
|
- Removes the bot cap.
|
||
|
|
- `/cbot config reset`
|
||
|
|
- Restores defaults and renames saved bot identities back to the default pattern.
|
||
|
|
|
||
|
|
## Ownership and persistence
|
||
|
|
|
||
|
|
- Ownership is stored per world in a `PersistentState`:
|
||
|
|
- `Map<UUID, List<String>> botNames`.
|
||
|
|
- By default, a player gets exactly one starter bot:
|
||
|
|
- `cbot_<ownerName>_1`.
|
||
|
|
- Additional bots are deterministic and per-owner:
|
||
|
|
- `cbot_<ownerName>_<n>`.
|
||
|
|
- Defaults:
|
||
|
|
- Bot name pattern: `cbot_{player}_{id}`
|
||
|
|
- Starting free bots: `1`
|
||
|
|
- Price: `1` `minecraft:netherite_block`
|
||
|
|
- Bot cap: none
|
||
|
|
- Changing `botname` renames saved identities immediately. Already-spawned old-name fake players are not killed automatically.
|
||
|
|
|
||
|
|
## Security model
|
||
|
|
|
||
|
|
`/cbot` executes underlying commands with elevated server permissions, but only after validation:
|
||
|
|
|
||
|
|
- Executor must be a real `ServerPlayerEntity`.
|
||
|
|
- Bot ID must resolve from that player's owned list.
|
||
|
|
- Commands are restricted to:
|
||
|
|
- `player <resolvedBotName> ...`
|
||
|
|
- `tp <resolvedBotName> ...`
|
||
|
|
- All dispatches are logged with owner UUID/name, bot name, action, and command string.
|
||
|
|
|
||
|
|
This prevents arbitrary command execution through `/cbot`.
|
||
|
|
|
||
|
|
## Quick test plan
|
||
|
|
|
||
|
|
1. Fresh world: join as PlayerA, run `/cbot list`, verify 1 starter bot.
|
||
|
|
2. Run `/cbot 1 spawn`, verify bot appears.
|
||
|
|
3. Run `/cbot 1 use once`, verify forwarding works.
|
||
|
|
4. Give netherite block, run `/cbot buy`, verify bot #2 appears in `/cbot list`.
|
||
|
|
5. Join PlayerB, verify PlayerB cannot manage PlayerA's bot IDs.
|
||
|
|
6. Restart server, verify ownership persists.
|
||
|
|
7. As an operator, run `/cbot config starting-free 3`, verify an existing player is topped up on the next `/cbot list`.
|
||
|
|
8. Run `/cbot config botname "cbot{id}_of_{player}"`, verify saved bot names are renamed and stay spawnable.
|
||
|
|
|
||
|
|
## E2E tests
|
||
|
|
|
||
|
|
Run the Mineflayer-based E2E test with:
|
||
|
|
|
||
|
|
```sh
|
||
|
|
npm run e2e
|
||
|
|
```
|
||
|
|
|
||
|
|
The test starts `./gradlew runServer`, ensures Fabric Carpet is available in `run/mods`, connects real network players with Mineflayer in offline mode, executes `/cbot` commands, checks chat responses, and stops the server.
|