Skip to content

Commit

Permalink
test: add custom structure test
Browse files Browse the repository at this point in the history
  • Loading branch information
quizhizhe committed Feb 15, 2025
1 parent 397c40b commit b115bc4
Show file tree
Hide file tree
Showing 24 changed files with 802 additions and 223 deletions.
20 changes: 20 additions & 0 deletions src/test/TestCustomDimension.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "test/generator/flat-gen-village/FlatVillageDimension.h"
#include "test/generator/generator-custom-structure/dimension/CustomStructureDimension.h"
#include "test/generator/generator-terrain/NxnBorderTerrainDimension.h"

#include "ll/api/event/EventBus.h"
Expand All @@ -10,21 +11,40 @@
static bool reg = [] {
using namespace ll::event;
EventBus::getInstance().emplaceListener<ServerStartedEvent>([](ServerStartedEvent&) {
// simplate dimension test
// vanilla overworld type dimension test
more_dimensions::CustomDimensionManager::getInstance().addDimension<more_dimensions::SimpleCustomDimension>(
"testNewDimension"
);

// vanilla flat type dimension test
more_dimensions::CustomDimensionManager::getInstance()
.addDimension<more_dimensions::SimpleCustomDimension>("testNewFlatDimension", 345, GeneratorType::Flat);

// vanilla nether type dimension test
more_dimensions::CustomDimensionManager::getInstance()
.addDimension<more_dimensions::SimpleCustomDimension>("testNewNetherDimension", 345, GeneratorType::Nether);

// vanilla the end type dimension test
more_dimensions::CustomDimensionManager::getInstance()
.addDimension<more_dimensions::SimpleCustomDimension>("testNewTheEndDimension", 345, GeneratorType::TheEnd);

// vanilla void dimension test
more_dimensions::CustomDimensionManager::getInstance()
.addDimension<more_dimensions::SimpleCustomDimension>("testNewVoidDimension", 345, GeneratorType::Void);

// custom diomension test
// flat type generator village dimension test
more_dimensions::CustomDimensionManager::getInstance()
.addDimension<flat_village_dimension::FlatVillageDimension>("testFlatVillage");

// flat type custom terrain dimension test
more_dimensions::CustomDimensionManager::getInstance()
.addDimension<nxn_border_terrain::NxnBorderTerrainDimension>("testFlatTerrain", 5);

// flat type custom structure dimension test
more_dimensions::CustomDimensionManager::getInstance()
.addDimension<custom_structure_dimension::CustomStructureDimension>("testCustomStructure");
});
return true;
}();
Expand Down
146 changes: 146 additions & 0 deletions src/test/generator/generator-custom-structure/CustomStructure.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
#include "CustomStructure.h"

#include "ll/api/memory/Hook.h"

#include "mc/deps/core/threading/WorkerPool.h"
#include "mc/resources/BaseGameVersion.h"
#include "mc/world/level/block/VanillaBlockTypeIds.h"
#include "mc/world/level/block/registry/BlockTypeRegistry.h"
#include "mc/world/level/levelgen/feature/registry/FeatureRegistry.h"
#include "mc/world/level/levelgen/structure/Projection.h"
#include "mc/world/level/levelgen/structure/StructureManager.h"
#include "mc/world/level/levelgen/structure/registry/JigsawStructureBlockRulesRegistry.h"
#include "mc/world/level/levelgen/structure/registry/JigsawStructureElementRegistry.h"
#include "mc/world/level/levelgen/structure/registry/JigsawStructureRegistry.h"
#include "mc/world/level/levelgen/structure/registry/StructurePools.h"
#include "mc/world/level/levelgen/structure/structurepools/StructurePoolActorRule.h"
#include "mc/world/level/levelgen/structure/structurepools/StructurePoolBlockPredicateAlwaysTrue.h"
#include "mc/world/level/levelgen/structure/structurepools/StructurePoolBlockPredicateBlockMatchRandom.h"
#include "mc/world/level/levelgen/structure/structurepools/StructurePoolBlockRule.h"
#include "mc/world/level/levelgen/structure/structurepools/StructurePoolBlockTagRule.h"
#include "mc/world/level/levelgen/structure/structurepools/StructurePoolElement.h"
#include "mc/world/level/levelgen/structure/structurepools/StructureTemplatePool.h"
#include "mc/world/level/storage/Experiments.h"

#include <memory>

namespace custom_structure {

void CustomJigsawStructureBlockRules::initialize(JigsawStructureRegistry& registry) {
auto& jigsawBlockRulesRegistry = registry.getJigsawStructureBlockRulesRegistry();
// auto& DefaultBlockState =
// BlockTypeRegistry::getDefaultBlockState(VanillaBlockTypeIds::PolishedBlackstoneBricks(), 1);
auto& resultBlock = BlockTypeRegistry::getDefaultBlockState(VanillaBlockTypeIds::RedstoneBlock(), 1);
auto& block = BlockTypeRegistry::getDefaultBlockState(VanillaBlockTypeIds::Blackstone(), 1);

std::unique_ptr<IStructurePoolBlockPredicate> sourceBlock =
std::make_unique<StructurePoolBlockPredicateBlockMatchRandom>(block, 0.3);
std::unique_ptr<IStructurePoolBlockPredicate> targetBlock =
std::make_unique<StructurePoolBlockPredicateAlwaysTrue>();

auto blockRule =
std::make_unique<StructurePoolBlockRule>(std::move(sourceBlock), std::move(targetBlock), &resultBlock);

auto ruleList = std::make_unique<std::vector<std::unique_ptr<StructurePoolBlockRule>>>();

ruleList->push_back(std::move(blockRule));

jigsawBlockRulesRegistry.registerBlockRules("custom:custom_structure_block_rule", std::move(ruleList));
}

void CustomJigsawStructureElements::initialize(
gsl::not_null<Bedrock::NonOwnerPointer<StructureManager>> manager,
FeatureRegistry& featureRegistry,
JigsawStructureRegistry& jigsawRegistry
) {
auto& jigsawBlockRulesRegistry = jigsawRegistry.getJigsawStructureBlockRulesRegistry();
auto& jigsawStructureElementRegistry = jigsawRegistry.getJigsawStructureElementRegistry();
auto ruleList = jigsawBlockRulesRegistry.lookupByName("custom:custom_structure_block_rule");
std::vector<std::unique_ptr<StructurePoolBlockTagRule>> blockTag{};
std::vector<std::unique_ptr<StructurePoolActorRule>> actorRule{};
// blockTag.push_back(nullptr);
// actorRule.push_back(nullptr);

// 每一个结构nbt文件都得这样注册进来,多个nbt结构文件的可以使用同一个Block Rule
jigsawStructureElementRegistry.registerStructureElement(
"mike:21room",
std::make_unique<StructurePoolElement>(
manager,
"custom/21room",
ruleList,
nullptr,
nullptr,
Projection::Rigid,
PostProcessSettings::None
)
);

jigsawStructureElementRegistry.registerStructureElement(
"mike:ew7x4",
std::make_unique<StructurePoolElement>(
manager,
"custom/ewhall",
ruleList,
nullptr,
nullptr,
Projection::Rigid,
PostProcessSettings::None
)
);

jigsawStructureElementRegistry.registerStructureElement(
"mike:ns7x4",
std::make_unique<StructurePoolElement>(
manager,
"custom/nshall",
ruleList,
nullptr,
nullptr,
Projection::Rigid,
PostProcessSettings::None
)
);
}

void CustomJigsawStructure::initialize(
Bedrock::NotNullNonOwnerPtr<::StructureManager> manager,
FeatureRegistry& featureRegistry,
JigsawStructureRegistry& registry
) {
CustomJigsawStructureBlockRules::initialize(registry);
CustomJigsawStructureElements::initialize(manager, featureRegistry, registry);
auto& jigsawStructureElementRegistry = registry.getJigsawStructureElementRegistry();

std::vector<std::pair<StructurePoolElement const*, int>> templates_room{
{jigsawStructureElementRegistry.lookupByName("mike:21room"), 1}
};
std::vector<std::pair<StructurePoolElement const*, int>> templates_ew{
{jigsawStructureElementRegistry.lookupByName("mike:ew7x4"), 1}
};
std::vector<std::pair<StructurePoolElement const*, int>> templates_ns{
{jigsawStructureElementRegistry.lookupByName("mike:ns7x4"), 1}
};

registry.registerPool(std::make_unique<StructureTemplatePool>("mike:21room", "empty", templates_room));
registry.registerPool(std::make_unique<StructureTemplatePool>("mike:ew7x4", "empty", templates_ew));
registry.registerPool(std::make_unique<StructureTemplatePool>("mike:ns7x4", "empty", templates_ns));
}

} // namespace custom_structure

LL_AUTO_TYPE_STATIC_HOOK(
InitStructure,
HookPriority::Normal,
br::worldgen::StructurePools,
br::worldgen::StructurePools::bootstrap,
void,
Bedrock::NotNullNonOwnerPtr<StructureManager> structureManager,
FeatureRegistry& featureRegistry,
JigsawStructureRegistry& jigsawStructureRegistry,
BaseGameVersion const& baseGameVersion,
Experiments const& experiments
) {
origin(structureManager, featureRegistry, jigsawStructureRegistry, baseGameVersion, experiments);
custom_structure::CustomJigsawStructure::initialize(structureManager, featureRegistry, jigsawStructureRegistry);
return;
};
41 changes: 41 additions & 0 deletions src/test/generator/generator-custom-structure/CustomStructure.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#pragma once

#include "mc/deps/core/utility/NonOwnerPointer.h"

#include "gsl/pointers"

class FeatureRegistry;
class JigsawStructureRegistry;
class WorkerPool;
class StructureManager;

namespace custom_structure {

namespace CustomJigsawStructure {

// 总注册初始化函数
void initialize(
Bedrock::NotNullNonOwnerPtr<::StructureManager> manager,
FeatureRegistry& featureRegistry,
JigsawStructureRegistry& registry
);

} // namespace CustomJigsawStructure

namespace CustomJigsawStructureBlockRules {

void initialize(JigsawStructureRegistry& registry);

}

namespace CustomJigsawStructureElements {

void initialize(
gsl::not_null<Bedrock::NonOwnerPointer<StructureManager>> manager,
FeatureRegistry& featureRegistry,
JigsawStructureRegistry& jigsawRegistry
);

}

} // namespace custom_structure
5 changes: 5 additions & 0 deletions src/test/generator/generator-custom-structure/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
## You need to copy the files in the `structure-files` folder to this path

```
behavior_packs\vanilla\structures\
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
#include "CustomStructureDimension.h"

#include "test/generator/generator-custom-structure/generator/CustomStructureGenerator.h"
#include "test/generator/generator-custom-structure/structure/CustomStructureFeature.h"

#include "mc/common/Brightness.h"
#include "mc/common/BrightnessPair.h"
#include "mc/deps/core/math/Vec3.h"
#include "mc/world/level/BlockSource.h"
#include "mc/world/level/DimensionConversionData.h"
#include "mc/world/level/Level.h"
#include "mc/world/level/LevelSeed64.h"
#include "mc/world/level/chunk/vanilla_level_chunk_upgrade/VanillaLevelChunkUpgrade.h"
#include "mc/world/level/dimension/DimensionBrightnessRamp.h"
#include "mc/world/level/dimension/DimensionHeightRange.h"
#include "mc/world/level/dimension/OverworldBrightnessRamp.h"
#include "mc/world/level/dimension/VanillaDimensions.h"
#include "mc/world/level/levelgen/structure/StructureFeatureRegistry.h"
#include "mc/world/level/levelgen/structure/VillageFeature.h"
#include "mc/world/level/levelgen/structure/registry/StructureSetRegistry.h"
#include "mc/world/level/levelgen/v2/ChunkGeneratorStructureState.h"
#include "mc/world/level/storage/LevelData.h"


namespace custom_structure_dimension {

CustomStructureDimension::CustomStructureDimension(
std::string const& name,
more_dimensions::DimensionFactoryInfo const& info
)
: Dimension(info.level, info.dimId, {-64, 320}, info.scheduler, name) {
// 这里说明下,在DimensionFactoryInfo里面more-dimensions会提供维度id,请不要使用固定维度id,避免id冲突导致维度注册出现异常
mDefaultBrightness->sky = Brightness::MAX();
mSeaLevel = -61;
mHasWeather = true;
mDimensionBrightnessRamp = std::make_unique<OverworldBrightnessRamp>();
mDimensionBrightnessRamp->buildBrightnessRamp();
}

CompoundTag CustomStructureDimension::generateNewData() { return {}; }

std::unique_ptr<WorldGenerator>
CustomStructureDimension::createGenerator(br::worldgen::StructureSetRegistry const& structureSetRegistry) {
std::unique_ptr<WorldGenerator> worldGenerator;
uint seed = 2024;
auto& levelData = getLevel().getLevelData();

// 实例化我们写的Generator类
worldGenerator = std::make_unique<custom_structure_generator::CustomStructureGenerator>(
*this,
seed,
levelData.getFlatWorldGeneratorOptions()
);
// structureSetRegistry里面仅有的土径结构村庄生成需要用到,所以我们拿一下
std::vector<std::shared_ptr<const br::worldgen::StructureSet>> structureMap;
for (auto iter = structureSetRegistry.mStructureSets->begin(); iter != structureSetRegistry.mStructureSets->end(); iter++) {
structureMap.emplace_back(iter->second);
}
worldGenerator->getStructureFeatureRegistry().mGeneratorState->mSeed = seed;
worldGenerator->getStructureFeatureRegistry().mGeneratorState->mSeed64 =
LevelSeed64(seed);

// 这个就相当于在这个生成器里注册结构了
// VillageFeature的第二第三个参数是村庄之间的最大间隔与最小间隔
worldGenerator->getStructureFeatureRegistry().mStructureFeatures->emplace_back(
std::make_unique<VillageFeature>(seed, 34, 8)
);
worldGenerator->getStructureFeatureRegistry().mStructureFeatures->emplace_back(
std::make_unique<custom_structure::CustomStructureFeature>(seed)
);
// 此为必须,一些结构生成相关
worldGenerator->getStructureFeatureRegistry().mGeneratorState =
br::worldgen::ChunkGeneratorStructureState::createFlat(seed, worldGenerator->getBiomeSource(), structureMap);

return std::move(worldGenerator);
}

void CustomStructureDimension::upgradeLevelChunk(ChunkSource& cs, LevelChunk& lc, LevelChunk& generatedChunk) {
auto blockSource = BlockSource(getLevel(), *this, cs, false, true, false);
VanillaLevelChunkUpgrade::_upgradeLevelChunkViaMetaData(lc, generatedChunk, blockSource);
VanillaLevelChunkUpgrade::_upgradeLevelChunkLegacy(lc, blockSource);
}

void CustomStructureDimension::fixWallChunk(ChunkSource& cs, LevelChunk& lc) {
auto blockSource = BlockSource(getLevel(), *this, cs, false, true, false);
VanillaLevelChunkUpgrade::fixWallChunk(lc, blockSource);
}

bool CustomStructureDimension::levelChunkNeedsUpgrade(LevelChunk const& lc) const {
return VanillaLevelChunkUpgrade::levelChunkNeedsUpgrade(lc);
}
void CustomStructureDimension::_upgradeOldLimboEntity(CompoundTag& tag, ::LimboEntitiesVersion vers) {
auto isTemplate = getLevel().getLevelData().isFromWorldTemplate();
return VanillaLevelChunkUpgrade::upgradeOldLimboEntity(tag, vers, isTemplate);
}

std::unique_ptr<ChunkSource> CustomStructureDimension::
_wrapStorageForVersionCompatibility(std::unique_ptr<ChunkSource> cs, ::StorageVersion /*ver*/) {
return cs;
}

Vec3 CustomStructureDimension::translatePosAcrossDimension(Vec3 const& fromPos, DimensionType fromId) const {
Vec3 topos;
VanillaDimensions::convertPointBetweenDimensions(
fromPos,
topos,
fromId,
mId,
getLevel().getDimensionConversionData()
);
constexpr auto clampVal = 32000000.0f - 128.0f;

topos.x = std::clamp(topos.x, -clampVal, clampVal);
topos.z = std::clamp(topos.z, -clampVal, clampVal);

return topos;
}

short CustomStructureDimension::getCloudHeight() const { return 192; }

bool CustomStructureDimension::hasPrecipitationFog() const { return true; }

} // namespace custom_structure_dimension
Loading

0 comments on commit b115bc4

Please sign in to comment.