package net.minecraft.world.level.block; import com.google.common.collect.Maps; import com.mojang.serialization.MapCodec; import com.mojang.serialization.codecs.RecordCodecBuilder; import java.util.Map; import java.util.function.Supplier; import net.minecraft.core.BlockPos; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.server.level.ServerLevel; import net.minecraft.tags.EnchantmentTags; import net.minecraft.world.entity.EntitySpawnReason; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.monster.Silverfish; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.enchantment.EnchantmentHelper; import net.minecraft.world.level.GameRules; import net.minecraft.world.level.block.state.BlockBehaviour; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.properties.Property; public class InfestedBlock extends Block { public static final MapCodec CODEC = RecordCodecBuilder.mapCodec( instance -> instance.group(BuiltInRegistries.BLOCK.byNameCodec().fieldOf("host").forGetter(InfestedBlock::getHostBlock), propertiesCodec()) .apply(instance, InfestedBlock::new) ); private final Block hostBlock; private static final Map BLOCK_BY_HOST_BLOCK = Maps.newIdentityHashMap(); private static final Map HOST_TO_INFESTED_STATES = Maps.newIdentityHashMap(); private static final Map INFESTED_TO_HOST_STATES = Maps.newIdentityHashMap(); @Override public MapCodec codec() { return CODEC; } public InfestedBlock(Block hostBlock, BlockBehaviour.Properties properties) { super(properties.destroyTime(hostBlock.defaultDestroyTime() / 2.0F).explosionResistance(0.75F)); this.hostBlock = hostBlock; BLOCK_BY_HOST_BLOCK.put(hostBlock, this); } public Block getHostBlock() { return this.hostBlock; } public static boolean isCompatibleHostBlock(BlockState state) { return BLOCK_BY_HOST_BLOCK.containsKey(state.getBlock()); } private void spawnInfestation(ServerLevel level, BlockPos pos) { Silverfish silverfish = EntityType.SILVERFISH.create(level, EntitySpawnReason.TRIGGERED); if (silverfish != null) { silverfish.moveTo(pos.getX() + 0.5, pos.getY(), pos.getZ() + 0.5, 0.0F, 0.0F); level.addFreshEntity(silverfish); silverfish.spawnAnim(); } } @Override protected void spawnAfterBreak(BlockState state, ServerLevel level, BlockPos pos, ItemStack stack, boolean dropExperience) { super.spawnAfterBreak(state, level, pos, stack, dropExperience); if (level.getGameRules().getBoolean(GameRules.RULE_DOBLOCKDROPS) && !EnchantmentHelper.hasTag(stack, EnchantmentTags.PREVENTS_INFESTED_SPAWNS)) { this.spawnInfestation(level, pos); } } public static BlockState infestedStateByHost(BlockState host) { return getNewStateWithProperties(HOST_TO_INFESTED_STATES, host, () -> ((Block)BLOCK_BY_HOST_BLOCK.get(host.getBlock())).defaultBlockState()); } public BlockState hostStateByInfested(BlockState infested) { return getNewStateWithProperties(INFESTED_TO_HOST_STATES, infested, () -> this.getHostBlock().defaultBlockState()); } private static BlockState getNewStateWithProperties(Map stateMap, BlockState state, Supplier supplier) { return (BlockState)stateMap.computeIfAbsent(state, blockState -> { BlockState blockState2 = (BlockState)supplier.get(); for (Property property : blockState.getProperties()) { blockState2 = blockState2.hasProperty(property) ? blockState2.setValue(property, blockState.getValue(property)) : blockState2; } return blockState2; }); } }