mirror of
https://github.com/Creators-of-Create/Create.git
synced 2024-12-15 02:43:44 +01:00
Schematic insta-placement now uses Schematicannon logic
This commit is contained in:
parent
e55ae22d7d
commit
96e865be02
5 changed files with 434 additions and 284 deletions
|
@ -0,0 +1,305 @@
|
|||
package com.simibubi.create.content.schematics;
|
||||
|
||||
import com.simibubi.create.AllBlocks;
|
||||
import com.simibubi.create.AllTags;
|
||||
import com.simibubi.create.content.contraptions.components.structureMovement.BlockMovementChecks;
|
||||
import com.simibubi.create.content.contraptions.relays.belt.BeltTileEntity;
|
||||
import com.simibubi.create.content.schematics.block.SchematicannonTileEntity;
|
||||
|
||||
import com.simibubi.create.content.schematics.item.SchematicItem;
|
||||
|
||||
import com.simibubi.create.foundation.utility.BlockHelper;
|
||||
|
||||
import com.simibubi.create.foundation.utility.IPartialSafeNBT;
|
||||
import com.simibubi.create.foundation.utility.NBTProcessors;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
import net.minecraft.nbt.ListNBT;
|
||||
import net.minecraft.nbt.NBTUtil;
|
||||
import net.minecraft.state.properties.BedPart;
|
||||
import net.minecraft.state.properties.BlockStateProperties;
|
||||
import net.minecraft.state.properties.DoubleBlockHalf;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.MutableBoundingBox;
|
||||
import net.minecraft.util.math.vector.Vector3i;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.gen.feature.template.PlacementSettings;
|
||||
import net.minecraft.world.gen.feature.template.Template;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class SchematicPrinter {
|
||||
public enum PrintStage {
|
||||
BLOCKS, DEFERRED_BLOCKS, ENTITIES
|
||||
}
|
||||
|
||||
private boolean schematicLoaded;
|
||||
private SchematicWorld blockReader;
|
||||
private BlockPos schematicAnchor;
|
||||
|
||||
private BlockPos currentPos;
|
||||
private int printingEntityIndex;
|
||||
private PrintStage printStage;
|
||||
private List<BlockPos> deferredBlocks;
|
||||
|
||||
public SchematicPrinter() {
|
||||
printingEntityIndex = -1;
|
||||
printStage = PrintStage.BLOCKS;
|
||||
deferredBlocks = new LinkedList<>();
|
||||
}
|
||||
|
||||
public void fromTag(CompoundNBT compound, boolean clientPacket) {
|
||||
if (compound.contains("CurrentPos"))
|
||||
currentPos = NBTUtil.readBlockPos(compound.getCompound("CurrentPos"));
|
||||
|
||||
printingEntityIndex = compound.getInt("EntityProgress");
|
||||
printStage = PrintStage.valueOf(compound.getString("PrintStage"));
|
||||
compound.getList("DeferredBlocks", 10).stream()
|
||||
.map(p -> NBTUtil.readBlockPos((CompoundNBT) p))
|
||||
.collect(Collectors.toCollection(() -> deferredBlocks));
|
||||
}
|
||||
|
||||
public void write(CompoundNBT compound) {
|
||||
if (currentPos != null)
|
||||
compound.put("CurrentPos", NBTUtil.writeBlockPos(currentPos));
|
||||
|
||||
compound.putInt("EntityProgress", printingEntityIndex);
|
||||
compound.putString("PrintStage", printStage.name());
|
||||
ListNBT tagDeferredBlocks = new ListNBT();
|
||||
for (BlockPos p : deferredBlocks)
|
||||
tagDeferredBlocks.add(NBTUtil.writeBlockPos(p));
|
||||
compound.put("DeferredBlocks", tagDeferredBlocks);
|
||||
}
|
||||
|
||||
public void loadSchematic(ItemStack blueprint, World originalWorld, boolean processNBT) {
|
||||
if (!blueprint.hasTag() || !blueprint.getTag().getBoolean("Deployed"))
|
||||
return;
|
||||
|
||||
Template activeTemplate = SchematicItem.loadSchematic(blueprint);
|
||||
PlacementSettings settings = SchematicItem.getSettings(blueprint, processNBT);
|
||||
|
||||
schematicAnchor = NBTUtil.readBlockPos(blueprint.getTag().getCompound("Anchor"));
|
||||
blockReader = new SchematicWorld(schematicAnchor, originalWorld);
|
||||
activeTemplate.place(blockReader, schematicAnchor, settings, blockReader.getRandom());
|
||||
|
||||
printingEntityIndex = -1;
|
||||
printStage = PrintStage.BLOCKS;
|
||||
deferredBlocks.clear();
|
||||
MutableBoundingBox bounds = blockReader.getBounds();
|
||||
currentPos = new BlockPos(bounds.minX - 1, bounds.minY, bounds.minZ);
|
||||
schematicLoaded = true;
|
||||
}
|
||||
|
||||
public void resetSchematic() {
|
||||
schematicLoaded = false;
|
||||
schematicAnchor = null;
|
||||
currentPos = null;
|
||||
blockReader = null;
|
||||
printingEntityIndex = -1;
|
||||
printStage = PrintStage.BLOCKS;
|
||||
deferredBlocks.clear();
|
||||
}
|
||||
|
||||
public boolean isLoaded() {
|
||||
return schematicLoaded;
|
||||
}
|
||||
|
||||
public BlockPos getCurrentTarget() {
|
||||
if (!isLoaded())
|
||||
return null;
|
||||
return schematicAnchor.add(currentPos);
|
||||
}
|
||||
|
||||
public PrintStage getPrintStage() {
|
||||
return printStage;
|
||||
}
|
||||
|
||||
public BlockPos getAnchor() {
|
||||
return schematicAnchor;
|
||||
}
|
||||
|
||||
public boolean isWorldEmpty() {
|
||||
return blockReader.getBounds().getLength().equals(new Vector3i(0,0,0));
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface BlockTargetHandler {
|
||||
void handle(BlockPos target, BlockState blockState, TileEntity tileEntity);
|
||||
}
|
||||
@FunctionalInterface
|
||||
public interface EntityTargetHandler {
|
||||
void handle(BlockPos target, Entity entity);
|
||||
}
|
||||
|
||||
public void handleCurrentTarget(BlockTargetHandler blockHandler, EntityTargetHandler entityHandler) {
|
||||
BlockPos target = getCurrentTarget();
|
||||
|
||||
if (printStage == PrintStage.ENTITIES) {
|
||||
Entity entity = blockReader.getEntities()
|
||||
.collect(Collectors.toList())
|
||||
.get(printingEntityIndex);
|
||||
entityHandler.handle(target, entity);
|
||||
} else {
|
||||
BlockState blockState = BlockHelper.setZeroAge(blockReader.getBlockState(target));
|
||||
TileEntity tileEntity = blockReader.getTileEntity(target);
|
||||
blockHandler.handle(target, blockState, tileEntity);
|
||||
}
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface PlacementPredicate {
|
||||
boolean shouldPlace(BlockPos target, BlockState blockState, TileEntity tileEntity,
|
||||
BlockState toReplace, BlockState toReplaceOther, boolean isNormalCube);
|
||||
}
|
||||
|
||||
public boolean shouldPlaceCurrent(World world) { return shouldPlaceCurrent(world, (a,b,c,d,e,f) -> true); }
|
||||
|
||||
public boolean shouldPlaceCurrent(World world, PlacementPredicate predicate) {
|
||||
if (world == null)
|
||||
return false;
|
||||
|
||||
if (printStage == PrintStage.ENTITIES)
|
||||
return true;
|
||||
|
||||
return shouldPlaceBlock(world, predicate, getCurrentTarget());
|
||||
}
|
||||
|
||||
public boolean shouldPlaceBlock(World world, PlacementPredicate predicate, BlockPos pos) {
|
||||
BlockState state = BlockHelper.setZeroAge(blockReader.getBlockState(pos));
|
||||
TileEntity tileEntity = blockReader.getTileEntity(pos);
|
||||
|
||||
BlockState toReplace = world.getBlockState(pos);
|
||||
BlockState toReplaceOther = null;
|
||||
if (state.contains(BlockStateProperties.BED_PART) && state.contains(BlockStateProperties.HORIZONTAL_FACING)
|
||||
&& state.get(BlockStateProperties.BED_PART) == BedPart.FOOT)
|
||||
toReplaceOther = world.getBlockState(pos.offset(state.get(BlockStateProperties.HORIZONTAL_FACING)));
|
||||
if (state.contains(BlockStateProperties.DOUBLE_BLOCK_HALF)
|
||||
&& state.get(BlockStateProperties.DOUBLE_BLOCK_HALF) == DoubleBlockHalf.LOWER)
|
||||
toReplaceOther = world.getBlockState(pos.up());
|
||||
|
||||
if (!world.isBlockPresent(pos))
|
||||
return false;
|
||||
if (!world.getWorldBorder().contains(pos))
|
||||
return false;
|
||||
if (toReplace == state)
|
||||
return false;
|
||||
if (toReplace.getBlockHardness(world, pos) == -1
|
||||
|| (toReplaceOther != null && toReplaceOther.getBlockHardness(world, pos) == -1))
|
||||
return false;
|
||||
|
||||
boolean isNormalCube = state.isNormalCube(blockReader, currentPos);
|
||||
return predicate.shouldPlace(pos, state, tileEntity, toReplace, toReplaceOther, isNormalCube);
|
||||
}
|
||||
|
||||
public ItemRequirement getCurrentRequirement() {
|
||||
if (printStage == PrintStage.ENTITIES)
|
||||
return ItemRequirement.of(blockReader.getEntities()
|
||||
.collect(Collectors.toList())
|
||||
.get(printingEntityIndex));
|
||||
|
||||
BlockPos target = getCurrentTarget();
|
||||
BlockState blockState = BlockHelper.setZeroAge(blockReader.getBlockState(target));
|
||||
TileEntity tileEntity = blockReader.getTileEntity(target);
|
||||
return ItemRequirement.of(blockState, tileEntity);
|
||||
}
|
||||
|
||||
public int markAllBlockRequirements(MaterialChecklist checklist, World world, PlacementPredicate predicate) {
|
||||
int blocksToPlace = 0;
|
||||
for (BlockPos pos : blockReader.getAllPositions()) {
|
||||
BlockPos relPos = pos.add(schematicAnchor);
|
||||
BlockState required = blockReader.getBlockState(relPos);
|
||||
TileEntity requiredTE = blockReader.getTileEntity(relPos);
|
||||
|
||||
if (!world.isAreaLoaded(pos.add(schematicAnchor), 0)) {
|
||||
checklist.warnBlockNotLoaded();
|
||||
continue;
|
||||
}
|
||||
if (!shouldPlaceBlock(world, predicate, relPos))
|
||||
continue;
|
||||
ItemRequirement requirement = ItemRequirement.of(required, requiredTE);
|
||||
if (requirement.isEmpty())
|
||||
continue;
|
||||
if (requirement.isInvalid())
|
||||
continue;
|
||||
checklist.require(requirement);
|
||||
blocksToPlace++;
|
||||
}
|
||||
return blocksToPlace;
|
||||
}
|
||||
|
||||
public void markAllEntityRequirements(MaterialChecklist checklist) {
|
||||
blockReader.getEntities()
|
||||
.forEach(entity -> {
|
||||
ItemRequirement requirement = ItemRequirement.of(entity);
|
||||
if (requirement.isEmpty())
|
||||
return;
|
||||
if (requirement.isInvalid())
|
||||
return;
|
||||
checklist.require(requirement);
|
||||
});
|
||||
}
|
||||
|
||||
public boolean advanceCurrentPos() {
|
||||
List<Entity> entities = blockReader.getEntities().collect(Collectors.toList());
|
||||
|
||||
do {
|
||||
if (printStage == PrintStage.BLOCKS) {
|
||||
while (tryAdvanceCurrentPos()) {
|
||||
deferredBlocks.add(currentPos);
|
||||
}
|
||||
}
|
||||
|
||||
if (printStage == PrintStage.DEFERRED_BLOCKS) {
|
||||
if (deferredBlocks.isEmpty()) {
|
||||
printStage = PrintStage.ENTITIES;
|
||||
} else {
|
||||
currentPos = deferredBlocks.remove(0);
|
||||
}
|
||||
}
|
||||
|
||||
if (printStage == PrintStage.ENTITIES) {
|
||||
if (printingEntityIndex + 1 < entities.size()) {
|
||||
printingEntityIndex++;
|
||||
currentPos = entities.get(printingEntityIndex).getBlockPos().subtract(schematicAnchor);
|
||||
} else {
|
||||
// Reached end of printing
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} while (!blockReader.getBounds().isVecInside(currentPos));
|
||||
|
||||
// More things available to print
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean tryAdvanceCurrentPos() {
|
||||
currentPos = currentPos.offset(Direction.EAST);
|
||||
MutableBoundingBox bounds = blockReader.getBounds();
|
||||
BlockPos posInBounds = currentPos.add(-bounds.minX, -bounds.minY, -bounds.minZ);
|
||||
|
||||
if (posInBounds.getX() > bounds.getXSize())
|
||||
currentPos = new BlockPos(bounds.minX, currentPos.getY(), currentPos.getZ() + 1).west();
|
||||
if (posInBounds.getZ() > bounds.getZSize())
|
||||
currentPos = new BlockPos(currentPos.getX(), currentPos.getY() + 1, bounds.minZ).west();
|
||||
|
||||
// End of blocks reached
|
||||
if (currentPos.getY() > bounds.getYSize()) {
|
||||
printStage = PrintStage.DEFERRED_BLOCKS;
|
||||
return false;
|
||||
}
|
||||
|
||||
return shouldDeferBlock(blockReader.getBlockState(getCurrentTarget()));
|
||||
}
|
||||
|
||||
public static boolean shouldDeferBlock(BlockState state) {
|
||||
return state.getBlock().is(AllBlocks.GANTRY_CARRIAGE.get()) || BlockMovementChecks.isBrittle(state);
|
||||
}
|
||||
}
|
|
@ -84,13 +84,14 @@ public class SchematicannonRenderer extends SafeTileEntityRenderer<Schematicanno
|
|||
double yaw = 0;
|
||||
double pitch = 40;
|
||||
|
||||
if (tile.target != null) {
|
||||
BlockPos target = tile.printer.getCurrentTarget();
|
||||
if (target != null) {
|
||||
|
||||
// Calculate Angle of Cannon
|
||||
Vector3d diff = Vector3d.of(tile.target.subtract(pos));
|
||||
Vector3d diff = Vector3d.of(target.subtract(pos));
|
||||
if (tile.previousTarget != null) {
|
||||
diff = (Vector3d.of(tile.previousTarget)
|
||||
.add(Vector3d.of(tile.target.subtract(tile.previousTarget)).scale(partialTicks)))
|
||||
.add(Vector3d.of(target.subtract(tile.previousTarget)).scale(partialTicks)))
|
||||
.subtract(Vector3d.of(pos));
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ import com.simibubi.create.content.contraptions.relays.elementary.AbstractShaftB
|
|||
import com.simibubi.create.content.schematics.ItemRequirement;
|
||||
import com.simibubi.create.content.schematics.ItemRequirement.ItemUseType;
|
||||
import com.simibubi.create.content.schematics.MaterialChecklist;
|
||||
import com.simibubi.create.content.schematics.SchematicPrinter;
|
||||
import com.simibubi.create.content.schematics.SchematicWorld;
|
||||
import com.simibubi.create.content.schematics.item.SchematicItem;
|
||||
import com.simibubi.create.foundation.config.AllConfigs;
|
||||
|
@ -81,10 +82,6 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
|
|||
STOPPED, PAUSED, RUNNING;
|
||||
}
|
||||
|
||||
public enum PrintStage {
|
||||
BLOCKS, DEFERRED_BLOCKS, ENTITIES
|
||||
}
|
||||
|
||||
// Inventory
|
||||
public SchematicannonInventory inventory;
|
||||
|
||||
|
@ -94,25 +91,18 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
|
|||
public int neighbourCheckCooldown;
|
||||
|
||||
// Printer
|
||||
private SchematicWorld blockReader;
|
||||
public BlockPos currentPos;
|
||||
public BlockPos schematicAnchor;
|
||||
public boolean schematicLoaded;
|
||||
public SchematicPrinter printer;
|
||||
public ItemStack missingItem;
|
||||
public boolean positionNotLoaded;
|
||||
public boolean hasCreativeCrate;
|
||||
private int printerCooldown;
|
||||
private int skipsLeft;
|
||||
private boolean blockSkipped;
|
||||
private int printingEntityIndex;
|
||||
private PrintStage printStage;
|
||||
|
||||
public BlockPos target;
|
||||
public BlockPos previousTarget;
|
||||
public LinkedHashSet<LazyOptional<IItemHandler>> attachedInventories;
|
||||
public List<LaunchedItem> flyingBlocks;
|
||||
public MaterialChecklist checklist;
|
||||
public List<BlockPos> deferredBlocks;
|
||||
|
||||
// Gui information
|
||||
public float fuelLevel;
|
||||
|
@ -150,11 +140,9 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
|
|||
inventory = new SchematicannonInventory(this);
|
||||
statusMsg = "idle";
|
||||
state = State.STOPPED;
|
||||
printingEntityIndex = -1;
|
||||
printStage = PrintStage.BLOCKS;
|
||||
deferredBlocks = new LinkedList<>();
|
||||
replaceMode = 2;
|
||||
checklist = new MaterialChecklist();
|
||||
printer = new SchematicPrinter();
|
||||
}
|
||||
|
||||
public void findInventories() {
|
||||
|
@ -183,8 +171,6 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
|
|||
protected void fromTag(BlockState blockState, CompoundNBT compound, boolean clientPacket) {
|
||||
if (!clientPacket) {
|
||||
inventory.deserializeNBT(compound.getCompound("Inventory"));
|
||||
if (compound.contains("CurrentPos"))
|
||||
currentPos = NBTUtil.readBlockPos(compound.getCompound("CurrentPos"));
|
||||
}
|
||||
|
||||
// Gui information
|
||||
|
@ -195,7 +181,6 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
|
|||
state = State.valueOf(compound.getString("State"));
|
||||
blocksPlaced = compound.getInt("AmountPlaced");
|
||||
blocksToPlace = compound.getInt("AmountToPlace");
|
||||
printingEntityIndex = compound.getInt("EntityProgress");
|
||||
|
||||
missingItem = null;
|
||||
if (compound.contains("MissingItem"))
|
||||
|
@ -208,14 +193,8 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
|
|||
replaceTileEntities = options.getBoolean("ReplaceTileEntities");
|
||||
|
||||
// Printer & Flying Blocks
|
||||
if (compound.contains("PrintStage"))
|
||||
printStage = PrintStage.valueOf(compound.getString("PrintStage"));
|
||||
if (compound.contains("Target"))
|
||||
target = NBTUtil.readBlockPos(compound.getCompound("Target"));
|
||||
if (compound.contains("DeferredBlocks"))
|
||||
compound.getList("DeferredBlocks", 10).stream()
|
||||
.map(p -> NBTUtil.readBlockPos((CompoundNBT) p))
|
||||
.collect(Collectors.toCollection(() -> deferredBlocks));
|
||||
if (compound.contains("Printer"))
|
||||
printer.fromTag(compound.getCompound("Printer"), clientPacket);
|
||||
if (compound.contains("FlyingBlocks"))
|
||||
readFlyingBlocks(compound);
|
||||
|
||||
|
@ -263,8 +242,6 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
|
|||
compound.put("Inventory", inventory.serializeNBT());
|
||||
if (state == State.RUNNING) {
|
||||
compound.putBoolean("Running", true);
|
||||
if (currentPos != null)
|
||||
compound.put("CurrentPos", NBTUtil.writeBlockPos(currentPos));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -276,7 +253,6 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
|
|||
compound.putString("State", state.name());
|
||||
compound.putInt("AmountPlaced", blocksPlaced);
|
||||
compound.putInt("AmountToPlace", blocksToPlace);
|
||||
compound.putInt("EntityProgress", printingEntityIndex);
|
||||
|
||||
if (missingItem != null)
|
||||
compound.put("MissingItem", missingItem.serializeNBT());
|
||||
|
@ -289,15 +265,9 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
|
|||
compound.put("Options", options);
|
||||
|
||||
// Printer & Flying Blocks
|
||||
compound.putString("PrintStage", printStage.name());
|
||||
|
||||
if (target != null)
|
||||
compound.put("Target", NBTUtil.writeBlockPos(target));
|
||||
|
||||
ListNBT tagDeferredBlocks = new ListNBT();
|
||||
for (BlockPos p : deferredBlocks)
|
||||
tagDeferredBlocks.add(NBTUtil.writeBlockPos(p));
|
||||
compound.put("DeferredBlocks", tagDeferredBlocks);
|
||||
CompoundNBT printerData = new CompoundNBT();
|
||||
printer.write(printerData);
|
||||
compound.put("Printer", printerData);
|
||||
|
||||
ListNBT tagFlyingBlocks = new ListNBT();
|
||||
for (LaunchedItem b : flyingBlocks)
|
||||
|
@ -317,7 +287,7 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
|
|||
}
|
||||
|
||||
firstRenderTick = true;
|
||||
previousTarget = target;
|
||||
previousTarget = printer.getCurrentTarget();
|
||||
tickFlyingBlocks();
|
||||
|
||||
if (world.isRemote)
|
||||
|
@ -355,7 +325,7 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
|
|||
|
||||
// Skip if not Active
|
||||
if (state == State.STOPPED) {
|
||||
if (schematicLoaded)
|
||||
if (printer.isLoaded())
|
||||
resetPrinter();
|
||||
return;
|
||||
}
|
||||
|
@ -371,7 +341,7 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
|
|||
return;
|
||||
|
||||
// Initialize Printer
|
||||
if (!schematicLoaded) {
|
||||
if (!printer.isLoaded()) {
|
||||
initializePrinter(blueprint);
|
||||
return;
|
||||
}
|
||||
|
@ -391,7 +361,6 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
|
|||
return;
|
||||
}
|
||||
|
||||
// Update Target
|
||||
if (hasCreativeCrate) {
|
||||
if (missingItem != null) {
|
||||
missingItem = null;
|
||||
|
@ -399,23 +368,17 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
|
|||
}
|
||||
}
|
||||
|
||||
// Update Target
|
||||
if (missingItem == null && !positionNotLoaded) {
|
||||
do {
|
||||
advanceCurrentPos();
|
||||
if (state == State.STOPPED)
|
||||
return;
|
||||
|
||||
} while (!blockReader.getBounds()
|
||||
.isVecInside(currentPos));
|
||||
|
||||
if (!printer.advanceCurrentPos()) {
|
||||
finishedPrinting();
|
||||
return;
|
||||
}
|
||||
sendUpdate = true;
|
||||
target = schematicAnchor.add(currentPos);
|
||||
}
|
||||
|
||||
boolean entityMode = printStage == PrintStage.ENTITIES;
|
||||
|
||||
// Check block
|
||||
if (!getWorld().isAreaLoaded(target, 0)) {
|
||||
if (!getWorld().isAreaLoaded(printer.getCurrentTarget(), 0)) {
|
||||
positionNotLoaded = true;
|
||||
statusMsg = "targetNotLoaded";
|
||||
state = State.PAUSED;
|
||||
|
@ -427,24 +390,9 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
|
|||
}
|
||||
}
|
||||
|
||||
boolean shouldSkip = false;
|
||||
BlockState blockState = Blocks.AIR.getDefaultState();
|
||||
TileEntity tileEntity = null;
|
||||
ItemRequirement requirement;
|
||||
|
||||
if (entityMode) {
|
||||
requirement = ItemRequirement.of(blockReader.getEntities()
|
||||
.collect(Collectors.toList())
|
||||
.get(printingEntityIndex));
|
||||
|
||||
} else {
|
||||
blockState = BlockHelper.setZeroAge(blockReader.getBlockState(target));
|
||||
tileEntity = blockReader.getTileEntity(target);
|
||||
requirement = ItemRequirement.of(blockState, tileEntity);
|
||||
shouldSkip = !shouldPlace(target, blockState, tileEntity);
|
||||
}
|
||||
|
||||
if (shouldSkip || requirement.isInvalid()) {
|
||||
// Get item requirement
|
||||
ItemRequirement requirement = printer.getCurrentRequirement();
|
||||
if (requirement.isInvalid() || !printer.shouldPlaceCurrent(world, this::shouldPlace)) {
|
||||
statusMsg = "searching";
|
||||
blockSkipped = true;
|
||||
return;
|
||||
|
@ -478,39 +426,16 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
|
|||
|
||||
// Success
|
||||
state = State.RUNNING;
|
||||
if (blockState.getBlock() != Blocks.AIR || entityMode)
|
||||
statusMsg = "placing";
|
||||
else
|
||||
statusMsg = "clearing";
|
||||
|
||||
ItemStack icon = requirement.isEmpty() || requiredItems.isEmpty() ? ItemStack.EMPTY : requiredItems.get(0).item;
|
||||
if (entityMode)
|
||||
launchEntity(target, icon, blockReader.getEntities()
|
||||
.collect(Collectors.toList())
|
||||
.get(printingEntityIndex));
|
||||
else if (AllBlocks.BELT.has(blockState)) {
|
||||
TileEntity te = blockReader.getTileEntity(currentPos.add(schematicAnchor));
|
||||
blockState = stripBeltIfNotLast(blockState);
|
||||
if (te instanceof BeltTileEntity && AllBlocks.BELT.has(blockState))
|
||||
launchBelt(target, blockState, ((BeltTileEntity) te).beltLength);
|
||||
else
|
||||
launchBlock(target, icon, blockState, null);
|
||||
} else {
|
||||
CompoundNBT data = null;
|
||||
TileEntity tile = blockReader.getTileEntity(target);
|
||||
if (tile != null) {
|
||||
if (AllBlockTags.SAFE_NBT.matches(blockState)) {
|
||||
data = tile.write(new CompoundNBT());
|
||||
data = NBTProcessors.process(tile, data, true);
|
||||
} else if (tile instanceof IPartialSafeNBT) {
|
||||
data = new CompoundNBT();
|
||||
((IPartialSafeNBT) tile).writeSafe(data, false);
|
||||
data = NBTProcessors.process(tile, data, true);
|
||||
}
|
||||
}
|
||||
|
||||
launchBlock(target, icon, blockState, data);
|
||||
}
|
||||
printer.handleCurrentTarget((target, blockState, tile) -> {
|
||||
// Launch block
|
||||
statusMsg = blockState.getBlock() != Blocks.AIR ? "placing" : "clearing";
|
||||
launchBlockOrBelt(target, icon, blockState, tile);
|
||||
}, (target, entity) -> {
|
||||
// Launch entity
|
||||
statusMsg = "placing";
|
||||
launchEntity(target, icon, entity);
|
||||
});
|
||||
|
||||
printerCooldown = config().schematicannonDelay.get();
|
||||
fuelLevel -= getFuelUsageRate();
|
||||
|
@ -518,35 +443,6 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
|
|||
missingItem = null;
|
||||
}
|
||||
|
||||
public BlockState stripBeltIfNotLast(BlockState blockState) {
|
||||
// is highest belt?
|
||||
boolean isLastSegment = false;
|
||||
Direction facing = blockState.get(BeltBlock.HORIZONTAL_FACING);
|
||||
BeltSlope slope = blockState.get(BeltBlock.SLOPE);
|
||||
boolean positive = facing.getAxisDirection() == AxisDirection.POSITIVE;
|
||||
boolean start = blockState.get(BeltBlock.PART) == BeltPart.START;
|
||||
boolean end = blockState.get(BeltBlock.PART) == BeltPart.END;
|
||||
|
||||
switch (slope) {
|
||||
case DOWNWARD:
|
||||
isLastSegment = start;
|
||||
break;
|
||||
case UPWARD:
|
||||
isLastSegment = end;
|
||||
break;
|
||||
case HORIZONTAL:
|
||||
case VERTICAL:
|
||||
default:
|
||||
isLastSegment = positive && end || !positive && start;
|
||||
}
|
||||
if (!isLastSegment)
|
||||
blockState = (blockState.get(BeltBlock.PART) == BeltPart.MIDDLE) ? Blocks.AIR.getDefaultState()
|
||||
: AllBlocks.SHAFT.getDefaultState()
|
||||
.with(AbstractShaftBlock.AXIS, facing.rotateY()
|
||||
.getAxis());
|
||||
return blockState;
|
||||
}
|
||||
|
||||
public double getFuelUsageRate() {
|
||||
return hasCreativeCrate ? 0 : config().schematicannonFuelUsage.get() / 100f;
|
||||
}
|
||||
|
@ -568,40 +464,29 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
|
|||
}
|
||||
|
||||
// Load blocks into reader
|
||||
Template activeTemplate = SchematicItem.loadSchematic(blueprint);
|
||||
BlockPos anchor = NBTUtil.readBlockPos(blueprint.getTag()
|
||||
.getCompound("Anchor"));
|
||||
printer.loadSchematic(blueprint, world, true);
|
||||
|
||||
if (activeTemplate.getSize()
|
||||
.equals(BlockPos.ZERO)) {
|
||||
if (printer.isWorldEmpty()) {
|
||||
state = State.STOPPED;
|
||||
statusMsg = "schematicExpired";
|
||||
inventory.setStackInSlot(0, ItemStack.EMPTY);
|
||||
inventory.setStackInSlot(1, new ItemStack(AllItems.EMPTY_SCHEMATIC.get()));
|
||||
printer.resetSchematic();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!anchor.withinDistance(getPos(), MAX_ANCHOR_DISTANCE)) {
|
||||
if (!printer.getAnchor().withinDistance(getPos(), MAX_ANCHOR_DISTANCE)) {
|
||||
state = State.STOPPED;
|
||||
statusMsg = "targetOutsideRange";
|
||||
printer.resetSchematic();
|
||||
return;
|
||||
}
|
||||
|
||||
schematicAnchor = anchor;
|
||||
blockReader = new SchematicWorld(schematicAnchor, world);
|
||||
PlacementSettings settings = SchematicItem.getSettings(blueprint);
|
||||
activeTemplate.place(blockReader, schematicAnchor, settings, blockReader.getRandom());
|
||||
schematicLoaded = true;
|
||||
state = State.PAUSED;
|
||||
statusMsg = "ready";
|
||||
printingEntityIndex = -1;
|
||||
printStage = PrintStage.BLOCKS;
|
||||
deferredBlocks.clear();
|
||||
updateChecklist();
|
||||
sendUpdate = true;
|
||||
blocksToPlace += blocksPlaced;
|
||||
MutableBoundingBox bounds = blockReader.getBounds();
|
||||
currentPos = currentPos != null ? currentPos.west() : new BlockPos(bounds.minX - 1, bounds.minY, bounds.minZ);
|
||||
}
|
||||
|
||||
protected ItemStack getItemForBlock(BlockState blockState) {
|
||||
|
@ -679,57 +564,6 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
|
|||
return success;
|
||||
}
|
||||
|
||||
protected void advanceCurrentPos() {
|
||||
List<Entity> entities = blockReader.getEntities()
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (printStage == PrintStage.BLOCKS) {
|
||||
MutableBoundingBox bounds = blockReader.getBounds();
|
||||
while (tryAdvanceCurrentPos(bounds, entities)) {
|
||||
deferredBlocks.add(currentPos);
|
||||
}
|
||||
}
|
||||
|
||||
if (printStage == PrintStage.DEFERRED_BLOCKS) {
|
||||
if (deferredBlocks.isEmpty()) {
|
||||
printStage = PrintStage.ENTITIES;
|
||||
} else {
|
||||
currentPos = deferredBlocks.remove(0);
|
||||
}
|
||||
}
|
||||
|
||||
if (printStage == PrintStage.ENTITIES) {
|
||||
if (printingEntityIndex + 1 < entities.size()) {
|
||||
printingEntityIndex++;
|
||||
currentPos = entities.get(printingEntityIndex).getBlockPos().subtract(schematicAnchor);
|
||||
} else {
|
||||
finishedPrinting();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean tryAdvanceCurrentPos(MutableBoundingBox bounds, List<Entity> entities) {
|
||||
currentPos = currentPos.offset(Direction.EAST);
|
||||
BlockPos posInBounds = currentPos.add(-bounds.minX, -bounds.minY, -bounds.minZ);
|
||||
|
||||
if (posInBounds.getX() > bounds.getXSize())
|
||||
currentPos = new BlockPos(bounds.minX, currentPos.getY(), currentPos.getZ() + 1).west();
|
||||
if (posInBounds.getZ() > bounds.getZSize())
|
||||
currentPos = new BlockPos(currentPos.getX(), currentPos.getY() + 1, bounds.minZ).west();
|
||||
|
||||
// End of blocks reached
|
||||
if (currentPos.getY() > bounds.getYSize()) {
|
||||
printStage = PrintStage.DEFERRED_BLOCKS;
|
||||
return false;
|
||||
}
|
||||
|
||||
return shouldDeferBlock(blockReader.getBlockState(schematicAnchor.add(currentPos)));
|
||||
}
|
||||
|
||||
public static boolean shouldDeferBlock(BlockState state) {
|
||||
return state.getBlock().is(AllBlocks.GANTRY_CARRIAGE.get()) || BlockMovementChecks.isBrittle(state);
|
||||
}
|
||||
|
||||
public void finishedPrinting() {
|
||||
inventory.setStackInSlot(0, ItemStack.EMPTY);
|
||||
inventory.setStackInSlot(1, new ItemStack(AllItems.EMPTY_SCHEMATIC.get(), inventory.getStackInSlot(1)
|
||||
|
@ -737,71 +571,43 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
|
|||
state = State.STOPPED;
|
||||
statusMsg = "finished";
|
||||
resetPrinter();
|
||||
target = getPos().add(1, 0, 0);
|
||||
AllSoundEvents.SCHEMATICANNON_FINISH.playOnServer(world, pos);
|
||||
sendUpdate = true;
|
||||
}
|
||||
|
||||
protected void resetPrinter() {
|
||||
schematicLoaded = false;
|
||||
schematicAnchor = null;
|
||||
currentPos = null;
|
||||
blockReader = null;
|
||||
printer.resetSchematic();
|
||||
missingItem = null;
|
||||
sendUpdate = true;
|
||||
printingEntityIndex = 0;
|
||||
printStage = PrintStage.BLOCKS;
|
||||
schematicProgress = 0;
|
||||
blocksPlaced = 0;
|
||||
blocksToPlace = 0;
|
||||
deferredBlocks.clear();
|
||||
}
|
||||
|
||||
protected boolean shouldPlace(BlockPos pos, BlockState state, TileEntity te) {
|
||||
if (world == null)
|
||||
return false;
|
||||
BlockState toReplace = world.getBlockState(pos);
|
||||
boolean placingAir = state.getBlock()
|
||||
.isAir(state, world, pos);
|
||||
|
||||
BlockState toReplaceOther = null;
|
||||
if (state.contains(BlockStateProperties.BED_PART) && state.contains(BlockStateProperties.HORIZONTAL_FACING)
|
||||
&& state.get(BlockStateProperties.BED_PART) == BedPart.FOOT)
|
||||
toReplaceOther = world.getBlockState(pos.offset(state.get(BlockStateProperties.HORIZONTAL_FACING)));
|
||||
if (state.contains(BlockStateProperties.DOUBLE_BLOCK_HALF)
|
||||
&& state.get(BlockStateProperties.DOUBLE_BLOCK_HALF) == DoubleBlockHalf.LOWER)
|
||||
toReplaceOther = world.getBlockState(pos.up());
|
||||
|
||||
if (!world.isBlockPresent(pos))
|
||||
return false;
|
||||
if (!world.getWorldBorder()
|
||||
.contains(pos))
|
||||
return false;
|
||||
if (toReplace == state)
|
||||
return false;
|
||||
if (toReplace.getBlockHardness(world, pos) == -1
|
||||
|| (toReplaceOther != null && toReplaceOther.getBlockHardness(world, pos) == -1))
|
||||
return false;
|
||||
protected boolean shouldPlace(BlockPos pos, BlockState state, TileEntity te,
|
||||
BlockState toReplace, BlockState toReplaceOther, boolean isNormalCube) {
|
||||
if (pos.withinDistance(getPos(), 2f))
|
||||
return false;
|
||||
if (!replaceTileEntities
|
||||
&& (toReplace.hasTileEntity() || (toReplaceOther != null && toReplaceOther.hasTileEntity())))
|
||||
&& (toReplace.hasTileEntity() || (toReplaceOther != null && toReplaceOther.hasTileEntity())))
|
||||
return false;
|
||||
|
||||
if (shouldIgnoreBlockState(state, te))
|
||||
return false;
|
||||
|
||||
boolean placingAir = state.getBlock().isAir(state, world, pos);
|
||||
|
||||
if (replaceMode == 3)
|
||||
return true;
|
||||
if (replaceMode == 2 && !placingAir)
|
||||
return true;
|
||||
if (replaceMode == 1
|
||||
&& (state.isNormalCube(blockReader, pos.subtract(schematicAnchor)) || (!toReplace.isNormalCube(world, pos)
|
||||
&& (isNormalCube || (!toReplace.isNormalCube(world, pos)
|
||||
&& (toReplaceOther == null || !toReplaceOther.isNormalCube(world, pos))))
|
||||
&& !placingAir)
|
||||
&& !placingAir)
|
||||
return true;
|
||||
if (replaceMode == 0 && !toReplace.isNormalCube(world, pos)
|
||||
&& (toReplaceOther == null || !toReplaceOther.isNormalCube(world, pos)) && !placingAir)
|
||||
&& (toReplaceOther == null || !toReplaceOther.isNormalCube(world, pos)) && !placingAir)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
|
@ -874,7 +680,7 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
|
|||
return;
|
||||
}
|
||||
|
||||
if (!schematicLoaded) {
|
||||
if (!printer.isLoaded()) {
|
||||
if (!blueprint.isEmpty())
|
||||
initializePrinter(blueprint);
|
||||
return;
|
||||
|
@ -889,8 +695,7 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
|
|||
dontUpdateChecklist = true;
|
||||
inventory.extractItem(BookInput, 1, false);
|
||||
ItemStack stack = checklist.createItem();
|
||||
stack.setCount(inventory.getStackInSlot(BookOutput)
|
||||
.getCount() + 1);
|
||||
stack.setCount(inventory.getStackInSlot(BookOutput).getCount() + 1);
|
||||
inventory.setStackInSlot(BookOutput, stack);
|
||||
sendUpdate = true;
|
||||
return;
|
||||
|
@ -900,6 +705,58 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
|
|||
sendUpdate = true;
|
||||
}
|
||||
|
||||
public static BlockState stripBeltIfNotLast(BlockState blockState) {
|
||||
// is highest belt?
|
||||
boolean isLastSegment = false;
|
||||
Direction facing = blockState.get(BeltBlock.HORIZONTAL_FACING);
|
||||
BeltSlope slope = blockState.get(BeltBlock.SLOPE);
|
||||
boolean positive = facing.getAxisDirection() == AxisDirection.POSITIVE;
|
||||
boolean start = blockState.get(BeltBlock.PART) == BeltPart.START;
|
||||
boolean end = blockState.get(BeltBlock.PART) == BeltPart.END;
|
||||
|
||||
switch (slope) {
|
||||
case DOWNWARD:
|
||||
isLastSegment = start;
|
||||
break;
|
||||
case UPWARD:
|
||||
isLastSegment = end;
|
||||
break;
|
||||
case HORIZONTAL:
|
||||
case VERTICAL:
|
||||
default:
|
||||
isLastSegment = positive && end || !positive && start;
|
||||
}
|
||||
if (!isLastSegment)
|
||||
blockState = (blockState.get(BeltBlock.PART) == BeltPart.MIDDLE) ? Blocks.AIR.getDefaultState()
|
||||
: AllBlocks.SHAFT.getDefaultState()
|
||||
.with(AbstractShaftBlock.AXIS, facing.rotateY()
|
||||
.getAxis());
|
||||
return blockState;
|
||||
}
|
||||
|
||||
protected void launchBlockOrBelt(BlockPos target, ItemStack icon, BlockState blockState, TileEntity tile) {
|
||||
if (AllBlocks.BELT.has(blockState)) {
|
||||
blockState = stripBeltIfNotLast(blockState);
|
||||
if (tile instanceof BeltTileEntity && AllBlocks.BELT.has(blockState))
|
||||
launchBelt(target, blockState, ((BeltTileEntity) tile).beltLength);
|
||||
else
|
||||
launchBlock(target, icon, blockState, null);
|
||||
} else {
|
||||
CompoundNBT data = null;
|
||||
if (tile != null) {
|
||||
if (AllBlockTags.SAFE_NBT.matches(blockState)) {
|
||||
data = tile.write(new CompoundNBT());
|
||||
data = NBTProcessors.process(tile, data, true);
|
||||
} else if (tile instanceof IPartialSafeNBT) {
|
||||
data = new CompoundNBT();
|
||||
((IPartialSafeNBT) tile).writeSafe(data, false);
|
||||
data = NBTProcessors.process(tile, data, true);
|
||||
}
|
||||
}
|
||||
launchBlock(target, icon, blockState, data);
|
||||
}
|
||||
}
|
||||
|
||||
protected void launchBelt(BlockPos target, BlockState state, int length) {
|
||||
blocksPlaced++;
|
||||
ItemStack connector = AllItems.BELT_CONNECTOR.asStack();
|
||||
|
@ -908,8 +765,7 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
|
|||
}
|
||||
|
||||
protected void launchBlock(BlockPos target, ItemStack stack, BlockState state, @Nullable CompoundNBT data) {
|
||||
if (!state.getBlock()
|
||||
.isAir(state, world, target))
|
||||
if (!state.getBlock().isAir(state, world, target))
|
||||
blocksPlaced++;
|
||||
flyingBlocks.add(new LaunchedItem.ForBlockState(this.getPos(), target, stack, state, data));
|
||||
playFiringSound();
|
||||
|
@ -945,37 +801,10 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
|
|||
checklist.damageRequired.clear();
|
||||
checklist.blocksNotLoaded = false;
|
||||
|
||||
if (schematicLoaded) {
|
||||
if (printer.isLoaded()) {
|
||||
blocksToPlace = blocksPlaced;
|
||||
for (BlockPos pos : blockReader.getAllPositions()) {
|
||||
BlockPos relPos = pos.add(schematicAnchor);
|
||||
BlockState required = blockReader.getBlockState(relPos);
|
||||
TileEntity requiredTE = blockReader.getTileEntity(relPos);
|
||||
|
||||
if (!getWorld().isAreaLoaded(pos.add(schematicAnchor), 0)) {
|
||||
checklist.warnBlockNotLoaded();
|
||||
continue;
|
||||
}
|
||||
if (!shouldPlace(pos.add(schematicAnchor), required, requiredTE))
|
||||
continue;
|
||||
ItemRequirement requirement = ItemRequirement.of(required, blockReader.getTileEntity(relPos));
|
||||
if (requirement.isEmpty())
|
||||
continue;
|
||||
if (requirement.isInvalid())
|
||||
continue;
|
||||
checklist.require(requirement);
|
||||
blocksToPlace++;
|
||||
}
|
||||
blockReader.getEntities()
|
||||
.forEach(entity -> {
|
||||
ItemRequirement requirement = ItemRequirement.of(entity);
|
||||
if (requirement.isEmpty())
|
||||
return;
|
||||
if (requirement.isInvalid())
|
||||
return;
|
||||
checklist.require(requirement);
|
||||
});
|
||||
|
||||
blocksToPlace += printer.markAllBlockRequirements(checklist, world, this::shouldPlace);
|
||||
printer.markAllEntityRequirements(checklist);
|
||||
}
|
||||
checklist.gathered.clear();
|
||||
findInventories();
|
||||
|
|
|
@ -99,12 +99,13 @@ public class SchematicItem extends Item {
|
|||
SchematicInstances.clearHash(blueprint);
|
||||
}
|
||||
|
||||
public static PlacementSettings getSettings(ItemStack blueprint) {
|
||||
public static PlacementSettings getSettings(ItemStack blueprint, boolean processNBT) {
|
||||
CompoundNBT tag = blueprint.getTag();
|
||||
PlacementSettings settings = new PlacementSettings();
|
||||
settings.setRotation(Rotation.valueOf(tag.getString("Rotation")));
|
||||
settings.setMirror(Mirror.valueOf(tag.getString("Mirror")));
|
||||
settings.addProcessor(SchematicProcessor.INSTANCE);
|
||||
if (processNBT)
|
||||
settings.addProcessor(SchematicProcessor.INSTANCE);
|
||||
return settings;
|
||||
}
|
||||
|
||||
|
|
|
@ -2,14 +2,19 @@ package com.simibubi.create.content.schematics.packet;
|
|||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import com.simibubi.create.content.schematics.SchematicPrinter;
|
||||
import com.simibubi.create.content.schematics.SchematicProcessor;
|
||||
import com.simibubi.create.content.schematics.item.SchematicItem;
|
||||
import com.simibubi.create.foundation.networking.SimplePacketBase;
|
||||
|
||||
import com.simibubi.create.foundation.utility.BlockHelper;
|
||||
|
||||
import net.minecraft.entity.player.ServerPlayerEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
import net.minecraft.nbt.NBTUtil;
|
||||
import net.minecraft.network.PacketBuffer;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.gen.feature.template.PlacementSettings;
|
||||
import net.minecraft.world.gen.feature.template.Template;
|
||||
import net.minecraftforge.fml.network.NetworkEvent.Context;
|
||||
|
@ -35,13 +40,22 @@ public class SchematicPlacePacket extends SimplePacketBase {
|
|||
ServerPlayerEntity player = context.get().getSender();
|
||||
if (player == null)
|
||||
return;
|
||||
Template t = SchematicItem.loadSchematic(stack);
|
||||
PlacementSettings settings = SchematicItem.getSettings(stack);
|
||||
if (player.canUseCommandBlock())
|
||||
settings.func_215220_b(SchematicProcessor.INSTANCE); // remove processor
|
||||
settings.setIgnoreEntities(false);
|
||||
t.place(player.getServerWorld(), NBTUtil.readBlockPos(stack.getTag().getCompound("Anchor")),
|
||||
settings, player.getRNG());
|
||||
|
||||
World world = player.getServerWorld();
|
||||
SchematicPrinter printer = new SchematicPrinter();
|
||||
printer.loadSchematic(stack, world, !player.canUseCommandBlock());
|
||||
|
||||
while(printer.advanceCurrentPos()) {
|
||||
if (!printer.shouldPlaceCurrent(world))
|
||||
continue;
|
||||
|
||||
printer.handleCurrentTarget((pos, state, tile) -> {
|
||||
CompoundNBT tileData = tile != null ? tile.write(new CompoundNBT()) : null;
|
||||
BlockHelper.placeSchematicBlock(world, state, pos, null, tileData);
|
||||
}, (pos, entity) -> {
|
||||
world.addEntity(entity);
|
||||
});
|
||||
}
|
||||
});
|
||||
context.get().setPacketHandled(true);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue