@dao3fun/terrain-schematic
v1.3.8
Published
`TerrainSchematic` 是一个强大且易于使用的地形蓝图工具库,专为在神岛游戏环境中处理三维建筑蓝图而设计。它提供了一套完整的解决方案,用于从游戏世界中**捕获**、**编辑**(旋转、翻转、替换方块等)、**操作**和**放置**建筑结构。
Keywords
Readme
TerrainSchematic - 适用于神岛的地形蓝图库
一个功能强大的 TypeScript 库,用于在游戏中以程序化的方式创建、操作和导入 3D 结构(蓝图)。它提供了流畅的链式 API,使你能够轻松地组合复杂的操作。

地图演示:https://dao3.fun/exp/experience/detail/100478935
地图示例代码:https://codecopy.cn/post/a1z0k3
核心特性
- 程序化形状生成: 快速创建球体、长方体、圆柱、金字塔、圆环、棱柱等多种几何形状。
- 文字生成: 支持从字符串生成 3D 文字。
- 路径构建: 能够沿着自定义路径(支持贝塞尔平滑)创建复杂的结构,如墙壁和管道。
- 流畅的链式 API: 所有修改操作都会返回实例本身,让你可以像
schematic.rotate(...).flip(...).import()这样进行链式调用。 - 高级变换: 支持围绕自定义轴心点进行旋转、缩放、翻转和镜像。
- 布尔运算: 支持对两个蓝图进行并集 (
add)、差集 (subtract) 和交集 (intersect) 操作。 - 强大的特效滤镜: 内置侵蚀、平滑、锐化、腐朽、线框、外壳等多种效果。
- 高级方块替换: 不仅可以进行简单的 1:1 替换,还支持基于权重的模式匹配替换,轻松创造自然纹理。
- 与游戏世界交互: 支持从游戏世界中导出地形,或将蓝图异步/同步地导入到世界中。
- 分析与导出: 可以获取蓝图的尺寸、计算所需材料,或将其导出为 JSON 数据。
安装
npm install @dao3fun/terrain-schematic快速上手
下面是一个简单的例子,创建一个半径为 10 的空心石球,然后将其放置在世界坐标 (0, 100, 0) 处。
import { TerrainSchematic, SphereOptions } from "@dao3fun/terrain-schematic";
// 定义球体的选项
const options: SphereOptions = {
isHollow: true,
thickness: 2,
};
// 使用静态方法创建蓝图,然后链式调用导入方法
TerrainSchematic.fromSphere(10, 1, 0, options) // 半径10, 方块ID 1 (石头), 旋转0
.import(new GameVector3(0, 100, 0));API 概览
1. 导出与导入
你可以轻松地将地形蓝图导出为可序列化的 JavaScript 对象,以便存储或传输,然后再从该对象导入,恢复为 TerrainSchematic 实例。
导出为数据对象:
// 捕获一个 32x64x32 区域的地形
const bounds = new GameBounds3(
new GameVector3(1, 1, 1),
new GameVector3(32, 64, 32)
);
// 创建蓝图
const schematic = new TerrainSchematic(bounds);
// 当玩家加入时,将蓝图数据复制到玩家的剪贴板
world.onPlayerJoin(({ entity }) => {
schematic.copyJSON(entity);
});从数据对象导入:
// 导入蓝图JSON数据
import map from "map.json";
// 从数据创建实例
const newSchematic = TerrainSchematic.fromData(map);
// 导入地形到地图中
newSchematic.import(new GameVector3(1, 1, 1));2. 创建蓝图
有多种方式可以创建 TerrainSchematic 实例。
从游戏世界中捕获:
// 捕获一个 32x64x32 区域的地形
const bounds = new GameBounds3(
new GameVector3(1, 1, 1),
new GameVector3(32, 64, 32)
);
const schematic = new TerrainSchematic(bounds);从预设几何体创建 (静态方法):
// 创建一个长方体
const wall = TerrainSchematic.fromCuboid(new GameVector3(10, 5, 1), 1);
// 创建一个圆锥
const cone = TerrainSchematic.fromCone(8, 12, 45); // 半径8, 高度12, 方块ID 45
// 创建一个六棱柱
const pillar = TerrainSchematic.fromPrism(6, 5, 20, 1); // 6条边, 半径5, 高度20支持的静态创建方法包括: fromSphere, fromCylinder, fromPyramid, fromCuboid, fromTorus, fromPipe, fromCapsule, fromCone, fromPrism, fromText
2. 操作蓝图 (链式方法)
几乎所有的操作方法都会返回 this,方便进行链式调用。
变换:
schematic
.rotate("y", 90) // 绕Y轴旋转90度
.scale(new GameVector3(1, 2, 1)) // 在Y轴上拉伸2倍
.flip("x"); // 沿X轴翻转布尔运算:
const wall = TerrainSchematic.fromCuboid(new GameVector3(20, 10, 3), 1);
const window = TerrainSchematic.fromCuboid(new GameVector3(5, 5, 3), 0);
// 在墙上开一个窗户
const wallWithWindow = wall.subtract(window, new GameVector3(7, 2, 0));
wallWithWindow.import();方块替换:
// 1. 简单替换:将所有石头(ID=1)替换为草方块(ID=2)
schematic.replaceBlocks(new Map([[1, 2]]));
// 2. 高级模式替换:创建更自然的纹理混合
const pattern: PatternMap = new Map([
[
1,
[
// 当遇到方块ID为 1 (石头) 时
{ id: 1, weight: 80 }, // 80% 几率保持为石头
{ id: 4, weight: 15 }, // 15% 几率变为圆石
{ id: 169, weight: 5 }, // 5% 几率变为苔石
],
],
]);
schematic.replaceByPattern(pattern);特效:
// 对一个山脉蓝图应用侵蚀效果,然后平滑,最后挖空
mountain
.erode({ iterations: 50, erosion: 0.1 })
.smooth({ iterations: 2 })
.shell(3)
.import();3. 导入与导出
导入到世界:
// 同步导入
schematic.import(new GameVector3(50, 20, 50));
// 异步导入,防止卡顿
schematic.importAsync(new GameVector3(50, 20, 50), 500); // 每tick处理500个方块数据序列化:
// 将蓝图转换为可序列化的JS对象
const data = schematic.getData();
const jsonString = JSON.stringify(data);
// 从数据中恢复蓝图
const loadedSchematic = TerrainSchematic.fromData(JSON.parse(jsonString));高级示例
建造一座蜿蜒的城墙
使用 fromPathWall 和贝塞尔平滑来创建一道沿着曲线路径的城墙。
import { TerrainSchematic } from "@dao3fun/terrain-schematic";
const path = [
new GameVector3(0, 0, 0),
new GameVector3(20, 5, 40),
new GameVector3(-10, 8, 80),
new GameVector3(30, 2, 120),
];
TerrainSchematic.fromPathWall(path, 10, 3, 4, 0, {
useBezier: true, // 路径平滑
bezierSampleCount: 40,
}).import(new GameVector3(100, 64, 100));创建一个空心的圆顶
组合使用布尔运算来创建一个空心的圆顶。
import { TerrainSchematic, SphereOptions } from "@dao3fun/terrain-schematic";
// 创建一个大球
const outerSphere = TerrainSchematic.fromSphere(20, 1);
// 创建一个小一点的球,用于挖空
const innerSphere = TerrainSchematic.fromSphere(18, 0); // 使用空气方块
// 创建一个巨大的长方体,用于切掉下半部分
const cutter = TerrainSchematic.fromCuboid(new GameVector3(50, 21, 50), 0);
// 最终操作
outerSphere
.subtract(innerSphere) // 挖空
.subtract(cutter, new GameVector3(-25, -20, -25)) // 切掉底部
.import(new GameVector3(0, 80, 0));