ปลั๊กอิน Paper (Minecraft Java) สำหรับอัพเกรด เตาเผาทุกชนิด (Furnace / Blast Furnace / Smoker), Hopper, Dispenser, Dropper และ Crafter
- ทุกการอัพเกรด เพิ่มแค่ "อัตรา" เท่านั้น — ไม่มีไอเทมใหม่ ไม่มีสูตรใหม่ ไม่เปลี่ยนกลไกวานิลลาอื่น ๆ
- เตาเผา → เผาได้ครั้งละหลายชิ้น (batch smelting) ระดับ 1-4 = 8/16/24/32 ชิ้นต่อ 1 รอบเผา — เวลาต่อรอบและเชื้อเพลิงที่ใช้เท่าวานิลลาเดิม ใช้แค่วัตถุดิบเพิ่มตามจำนวนที่เผา (ยิ่งอัพเกรดสูงยิ่งคุ้มเชื้อเพลิง)
- Hopper → ส่งไอเทมได้มากขึ้นต่อรอบ (ปกติ 1 ชิ้น/8 ticks)
- Dispenser / Dropper → ยิง/ดันไอเทมออกมากขึ้นต่อการทำงาน 1 ครั้ง (สองบล็อกนี้ใช้กลไกเดียวกัน แค่ตั้งค่าคนละชุด)
- Crafter → คราฟซ้ำได้มากขึ้นต่อการทริกเกอร์ 1 ครั้ง
- ระดับอัพเกรดถูกเก็บไว้ บนตัวบล็อกโดยตรง ผ่าน PersistentDataContainer (ไม่มีดาต้าเบสภายนอก ย้าย/โหลดพร้อมโลกเสมอ) และติดไปกับไอเทมด้วยเมื่อทุบบล็อก (ดูหัวข้อ "ทุบ/วางบล็อกที่อัพเกรดแล้ว")
- เซิร์ฟเวอร์ Purpur/Paper 26.2+ (ทดสอบจริงบน Purpur 26.2-stable) — ไม่ใช่ Spigot ธรรมดา เพราะใช้
CrafterCraftEvent - Java 25+ (ตรงกับ runtime ที่ Purpur 26.2/26.3 ต้องการ)
- Maven (สำหรับ build)
- Vault (ทางเลือก) — ติดตั้งเพิ่มถ้าต้องการเก็บราคาอัพเกรดเป็น "เงิน" (ต้องมีปลั๊กอินระบบเงินอย่าง EssentialsX ด้วย) ถ้าไม่ติดตั้ง Vault ราคาส่วนที่เป็นเงินจะถูกข้ามอัตโนมัติ ไม่กระทบการทำงานส่วนอื่น
mvn clean packageไฟล์ jar จะอยู่ที่ target/upgrademachines-1.0.0.jar — เอาไปวางในโฟลเดอร์ plugins/ ของเซิร์ฟเวอร์แล้วรีสตาร์ท
| คำสั่ง | คำอธิบาย | สิทธิ์ |
|---|---|---|
/upgrade info |
ดูระดับอัพเกรดของบล็อกที่กำลังมอง + ราคาระดับถัดไป | ทุกคน |
/upgrade reload |
โหลดค่า config.yml ใหม่ | upgrademachine.admin |
การอัพเกรดบล็อก: Shift + คลิกขวา ที่เตาเผา/ฮอปเปอร์/ดิสเพนเซอร์/ดรอปเปอร์/คราฟเตอร์ → เปิดกล่องยืนยันอัพเกรด โดยชื่อกล่อง (แถบหัวกล่อง) จะแสดงผลที่จะได้และราคาไปเลยทันทีที่เปิด (เช่น เตาเผา เผาทีละ: 16 ชิ้น - 500) และในช่องไอเทมกลางก็มี lore แจกแจงระดับปัจจุบัน → ระดับใหม่, ผล, ราคาซ้ำอีกรอบแบบละเอียด พร้อมปุ่ม ยืนยันอัพเกรด (หักเงิน/ไอเทมแล้วอัพเกรดจริง) กับ ยกเลิกการอัพเกรด (ปิดกล่องเฉย ๆ ไม่เสียอะไร) ไม่ต้องใช้ไม้หรือไอเทมพิเศษใด ๆ — ถืออะไรอยู่ก็เปิดกล่องได้ ต้องมีสิทธิ์ upgrademachine.use (ค่าเริ่มต้นเปิดให้ทุกคน)
คลิกขวาแบบไม่กด Shift ยังเปิด/ใช้งานบล็อกตามปกติแบบวานิลลาเหมือนเดิม ไม่มีการลดระดับ (downgrade) ในปลั๊กอินนี้
โหมดยืนยันอัพเกรด (gui.style) มี 3 แบบ:
inventory(default) — กล่องยืนยัน/ยกเลิกแบบ 27 ช่องตามที่อธิบายด้านบนactionbar— ไม่เปิดกล่องเลย ขึ้นข้อความ prompt สั้น ๆ ที่แถบด้านล่างจอแทน (gui.actionbar.prompt-format) — Shift+คลิกขวาครั้งแรกโชว์ราคา/ผลลัพธ์ ครั้งที่สองที่บล็อกเดิมภายในเวลาที่กำหนด (gui.actionbar.timeout-seconds, default 6 วินาที) ถือเป็นการยืนยันทันที ข้อความเป็น action bar ธรรมดาไม่มีกรอบ/พื้นหลังสวย ๆ ให้เอง (ต้องมี resource pack ของตัวเองถ้าอยากได้แบบมีกรอบ) ไม่มีปุ่มยกเลิกชัดเจน — แค่ไม่คลิกซ้ำหรือปล่อยให้หมดเวลาก็ถือว่ายกเลิกdialog— เปิดกล่อง Dialog แบบวานิลลาจริง (ฟีเจอร์ Dialogs ของเกม ไม่ใช่ inventory hack) มีกรอบ/พื้นหลังสวยงามให้เองทันทีโดยไม่ต้องมี resource pack และมีปุ่ม ยืนยัน/ยกเลิก เป็นปุ่มจริงกดง่ายกว่าเปิดกล่อง inventory บนมือถือ ตั้งข้อความหัวเรื่อง/เนื้อหา/ปุ่มได้ผ่านgui.dialog.*— ต้องใช้ไคลเอนต์เวอร์ชันที่รองรับฟีเจอร์ Dialogs (มากับ Minecraft รุ่นใหม่ที่รองรับ paper-api 26.2 ขึ้นไป) ไม่งั้นอาจไม่แสดงผล
ทั้ง actionbar และ dialog เหมาะกับผู้เล่นมือถือที่เล็งแตะช่องเล็ก ๆ ในกริดได้ยากมากกว่าโหมด inventory เดิม
ทุบบล็อกที่มีระดับอัพเกรด (Lv. ≥ 1) จะได้ไอเทมที่เปลี่ยนชื่อ + lore ให้เห็นค่าประสิทธิภาพจริงทันที เช่น
ดรอปเปอร์ → Lv.3
ดรอปทีละ: 4 ชิ้น
ระดับอัพเกรดถูกฝังไว้ในตัวไอเทมเอง (ไม่ใช่แค่ข้อความ) เอาไปวางที่ไหนก็ได้ — บล็อกใหม่จะได้ระดับเดิมกลับคืนทันที (ถ้า config ปัจจุบันลด max-level ลงจนต่ำกว่าระดับเดิม ระดับที่ได้จะถูก clamp ลงมาที่ max ใหม่) บล็อกที่ยังไม่เคยอัพเกรด (Lv.0) ทุบแล้วดรอปเป็นไอเทมปกติแบบวานิลลา ไม่มีการเปลี่ยนแปลงใด ๆ
โหมด Creative: ปกติวานิลลาทุบบล็อกในโหมด Creative จะไม่ดรอปไอเทมเลย (บล็อกหายไปเฉย ๆ) ซึ่งจะทำให้ระดับอัพเกรดหายไปด้วยถ้าไม่จัดการเป็นพิเศษ — ปลั๊กอินนี้เลยมอบไอเทมที่เปลี่ยนชื่อแล้วเข้ากระเป๋าผู้เล่นโดยตรงแทนในกรณีนี้ (เฉพาะบล็อกที่มีระดับ ≥ 1 เท่านั้น บล็อก Lv.0 ยังคงหายไปตามวานิลลาปกติ)
ชื่อกล่อง GUI ของบล็อกเอง (เช่น เปิดคราฟเตอร์เพื่อคราฟ): อัพเกรดปุ๊บ ชื่อกล่อง (title) ของบล็อกจะเปลี่ยนตามทันที ไม่ต้องทุบวางใหม่ — ใช้ชื่อฟอร์แมตเดียวกับ item-name-format (Furnace/Hopper/Dispenser/Dropper/Crafter ทุกตัวรองรับ Nameable ของ Bukkit อยู่แล้ว)
ข้อจำกัด: ครอบคลุมเฉพาะการทุบด้วยผู้เล่นตามปกติ (BlockBreakEvent) — บล็อกที่ถูกทำลายด้วยระเบิดหรือวิธีอื่นจะดรอปเป็นไอเทมวานิลลาปกติและเสียระดับอัพเกรดไป
แต่ละเครื่องมี display-name (ชื่อที่แสดงในเมนู/ข้อความ/ไอเทมที่ดรอป), max-level, list อัตราตามระดับ, และ price (index 0 = ยังไม่อัพเกรด = ไม่มีราคา) ปรับได้อิสระ เช่น
furnace:
display-name: "เตาเผา" # ชื่อที่แสดงในเมนู/ข้อความ/ไอเทมที่ดรอป - แก้เป็นข้อความอะไรก็ได้
effect-format: "เผาทีละ: {rate} ชิ้น" # ข้อความเอฟเฟค ({effect} ในกล่อง/ไอเทม) - {rate} = ตัวเลขจาก list ด้านล่าง แก้ได้แค่คำ ตัวเลขยังมาจาก list เสมอ
max-level: 4
# index 0 = ยังไม่อัพเกรด (เผาทีละ 1 ชิ้นแบบวานิลลา), ระดับ 1-4 = 8/16/24/32
smelt-batch-size: [1, 8, 16, 24, 32]
price:
money: [0, 500, 1500, 3000, 6000] # ราคาเงินเพื่อ "ไปถึง" ระดับนั้น (ต้องมี Vault)
item:
material: IRON_INGOT # ตั้งเป็น "" ถ้าไม่ต้องการเก็บราคาไอเทม
amounts: [0, 8, 16, 32, 64]- ตั้งได้ทั้งราคาเงินและไอเทมพร้อมกัน (ต้องจ่ายครบทั้งคู่ถ้าตั้งไว้ทั้งคู่) หรือเปิดแค่อย่างใดอย่างหนึ่งก็ได้ (ตั้งอีกอย่างเป็น 0 / material เป็น
"") effect-formatมีให้ทุกเครื่อง (furnace/hopper/dispenser/dropper/crafter) คนละข้อความ ใช้ placeholder{rate}ได้ตัวเดียว และใช้โค้ดสี&ได้ ผลลัพธ์คือค่าที่ไปแทน{effect}ในทุกจุด (title กล่อง, lore,/upgrade info, ไอเทมที่ดรอป)- แก้ตัวเลขในไฟล์แล้วรัน
/upgrade reloadใช้ได้ทันที ไม่ต้อง build ใหม่
เครื่องบางชนิดครอบคลุมบล็อกวานิลลาหลายแบบไว้ในเครื่องเดียว (ตอนนี้มีแค่ furnace ที่ครอบ Furnace/Blast Furnace/Smoker เพราะอัตราเผา/ราคาเหมือนกันทั้ง 3 ชนิด) ถ้าอยากตั้งชื่อแยกกันแต่ยังใช้อัตรา/ราคาเดียวกัน ใช้ display-names (ไม่บังคับต้องตั้งครบทุกชนิด — ชนิดที่ไม่ตั้งจะ fallback ไปใช้ display-name ปกติ):
furnace:
display-name: "เตาเผา" # ชื่อ default/fallback
display-names:
FURNACE: "เตาเผา"
BLAST_FURNACE: "เตาถลุงแร่"
SMOKER: "เตาอบรมควัน"คีย์ต้องเป็นชื่อ Material ของ Bukkit ตัวพิมพ์ใหญ่ (FURNACE, BLAST_FURNACE, SMOKER) ผลจะไปโผล่ทุกจุดที่มีคำว่า {name} (title กล่อง, ข้อความ, ชื่อไอเทมที่ดรอป) โดยอัตโนมัติ
ทั้ง display-name และแต่ละค่าใน display-names ตั้งเป็นข้อความเดียว (ใช้ทุกระดับเหมือนเดิม) หรือเป็น list แยกตามระดับ ก็ได้ — index ของ list = ระดับ เหมือนหลักการเดียวกับ list อัตรา/ราคาทั้งไฟล์ (index 0 = ยังไม่อัพเกรด, index 1 = Lv.1, ...) ตัวอย่างที่มากับปลั๊กอิน (config.yml ที่แถมมาตั้งไว้แบบนี้อยู่แล้ว ทุกเครื่อง):
furnace:
display-names:
FURNACE: ["เตาเผา", "เตาเผาทองแดง", "เตาเผาเหล็ก", "เตาเผาทอง", "เตาเผาเพชร"]
hopper:
display-name: ["ฮอปเปอร์", "ฮอปเปอร์ทองแดง", "ฮอปเปอร์เหล็ก", "ฮอปเปอร์ทอง", "ฮอปเปอร์เพชร", "ฮอปเปอร์เนเธอร์ไรต์"]จำนวนช่องใน list ควรเท่ากับ max-level + 1 (index 0 ถึง max-level) ถ้าระดับไหนไม่มีชื่อใน list (list สั้นไป หรือช่องว่าง "") จะ fallback ไปตามลำดับ: display-names.<MATERIAL> (แบบ list หรือข้อความเดียว) → display-name (แบบ list หรือข้อความเดียว) → ชื่อ default ในตัวปลั๊กอิน ไม่มีทางว่างเปล่า
นอกจาก {level}/{current}/{max} (เลขอารบิก 1, 2, 3, ...) ทุก placeholder เหล่านี้มีเวอร์ชันเลขโรมันให้ใช้คู่กัน: {level-roman}/{current-roman}/{max-roman} (I, II, III, IV, V, ...) — ค่า default ที่แถมมากับปลั๊กอินใช้เลขโรมันอยู่แล้ว ทุกจุดที่โชว์ "Lv." (title กล่อง, ชื่อไอเทมที่ดรอป, /upgrade info, ข้อความอัพเกรดสำเร็จ/ผิดพลาด) ถ้าอยากกลับไปใช้เลขอารบิกธรรมดา แก้ใน gui.info-item.name-format, gui.info-item.lore, gui.item-name-format ให้ใช้ {level}/{current}/{max} แทน (ระดับ 0 ไม่มีเลขโรมัน จะโชว์เป็น 0 เฉย ๆ)
ส่วน gui: (ไฟล์เดียวกัน อยู่บนสุดก่อน furnace:) คุมหน้าตากล่อง Shift+คลิกขวา และชื่อ/lore ของไอเทมที่ดรอปตอนทุบบล็อกที่อัพเกรดแล้ว ทุกช่องข้อความแก้ได้อิสระและใช้ placeholder ได้:
| Placeholder | ความหมาย |
|---|---|
{name} |
ชื่อเครื่อง ณ ระดับนั้น (จาก display-name/display-names - ดูหัวข้อชื่อแยกตามระดับด้านล่าง) |
{level} / {level-roman} |
ระดับเป้าหมาย - เลขอารบิก / เลขโรมัน |
{current} / {current-roman} |
ระดับปัจจุบัน - เลขอารบิก / เลขโรมัน |
{max} / {max-roman} |
ระดับสูงสุด - เลขอารบิก / เลขโรมัน |
{rate} |
ตัวเลขดิบล้วน ๆ ของระดับเป้าหมาย (ตัวเดียวกับที่ effect-format เอาไปประกอบเป็น {effect}) เช่น 16 เฉย ๆ ไม่มีข้อความรอบข้าง ใช้เมื่อไม่ต้องการข้อความเต็มจาก effect-format |
{effect} |
ข้อความผลลัพธ์เต็ม (มาจาก effect-format ของเครื่องนั้น) เช่น เผาทีละ: 16 ชิ้น |
{price} |
ราคาสรุปสั้น ๆ เช่น 500 + 8x IRON_INGOT หรือ ฟรี — ตัวเลข/ชื่อไอเทมในนี้ไม่มีสีบังคับของตัวเอง สีที่ใส่ไว้ก่อน {price} ใน template จะมีผลจริง (เช่น &e{price} ได้สีเหลืองทั้งราคา) ยกเว้นข้อความ "ฟรี" กับตัวคั่น + ระหว่างราคาเงิน/ไอเทม ที่มีสีของตัวเองแยกไว้ ตั้งได้ผ่าน gui.price-free (default &aฟรี) และ gui.price-separator (default &7 + ) |
สีใช้โค้ด & (เช่น &a เขียว, &c แดง, &l ตัวหนา) หรือจะใช้ hex color แบบ &#RRGGBB ก็ได้ (เช่น D60FF = สีน้ำเงิน) ใช้ปนกับโค้ดสีปกติในสตริงเดียวกันได้ (ใส่ในค่า display-name/display-names เองก็ได้เช่นกัน ไม่ต้องอยู่ใน template เท่านั้น) material ของปุ่ม/ไอเทมเติมช่องว่างตั้งเป็นชื่อ Material ของ Bukkit ได้ตามใจ (ไอคอนไอเทมกลางกล่องคงเป็นบล็อกที่กำลังอัพเกรดเสมอ เปลี่ยน material ไม่ได้) ค่า default ที่แถมมาใช้เลขโรมัน ({level-roman} ฯลฯ) ทุกจุด:
gui:
title-format: "&8{name} &f{effect} &7- {price}"
info-item:
name-format: "&b&l{name} &f→ &bLv.{level-roman}"
lore:
- "&7ระดับ: &f{current-roman} &7→ &a{level-roman}&7/{max-roman}"
- "&7ผล: &f{effect}"
- ""
- "&7ราคา: &f{price}"
confirm-button:
material: LIME_STAINED_GLASS_PANE
name: "&a&lยืนยันอัพเกรด"
lore: ["&7คลิกเพื่อยืนยันการอัพเกรด"]
cancel-button:
material: RED_STAINED_GLASS_PANE
name: "&c&lยกเลิกการอัพเกรด"
lore: ["&7ปิดกล่องนี้โดยไม่เสียเงิน/ไอเทม"]
filler:
material: GRAY_STAINED_GLASS_PANE
item-name-format: "&b{name} &f→ &bLv.{level-roman}" # ชื่อไอเทมที่ดรอป
item-lore-format: ["&7{effect}"] # lore ของไอเทมที่ดรอปitem-name-format/item-lore-format ใช้ {level}/{current} (และเวอร์ชันโรมัน) เป็นค่าเดียวกัน (ระดับของไอเทมนั้น ๆ ไม่มีแนวคิดเป้าหมาย/ปัจจุบันต่างกันแบบในกล่อง)
ข้อความในคำสั่ง /upgrade info และข้อความแชทตอนอัพเกรดสำเร็จ/ผิดพลาด (ไม่ผ่านระบบ template ด้านบน) ก็ใช้เลขโรมันเหมือนกัน ถ้าอยากเปลี่ยนกลับเป็นเลขอารบิกต้องแก้โค้ด (UpgradeManager.toRoman(...) ใน UpgradeCommand.java/UpgradeConfirmGuiListener.java) ไม่ใช่แค่แก้ config.yml
- Dispenser / Dropper: ไอเทมพิเศษที่ดันออกเพิ่ม จะถูก "ดรอปออกมาตรง ๆ" หน้าตัวบล็อก แทนที่จะเลียนแบบพฤติกรรมพิเศษของไอเทมนั้น ๆ ทุกอย่าง (เช่น ถังน้ำ/ไข่มอนสเตอร์/ลูกศร ของ Dispenser) ของชิ้นแรกยังทำงานแบบวานิลลาปกติ ส่วนชิ้นโบนัสจะออกมาเป็นไอเทมดรอปเฉย ๆ
- Crafter: เป็นบล็อกใหม่ (1.21+) API ของ Paper ยังไม่นิ่งเท่าตัวอื่น จึงใช้วิธี "คราฟซ้ำ" แทนการลด cooldown ภายในบล็อกโดยตรง ควรทดสอบกับเวอร์ชันเซิร์ฟเวอร์จริงก่อนใช้งานจริง
- ราคาเงิน: ต้องมี Vault + ปลั๊กอินระบบเงิน (เช่น EssentialsX) ติดตั้งอยู่ ไม่งั้นจะถูกข้ามอัตโนมัติ (ปลั๊กอินนี้ไม่ผูกกับปลั๊กอินระบบเงินเจาะจงตัวใดตัวหนึ่ง)
- ทดสอบบน Purpur 26.2-stable เป็นหลัก (compile ด้วย
paper-api:26.2.build.121-stable, Java 25) โค้ดใช้แต่ API มาตรฐานที่ไม่เปลี่ยนระหว่าง 26.2 → 26.3-alpha จึงรองรับ Purpur 26.3 ล่วงหน้าได้ในทางเทคนิค แต่ควรทดสอบซ้ำบนเซิร์ฟ 26.3 จริงทันทีที่มี stable build ให้ใช้ (ดู HANDOFF.md)