mirror of
https://github.com/Creators-of-Create/Create.git
synced 2024-11-13 21:41:34 +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 yaw = 0;
|
||||||
double pitch = 40;
|
double pitch = 40;
|
||||||
|
|
||||||
if (tile.target != null) {
|
BlockPos target = tile.printer.getCurrentTarget();
|
||||||
|
if (target != null) {
|
||||||
|
|
||||||
// Calculate Angle of Cannon
|
// Calculate Angle of Cannon
|
||||||
Vector3d diff = Vector3d.of(tile.target.subtract(pos));
|
Vector3d diff = Vector3d.of(target.subtract(pos));
|
||||||
if (tile.previousTarget != null) {
|
if (tile.previousTarget != null) {
|
||||||
diff = (Vector3d.of(tile.previousTarget)
|
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));
|
.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;
|
||||||
import com.simibubi.create.content.schematics.ItemRequirement.ItemUseType;
|
import com.simibubi.create.content.schematics.ItemRequirement.ItemUseType;
|
||||||
import com.simibubi.create.content.schematics.MaterialChecklist;
|
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.SchematicWorld;
|
||||||
import com.simibubi.create.content.schematics.item.SchematicItem;
|
import com.simibubi.create.content.schematics.item.SchematicItem;
|
||||||
import com.simibubi.create.foundation.config.AllConfigs;
|
import com.simibubi.create.foundation.config.AllConfigs;
|
||||||
|
@ -81,10 +82,6 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
|
||||||
STOPPED, PAUSED, RUNNING;
|
STOPPED, PAUSED, RUNNING;
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum PrintStage {
|
|
||||||
BLOCKS, DEFERRED_BLOCKS, ENTITIES
|
|
||||||
}
|
|
||||||
|
|
||||||
// Inventory
|
// Inventory
|
||||||
public SchematicannonInventory inventory;
|
public SchematicannonInventory inventory;
|
||||||
|
|
||||||
|
@ -94,25 +91,18 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
|
||||||
public int neighbourCheckCooldown;
|
public int neighbourCheckCooldown;
|
||||||
|
|
||||||
// Printer
|
// Printer
|
||||||
private SchematicWorld blockReader;
|
public SchematicPrinter printer;
|
||||||
public BlockPos currentPos;
|
|
||||||
public BlockPos schematicAnchor;
|
|
||||||
public boolean schematicLoaded;
|
|
||||||
public ItemStack missingItem;
|
public ItemStack missingItem;
|
||||||
public boolean positionNotLoaded;
|
public boolean positionNotLoaded;
|
||||||
public boolean hasCreativeCrate;
|
public boolean hasCreativeCrate;
|
||||||
private int printerCooldown;
|
private int printerCooldown;
|
||||||
private int skipsLeft;
|
private int skipsLeft;
|
||||||
private boolean blockSkipped;
|
private boolean blockSkipped;
|
||||||
private int printingEntityIndex;
|
|
||||||
private PrintStage printStage;
|
|
||||||
|
|
||||||
public BlockPos target;
|
|
||||||
public BlockPos previousTarget;
|
public BlockPos previousTarget;
|
||||||
public LinkedHashSet<LazyOptional<IItemHandler>> attachedInventories;
|
public LinkedHashSet<LazyOptional<IItemHandler>> attachedInventories;
|
||||||
public List<LaunchedItem> flyingBlocks;
|
public List<LaunchedItem> flyingBlocks;
|
||||||
public MaterialChecklist checklist;
|
public MaterialChecklist checklist;
|
||||||
public List<BlockPos> deferredBlocks;
|
|
||||||
|
|
||||||
// Gui information
|
// Gui information
|
||||||
public float fuelLevel;
|
public float fuelLevel;
|
||||||
|
@ -150,11 +140,9 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
|
||||||
inventory = new SchematicannonInventory(this);
|
inventory = new SchematicannonInventory(this);
|
||||||
statusMsg = "idle";
|
statusMsg = "idle";
|
||||||
state = State.STOPPED;
|
state = State.STOPPED;
|
||||||
printingEntityIndex = -1;
|
|
||||||
printStage = PrintStage.BLOCKS;
|
|
||||||
deferredBlocks = new LinkedList<>();
|
|
||||||
replaceMode = 2;
|
replaceMode = 2;
|
||||||
checklist = new MaterialChecklist();
|
checklist = new MaterialChecklist();
|
||||||
|
printer = new SchematicPrinter();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void findInventories() {
|
public void findInventories() {
|
||||||
|
@ -183,8 +171,6 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
|
||||||
protected void fromTag(BlockState blockState, CompoundNBT compound, boolean clientPacket) {
|
protected void fromTag(BlockState blockState, CompoundNBT compound, boolean clientPacket) {
|
||||||
if (!clientPacket) {
|
if (!clientPacket) {
|
||||||
inventory.deserializeNBT(compound.getCompound("Inventory"));
|
inventory.deserializeNBT(compound.getCompound("Inventory"));
|
||||||
if (compound.contains("CurrentPos"))
|
|
||||||
currentPos = NBTUtil.readBlockPos(compound.getCompound("CurrentPos"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gui information
|
// Gui information
|
||||||
|
@ -195,7 +181,6 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
|
||||||
state = State.valueOf(compound.getString("State"));
|
state = State.valueOf(compound.getString("State"));
|
||||||
blocksPlaced = compound.getInt("AmountPlaced");
|
blocksPlaced = compound.getInt("AmountPlaced");
|
||||||
blocksToPlace = compound.getInt("AmountToPlace");
|
blocksToPlace = compound.getInt("AmountToPlace");
|
||||||
printingEntityIndex = compound.getInt("EntityProgress");
|
|
||||||
|
|
||||||
missingItem = null;
|
missingItem = null;
|
||||||
if (compound.contains("MissingItem"))
|
if (compound.contains("MissingItem"))
|
||||||
|
@ -208,14 +193,8 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
|
||||||
replaceTileEntities = options.getBoolean("ReplaceTileEntities");
|
replaceTileEntities = options.getBoolean("ReplaceTileEntities");
|
||||||
|
|
||||||
// Printer & Flying Blocks
|
// Printer & Flying Blocks
|
||||||
if (compound.contains("PrintStage"))
|
if (compound.contains("Printer"))
|
||||||
printStage = PrintStage.valueOf(compound.getString("PrintStage"));
|
printer.fromTag(compound.getCompound("Printer"), clientPacket);
|
||||||
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("FlyingBlocks"))
|
if (compound.contains("FlyingBlocks"))
|
||||||
readFlyingBlocks(compound);
|
readFlyingBlocks(compound);
|
||||||
|
|
||||||
|
@ -263,8 +242,6 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
|
||||||
compound.put("Inventory", inventory.serializeNBT());
|
compound.put("Inventory", inventory.serializeNBT());
|
||||||
if (state == State.RUNNING) {
|
if (state == State.RUNNING) {
|
||||||
compound.putBoolean("Running", true);
|
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.putString("State", state.name());
|
||||||
compound.putInt("AmountPlaced", blocksPlaced);
|
compound.putInt("AmountPlaced", blocksPlaced);
|
||||||
compound.putInt("AmountToPlace", blocksToPlace);
|
compound.putInt("AmountToPlace", blocksToPlace);
|
||||||
compound.putInt("EntityProgress", printingEntityIndex);
|
|
||||||
|
|
||||||
if (missingItem != null)
|
if (missingItem != null)
|
||||||
compound.put("MissingItem", missingItem.serializeNBT());
|
compound.put("MissingItem", missingItem.serializeNBT());
|
||||||
|
@ -289,15 +265,9 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
|
||||||
compound.put("Options", options);
|
compound.put("Options", options);
|
||||||
|
|
||||||
// Printer & Flying Blocks
|
// Printer & Flying Blocks
|
||||||
compound.putString("PrintStage", printStage.name());
|
CompoundNBT printerData = new CompoundNBT();
|
||||||
|
printer.write(printerData);
|
||||||
if (target != null)
|
compound.put("Printer", printerData);
|
||||||
compound.put("Target", NBTUtil.writeBlockPos(target));
|
|
||||||
|
|
||||||
ListNBT tagDeferredBlocks = new ListNBT();
|
|
||||||
for (BlockPos p : deferredBlocks)
|
|
||||||
tagDeferredBlocks.add(NBTUtil.writeBlockPos(p));
|
|
||||||
compound.put("DeferredBlocks", tagDeferredBlocks);
|
|
||||||
|
|
||||||
ListNBT tagFlyingBlocks = new ListNBT();
|
ListNBT tagFlyingBlocks = new ListNBT();
|
||||||
for (LaunchedItem b : flyingBlocks)
|
for (LaunchedItem b : flyingBlocks)
|
||||||
|
@ -317,7 +287,7 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
|
||||||
}
|
}
|
||||||
|
|
||||||
firstRenderTick = true;
|
firstRenderTick = true;
|
||||||
previousTarget = target;
|
previousTarget = printer.getCurrentTarget();
|
||||||
tickFlyingBlocks();
|
tickFlyingBlocks();
|
||||||
|
|
||||||
if (world.isRemote)
|
if (world.isRemote)
|
||||||
|
@ -355,7 +325,7 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
|
||||||
|
|
||||||
// Skip if not Active
|
// Skip if not Active
|
||||||
if (state == State.STOPPED) {
|
if (state == State.STOPPED) {
|
||||||
if (schematicLoaded)
|
if (printer.isLoaded())
|
||||||
resetPrinter();
|
resetPrinter();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -371,7 +341,7 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Initialize Printer
|
// Initialize Printer
|
||||||
if (!schematicLoaded) {
|
if (!printer.isLoaded()) {
|
||||||
initializePrinter(blueprint);
|
initializePrinter(blueprint);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -391,7 +361,6 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update Target
|
|
||||||
if (hasCreativeCrate) {
|
if (hasCreativeCrate) {
|
||||||
if (missingItem != null) {
|
if (missingItem != null) {
|
||||||
missingItem = null;
|
missingItem = null;
|
||||||
|
@ -399,23 +368,17 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update Target
|
||||||
if (missingItem == null && !positionNotLoaded) {
|
if (missingItem == null && !positionNotLoaded) {
|
||||||
do {
|
if (!printer.advanceCurrentPos()) {
|
||||||
advanceCurrentPos();
|
finishedPrinting();
|
||||||
if (state == State.STOPPED)
|
return;
|
||||||
return;
|
}
|
||||||
|
|
||||||
} while (!blockReader.getBounds()
|
|
||||||
.isVecInside(currentPos));
|
|
||||||
|
|
||||||
sendUpdate = true;
|
sendUpdate = true;
|
||||||
target = schematicAnchor.add(currentPos);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean entityMode = printStage == PrintStage.ENTITIES;
|
|
||||||
|
|
||||||
// Check block
|
// Check block
|
||||||
if (!getWorld().isAreaLoaded(target, 0)) {
|
if (!getWorld().isAreaLoaded(printer.getCurrentTarget(), 0)) {
|
||||||
positionNotLoaded = true;
|
positionNotLoaded = true;
|
||||||
statusMsg = "targetNotLoaded";
|
statusMsg = "targetNotLoaded";
|
||||||
state = State.PAUSED;
|
state = State.PAUSED;
|
||||||
|
@ -427,24 +390,9 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean shouldSkip = false;
|
// Get item requirement
|
||||||
BlockState blockState = Blocks.AIR.getDefaultState();
|
ItemRequirement requirement = printer.getCurrentRequirement();
|
||||||
TileEntity tileEntity = null;
|
if (requirement.isInvalid() || !printer.shouldPlaceCurrent(world, this::shouldPlace)) {
|
||||||
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()) {
|
|
||||||
statusMsg = "searching";
|
statusMsg = "searching";
|
||||||
blockSkipped = true;
|
blockSkipped = true;
|
||||||
return;
|
return;
|
||||||
|
@ -478,39 +426,16 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
|
||||||
|
|
||||||
// Success
|
// Success
|
||||||
state = State.RUNNING;
|
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;
|
ItemStack icon = requirement.isEmpty() || requiredItems.isEmpty() ? ItemStack.EMPTY : requiredItems.get(0).item;
|
||||||
if (entityMode)
|
printer.handleCurrentTarget((target, blockState, tile) -> {
|
||||||
launchEntity(target, icon, blockReader.getEntities()
|
// Launch block
|
||||||
.collect(Collectors.toList())
|
statusMsg = blockState.getBlock() != Blocks.AIR ? "placing" : "clearing";
|
||||||
.get(printingEntityIndex));
|
launchBlockOrBelt(target, icon, blockState, tile);
|
||||||
else if (AllBlocks.BELT.has(blockState)) {
|
}, (target, entity) -> {
|
||||||
TileEntity te = blockReader.getTileEntity(currentPos.add(schematicAnchor));
|
// Launch entity
|
||||||
blockState = stripBeltIfNotLast(blockState);
|
statusMsg = "placing";
|
||||||
if (te instanceof BeltTileEntity && AllBlocks.BELT.has(blockState))
|
launchEntity(target, icon, entity);
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
printerCooldown = config().schematicannonDelay.get();
|
printerCooldown = config().schematicannonDelay.get();
|
||||||
fuelLevel -= getFuelUsageRate();
|
fuelLevel -= getFuelUsageRate();
|
||||||
|
@ -518,35 +443,6 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
|
||||||
missingItem = null;
|
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() {
|
public double getFuelUsageRate() {
|
||||||
return hasCreativeCrate ? 0 : config().schematicannonFuelUsage.get() / 100f;
|
return hasCreativeCrate ? 0 : config().schematicannonFuelUsage.get() / 100f;
|
||||||
}
|
}
|
||||||
|
@ -568,40 +464,29 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load blocks into reader
|
// Load blocks into reader
|
||||||
Template activeTemplate = SchematicItem.loadSchematic(blueprint);
|
printer.loadSchematic(blueprint, world, true);
|
||||||
BlockPos anchor = NBTUtil.readBlockPos(blueprint.getTag()
|
|
||||||
.getCompound("Anchor"));
|
|
||||||
|
|
||||||
if (activeTemplate.getSize()
|
if (printer.isWorldEmpty()) {
|
||||||
.equals(BlockPos.ZERO)) {
|
|
||||||
state = State.STOPPED;
|
state = State.STOPPED;
|
||||||
statusMsg = "schematicExpired";
|
statusMsg = "schematicExpired";
|
||||||
inventory.setStackInSlot(0, ItemStack.EMPTY);
|
inventory.setStackInSlot(0, ItemStack.EMPTY);
|
||||||
inventory.setStackInSlot(1, new ItemStack(AllItems.EMPTY_SCHEMATIC.get()));
|
inventory.setStackInSlot(1, new ItemStack(AllItems.EMPTY_SCHEMATIC.get()));
|
||||||
|
printer.resetSchematic();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!anchor.withinDistance(getPos(), MAX_ANCHOR_DISTANCE)) {
|
if (!printer.getAnchor().withinDistance(getPos(), MAX_ANCHOR_DISTANCE)) {
|
||||||
state = State.STOPPED;
|
state = State.STOPPED;
|
||||||
statusMsg = "targetOutsideRange";
|
statusMsg = "targetOutsideRange";
|
||||||
|
printer.resetSchematic();
|
||||||
return;
|
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;
|
state = State.PAUSED;
|
||||||
statusMsg = "ready";
|
statusMsg = "ready";
|
||||||
printingEntityIndex = -1;
|
|
||||||
printStage = PrintStage.BLOCKS;
|
|
||||||
deferredBlocks.clear();
|
|
||||||
updateChecklist();
|
updateChecklist();
|
||||||
sendUpdate = true;
|
sendUpdate = true;
|
||||||
blocksToPlace += blocksPlaced;
|
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) {
|
protected ItemStack getItemForBlock(BlockState blockState) {
|
||||||
|
@ -679,57 +564,6 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
|
||||||
return success;
|
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() {
|
public void finishedPrinting() {
|
||||||
inventory.setStackInSlot(0, ItemStack.EMPTY);
|
inventory.setStackInSlot(0, ItemStack.EMPTY);
|
||||||
inventory.setStackInSlot(1, new ItemStack(AllItems.EMPTY_SCHEMATIC.get(), inventory.getStackInSlot(1)
|
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;
|
state = State.STOPPED;
|
||||||
statusMsg = "finished";
|
statusMsg = "finished";
|
||||||
resetPrinter();
|
resetPrinter();
|
||||||
target = getPos().add(1, 0, 0);
|
|
||||||
AllSoundEvents.SCHEMATICANNON_FINISH.playOnServer(world, pos);
|
AllSoundEvents.SCHEMATICANNON_FINISH.playOnServer(world, pos);
|
||||||
sendUpdate = true;
|
sendUpdate = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void resetPrinter() {
|
protected void resetPrinter() {
|
||||||
schematicLoaded = false;
|
printer.resetSchematic();
|
||||||
schematicAnchor = null;
|
|
||||||
currentPos = null;
|
|
||||||
blockReader = null;
|
|
||||||
missingItem = null;
|
missingItem = null;
|
||||||
sendUpdate = true;
|
sendUpdate = true;
|
||||||
printingEntityIndex = 0;
|
|
||||||
printStage = PrintStage.BLOCKS;
|
|
||||||
schematicProgress = 0;
|
schematicProgress = 0;
|
||||||
blocksPlaced = 0;
|
blocksPlaced = 0;
|
||||||
blocksToPlace = 0;
|
blocksToPlace = 0;
|
||||||
deferredBlocks.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean shouldPlace(BlockPos pos, BlockState state, TileEntity te) {
|
protected boolean shouldPlace(BlockPos pos, BlockState state, TileEntity te,
|
||||||
if (world == null)
|
BlockState toReplace, BlockState toReplaceOther, boolean isNormalCube) {
|
||||||
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;
|
|
||||||
if (pos.withinDistance(getPos(), 2f))
|
if (pos.withinDistance(getPos(), 2f))
|
||||||
return false;
|
return false;
|
||||||
if (!replaceTileEntities
|
if (!replaceTileEntities
|
||||||
&& (toReplace.hasTileEntity() || (toReplaceOther != null && toReplaceOther.hasTileEntity())))
|
&& (toReplace.hasTileEntity() || (toReplaceOther != null && toReplaceOther.hasTileEntity())))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (shouldIgnoreBlockState(state, te))
|
if (shouldIgnoreBlockState(state, te))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
boolean placingAir = state.getBlock().isAir(state, world, pos);
|
||||||
|
|
||||||
if (replaceMode == 3)
|
if (replaceMode == 3)
|
||||||
return true;
|
return true;
|
||||||
if (replaceMode == 2 && !placingAir)
|
if (replaceMode == 2 && !placingAir)
|
||||||
return true;
|
return true;
|
||||||
if (replaceMode == 1
|
if (replaceMode == 1
|
||||||
&& (state.isNormalCube(blockReader, pos.subtract(schematicAnchor)) || (!toReplace.isNormalCube(world, pos)
|
&& (isNormalCube || (!toReplace.isNormalCube(world, pos)
|
||||||
&& (toReplaceOther == null || !toReplaceOther.isNormalCube(world, pos))))
|
&& (toReplaceOther == null || !toReplaceOther.isNormalCube(world, pos))))
|
||||||
&& !placingAir)
|
&& !placingAir)
|
||||||
return true;
|
return true;
|
||||||
if (replaceMode == 0 && !toReplace.isNormalCube(world, pos)
|
if (replaceMode == 0 && !toReplace.isNormalCube(world, pos)
|
||||||
&& (toReplaceOther == null || !toReplaceOther.isNormalCube(world, pos)) && !placingAir)
|
&& (toReplaceOther == null || !toReplaceOther.isNormalCube(world, pos)) && !placingAir)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -874,7 +680,7 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!schematicLoaded) {
|
if (!printer.isLoaded()) {
|
||||||
if (!blueprint.isEmpty())
|
if (!blueprint.isEmpty())
|
||||||
initializePrinter(blueprint);
|
initializePrinter(blueprint);
|
||||||
return;
|
return;
|
||||||
|
@ -889,8 +695,7 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
|
||||||
dontUpdateChecklist = true;
|
dontUpdateChecklist = true;
|
||||||
inventory.extractItem(BookInput, 1, false);
|
inventory.extractItem(BookInput, 1, false);
|
||||||
ItemStack stack = checklist.createItem();
|
ItemStack stack = checklist.createItem();
|
||||||
stack.setCount(inventory.getStackInSlot(BookOutput)
|
stack.setCount(inventory.getStackInSlot(BookOutput).getCount() + 1);
|
||||||
.getCount() + 1);
|
|
||||||
inventory.setStackInSlot(BookOutput, stack);
|
inventory.setStackInSlot(BookOutput, stack);
|
||||||
sendUpdate = true;
|
sendUpdate = true;
|
||||||
return;
|
return;
|
||||||
|
@ -900,6 +705,58 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
|
||||||
sendUpdate = true;
|
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) {
|
protected void launchBelt(BlockPos target, BlockState state, int length) {
|
||||||
blocksPlaced++;
|
blocksPlaced++;
|
||||||
ItemStack connector = AllItems.BELT_CONNECTOR.asStack();
|
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) {
|
protected void launchBlock(BlockPos target, ItemStack stack, BlockState state, @Nullable CompoundNBT data) {
|
||||||
if (!state.getBlock()
|
if (!state.getBlock().isAir(state, world, target))
|
||||||
.isAir(state, world, target))
|
|
||||||
blocksPlaced++;
|
blocksPlaced++;
|
||||||
flyingBlocks.add(new LaunchedItem.ForBlockState(this.getPos(), target, stack, state, data));
|
flyingBlocks.add(new LaunchedItem.ForBlockState(this.getPos(), target, stack, state, data));
|
||||||
playFiringSound();
|
playFiringSound();
|
||||||
|
@ -945,37 +801,10 @@ public class SchematicannonTileEntity extends SmartTileEntity implements INamedC
|
||||||
checklist.damageRequired.clear();
|
checklist.damageRequired.clear();
|
||||||
checklist.blocksNotLoaded = false;
|
checklist.blocksNotLoaded = false;
|
||||||
|
|
||||||
if (schematicLoaded) {
|
if (printer.isLoaded()) {
|
||||||
blocksToPlace = blocksPlaced;
|
blocksToPlace = blocksPlaced;
|
||||||
for (BlockPos pos : blockReader.getAllPositions()) {
|
blocksToPlace += printer.markAllBlockRequirements(checklist, world, this::shouldPlace);
|
||||||
BlockPos relPos = pos.add(schematicAnchor);
|
printer.markAllEntityRequirements(checklist);
|
||||||
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);
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
}
|
||||||
checklist.gathered.clear();
|
checklist.gathered.clear();
|
||||||
findInventories();
|
findInventories();
|
||||||
|
|
|
@ -99,12 +99,13 @@ public class SchematicItem extends Item {
|
||||||
SchematicInstances.clearHash(blueprint);
|
SchematicInstances.clearHash(blueprint);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PlacementSettings getSettings(ItemStack blueprint) {
|
public static PlacementSettings getSettings(ItemStack blueprint, boolean processNBT) {
|
||||||
CompoundNBT tag = blueprint.getTag();
|
CompoundNBT tag = blueprint.getTag();
|
||||||
PlacementSettings settings = new PlacementSettings();
|
PlacementSettings settings = new PlacementSettings();
|
||||||
settings.setRotation(Rotation.valueOf(tag.getString("Rotation")));
|
settings.setRotation(Rotation.valueOf(tag.getString("Rotation")));
|
||||||
settings.setMirror(Mirror.valueOf(tag.getString("Mirror")));
|
settings.setMirror(Mirror.valueOf(tag.getString("Mirror")));
|
||||||
settings.addProcessor(SchematicProcessor.INSTANCE);
|
if (processNBT)
|
||||||
|
settings.addProcessor(SchematicProcessor.INSTANCE);
|
||||||
return settings;
|
return settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,14 +2,19 @@ package com.simibubi.create.content.schematics.packet;
|
||||||
|
|
||||||
import java.util.function.Supplier;
|
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.SchematicProcessor;
|
||||||
import com.simibubi.create.content.schematics.item.SchematicItem;
|
import com.simibubi.create.content.schematics.item.SchematicItem;
|
||||||
import com.simibubi.create.foundation.networking.SimplePacketBase;
|
import com.simibubi.create.foundation.networking.SimplePacketBase;
|
||||||
|
|
||||||
|
import com.simibubi.create.foundation.utility.BlockHelper;
|
||||||
|
|
||||||
import net.minecraft.entity.player.ServerPlayerEntity;
|
import net.minecraft.entity.player.ServerPlayerEntity;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.nbt.CompoundNBT;
|
||||||
import net.minecraft.nbt.NBTUtil;
|
import net.minecraft.nbt.NBTUtil;
|
||||||
import net.minecraft.network.PacketBuffer;
|
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.PlacementSettings;
|
||||||
import net.minecraft.world.gen.feature.template.Template;
|
import net.minecraft.world.gen.feature.template.Template;
|
||||||
import net.minecraftforge.fml.network.NetworkEvent.Context;
|
import net.minecraftforge.fml.network.NetworkEvent.Context;
|
||||||
|
@ -35,13 +40,22 @@ public class SchematicPlacePacket extends SimplePacketBase {
|
||||||
ServerPlayerEntity player = context.get().getSender();
|
ServerPlayerEntity player = context.get().getSender();
|
||||||
if (player == null)
|
if (player == null)
|
||||||
return;
|
return;
|
||||||
Template t = SchematicItem.loadSchematic(stack);
|
|
||||||
PlacementSettings settings = SchematicItem.getSettings(stack);
|
World world = player.getServerWorld();
|
||||||
if (player.canUseCommandBlock())
|
SchematicPrinter printer = new SchematicPrinter();
|
||||||
settings.func_215220_b(SchematicProcessor.INSTANCE); // remove processor
|
printer.loadSchematic(stack, world, !player.canUseCommandBlock());
|
||||||
settings.setIgnoreEntities(false);
|
|
||||||
t.place(player.getServerWorld(), NBTUtil.readBlockPos(stack.getTag().getCompound("Anchor")),
|
while(printer.advanceCurrentPos()) {
|
||||||
settings, player.getRNG());
|
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);
|
context.get().setPacketHandled(true);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue