Skip to content

Add examples for q03, q04, and q06 with various fixes - #71

Merged
xinshoutw merged 10 commits into
mainfrom
dev
Aug 2, 2026
Merged

xinshoutw merged 10 commits into
mainfrom
dev

Conversation

@xinshoutw

Copy link
Copy Markdown
Contributor

This pull request adds a variety of new example scripts and documentation for quest solutions, as well as a bugfix note in the documentation and an additional workflow check. The main focus is on providing reference implementations for "random_quests" and new quest stages, along with improved documentation for library and restaurant quests. Additionally, the workflow now verifies that the release tag matches the version in pyproject.toml.

New example scripts and quest solutions:

  • Added complete reference solutions for all "random_quests" tasks, each as a self-contained Python script under examples/quests/random_quests/, along with a comprehensive README.md explaining their use and caveats. [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13]
  • Added new example scripts for quest "q03_dance" state 1 and 2, demonstrating how to interact with block properties and sequence actions based on game state. [1] [2]
  • Added new example scripts for quest "q06_restaurant" stages 1 and 2, showcasing event-driven handling of in-game messages and dynamic calculation of coin combinations for change-making tasks. [1] [2]

Documentation improvements:

  • Added a detailed README.md for the "q04_library" quest, listing book locations, hints, and the command to give the written book, to guide users through the quest.

Bugfix notes and workflow improvements:

  • Documented a critical bug and its workaround regarding entity velocity handling in the AGENTS.md file, explaining the NaN position issue and the temporary JavaScript-side repair logic.
  • Updated the GitHub Actions workflow (.github/workflows/publish.yml) to add a step that verifies the release tag matches the version specified in pyproject.toml, preventing mismatched releases.

huangtank and others added 10 commits July 31, 2026 01:09
q03_dance 第一、二關優化
q04_library 新增指令,給予書本
q06_restaurant 錯字修正
* ci(publish): fail fast when tag does not match pyproject version

- v0.4.10 was tagged while pyproject.toml still declared 0.4.9, so uv build
  produced 0.4.9 artifacts and PyPI rejected them with "File already exists"
- add a guard right after the on-main check so the mismatch is caught in
  seconds instead of after tests, build and a failed upload
- read the version with tomllib rather than grep so the check does not depend
  on the field's formatting
- deliberately not using skip-existing: it would have hidden this mismatch and
  silently published nothing

* chore(release): bump version to 0.4.10

- the v0.4.10 tag already exists on origin and points at main HEAD, but the
  packaged version was never bumped

* fix(runtime): repair NaN knockback velocity from mineflayer/minecraft-data skew

mineflayer 4.37.0 gates the 1.21.2+ nested velocity shape of
entity_velocity behind supportFeature('entityVelocityIsLpVec3'), a
feature the minecraft-data it installs against (<= 3.110.x) never
shipped. The legacy branch then reads packet.velocityX (undefined on
1.21.2+), fromNotchVelocity turns Vec3(undefined) into NaN on
entity.velocity, and the first hit the bot takes lets the physics tick
integrate NaN into bot.entity.position. JSPyBridge serializes NaN as
null, so every position read in Python becomes None and a student's
move_forward() dies with "float() ... not 'NoneType'" the moment a
player lands a punch.

- install a node-side entity_velocity listener via eval_js at
  create_bot that re-parses the nested shape (packet.velocity / 8000
  per axis); zero bridge traffic per packet, no-op on flat velocityX
  packets and on healthy minecraft-data pairings
- unit-test the Python wiring: missing-client warn path, eval/install
  handshake, create_bot call site
- add an integration test that runs the JS against a real node
  EventEmitter (needs node only, no Minecraft server)
- document the repair and its removal condition in AGENTS.md

Upstream has since fixed the pairing (minecraft-data master carries the
feature, mineflayer master dropped the gate), so the repair becomes
removable once the bundled mineflayer pin moves past 4.37.x; it stays
harmless if left in. Verified live against the camp server: spawn,
get_pos and move_forward all work with the repair installed.

* chore(version): bump version to 0.4.11 in pyproject.toml and uv.lock

* @
feat(examples): 新增 random_quests 十五題加分題的參考解答

datapack 與 Skript 兩側已完成,minethon 這邊補上學員程式。每題一個資料夾,
一律 create_bot("bonus"),全部是直線腳本:join.sk 的登入閘門保證機器人只可能
在題目進行中上線,不需要用迴圈等題目開始。

第 5、8、14、15 題是解密題,密文每輪由伺服器隨機抽(第 15 題寫死),
範例裡的 cipher 與答案要換成當場公告的那一組。
@

* @
docs(examples): 第 15 題也有四組密文變體

原本 README 寫「第 15 題密文寫死、範例可以整支直接跑」,那是建立在
「Skript 讀不到 fake player 分數」這個已經過期的前提上。
@

* @
docs(examples): 說明進度跨重連累積

伺服器每輪只抓一次統計基準,做到一半中斷、改完再跑是接著算的,計數類題目
因此也不需要迴圈硬撐。
@

* fix(examples): 修正 random_quests 示範的迴圈與跳躍節奏

- README 的「進度跨重連累積」寫反了:基準是登入那一刻抓的,重跑程式=斷線重連
  =基準重抓,做到一半的進度會歸零,所以一次執行就要做滿門檻
- 因此拿掉 t03/t04/t05/t06 的 while True,一次做完就結束
- t03/t13 補 bot.wait(0.5):bot.jump() 按完鍵就返回、不等落地,而跳躍鍵只在
  站在地上時有作用,連續呼叫約有一半是在半空中按的,十次只跳得出約五下
- t09 轉向同理補 bot.wait(0.6)
- t05/t08/t14/t15 的密文改成佔位字串,並補上解密迴圈與 print,讓學員自己判讀

---------

Co-authored-by: xinshoutw <me@xinshou.tw>
@xinshoutw
xinshoutw merged commit f42d2dd into main Aug 2, 2026
4 checks passed
@greptile-apps

greptile-apps Bot commented Aug 2, 2026

Copy link
Copy Markdown

Greptile Summary

The PR adds runnable examples and documentation for dance, library, restaurant, and random quests, and advances the package version to 0.4.12.

  • Adds staged dance and event-driven restaurant reference implementations.
  • Adds fifteen straight-line random-quest examples and usage guidance.
  • Adds library quest location documentation.
  • Synchronizes the project and lockfile package versions.

Confidence Score: 4/5

The restaurant examples need fixes before merging because arbitrary player chat can trigger inventory loss and, in stage 2, resource exhaustion.

Both handlers ignore the message-position argument and trust matching text from the broad messagestr event; stage 2 also allocates and processes a table whose size is directly controlled by the parsed message amount.

Files Needing Attention: examples/quests/q06_restaurant/state_1/main.py, examples/quests/q06_restaurant/state_2/main.py

Security Review

The restaurant examples process player-chat messages as trusted quest instructions. Both stages can be induced to discard inventory, and stage 2 additionally permits an unbounded message-controlled allocation and computation.

Important Files Changed

Filename Overview
examples/quests/q06_restaurant/state_1/main.py Adds a change-making message handler, but any matching player-chat message can trigger inventory drops.
examples/quests/q06_restaurant/state_2/main.py Adds dynamic-programming change calculation with unrestricted chat-triggered inventory actions and an unbounded amount-controlled allocation.
examples/quests/q03_dance/state_2/main.py Adds lamp-sequence recording and replay logic; no concrete defect was established.
examples/quests/random_quests/README.md Documents task behavior, execution constraints, pacing, and required per-round placeholder replacement.
pyproject.toml Advances the package version from 0.4.11 to 0.4.12, synchronized with the lockfile.
uv.lock Synchronizes the editable package version with pyproject.toml.

Fix All in Claude Code

Prompt To Fix All With AI
### Issue 1
examples/quests/q06_restaurant/state_1/main.py:10-11
**Untrusted chat triggers inventory drops**

When any player sends a message containing `請幫我找零` and a parseable amount, both restaurant handlers ignore the supplied message position and treat it as a trusted quest broadcast, causing the bot to discard currency from its inventory. Restrict processing to the expected `system` or `game_info` position. **How this was verified:** The `messagestr` callback exposes `chat`, `system`, and `game_info` positions, but these handlers discard that argument before invoking `bot.drop()`.

### Issue 2
examples/quests/q06_restaurant/state_2/main.py:23-25
**Message amount controls unbounded allocation**

When a player sends a matching message with a very large numeric amount, the handler allocates one five-element list per unit and then iterates over the entire table, exhausting memory or stalling the bot process. Validate a quest-appropriate upper bound before constructing `dp`. **How this was verified:** The unrestricted message amount is converted with `int()` and passed directly to `range(target_money + 1)` without a range check.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Reviews (1): Last reviewed commit: "Merge branch 'main' into dev" | Re-trigger Greptile

Comment on lines +10 to +11
if "請幫我找零" not in msg_str:
return

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 security Untrusted chat triggers inventory drops

When any player sends a message containing 請幫我找零 and a parseable amount, both restaurant handlers ignore the supplied message position and treat it as a trusted quest broadcast, causing the bot to discard currency from its inventory. Restrict processing to the expected system or game_info position. How this was verified: The messagestr callback exposes chat, system, and game_info positions, but these handlers discard that argument before invoking bot.drop().

Knowledge Base Used: Example Quests and the Unit Test Suite

Prompt To Fix With AI
This is a comment left during a code review.
Path: examples/quests/q06_restaurant/state_1/main.py
Line: 10-11

Comment:
**Untrusted chat triggers inventory drops**

When any player sends a message containing `請幫我找零` and a parseable amount, both restaurant handlers ignore the supplied message position and treat it as a trusted quest broadcast, causing the bot to discard currency from its inventory. Restrict processing to the expected `system` or `game_info` position. **How this was verified:** The `messagestr` callback exposes `chat`, `system`, and `game_info` positions, but these handlers discard that argument before invoking `bot.drop()`.

**Knowledge Base Used:** [Example Quests and the Unit Test Suite](https://app.greptile.com/xinshoutw/-/custom-context/knowledge-base/hack-the-sdgs/minethon/-/docs/testing-quests.md)

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Fix in Claude Code

Comment on lines +23 to +25
dp = []
for i in range(target_money + 1):
dp.append([257, 0, 0, 0, 0])

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 security Message amount controls unbounded allocation

When a player sends a matching message with a very large numeric amount, the handler allocates one five-element list per unit and then iterates over the entire table, exhausting memory or stalling the bot process. Validate a quest-appropriate upper bound before constructing dp. How this was verified: The unrestricted message amount is converted with int() and passed directly to range(target_money + 1) without a range check.

Knowledge Base Used: Example Quests and the Unit Test Suite

Prompt To Fix With AI
This is a comment left during a code review.
Path: examples/quests/q06_restaurant/state_2/main.py
Line: 23-25

Comment:
**Message amount controls unbounded allocation**

When a player sends a matching message with a very large numeric amount, the handler allocates one five-element list per unit and then iterates over the entire table, exhausting memory or stalling the bot process. Validate a quest-appropriate upper bound before constructing `dp`. **How this was verified:** The unrestricted message amount is converted with `int()` and passed directly to `range(target_money + 1)` without a range check.

**Knowledge Base Used:** [Example Quests and the Unit Test Suite](https://app.greptile.com/xinshoutw/-/custom-context/knowledge-base/hack-the-sdgs/minethon/-/docs/testing-quests.md)

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Fix in Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants