📚Dispenser Plus

Advanced Tool Interaction System with Custom Durability and Protection Integration Version: 2.0 | Author: HoHighMa | API Version: 1.2


🎯 ภาพรวมปลั๊กอิน

DispenserPlus คือปลั๊กอินที่ขยายความสามารถของ Dispenser ใน Minecraft ให้สามารถใช้เครื่องมือต่างๆ เพื่อทำงานอัตโนมัติได้ เหมือนกับผู้เล่นใช้เครื่องมือด้วยตนเอง พร้อมระบบป้องกันเขตที่ครอบคลุม

✨ ฟีเจอร์เด่น

  • ระบบเครื่องมือครบครัน: Pickaxe, Axe, Hoe ทำงานได้ตามหลัก Vanilla

  • ระบบตัดไม้แบบ SmoothTimber: ตัดไม้ทั้งต้นด้วยขวานเพียงครั้งเดียว

  • ระบบป้องกันเขต: รองรับ Lands, Towny, WorldGuard

  • ระบบความทนทาน: จัดการ Durability แบบกำหนดเอง (ปิดการใช้งาน Unbreaking)

  • ระบบ Hotbar: เครื่องมือทำงานได้ทุกช่องใน Hotbar

  • ปลูกพืชอัตโนมัติ: Dispenser ปลูกพืชบน Farmland ได้

  • ระบบ Reload: โหลดค่าตั้งค่าใหม่โดยไม่ต้อง Restart Server


🛠️ ระบบหลักทั้งหมด

1️⃣ ระบบเครื่องมือ (Tool System)

Dispenser สามารถใช้เครื่องมือได้ 3 ประเภทหลัก:

🪓 Axe (ขวาน) Iron/Diamond/Netherite

  • ใช้งานได้:

    • ✅ ตัดไม้ (ตาม Tag.LOGS ของ Minecraft)

    • ✅ ตัดไม้ทั้งต้น (เมื่อเปิด Tree Chopping)

    • ✅ ทำงานจาก Hotbar ทุกช่อง

  • ใช้งานไม่ได้:

    • ❌ Strip Wood (ลอกเปลือกไม้)

    • ❌ เก็บเกี่ยว Wheat

    • ❌ ขุดหิน

Diamond Axe

⛏️ Pickaxe (อีเต้อ) Iron/Diamond/Netherite

  • ใช้งานได้:

    • ✅ ขุดหิน (ตามกฎ Vanilla)

    • ✅ ขุดดิน (ตามกฎ Vanilla)

    • ✅ ทำงานจาก Hotbar ทุกช่อง

  • ใช้งานไม่ได้:

    • ❌ เก็บเกี่ยว Wheat

    • ❌ ตัดไม้

    • ❌ Strip Wood

Diamond Pickaxe

🪴 Hoe (จอบ) Iron/Diamond/Netherite

  • ใช้งานได้:

    • ✅ ไถดิน (Till Dirt → Farmland)

    • ✅ เก็บเกี่ยว Wheat (เฉพาะ Hoe เท่านั้น)

    • ✅ ทำงานจาก Hotbar ทุกช่อง

  • ใช้งานไม่ได้:

    • ❌ ขุดบลอกอื่นๆ

    • ❌ ตัดไม้

Diamond Hoe

2️⃣ ระบบปลูกพืช (Planting System)

  • Dispenser + Farmland: วาง Dispenser เหนือ Farmland 1 บลอก → ปลูกพืชอัตโนมัติ

  • สูตร: Dispenser Height = Farmland + 1 block

  • รองรับ: Seeds (เมล็ดพืช), Saplings (ต้นไม้)

⚙️ CobbleStone Generator

Diamond Pickaxe

🌲 ระบบตัดไม้ (Tree Chopping System)

ระบบนี้เลียนแบบ SmoothTimber โดยใช้ Algorithm BFS เพื่อค้นหาบลอกไม้ที่เชื่อมต่อกัน:

// TreeLocator.java - BFS Algorithm
public static void locateWood(Location breakPoint, List<Location> output, int limit) {
    int checkRadius = 1;    // ตรวจสอบรัศมี 1 บลอก
    int rootDepth = 5;      // ตรวจสอบลึกลงไป 5 บลอก (หาราก)
    
    // 1. หาราก: เริ่มจากจุดตัดลงไป 5 บลอก
    for (int y = 0; y <= rootDepth; y++) {
        Location rootLoc = breakPoint.clone().subtract(0, y, 0);
        if (isWoodBlock(rootLoc.getBlock())) {
            queue.offer(rootLoc);
            break;
        }
    }
    
    // 2. BFS: ค้นหาบลอกไม้ที่เชื่อมต่อกัน
    while (!queue.isEmpty()) {
        Location current = queue.poll();
        // ตรวจสอบ 26 บลอกรอบๆ (3x3x3 - 1)
        for (dx, dy, dz in [-1, 0, 1]) {
            if (isWoodBlock(neighbor)) {
                output.add(neighbor);
            }
        }
    }
}

⚙️ การตั้งค่า

# config.yml
enableTreeChopping: true    # เปิด/ปิดระบบตัดไม้
maxTreeBlocks: 100         # จำกัดบลอกไม้สูงสุดที่ตัดได้ (ป้องกัน Lag)

🎯 การใช้งาน

  1. ใส่ Axe ใดๆ ใน Dispenser (ทุกช่อง Hotbar)

  2. ให้ Dispenser หันหน้าไปที่ Log (ไม้)

  3. ส่งสัญญาณ Redstone → Dispenser ตัดไม้ทั้งต้น

  4. ไม้ทั้งหมดดรอป + Axe ลด Durability

🚧 ข้อจำกัด

  • จำกัดบลอก: ป้องกันไม่ให้ตัดไม้ต้นใหญ่เกิน maxTreeBlocks (ป้องกัน Lag)

  • จำกัด Durability: ถ้า Axe มี Durability เหลือน้อย จะตัดได้เท่าที่ Durability เหลือ


🛡️ ระบบป้องกันเขต (Protection Integration)

🔐 ปลั๊กอินที่รองรับ

ปลั๊กอิน
API
คุณสมบัติ

Lands

LandsAPI 6.28.11

เปรียบเทียบ Land ID

Towny

TownyAPI 0.100.3.0

เปรียบเทียบ Town UUID

WorldGuard

WorldGuard 7.0.9

ตรวจสอบ Overlapping Regions

📋 หลักการทำงาน

// ProtectionManager.java
public boolean canDispenserInteract(Block dispenserBlock, Block targetBlock) {
    // กฎ 1: Dispenser และ Target ต้องอยู่ใน SAME REGION เท่านั้น
    // กฎ 2: ถ้า Dispenser อยู่ที่ขอบเขต ห้ามทำงานข้ามเขต
    // กฎ 3: ถ้าทั้งสองอยู่ในพื้นที่ไม่มีเจ้าของ (Wilderness) อนุญาต
    
    if (landsEnabled) {
        // Lands: ตรวจสอบ getLand().getId()
        return dispenserLand.getId() == targetLand.getId();
    }
    
    if (townyEnabled) {
        // Towny: ตรวจสอบ getTownOrNull().getUUID()
        return dispenserTown.getUUID() == targetTown.getUUID();
    }
    
    if (worldGuardEnabled) {
        // WorldGuard: ตรวจสอบ Overlapping Regions
        Set<String> commonRegions = findCommonRegions(dispenserLoc, targetLoc);
        return !commonRegions.isEmpty();
    }
}

🌍 WorldGuard - ระบบ Overlapping Regions

// WorldGuardHook.java
public boolean canInteract(Location dispenserLoc, Location targetLoc) {
    // 1. ดึง Region Sets ของทั้งสองตำแหน่ง
    ApplicableRegionSet dispenserSet = getRegions(dispenserLoc);
    ApplicableRegionSet targetSet = getRegions(targetLoc);
    
    // 2. แปลงเป็น Region IDs
    Set<String> dispenserRegions = extractRegionIds(dispenserSet);
    Set<String> targetRegions = extractRegionIds(targetSet);
    
    // 3. หา Common Regions (Intersection)
    dispenserRegions.retainAll(targetRegions);
    
    // 4. ถ้ามี Common Region → อนุญาต
    return !dispenserRegions.isEmpty();
}

⚙️ การตั้งค่า

# config.yml
enableProtectionIntegration: true  # เปิด/ปิดระบบป้องกันเขต

📌 ตัวอย่างการใช้งาน

✅ อนุญาต (Allowed)

[Dispenser + Axe] ← Region A → [Wood] 
✓ ทั้งสองอยู่ใน Region A → ตัดไม้ได้

❌ ไม่อนุญาต (Blocked)

[Dispenser + Axe] ← Region A | Region B → [Wood]
✗ Dispenser อยู่ Region A, Wood อยู่ Region B → ตัดไม้ไม่ได้

✅ อนุญาต (Wilderness)

[Dispenser + Axe] ← Wilderness → [Wood]
✓ ทั้งสองอยู่นอกเขต → ตัดไม้ได้

⚡ ระบบความทนทาน (Durability System)

🔧 กฎการทำงาน

# หลักการ
- Unbreaking Enchantment: ถูก IGNORE ทั้งหมด
- ทุกเครื่องมือลด Durability: 1 ต่อการใช้งาน (ไม่มีข้อยกเว้น)
- Drop Tools: เลือกได้ว่าจะ Drop หรือทำลายเมื่อ Durability = 0

⚙️ การตั้งค่า

dropToolsOnLastDurability: true   # Drop เครื่องมือเมื่อใกล้หมดอายุ
                                  # false = ทำลายเครื่องมือ

📊 ตัวอย่างการคำนวณ

กรณี: ตัดไม้ 50 บลอก ด้วย Diamond Axe

Diamond Axe Durability: 1561
Tree Blocks: 50

Durability After Chopping: 1561 - 50 = 1511
Result: Axe ยังใช้ได้ต่อ

กรณี: ตัดไม้ 150 บลอก ด้วย Stone Axe

Stone Axe Durability: 131
Tree Blocks: 150
maxTreeBlocks: 100

Actual Chop: min(150, 100, 131) = 100
Durability After: 131 - 100 = 31
Result: ตัดได้เพียง 100 บลอก (จำกัดโดย maxTreeBlocks)

กรณี: Axe ใกล้หมดอายุ

Wood Axe Durability: 5 (เหลือ 5 จากทั้งหมด 59)
Tree Blocks: 80
dropToolsOnLastDurability: true

Actual Chop: 5 blocks
Result: ตัดได้ 5 บลอก → Drop Wood Axe (ไม่ทำลาย)

💻 คำสั่งและการใช้งาน

🎮 คำสั่งหลัก

/dispenserplus reload    # โหลดค่า config.yml ใหม่
/dplus reload           # Alias
/dp reload              # Alias

🔑 Permissions

permissions:
  dispenserplus.reload:
    description: อนุญาตให้ Reload Plugin
    default: op                      # เฉพาะ OP เท่านั้น

📋 ข้อมูลที่แสดงเมื่อ Reload

[DispenserPlus] Configuration reloaded!
[DispenserPlus] Tree Chopping: Enabled
[DispenserPlus] Max Tree Blocks: 100
[DispenserPlus] Drop Tools: Enabled
[DispenserPlus] Protection Integration: Enabled
[DispenserPlus] Protection: Lands Towny WorldGuard

⚙️ การตั้งค่า (Configuration)

📄 ไฟล์ config.yml ฉบับเต็ม

# DispenserPlus Plugin Configuration
# Minecraft 1.21.8 Compatible

# ========================================
# Disabled Items/Tags
# ========================================
disabledItems: []           # รายการ Items ที่ห้ามใช้ (Namespaced Key)
disabledTags: []            # รายการ Tags ที่ห้ามใช้ (Namespaced Key)

# ========================================
# Durability System
# ========================================
dropToolsOnLastDurability: true  
# true:  เครื่องมือจะ Drop ออกมาเมื่อใกล้หมดอายุ
# false: เครื่องมือจะถูกทำลายเมื่อ Durability = 0

# ========================================
# Tool Restrictions
# ========================================
allowHarvestBlocksWithPickaxe: true  
# true:  Pickaxe ขุดบลอกได้ตามปกติ
# false: Pickaxe ไม่สามารถขุดบลอกใดๆ ได้

# Tool Rules Summary:
# - Pickaxe: ขุดหิน, ขุดดิน (ห้ามเก็บ Wheat, ห้ามตัดไม้)
# - Axe:     ตัดไม้, ตัดไม้ทั้งต้น (ห้าม Strip, ห้ามเก็บ Wheat, ห้ามขุดหิน)
# - Hoe:     ไถดิน, เก็บ Wheat (เฉพาะ Hoe เท่านั้นเก็บ Wheat ได้)

# ========================================
# Tree Chopping System
# ========================================
enableTreeChopping: true    # เปิด/ปิดระบบตัดไม้ทั้งต้น
maxTreeBlocks: 100         # จำกัดบลอกไม้สูงสุดที่ตัดได้ต่อครั้ง

# Tree Chopping Algorithm: BFS (Breadth-First Search)
# - checkRadius: 1 (ตรวจสอบรัศมี 1 บลอก)
# - rootDepth: 5 (ตรวจสอบราก 5 บลอก)
# - Supports: Tag.LOGS (ไม้ทุกชนิดใน Minecraft)

# ========================================
# Protection Integration
# ========================================
enableProtectionIntegration: true  # เปิด/ปิดระบบป้องกันเขต

# รองรับปลั๊กอิน:
# - Lands (LandsAPI 6.28.11)
# - Towny (TownyAPI 0.100.3.0)
# - WorldGuard (WorldGuard 7.0.9)

# กฎการทำงาน:
# 1. Dispenser และ Target ต้องอยู่ใน SAME REGION
# 2. ห้าม Dispenser ทำงานข้ามเขต (Edge Protection)
# 3. อนุญาตให้ทำงานใน Wilderness (พื้นที่ไม่มีเจ้าของ)
# 4. WorldGuard: ตรวจสอบ Overlapping Regions

🔄 การโหลดค่าใหม่

// ReloadCommand.java
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
    // 1. ตรวจสอบ Permission
    if (!sender.hasPermission("dispenserplus.reload")) {
        sender.sendMessage(ChatColor.RED + "No permission!");
        return true;
    }
    
    // 2. Reload Config
    plugin.reloadConfig();
    plugin.refreshConfig();
    
    // 3. แสดงสถานะ
    FileConfiguration config = plugin.getConfig();
    sender.sendMessage(ChatColor.GREEN + "Configuration reloaded!");
    sender.sendMessage(ChatColor.YELLOW + "Tree Chopping: " + 
                      (config.getBoolean("enableTreeChopping") ? "Enabled" : "Disabled"));
    // ... แสดงข้อมูลอื่นๆ
    
    return true;
}

🏗️ ข้อมูลทางเทคนิค

📦 Dependencies

Maven Repositories

<!-- pom.xml -->
<repositories>
    <!-- Spigot API -->
    <repository>
        <id>spigotmc-repo</id>
        <url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
    </repository>
    
    <!-- WorldGuard & WorldEdit -->
    <repository>
        <id>enginehub-repo</id>
        <url>https://maven.enginehub.org/repo/</url>
    </repository>
    
    <!-- Lands -->
    <repository>
        <id>jitpack.io</id>
        <url>https://jitpack.io</url>
    </repository>
    
    <!-- Towny -->
    <repository>
        <id>glaremasters-repo</id>
        <url>https://repo.glaremasters.me/repository/towny/</url>
    </repository>
</repositories>

Dependencies List

<dependencies>
    <!-- Spigot API 1.21.3 -->
    <dependency>
        <groupId>org.spigotmc</groupId>
        <artifactId>spigot-api</artifactId>
        <version>1.21.3-R0.1-SNAPSHOT</version>
        <scope>provided</scope>
    </dependency>
    
    <!-- Lands API 6.28.11 -->
    <dependency>
        <groupId>com.github.angeschossen</groupId>
        <artifactId>LandsAPI</artifactId>
        <version>6.28.11</version>
        <scope>provided</scope>
        <optional>true</optional>
    </dependency>
    
    <!-- Towny 0.100.3.0 -->
    <dependency>
        <groupId>com.palmergames.bukkit.towny</groupId>
        <artifactId>towny</artifactId>
        <version>0.100.3.0</version>
        <scope>provided</scope>
        <optional>true</optional>
    </dependency>
    
    <!-- WorldEdit 7.3.0 -->
    <dependency>
        <groupId>com.sk89q.worldedit</groupId>
        <artifactId>worldedit-bukkit</artifactId>
        <version>7.3.0</version>
        <scope>provided</scope>
        <optional>true</optional>
    </dependency>
    
    <!-- WorldGuard 7.0.9 -->
    <dependency>
        <groupId>com.sk89q.worldguard</groupId>
        <artifactId>worldguard-bukkit</artifactId>
        <version>7.0.9</version>
        <scope>provided</scope>
        <optional>true</optional>
    </dependency>
</dependencies>

📂 โครงสร้างโปรเจค

DispenserPlus/
├── src/main/java/io/github/hohighma/dispenserplus/
│   ├── SuperDispensersPlugin.java          # Main Plugin Class
│   ├── command/
│   │   └── ReloadCommand.java              # Reload Command Handler
│   ├── event/
│   │   ├── DispenseEventHandler.java       # Main Event Listener
│   │   └── DispenseEventHelpers.java       # Tool Logic & Helpers
│   ├── protection/
│   │   ├── ProtectionManager.java          # Protection System Manager
│   │   ├── LandsHook.java                  # Lands Integration
│   │   ├── TownyHook.java                  # Towny Integration
│   │   └── WorldGuardHook.java             # WorldGuard Integration
│   └── util/
│       └── TreeLocator.java                # BFS Tree Detection
├── src/main/resources/
│   ├── plugin.yml                          # Plugin Metadata
│   └── config.yml                          # Configuration File
├── pom.xml                                 # Maven Build Config
└── target/
    └── dispenserplus-2.0.jar              # Compiled JAR (44.1 KB)

🔌 Plugin Metadata

# plugin.yml
name: DispenserPlus
version: '2.0'
main: io.github.hohighma.dispenserplus.SuperDispensersPlugin
api-version: '1.21'
author: HoHighMa
description: Advanced Tool Interaction System for Minecraft 1.21.8

commands:
  dispenserplus:
    description: DispenserPlus main command
    usage: /dispenserplus reload
    aliases: [dplus, dp]
    permission: dispenserplus.reload

permissions:
  dispenserplus.reload:
    description: Allow reloading the plugin configuration
    default: op

# Soft Dependencies (Optional)
softdepend: [Lands, Towny, WorldGuard, WorldEdit]

🔨 Build Configuration

<!-- pom.xml -->
<build>
    <plugins>
        <!-- Java Compiler -->
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.8.1</version>
            <configuration>
                <source>21</source>
                <target>21</target>
            </configuration>
        </plugin>
        
        <!-- Maven Shade Plugin -->
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-shade-plugin</artifactId>
            <version>3.2.4</version>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>shade</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

🧑‍💻 API สำหรับนักพัฒนา

🔧 ProtectionManager API

// ดึง Instance ของ ProtectionManager
ProtectionManager pm = SuperDispensersPlugin.getInstance().getProtectionManager();

// ตรวจสอบว่า Dispenser สามารถทำงานกับ Block ได้หรือไม่
boolean canInteract = pm.canDispenserInteract(dispenserBlock, targetBlock);

// ตรวจสอบว่ามีปลั๊กอินป้องกันเขตติดตั้งหรือไม่
boolean hasProtection = pm.hasProtectionEnabled();

// ดึงสถานะของปลั๊กอินป้องกันเขต
String status = pm.getProtectionStatus(); // "Protection Integration: Lands Towny WorldGuard"

// ตรวจสอบปลั๊กอินแต่ละตัว
boolean lands = pm.isLandsEnabled();
boolean towny = pm.isTownyEnabled();
boolean worldGuard = pm.isWorldGuardEnabled();

🌲 TreeLocator API

// ค้นหาบลอกไม้ทั้งหมดที่เชื่อมต่อกัน
List<Location> woodBlocks = new ArrayList<>();
TreeLocator.locateWood(breakPoint, woodBlocks, 100); // จำกัด 100 บลอก

// ตรวจสอบว่า Block เป็นไม้หรือไม่
boolean isWood = TreeLocator.isWoodBlock(block);

🛠️ DispenseEventHelpers API

DispenseEventHelpers h = new DispenseEventHelpers();

// ตัดไม้ทั้งต้น
boolean success = h.tryChopTree(
    block,              // Block ที่จะตัด
    blockFace,          // ทิศทางของ Dispenser
    itemStack,          // เครื่องมือ (Axe)
    (Dispenser) state   // Dispenser BlockState
);

// ทำลาย Block ด้วยเครื่องมือ
boolean success = h.breakBlockWithDispenser(
    block,
    blockFace,
    itemStack,
    (Dispenser) state
);

// เก็บเกี่ยว Wheat
boolean success = h.tryHarvestWheat(
    block,
    blockFace,
    itemStack,
    (Dispenser) state
);

// ไถดิน
boolean success = h.tryTillDirt(
    block,
    blockFace,
    itemStack,
    (Dispenser) state
);

🎯 Event Listener Examples

// ตัวอย่างการใช้ Event Listener ของ DispenserPlus
@EventHandler
public void onBlockDispense(BlockDispenseEvent event) {
    Block block = event.getBlock();
    ItemStack item = event.getItem();
    
    // ตรวจสอบว่าเป็น Dispenser
    if (block.getType() != Material.DISPENSER) return;
    
    // ตรวจสอบว่าเป็นเครื่องมือที่รองรับ
    if (Tag.ITEMS_AXES.isTagged(item.getType())) {
        // Axe Logic
        BlockFace facing = ((Directional) block.getBlockData()).getFacing();
        Block target = block.getRelative(facing);
        
        // ตรวจสอบ Protection
        ProtectionManager pm = plugin.getProtectionManager();
        if (!pm.canDispenserInteract(block, target)) {
            event.setCancelled(true);
            return;
        }
        
        // ทำงานต่อไป...
    }
}

📊 ตารางสรุปคุณสมบัติ

เครื่องมือ vs การใช้งาน

เครื่องมือ
ขุดหิน
ขุดดิน
ตัดไม้
ตัดไม้ทั้งต้น
ไถดิน
เก็บ Wheat
Strip Wood

Pickaxe

Axe

Hoe

ปลั๊กอิน Protection vs API

ปลั๊กอิน
API Version
วิธีตรวจสอบ
Overlapping Regions

Lands

6.28.11

getLand().getId()

Towny

0.100.3.0

getTownOrNull().getUUID()

WorldGuard

7.0.9

ApplicableRegionSet

ระบบ vs สถานะ

ระบบ
สถานะ
ตั้งค่าได้
หมายเหตุ

Tree Chopping

✅ Enabled

BFS Algorithm

Protection Integration

✅ Enabled

3 ปลั๊กอิน

Durability System

✅ Enabled

Unbreaking = IGNORED

Hotbar System

✅ Enabled

ทำงานทุกช่อง

Reload Command

✅ Enabled

Permission: OP


🎓 คำแนะนำการใช้งาน

🌲 การตั้งค่าฟาร์มไม้อัตโนมัติ

1. วาง Dispenser หันหน้าไปที่ต้นไม้
2. ใส่ Axe ใน Dispenser (ช่องไหนก็ได้)
3. ต่อสัญญาณ Redstone (Clock/Observer)
4. ตั้งค่า config.yml:
   enableTreeChopping: true
   maxTreeBlocks: 100
5. เริ่มทำงาน → ไม้ทั้งต้นถูกตัด

🌾 การตั้งค่าฟาร์มข้าวอัตโนมัติ

1. สร้าง Farmland (ไถดินด้วย Hoe)
2. วาง Dispenser เหนือ Farmland 1 บลอก
3. ใส่ Hoe + Seeds ใน Dispenser
4. สัญญาณแรก: ปลูก Seeds
5. รอข้าวโต (Wheat Age = 7)
6. สัญญาณสอง: เก็บเกี่ยว Wheat (ด้วย Hoe)
7. วนซ้ำ

🛡️ การตั้งค่าระบบป้องกันเขต

1. ติดตั้งปลั๊กอิน: Lands / Towny / WorldGuard
2. ตั้งค่า config.yml:
   enableProtectionIntegration: true
3. สร้าง Region/Land/Town
4. วาง Dispenser ใน Region
5. Dispenser ทำงานได้เฉพาะในเขตเดียวกัน

⚠️ ข้อควรระวัง

🚫 ข้อจำกัดที่สำคัญ

  1. Unbreaking Enchantment: ถูกปิดการใช้งานทั้งหมด → ทุกเครื่องมือลด Durability 1 ต่อครั้ง

  2. Cross-Region Interaction: ห้าม Dispenser ทำงานข้ามเขต (Edge Protection)

  3. Tree Block Limit: จำกัดด้วย maxTreeBlocks เพื่อป้องกัน Server Lag

  4. Tool Validation: เครื่องมือทำงานได้ตามกฎ Vanilla เท่านั้น (ไม่สามารถแก้ไขได้)

  5. Soft Dependencies: ปลั๊กอิน Protection เป็น Optional (ติดตั้งหรือไม่ก็ได้)

🔧 การแก้ปัญหา

ปัญหา
สาเหตุ
วิธีแก้

Dispenser ไม่ตัดไม้

enableTreeChopping: false

ตั้งเป็น true ใน config.yml

Dispenser ทำงานข้ามเขต

Protection ปิด

ตั้ง enableProtectionIntegration: true

เครื่องมือหายเร็ว

Durability ปกติ

Unbreaking ถูก IGNORE (ตามออกแบบ)

ตัดไม้ไม่ครบ

Tree > maxTreeBlocks

เพิ่มค่า maxTreeBlocks

Permission Denied

ไม่มีสิทธิ์ OP

ใช้ /op <player>


📞 ข้อมูลติดต่อ

ผู้พัฒนา: HoHighMa Version: 2.0 Minecraft Version: 1.21.8 API Version: 1.21 Build System: Maven JAR Size: 44.1 KB


📄 License & Credits

เครดิต

  • SmoothTimber: แรงบันดาลใจของระบบตัดไม้ (BFS Algorithm)

  • Spigot API: Minecraft Server API

  • Lands API: Land Protection System

  • Towny API: Town Management System

  • WorldGuard/WorldEdit: Region Protection System

ใบอนุญาต

ปลั๊กอินนี้พัฒนาขึ้นเพื่อการศึกษาและใช้งานส่วนตัว กรุณาตรวจสอบเงื่อนไขการใช้งานของแต่ละ Dependency API ที่ใช้งาน


🎉 ขอบคุณที่ใช้งาน DispenserPlus!

"Make Minecraft Automation Great Again with DispenserPlus"


Last Updated: November 20, 2025 Documentation Version: 1.0 Plugin Version: 2.0

Last updated