Skip to content

feat: add Minecraft 26.1.2 spigot support with auto beta-tag workflow#23

Open
clawd131662[bot] wants to merge 3 commits into
v3.0-forkfrom
claude/minecraft-26.1.2-upgrade-dTYWZ
Open

feat: add Minecraft 26.1.2 spigot support with auto beta-tag workflow#23
clawd131662[bot] wants to merge 3 commits into
v3.0-forkfrom
claude/minecraft-26.1.2-upgrade-dTYWZ

Conversation

@clawd131662
Copy link
Copy Markdown

@clawd131662 clawd131662 Bot commented May 4, 2026

Summary

  • Adds bukkit-helper-26-1-2 (cloned from bukkit-helper-121-11), pointing at the Paper dev bundle 26.1.2.build.57-stable. Replaces the removed BlockState#getLightBlock() call with the renamed getLightDampening() introduced in MC 26.1.
  • Bumps io.papermc.paperweight.userdev to 2.0.0-beta.21 (required for paperweight data version 8 dev bundles) and adds org.gradle.toolchains.foojay-resolver-convention 1.0.0 so the JDK 25 toolchain Paper 26.1+ requires is auto-provisioned by Gradle.
  • Wires the new helper into spigot/build.gradle and routes every (MC: 26.x) server in spigot/.../Helper.java to it. Bumps the project version to 26.1.2-beta.1.
  • Compiles the helper with the JDK 25 toolchain but emits Java 21 bytecode via options.release = 21 (so the Shadow plugin running on JDK 21 can read its class files), while pinning the org.gradle.jvm.version resolution attribute to 25 so the Java-25-only paper-api still resolves. Spigot consumes this module via the default configuration to bypass paperweight's empty reobf variant (Paper 26.1+ ships Mojang-mapped only).
  • Synchronizes MapChunkCache26_1_2.initReflection() and BukkitVersionHelperSpigot26_1_2.initCraftBukkitClasses() to fix a lazy-init race where one render thread observed initialized==true while another was still populating the static Method fields, surfacing as NullPointerException on craftWorldGetHandle.invoke().
  • Adds .github/workflows/auto-tag-beta.yml: every push to a claude/** branch computes the next 26.1.2-beta.N, syncs build.gradle, commits the bump back with [skip ci], builds the spigot jar with the JDK 25 toolchain and publishes a GitHub Release with the jar attached. Concurrency is serialized across branches (group: auto-tag-beta) so simultaneous pushes don't race for the same tag. The workflow does NOT create PRs; that is done out-of-band by an operator with pull_requests:write.
  • Migrates release.yml off the deprecated actions/upload-release-asset@v1 and uses gh release upload --clobber instead.

Verification

  • ./gradlew :spigot:build succeeds locally and produces target/Dynmap-26.1.2-beta.N-spigot.jar (Java 25 toolchain auto-fetched via foojay).
  • The auto-tag-beta workflow ran successfully on each push and produced release 26.1.2-beta.1 onwards with the spigot jar attached.

Test plan

  • Subsequent pushes auto-increment to 26.1.2-beta.2, .3, ...
  • Plugin loads on a Paper 26.1.2 server and the dynamic map renders correctly.

@shikendon
Copy link
Copy Markdown
Member

Review Summary

整體方向 OK,跑得起來(自動發 release 已經到 beta.6),但有幾個值得在合併前處理的點。

已修好的部分

  • cab31fe6 把 paperweight 預設指向空 reobf variant 的問題收掉了,根因(disable reobfJar 後 consumer 抓到空 artifact)的說明完整。
  • 016b856finitCraftBukkitClasses() / initReflection() 加上 synchronized,原本 if (initialized) return; initialized = true; 的 broken double-check race 修掉了。
  • release.yml 從 deprecated 的 actions/upload-release-asset@v1 遷到 gh release upload --clobber,沒問題。

建議在 merge 前處理(功能性)

  1. 同樣的 lazy-init race 還在 BukkitVersionHelperSpigot26_1_2.getBiomeReg()(檔案約 358–369 行)。 biomeRegistry == null 檢查 + getKeyMethod / getIdMethod 三個 static 欄位賦值,跟剛修掉的 pattern 一模一樣;MapChunkCache26_1_2 的 async 路徑會多執行緒打到 helper,這裡同樣會壞。建議一起補 synchronized,或乾脆把整段反射搬去 static { ... } 區塊讓 JVM class-init 鎖去保證。
  2. Spigot fallback package org.bukkit.craftbukkit.v1_21_R7(兩個 helper 檔的 initCraftBukkitClasses / initReflection 內)對 MC 26.1 的真實 Spigot 版本幾乎不可能還是 v1_21_R7。要嘛實際對 Spigot 26.1.2 build 確認過真名後改掉,要嘛刪掉 fallback 只留 Paper unversioned 路徑,免得問題真的出現時被 fallback 蓋掉真實錯誤。
  3. BukkitVersionHelperSpigot26_1_2 裡的 craftServerClass / craftServerGetServer 查了沒用,可以刪。

建議改善(非阻擋)

  1. spigot/build.gradleconfiguration: 'default'include(dependency(':bukkit-helper-26-1-2:.*')) 跟兄弟模組寫法不一致,是繞過 Gradle variant 解析的 workaround。請在註解裡明寫「workaround for paperweight registering empty reobf as preferred runtime variant」,否則之後維護者很容易把它「對齊」回去然後弄壞 build。
  2. 整條 cross-compile dance(toolchain 25 + options.release = 21 + 屬性蓋回 25)的本質原因是 workflow 的 Gradle 跑在 JDK 21(為了 Shadow 9.x)。等 Shadow 支援 JDK 25 之後可以整段拆掉,建議在 bukkit-helper-26-1-2/build.gradle 留一個 // FIXME: drop once Shadow runs on JDK 25 之類的 marker。
  3. auto-tag-beta.yml 仍是 branches: ['claude/**'] + 跨分支用同一個 concurrency group。5dacd4a1 已接受「跨分支序列化」這個現實,但所有 claude/** 分支共用 26.1.2-beta.N 命名空間並不直覺;至少在 workflow 開頭註解寫清楚。
  4. auto-tag-beta.yml26.1.2 寫死在 git tag --list filter、sed 與 release notes。下一個 MC 版本得在三處同時改;建議從 build.gradle 的 base version 推導出來。
  5. Helper.java(MC: 26. 是 prefix 比對,未來若加 (MC: 26.2.x) 專屬 helper,記得擺在這條前面,否則會被吞掉。

沒有 blocking 的問題

Identifiernet.minecraft.resources.Identifier)這個 import 看起來反直覺,但既然 :spigot:build 過了、自動 release 也跑到 beta.6,視為已驗證即可。

LGTM once (1) the getBiomeReg race is fixed and (2) the Spigot fallback prefix is either corrected or removed. 其餘可以以 follow-up issue / FIXME 的形式留在後面處理。

shikendon pushed a commit that referenced this pull request May 4, 2026
Blocking points called out in review of #23:

- BukkitVersionHelperSpigot26_1_2.getBiomeReg() had the same
  broken-double-checked-locking shape as initReflection /
  initCraftBukkitClasses (race between `if (biomeRegistry == null)` and
  the static field assignments). Add `synchronized` so all three reach
  callers with consistent state.
- Drop the bogus `org.bukkit.craftbukkit.v1_21_R7` Spigot fallback in
  both initCraftBukkitClasses and MapChunkCache26_1_2.initReflection.
  The package name was a guess and a wrong fallback would mask a real
  ClassNotFoundException with a misleading "fell through to Spigot"
  path. If/when a Spigot-versioned helper is needed, add it after
  confirming the package against an actual Spigot 26.1.2 build.
- Remove the now-unused craftServerClass / craftServerGetServer fields
  from BukkitVersionHelperSpigot26_1_2 (they were looked up but never
  invoked; the helper that does need them lives in MapChunkCache26_1_2).

Non-blocking polish from the same review:

- spigot/build.gradle: expand the comment around the `configuration:
  'default'` workaround so future maintainers don't "align" the entry
  back to the sibling helper modules' style and break the build.
- bukkit-helper-26-1-2/build.gradle: add a FIXME marker for the
  toolchain-25 + `--release 21` + JVM-25-attribute dance. It only
  exists because Shadow runs on JDK 21; revisit once Shadow handles
  major-69 class files.
- spigot/Helper.java: warn that the `(MC: 26.` branch is a prefix
  match, so future per-MC helpers must be added above this line.
- .github/workflows/auto-tag-beta.yml: derive the beta base (e.g.
  "26.1.2-beta") from build.gradle's existing version line so a future
  MC bump only needs editing build.gradle, not three places in the
  workflow. Document that all `claude/**` branches share a single tag
  namespace via the global concurrency group.
@clawd131662
Copy link
Copy Markdown
Author

clawd131662 Bot commented May 4, 2026

Thanks for the thorough review. Pushed 2cf6199 addressing everything.

Blocking

  1. getBiomeReg() now synchronized. Same race shape as the other two — confirmed ACC_SYNCHRONIZED is on the resulting class file alongside initReflection/initCraftBukkitClasses.
  2. Dropped the org.bukkit.craftbukkit.v1_21_R7 fallback in both BukkitVersionHelperSpigot26_1_2 and MapChunkCache26_1_2. Kept just the unversioned Paper path; if a real Spigot-versioned helper is ever needed, we'll add it after confirming the actual package name on a Spigot 26.1.2 build.

Non-blocking

  1. Removed the unused craftServerClass / craftServerGetServer from BukkitVersionHelperSpigot26_1_2. (MapChunkCache26_1_2 does use them, so those stay.)
  2. Expanded the comment around configuration: 'default' in spigot/build.gradle, explicitly labelling it a workaround for paperweight's empty reobf runtime variant and warning against "alignment" with sibling helpers.
  3. Added a FIXME in bukkit-helper-26-1-2/build.gradle to drop the toolchain-25 + --release 21 + JVM-25-attribute dance once Shadow runs on JDK 25.
  4. Documented at the top of auto-tag-beta.yml that all claude/** branches share the same tag namespace via the global concurrency group.
  5. The workflow now derives the beta base (e.g. 26.1.2-beta) from build.gradle itself, so a future MC bump only requires editing build.gradle.
  6. Added a comment on Helper.java's (MC: 26. branch noting it's a prefix match and any specialised helper must go above it.

The Identifier import you flagged: agreed, leaving it as-is given :spigot:build and the auto-released beta.N jars.

@shikendon
Copy link
Copy Markdown
Member

Review Summary (round 3)

2cf61991 把上一輪 8 點全部收掉了,逐項對齊:

Blocking 部分(已修)

  • getBiomeReg() 加上 synchronized,第三處 broken double-check 一併修掉。
  • ✅ 兩個 helper 檔的 org.bukkit.craftbukkit.v1_21_R7 假 Spigot fallback 都拿掉了,改成單一 Paper unversioned 路徑 + 清楚的註解說明「沒驗證過就不留 fallback,免得遮蔽真正的 ClassNotFoundException」——這個取捨我同意。
  • craftServerClass / craftServerGetServerBukkitVersionHelperSpigot26_1_2 移除。

非阻擋的 polish(已修)

  • spigot/build.gradleconfiguration: 'default' workaround 註解擴寫,明寫「Do NOT 'align' this back」。
  • bukkit-helper-26-1-2/build.gradle 補了 FIXME: drop ... once Shadow plugin can run on JDK 25
  • Helper.java(MC: 26. prefix match 加了 NOTE 提醒未來更專一的版本要擺在上面。
  • auto-tag-beta.ymlbuild.gradlesed 推導 BASE,三處寫死收成一處;workflow header 也明寫了「所有 claude/** 分支共用同一個 tag namespace」。

還可以再改進,但完全可以 follow-up

  • auto-tag-beta.yml 裡推導出的 BASE 直接內插進另一個 sed regex(s/^${BASE}\.\([0-9]\+\)\$/\1/p)。BASE. 字元時,那個 . 在 sed regex 裡會匹配任意字元,理論上 26X1X2-beta.5 這種怪 tag 也會被收進來。實務上不會發生,但若想完全乾淨可以 escape 一下。
  • 兩個 helper 的 synchronized lazy init 在熱路徑上每次都吃一次 monitor。換成 static { ... } 區塊(或 holder class)可以省掉旗標跟鎖,但既然反射只會在 server start 後第一次 render 之前完成,差異微乎其微,不值得阻擋。

LGTM 👍 這版可以合了,剩下兩點如果想處理就 follow-up,不處理也沒關係。

shikendon pushed a commit that referenced this pull request May 4, 2026
Round-3 review nit from #23: ${BASE} (e.g. "26.1.2-beta") was spliced
straight into sed's regex; the literal `.`s would match any character
and let stray tags like `26X1X2-beta.5` be picked up by `LAST=$(...)`.
Pass BASE through a one-shot escape before using it in the regex.
Verified locally that `26X1X2-beta.5` is no longer matched while real
tags `26.1.2-beta.5` / `26.1.2-beta.10` still are.
@clawd131662
Copy link
Copy Markdown
Author

clawd131662 Bot commented May 4, 2026

LGTM 收到,謝謝 :) 順手把第一個 follow-up 收掉了:

  • befe986 / 1a4a63bBASE 進 sed 前先 escape 一次 regex metacharacters,避免 . 變 wildcard。本機驗過 26X1X2-beta.5 不再會被 git tag --list 之後的 sed 撈進來,而真實 tag 26.1.2-beta.5 / 26.1.2-beta.10 仍正確命中。

第二個(synchronizedstatic { ... } 區塊或 holder pattern)就照你建議當作 follow-up 處理,以這個 PR 的 scope 來說性價比不高。

@shikendon
Copy link
Copy Markdown
Member

Review Summary (round 4)

1a4a63ba 把上一輪的 sed regex metachar nit 收掉了——加了 BASE_RE 做 escape,commit message 還附上 26X1X2-beta.5 不再被誤抓的本地驗證結果。乾淨。

跳脫字元集 [.[\^$*+?(){}|\\] 涵蓋了所有實際會出現在 version string 裡的 BRE metachar,] 沒包進去但 build.gradle 的版本不會有 ],沒必要過度防禦。

剩下唯一未做的 follow-up(synchronized lazy init → static {} 區塊)純屬風格優化,差異在熱路徑上幾乎看不到,可以不做。

可以合了 ✅

- Add bukkit-helper-26-1-2 (cloned from bukkit-helper-121-11), pointing
  at the Paper dev bundle 26.1.2.build.57-stable. Source uses Mojang-
  mapped NMS imports and resolves CraftBukkit classes via reflection at
  runtime; getBiomeReg / initReflection / initCraftBukkitClasses are
  synchronized to avoid the broken-double-checked-locking race that the
  121-x helpers historically had.
- Bump io.papermc.paperweight.userdev to 2.0.0-beta.21 (required for
  paperweight 'data version 8' dev bundles -- beta.19 rejects 26.1.2 at
  setup time) and add org.gradle.toolchains.foojay-resolver-convention
  1.0.0 so the JDK 25 toolchain Paper 26.1+ requires gets auto-
  provisioned by Gradle.
- Compile bukkit-helper-26-1-2 with the JDK 25 toolchain but emit Java
  21 bytecode via options.release = 21 (so the Shadow plugin running
  on JDK 21 can read its class files), while pinning the
  org.gradle.jvm.version resolution attribute to 25 so the Java-25-only
  paper-api still resolves. Drop reobfJar (Paper 26.1+ ships Mojang-
  mapped only, no reobf mappings) and have spigot consume this module
  via configuration: 'default' to bypass paperweight's now-empty reobf
  variant.
- Wire the new helper into spigot/build.gradle and dispatch every
  (MC: 26.x) server in spigot/.../Helper.java to it. Bump the project
  version to 26.1.2-beta.1.
- Add .github/workflows/auto-tag-beta.yml: every push to a claude/**
  branch derives the beta base from build.gradle (regex metachars
  escaped), computes the next <base>.N, syncs build.gradle, commits the
  bump back with [skip ci], builds the spigot jar with the JDK 25
  toolchain and publishes a GitHub Release with the jar attached.
  Concurrency is serialized across branches so simultaneous pushes
  don't race for the same tag. The workflow does NOT create PRs; that
  is done out-of-band by an operator with pull_requests:write.
- Migrate release.yml off the deprecated actions/upload-release-asset@v1
  to gh release upload --clobber (built into the GitHub Actions runner,
  supports re-runs without 'asset already exists' failures).
@shikendon shikendon force-pushed the claude/minecraft-26.1.2-upgrade-dTYWZ branch from 293f63a to 319ae70 Compare May 6, 2026 09:42
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.

2 participants