Compare commits

...

2 commits

Author SHA1 Message Date
bb48292c6f Fix destruction behind permeable blocks 2021-10-22 17:42:54 +02:00
c60260ea5c Fix #40 wand replacing half slabs
Fix destruction wand removing blocks not facing the player
2021-10-22 16:25:24 +02:00
4 changed files with 26 additions and 7 deletions

View file

@ -8,4 +8,4 @@ mcp_channel=official
mcp_mappings=1.17.1 mcp_mappings=1.17.1
botania=1.16.2-405 botania=1.16.2-405
version_major=2 version_major=2
version_minor=3 version_minor=4

View file

@ -11,9 +11,11 @@ import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.BlockItem; import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.Item; import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.Vec3;
import net.minecraft.world.phys.shapes.VoxelShape; import net.minecraft.world.phys.shapes.VoxelShape;
import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.MinecraftForge;
@ -22,6 +24,7 @@ import net.minecraftforge.event.world.BlockEvent;
import thetadev.constructionwand.ConstructionWand; import thetadev.constructionwand.ConstructionWand;
import thetadev.constructionwand.containers.ContainerManager; import thetadev.constructionwand.containers.ContainerManager;
import thetadev.constructionwand.items.wand.ItemWand; import thetadev.constructionwand.items.wand.ItemWand;
import thetadev.constructionwand.wand.WandItemUseContext;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.ArrayList; import java.util.ArrayList;
@ -187,13 +190,19 @@ public class WandUtil
/** /**
* Tests if a wand can place a block at a certain position. * Tests if a wand can place a block at a certain position.
* This check is independent from the used block. * This check is independent of the used block.
*/ */
public static boolean isPositionPlaceable(Level world, Player player, BlockPos pos, boolean replace) { public static boolean isPositionPlaceable(Level world, Player player, BlockPos pos, boolean replace) {
if(!isPositionModifiable(world, player, pos)) return false; if(!isPositionModifiable(world, player, pos)) return false;
// If replace mode is off, target has to be air // If replace mode is off, target has to be air
return replace || world.isEmptyBlock(pos); if(world.isEmptyBlock(pos)) return true;
// Otherwise, check if the block can be replaced by a generic block
return replace && world.getBlockState(pos).canBeReplaced(
new WandItemUseContext(world, player,
new BlockHitResult(new Vec3(0, 0, 0), Direction.DOWN, pos, false),
pos, (BlockItem) Items.STONE));
} }
public static boolean isBlockRemovable(Level world, Player player, BlockPos pos) { public static boolean isBlockRemovable(Level world, Player player, BlockPos pos) {
@ -205,6 +214,10 @@ public class WandUtil
return true; return true;
} }
public static boolean isBlockPermeable(Level world, BlockPos pos) {
return world.isEmptyBlock(pos) || world.getBlockState(pos).getCollisionShape(world, pos).isEmpty();
}
public static boolean entitiesCollidingWithBlock(Level world, BlockState blockState, BlockPos pos) { public static boolean entitiesCollidingWithBlock(Level world, BlockState blockState, BlockPos pos) {
VoxelShape shape = blockState.getCollisionShape(world, pos); VoxelShape shape = blockState.getCollisionShape(world, pos);
if(!shape.isEmpty()) { if(!shape.isEmpty()) {

View file

@ -10,6 +10,7 @@ import net.minecraft.world.phys.BlockHitResult;
import thetadev.constructionwand.api.IWandAction; import thetadev.constructionwand.api.IWandAction;
import thetadev.constructionwand.api.IWandSupplier; import thetadev.constructionwand.api.IWandSupplier;
import thetadev.constructionwand.basics.ConfigServer; import thetadev.constructionwand.basics.ConfigServer;
import thetadev.constructionwand.basics.WandUtil;
import thetadev.constructionwand.basics.option.WandOptions; import thetadev.constructionwand.basics.option.WandOptions;
import thetadev.constructionwand.wand.undo.DestroySnapshot; import thetadev.constructionwand.wand.undo.DestroySnapshot;
import thetadev.constructionwand.wand.undo.ISnapshot; import thetadev.constructionwand.wand.undo.ISnapshot;
@ -38,14 +39,14 @@ public class ActionDestruction implements IWandAction
HashSet<BlockPos> allCandidates = new HashSet<>(); HashSet<BlockPos> allCandidates = new HashSet<>();
// Block face the wand was pointed at // Block face the wand was pointed at
Direction breakDirection = rayTraceResult.getDirection(); Direction breakFace = rayTraceResult.getDirection();
// Block the wand was pointed at // Block the wand was pointed at
BlockPos startingPoint = rayTraceResult.getBlockPos(); BlockPos startingPoint = rayTraceResult.getBlockPos();
BlockState targetBlock = world.getBlockState(rayTraceResult.getBlockPos()); BlockState targetBlock = world.getBlockState(rayTraceResult.getBlockPos());
// Is break direction allowed by lock? // Is break direction allowed by lock?
// Tried to break blocks from top/bottom face, so the wand should allow breaking in NS/EW direction // Tried to break blocks from top/bottom face, so the wand should allow breaking in NS/EW direction
if(breakDirection == Direction.UP || breakDirection == Direction.DOWN) { if(breakFace == Direction.UP || breakFace == Direction.DOWN) {
if(options.testLock(WandOptions.LOCK.NORTHSOUTH) || options.testLock(WandOptions.LOCK.EASTWEST)) if(options.testLock(WandOptions.LOCK.NORTHSOUTH) || options.testLock(WandOptions.LOCK.EASTWEST))
candidates.add(startingPoint); candidates.add(startingPoint);
} }
@ -56,6 +57,10 @@ public class ActionDestruction implements IWandAction
// Process current candidates, stop when none are avaiable or block limit is reached // Process current candidates, stop when none are avaiable or block limit is reached
while(!candidates.isEmpty() && destroySnapshots.size() < limit) { while(!candidates.isEmpty() && destroySnapshots.size() < limit) {
BlockPos currentCandidate = candidates.removeFirst(); BlockPos currentCandidate = candidates.removeFirst();
// Only break blocks facing the player, with no collidable blocks in between
if(!WandUtil.isBlockPermeable(world, currentCandidate.offset(breakFace.getNormal()))) continue;
try { try {
BlockState candidateBlock = world.getBlockState(currentCandidate); BlockState candidateBlock = world.getBlockState(currentCandidate);
@ -66,7 +71,7 @@ public class ActionDestruction implements IWandAction
if(snapshot == null) continue; if(snapshot == null) continue;
destroySnapshots.add(snapshot); destroySnapshots.add(snapshot);
switch(breakDirection) { switch(breakFace) {
case DOWN: case DOWN:
case UP: case UP:
if(options.testLock(WandOptions.LOCK.NORTHSOUTH)) { if(options.testLock(WandOptions.LOCK.NORTHSOUTH)) {

View file

@ -6,6 +6,7 @@ import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.BlockItem; import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.Item; import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.BlockHitResult;
@ -51,7 +52,7 @@ public class SupplierInventory implements IWandSupplier
addBlockItem((BlockItem) offhandStack.getItem()); addBlockItem((BlockItem) offhandStack.getItem());
} }
// Otherwise use target block // Otherwise use target block
else { else if(target != null && target != Items.AIR) {
addBlockItem(target); addBlockItem(target);
// Add replacement items // Add replacement items