mirror of
https://github.com/Theta-Dev/ConstructionWand.git
synced 2025-08-05 02:15:27 +02:00
(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.
121 lines
No EOL
4.8 KiB
Java
121 lines
No EOL
4.8 KiB
Java
package thetadev.constructionwand.wand;
|
|
|
|
import net.minecraft.block.SoundType;
|
|
import net.minecraft.entity.player.PlayerEntity;
|
|
import net.minecraft.item.BlockItem;
|
|
import net.minecraft.item.Item;
|
|
import net.minecraft.item.ItemStack;
|
|
import net.minecraft.util.SoundCategory;
|
|
import net.minecraft.util.math.BlockPos;
|
|
import net.minecraft.util.math.BlockRayTraceResult;
|
|
import net.minecraft.util.math.RayTraceResult;
|
|
import net.minecraft.world.World;
|
|
import thetadev.constructionwand.ConstructionWand;
|
|
import thetadev.constructionwand.api.IWandAction;
|
|
import thetadev.constructionwand.api.IWandSupplier;
|
|
import thetadev.constructionwand.basics.ConfigServer;
|
|
import thetadev.constructionwand.basics.ModStats;
|
|
import thetadev.constructionwand.basics.WandUtil;
|
|
import thetadev.constructionwand.basics.option.WandOptions;
|
|
import thetadev.constructionwand.items.ModItems;
|
|
import thetadev.constructionwand.items.wand.ItemWand;
|
|
import thetadev.constructionwand.wand.supplier.SupplierInventory;
|
|
import thetadev.constructionwand.wand.supplier.SupplierRandom;
|
|
import thetadev.constructionwand.wand.undo.ISnapshot;
|
|
|
|
import javax.annotation.Nullable;
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
import java.util.Set;
|
|
import java.util.stream.Collectors;
|
|
|
|
public class WandJob
|
|
{
|
|
public final PlayerEntity player;
|
|
public final World world;
|
|
public final BlockRayTraceResult rayTraceResult;
|
|
public final WandOptions options;
|
|
public final ItemStack wand;
|
|
public final ItemWand wandItem;
|
|
|
|
private final IWandAction wandAction;
|
|
private final IWandSupplier wandSupplier;
|
|
|
|
private List<ISnapshot> placeSnapshots;
|
|
|
|
public WandJob(PlayerEntity player, World world, BlockRayTraceResult rayTraceResult, ItemStack wand) {
|
|
this.player = player;
|
|
this.world = world;
|
|
this.rayTraceResult = rayTraceResult;
|
|
this.placeSnapshots = new ArrayList<>();
|
|
|
|
// Get wand
|
|
this.wand = wand;
|
|
this.wandItem = (ItemWand) wand.getItem();
|
|
options = new WandOptions(wand);
|
|
|
|
// Select wand action and supplier based on options
|
|
wandSupplier = options.random.get() ?
|
|
new SupplierRandom(player, options) : new SupplierInventory(player, options);
|
|
wandAction = options.cores.get().getWandAction();
|
|
|
|
wandSupplier.getSupply(getTargetItem(world, rayTraceResult));
|
|
}
|
|
|
|
@Nullable
|
|
private static BlockItem getTargetItem(World world, BlockRayTraceResult rayTraceResult) {
|
|
// Get target item
|
|
Item tgitem = world.getBlockState(rayTraceResult.getPos()).getBlock().asItem();
|
|
if(!(tgitem instanceof BlockItem)) return null;
|
|
return (BlockItem) tgitem;
|
|
}
|
|
|
|
public void getSnapshots() {
|
|
int limit;
|
|
// Infinity wand gets enhanced limit in creative mode
|
|
if(player.isCreative() && wandItem == ModItems.WAND_INFINITY) limit = ConfigServer.LIMIT_CREATIVE.get();
|
|
else limit = Math.min(wandItem.remainingDurability(wand), wandAction.getLimit(wand));
|
|
|
|
if(rayTraceResult.getType() == RayTraceResult.Type.BLOCK)
|
|
placeSnapshots = wandAction.getSnapshots(world, player, rayTraceResult, wand, options, wandSupplier, limit);
|
|
else
|
|
placeSnapshots = wandAction.getSnapshotsFromAir(world, player, rayTraceResult, wand, options, wandSupplier, limit);
|
|
}
|
|
|
|
public Set<BlockPos> getBlockPositions() {
|
|
return placeSnapshots.stream().map(ISnapshot::getPos).collect(Collectors.toSet());
|
|
}
|
|
|
|
public boolean doIt() {
|
|
ArrayList<ISnapshot> executed = new ArrayList<>();
|
|
|
|
for(ISnapshot snapshot : placeSnapshots) {
|
|
if(wand.isEmpty() || wandItem.remainingDurability(wand) == 0) break;
|
|
|
|
if(snapshot.execute(world, player, rayTraceResult)) {
|
|
// If the item cant be taken, undo the placement
|
|
if(wandSupplier.takeItemStack(snapshot.getRequiredItems()) == 0) executed.add(snapshot);
|
|
else {
|
|
ConstructionWand.LOGGER.info("Item could not be taken. Remove block: " +
|
|
snapshot.getBlockState().getBlock().toString());
|
|
snapshot.forceRestore(world);
|
|
}
|
|
|
|
wand.damageItem(1, player, (e) -> e.sendBreakAnimation(player.swingingHand));
|
|
player.addStat(ModStats.USE_WAND);
|
|
}
|
|
}
|
|
placeSnapshots = executed;
|
|
|
|
// Play place sound
|
|
if(!placeSnapshots.isEmpty()) {
|
|
SoundType sound = placeSnapshots.get(0).getBlockState().getSoundType();
|
|
world.playSound(null, WandUtil.playerPos(player), sound.getPlaceSound(), SoundCategory.BLOCKS, sound.volume, sound.pitch);
|
|
|
|
// Add to job history for undo
|
|
ConstructionWand.instance.undoHistory.add(player, world, placeSnapshots);
|
|
}
|
|
|
|
return !placeSnapshots.isEmpty();
|
|
}
|
|
} |