Fort様専用・作業記録

Speedmine 移植の記録

THM-Addons のパケットマイナーを QuinnAddon へ移植し、原典の不具合9件を直した作業の全記録。公開ページの日本語版に、Fort様向けの補足を加えたもの。

原典
THM 26.2
元の行数
1,507
移植後
1,440
修正
9
ミックスイン
3
ビルド
成功

何をしたか

渡したもの

ファイル中身
fixed/
Speedmine.java
不具合9件を直した版。1,440行。採用するのはこちら
port-only/
Speedmine.java
挙動は原典のまま、ビルドが通る形にしただけの版。1,384行。比較の基準点
changes.diff上2つの差分249行。修正だけを独立して読める
mixin/ 3本シーケンス番号・リブレイクのロールバック・Air Miner の接地偽装

英語の公開ページと、全ソースの閲覧は こちら 。 コードそのものは ソースページ で全文と raw が読める。

配布物

ファイル中身
QuinnAddon-Test
-0.1.0.jar
テスター用。Speedmine と2モジュールのみ。48KB。mod id もパッケージも本家と別なので共存できる
quinnaddon-test
-source.zip
その jar を作ったプロジェクト一式
QuinnAddon-v0.4.0
-with-speedmine.jar
本家のタグ v0.4.0 に全部マージしてビルドが通ることの証明。リリースではない
SHA256SUMS.txt上3つのハッシュ

ハッシュが証明するのは「転送中に化けていないこと」だけで、中身の安全性は何も保証しない。だから同じ場所にソースを置いてある。

ライセンス(守る必要のある条件)

原典のヘッダに、次の記載がある。これは好意ではなく使用条件。

Copyright (c) THM Addons contributors. Credit the devs, keep the link.
By using this code you agree to the license terms and to keep your repo public.

したがって移植版にも THM へのリンクと出典を残した。QuinnAddon は public なので「公開リポジトリのままにする」条件も満たしている。このヘッダを消すとライセンス違反になるので、Quinn にもそう伝えてある。クローズドソース配布が選べなかったのも、この条項による。

なぜコピペで済まなかったか

THM は Mojang マッピング、QuinnAddon は Yarn。全クラス名・メソッド名が違うので、1行もそのままでは通らない。加えて THM は自前の支援クラスに依存しており、QuinnAddon にはどれも存在しない。

THM移植版
MojangマッピングYarn。mc.level→mc.world、ServerboundPlayerActionPacket→PlayerActionC2SPacket
InventoryManagerサーバースロットの自前追跡(UpdateSelectedSlotC2SPacket)
RangeUtilsファイル内の isInRange() / closestFace()
RenderUtilsTHMRender3DEvent.renderer.box()
手書きの採掘速度式BlockUtils.getBreakDelta(slot, state)。Meteor が既に持っていた
ClientLevelミックスインMeteor の BlockUpdateEvent
シーケンス送信アクセサ同じ発想で、自前のインボーカーを ClientPlayerInteractionManager に
PaketLimiter等削除。THM固有
fromTag()設定移行削除。移行対象なし

とくに大きいのは採掘速度の式。THM はこれを手書きし、しかも2箇所に重複して、内容が食い違っていた。Meteor が同じ計算を持っているので、移植版では丸ごと消えている。ワールド更新用のミックスインも不要になった。

THM との挙動差

設定は35項目すべて移植済みで、欠落も追加もない。以下は挙動の差で、いずれも QuinnAddon に対応する仕組みが無いことに由来する。

直した9件

  1. 断ったクリックが完全に無反応だった

    判定前にイベントを cancel していたため、multitask off でアイテム使用中にブロックを左クリックすると、パケット採掘もバニラ採掘もせず何も起きなかった。引き受けたときだけ cancel するようにした。

  2. requestBreak がモジュール全体を止めうる

    空気かどうかしか見ていないため、掘れないブロックを渡されると進捗ゼロのまま primary 枠を永久に占有した。検証と3秒の停滞タイムアウトを追加。原典の未使用フィールド startMs は、このタイムアウトを入れ忘れた痕跡に見える。

  3. キュー追加1箇所だけ immutable() が無い

    他3箇所には付いていた。現在の呼び出し元では表に出ないが、MutableBlockPos が1つ入るだけで中身が後から書き換わる。

  4. 差し替えられたブロックを掘り続ける

    開始時の state を保持したまま削除判定だけが現在のワールドを見るため、古い硬度で進捗が進み、破壊パーティクルも別ブロックのものになる。

  5. surround が1段ずれる

    敵の Y を Math.round していたため、ハーフブロック・雪・ソウルサンドの上でリング全体が上にずれる。floor に修正。

  6. 死亡モーション中の敵を狙う

    isSpectator は見ていたが isAlive を見ていなかった。

  7. 道具探索が「道具なし」を返せない

    初期値 -1 は素手でも超えるため、該当分岐が全部死にコード。同点で常に低い番号が勝つので、手に持っている最適な道具からわざわざ持ち替えていた。選択中スロットを起点にした。

  8. 同じタイムアウトが単位違いで二重管理

    ms と ns で別々に書かれていた。定数1つから導出するようにした。

  9. 枠線が rebreak-mode Off を無視

    他のリブレイク判定は全てモードを見ているのに、描画だけ見ていなかった。

わざと直していないもの

ビルド確認

Minecraft 1.21.11、Yarn 1.21.11+build.3、meteor-client:1.21.11-SNAPSHOT でビルド成功。gradlew build が compileJava → jar → remapJar まで完走し、jar に Speedmine.class とアクセサ3本が入っている。

途中で実際に出た不具合は1件。PendingUpdateManager は net.minecraft.client.network にあり(client.world ではない)、ClientWorld.getPendingUpdateManager() は非公開だった。これが2本目のミックスインが要る理由。怪しいと事前に挙げていた isGliding()・PlayerMoveC2SPacket.Full・getSelectedSlot() は全て正しかった。

覆っていないこと: ゲーム内で一度も動かしていない。ミックスインはコンパイルも登録も済んでいるが、実行時に適用されるか、実戦のアンチチートがどう反応するかは未検証。

insta rebreak の問いへの答え

Quinn の元投稿は「FutureClient / Mio の speedmine、とくに insta rebreak の水準か」だった。全文を読んだ上での所見。

実際に同水準かは読んで分かることではなく測って分かることで、ゲーム内未検証。ただし答えは設定1つ分の距離にある。debug-rebreak を入れて、他のクライアントも同条件で並べて数字を比べればよい。

InventoryCleaner と AutoAccept

どちらも依頼外。Fort様の持ち込みで、こちらの判断で入れた。Speedmine はどちらにも依存していないので、外しても何も壊れない。公開ページにも「頼まれていない」と明記してある。

両方とも、そもそもコンパイルが通らなかった。 InventoryCleaner は Category.Misc(Category はクラスで、正しくは Categories)。AutoAccept は存在しない Addon クラスと utils.Utils を参照し、さらに GameProfile.getName() が record 化で name() になっていた。

未対応:InventoryCleaner のオフハンド(走査範囲外)、AutoAccept のチャット判定が発見的手法である点(珍しい文面形式なら抜けうる。タブリスト照合がその保険)。

QuinnAddon でやるとよいこと

こちらの取りこぼし(記録)

Fort様に指摘されて見つかった、私の側の不手際。公開ページには書いていない。

  • パケット起点リブレイクの予測管理を落としていた。 THM が持っていた「サーバーには実際にブロックがある」と予測管理に教える処理を、移植時に削った。リブレイクが弾かれたときのロールバック先が空気になり、実在しない穴が見える可能性があった。Quinn が最も気にしている rebreak のど真ん中
  • 選択肢ごとの説明文を全部消していた。 THM が各列挙値に付けていた1行説明が、独自インターフェース経由だったため移植で消滅していた
  • swap-mode の表示名を消していた。「Keep for Next Tick」等のラベルが、素の定数名で表示される状態だった

原因は、移植中に「これは THM 固有だから落としてよい」と判断したものの中に、固有でないものが混ざっていたこと。設定35項目とメソッドを機械的に突き合わせて洗い出し、全部直した。最初からその突き合わせをしてから報告すべきだった。

もう1件、公開ページの <section> 開始タグを節の差し替え時に落とし、HTML構造を壊していた。見た目はほぼ変わらなかったが、後で気づいて修復した。

残っている判断