Doc ID: SIRC-046

WorldGuard & WorldEdit API 知识库

本文档用于系统性整理 WorldGuard / WorldEdit / FastAsyncWorldEdit(FAWE) 在插件二次开发中的 核心类、包结构、对象获取流程以及高频使用场景.

Overview

WorldGuard & WorldEdit API 知识库

本文档用于系统性整理 WorldGuard / WorldEdit / FastAsyncWorldEdit(FAWE) 在插件二次开发中的 核心类、包结构、对象获取流程以及高频使用场景

目标是:

让开发者在涉及区域保护、选区编辑、大规模方块操作时,有一份“可直接照抄结构、不靠猜”的 API 参考。


一、整体关系说明

三者之间的职责划分

  • WorldGuard

    • 区域(Region)管理
    • 权限 / Flag / 建筑检测
    • 与“能不能做某件事”有关
  • WorldEdit

    • 方块编辑引擎
    • 选区、复制、粘贴、形状生成
    • 与“怎么改世界”有关
  • FastAsyncWorldEdit(FAWE)

    • WorldEdit 的高性能替代实现
    • 提供异步队列与性能限制器
    • 与“大规模操作不炸服”有关

二、WorldGuard API 详解

1️⃣ 获取 WorldGuard 实例

import com.sk89q.worldguard.WorldGuard;

WorldGuard worldGuard = WorldGuard.getInstance();
  • WorldGuard 使用 单例模式
  • 所有 API 入口都从这里开始

2️⃣ RegionContainer 与 RegionManager

import com.sk89q.worldguard.protection.regions.RegionContainer;
import com.sk89q.worldguard.protection.regions.RegionManager;

RegionContainer container = worldGuard.getPlatform().getRegionContainer();
RegionManager regionManager = container.get(world);

说明:

  • RegionContainer:全局区域容器
  • RegionManager单个世界的区域管理器
  • world 为 Bukkit World

⚠️ regionManager 可能为 null(例如该世界未加载)


3️⃣ Bukkit Player → WorldGuard LocalPlayer

import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import com.sk89q.worldguard.LocalPlayer;

LocalPlayer localPlayer = WorldGuardPlugin.inst().wrapPlayer(player);
  • 所有权限 / Flag / Bypass 检查 必须使用 LocalPlayer
  • 不要直接用 Bukkit Player

4️⃣ RegionQuery(最常用)

import com.sk89q.worldguard.protection.regions.RegionQuery;

RegionQuery query = container.createQuery();

4.1 建筑权限检测

boolean canBuild = query.testBuild(location, localPlayer);

4.2 Flag 检测(示例:ENTRY)

import com.sk89q.worldguard.protection.flags.Flags;

boolean allowed = query.testState(location, localPlayer, Flags.ENTRY);

5️⃣ Bypass(管理员绕过)检测

boolean canBypass = worldGuard
        .getPlatform()
        .getSessionManager()
        .hasBypass(localPlayer, world);
  • 拥有 bypass 的玩家不受区域限制

6️⃣ 获取某位置所属区域

import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldguard.protection.ApplicableRegionSet;

BlockVector3 pos = BlockVector3.at(x, y, z);
ApplicableRegionSet regions = regionManager.getApplicableRegions(pos);

7️⃣ 创建 / 添加 / 删除区域

7.1 创建 Cuboid 区域

import com.sk89q.worldguard.protection.regions.ProtectedCuboidRegion;

ProtectedCuboidRegion region = new ProtectedCuboidRegion(
        "region_id",
        min,
        max
);

7.2 添加区域

regionManager.addRegion(region);

7.3 删除区域

regionManager.removeRegion("region_id");

8️⃣ 区域 Flag 操作

import com.sk89q.worldguard.protection.flags.Flags;
import com.sk89q.worldguard.protection.flags.StateFlag;

region.setFlag(Flags.PVP, StateFlag.State.DENY);
region.setFlag(Flags.GREETING, "欢迎来到这个区域!");

三、WorldEdit API 详解

1️⃣ 获取 WorldEdit 实例

import com.sk89q.worldedit.WorldEdit;

WorldEdit worldEdit = WorldEdit.getInstance();

2️⃣ Actor 与 LocalSession

import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.session.LocalSession;

Actor actor = BukkitAdapter.adapt(player);
LocalSession session = worldEdit.getSessionManager().get(actor);

3️⃣ EditSession(核心编辑对象)

import com.sk89q.worldedit.EditSession;

try (EditSession editSession = worldEdit.newEditSession(world)) {
    // edit logic
}
  • 必须 try-with-resources
  • 自动提交与释放资源

4️⃣ 单点方块操作

import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.block.BlockTypes;

BlockVector3 pos = BlockVector3.at(x, y, z);
editSession.setBlock(pos, BlockTypes.STONE.getDefaultState());

5️⃣ CuboidRegion 批量操作

import com.sk89q.worldedit.regions.CuboidRegion;

Region region = new CuboidRegion(min, max);
editSession.setBlocks(region, BlockTypes.AIR.getDefaultState());

6️⃣ 玩家选区操作

获取选区

Region selection = session.getSelection(world);

设置选区

session.setRegionSelector(world, new CuboidRegionSelector(world, cuboid));

7️⃣ 复制与粘贴(结构化流程)

  1. Selection → Clipboard
  2. Clipboard → ForwardExtentCopy
  3. Operations.complete(copy)

这是 WorldEdit 标准复制粘贴三步法


8️⃣ 形状生成

editSession.makeSphere(center, pattern, radius, radius, radius, true);
editSession.makeCylinder(center, pattern, radius, height, true);
editSession.makePyramid(center, pattern, size, true);

四、FastAsyncWorldEdit(FAWE)API

1️⃣ 异步 World 包装

import com.fastasyncworldedit.core.FaweAPI;
import com.fastasyncworldedit.core.world.AsyncWorld;

AsyncWorld asyncWorld = AsyncWorld.wrap(world);

2️⃣ 异步 EditSession

EditSession editSession = WorldEdit.getInstance().newEditSession(asyncWorld);

3️⃣ 队列方式操作(高性能)

import com.fastasyncworldedit.core.queue.IQueueExtent;

IQueueExtent queue = FaweAPI.getQueue(world);
queue.setBlock(x, y, z, BlockTypes.STONE.getDefaultState());
queue.flush();

4️⃣ 限制器(Limit)

  • FAWE 会根据 Actor 应用修改限制

  • 包括:

    • 最大修改量
    • 最大操作速率

五、开发实践建议

✅ 推荐

  • 区域判断:WorldGuard
  • 方块操作:WorldEdit / FAWE
  • 大规模修改:FAWE 队列

❌ 不推荐

  • 主线程循环 setBlock
  • 直接依赖内部实现类
  • 跳过 LocalPlayer / Actor 转换

六、文档定位说明

本文档适用于:

  • 区域保护插件
  • 建筑 / 地形生成插件
  • 副本 / 任务 / 地图编辑插件
  • AI 自动生成 WorldEdit / WorldGuard 代码

不适用于:

  • 指令教学
  • 普通玩家使用说明

📌 核心原则:

WorldGuard 决定“能不能”,WorldEdit 决定“怎么改”,FAWE 决定“改多少也不炸”。