Skip to content

Commit

Permalink
test: add simple terrain test
Browse files Browse the repository at this point in the history
  • Loading branch information
quizhizhe committed Feb 6, 2025
1 parent d5b13a7 commit 397c40b
Show file tree
Hide file tree
Showing 8 changed files with 340 additions and 152 deletions.
3 changes: 3 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-terrain/NxnBorderTerrainDimension.h"

#include "ll/api/event/EventBus.h"
#include "ll/api/event/server/ServerStartedEvent.h"
Expand All @@ -22,6 +23,8 @@ static bool reg = [] {
.addDimension<more_dimensions::SimpleCustomDimension>("testNewVoidDimension", 345, GeneratorType::Void);
more_dimensions::CustomDimensionManager::getInstance()
.addDimension<flat_village_dimension::FlatVillageDimension>("testFlatVillage");
more_dimensions::CustomDimensionManager::getInstance()
.addDimension<nxn_border_terrain::NxnBorderTerrainDimension>("testFlatTerrain", 5);
});
return true;
}();
Expand Down
108 changes: 108 additions & 0 deletions src/test/generator/generator-terrain/NxnBorderTerrainDimension.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
#include "NxnBorderTerrainDimension.h"

#include "test/generator/generator-terrain/NxnBorderTerrainGenerator.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/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/flat/FlatWorldGenerator.h"
#include "mc/world/level/levelgen/structure/StructureFeatureRegistry.h"
#include "mc/world/level/levelgen/structure/VillageFeature.h"
#include "mc/world/level/levelgen/v2/ChunkGeneratorStructureState.h"
#include "mc/world/level/storage/LevelData.h"


namespace nxn_border_terrain {

NxnBorderTerrainDimension::NxnBorderTerrainDimension(
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();

// 这个是边长的区块数,是将会传到生成器里面用的
chunkLength = info.data["ChunkLength"];
}

CompoundTag NxnBorderTerrainDimension::generateNewData(uint chunkLength) {
CompoundTag result;
result["ChunkLength"] = chunkLength;
return result;
}

std::unique_ptr<WorldGenerator> NxnBorderTerrainDimension::createGenerator(br::worldgen::StructureSetRegistry const&) {

std::unique_ptr<WorldGenerator> worldGenerator;
auto seed = getLevel().getSeed();
auto& levelData = getLevel().getLevelData();

// 实例化一个FlatWorldGenerator类
worldGenerator =
std::make_unique<NxnBorderTerrainGenerator>(*this, seed, chunkLength, levelData.getFlatWorldGeneratorOptions());
// 此为必须,一些结构生成相关
worldGenerator->getStructureFeatureRegistry().mGeneratorState =
br::worldgen::ChunkGeneratorStructureState::createFlat(seed, worldGenerator->getBiomeSource(), {});

return std::move(worldGenerator);
}

void NxnBorderTerrainDimension::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 NxnBorderTerrainDimension::fixWallChunk(ChunkSource& cs, LevelChunk& lc) {
auto blockSource = BlockSource(getLevel(), *this, cs, false, true, false);
VanillaLevelChunkUpgrade::fixWallChunk(lc, blockSource);
}

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

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

Vec3 NxnBorderTerrainDimension::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 NxnBorderTerrainDimension::getCloudHeight() const { return 192; }

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

} // namespace nxn_border_terrain
49 changes: 49 additions & 0 deletions src/test/generator/generator-terrain/NxnBorderTerrainDimension.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#pragma once

#include "mc/world/level/dimension/Dimension.h" // 新维度类需要继承的类
#include "more_dimensions/api/dimension/CustomDimensionManager.h" // 使用DimensionFactoryInfo的声明

// 建议是加一个命名空间,避免与其他插件同类名的情况
namespace nxn_border_terrain {

class NxnBorderTerrainDimension : public Dimension {
uint chunkLength;

public:
// 建议固定这样写,DimensionFactoryInfo类里面提供了Dimension实例化的基本数据,name就是维度名,多维度是维度名区分不同维度
NxnBorderTerrainDimension(std::string const& name, more_dimensions::DimensionFactoryInfo const& info);

// 多维度需要的一个方法,参数是你需要的一些额外的数据,比如种子
static CompoundTag generateNewData(uint chunkLength = 4);

// 以下六个是必须重写的函数
// 维度地形的生成器,是本教程主要更改的地方
std::unique_ptr<WorldGenerator> createGenerator(br::worldgen::StructureSetRegistry const&) override;

// 与本教程无关,按照本教程写的就行,无需留意
void upgradeLevelChunk(ChunkSource& chunkSource, LevelChunk& oldLc, LevelChunk& newLc) override;

// 与本教程无关,按照本教程写的就行,无需留意
void fixWallChunk(ChunkSource& cs, LevelChunk& lc) override;

// 与本教程无关,按照本教程写的就行,无需留意
bool levelChunkNeedsUpgrade(LevelChunk const& lc) const override;

// 与本教程无关,按照本教程写的就行,无需留意
void _upgradeOldLimboEntity(CompoundTag& tag, ::LimboEntitiesVersion vers) override;

// 与本教程无关,按照本教程写的就行,无需留意
std::unique_ptr<ChunkSource>
_wrapStorageForVersionCompatibility(std::unique_ptr<ChunkSource> cs, ::StorageVersion ver) override;

// 当你转到这个维度时,坐标怎么转换,比如主世界与地狱的
Vec3 translatePosAcrossDimension(Vec3 const& pos, DimensionType did) const override;

// 云高度,默认是y128,但多维度高度范围是在y-64~320,与主世界相同,重写它,放高些
short getCloudHeight() const override;

// 非必要。下雨时,可视范围的更改
bool hasPrecipitationFog() const override;
};

} // namespace nxn_border_terrain
141 changes: 141 additions & 0 deletions src/test/generator/generator-terrain/NxnBorderTerrainGenerator.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
//
// Created by User on 2024/2/22.
//

#include "NxnBorderTerrainGenerator.h"

#include "mc/world/level/ChunkPos.h"
#include "mc/world/level/biome/source/FixedBiomeSource.h"
#include "mc/world/level/block/BedrockBlockNames.h"
#include "mc/world/level/block/Block.h"
#include "mc/world/level/block/BlockVolume.h"
#include "mc/world/level/block/VanillaBlockTypeIds.h"
#include "mc/world/level/block/registry/BlockTypeRegistry.h"
#include "mc/world/level/chunk/LevelChunk.h"
#include "mc/world/level/dimension/Dimension.h"
#include "mc/world/level/levelgen/v1/ChunkLocalNoiseCache.h"

#include "mc/world/level/block/Block.h"


namespace nxn_border_terrain {

NxnBorderTerrainGenerator::NxnBorderTerrainGenerator(
Dimension& dimension,
uint seed,
uint chunkLength,
Json::Value const& generationOptionsJSON
)
: FlatWorldGenerator(dimension, seed, generationOptionsJSON) {
chunk_n = chunkLength;
auto height = mPrototype->mHeight;
auto& roadBlock = BlockTypeRegistry::getDefaultBlockState(VanillaBlockTypeIds::GrassPath());
auto& borderBlock = BlockTypeRegistry::getDefaultBlockState(VanillaBlockTypeIds::SmoothStoneSlab());

east_side_b.mBlocks = {east_side.data(), east_side.data() + east_side.size()};
south_side_b.mBlocks = {south_side.data(), south_side.data() + south_side.size()};
west_side_b.mBlocks = {west_side.data(), west_side.data() + west_side.size()};
north_side_b.mBlocks = {north_side.data(), north_side.data() + north_side.size()};
n_e_angle_b.mBlocks = {n_e_angle.data(), n_e_angle.data() + n_e_angle.size()};
e_s_angle_b.mBlocks = {e_s_angle.data(), e_s_angle.data() + e_s_angle.size()};
s_w_angle_b.mBlocks = {s_w_angle.data(), s_w_angle.data() + s_w_angle.size()};
w_n_angle_b.mBlocks = {w_n_angle.data(), w_n_angle.data() + w_n_angle.size()};

for (int i = 0; i < 16; i++) {
// 一般开始的是距离第一个方块的差值,然后是会乘
// i的间隔方块,然后是与另外一条路或者半砖方块的间隔,最后面的是第几层
// 南边
e_s_angle[height * 15 + height * 16 * i + 3] = &roadBlock;

s_w_angle[height * 15 + height * 16 * i + 3] = &roadBlock;

south_side[height * 15 + height * 16 * i + 3] = &roadBlock;
south_side[height * 14 + height * 16 * i + 4] = &borderBlock;
// 东边
e_s_angle[height * 16 * 15 + height * i + 3] = &roadBlock;

n_e_angle[height * 16 * 15 + height * i + 3] = &roadBlock;

east_side[height * 16 * 15 + height * i + 3] = &roadBlock;
east_side[height * 16 * 14 + height * i + 4] = &borderBlock;
// 西边
s_w_angle[height * i + 3] = &roadBlock;

w_n_angle[height * i + 3] = &roadBlock;

west_side[height * i + 3] = &roadBlock;
west_side[height * 16 + height * i + 4] = &borderBlock;
// 北边
n_e_angle[height * 16 * i + 3] = &roadBlock;

w_n_angle[height * 16 * i + 3] = &roadBlock;

north_side[height * 16 * i + 3] = &roadBlock;
north_side[height + height * 16 * i + 4] = &borderBlock;

// 半砖避免放到路上,最后一次循环
if (i < 15) {
//
e_s_angle[height * 14 + height * 16 * i + 4] = &borderBlock;
//
e_s_angle[height * 16 * 14 + height * i + 4] = &borderBlock;
// 西
s_w_angle[height * 16 + height * i + 4] = &borderBlock;
//
n_e_angle[height + height * 16 * i + 4] = &borderBlock;
}
// 第一次循环
if (i > 0) {
// 西
w_n_angle[height * 16 + height * i + 4] = &borderBlock;
//
w_n_angle[height + height * 16 * i + 4] = &borderBlock;
//
s_w_angle[height * 14 + height * 16 * i + 4] = &borderBlock;
//
n_e_angle[height * 16 * 14 + height * i + 4] = &borderBlock;
}
}
}

void NxnBorderTerrainGenerator::loadChunk(LevelChunk& levelchunk, bool forceImmediateReplacementDataLoad) {
auto chunkPos = levelchunk.getPosition();

int n = chunk_n;
auto pos_x = (chunkPos.x % n + n) % n;
auto pos_z = (chunkPos.z % n + n) % n;

if (pos_x == 0) {
if (pos_z == 0) {
levelchunk.setBlockVolume(w_n_angle_b, 0);
} else if (pos_z == (n - 1)) {
levelchunk.setBlockVolume(s_w_angle_b, 0);
} else {
levelchunk.setBlockVolume(west_side_b, 0);
}

} else if (pos_x == (n - 1)) {
if (pos_z == 0) {
levelchunk.setBlockVolume(n_e_angle_b, 0);
} else if (pos_z == (n - 1)) {
levelchunk.setBlockVolume(e_s_angle_b, 0);
} else {
levelchunk.setBlockVolume(east_side_b, 0);
}
} else if (pos_z == 0) {
levelchunk.setBlockVolume(north_side_b, 0);
} else if (pos_z == (n - 1)) {
levelchunk.setBlockVolume(south_side_b, 0);
} else {
levelchunk.setBlockVolume(mPrototype, 0);
}

levelchunk.recomputeHeightMap(false);
mBiomeSource = std::make_unique<FixedBiomeSource>(*mBiome);
ChunkLocalNoiseCache chunkLocalNoiseCache;
mBiomeSource->fillBiomes(levelchunk, chunkLocalNoiseCache);
levelchunk.setSaved();
levelchunk.changeState(ChunkState::Generating, ChunkState::Generated);
}

} // namespace nxn_border_terrain
37 changes: 37 additions & 0 deletions src/test/generator/generator-terrain/NxnBorderTerrainGenerator.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#pragma once

#include "mc/world/level/block/BlockVolume.h"
#include "mc/world/level/levelgen/flat/FlatWorldGenerator.h"

#include <vector>

namespace nxn_border_terrain {

class NxnBorderTerrainGenerator : public FlatWorldGenerator {
public:
uint chunk_n = 4; // n * n的区块
std::vector<Block const*> east_side = mPrototypeBlocks;
std::vector<Block const*> south_side = mPrototypeBlocks;
std::vector<Block const*> west_side = mPrototypeBlocks;
std::vector<Block const*> north_side = mPrototypeBlocks;
std::vector<Block const*> n_e_angle = mPrototypeBlocks;
std::vector<Block const*> e_s_angle = mPrototypeBlocks;
std::vector<Block const*> s_w_angle = mPrototypeBlocks;
std::vector<Block const*> w_n_angle = mPrototypeBlocks;
BlockVolume east_side_b = mPrototype;
BlockVolume south_side_b = mPrototype;
BlockVolume west_side_b = mPrototype;
BlockVolume north_side_b = mPrototype;
BlockVolume n_e_angle_b = mPrototype;
BlockVolume e_s_angle_b = mPrototype;
BlockVolume s_w_angle_b = mPrototype;
BlockVolume w_n_angle_b = mPrototype;
NxnBorderTerrainGenerator(
Dimension& dimension,
uint seed,
uint chunkLength,
Json::Value const& generationOptionsJSON
);
void loadChunk(class LevelChunk& levelchunk, bool forceImmediateReplacementDataLoad);
};
} // namespace nxn_border_terrain
Loading

0 comments on commit 397c40b

Please sign in to comment.