Files
minecraft-bot/AGENTS.md
T

68 lines
4.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Bot Development Notes
- Target **Minecraft 26.3 / protocol 777 only**. Do not add old-version compatibility.
- Put protocol-777 changes in the main modules; do not create `*_26_3.py` copies.
- Entry point: `python mosfet.py` from this repository root; use `.venv` dependencies.
- Use the editable sibling `../pyCraft` checkout for shared protocol packet support.
- Keep packet IDs and layouts aligned with `PROTOCOL_777.html` and the local 26.3 server; do not infer them from older protocol versions.
- You can test bots on the Minecraft server running locally: `SERVER=127.0.0.1`.
- The local server runs out of `~/tmp/minecraft`. Read `server.properties` for the RCON password.
- Use offline test accounts `mosfet1` and, when an observer is needed, `mosfet2`; read passwords from environment variables, never hard-code them.
- If `python mosfet.py` is already running, feel free to kill the script.
- Stop test bots and confirm no bot process remains afterward.
- Don’t change existing job sequencing/behavior unless the request asks for it; port packet and data handling in place.
- Check README and command gates before assuming a legacy command is available on 26.3.
- Run tests with `.venv/bin/python -m unittest discover -s tests -v`.
- Run a syntax check with `.venv/bin/python -m compileall -q mosfet tests` and `git diff --check`.
- Add regression tests for packet encodings, world-state behavior, and migrated job state transitions.
- If changes span both repositories, commit bot and pyCraft changes separately.
## Theory
- **Runtime flow:** `mosfet.py` owns global state, the dashboard, and hot reload; it calls `mosfet/connect.py` to connect and initialize the 26.3 runtime.
- **Connection setup:** `connect.py` handles offline login/AuthMe and wires the current world, entity, inventory, chat, command, game, and job adapters.
- **Packet-to-state flow:** `../pyCraft/minecraft/networking/modern.py` defines protocol-777 wire packets; `mosfet/protocol/modern.py` and `packets.py` add bot-specific packet classes; `mosfet/protocol/managers.py` updates cached world, entities, and inventory.
- **Tick flow:** `mosfet/bot.py` advances movement/physics, then ticks the active job and game actions. `mosfet/path.py` supplies A* navigation over `mosfet/world.py` and the loaded block-state cache.
- **Commands and jobs:** `mosfet/commands.py` parses chat commands; `mosfet/job.py` selects existing job sequences; each `mosfet/jobs/*.py` module implements a state machine. Keep job sequencing intact unless requested.
- **Game actions:** `mosfet/game.py` sends current-protocol actions such as block breaking, inventory selection, item use, and punches/arm swings.
- **Data:** `mosfet/info/data/26.3/` contains checked-in Minecraft data; `mosfet/info/{blocks,items,mobs,mcdata}.py` exposes it to runtime code. `PROTOCOL_777.html` is the local packet reference.
- **Validation:** `tests/` contains offline regression tests; use the test and compile commands above before committing.
## Live Checks
- For one-off live checks, start `mosfet.py` inside a Python heredoc so the test can inspect `app.g` and shut the bot down cleanly. Run from the repo root, keep `SERVER=127.0.0.1`, and let `GAME_PASSWORD` come from the environment.
```sh
SERVER=127.0.0.1 PLAYER_NAME=mosfet1 .venv/bin/python - <<'PY'
import importlib.util, os, threading, time
spec = importlib.util.spec_from_file_location(
"mosfet_runtime", os.path.abspath("mosfet.py"))
app = importlib.util.module_from_spec(spec)
spec.loader.exec_module(app)
g = app.g
runner = threading.Thread(target=app.main, name="mosfet-test", daemon=True)
runner.start()
try:
deadline = time.monotonic() + 20
while time.monotonic() < deadline:
if g.get("connected") and g.get("pos") and g.chunks.check_loaded(2):
break
time.sleep(0.1)
else:
raise TimeoutError("bot did not finish joining/loading nearby chunks")
print("mosfet1 position:", tuple(g.pos))
g.commands.handle_chat(("CHAT", "test", "tester: 1ping"))
finally:
if g.get("job") and g.get("connection") and g.connection.connected:
g.job.stop()
g.running = False
runner.join(timeout=5)
if runner.is_alive():
raise RuntimeError("bot test thread did not stop")
PY
```
- Give enough time for the bot and world to load.
- Always include the `finally` cleanup.