128 lines
4.7 KiB
Java
128 lines
4.7 KiB
Java
package com.cursedcauldron.wildbackport.common.blocks;
|
|
|
|
import java.util.Random;
|
|
|
|
import com.cursedcauldron.wildbackport.common.registry.WBBlocks;
|
|
import net.minecraft.core.BlockPos;
|
|
import net.minecraft.server.level.ServerLevel;
|
|
import net.minecraft.sounds.SoundSource;
|
|
import net.minecraft.util.Mth;
|
|
import net.minecraft.world.item.ItemStack;
|
|
import net.minecraft.world.item.enchantment.EnchantmentHelper;
|
|
import net.minecraft.world.item.enchantment.Enchantments;
|
|
import net.minecraft.world.level.LevelAccessor;
|
|
import net.minecraft.world.level.block.Blocks;
|
|
import net.minecraft.world.level.block.OreBlock;
|
|
import net.minecraft.world.level.block.state.BlockState;
|
|
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
|
|
import net.minecraft.world.level.material.Fluids;
|
|
|
|
public class SculkBlock extends OreBlock implements SculkSpreadable {
|
|
public SculkBlock(Properties properties) {
|
|
super(properties);
|
|
}
|
|
|
|
@Override
|
|
public int spread(
|
|
SculkSpreadManager.Cursor cursor,
|
|
LevelAccessor level,
|
|
BlockPos pos,
|
|
Random random,
|
|
SculkSpreadManager manager,
|
|
boolean shouldConvert
|
|
) {
|
|
int charge = cursor.getCharge();
|
|
if (charge != 0 && random.nextInt(manager.getSpreadChance()) == 0) {
|
|
BlockPos blockPos = cursor.getPos();
|
|
boolean inRange = blockPos.closerThan(pos, manager.getMaxDistance());
|
|
if (!inRange && shouldNotDecay(level, blockPos)) {
|
|
int chance = manager.getExtraBlockChance();
|
|
if (random.nextInt(chance) < charge) {
|
|
BlockPos growthPos = blockPos.above();
|
|
BlockState state = this.getExtraBlockState(
|
|
level, growthPos, random, manager.isWorldGen()
|
|
);
|
|
level.setBlock(growthPos, state, 3);
|
|
level.playSound(
|
|
null,
|
|
blockPos,
|
|
state.getSoundType().getPlaceSound(),
|
|
SoundSource.BLOCKS,
|
|
1.0F,
|
|
1.0F
|
|
);
|
|
}
|
|
|
|
return Math.max(0, charge - chance);
|
|
} else {
|
|
return random.nextInt(manager.getDecayChance()) != 0
|
|
? charge
|
|
: charge - (inRange ? 1 : getDecay(manager, blockPos, pos, charge));
|
|
}
|
|
} else {
|
|
return charge;
|
|
}
|
|
}
|
|
|
|
private static int
|
|
getDecay(SculkSpreadManager manager, BlockPos source, BlockPos target, int charge) {
|
|
int maxDistance = manager.getMaxDistance();
|
|
float range
|
|
= Mth.square((float) Math.sqrt(source.distSqr(target)) - (float) maxDistance);
|
|
int distance = Mth.square(24 - maxDistance);
|
|
float spread = Math.min(1.0F, range / (float) distance);
|
|
return Math.max(1, (int) ((float) charge * spread * 0.5F));
|
|
}
|
|
|
|
private BlockState getExtraBlockState(
|
|
LevelAccessor level, BlockPos pos, Random random, boolean isWorldGen
|
|
) {
|
|
BlockState state = random.nextInt(11) == 0
|
|
? WBBlocks.SCULK_SHRIEKER.get().defaultBlockState().setValue(
|
|
SculkShriekerBlock.CAN_SUMMON, isWorldGen
|
|
)
|
|
: Blocks.SCULK_SENSOR.defaultBlockState();
|
|
return state.hasProperty(BlockStateProperties.WATERLOGGED)
|
|
&& !level.getFluidState(pos).isEmpty()
|
|
? state.setValue(BlockStateProperties.WATERLOGGED, true)
|
|
: state;
|
|
}
|
|
|
|
private static boolean shouldNotDecay(LevelAccessor level, BlockPos pos) {
|
|
BlockState state = level.getBlockState(pos.above());
|
|
if (state.isAir()
|
|
|| state.is(Blocks.WATER) && state.getFluidState().is(Fluids.WATER)) {
|
|
int chance = 0;
|
|
|
|
for (BlockPos position :
|
|
BlockPos.betweenClosed(pos.offset(-4, 0, -4), pos.offset(4, 2, 4))) {
|
|
BlockState growth = level.getBlockState(position);
|
|
if (growth.is(Blocks.SCULK_SENSOR)
|
|
|| growth.is(WBBlocks.SCULK_SHRIEKER.get())) {
|
|
++chance;
|
|
}
|
|
|
|
if (chance > 2) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void
|
|
spawnAfterBreak(BlockState state, ServerLevel level, BlockPos pos, ItemStack stack) {
|
|
if (EnchantmentHelper.getItemEnchantmentLevel(Enchantments.SILK_TOUCH, stack)
|
|
== 0)
|
|
this.popExperience(level, pos, 1);
|
|
}
|
|
|
|
@Override
|
|
public boolean shouldConvertToSpreadable() {
|
|
return true;
|
|
}
|
|
} |