package eiteam.esteemedinnovation.materials.raw;
import net.minecraft.block.Block;
import net.minecraft.block.SoundType;
import net.minecraft.block.material.Material;
import net.minecraft.block.properties.PropertyBool;
import net.minecraft.block.properties.PropertyEnum;
import net.minecraft.block.state.BlockStateContainer;
import net.minecraft.block.state.IBlockState;
import net.minecraft.block.state.pattern.BlockMatcher;
import net.minecraft.init.Blocks;
import net.minecraft.item.Item;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.IStringSerializable;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import java.util.Random;
import static eiteam.esteemedinnovation.materials.MaterialsModule.ORE_BLOCK;
public class BlockOreDepositGenerator extends Block {
public static final PropertyEnum<Types> VARIANT = PropertyEnum.create("variant", Types.class);
public static final PropertyBool WORKED_OUT = PropertyBool.create("worked_out");
public BlockOreDepositGenerator() {
super(Material.ROCK);
// Same values as BlockGenericOre.
setResistance(5F);
setHardness(3F);
setSoundType(SoundType.STONE);
setHarvestLevel("pickaxe", 1);
}
@Override
public BlockStateContainer createBlockState() {
return new BlockStateContainer(this, VARIANT, WORKED_OUT);
}
@Override
public int getMetaFromState(IBlockState state) {
// The variant occupies the first bit, the worked out value occupies the second bit.
int variant = state.getValue(VARIANT).ordinal();
int workedOut = (state.getValue(WORKED_OUT) ? 1 : 0) << 1;
return variant + workedOut;
}
@Override
public IBlockState getStateFromMeta(int meta) {
Types variant = Types.LOOKUP[meta & 1];
boolean workedOut = ((meta >> 1) & 1) == 1;
return getDefaultState().withProperty(VARIANT, variant).withProperty(WORKED_OUT, workedOut);
}
@Override
public int damageDropped(IBlockState state) {
return state.getValue(VARIANT).ordinal();
}
@Override
public Item getItemDropped(IBlockState state, Random rand, int fortune) {
return Item.getItemFromBlock(ORE_BLOCK);
}
@Override
public int tickRate(World world) {
// 20 minutes, the time in a single MC day.
return 24_000;
}
@Override
public void updateTick(World world, BlockPos pos, IBlockState state, Random rand) {
world.scheduleBlockUpdate(pos, this, tickRate(world), 0);
generateAdjacentOres(world, pos, false);
}
@Override
public void onBlockAdded(World world, BlockPos pos, IBlockState state) {
world.scheduleBlockUpdate(pos, this, tickRate(world), 0);
generateAdjacentOres(world, pos, true);
}
/**
* Generates ores adjacent in all directions to this deposit generator.
* @param world The world
* @param center The center (deposit generator) position
* @param firstRun Whether this is the first time this is being generated. If this is not the first run, it will only
* generate if the adjacent block is air, and will return as soon as it generates a single ore.
* If it <b>is</b> the first run, then it will replace adjacent blocks if possible, and fill in all
* spaces adjacent to it.
*/
private void generateAdjacentOres(World world, BlockPos center, boolean firstRun) {
IBlockState oreState = getOreState(world, center);
boolean workedOut = world.getBlockState(center).getValue(WORKED_OUT);
for (EnumFacing dir : EnumFacing.VALUES) {
if (firstRun && workedOut && world.rand.nextBoolean()) {
continue;
}
BlockPos adjacent = center.offset(dir);
boolean place = firstRun ? canReplace(adjacent, world) : world.isAirBlock(adjacent);
if (place) {
world.setBlockState(adjacent, oreState);
if (!firstRun) {
return;
}
}
}
}
public static boolean canReplace(BlockPos replacePos, World world) {
IBlockState replaceState = world.getBlockState(replacePos);
return replaceState.getBlock().isReplaceableOreGen(replaceState, world, replacePos, BlockMatcher.forBlock(Blocks.STONE));
}
private IBlockState getOreState(World world, BlockPos center) {
return getOreState(world.getBlockState(center));
}
private IBlockState getOreState(IBlockState depositState) {
return ORE_BLOCK.getDefaultState().withProperty(BlockGenericOre.VARIANT,
depositState.getValue(VARIANT) == Types.COPPER ? BlockGenericOre.OreBlockTypes.OVERWORLD_COPPER : BlockGenericOre.OreBlockTypes.OVERWORLD_ZINC);
}
public enum Types implements IStringSerializable {
COPPER,
ZINC;
public static Types[] LOOKUP = new Types[values().length];
static {
for (Types type : values()) {
LOOKUP[type.ordinal()] = type;
}
}
@Override
public String getName() {
return toString().toLowerCase();
}
}
}