First pass at world gen, rubber tree needs further work, ideally depends on fab api changes.

This commit is contained in:
modmuss50 2021-11-16 23:54:31 +00:00
parent 4a2e81550f
commit e1093d782a
13 changed files with 270 additions and 560 deletions

View file

@ -85,7 +85,7 @@ public class TechReborn implements ModInitializer {
RecipeCrafter.soundHanlder = new ModSounds.SoundHandler(); RecipeCrafter.soundHanlder = new ModSounds.SoundHandler();
} }
ModLoot.init(); ModLoot.init();
// WorldGenerator.initWorldGen(); WorldGenerator.initWorldGen();
FluidGeneratorRecipes.init(); FluidGeneratorRecipes.init();
//Force loads the block entities at the right time //Force loads the block entities at the right time
//noinspection ResultOfMethodCallIgnored //noinspection ResultOfMethodCallIgnored

View file

@ -41,7 +41,6 @@ import reborncore.common.fluid.FluidValue;
import reborncore.common.powerSystem.PowerAcceptorBlockEntity; import reborncore.common.powerSystem.PowerAcceptorBlockEntity;
import reborncore.common.powerSystem.RcEnergyTier; import reborncore.common.powerSystem.RcEnergyTier;
import reborncore.common.powerSystem.RcEnergyTier;
import techreborn.TechReborn; import techreborn.TechReborn;
import techreborn.blockentity.generator.LightningRodBlockEntity; import techreborn.blockentity.generator.LightningRodBlockEntity;
import techreborn.blockentity.generator.PlasmaGeneratorBlockEntity; import techreborn.blockentity.generator.PlasmaGeneratorBlockEntity;
@ -85,7 +84,8 @@ import techreborn.items.UpgradeItem;
import techreborn.items.armor.QuantumSuitItem; import techreborn.items.armor.QuantumSuitItem;
import techreborn.items.tool.MiningLevel; import techreborn.items.tool.MiningLevel;
import techreborn.utils.InitUtils; import techreborn.utils.InitUtils;
import techreborn.world.DataDrivenFeature; import techreborn.world.OreFeature;
import techreborn.world.TargetDimension;
import java.util.*; import java.util.*;
import java.util.function.Function; import java.util.function.Function;
@ -378,21 +378,21 @@ public class TRContent {
} }
public enum Ores implements ItemConvertible { public enum Ores implements ItemConvertible {
BAUXITE(6, 10, 10, 60, MiningLevel.IRON), BAUXITE(6, 10, 10, 60, MiningLevel.IRON, TargetDimension.OVERWORLD),
CINNABAR(6, 3, 10, 126, MiningLevel.IRON), CINNABAR(6, 3, 10, 126, MiningLevel.IRON, TargetDimension.NETHER),
GALENA(8, 16, 10, 60, MiningLevel.IRON), GALENA(8, 16, 10, 60, MiningLevel.IRON, TargetDimension.OVERWORLD),
IRIDIUM(3, 3, 5, 60, MiningLevel.DIAMOND), IRIDIUM(3, 3, 5, 60, MiningLevel.DIAMOND, TargetDimension.OVERWORLD),
LEAD(6, 16, 20, 60, MiningLevel.IRON), LEAD(6, 16, 20, 60, MiningLevel.IRON, TargetDimension.OVERWORLD),
PERIDOT(6, 3, 10, 250, MiningLevel.DIAMOND), PERIDOT(6, 3, 10, 250, MiningLevel.DIAMOND, TargetDimension.END),
PYRITE(6, 3, 10, 126, MiningLevel.DIAMOND), PYRITE(6, 3, 10, 126, MiningLevel.DIAMOND, TargetDimension.NETHER),
RUBY(6, 3, 10, 60, MiningLevel.IRON), RUBY(6, 3, 10, 60, MiningLevel.IRON, TargetDimension.OVERWORLD),
SAPPHIRE(6, 3, 10, 60, MiningLevel.IRON), SAPPHIRE(6, 3, 10, 60, MiningLevel.IRON, TargetDimension.OVERWORLD),
SHELDONITE(6, 3, 10, 250, MiningLevel.DIAMOND), SHELDONITE(6, 3, 10, 250, MiningLevel.DIAMOND, TargetDimension.END),
SILVER(6, 16, 20, 60, MiningLevel.IRON), SILVER(6, 16, 20, 60, MiningLevel.IRON, TargetDimension.OVERWORLD),
SODALITE(6, 3, 10, 250, MiningLevel.DIAMOND), SODALITE(6, 3, 10, 250, MiningLevel.DIAMOND, TargetDimension.END),
SPHALERITE(6, 3, 10, 126, MiningLevel.IRON), SPHALERITE(6, 3, 10, 126, MiningLevel.IRON, TargetDimension.NETHER),
TIN(8, 16, 20, 60, MiningLevel.STONE), TIN(8, 16, 20, 60, MiningLevel.STONE, TargetDimension.OVERWORLD),
TUNGSTEN(6, 3, 10, 250, MiningLevel.DIAMOND); TUNGSTEN(6, 3, 10, 250, MiningLevel.DIAMOND, TargetDimension.END);
public final String name; public final String name;
public final Block block; public final Block block;
@ -400,8 +400,10 @@ public class TRContent {
public final int veinsPerChunk; public final int veinsPerChunk;
public final int minY; public final int minY;
public final int maxY; public final int maxY;
public final TargetDimension dimension;
Ores(int veinSize, int veinsPerChunk, int minY, int maxY, MiningLevel miningLevel) { Ores(int veinSize, int veinsPerChunk, int minY, int maxY, MiningLevel miningLevel, TargetDimension dimension) {
this.dimension = dimension;
name = this.toString().toLowerCase(Locale.ROOT); name = this.toString().toLowerCase(Locale.ROOT);
block = new OreBlock(FabricBlockSettings.of(Material.STONE) block = new OreBlock(FabricBlockSettings.of(Material.STONE)
.breakByTool(FabricToolTags.PICKAXES, miningLevel.intLevel) .breakByTool(FabricToolTags.PICKAXES, miningLevel.intLevel)
@ -420,11 +422,6 @@ public class TRContent {
public Item asItem() { public Item asItem() {
return block.asItem(); return block.asItem();
} }
public DataDrivenFeature asNewOres(Identifier identifier, Predicate<BiomeSelectionContext> targetType, RuleTest ruleTest) {
return new DataDrivenFeature(identifier, targetType, ruleTest, block.getDefaultState(), maxY, veinSize, veinsPerChunk);
}
} }
public enum StorageBlocks implements ItemConvertible { public enum StorageBlocks implements ItemConvertible {

View file

@ -1,82 +0,0 @@
/*
* This file is part of TechReborn, licensed under the MIT License (MIT).
*
* Copyright (c) 2020 TechReborn
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package techreborn.world;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import net.fabricmc.fabric.api.biome.v1.BiomeSelectionContext;
import net.fabricmc.fabric.api.biome.v1.BiomeSelectors;
import net.minecraft.util.Util;
import net.minecraft.world.biome.Biome;
import java.util.*;
import java.util.function.Predicate;
public class BiomeSelectorDeserialiser {
private static final Map<String, Predicate<BiomeSelectionContext>> SIMPLE_SELECTOR_MAP = Util.make(new HashMap<>(), map -> {
map.put("all", BiomeSelectors.all());
map.put("overworld", BiomeSelectors.foundInOverworld());
map.put("end", BiomeSelectors.foundInTheEnd());
map.put("nether", BiomeSelectors.foundInTheNether());
});
public static Predicate<BiomeSelectionContext> deserialise(JsonElement jsonElement) {
if (jsonElement.isJsonPrimitive() && jsonElement.getAsJsonPrimitive().isString()) {
Predicate<BiomeSelectionContext> selector = SIMPLE_SELECTOR_MAP.get(jsonElement.getAsString().toLowerCase(Locale.ROOT));
if (selector == null) {
throw new JsonParseException("Could not find selector for " + jsonElement.getAsString());
}
return selector;
}
if (jsonElement.isJsonArray()) {
JsonArray jsonArray = jsonElement.getAsJsonArray();
Set<Biome.Category> categorySet = EnumSet.noneOf(Biome.Category.class);
for (JsonElement element : jsonArray) {
if (!(element.isJsonPrimitive() && element.getAsJsonPrimitive().isString())) {
throw new JsonParseException("json array must only contain strings");
}
Biome.Category category = Biome.Category.byName(element.getAsString());
if (category == null) {
throw new JsonParseException("Could not find biome category: " + element.getAsString());
}
categorySet.add(category);
}
return context -> categorySet.contains(context.getBiome().getCategory());
}
// TODO support more complex selectors here
throw new JsonParseException("Could not parse biome selector");
}
}

View file

@ -1,132 +0,0 @@
/*
* This file is part of TechReborn, licensed under the MIT License (MIT).
*
* Copyright (c) 2020 TechReborn
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package techreborn.world;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.mojang.serialization.DataResult;
import com.mojang.serialization.Dynamic;
import com.mojang.serialization.JsonOps;
import net.fabricmc.fabric.api.biome.v1.BiomeSelectionContext;
import net.minecraft.block.BlockState;
import net.minecraft.structure.rule.RuleTest;
import net.minecraft.util.Identifier;
import net.minecraft.util.JsonHelper;
import net.minecraft.util.registry.BuiltinRegistries;
import net.minecraft.util.registry.RegistryKey;
import net.minecraft.world.gen.GenerationStep;
import net.minecraft.world.gen.YOffset;
import net.minecraft.world.gen.feature.ConfiguredFeature;
import net.minecraft.world.gen.feature.Feature;
import net.minecraft.world.gen.feature.OreFeatureConfig;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.util.function.Predicate;
public class DataDrivenFeature {
private static final Logger LOGGER = LogManager.getLogger();
private Predicate<BiomeSelectionContext> biomeSelector;
private ConfiguredFeature<?, ?> configuredFeature;
private GenerationStep.Feature generationStep;
private Identifier identifier;
// public DataDrivenFeature(Identifier identifier, Predicate<BiomeSelectionContext> biomeSelector, ConfiguredFeature<?, ?> configuredFeature, GenerationStep.Feature generationStep) {
// this.identifier = identifier;
// this.biomeSelector = biomeSelector;
// this.configuredFeature = configuredFeature;
// this.generationStep = generationStep;
// }
@Deprecated
public DataDrivenFeature(Identifier identifier, Predicate<BiomeSelectionContext> biomeSelector, RuleTest ruleTest, BlockState blockState, int maxY, int veinSize, int veinCount) {
// this(identifier, biomeSelector, Feature.ORE.configure(
// new OreFeatureConfig(ruleTest, blockState, veinSize)
// ));
// TODO 1.18
// .uniformRange(YOffset.getBottom(), YOffset.fixed(maxY))
// .spreadHorizontally()
// .repeat(veinCount), GenerationStep.Feature.UNDERGROUND_ORES);
}
public static DataDrivenFeature deserialise(Identifier identifier, JsonObject jsonObject) {
if (!JsonHelper.hasElement(jsonObject, "biomeSelector")) {
throw new JsonParseException("Could not find biomeSelector element");
}
Predicate<BiomeSelectionContext> biomeSelector = BiomeSelectorDeserialiser.deserialise(jsonObject.get("biomeSelector"));
if (!JsonHelper.hasElement(jsonObject, "configuredFeature")) {
throw new JsonParseException("Could not find configuredFeature element");
}
DataResult<ConfiguredFeature<?, ?>> dataResult = ConfiguredFeature.CODEC.parse(new Dynamic<>(JsonOps.INSTANCE, jsonObject.get("configuredFeature")));
ConfiguredFeature<?, ?> configuredFeature = dataResult.getOrThrow(true, s -> {
throw new JsonParseException(s);
});
if (!JsonHelper.hasElement(jsonObject, "generationStep")) {
throw new JsonParseException("Could not find generationStep element");
}
DataResult<WorldGenCodecs.GenerationStepFeature> genStepDataResult = WorldGenCodecs.GenerationStepFeature.CODEC.parse(new Dynamic<>(JsonOps.INSTANCE, jsonObject.get("generationStep")));
GenerationStep.Feature generationStep = genStepDataResult.getOrThrow(true, s -> {
throw new JsonParseException(s);
}).getFeature();
return null;
// return new DataDrivenFeature(identifier, biomeSelector, configuredFeature, generationStep);
}
public JsonObject serialise() {
JsonObject jsonObject = new JsonObject();
jsonObject.addProperty("biomeSelector", "overworld");
jsonObject.add("generationStep", WorldGenCodecs.GenerationStepFeature.CODEC.encodeStart(JsonOps.INSTANCE, WorldGenCodecs.GenerationStepFeature.byFeature(generationStep)).getOrThrow(true, LOGGER::error));
jsonObject.add("configuredFeature", ConfiguredFeature.CODEC.encodeStart(JsonOps.INSTANCE, configuredFeature).getOrThrow(true, LOGGER::error));
return jsonObject;
}
public ConfiguredFeature<?, ?> getConfiguredFeature() {
return configuredFeature;
}
public RegistryKey<ConfiguredFeature<?, ?>> getRegistryKey() {
return RegistryKey.of(BuiltinRegistries.CONFIGURED_FEATURE.getKey(), identifier);
}
public Identifier getIdentifier() {
return identifier;
}
public GenerationStep.Feature getGenerationStep() {
return generationStep;
}
public Predicate<BiomeSelectionContext> getBiomeSelector() {
return biomeSelector;
}
}

View file

@ -1,141 +0,0 @@
/*
* This file is part of TechReborn, licensed under the MIT License (MIT).
*
* Copyright (c) 2020 TechReborn
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package techreborn.world;
import com.google.gson.JsonElement;
import net.fabricmc.fabric.api.biome.v1.BiomeSelectionContext;
import net.fabricmc.fabric.api.biome.v1.BiomeSelectors;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.structure.rule.BlockStateMatchRuleTest;
import net.minecraft.structure.rule.RuleTest;
import net.minecraft.util.Identifier;
import net.minecraft.util.collection.DataPool;
import net.minecraft.util.math.Direction;
import net.minecraft.util.registry.Registry;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.gen.GenerationStep;
import net.minecraft.world.gen.feature.ConfiguredFeature;
import net.minecraft.world.gen.feature.OreConfiguredFeatures;
import net.minecraft.world.gen.stateprovider.BlockStateProvider;
import net.minecraft.world.gen.stateprovider.WeightedBlockStateProvider;
import org.apache.logging.log4j.util.TriConsumer;
import techreborn.blocks.misc.BlockRubberLog;
import techreborn.init.TRContent;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
public class DefaultWorldGen {
private static final RuleTest END_STONE = new BlockStateMatchRuleTest(Blocks.END_STONE.getDefaultState());
private static ConfiguredFeature<?, ?> getRubberTree() {
DataPool.Builder<BlockState> logPoolBuilder = DataPool.<BlockState>builder()
.add(TRContent.RUBBER_LOG.getDefaultState(), 10);
Arrays.stream(Direction.values())
.filter(direction -> direction.getAxis().isHorizontal())
.map(direction -> TRContent.RUBBER_LOG.getDefaultState()
.with(BlockRubberLog.HAS_SAP, true)
.with(BlockRubberLog.SAP_SIDE, direction)
)
.forEach(state -> logPoolBuilder.add(state, 1));
BlockStateProvider logProvider = new WeightedBlockStateProvider(logPoolBuilder.build());
// TreeFeatureConfig treeFeatureConfig = new TreeFeatureConfig.Builder(
// logProvider,
// new StraightTrunkPlacer(6, 3, 0),
// BlockStateProvider.of(TRContent.RUBBER_LEAVES.getDefaultState()),
// BlockStateProvider.of(TRContent.RUBBER_SAPLING.getDefaultState()),
// new RubberTreeFeature.FoliagePlacer(ConstantIntProvider.create(2), ConstantIntProvider.create(0), 3, 3, TRContent.RUBBER_LEAVES.getDefaultState()),
// new TwoLayersFeatureSize(1, 0, 1)
// ).build();
return null; // TODO 1.18
// return WorldGenerator.RUBBER_TREE_FEATURE.configure(treeFeatureConfig)
// .decorate(WorldGenerator.RUBBER_TREE_DECORATOR
// .configure(new ChanceDecoratorConfig(50)
// ));
}
public static List<DataDrivenFeature> getDefaultFeatures() {
List<DataDrivenFeature> features = new ArrayList<>();
TriConsumer<Predicate<BiomeSelectionContext>, RuleTest, TRContent.Ores> addOre = (worldTargetType, ruleTest, ore) ->
features.add(ore.asNewOres(new Identifier("techreborn", Registry.BLOCK.getId(ore.block).getPath()), worldTargetType, ruleTest));
addOre.accept(BiomeSelectors.foundInTheNether(), OreConfiguredFeatures.BASE_STONE_NETHER, TRContent.Ores.CINNABAR);
addOre.accept(BiomeSelectors.foundInTheNether(), OreConfiguredFeatures.BASE_STONE_NETHER, TRContent.Ores.PYRITE);
addOre.accept(BiomeSelectors.foundInTheNether(), OreConfiguredFeatures.BASE_STONE_NETHER, TRContent.Ores.SPHALERITE);
addOre.accept(BiomeSelectors.foundInTheEnd(), END_STONE, TRContent.Ores.PERIDOT);
addOre.accept(BiomeSelectors.foundInTheEnd(), END_STONE, TRContent.Ores.SHELDONITE);
addOre.accept(BiomeSelectors.foundInTheEnd(), END_STONE, TRContent.Ores.SODALITE);
addOre.accept(BiomeSelectors.foundInTheEnd(), END_STONE, TRContent.Ores.TUNGSTEN);
addOre.accept(BiomeSelectors.foundInOverworld(), OreConfiguredFeatures.BASE_STONE_OVERWORLD, TRContent.Ores.BAUXITE);
addOre.accept(BiomeSelectors.foundInOverworld(), OreConfiguredFeatures.BASE_STONE_OVERWORLD, TRContent.Ores.GALENA);
addOre.accept(BiomeSelectors.foundInOverworld(), OreConfiguredFeatures.BASE_STONE_OVERWORLD, TRContent.Ores.IRIDIUM);
addOre.accept(BiomeSelectors.foundInOverworld(), OreConfiguredFeatures.BASE_STONE_OVERWORLD, TRContent.Ores.LEAD);
addOre.accept(BiomeSelectors.foundInOverworld(), OreConfiguredFeatures.BASE_STONE_OVERWORLD, TRContent.Ores.RUBY);
addOre.accept(BiomeSelectors.foundInOverworld(), OreConfiguredFeatures.BASE_STONE_OVERWORLD, TRContent.Ores.SAPPHIRE);
addOre.accept(BiomeSelectors.foundInOverworld(), OreConfiguredFeatures.BASE_STONE_OVERWORLD, TRContent.Ores.SILVER);
addOre.accept(BiomeSelectors.foundInOverworld(), OreConfiguredFeatures.BASE_STONE_OVERWORLD, TRContent.Ores.TIN);
//
// features.add(new DataDrivenFeature(
// RubberSaplingGenerator.IDENTIFIER,
// BiomeSelectors.categories(Biome.Category.FOREST, Biome.Category.TAIGA, Biome.Category.SWAMP),
// getRubberTree(),
// GenerationStep.Feature.VEGETAL_DECORATION
// ));
return features;
}
// Used to export the worldgen jsons
public static void export() {
for (DataDrivenFeature defaultFeature : getDefaultFeatures()) {
JsonElement jsonElement = defaultFeature.serialise();
String json = jsonElement.toString();
Path dir = Paths.get("..\\src\\main\\resources\\data\\techreborn\\techreborn\\features");
try {
Files.writeString(dir.resolve(defaultFeature.getIdentifier().getPath() + ".json"), json);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

View file

@ -0,0 +1,83 @@
/*
* This file is part of TechReborn, licensed under the MIT License (MIT).
*
* Copyright (c) 2020 TechReborn
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package techreborn.world;
import net.fabricmc.fabric.api.biome.v1.BiomeSelectionContext;
import net.minecraft.util.Identifier;
import net.minecraft.util.registry.BuiltinRegistries;
import net.minecraft.util.registry.Registry;
import net.minecraft.util.registry.RegistryKey;
import net.minecraft.world.gen.YOffset;
import net.minecraft.world.gen.decorator.*;
import net.minecraft.world.gen.feature.*;
import techreborn.init.TRContent;
import java.util.List;
import java.util.function.Predicate;
public class OreFeature {
private final TRContent.Ores ore;
private final ConfiguredFeature<?, ?> configuredFeature;
private final PlacedFeature placedFeature;
public OreFeature(TRContent.Ores ore) {
this.ore = ore;
this.configuredFeature = configureAndRegisterFeature();
this.placedFeature = configureAndRegisterPlacedFeature();
}
private ConfiguredFeature<?, ?> configureAndRegisterFeature() {
ConfiguredFeature<?, ?> configuredFeature = Feature.ORE.configure(new OreFeatureConfig(ore.dimension.ruleTest, ore.block.getDefaultState(), ore.veinSize));
Registry.register(BuiltinRegistries.CONFIGURED_FEATURE, getId(), configuredFeature);
return configuredFeature;
}
private PlacedFeature configureAndRegisterPlacedFeature() {
PlacedFeature placedFeature = configuredFeature.withPlacement(getPlacementModifiers());
Registry.register(BuiltinRegistries.PLACED_FEATURE, getId(), placedFeature);
return placedFeature;
}
private List<PlacementModifier> getPlacementModifiers() {
return modifiers(CountPlacementModifier.of(ore.veinsPerChunk), HeightRangePlacementModifier.trapezoid(YOffset.aboveBottom(ore.minY), YOffset.aboveBottom(ore.maxY)));
}
private static List<PlacementModifier> modifiers(PlacementModifier first, PlacementModifier second) {
return List.of(first, SquarePlacementModifier.of(), second, BiomePlacementModifier.of());
}
public final Identifier getId() {
return new Identifier("techreborn", ore.name + "_ore");
}
public Predicate<BiomeSelectionContext> getBiomeSelector() {
return ore.dimension.biomeSelector;
}
public RegistryKey<PlacedFeature> getPlacedFeatureRegistryKey() {
return BuiltinRegistries.PLACED_FEATURE.getKey(this.placedFeature).orElseThrow();
}
}

View file

@ -25,8 +25,6 @@
package techreborn.world; package techreborn.world;
import net.minecraft.block.sapling.SaplingGenerator; import net.minecraft.block.sapling.SaplingGenerator;
import net.minecraft.util.Identifier;
import net.minecraft.util.registry.BuiltinRegistries;
import net.minecraft.world.gen.feature.ConfiguredFeature; import net.minecraft.world.gen.feature.ConfiguredFeature;
import net.minecraft.world.gen.feature.TreeFeatureConfig; import net.minecraft.world.gen.feature.TreeFeatureConfig;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@ -34,14 +32,9 @@ import org.jetbrains.annotations.Nullable;
import java.util.Random; import java.util.Random;
public class RubberSaplingGenerator extends SaplingGenerator { public class RubberSaplingGenerator extends SaplingGenerator {
public static final Identifier IDENTIFIER = new Identifier("techreborn", "techreborn/features/rubber_tree.json");
@Nullable @Nullable
@Override @Override
protected ConfiguredFeature<TreeFeatureConfig, ?> getTreeFeature(Random random, boolean bl) { protected ConfiguredFeature<TreeFeatureConfig, ?> getTreeFeature(Random random, boolean bl) {
// DecoratedFeatureConfig decoratedFeatureConfig = (DecoratedFeatureConfig) BuiltinRegistries.CONFIGURED_FEATURE.get(IDENTIFIER).getConfig(); return WorldGenerator.RUBBER_TREE_FEATURE;
// //noinspection unchecked
// return (ConfiguredFeature<TreeFeatureConfig, ?>) decoratedFeatureConfig.feature.get();
return null; // TODO 1.18
} }
} }

View file

@ -1,59 +0,0 @@
/*
* This file is part of TechReborn, licensed under the MIT License (MIT).
*
* Copyright (c) 2020 TechReborn
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package techreborn.world;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.Heightmap;
import net.minecraft.world.gen.decorator.DecoratorContext;
import java.util.Random;
import java.util.stream.IntStream;
import java.util.stream.Stream;
// Big thanks to SuperCoder7979 for this
public class RubberTreeDecorator { // extends Decorator<ChanceDecoratorConfig> {
// TODO 1.18
// public RubberTreeDecorator(Codec<ChanceDecoratorConfig> codec) {
// super(codec);
// }
//
// @Override
// public Stream<BlockPos> getPositions(DecoratorContext context, Random random, ChanceDecoratorConfig config, BlockPos pos) {
// // Generate tree clusters randomly
// if (random.nextInt(config.chance) == 0) {
// // Generate 4 - 8 trees
// int treeCount = 4 + random.nextInt(5);
// return IntStream.range(0, treeCount).mapToObj((i) -> {
// int x = random.nextInt(16) + pos.getX();
// int z = random.nextInt(16) + pos.getZ();
// int y = context.getTopY(Heightmap.Type.MOTION_BLOCKING, x, z);
// return new BlockPos(x, y, z);
// });
// }
// return Stream.empty();
// }
}

View file

@ -94,7 +94,7 @@ public class RubberTreeFeature extends TreeFeature {
@Override @Override
protected FoliagePlacerType<?> getType() { protected FoliagePlacerType<?> getType() {
return WorldGenerator.RUBBER_TREE_FOLIAGE_PLACER_TYPE; return null;
} }
public int getSpireHeight() { public int getSpireHeight() {
@ -105,6 +105,4 @@ public class RubberTreeFeature extends TreeFeature {
return spireBlockState; return spireBlockState;
} }
} }
} }

View file

@ -0,0 +1,51 @@
package techreborn.world;
import net.minecraft.block.BlockState;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.TestableWorld;
import net.minecraft.world.gen.treedecorator.TreeDecorator;
import net.minecraft.world.gen.treedecorator.TreeDecoratorType;
import java.util.List;
import java.util.Random;
import java.util.function.BiConsumer;
public class RubberTreeSpikeDecorator extends TreeDecorator {
private final int spireHeight;
private final BlockState spireBlockState;
public RubberTreeSpikeDecorator(int spireHeight, BlockState spireBlockState) {
this.spireHeight = spireHeight;
this.spireBlockState = spireBlockState;
}
@Override
protected TreeDecoratorType<?> getType() {
// TODO 1.18 really needs fabric api help here.
throw new UnsupportedOperationException();
}
@Override
public void generate(TestableWorld world, BiConsumer<BlockPos, BlockState> replacer, Random random, List<BlockPos> logPositions, List<BlockPos> leavesPositions) {
System.out.println("hi");
}
private void generateSpike(TestableWorld world, BlockPos pos, BiConsumer<BlockPos, BlockState> replacer) {
final int startScan = pos.getY();
BlockPos topPos = null;
//Limit the scan to 15 blocks
while (topPos == null && pos.getY() - startScan < 15) {
pos = pos.up();
if (world.testBlockState(pos, BlockState::isAir)) {
topPos = pos;
}
}
if (topPos == null) return;
for (int i = 0; i < spireHeight; i++) {
replacer.accept(pos.up(i), spireBlockState);
}
}
}

View file

@ -0,0 +1,24 @@
package techreborn.world;
import net.fabricmc.fabric.api.biome.v1.BiomeSelectionContext;
import net.fabricmc.fabric.api.biome.v1.BiomeSelectors;
import net.minecraft.block.Blocks;
import net.minecraft.structure.rule.BlockStateMatchRuleTest;
import net.minecraft.structure.rule.RuleTest;
import net.minecraft.world.gen.feature.OreConfiguredFeatures;
import java.util.function.Predicate;
public enum TargetDimension {
OVERWORLD(BiomeSelectors.foundInOverworld(), OreConfiguredFeatures.BASE_STONE_OVERWORLD),
NETHER(BiomeSelectors.foundInTheNether(), OreConfiguredFeatures.BASE_STONE_NETHER),
END(BiomeSelectors.foundInTheEnd(), new BlockStateMatchRuleTest(Blocks.END_STONE.getDefaultState()));
public final Predicate<BiomeSelectionContext> biomeSelector;
public final RuleTest ruleTest;
TargetDimension(Predicate<BiomeSelectionContext> biomeSelector, RuleTest ruleTest) {
this.biomeSelector = biomeSelector;
this.ruleTest = ruleTest;
}
}

View file

@ -1,86 +0,0 @@
/*
* This file is part of TechReborn, licensed under the MIT License (MIT).
*
* Copyright (c) 2020 TechReborn
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package techreborn.world;
import com.mojang.serialization.Codec;
import net.minecraft.util.StringIdentifiable;
import net.minecraft.world.gen.GenerationStep;
import org.jetbrains.annotations.Nullable;
import java.util.Arrays;
import java.util.Map;
import java.util.stream.Collectors;
public class WorldGenCodecs {
// just a wrapper around GenerationStep.Feature with a codec
public static enum GenerationStepFeature implements StringIdentifiable {
RAW_GENERATION("RAW_GENERATION", GenerationStep.Feature.RAW_GENERATION),
LAKES("LAKES", GenerationStep.Feature.LAKES),
LOCAL_MODIFICATIONS("LOCAL_MODIFICATIONS", GenerationStep.Feature.LOCAL_MODIFICATIONS),
UNDERGROUND_STRUCTURES("UNDERGROUND_STRUCTURES", GenerationStep.Feature.UNDERGROUND_STRUCTURES),
SURFACE_STRUCTURES("SURFACE_STRUCTURES", GenerationStep.Feature.SURFACE_STRUCTURES),
STRONGHOLDS("STRONGHOLDS", GenerationStep.Feature.STRONGHOLDS),
UNDERGROUND_ORES("UNDERGROUND_ORES", GenerationStep.Feature.UNDERGROUND_ORES),
UNDERGROUND_DECORATION("UNDERGROUND_DECORATION", GenerationStep.Feature.UNDERGROUND_DECORATION),
VEGETAL_DECORATION("VEGETAL_DECORATION", GenerationStep.Feature.VEGETAL_DECORATION),
TOP_LAYER_MODIFICATION("TOP_LAYER_MODIFICATION", GenerationStep.Feature.TOP_LAYER_MODIFICATION);
public static final Codec<GenerationStepFeature> CODEC = StringIdentifiable.createCodec(GenerationStepFeature::values, GenerationStepFeature::byName);
private static final Map<String, GenerationStepFeature> BY_NAME = Arrays.stream(values()).collect(Collectors.toMap(GenerationStepFeature::getName, (carver) -> carver));
private static final Map<GenerationStep.Feature, GenerationStepFeature> BY_FEATURE = Arrays.stream(values()).collect(Collectors.toMap(GenerationStepFeature::getFeature, (carver) -> carver));
private final String name;
private final GenerationStep.Feature feature;
GenerationStepFeature(String name, GenerationStep.Feature feature) {
this.name = name;
this.feature = feature;
}
public GenerationStep.Feature getFeature() {
return feature;
}
public String getName() {
return this.name;
}
@Nullable
public static WorldGenCodecs.GenerationStepFeature byName(String name) {
return BY_NAME.get(name);
}
@Nullable
public static WorldGenCodecs.GenerationStepFeature byFeature(GenerationStep.Feature feature) {
return BY_FEATURE.get(feature);
}
@Override
public String asString() {
return name;
}
}
}

View file

@ -24,48 +24,112 @@
package techreborn.world; package techreborn.world;
import net.fabricmc.fabric.api.biome.v1.BiomeModifications; import net.fabricmc.fabric.api.biome.v1.*;
import net.fabricmc.fabric.api.biome.v1.BiomeSelectors;
import net.fabricmc.fabric.api.biome.v1.ModificationPhase;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
import net.minecraft.util.math.intprovider.ConstantIntProvider;
import net.minecraft.util.registry.BuiltinRegistries; import net.minecraft.util.registry.BuiltinRegistries;
import net.minecraft.util.registry.Registry; import net.minecraft.util.registry.Registry;
import net.minecraft.world.gen.feature.Feature; import net.minecraft.util.registry.RegistryKey;
import net.minecraft.world.gen.feature.TreeFeatureConfig; import net.minecraft.world.biome.Biome;
import net.minecraft.world.gen.foliage.FoliagePlacerType; import net.minecraft.world.gen.GenerationStep;
import reborncore.mixin.common.AccessorFoliagePlacerType; import net.minecraft.world.gen.decorator.BiomePlacementModifier;
import net.minecraft.world.gen.decorator.RarityFilterPlacementModifier;
import net.minecraft.world.gen.decorator.SquarePlacementModifier;
import net.minecraft.world.gen.feature.*;
import net.minecraft.world.gen.feature.size.TwoLayersFeatureSize;
import net.minecraft.world.gen.foliage.BlobFoliagePlacer;
import net.minecraft.world.gen.stateprovider.BlockStateProvider;
import net.minecraft.world.gen.trunk.StraightTrunkPlacer;
import techreborn.init.TRContent;
import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.function.BiConsumer;
// TODO 1.18
public class WorldGenerator { public class WorldGenerator {
public static Feature<TreeFeatureConfig> RUBBER_TREE_FEATURE; public static ConfiguredFeature<TreeFeatureConfig, ?> RUBBER_TREE_FEATURE;
public static RubberTreeDecorator RUBBER_TREE_DECORATOR; public static PlacedFeature RUBBER_TREE_PLACED_FEATURE;
public static FoliagePlacerType<RubberTreeFeature.FoliagePlacer> RUBBER_TREE_FOLIAGE_PLACER_TYPE;
public static ConfiguredFeature<RandomPatchFeatureConfig, ?> RUBBER_TREE_PATCH_FEATURE;
public static PlacedFeature RUBBER_TREE_PATCH_PLACED_FEATURE;
public static final List<OreFeature> ORE_FEATURES = getOreFeatures();
public static void initWorldGen() { public static void initWorldGen() {
registerTreeDecorators(); registerTreeDecorators();
List<DataDrivenFeature> features = DefaultWorldGen.getDefaultFeatures(); BiomeModifications.create(new Identifier("techreborn", "features"))
//TODO modify list with a config .add(ModificationPhase.ADDITIONS, BiomeSelectors.all(), oreModifier())
.add(ModificationPhase.ADDITIONS, BiomeSelectors.categories(Biome.Category.FOREST, Biome.Category.TAIGA, Biome.Category.SWAMP), rubberTreeModifier());
}
for (DataDrivenFeature feature : features) { private static BiConsumer<BiomeSelectionContext, BiomeModificationContext> oreModifier() {
Registry.register(BuiltinRegistries.CONFIGURED_FEATURE, feature.getRegistryKey().getValue(), feature.getConfiguredFeature()); return (biomeSelectionContext, biomeModificationContext) -> {
} for (OreFeature feature : ORE_FEATURES) {
BiomeModifications.create(new Identifier("techreborn", "features")).add(ModificationPhase.ADDITIONS, BiomeSelectors.all(),
(biomeSelectionContext, biomeModificationContext) -> {
for (DataDrivenFeature feature : features) {
if (feature.getBiomeSelector().test(biomeSelectionContext)) { if (feature.getBiomeSelector().test(biomeSelectionContext)) {
// biomeModificationContext.getGenerationSettings().addFeature(feature.getGenerationStep(), feature.getRegistryKey()); biomeModificationContext.getGenerationSettings().addFeature(GenerationStep.Feature.UNDERGROUND_ORES, feature.getPlacedFeatureRegistryKey());
} }
} }
}); };
}
private static List<OreFeature> getOreFeatures() {
return Arrays.stream(TRContent.Ores.values())
.map(OreFeature::new)
.toList();
} }
private static void registerTreeDecorators() { private static void registerTreeDecorators() {
RUBBER_TREE_FEATURE = Registry.register(Registry.FEATURE, new Identifier("techreborn:rubber_tree"), new RubberTreeFeature(TreeFeatureConfig.CODEC)); Identifier treeId = new Identifier("techreborn", "rubber_tree");
// RUBBER_TREE_DECORATOR = Registry.register(Registry.DECORATOR, new Identifier("techreborn:rubber_tree"), new RubberTreeDecorator(ChanceDecoratorConfig.CODEC)); Identifier patchId = new Identifier("techreborn", "rubber_tree_patch");
RUBBER_TREE_FOLIAGE_PLACER_TYPE = AccessorFoliagePlacerType.register("techreborn:rubber_tree", RubberTreeFeature.FoliagePlacer.CODEC);
RUBBER_TREE_FEATURE = Registry.register(BuiltinRegistries.CONFIGURED_FEATURE, treeId,
Feature.TREE.configure(rubber().build())
);
RUBBER_TREE_PLACED_FEATURE = Registry.register(BuiltinRegistries.PLACED_FEATURE, treeId,
RUBBER_TREE_FEATURE.withWouldSurviveFilter(TRContent.RUBBER_SAPLING)
);
RUBBER_TREE_PATCH_FEATURE = Registry.register(BuiltinRegistries.CONFIGURED_FEATURE, patchId,
Feature.RANDOM_PATCH.configure(
ConfiguredFeatures.createRandomPatchFeatureConfig(10, RUBBER_TREE_PLACED_FEATURE)
)
);
RUBBER_TREE_PATCH_PLACED_FEATURE = Registry.register(BuiltinRegistries.PLACED_FEATURE, patchId,
RUBBER_TREE_PATCH_FEATURE.withPlacement(
RarityFilterPlacementModifier.of(5),
SquarePlacementModifier.of(),
PlacedFeatures.MOTION_BLOCKING_HEIGHTMAP,
BiomePlacementModifier.of()
)
);
}
private static BiConsumer<BiomeSelectionContext, BiomeModificationContext> rubberTreeModifier() {
final RegistryKey<PlacedFeature> registryKey = BuiltinRegistries.PLACED_FEATURE.getKey(RUBBER_TREE_PATCH_PLACED_FEATURE).orElseThrow();
return (biomeSelectionContext, biomeModificationContext) ->
biomeModificationContext.getGenerationSettings().addFeature(GenerationStep.Feature.VEGETAL_DECORATION, registryKey);
}
private static TreeFeatureConfig.Builder rubber() {
return new TreeFeatureConfig.Builder(
BlockStateProvider.of(TRContent.RUBBER_LOG.getDefaultState()), // TODO 1.18 spawn with rubber
new StraightTrunkPlacer(6, 3, 0),
BlockStateProvider.of(TRContent.RUBBER_LEAVES.getDefaultState()),
new BlobFoliagePlacer(
ConstantIntProvider.create(2),
ConstantIntProvider.create(0),
3
),
new TwoLayersFeatureSize(
1,
0,
1
));
// TODO 1.18
// .decorators(List.of(new RubberTreeSpikeDecorator(4, TRContent.RUBBER_LEAVES.getDefaultState())));
} }
} }