4.4 KiB
4.4 KiB
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.pycopies. - Entry point:
python mosfet.pyfrom this repository root; use.venvdependencies. - Use the editable sibling
../pyCraftcheckout for shared protocol packet support. - Keep packet IDs and layouts aligned with
PROTOCOL_777.htmland 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. Readserver.propertiesfor the RCON password. - Use offline test accounts
mosfet1and, when an observer is needed,mosfet2; read passwords from environment variables, never hard-code them. - If
python mosfet.pyis 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 testsandgit diff --check. - Add regression tests for packet encodings, world-state behavior, and migrated job state transitions.
- Do not git commit changes until explicitly asked each time.
- If changes span both repositories, commit bot and pyCraft changes separately.
Theory
- Runtime flow:
mosfet.pyowns global state, the dashboard, and hot reload; it callsmosfet/connect.pyto connect and initialize the 26.3 runtime. - Connection setup:
connect.pyhandles offline login/AuthMe and wires the current world, entity, inventory, chat, command, game, and job adapters. - Packet-to-state flow:
../pyCraft/minecraft/networking/modern.pydefines protocol-777 wire packets;mosfet/protocol/modern.pyandpackets.pyadd bot-specific packet classes;mosfet/protocol/managers.pyupdates cached world, entities, and inventory. - Tick flow:
mosfet/bot.pyadvances movement/physics, then ticks the active job and game actions.mosfet/path.pysupplies A* navigation overmosfet/world.pyand the loaded block-state cache. - Commands and jobs:
mosfet/commands.pyparses chat commands;mosfet/job.pyselects existing job sequences; eachmosfet/jobs/*.pymodule implements a state machine. Keep job sequencing intact unless requested. - Game actions:
mosfet/game.pysends 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}.pyexposes it to runtime code.PROTOCOL_777.htmlis 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.pyinside a Python heredoc so the test can inspectapp.gand shut the bot down cleanly. Run from the repo root, keepSERVER=127.0.0.1.
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(time.monotonic(), "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
finallycleanup. - When printing during live checks, include
time.monotonic()to better understand the timing of events.