跳到主要内容

开发者 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() 获取容器的快照物品栏,然后使用物品栏方法 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,每个 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 被击杀时移除区域保护