结构放置API

结构放置API

为fabric模组开发者制作的用于生成NBT结构的API

基础库

结构放置器 API

这个简单的 API 提供了一种简便的方式,在你的世界中一次性生成一个结构,而不是将其放入世界生成中。这对于创建传送门的物品,或其他类型的结构可能非常有用。或者用来创建幸运方块,谁知道呢!

设置

将这个库作为依赖项添加到你的 build.gradle 中

repositories {
    maven {
        name = "Modrinth"
        url = "https://api.modrinth.com/maven"
        content {
            includeGroup "maven.modrinth"
        }
    }
}

dependencies {
    modImplementation "maven.modrinth:structureplacerapi:<version>"
}

如果你愿意,可以通过只添加 include 字符串将 API include 到你的 jar 文件中:

repositories {
    maven {
        name = "Modrinth"
        url = "https://api.modrinth.com/maven"
        content {
            includeGroup "maven.modrinth"
        }
    }
}

dependencies {
    modImplementation "maven.modrinth:structureplacerapi:<version>"
    include "maven.modrinth:structureplacerapi:<version>"
}

它不到 25 kb!

nodecraft

如何使用它

如何创建结构?

你必须使用 Minecraft 的结构方块创建一个 NBT 结构,如本视频所示:https://www.youtube.com/watch?v=umhuRXinD3o

我得到的文件应该放在哪里?

你需要将 structure.nbt 文件放在你的模组的 data 文件夹内,像这样:data/yourmodid/structures

创建一个新的放置器对象

为了放置结构,你需要先创建一个放置器对象,这只需创建一个新的 StructurePlacerAPI 对象即可。它有不少参数可以调整:

StructurePlacerAPI(ServerWorld world, Identifier templateName, BlockPos blockPos, BlockMirror mirror, BlockRotation rotation, boolean ignoreEntities, float integrity, BlockPos offset)

参数说明

  • 第一个参数 world 是我们要放置结构的世界。你可以从实体或其他地方获取它。
  • 第二个参数 templateName 是由你模组的 MOD_ID 和结构名称组成的 Identifier
  • 第三个参数 blockPos 是你的结构将要生成的方块位置。例如,你可以从实体的坐标获取它
  • 第四个参数 mirror 是第一个可选参数。通过它,你可以使用 BlockMirror 类来镜像你的结构。无需创建另一个对象,只需输入 BlockMirror.#stuff
  • 第五个参数 rotation 与前一个类似,你可以使用 BlockRotation 类来旋转你的结构。无需创建另一个对象,只需输入 BlockMirror.#stuff
  • ignoreEntities 参数如果设置为 true,则不会生成结构文件中包含的实体。如果设置为 false,则会生成它们
  • integrity 参数相当有趣,因为它是一个介于 0f 和 1f 之间的浮点值,将决定结构的破旧程度。如果设置为低于 1f 的值,生成时一些方块将被移除
  • 最后,offset 参数是另一个 BlockPos,可用于将结构重新定位到实体脚下或其他位置。

放置结构

你刚刚创建了一个 StructurePlacerAPI placer = new StructurePlacerAPI(上面的那些东西),要生成它,你需要这样做:

placer.loadStructure();

是的,好吧,这并不太难。你只需要运行那个就行,而不是直接使用 .place 方法,因为 load 方法会在生成之前检查该结构是否存在。

一段时间后恢复旧地形

从版本 1.1.0 开始,你还可以使用:

placer.loadAndRestoreStructure(int restore_ticks);

来提供一个 tick 数量(1 秒 = 20 ticks),在此之后旧地形将被恢复。 注意:这可能会导致性能问题,特别是如果结构非常大的话!(它需要保存结构内的每一个方块!)

你还可以通过使用以下内容为方块重新出现添加动画:

placer.loadAndRestoreStructureAnimated(int restore_ticks, int blocks_per_tick, boolean random);
  • blocks_per_ticks 是每个 tick 将被替换的方块数量,所以如果你的结构由 200 个方块组成,而 blocks_per_ticks 设置为 1,则每秒将放置 20 个方块,需要 20 秒完成地形恢复。
  • random 指的是方块被替换的顺序。设置为 true 时,每次重新生成的方块都是随机的,否则将从结构的一个角到另一个角。在我看来,random = true 更酷。

选择哪些方块应该被替换(从 2.0.0 起)

你现在可以指定被放置的结构是否可以替换基岩和屏障或具有特定标签的方块,或者它只能替换具有特定标签的方块。 在你创建了 StructurePlacerAPI 放置器对象之后,你可以使用这些方法:

/** 设置此结构是否应替换基岩 */
placer.setReplaceBedrock(boolean replaceBedrock)
    
/** 设置此结构是否应替换屏障方块 */
placer.setReplaceBarrier(boolean replaceBarrier)

/** 设置此结构是否应仅替换具有所提供标签的方块,例如仅替换空气方块 */
placer.setOnlyReplaceTaggedBlocks(boolean onlyReplaceTaggedBlocks, TagKey<Block> tag)

/** 允许指定如果具有所提供标签则不会被替换的方块 */
placer.setPreventReplacementOfTaggedBlocks(boolean preventReplacementOfTaggedBlocks, TagKey<Block> tag)

当结构放置了某个方块或被其替换时执行操作(2.0.0+)

现在你可以选择在结构内的某个方块被放置到世界中时,或在放置结构时某个方块被替换时执行一个函数。

例如,如果你希望在放置包含浆果丛的结构时生成一只随机狐狸,你可以使用:

placer.actionOnBlocksPlacedByStructure(ActionOnBlockFind action, TagKey<Block> targets);

//示例:
placer.actionOnBlocksPlacedByStructure((info, world) -> {world.spawnEntity(EntityType.FoxEntity, ...)}, BlockTags.BUSHES);

该操作是一个 lambda 函数,为你提供 StructureBlockInfo 和 ServerWorldAccess(或 ServerLevelAccess,取决于你使用的是 mojmaps 还是其他映射)。你必须为你想要替换的方块类型指定一个标签。如果只是单个方块类型,请为该方块创建一个 Tag。

你可以做的另一件事是在一个已经在世界中的方块被结构替换时执行某些操作。 例如在冰块被替换时生成雪花粒子:

placer.actionOnBlocksReplacedByStructure(ActionOnBlockFind action, TagKey<Block> targets);

//示例:
placer.actionOnBlocksReplacedByStructure((info, world) -> {world.spawnParticles(ParticleType.SNOW, ...)}, BlockTags.ICE);

示例

一个示例可以在 LightWithin 模组中找到(顺便说一下,你应该去看看):

StructurePlacer placer = new StructurePlacer((ServerWorld) caster.getWorld(), new Identifier(MOD_ID, "frost_light"), caster.getBlockPos(), BlockMirror.NONE, BlockRotation.CLOCKWISE_90, true, 1.0f, new BlockPos(-4, -3, -3));
placer.loadStructure();

以获得一个永久结构

StructurePlacer placer = new StructurePlacer((ServerWorld) caster.getWorld(), new Identifier(MOD_ID, "frost_light"), caster.getBlockPos(), BlockMirror.NONE, BlockRotation.CLOCKWISE_90, true, 1.0f, new BlockPos(-4, -3, -3));
placer.loadAndRestoreStructureAnimated(200, 2, true);

以使旧地形以随机顺序每 tick 替换两个方块的方式重新生成。

警告!

重要!确保你在服务器线程上运行!

if(!world.isClient){
//运行内容
}

支持我

如果你想请我喝杯咖啡,请便。

ko-fi 或者,你也可以通过使用下面这个代码为你和你的朋友在服务器上获得 25% 的折扣来支持我

许可证

此 API 在 CC0 许可下可用。欢迎从中学习并将其纳入你的项目