Jump to content
View in the app

A better way to browse. Learn more.

Forge Forums

A full-screen app on your home screen with push notifications, badges and more.

To install this app on iOS and iPadOS
  1. Tap the Share icon in Safari
  2. Scroll the menu and tap Add to Home Screen.
  3. Tap Add in the top-right corner.
To install this app on Android
  1. Tap the 3-dot menu (⋮) in the top-right corner of the browser.
  2. Tap Add to Home screen or Install app.
  3. Confirm by tapping Install.

Featured Replies

Posted

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.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

Important Information

By using this site, you agree to our Terms of Use.

Configure browser push notifications

Chrome (Android)
  1. Tap the lock icon next to the address bar.
  2. Tap Permissions → Notifications.
  3. Adjust your preference.
Chrome (Desktop)
  1. Click the padlock icon in the address bar.
  2. Select Site settings.
  3. Find Notifications and adjust your preference.