Blacklist
Reaviik opened this issue ยท 1 comments
Please make the blacklist bidirectional, currently it only works for the block to be swapped and not the one it will replace
If it's not too much trouble, a world blacklist would also be welcome <3
I got a little carried away, I hope you get mad about it, I really liked your mod.
I added a function for multiple swapping, but I really wanted to know how to make the player place the block and not the server because that caused me some problems ^^
Spoiler
` public class SwapperInteraction {@SubscribeEvent
public static void swapperMainHandInteraction(PlayerInteractEvent.RightClickBlock event) {
processSwapperInteraction(event, true);
}
@SubscribeEvent
public static void swapperOffhandInteraction(PlayerInteractEvent.RightClickBlock event) {
processSwapperInteraction(event, false);
}
private static void processSwapperInteraction(PlayerInteractEvent.RightClickBlock event, boolean isMainHand) {
if(event.isCanceled()){ return;}
Player player = event.getEntity();
if(!(player instanceof ServerPlayer serverPlayer)){ return;}
Direction facing = event.getFace();
BlockPos pos = event.getPos();
Level world = event.getLevel();
ItemStack swapperStack = isMainHand ? player.getMainHandItem() : player.getOffhandItem();
ItemStack blockStack = isMainHand ? player.getOffhandItem() : player.getMainHandItem();
if (!swapperStack.is(ItemsInit.COPPER_BLOCK_SWAPPER.get())
|| !blockStack.is(ItemsInit.COPPER_BLOCK_SWAPPER.get())
|| !swapperStack.is(ItemsInit.NETHERITE_BLOCK_SWAPPER.get())
|| !blockStack.is(ItemsInit.NETHERITE_BLOCK_SWAPPER.get())) {
return;
}
BlockState oldBlockState = world.getBlockState(pos);
BlockState newBlockState = Blocks.AIR.defaultBlockState();
SoundType oldSound = oldBlockState.getSoundType();
boolean facingBlock = (facing != null);
boolean playerCanEditBlock = player.mayUseItemAt(pos.offset(facing.getNormal()), facing, swapperStack);
boolean creative = player.isCreative() && ServerConfig.doesCreativeAffect();
boolean canMine = creative;
boolean notEntity = !oldBlockState.hasBlockEntity();
boolean extended = swapperStack.getOrCreateTag().getBoolean("Extended");
if (swapperStack.is(ItemsInit.COPPER_BLOCK_SWAPPER.get())) {
if (Items.STONE_AXE.isCorrectToolForDrops(oldBlockState) ||
Items.STONE_PICKAXE.isCorrectToolForDrops(oldBlockState) ||
Items.STONE_SHOVEL.isCorrectToolForDrops(oldBlockState) ||
Items.STONE_SWORD.isCorrectToolForDrops(oldBlockState) ||
Items.STONE_HOE.isCorrectToolForDrops(oldBlockState) ||
Items.SHEARS.isCorrectToolForDrops(oldBlockState)) {
canMine = true;
}
} else if (swapperStack.is(ItemsInit.NETHERITE_BLOCK_SWAPPER.get())) {
if (Items.DIAMOND_AXE.isCorrectToolForDrops(oldBlockState) ||
Items.DIAMOND_PICKAXE.isCorrectToolForDrops(oldBlockState) ||
Items.DIAMOND_SHOVEL.isCorrectToolForDrops(oldBlockState) ||
Items.DIAMOND_SWORD.isCorrectToolForDrops(oldBlockState) ||
Items.DIAMOND_HOE.isCorrectToolForDrops(oldBlockState) ||
Items.SHEARS.isCorrectToolForDrops(oldBlockState)) {
canMine = true;
}
} else return;
if (blockStack.getItem() instanceof BlockItem blockItem) {
if (ServerConfig.getSwapDisabled(blockItem.getBlock())) {
world.playSound(player, pos, oldSound.getBreakSound(), SoundSource.BLOCKS, oldSound.getVolume(), oldSound.getPitch());
event.setCanceled(true);
event.setCancellationResult(InteractionResult.SUCCESS);
return;
}
newBlockState = blockItem.getBlock().withPropertiesOf(oldBlockState);
} else if (swapperStack.getEnchantmentLevel(EnchantmentsInit.EXCAVATING.get()) > 0 || creative) {
if (ServerConfig.getExcavateDisabled(oldBlockState.getBlock()) && !creative) {
world.playSound(player, pos, oldSound.getBreakSound(), SoundSource.BLOCKS, oldSound.getVolume(), oldSound.getPitch());
event.setCanceled(true);
event.setCancellationResult(InteractionResult.SUCCESS);
return;
}
} else return;
if (ServerConfig.getSwapDisabled(oldBlockState.getBlock())) canMine = false;
if (player.hasEffect(MobEffect.byId(4)) && ServerConfig.doesFatigueAffect()) canMine = false;
if (!facingBlock || !playerCanEditBlock || !notEntity) return;
if (newBlockState.equals(oldBlockState) || (!canMine && !creative)) {
world.playSound(player, pos, oldSound.getBreakSound(), SoundSource.BLOCKS, oldSound.getVolume(), oldSound.getPitch());
event.setCanceled(true);
event.setCancellationResult(InteractionResult.SUCCESS);
return;
}
List<BlockPos> blocksToReplace = (extended && player.isShiftKeyDown()) ?
findConnectedBlocks(world, pos, oldBlockState, 64) :
Collections.singletonList(pos);
int maxToReplace = blocksToReplace.size();
if (!creative && blockStack.getItem() instanceof BlockItem) {
maxToReplace = Math.min(maxToReplace, blockStack.getCount());
}
if (maxToReplace <= 0) {
world.playSound(player, pos, oldSound.getBreakSound(), SoundSource.BLOCKS, oldSound.getVolume(), oldSound.getPitch());
event.setCanceled(true);
event.setCancellationResult(InteractionResult.SUCCESS);
return;
}
int finalMaxToReplace = maxToReplace;
world.playSound(player, pos, oldSound.getBreakSound(), SoundSource.BLOCKS, oldSound.getVolume(), oldSound.getPitch());
if (!world.isClientSide()) {
BlockState finalNewBlockState = newBlockState;
AtomicInteger replacedBlocks = new AtomicInteger(0);
blocksToReplace.subList(0, finalMaxToReplace).forEach(currentPos -> {
if (player.mayUseItemAt(currentPos.offset(facing.getNormal()), facing, swapperStack)) {
boolean destroyed = serverPlayer.gameMode.destroyBlock(currentPos);
BlockState currentState = world.getBlockState(currentPos);
if (!destroyed || !currentState.isAir()) {
return;
}
BlockState placementState = finalNewBlockState;
if (placementState.hasProperty(BlockStateProperties.PERSISTENT) &&
!currentState.hasProperty(BlockStateProperties.PERSISTENT)) {
placementState = placementState.setValue(BlockStateProperties.PERSISTENT, true);
}
world.setBlock(currentPos, placementState, 11);
world.gameEvent(GameEvent.BLOCK_CHANGE, currentPos, GameEvent.Context.of(player, placementState));
replacedBlocks.incrementAndGet();
}
});
int actuallyReplaced = replacedBlocks.get();
if (!player.isCreative() && blockStack.getItem() instanceof BlockItem) {
blockStack.shrink(actuallyReplaced);
}
swapperStack.hurtAndBreak(actuallyReplaced, player, pl ->
pl.broadcastBreakEvent(isMainHand ? EquipmentSlot.MAINHAND : EquipmentSlot.OFFHAND));
}
SoundType newSound = newBlockState.getSoundType();
world.playSound(player, pos, newSound.getPlaceSound(), SoundSource.BLOCKS, newSound.getVolume(), newSound.getPitch());
if (!isMainHand) {
player.swing(InteractionHand.OFF_HAND);
}
event.setCanceled(true);
event.setCancellationResult(InteractionResult.SUCCESS);
}
private static List<BlockPos> findConnectedBlocks(Level world, BlockPos startPos, BlockState targetState, int maxBlocks) {
List<BlockPos> connected = new ArrayList<>();
Queue<BlockPos> queue = new LinkedList<>();
Set<BlockPos> visited = new HashSet<>();
queue.add(startPos);
visited.add(startPos);
while (!queue.isEmpty() && connected.size() < maxBlocks) {
BlockPos current = queue.poll();
connected.add(current);
for (Direction dir : Direction.values()) {
BlockPos neighbor = current.relative(dir);
if (!visited.contains(neighbor)) {
BlockState neighborState = world.getBlockState(neighbor);
if (neighborState.equals(targetState)) {
visited.add(neighbor);
queue.add(neighbor);
if (connected.size() + queue.size() >= maxBlocks) {
break;
}
}
}
}
}
return connected.subList(0, Math.min(connected.size(), maxBlocks));
}
}`