package com.teamwizardry.wizardry.api.util; import com.mojang.authlib.GameProfile; import com.teamwizardry.wizardry.Wizardry; import com.teamwizardry.wizardry.init.ModBlocks; import net.minecraft.block.Block; import net.minecraft.block.state.IBlockState; import net.minecraft.entity.Entity; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.init.Blocks; import net.minecraft.item.ItemStack; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumActionResult; import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumFacing.Axis; import net.minecraft.util.EnumHand; import net.minecraft.util.math.BlockPos; import net.minecraft.world.IBlockAccess; import net.minecraft.world.World; import net.minecraft.world.WorldServer; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.util.BlockSnapshot; import net.minecraftforge.common.util.FakePlayer; import net.minecraftforge.common.util.FakePlayerFactory; import net.minecraftforge.event.world.BlockEvent; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.nio.charset.StandardCharsets; import java.util.*; import java.util.function.Predicate; /** * Created by Demoniaque. */ public final class BlockUtils { private final static UUID ID = UUID.nameUUIDFromBytes(Wizardry.MODID.getBytes(StandardCharsets.UTF_8)); private final static GameProfile BREAKER = new GameProfile(ID, "Wizardry Block Breaker"); private final static GameProfile PLACER = new GameProfile(ID, "Wizardry Block Placer"); private BlockUtils() { } public static boolean isAnyAir(IBlockState state) { return state.getBlock() == Blocks.AIR || state.getBlock() == ModBlocks.FAKE_AIR; } public static boolean isAnyAir(World world, BlockPos pos) { IBlockState state = world.getBlockState(pos); return state.getBlock() == Blocks.AIR || state.getBlock() == ModBlocks.FAKE_AIR; } public static boolean isAnyAir(Block block) { return block == Blocks.AIR || block == ModBlocks.FAKE_AIR; } public static EntityPlayerMP makePlacer(@Nonnull World world, @Nonnull BlockPos pos, @Nullable Entity entity) { if (entity instanceof EntityPlayerMP) { return (EntityPlayerMP) entity; } EntityPlayerMP bro = FakePlayerFactory.get((WorldServer) world, PLACER); bro.moveToBlockPosAndAngles(pos, 0, -90); bro.setSneaking(true); return bro; } /** * Places the specified block into the world at the specified position if it is possible to do so without violating permission restrictions. * * @return <tt>true</tt> if the specified block was successfully placed into the world */ public static boolean placeBlock(@Nonnull World world, @Nonnull BlockPos pos, @Nonnull IBlockState state, @Nonnull EntityPlayerMP player) { if (!world.isBlockLoaded(pos)) return false; if (!hasEditPermission(pos, player)) return false; BlockEvent.PlaceEvent event = new BlockEvent.PlaceEvent(BlockSnapshot.getBlockSnapshot(world, pos), Blocks.AIR.getDefaultState(), player, player.getActiveHand()); MinecraftForge.EVENT_BUS.post(event); if (event.isCanceled()) return false; world.setBlockState(pos, state); world.notifyBlockUpdate(pos, state, state, 3); return true; } public static boolean placeBlock(@Nonnull World world, @Nonnull BlockPos pos, @Nonnull EnumFacing facing, @Nonnull ItemStack stack) { if (!world.isBlockLoaded(pos)) return false; FakePlayer player = FakePlayerFactory.get((WorldServer) world, PLACER); player.moveToBlockPosAndAngles(pos, 0, -90); player.setHeldItem(EnumHand.MAIN_HAND, stack); player.setSneaking(true); if (!hasEditPermission(pos, player)) return false; EnumActionResult result = player.interactionManager.processRightClickBlock( player, world, stack, EnumHand.MAIN_HAND, pos, facing, 0, 0, 0); return result != EnumActionResult.FAIL; } public static EntityPlayerMP makeBreaker(@Nonnull World world, @Nonnull BlockPos pos, @Nullable Entity entity) { if (entity instanceof EntityPlayerMP) { return (EntityPlayerMP) entity; } EntityPlayerMP bro = FakePlayerFactory.get((WorldServer) world, BREAKER); bro.moveToBlockPosAndAngles(pos, 0, -90); return bro; } /** * Tries breaking a block safely and fires an event for it. * * @return Whether the block was successfully broken */ public static boolean breakBlock(@Nonnull World world, @Nonnull BlockPos pos, @Nullable IBlockState oldState, @Nonnull EntityPlayerMP player) { if (!world.isBlockLoaded(pos)) return false; if (!(player instanceof FakePlayer) && !hasEditPermission(pos, player)) return false; if (oldState == null) oldState = world.getBlockState(pos); BlockEvent.BreakEvent event = new BlockEvent.BreakEvent(world, pos, oldState, player); MinecraftForge.EVENT_BUS.post(event); if (event.isCanceled()) return false; TileEntity tile = world.getTileEntity(pos); Block block = oldState.getBlock(); if (block.removedByPlayer(oldState, world, pos, player, true)) { block.onPlayerDestroy(world, pos, oldState); block.harvestBlock(world, player, pos, oldState, tile, player.getHeldItemMainhand()); world.notifyBlockUpdate(pos, oldState, Blocks.AIR.getDefaultState(), 3); } else return false; return true; } public static boolean hasEditPermission(@Nonnull BlockPos pos, @Nonnull EntityPlayerMP player) { World world = player.getEntityWorld(); if (!world.isBlockModifiable(player, pos)) return false; if (world.getBlockState(pos).getBlockHardness(world, pos) == -1.0F && !player.capabilities.isCreativeMode) return false; return player.isAllowEdit(); } public static Set<BlockPos> blocksInSquare(BlockPos center, Axis axis, int maxBlocks, int maxRange, Predicate<BlockPos> ignore) { Set<BlockPos> blocks = new HashSet<>(); if (ignore.test(center)) return blocks; blocks.add(center); if (blocks.size() >= maxBlocks) return blocks; Queue<BlockPos> blockQueue = new LinkedList<>(); blockQueue.add(center); while (!blockQueue.isEmpty()) { BlockPos pos = blockQueue.remove(); for (EnumFacing facing : EnumFacing.VALUES) { if (facing.getAxis() == axis) continue; BlockPos shift = pos.offset(facing); if (shift.getX() - center.getX() > maxRange || center.getX() - shift.getX() > maxRange) continue; if (shift.getY() - center.getY() > maxRange || center.getY() - shift.getY() > maxRange) continue; if (shift.getZ() - center.getZ() > maxRange || center.getZ() - shift.getZ() > maxRange) continue; if (blocks.contains(shift)) continue; if (ignore.test(shift)) continue; blocks.add(shift); blockQueue.add(shift); if (blocks.size() >= maxBlocks) break; } if (blocks.size() >= maxBlocks) break; } return blocks; } public static Set<BlockPos> blocksInSquare(BlockPos center, EnumFacing facing, int maxBlocks, int maxRange, Predicate<BlockPos> ignore) { return blocksInSquare(center, facing.getAxis(), maxBlocks, maxRange, ignore); } @SuppressWarnings("unchecked") public static <T extends TileEntity> T getTileEntity(IBlockAccess world, BlockPos pos, Class<T> clazz) { TileEntity te = world.getTileEntity(pos); if (!clazz.isInstance(te)) return null; return (T) te; } }