跳至主要內容

開發者 API

產生的 Java 參考文件 包含可搜尋的類別、方法與簽章,並記錄每個模組的來源版本與提交。

要求​

BetterStructures 需要:

  • Java 21 或更高版本
  • Spigot/Paper 伺服器
  • WorldEdit 外掛(硬依賴)

可選依賴:

  • WorldGuard - 用於區域保護功能(需要同時安裝 EliteMobs 以實現完整整合)
  • EliteMobs - 用於精英怪物生成整合
  • MythicMobs - 用於 MythicMobs 整合
  • Terralith、Iris、Terra、TerraformGenerator - 用於自訂生態群系相容性

公共儲存庫

Maven​

<repositories>
<repository>
<id>magmaguy-repo-releases</id>
<name>MagmaGuy's Repository</name>
<url>https://repo.magmaguy.com/releases</url>
</repository>
</repositories>

<dependency>
<groupId>com.magmaguy</groupId>
<artifactId>BetterStructures</artifactId>
<version>2.7.7</version>
<scope>provided</scope>
</dependency>

可用版本請見 Maven 儲存庫。範例使用已發布的 2.7.7,目前原始碼版本為 2.7.7。請選擇與已安裝外掛相符的版本。

Gradle

repositories {
maven {
name = "magmaguyRepoReleases"
url = uri("https://repo.magmaguy.com/releases")
}
}

dependencies {
compileOnly("com.magmaguy:BetterStructures:2.7.7")
}

可用版本請見 Maven 儲存庫。範例使用已發布的 2.7.7,目前原始碼版本為 2.7.7。請選擇與已安裝外掛相符的版本。

事件

注意:事件位於 com.magmaguy.betterstructures.api

套件匯入​

import com.magmaguy.betterstructures.api.BuildCustomMarkerEvent;
import com.magmaguy.betterstructures.api.BuildPasteCompleteEvent;
import com.magmaguy.betterstructures.api.BuildPlaceEvent;
import com.magmaguy.betterstructures.api.ChestFillEvent;
import com.magmaguy.betterstructures.api.WorldGenerationFinishEvent;
import com.magmaguy.betterstructures.buildingfitter.FitAnything;
import com.magmaguy.betterstructures.modules.ModularWorld;
import com.magmaguy.betterstructures.thirdparty.WorldGuard;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Container;
import org.bukkit.entity.EntityType;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import java.util.List;

BuildPlaceEvent​

當某個建築即將被放置時呼叫。透過 FitAnything 物件公開哪個建築將被放置在何處等資料。

請勿嘗試修改正在被放置的建築! 你可以修改一些小細節,但更改整個建築很可能會導致適配不良。

此事件可以取消。

ChestFillEvent​

當箱子被填充時呼叫。使用容器的快照庫存來安全地儲存要套用的資料。

你可以透過 getContainer().getSnapshotInventory() 取得容器的快照庫存,然後使用 Inventory 方法 addItem() 或 removeItem() 修改戰利品。

你也可以呼叫 getTreasureConfigFilename() 來識別用於填充此箱子的戰利品表設定。

此事件可以取消。

BuildCustomMarkerEvent​

在結構的方塊、戰利品、怪物與實體都貼上後,針對每個 [custom] 告示牌各呼叫一次。BetterStructures 會先移除告示牌,因此 getLocation() 所在的方塊是空氣,你可以在那裡放置任何東西。

  • getId() - 告示牌第 2 至 4 行不加分隔符號串接而成的字串,例如 Zombie_Plus
  • getLines() - 個別的第 2 至 4 行,已去除前後空白,空白行為空字串
  • getLocation() - 告示牌在世界中的位置
  • getFitAnything() - 正在貼上的結構,與 BuildPlaceEvent 相同

此事件「不可」取消。

BuildPasteCompleteEvent​

在一般結構完全貼上後呼叫一次,時間點在該結構所有 BuildCustomMarkerEvent 之後。貼上會分散在多個 tick 中進行,因此這是處理已放置結構的可靠時機。BuildPlaceEvent 則在這一切發生之前觸發。若有收尾步驟失敗,例如告示牌 Boss 無法生成,貼上會停止,此事件也不會觸發。

  • getFitAnything() - 已貼上的結構
  • getLowestCorner() 與 getHighestCorner() - 已貼上結構圖的方塊角落(世界座標),兩者皆包含在內
  • getBoundingBox() - 這些方塊所涵蓋的空間
  • getContainerLocations() - 結構圖中的每個箱子、陷阱箱、界伏盒與木桶,不論 BetterStructures 是否已在其中填入戰利品

此事件「不可」取消。

WorldGenerationFinishEvent​

當在專屬世界中生成的模組化地城(isWorldGeneration: true)完成貼上時呼叫。貼到現有世界中的地城不會觸發此事件。提供對 ModularWorld 物件的存取,該物件包含已生成世界的所有資料,包括生成點、箱子位置與出口點。

此事件「不可」取消。

你可以透過 getModularWorld() 方法存取世界資料。請參閱下方的 ModularWorld 章節以了解所有可用方法。

事件監聽器範例

public class MyBetterStructuresListener implements Listener {

@EventHandler
public void onBuildPlace(BuildPlaceEvent event) {
FitAnything build = event.getFitAnything();
Location location = build.getLocation();
// Custom logic here
// event.setCancelled(true); // To prevent placement
}

@EventHandler
public void onChestFill(ChestFillEvent event) {
Container container = event.getContainer();
Inventory inv = container.getSnapshotInventory();
// Modify inventory here
inv.addItem(new ItemStack(Material.DIAMOND, 1));
}

@EventHandler
public void onCustomMarker(BuildCustomMarkerEvent event) {
if (!event.getId().equals("Zombie_Plus")) return;
// Spawn your own mob at the marker
event.getLocation().getWorld().spawnEntity(event.getLocation().add(0.5, 0, 0.5), EntityType.ZOMBIE);
}

@EventHandler
public void onPasteComplete(BuildPasteCompleteEvent event) {
for (Location containerLocation : event.getContainerLocations()) {
if (!(containerLocation.getBlock().getState() instanceof Container container)) continue;
// Replace the contents with your own loot
container.getInventory().clear();
container.getInventory().addItem(new ItemStack(Material.EMERALD, 3));
}
}

@EventHandler
public void onWorldGenFinish(WorldGenerationFinishEvent event) {
ModularWorld world = event.getModularWorld();
// Access generated world data
List<Location> spawns = world.getSpawnLocations();
}
}

關鍵類別

FitAnything​

FitAnything 類別是在建築被貼上時所實例化的類別,負責處理貼上的每個面向,包括填充箱子與生成怪物。

可用的 getter 方法:

  • getSchematicContainer() - 返回結構圖容器
  • getSchematicClipboard() - 返回 WorldEdit 的 Clipboard 物件
  • getSchematicOffset() - 返回放置用的 Vector 偏移
  • getLocation() - 返回放置的 Location

這些方法在建立自訂區域保護或分析建築放置時很有用。

ModularWorld​

ModularWorld 類別代表已生成的模組化世界,並透過 WorldGenerationFinishEvent 提供。它包含所有位置資料,以及在已生成世界中生成實體與容器的方法。

關鍵方法:

  • getWorld() - 返回 Bukkit 的 World 實例
  • getWorldFolder() - 返回世界的 File 資料夾
  • getCenter() - 返回地城的起點,難度區間即以此為基準測量
  • getHorizontalSize() - 返回地城的寬度(以方塊為單位),即 (2 × radius − 1) × moduleSizeXZ
  • getDifficultyId(Location) - 返回某位置的 EliteMobs 實例難度 ID:距中心(以 X 與 Z 偏移中較大者計算)在寬度六分之一以內為 2,三分之一以內為 1,其餘為 0
  • getSpawnLocations() - 返回所有已標記的生成位置(List<Location>)
  • getChestLocations() - 返回所有箱子生成位置(List<Location>)
  • getBarrelLocations() - 返回所有木桶生成位置(List<Location>)
  • getExitLocations() - 返回所有出口點位置。請注意 ExitLocation 是私有的巢狀 record,因此在外掛之外你只能以萬用字元清單持有其結果;目前並沒有可用於其元素的公開型別。
  • spawnChests() - 在已標記位置生成箱子,返回 List<Block>
  • spawnBarrels() - 在已標記位置生成木桶,返回 List<Block>
  • spawnInaccessibleExitLocations() - 生成上層電梯結構圖,返回 List<Location>
  • spawnAccessibleExitLocations() - 生成下層電梯結構圖,返回 List<Location>
  • spawnOtherEntities() - 在下一個 tick 處理貼上過程尚未處理的生成池告示牌,然後再次觸發 WorldGenerationFinishEvent。貼上過程通常會自行處理所有生成池告示牌。若從 WorldGenerationFinishEvent 監聽器中呼叫它,會導致它每個 tick 都重複執行。
  • spawnInstancedEntities() - 以生成池的 maxLevel 生成佇列中的實例化生成池 Boss,各自套用 getDifficultyId 給出的難度 ID,並返回 List<InstancedBossEntity>。每個 Boss 都會以 betterstructures:spawnpool 為鍵,將生成池檔名存為自訂資料。

WorldGuard​

WorldGuard 類別負責處理 WorldGuard 的區域保護。提供了實用方法 public static ProtectedRegion generateProtectedRegion(FitAnything fitAnything, String regionName),讓開發者能夠輕鬆地在 BetterStructures 之上掛接自訂的區域保護方案。

其他有用的方法:

  • checkArea(Location, Player) - 檢查某位置是否位於受 BetterStructures 保護的區域內(如果受保護則返回 true,並向玩家傳送警告訊息)
  • Protect(...) - 以程式方式建立受保護區域
  • Unprotect(CustomBossEntity) - 當 Boss 被擊殺時移除區域保護