Jump to content

[1.12] Biome Alteration Not Quite As Expected


IceMetalPunk

Recommended Posts

With RedPlusPlus released and done, I've started work on another mod. For it, I'll need to alter existing biomes, and I don't have much experience with modding Biomes, so I started the project by playing around with the relevant classes and just testing things.

For the first test, I wanted all Swamps to generate with a layer of blocks just above all the water that has sky access (before trees, etc. are generated). I randomly picked magma blocks, and came up with this code (the class is registered in the RegistryEvent.Register<Biome> event, and overrides the default vanilla minecraft:swampland registry entry):

 

public class BiomeMitaSwamp extends BiomeSwamp {

	public BiomeMitaSwamp(BiomeProperties properties) {
		super(properties);
		this.setRegistryName("minecraft", "swampland");
	}

	@Override
	public void genTerrainBlocks(World worldIn, Random rand, ChunkPrimer chunkPrimerIn, int j, int i, double noiseVal) {
		super.genTerrainBlocks(worldIn, rand, chunkPrimerIn, j, i, noiseVal);
		int x = j & 15;
		int z = i & 15;
		for (int y = 255; y >= 0; --y) {
			boolean isWater = (chunkPrimerIn.getBlockState(x, y, z).getMaterial() == Material.WATER);
			boolean isAir = (chunkPrimerIn.getBlockState(x, y, z).getMaterial() == Material.AIR);
			boolean isUpAir = (chunkPrimerIn.getBlockState(x, y + 1, z).getMaterial() == Material.AIR);
			if (!isAir) {
				if (isUpAir && isWater) {
					chunkPrimerIn.setBlockState(x, y + 1, z, Blocks.MAGMA.getDefaultState());
				}
				return;
			}
		}
	}

}

 

It almost works. The magma block layer does generate above water in swamps, but there are patches of water that don't have the layer above them. The patches have no blocks above them, are not rectangular, are not on chunk borders.... in short, I can't find any commonality among the patches, yet there are many of them amidst the magma blocks.

 

What would cause this code not to generate a magma block above water, in a swampland, with no other blocks above it? I can't see the flaw here.

Whatever Minecraft needs, it is most likely not yet another tool tier.

Link to comment
Share on other sites

Why do you get the block at the position twice, once to check if it's material is air and again to check is the material is water? If it is water, it CAN'T be air. 

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

Link to comment
Share on other sites

5 hours ago, Draco18s said:

Why do you get the block at the position twice, once to check if it's material is air and again to check is the material is water? If it is water, it CAN'T be air. 

Right, but those are for two different behaviors. If it's not air, no matter what it is, the generation should return immediately, as I'm only wanting to generate blocks above water on the surface, not underground. And then from there, it should only generate if the block is water.

So for instance, if it finds a grass block, that's not air, so I need to know that to stop looking further down, but it's also not water, which I need to know so it doesn't generate a block above the grass.

 

I just don't understand why it's not generating blocks above *all* the surface water like I'd expect.

The funny thing is I've been playing around with world generators using similar code (obviously with a bit added to iterate over an entire chunk), and it works perfectly fine; it's only when used in the Biome class that it doesn't fill every appropriate block. Are these methods not called for every block in the biome like I thought?

Whatever Minecraft needs, it is most likely not yet another tool tier.

Link to comment
Share on other sites

Then save the block (or the material) and reference it twice. 

Also, if you're looking top to bottom, the sheer fact that the generator is still running means the block above is air and you don't need that check. 

Edited by Draco18s

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

Link to comment
Share on other sites

22 minutes ago, Draco18s said:

Then save the block (or the material) and reference it twice. 

Also, if you're looking top to bottom, the sheer fact that the generator is still running means the block above is air and you don't need that check. 

This is true. Thanks.

So after making that optimization, the problem still persists: seemingly random patches of surface water in a swamp are not generating the blocks above them.

 

New code:

package com.icemetalpunk.mita.biome;

import java.util.Random;

import net.minecraft.block.material.Material;
import net.minecraft.init.Blocks;
import net.minecraft.world.World;
import net.minecraft.world.biome.BiomeSwamp;
import net.minecraft.world.chunk.ChunkPrimer;

public class BiomeMitaSwamp extends BiomeSwamp {

	public BiomeMitaSwamp(BiomeProperties properties) {
		super(properties);
		this.setRegistryName("minecraft", "swampland");
	}

	// FIXME: Leaves "random" patches of water in swamps uncovered; why?
	@Override
	public void genTerrainBlocks(World worldIn, Random rand, ChunkPrimer chunkPrimerIn, int j, int i, double noiseVal) {
		super.genTerrainBlocks(worldIn, rand, chunkPrimerIn, j, i, noiseVal);
		int x = j & 15;
		int z = i & 15;
		for (int y = 255; y >= 0; --y) {
			Material mat = chunkPrimerIn.getBlockState(x, y, z).getMaterial();
			boolean isWater = (mat == Material.WATER);
			boolean isAir = (mat == Material.AIR);
			if (!isAir) {
				if (isWater) {
					chunkPrimerIn.setBlockState(x, y + 1, z, Blocks.MAGMA.getDefaultState());
				}
				return;
			}
		}
	}

}

 

Whatever Minecraft needs, it is most likely not yet another tool tier.

Link to comment
Share on other sites

Just a guess, but those patches of water may be decorations.  (LAKE is what they are called in code, IIRC.). I wouldn't expect MC to generate lake decorations in a swamp, but I guess they normally just don't do anything.  There is a way to disable decorations in a biome, but I don't recall offhand what that is.

Link to comment
Share on other sites

On 7/11/2017 at 9:22 AM, Zaerudath said:

Just a guess, but those patches of water may be decorations.  (LAKE is what they are called in code, IIRC.). I wouldn't expect MC to generate lake decorations in a swamp, but I guess they normally just don't do anything.  There is a way to disable decorations in a biome, but I don't recall offhand what that is.

Ah, that might just be the case! Looking into it, the "generateFalls" field of the biome decorator is true by default and not overridden by swamps, so it does in fact create surface water patches during decoration; that would explain why the issue occurs if I do this from a Biome, but not from the main world generation.

 

I'll look into canceling the generation; I haven't used terrain generator events before, but I'm sure I can figure something out :) Thank you for pointing me in the right direction!

 

EDIT Well, that didn't work :( I created a terrain gen event handler to deny the generation of lakes in my biome. Here's the code, and yes, it's registered on the terrain gen bus:

 

package com.icemetalpunk.mita.events;

import com.icemetalpunk.mita.biome.BiomeMitaSwamp;

import net.minecraft.world.World;
import net.minecraft.world.biome.Biome;
import net.minecraftforge.event.terraingen.DecorateBiomeEvent;
import net.minecraftforge.event.terraingen.DecorateBiomeEvent.Decorate;
import net.minecraftforge.fml.common.eventhandler.Event.Result;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;

public class TerrainEventHandler {
	@SubscribeEvent
	public void onDecoration(DecorateBiomeEvent.Decorate ev) {
		World world = ev.getWorld();
		Decorate.EventType type = ev.getType();
		Biome biome = world.getBiome(ev.getPos());
		if (biome instanceof BiomeMitaSwamp && type == Decorate.EventType.LAKE_WATER) {
			ev.setResult(Result.DENY);
		}
	}
}

I know that it's definitely being run for my BiomeMitaSwamp because I originally tried to cancel it with ev.setCanceled(), and it crashed because it's not a cancelable event. But the description of the event says setting the result to DENY should prevent the decoration; yet it still has patches of water generating without blocks above them :(

Any other ideas?

Edited by IceMetalPunk

Whatever Minecraft needs, it is most likely not yet another tool tier.

Link to comment
Share on other sites

  • 3 months later...

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



×
×
  • Create New...

Important Information

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