Posted August 21, 20214 yr Hi, i've been working recently on a structure called the tree monument. I finished my code but the structure doesn't spawn in to the overworld what did i do wrong ? Here is the code: MAIN.class import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.eventbus.api.IEventBus; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent; import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import com.armanse.barkutil.init.BlockInit; import com.armanse.barkutil.init.FeatureInit; import com.armanse.barkutil.init.ItemInit; import com.armanse.barkutil.world.gen.STConfiguredStructures; import com.mojang.serialization.Codec; import net.minecraft.util.ResourceLocation; import net.minecraft.util.registry.Registry; import net.minecraft.world.World; import net.minecraft.world.gen.ChunkGenerator; import net.minecraft.world.gen.FlatChunkGenerator; import net.minecraft.world.gen.feature.structure.Structure; import net.minecraft.world.gen.settings.DimensionStructuresSettings; import net.minecraft.world.gen.settings.StructureSeparationSettings; import net.minecraft.world.server.ServerWorld; import net.minecraftforge.event.world.BiomeLoadingEvent; import net.minecraftforge.event.world.WorldEvent; import net.minecraftforge.eventbus.api.EventPriority; import net.minecraftforge.fml.common.ObfuscationReflectionHelper; import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; @Mod("bark_mod") public class Bark_UtilityMain { public static final Logger LOGGER = LogManager.getLogger(); public static final String MOD_ID = "bark_mod"; public Bark_UtilityMain() { IEventBus bus = FMLJavaModLoadingContext.get().getModEventBus(); BlockInit.BLOCKS.register(bus); ItemInit.ITEMS.register(bus); FeatureInit.STRUCTURE.register(bus); bus.addListener(this::setup); IEventBus forgeBus = MinecraftForge.EVENT_BUS; forgeBus.addListener(EventPriority.NORMAL, this::addDimensionalSpacing); forgeBus.addListener(EventPriority.HIGH, this::biomeModification); MinecraftForge.EVENT_BUS.register(this); } public void setup(final FMLCommonSetupEvent event) { event.enqueueWork(() -> { FeatureInit.setupStructures(); STConfiguredStructures.registerConfiguredStructures(); }); } public void biomeModification(final BiomeLoadingEvent event) { event.getGeneration().getStructures().add(() -> STConfiguredStructures.CONFIGURED_TREEMONUMENT); } private static Method GETCODEC_METHOD; public void addDimensionalSpacing(final WorldEvent.Load event) { if(event.getWorld() instanceof ServerWorld){ ServerWorld serverWorld = (ServerWorld)event.getWorld(); try { if(GETCODEC_METHOD == null) GETCODEC_METHOD = ObfuscationReflectionHelper.findMethod(ChunkGenerator.class, "func_230347_a_"); ResourceLocation cgRL = Registry.CHUNK_GENERATOR.getKey((Codec<? extends ChunkGenerator>) GETCODEC_METHOD.invoke(serverWorld.getChunkSource().generator)); if(cgRL != null && cgRL.getNamespace().equals("terraforged")) return; } catch(Exception e){ Bark_UtilityMain.LOGGER.error("Was unable to check if " + serverWorld.dimension().location() + " is using Terraforged's ChunkGenerator."); } if(serverWorld.getChunkSource().getGenerator() instanceof FlatChunkGenerator && serverWorld.dimension().equals(World.OVERWORLD)){ return; } Map<Structure<?>, StructureSeparationSettings> tempMap = new HashMap<>(serverWorld.getChunkSource().generator.getSettings().structureConfig()); tempMap.putIfAbsent(FeatureInit.TREEMONUMENT.get(), DimensionStructuresSettings.DEFAULTS.get(FeatureInit.TREEMONUMENT.get())); serverWorld.getChunkSource().generator.getSettings().structureConfig = tempMap; } } } FeatureInit.class: import java.util.HashMap; import java.util.Map; import com.armanse.barkutil.Bark_UtilityMain; import com.armanse.barkutil.world.features.TreeMonument; import com.google.common.collect.ImmutableMap; import net.minecraft.util.registry.WorldGenRegistries; import net.minecraft.world.gen.feature.NoFeatureConfig; import net.minecraft.world.gen.feature.structure.Structure; import net.minecraft.world.gen.settings.DimensionStructuresSettings; import net.minecraft.world.gen.settings.StructureSeparationSettings; import net.minecraftforge.fml.RegistryObject; import net.minecraftforge.registries.DeferredRegister; import net.minecraftforge.registries.ForgeRegistries; public class FeatureInit { public static final DeferredRegister<Structure<?>> STRUCTURE = DeferredRegister.create(ForgeRegistries.STRUCTURE_FEATURES, Bark_UtilityMain.MOD_ID); public static final RegistryObject<Structure<NoFeatureConfig>> TREEMONUMENT = STRUCTURE.register("treemonument", () -> new TreeMonument(NoFeatureConfig.CODEC)); public static void setupStructures() { setupMapSpacingAndLand( TREEMONUMENT.get(), new StructureSeparationSettings(10, 5, 1234567890), true); } public static <F extends Structure<?>> void setupMapSpacingAndLand( F structure, StructureSeparationSettings structureSeparationSettings, boolean transformSurroundingLand) { Structure.STRUCTURES_REGISTRY.put(structure.getRegistryName().toString(), structure); DimensionStructuresSettings.DEFAULTS.putAll(DimensionStructuresSettings.DEFAULTS); DimensionStructuresSettings.DEFAULTS.put(structure, structureSeparationSettings); DimensionStructuresSettings.DEFAULTS.builder().build(); WorldGenRegistries.NOISE_GENERATOR_SETTINGS.entrySet().forEach(settings -> { Map<Structure<?>, StructureSeparationSettings> structureMap = settings.getValue().structureSettings().structureConfig(); if(structureMap instanceof ImmutableMap){ Map<Structure<?>, StructureSeparationSettings> tempMap = new HashMap<>(structureMap); tempMap.put(structure, structureSeparationSettings); settings.getValue().structureSettings().structureConfig = tempMap; } else{ structureMap.put(structure, structureSeparationSettings); } }); } } Tree Monument.class: import java.util.List; import com.armanse.barkutil.Bark_UtilityMain; import com.google.common.collect.ImmutableList; import com.mojang.serialization.Codec; import net.minecraft.block.BlockState; import net.minecraft.entity.EntityType; import net.minecraft.util.SharedSeedRandom; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.ChunkPos; import net.minecraft.util.registry.DynamicRegistries; import net.minecraft.world.IBlockReader; import net.minecraft.world.biome.Biome; import net.minecraft.world.biome.MobSpawnInfo; import net.minecraft.world.biome.MobSpawnInfo.Spawners; import net.minecraft.world.biome.provider.BiomeProvider; import net.minecraft.world.gen.ChunkGenerator; import net.minecraft.world.gen.GenerationStage; import net.minecraft.world.gen.GenerationStage.Decoration; import net.minecraft.world.gen.feature.NoFeatureConfig; import net.minecraft.world.gen.feature.structure.Structure; import net.minecraft.world.gen.feature.structure.StructureStart; import net.minecraft.world.gen.feature.template.TemplateManager; import net.minecraft.world.gen.Heightmap; import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.MutableBoundingBox; import net.minecraft.util.math.vector.Vector3i; import net.minecraft.util.registry.Registry; import net.minecraft.world.gen.feature.jigsaw.JigsawManager; import net.minecraft.world.gen.feature.structure.*; import org.apache.logging.log4j.Level; public class TreeMonument extends Structure<NoFeatureConfig> { public TreeMonument(Codec<NoFeatureConfig> config) { super(config); // TODO Auto-generated constructor stub } @Override public IStartFactory<NoFeatureConfig> getStartFactory() { // TODO Auto-generated method stub return TreeMonument.Start::new; } @Override public String getFeatureName() { // TODO Auto-generated method stub return Bark_UtilityMain.MOD_ID + ":TreeMonument"; } @Override public Decoration step() { // TODO Auto-generated method stub return GenerationStage.Decoration.SURFACE_STRUCTURES; } private static final List<MobSpawnInfo.Spawners> STRUCTURE_MONSTERS = ImmutableList.of( new MobSpawnInfo.Spawners(EntityType.SILVERFISH, 100, 1, 5), new MobSpawnInfo.Spawners(EntityType.ENDERMITE, 100, 1, 5)); @Override public List<MobSpawnInfo.Spawners> getDefaultSpawnList() { return STRUCTURE_MONSTERS; } @Override public List<Spawners> getDefaultCreatureSpawnList() { // TODO Auto-generated method stub return super.getDefaultCreatureSpawnList(); } @Override protected boolean isFeatureChunk(ChunkGenerator chunkGenerator, BiomeProvider biomeprovider, long p_230363_3_, SharedSeedRandom p_230363_5_, int chunkX, int chunkZ, Biome biome, ChunkPos pos, NoFeatureConfig p_230363_10_) { BlockPos centerOfChunk = new BlockPos((chunkX << 4)+7, 0, (chunkZ<<4)+7); int landHeight = chunkGenerator.getFirstOccupiedHeight(centerOfChunk.getX(), centerOfChunk.getZ(), Heightmap.Type.WORLD_SURFACE_WG); IBlockReader columnOfBlocks = chunkGenerator.getBaseColumn(centerOfChunk.getX(), centerOfChunk.getZ()); BlockState topBlock = columnOfBlocks.getBlockState(centerOfChunk.above(landHeight)); return topBlock.getFluidState().isEmpty(); } public static class Start extends StructureStart<NoFeatureConfig> { public Start(Structure<NoFeatureConfig> structureIn, int chunkX, int chunkZ, MutableBoundingBox mutableBoundingBox, int referenceIn, long seedIn) { super(structureIn, chunkX, chunkZ, mutableBoundingBox, referenceIn, seedIn); } @Override public void generatePieces(DynamicRegistries dynamicRegistryManager, ChunkGenerator chunkGenerator, TemplateManager templateManagerIn, int chunkX, int chunkZ, Biome biomeIn, NoFeatureConfig config) { int x = (chunkX << 4) +7; int z = (chunkZ << 4) +7; BlockPos centerPos = new BlockPos(x, 0, z); JigsawManager.addPieces( dynamicRegistryManager, new VillageConfig(() -> dynamicRegistryManager.registryOrThrow(Registry.TEMPLATE_POOL_REGISTRY) .get(new ResourceLocation(Bark_UtilityMain.MOD_ID, "treemonument/start_pool")),10), AbstractVillagePiece::new, chunkGenerator, templateManagerIn, centerPos, this.pieces, this.random, false, true); this.pieces.forEach(piece -> piece.move(0, 1, 0)); this.pieces.forEach(piece -> piece.getBoundingBox().y0 -= 1); Vector3i structureCenter = this.pieces.get(0).getBoundingBox().getCenter(); int xOffset = centerPos.getX() - structureCenter.getX(); int zOffset = centerPos.getZ() - structureCenter.getZ(); for(StructurePiece structurePiece : this.pieces){ structurePiece.move(xOffset, 0, zOffset); } this.calculateBoundingBox(); Bark_UtilityMain.LOGGER.log(Level.DEBUG, "Tree at " + this.pieces.get(0).getBoundingBox().x0 + " " + this.pieces.get(0).getBoundingBox().y0 + " " + this.pieces.get(0).getBoundingBox().z0); } } } STConfiguredStructures.class : import com.armanse.barkutil.Bark_UtilityMain; import com.armanse.barkutil.init.FeatureInit; import net.minecraft.util.ResourceLocation; import net.minecraft.util.registry.Registry; import net.minecraft.util.registry.WorldGenRegistries; import net.minecraft.world.gen.FlatGenerationSettings; import net.minecraft.world.gen.feature.IFeatureConfig; import net.minecraft.world.gen.feature.StructureFeature; public class STConfiguredStructures { public static StructureFeature<?, ?> CONFIGURED_TREEMONUMENT = FeatureInit.TREEMONUMENT.get().configured(IFeatureConfig.NONE); public static void registerConfiguredStructures() { Registry<StructureFeature<?, ?>> registry = WorldGenRegistries.CONFIGURED_STRUCTURE_FEATURE; Registry.register(registry, new ResourceLocation(Bark_UtilityMain.MOD_ID, "configured_treemonument"), CONFIGURED_TREEMONUMENT); FlatGenerationSettings.STRUCTURE_FEATURES.put(FeatureInit.TREEMONUMENT.get(), CONFIGURED_TREEMONUMENT); } } I followed that example code for those who are wondering : https://github.com/TelepathicGrunt/StructureTutorialMod . Thank you
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.