Jump to content

Recommended Posts

Posted (edited)

Hello I am currently trying to make a biome in which my custom trees generate, I have the log, the leave and the sapling fully set up and working, however, getting my tree to generate naturally causes big problems, even though I don't understand why as the code is pretty much straight taken from the vanilla treegen with only slight changes made, here is my code:

WorldGen

Spoiler

public class WorldGen implements IWorldGenerator{

	private final WorldGenerator gen_cherry_tree = new WorldGenTrees(false, 5, Registry.CHERRY_LOG.getDefaultState(), Registry.CHERRY_LEAVES.getDefaultState(), false);
	private final WorldGenerator gen_big_cherry_tree = new WorldGenBigCherryTree(false);

	private void runGenerator(WorldGenerator generator, World world, Random random, int chunkX, int chunkZ, double chancesToSpawn, int minHeight, int maxHeight, Class<?>... classe) {
		if (chancesToSpawn < 1) {
				if (random.nextDouble() < chancesToSpawn)
					chancesToSpawn = 1;
				else
					chancesToSpawn = 0;
		}
		ArrayList<Class<?>> classesList = new ArrayList<Class<?>>(Arrays.asList(classe));
		int heightDiff = maxHeight - minHeight + 1;
		for (int i = 0; i < chancesToSpawn; i++) {
			BlockPos pos = new BlockPos(chunkX * 16 + 1 + random.nextInt(15),
					minHeight + random.nextInt(heightDiff),
					chunkZ * 16 + 1 + random.nextInt(15));
			if (minHeight < 0)
				pos = world.getHeight(pos);
			Class<?> biome = world.provider.getBiomeForCoords(pos).getClass();
			if (classesList.contains(biome) || classe.length == 0)
				generator.generate(world, random, pos);
		}
	}
	
	@Override
	public void generate(Random random, int chunkX, int chunkZ, World world, IChunkGenerator chunkGenerator, IChunkProvider chunkProvider) {
		switch (world.provider.getDimension()) {
	    case 0:
	    	this.runGenerator(gen_cherry_tree, world, random, chunkX, chunkZ, 1, -1, 0, BiomeCherryTreeForest.class);
	    	this.runGenerator(gen_big_cherry_tree, world, random, chunkX, chunkZ, 9, -1, 0, BiomeCherryTreeForest.class);
	    	break;
	    case -1:
	        break;
	    case 1:
	        break;
	    }
	}

 

 

WorldGenBigCherryTree

Spoiler

public class WorldGenBigCherryTree extends WorldGenAbstractTree {

	private Random rand;
    private World world;
    private BlockPos basePos = BlockPos.ORIGIN;
    int heightLimit;
    int height;
    double heightAttenuation = 0.618D;
    double branchSlope = 0.381D;
    double scaleWidth = 1.0D;
    double leafDensity = 1.0D;
    int trunkSize = 1;
    int heightLimitLimit = 12;
    /** Sets the distance limit for how far away the generator will populate leaves from the base leaf node. */
    int leafDistanceLimit = 4;
    List<WorldGenBigCherryTree.FoliageCoordinates> foliageCoords;

    public WorldGenBigCherryTree(boolean notify)
    {
        super(notify);
    }

    /**
     * Generates a list of leaf nodes for the tree, to be populated by generateLeaves.
     */
    void generateLeafNodeList()
    {
        this.height = (int)((double)this.heightLimit * this.heightAttenuation);

        if (this.height >= this.heightLimit)
        {
            this.height = this.heightLimit - 1;
        }

        int i = (int)(1.382D + Math.pow(this.leafDensity * (double)this.heightLimit / 13.0D, 2.0D));

        if (i < 1)
        {
            i = 1;
        }

        int j = this.basePos.getY() + this.height;
        int k = this.heightLimit - this.leafDistanceLimit;
        this.foliageCoords = Lists.<WorldGenBigCherryTree.FoliageCoordinates>newArrayList();
        this.foliageCoords.add(new WorldGenBigCherryTree.FoliageCoordinates(this.basePos.up(k), j));

        for (; k >= 0; --k)
        {
            float f = this.layerSize(k);

            if (f >= 0.0F)
            {
                for (int l = 0; l < i; ++l)
                {
                    double d0 = this.scaleWidth * (double)f * ((double)this.rand.nextFloat() + 0.328D);
                    double d1 = (double)(this.rand.nextFloat() * 2.0F) * Math.PI;
                    double d2 = d0 * Math.sin(d1) + 0.5D;
                    double d3 = d0 * Math.cos(d1) + 0.5D;
                    BlockPos blockpos = this.basePos.add(d2, (double)(k - 1), d3);
                    BlockPos blockpos1 = blockpos.up(this.leafDistanceLimit);

                    if (this.checkBlockLine(blockpos, blockpos1) == -1)
                    {
                        int i1 = this.basePos.getX() - blockpos.getX();
                        int j1 = this.basePos.getZ() - blockpos.getZ();
                        double d4 = (double)blockpos.getY() - Math.sqrt((double)(i1 * i1 + j1 * j1)) * this.branchSlope;
                        int k1 = d4 > (double)j ? j : (int)d4;
                        BlockPos blockpos2 = new BlockPos(this.basePos.getX(), k1, this.basePos.getZ());

                        if (this.checkBlockLine(blockpos2, blockpos) == -1)
                        {
                            this.foliageCoords.add(new WorldGenBigCherryTree.FoliageCoordinates(blockpos, blockpos2.getY()));
                        }
                    }
                }
            }
        }
    }

    void crosSection(BlockPos pos, float p_181631_2_, IBlockState p_181631_3_)
    {
        int i = (int)((double)p_181631_2_ + 0.618D);

        for (int j = -i; j <= i; ++j)
        {
            for (int k = -i; k <= i; ++k)
            {
                if (Math.pow((double)Math.abs(j) + 0.5D, 2.0D) + Math.pow((double)Math.abs(k) + 0.5D, 2.0D) <= (double)(p_181631_2_ * p_181631_2_))
                {
                    BlockPos blockpos = pos.add(j, 0, k);
                    IBlockState state = this.world.getBlockState(blockpos);

                    if (state.getBlock().isAir(state, world, blockpos) || state.getBlock().isLeaves(state, world, blockpos))
                    {
                        this.setBlockAndNotifyAdequately(this.world, blockpos, p_181631_3_);
                    }
                }
            }
        }
    }

    /**
     * Gets the rough size of a layer of the tree.
     */
    float layerSize(int y)
    {
        if ((float)y < (float)this.heightLimit * 0.3F)
        {
            return -1.0F;
        }
        else
        {
            float f = (float)this.heightLimit / 2.0F;
            float f1 = f - (float)y;
            float f2 = MathHelper.sqrt(f * f - f1 * f1);

            if (f1 == 0.0F)
            {
                f2 = f;
            }
            else if (Math.abs(f1) >= f)
            {
                return 0.0F;
            }

            return f2 * 0.5F;
        }
    }

    float leafSize(int y)
    {
        if (y >= 0 && y < this.leafDistanceLimit)
        {
            return y != 0 && y != this.leafDistanceLimit - 1 ? 3.0F : 2.0F;
        }
        else
        {
            return -1.0F;
        }
    }

    /**
     * Generates the leaves surrounding an individual entry in the leafNodes list.
     */
    void generateLeafNode(BlockPos pos)
    {
        for (int i = 0; i < this.leafDistanceLimit; ++i)
        {
            this.crosSection(pos.up(i), this.leafSize(i), Blocks.LEAVES.getDefaultState().withProperty(BlockLeaves.CHECK_DECAY, Boolean.valueOf(false)));
        }
    }

    void limb(BlockPos p_175937_1_, BlockPos p_175937_2_, Block p_175937_3_)
    {
        BlockPos blockpos = p_175937_2_.add(-p_175937_1_.getX(), -p_175937_1_.getY(), -p_175937_1_.getZ());
        int i = this.getGreatestDistance(blockpos);
        float f = (float)blockpos.getX() / (float)i;
        float f1 = (float)blockpos.getY() / (float)i;
        float f2 = (float)blockpos.getZ() / (float)i;

        for (int j = 0; j <= i; ++j)
        {
            BlockPos blockpos1 = p_175937_1_.add((double)(0.5F + (float)j * f), (double)(0.5F + (float)j * f1), (double)(0.5F + (float)j * f2));
            BlockLog.EnumAxis blocklog$enumaxis = this.getLogAxis(p_175937_1_, blockpos1);
            this.setBlockAndNotifyAdequately(this.world, blockpos1, p_175937_3_.getDefaultState().withProperty(BlockLog.LOG_AXIS, blocklog$enumaxis));
        }
    }

    /**
     * Returns the absolute greatest distance in the BlockPos object.
     */
    private int getGreatestDistance(BlockPos posIn)
    {
        int i = MathHelper.abs(posIn.getX());
        int j = MathHelper.abs(posIn.getY());
        int k = MathHelper.abs(posIn.getZ());

        if (k > i && k > j)
        {
            return k;
        }
        else
        {
            return j > i ? j : i;
        }
    }

    private BlockLog.EnumAxis getLogAxis(BlockPos p_175938_1_, BlockPos p_175938_2_)
    {
        BlockLog.EnumAxis blocklog$enumaxis = BlockLog.EnumAxis.Y;
        int i = Math.abs(p_175938_2_.getX() - p_175938_1_.getX());
        int j = Math.abs(p_175938_2_.getZ() - p_175938_1_.getZ());
        int k = Math.max(i, j);

        if (k > 0)
        {
            if (i == k)
            {
                blocklog$enumaxis = BlockLog.EnumAxis.X;
            }
            else if (j == k)
            {
                blocklog$enumaxis = BlockLog.EnumAxis.Z;
            }
        }

        return blocklog$enumaxis;
    }

    /**
     * Generates the leaf portion of the tree as specified by the leafNodes list.
     */
    void generateLeaves()
    {
        for (WorldGenBigCherryTree.FoliageCoordinates WorldGenBigCherryTree$foliagecoordinates : this.foliageCoords)
        {
            this.generateLeafNode(WorldGenBigCherryTree$foliagecoordinates);
        }
    }

    /**
     * Indicates whether or not a leaf node requires additional wood to be added to preserve integrity.
     */
    boolean leafNodeNeedsBase(int p_76493_1_)
    {
        return (double)p_76493_1_ >= (double)this.heightLimit * 0.2D;
    }

    /**
     * Places the trunk for the big tree that is being generated. Able to generate double-sized trunks by changing a
     * field that is always 1 to 2.
     */
    void generateTrunk()
    {
        BlockPos blockpos = this.basePos;
        BlockPos blockpos1 = this.basePos.up(this.height);
        Block block = Registry.CHERRY_LOG;
        this.limb(blockpos, blockpos1, block);

        if (this.trunkSize == 2)
        {
            this.limb(blockpos.east(), blockpos1.east(), block);
            this.limb(blockpos.east().south(), blockpos1.east().south(), block);
            this.limb(blockpos.south(), blockpos1.south(), block);
        }
    }

    /**
     * Generates additional wood blocks to fill out the bases of different leaf nodes that would otherwise degrade.
     */
    void generateLeafNodeBases()
    {
        for (WorldGenBigCherryTree.FoliageCoordinates WorldGenBigCherryTree$foliagecoordinates : this.foliageCoords)
        {
            int i = WorldGenBigCherryTree$foliagecoordinates.getBranchBase();
            BlockPos blockpos = new BlockPos(this.basePos.getX(), i, this.basePos.getZ());

            if (!blockpos.equals(WorldGenBigCherryTree$foliagecoordinates) && this.leafNodeNeedsBase(i - this.basePos.getY()))
            {
                this.limb(blockpos, WorldGenBigCherryTree$foliagecoordinates, Registry.CHERRY_LOG);
            }
        }
    }

    /**
     * Checks a line of blocks in the world from the first coordinate to triplet to the second, returning the distance
     * (in blocks) before a non-air, non-leaf block is encountered and/or the end is encountered.
     */
    int checkBlockLine(BlockPos posOne, BlockPos posTwo)
    {
        BlockPos blockpos = posTwo.add(-posOne.getX(), -posOne.getY(), -posOne.getZ());
        int i = this.getGreatestDistance(blockpos);
        float f = (float)blockpos.getX() / (float)i;
        float f1 = (float)blockpos.getY() / (float)i;
        float f2 = (float)blockpos.getZ() / (float)i;

        if (i == 0)
        {
            return -1;
        }
        else
        {
            for (int j = 0; j <= i; ++j)
            {
                BlockPos blockpos1 = posOne.add((double)(0.5F + (float)j * f), (double)(0.5F + (float)j * f1), (double)(0.5F + (float)j * f2));

                if (!this.isReplaceable(world, blockpos1))
                {
                    return j;
                }
            }

            return -1;
        }
    }

    public void setDecorationDefaults()
    {
        this.leafDistanceLimit = 5;
    }

    public boolean generate(World worldIn, Random rand, BlockPos position)
    {
        this.world = worldIn;
        this.basePos = position;
        this.rand = new Random(rand.nextLong());

        if (this.heightLimit == 0)
        {
            this.heightLimit = 5 + this.rand.nextInt(this.heightLimitLimit);
        }

        if (!this.validTreeLocation())
        {
            return false;
        }
        else
        {
            this.generateLeafNodeList();
            this.generateLeaves();
            this.generateTrunk();
            this.generateLeafNodeBases();
            return true;
        }
    }

    /**
     * Returns a boolean indicating whether or not the current location for the tree, spanning basePos to to the height
     * limit, is valid.
     */
    private boolean validTreeLocation()
    {
        BlockPos down = this.basePos.down();
        net.minecraft.block.state.IBlockState state = this.world.getBlockState(down);
        boolean isSoil = state.getBlock().canSustainPlant(state, this.world, down, net.minecraft.util.EnumFacing.UP, ((BlockCherrySapling)Registry.CHERRY_SAPLING));

        if (!isSoil)
        {
            return false;
        }
        else
        {
            int i = this.checkBlockLine(this.basePos, this.basePos.up(this.heightLimit - 1));

            if (i == -1)
            {
                return true;
            }
            else if (i < 6)
            {
                return false;
            }
            else
            {
                this.heightLimit = i;
                return true;
            }
        }
    }

    static class FoliageCoordinates extends BlockPos
        {
            private final int branchBase;

            public FoliageCoordinates(BlockPos pos, int p_i45635_2_)
            {
                super(pos.getX(), pos.getY(), pos.getZ());
                this.branchBase = p_i45635_2_;
            }

            public int getBranchBase()
            {
                return this.branchBase;
            }
        }

 

 

The issues I am facing are the following:

  • long chunk load times when in my biome
  • cascading worldgen lag warning (pretty much constantly when in my biome)
  • these really weird generation issues (see attachments)

Small side note regarding the generation issues (the ones where trees try to generate ontop of water or other trees): These really shouldn't be happening since in the generate method of WorldGenBigCherryTree (the method that is called first) the method's execution should be terminated when the position is not a valid tree position (so neither grass nor dirt below the block) which clearly isn't happening.

 

Any help would be greatly appreciated, thanks a lot!

 

2017-07-08_13.32.11.png

2017-07-08_13.32.26.png

2017-07-08_13.32.58.png

Edited by xyz

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...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Announcements



  • Recently Browsing

    • No registered users viewing this page.
  • Posts

    • Honestly, the forums are a back burner thing. Not many people use it. Best option is discord. I know that I haven't looked at the forums for more then admin tasks in quite a while. You're also best off not following tutorials which give you code. Knowing programming and reading the MC/Forge code yourself would be the best way to go.
    • on my last computer, i had a similar problem with forge/ neoforge mods but instead them launcher screen was black
    • I am trying to make a mod, all it is, a config folder that tells another mod to not require a dependency, pretty simple right.. well, I dont want whoever downloads my mod to have to download 4 other mods and then decide if they want 2 more that they kinda really need.. i want to make my mod basically implement all of these mods, i really dont care how it does it, ive tried putting them in every file location you can think of, ive downloaded intellij, mcreator, and tried vmware but thats eh (had it from school). I downloaded them in hopes theyd create the correct file i needed but honestly im only more lost now. I have gotten my config file to work, if i put all these mods into my own mods folder and the config file into the config and it works (unvbelievably) but i want to share this to everyone else, lets just say this mod will legitimately get 7M downloads.  I tried putting them in a run folder then having it create all the contents in that for a game (mods,config..etc) then i drop the mods in and all the sudden i cant even open the game, like it literally works with my own world i play on, but i cant get it to work on any coding platform, they all have like built in java versions you cant switch, its a nightmare. I am on 1.20.1 I need Java 17 (i dont think the specific versions of 17 matter) I have even tried recreating the mods i want to implement and deleting import things like net.adamsandler.themodsname and replacing it with what mine is. that only creates other problems, where im at right now is i got the thing to start opening then it crashes, closest ive gotten it, then it just says this  exception in thread "main" cpw.mods.niofs.union.unionfilesystem$uncheckedioexception: java.util.zip.zipexception: zip end header not found caused by: java.util.zip.zipexception: zip end header not found basically saying theres something wrong with my java.exe file, so i tried downloading so many different versions of java and putting them all in so many different spots, nothing, someone online says its just a mod that isnt built right so i put the mod into an editor and bunch of errors came up, id post it but i deleted it on accident, i just need help integrating mods
    • Vanilla 1.16.5 Crash Report [#L2KYKaK] - mclo.gs  
    • Hello, probably the last update, if anyone has the same problem or this can be of any help, the answer was pretty simple, textures started rendering just using a Tesselator instead of a VertexConsumer given by a MultibufferSource and a RenderType, pretty simple
  • Topics

×
×
  • Create New...

Important Information

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