Jump to content

[1.14.4] Surface ores. How to make ores that spawn on the surface?


Kenneth201998

Recommended Posts

I am making a block that looks like the ore rocks from runescape. Some of these blocks are found on runescape's surface and I was wondering if there is a way to make this block spawn on the surface or on the floors of caves. I also want the rock to be very rare, as when the block is mined it transforms into an "empty ore rock" just like in old school runescape. These rocks will eventually revert back to containing ore in them after a random amount of time has passed. So yeah how would I make these spawn?

 

EDIT: 

new problem: when the block is mined it completely disapears instead of converting into its empty state:

 

here is the code:

 

package com.kenneths_mod.objects.blocks.respawning_ores;

import java.util.Random;

import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.IGrowable;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.state.BooleanProperty;
import net.minecraft.state.IntegerProperty;
import net.minecraft.state.StateContainer.Builder;
import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IBlockReader;
import net.minecraft.world.World;

public class RespawningOreNode extends Block implements IGrowable {
	
	private static final IntegerProperty STAGE = BlockStateProperties.AGE_0_1;
	private static final BooleanProperty FILLED = BooleanProperty.create("filled");
	
	public RespawningOreNode(Properties properties) {
		super(properties);
		this.setDefaultState(this.stateContainer.getBaseState().with(STAGE, Integer.valueOf(0)).with(FILLED, Boolean.valueOf(true)));
	}
	
	@Override
	public boolean canGrow(IBlockReader worldIn, BlockPos pos, BlockState state, boolean isClient) {
		return true;
	}
	
	@Override
	public boolean canUseBonemeal(World worldIn, Random rand, BlockPos pos, BlockState state) {
		return true;
	}
	
	@Override
	public void onBlockHarvested(World worldIn, BlockPos pos, BlockState state, PlayerEntity player) {
		if(state.get(FILLED) == true) {
			worldIn.setBlockState(pos, this.stateContainer.getBaseState().with(STAGE, Integer.valueOf(0)).with(FILLED, Boolean.valueOf(false)));
		}
	}
	
	@Override
	public void grow(World worldIn, Random rand, BlockPos pos, BlockState state) {
		if (state.get(FILLED) == false) {
			if(state.get(STAGE) == 0) {
				worldIn.setBlockState(pos, state.cycle(STAGE), 4);
			} else {
				worldIn.setBlockState(pos, state.with(STAGE, Integer.valueOf(0)).with(FILLED, Boolean.valueOf(true)));
			}
		}
	}
	@Override
	protected void fillStateContainer(Builder<Block, BlockState> builder) {
		builder.add(STAGE, FILLED);
	}
}

 

Edited by Kenneth201998
Link to comment
Share on other sites

1 hour ago, Kenneth201998 said:

Integer.valueOf(0)).with(FILLED, Boolean.valueOf(false))

oh christ, why all this boxing?
Do you want an int or a bool?

Use the value you want, done.

 

with(FILLED, false).

with(STAGE, 0).

 

Also, nothing in your code ever sets FILLED to true.

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

17 minutes ago, Draco18s said:

oh christ, why all this boxing?
Do you want an int or a bool?

Use the value you want, done.

 

with(FILLED, false).

with(STAGE, 0).

 

Also, nothing in your code ever sets FILLED to true.

I updated the code:

package com.kenneths_mod.objects.blocks.respawning_ores;

import java.util.Random;

import com.kenneths_mod.KenmodMain;

import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.IGrowable;
import net.minecraft.state.BooleanProperty;
import net.minecraft.state.IntegerProperty;
import net.minecraft.state.StateContainer.Builder;
import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IBlockReader;
import net.minecraft.world.IWorld;
import net.minecraft.world.World;

public class RespawningOreNode extends Block implements IGrowable {
	
	private static final IntegerProperty STAGE = BlockStateProperties.AGE_0_1;
	private static final BooleanProperty FILLED = BooleanProperty.create("filled");
	
	public RespawningOreNode(Properties properties) {
		super(properties);
		this.setDefaultState(this.stateContainer.getBaseState().with(STAGE, Integer.valueOf(0)).with(FILLED, Boolean.valueOf(true)));
	}
	
	@Override
	public boolean canGrow(IBlockReader worldIn, BlockPos pos, BlockState state, boolean isClient) {
		return true;
	}
	
	@Override
	public boolean canUseBonemeal(World worldIn, Random rand, BlockPos pos, BlockState state) {
		return true;
	}
	
	@Override
	public void onPlayerDestroy(IWorld worldIn, BlockPos pos, BlockState state) {
		KenmodMain.debugString(state.getBlock().getRegistryName().toString());
		if(state.get(FILLED) == true) {
			KenmodMain.debugString("test0: " + worldIn.getBlockState(pos).getBlock().getRegistryName());
			worldIn.setBlockState(pos, this.stateContainer.getBaseState().with(STAGE, Integer.valueOf(0)).with(FILLED, Boolean.valueOf(false)), 1);
			KenmodMain.debugString("test1: " + worldIn.getBlockState(pos).getBlock().getRegistryName());
		}
	}
	
	@Override
	public void grow(World worldIn, Random rand, BlockPos pos, BlockState state) {
		if (state.get(FILLED) == false) {
			if(state.get(STAGE) == 0) {
				worldIn.setBlockState(pos, state.cycle(STAGE), 4);
			} else {
				worldIn.setBlockState(pos, state.with(STAGE, Integer.valueOf(0)).with(FILLED, Boolean.valueOf(true)));
			}
		}
	}
	@Override
	public boolean isSolid(BlockState state) {
		return false;
	}
	@Override
	protected void fillStateContainer(Builder<Block, BlockState> builder) {
		builder.add(STAGE, FILLED);
	}
}

The ore can be destroyed and set filled to false, but the ore will not respawn. Also I did the "boxing" thing because it appears that way in vanilla code.

Edited by Kenneth201998
Link to comment
Share on other sites

Ok so now the ore nodes respawn and I even figured out how to get them to spawn on the surface using these codes:
 

Respawnable ore node:

package com.kenneths_mod.objects.blocks.respawning_ores;

import java.util.Random;

import com.kenneths_mod.KenmodMain;

import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.state.BooleanProperty;
import net.minecraft.state.IntegerProperty;
import net.minecraft.state.StateContainer.Builder;
import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IWorld;
import net.minecraft.world.World;

public class RespawningOreNode extends Block {
	
	private static final IntegerProperty STAGE = BlockStateProperties.AGE_0_1;
	private static final BooleanProperty FILLED = BooleanProperty.create("filled");
	
	public RespawningOreNode(Properties properties) {
		super(properties);
		this.setDefaultState(this.stateContainer.getBaseState().with(STAGE, Integer.valueOf(0)).with(FILLED, Boolean.valueOf(true)));
	}
	
	@Override
	public void onPlayerDestroy(IWorld worldIn, BlockPos pos, BlockState state) {
		KenmodMain.debugString(state.getBlock().getRegistryName().toString());
		if(state.get(FILLED) == true) {
			worldIn.setBlockState(pos, this.stateContainer.getBaseState().with(STAGE, Integer.valueOf(0)).with(FILLED, Boolean.valueOf(false)), 1);
		}
	}
	@Override
	public boolean ticksRandomly(BlockState state) {
		return true;
	}
	@Override
	public void randomTick(BlockState state, World worldIn, BlockPos pos, Random random) {
		if (state.get(FILLED) == false) {
			if(state.get(STAGE) == 0) {
				worldIn.setBlockState(pos, state.cycle(STAGE), 4);
			} else {
				//Respawn Ore:
				worldIn.setBlockState(pos, state.with(STAGE, Integer.valueOf(0)).with(FILLED, Boolean.valueOf(true)));
			}
		}
	}
	@Override
	public boolean isSolid(BlockState state) {
		return false;
	}
	@Override
	protected void fillStateContainer(Builder<Block, BlockState> builder) {
		builder.add(STAGE, FILLED);
	}
}

Natural Generation: (I added it to VEGETAL_DECORATION because I want it to spawn on the surface of mountains similar to how dead bushes spawn on the surface of deserts:

	private void addFeatures () {
		Biomes.MOUNTAINS.addFeature(GenerationStage.Decoration.VEGETAL_DECORATION, Biome.createDecoratedFeature(KenmodFeatures.respawning_iron_feature, IFeatureConfig.NO_FEATURE_CONFIG, Placement.COUNT_EXTRA_HEIGHTMAP, new AtSurfaceWithExtraConfig(0, 0.2F, 1)));
	}

And here is the feature class:

package com.kenneths_mod.world_gen.respawning_ores;

import java.util.Random;
import java.util.function.Function;

import com.kenneths_mod.objects.BlockList;
import com.mojang.datafixers.Dynamic;

import net.minecraft.block.Blocks;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IWorld;
import net.minecraft.world.gen.ChunkGenerator;
import net.minecraft.world.gen.GenerationSettings;
import net.minecraft.world.gen.feature.Feature;
import net.minecraft.world.gen.feature.NoFeatureConfig;

public class RespawningIronFeature extends Feature<NoFeatureConfig> {

	public RespawningIronFeature(Function<Dynamic<?>, ? extends NoFeatureConfig> configFactoryIn) {
		super(configFactoryIn);
	}
	
	@Override
	public boolean place(IWorld worldIn, ChunkGenerator<? extends GenerationSettings> generator, Random rand, BlockPos pos, NoFeatureConfig config) {
		if(worldIn.isAirBlock(pos) && worldIn.getBlockState(pos.down()).getBlock() == Blocks.STONE) {
			worldIn.setBlockState(pos, BlockList.iron_ore_node.getDefaultState(), 2);
		}
		return true;
	}
}

I am still trying to get them to spawn on cave floors and that should look something like this:

 

Biomes.MOUNTAINS.addFeature(GenerationStage.Decoration.UNDERGROUND_DECORATION, Biome.createDecoratedFeature(KenmodFeatures.respawning_iron_feature, IFeatureConfig.NO_FEATURE_CONFIG, Placement.COUNT_EXTRA_HEIGHTMAP, //I dont know what to put here for cave features));

 

Still need help with the last bit of code above. Thanks.

Edited by Kenneth201998
Link to comment
Share on other sites

18 hours ago, Kenneth201998 said:

Also I did the "boxing" thing because it appears that way in vanilla code.

Vanilla code looks like that because the decompiler isn't smart enough to know the difference (5 and Integer.valueOf(5) compile to the same byte code).

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

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.