ConstructionWand/src/main/java/thetadev/constructionwand/wand/undo/DestroySnapshot.java
Theta-Dev cdba987f8d Fixed crash when placing many connectable blocks
(iron bars, glass panes, redstone)

The reason for this crash is that I precomputed the blockstates to be placed (which would be free standing poles when no blocks are present around them).
Placing all blocks at once then causes lots of block updates which may crash the game (especially in MC1.15).
So the solution is to calculate the blockstate directly before the placement.
2021-03-14 22:49:09 +01:00

77 lines
2.1 KiB
Java

package thetadev.constructionwand.wand.undo;
import net.minecraft.block.BlockState;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.fluid.Fluids;
import net.minecraft.item.ItemStack;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.world.World;
import thetadev.constructionwand.basics.WandUtil;
import javax.annotation.Nullable;
public class DestroySnapshot implements ISnapshot
{
private final BlockState block;
private final BlockPos pos;
public DestroySnapshot(BlockState block, BlockPos pos) {
this.pos = pos;
this.block = block;
}
@Nullable
public static DestroySnapshot get(World world, PlayerEntity player, BlockPos pos) {
if(!WandUtil.isBlockRemovable(world, player, pos)) return null;
return new DestroySnapshot(world.getBlockState(pos), pos);
}
@Override
public BlockPos getPos() {
return pos;
}
@Override
public BlockState getBlockState() {
return block;
}
@Override
public ItemStack getRequiredItems() {
return ItemStack.EMPTY;
}
@Override
public boolean execute(World world, PlayerEntity player, BlockRayTraceResult rayTraceResult) {
return WandUtil.removeBlock(world, player, block, pos);
}
@Override
public boolean canRestore(World world, PlayerEntity player) {
// Is position out of world?
if(!world.isBlockPresent(pos)) return false;
// Is block modifiable?
if(!world.isBlockModifiable(player, pos)) return false;
// Ignore blocks and entities when in creative
if(player.isCreative()) return true;
// Is block empty or fluid?
if(!world.isAirBlock(pos) && !world.getBlockState(pos).isReplaceable(Fluids.EMPTY)) return false;
return !WandUtil.entitiesCollidingWithBlock(world, block, pos);
}
@Override
public boolean restore(World world, PlayerEntity player) {
return WandUtil.placeBlock(world, player, block, pos, null);
}
@Override
public void forceRestore(World world) {
world.setBlockState(pos, block);
}
}