Merge branch 'mc1.15/dev' into mc1.15/ponder-ui

This commit is contained in:
simibubi 2021-02-16 19:36:12 +01:00
commit fd99acc00a
41 changed files with 732 additions and 356 deletions

View file

@ -822,6 +822,12 @@
"create.gui.goggles.kinetic_stats": "Kinetic Stats:", "create.gui.goggles.kinetic_stats": "Kinetic Stats:",
"create.gui.goggles.at_current_speed": "at current speed", "create.gui.goggles.at_current_speed": "at current speed",
"create.gui.goggles.pole_length": "Pole Length:", "create.gui.goggles.pole_length": "Pole Length:",
"create.gui.assembly.exception": "This Contraption was unable to assemble:",
"create.gui.assembly.exception.unmovableBlock": "Unmovable Block (%4$s) at [%1$s %2$s %3$s]",
"create.gui.assembly.exception.chunkNotLoaded": "The Block at [%1$s %2$s %3$s] was not in a loaded chunk",
"create.gui.assembly.exception.structureTooLarge": "There are too many Blocks included in the contraption.\nThe configured maximum is: %1$s",
"create.gui.assembly.exception.tooManyPistonPoles": "There are too many extension Poles attached to this Piston.\nThe configured maximum is: %1$s",
"create.gui.assembly.exception.noPistonPoles": "The Piston is missing some extension Poles",
"create.gui.gauge.info_header": "Gauge Information:", "create.gui.gauge.info_header": "Gauge Information:",
"create.gui.speedometer.title": "Rotation Speed", "create.gui.speedometer.title": "Rotation Speed",
"create.gui.stressometer.title": "Network Stress", "create.gui.stressometer.title": "Network Stress",

View file

@ -823,6 +823,12 @@
"create.gui.goggles.kinetic_stats": "UNLOCALIZED: Kinetic Stats:", "create.gui.goggles.kinetic_stats": "UNLOCALIZED: Kinetic Stats:",
"create.gui.goggles.at_current_speed": "UNLOCALIZED: at current speed", "create.gui.goggles.at_current_speed": "UNLOCALIZED: at current speed",
"create.gui.goggles.pole_length": "UNLOCALIZED: Pole Length:", "create.gui.goggles.pole_length": "UNLOCALIZED: Pole Length:",
"create.gui.assembly.exception": "UNLOCALIZED: This Contraption was unable to assemble:",
"create.gui.assembly.exception.unmovableBlock": "UNLOCALIZED: Unmovable Block (%4$s) at [%1$s %2$s %3$s]",
"create.gui.assembly.exception.chunkNotLoaded": "UNLOCALIZED: The Block at [%1$s %2$s %3$s] was not in a loaded chunk",
"create.gui.assembly.exception.structureTooLarge": "UNLOCALIZED: There are too many Blocks included in the contraption.\nThe configured maximum is: %1$s",
"create.gui.assembly.exception.tooManyPistonPoles": "UNLOCALIZED: There are too many extension Poles attached to this Piston.\nThe configured maximum is: %1$s",
"create.gui.assembly.exception.noPistonPoles": "UNLOCALIZED: The Piston is missing some extension Poles",
"create.gui.gauge.info_header": "UNLOCALIZED: Gauge Information:", "create.gui.gauge.info_header": "UNLOCALIZED: Gauge Information:",
"create.gui.speedometer.title": "UNLOCALIZED: Rotation Speed", "create.gui.speedometer.title": "UNLOCALIZED: Rotation Speed",
"create.gui.stressometer.title": "UNLOCALIZED: Network Stress", "create.gui.stressometer.title": "UNLOCALIZED: Network Stress",

View file

@ -38,7 +38,7 @@ public abstract class GeneratingKineticTileEntity extends KineticTileEntity {
if (!(tileEntity instanceof KineticTileEntity)) if (!(tileEntity instanceof KineticTileEntity))
return; return;
KineticTileEntity sourceTe = (KineticTileEntity) tileEntity; KineticTileEntity sourceTe = (KineticTileEntity) tileEntity;
if (reActivateSource && sourceTe != null && Math.abs(sourceTe.getSpeed()) >= Math.abs(getGeneratedSpeed())) if (reActivateSource && Math.abs(sourceTe.getSpeed()) >= Math.abs(getGeneratedSpeed()))
reActivateSource = false; reActivateSource = false;
} }

View file

@ -0,0 +1,91 @@
package com.simibubi.create.content.contraptions.components.structureMovement;
import com.simibubi.create.foundation.config.AllConfigs;
import net.minecraft.block.BlockState;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.TranslationTextComponent;
public class AssemblyException extends Exception {
public final ITextComponent component;
private BlockPos position = null;
public static void write(CompoundNBT compound, AssemblyException exception) {
if (exception == null)
return;
CompoundNBT nbt = new CompoundNBT();
nbt.putString("Component", ITextComponent.Serializer.toJson(exception.component));
if (exception.hasPosition())
nbt.putLong("Position", exception.getPosition().toLong());
compound.put("LastException", nbt);
}
public static AssemblyException read(CompoundNBT compound) {
if (!compound.contains("LastException"))
return null;
CompoundNBT nbt = compound.getCompound("LastException");
String string = nbt.getString("Component");
AssemblyException exception = new AssemblyException(ITextComponent.Serializer.fromJson(string));
if (nbt.contains("Position"))
exception.position = BlockPos.fromLong(nbt.getLong("Position"));
return exception;
}
public AssemblyException(ITextComponent component) {
this.component = component;
}
public AssemblyException(String langKey, Object... objects) {
this(new TranslationTextComponent("create.gui.assembly.exception." + langKey, objects));
}
public static AssemblyException unmovableBlock(BlockPos pos, BlockState state) {
AssemblyException e = new AssemblyException("unmovableBlock",
pos.getX(),
pos.getY(),
pos.getZ(),
new TranslationTextComponent(state.getBlock().getTranslationKey()));
e.position = pos;
return e;
}
public static AssemblyException unloadedChunk(BlockPos pos) {
AssemblyException e = new AssemblyException("chunkNotLoaded",
pos.getX(),
pos.getY(),
pos.getZ());
e.position = pos;
return e;
}
public static AssemblyException structureTooLarge() {
return new AssemblyException("structureTooLarge",
AllConfigs.SERVER.kinetics.maxBlocksMoved.get());
}
public static AssemblyException tooManyPistonPoles() {
return new AssemblyException("tooManyPistonPoles",
AllConfigs.SERVER.kinetics.maxPistonPoles.get());
}
public static AssemblyException noPistonPoles() {
return new AssemblyException("noPistonPoles");
}
public String getFormattedText() {
return component.getFormattedText();
}
public boolean hasPosition() {
return position != null;
}
public BlockPos getPosition() {
return position;
}
}

View file

@ -53,8 +53,7 @@ import net.minecraft.world.World;
public class BlockMovementTraits { public class BlockMovementTraits {
public static boolean movementNecessary(World world, BlockPos pos) { public static boolean movementNecessary(BlockState state, World world, BlockPos pos) {
BlockState state = world.getBlockState(pos);
if (isBrittle(state)) if (isBrittle(state))
return true; return true;
if (state.getBlock() instanceof FenceGateBlock) if (state.getBlock() instanceof FenceGateBlock)
@ -68,18 +67,17 @@ public class BlockMovementTraits {
return true; return true;
} }
public static boolean movementAllowed(World world, BlockPos pos) { public static boolean movementAllowed(BlockState state, World world, BlockPos pos) {
BlockState blockState = world.getBlockState(pos); Block block = state.getBlock();
Block block = blockState.getBlock();
if (block instanceof AbstractChassisBlock) if (block instanceof AbstractChassisBlock)
return true; return true;
if (blockState.getBlockHardness(world, pos) == -1) if (state.getBlockHardness(world, pos) == -1)
return false; return false;
if (AllBlockTags.NON_MOVABLE.matches(blockState)) if (AllBlockTags.NON_MOVABLE.matches(state))
return false; return false;
// Move controllers only when they aren't moving // Move controllers only when they aren't moving
if (block instanceof MechanicalPistonBlock && blockState.get(MechanicalPistonBlock.STATE) != PistonState.MOVING) if (block instanceof MechanicalPistonBlock && state.get(MechanicalPistonBlock.STATE) != PistonState.MOVING)
return true; return true;
if (block instanceof MechanicalBearingBlock) { if (block instanceof MechanicalBearingBlock) {
TileEntity te = world.getTileEntity(pos); TileEntity te = world.getTileEntity(pos);
@ -97,11 +95,11 @@ public class BlockMovementTraits {
return !((PulleyTileEntity) te).running; return !((PulleyTileEntity) te).running;
} }
if (AllBlocks.BELT.has(blockState)) if (AllBlocks.BELT.has(state))
return true; return true;
if (blockState.getBlock() instanceof GrindstoneBlock) if (state.getBlock() instanceof GrindstoneBlock)
return true; return true;
return blockState.getPushReaction() != PushReaction.BLOCK; return state.getPushReaction() != PushReaction.BLOCK;
} }
/** /**

View file

@ -1,26 +1,5 @@
package com.simibubi.create.content.contraptions.components.structureMovement; package com.simibubi.create.content.contraptions.components.structureMovement;
import static com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.isExtensionPole;
import static com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.isPistonHead;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
import java.util.function.BiConsumer;
import java.util.stream.Collectors;
import javax.annotation.Nullable;
import org.apache.commons.lang3.tuple.MutablePair;
import org.apache.commons.lang3.tuple.Pair;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllMovementBehaviours; import com.simibubi.create.AllMovementBehaviours;
import com.simibubi.create.content.contraptions.base.IRotate; import com.simibubi.create.content.contraptions.base.IRotate;
@ -55,15 +34,7 @@ import com.simibubi.create.foundation.utility.NBTHelper;
import com.simibubi.create.foundation.utility.NBTProcessors; import com.simibubi.create.foundation.utility.NBTProcessors;
import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.foundation.utility.worldWrappers.WrappedWorld; import com.simibubi.create.foundation.utility.worldWrappers.WrappedWorld;
import net.minecraft.block.*;
import net.minecraft.block.AbstractButtonBlock;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.block.ChestBlock;
import net.minecraft.block.DoorBlock;
import net.minecraft.block.IWaterLoggable;
import net.minecraft.block.PressurePlateBlock;
import net.minecraft.block.material.PushReaction; import net.minecraft.block.material.PushReaction;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.fluid.Fluids; import net.minecraft.fluid.Fluids;
@ -96,6 +67,16 @@ import net.minecraftforge.fluids.capability.IFluidHandler.FluidAction;
import net.minecraftforge.fluids.capability.templates.FluidTank; import net.minecraftforge.fluids.capability.templates.FluidTank;
import net.minecraftforge.items.IItemHandlerModifiable; import net.minecraftforge.items.IItemHandlerModifiable;
import net.minecraftforge.items.wrapper.CombinedInvWrapper; import net.minecraftforge.items.wrapper.CombinedInvWrapper;
import org.apache.commons.lang3.tuple.MutablePair;
import org.apache.commons.lang3.tuple.Pair;
import javax.annotation.Nullable;
import java.util.*;
import java.util.function.BiConsumer;
import java.util.stream.Collectors;
import static com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.isExtensionPole;
import static com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.isPistonHead;
public abstract class Contraption { public abstract class Contraption {
@ -139,7 +120,7 @@ public abstract class Contraption {
stabilizedSubContraptions = new HashMap<>(); stabilizedSubContraptions = new HashMap<>();
} }
public abstract boolean assemble(World world, BlockPos pos); public abstract boolean assemble(World world, BlockPos pos) throws AssemblyException;
public abstract boolean canBeStabilized(Direction facing, BlockPos localPos); public abstract boolean canBeStabilized(Direction facing, BlockPos localPos);
@ -154,7 +135,7 @@ public abstract class Contraption {
} }
protected boolean addToInitialFrontier(World world, BlockPos pos, Direction forcedDirection, protected boolean addToInitialFrontier(World world, BlockPos pos, Direction forcedDirection,
List<BlockPos> frontier) { Queue<BlockPos> frontier) throws AssemblyException {
return true; return true;
} }
@ -165,9 +146,9 @@ public abstract class Contraption {
return contraption; return contraption;
} }
public boolean searchMovedStructure(World world, BlockPos pos, @Nullable Direction forcedDirection) { public boolean searchMovedStructure(World world, BlockPos pos, @Nullable Direction forcedDirection) throws AssemblyException {
initialPassengers.clear(); initialPassengers.clear();
List<BlockPos> frontier = new ArrayList<>(); Queue<BlockPos> frontier = new LinkedList<>();
Set<BlockPos> visited = new HashSet<>(); Set<BlockPos> visited = new HashSet<>();
anchor = pos; anchor = pos;
@ -181,10 +162,10 @@ public abstract class Contraption {
for (int limit = 100000; limit > 0; limit--) { for (int limit = 100000; limit > 0; limit--) {
if (frontier.isEmpty()) if (frontier.isEmpty())
return true; return true;
if (!moveBlock(world, frontier.remove(0), forcedDirection, frontier, visited)) if (!moveBlock(world, forcedDirection, frontier, visited))
return false; return false;
} }
return false; throw AssemblyException.structureTooLarge();
} }
public void onEntityCreated(AbstractContraptionEntity entity) { public void onEntityCreated(AbstractContraptionEntity entity) {
@ -196,8 +177,12 @@ public abstract class Contraption {
StabilizedContraption subContraption = new StabilizedContraption(face); StabilizedContraption subContraption = new StabilizedContraption(face);
World world = entity.world; World world = entity.world;
BlockPos pos = blockFace.getPos(); BlockPos pos = blockFace.getPos();
try {
if (!subContraption.assemble(world, pos)) if (!subContraption.assemble(world, pos))
continue; continue;
} catch (AssemblyException e) {
continue;
}
subContraption.removeBlocksFromWorld(world, BlockPos.ZERO); subContraption.removeBlocksFromWorld(world, BlockPos.ZERO);
OrientedContraptionEntity movedContraption = OrientedContraptionEntity movedContraption =
OrientedContraptionEntity.create(world, subContraption, Optional.of(face)); OrientedContraptionEntity.create(world, subContraption, Optional.of(face));
@ -247,20 +232,25 @@ public abstract class Contraption {
fluidStorage.forEach((pos, mfs) -> mfs.tick(entity, pos, world.isRemote)); fluidStorage.forEach((pos, mfs) -> mfs.tick(entity, pos, world.isRemote));
} }
protected boolean moveBlock(World world, BlockPos pos, @Nullable Direction forcedDirection, List<BlockPos> frontier, /** move the first block in frontier queue */
Set<BlockPos> visited) { protected boolean moveBlock(World world, @Nullable Direction forcedDirection, Queue<BlockPos> frontier,
visited.add(pos); Set<BlockPos> visited) throws AssemblyException {
frontier.remove(pos); BlockPos pos = frontier.poll();
if (pos == null)
if (!world.isBlockPresent(pos))
return false; return false;
visited.add(pos);
if (World.isOutsideBuildHeight(pos))
return true;
if (!world.isBlockPresent(pos))
throw AssemblyException.unloadedChunk(pos);
if (isAnchoringBlockAt(pos)) if (isAnchoringBlockAt(pos))
return true; return true;
if (!BlockMovementTraits.movementNecessary(world, pos))
return true;
if (!movementAllowed(world, pos))
return false;
BlockState state = world.getBlockState(pos); BlockState state = world.getBlockState(pos);
if (!BlockMovementTraits.movementNecessary(state, world, pos))
return true;
if (!movementAllowed(state, world, pos))
throw AssemblyException.unmovableBlock(pos, state);
if (state.getBlock() instanceof AbstractChassisBlock if (state.getBlock() instanceof AbstractChassisBlock
&& !moveChassis(world, pos, forcedDirection, frontier, visited)) && !moveChassis(world, pos, forcedDirection, frontier, visited))
return false; return false;
@ -306,9 +296,10 @@ public abstract class Contraption {
} }
// Cart assemblers attach themselves // Cart assemblers attach themselves
BlockState stateBelow = world.getBlockState(pos.down()); BlockPos posDown = pos.down();
if (!visited.contains(pos.down()) && AllBlocks.CART_ASSEMBLER.has(stateBelow)) BlockState stateBelow = world.getBlockState(posDown);
frontier.add(pos.down()); if (!visited.contains(posDown) && AllBlocks.CART_ASSEMBLER.has(stateBelow))
frontier.add(posDown);
Map<Direction, SuperGlueEntity> superglue = SuperGlueHandler.gatherGlue(world, pos); Map<Direction, SuperGlueEntity> superglue = SuperGlueHandler.gatherGlue(world, pos);
@ -318,9 +309,9 @@ public abstract class Contraption {
BlockState blockState = world.getBlockState(offsetPos); BlockState blockState = world.getBlockState(offsetPos);
if (isAnchoringBlockAt(offsetPos)) if (isAnchoringBlockAt(offsetPos))
continue; continue;
if (!movementAllowed(world, offsetPos)) { if (!movementAllowed(blockState, world, offsetPos)) {
if (offset == forcedDirection) if (offset == forcedDirection)
return false; throw AssemblyException.unmovableBlock(pos, state);
continue; continue;
} }
@ -349,10 +340,13 @@ public abstract class Contraption {
} }
addBlock(pos, capture(world, pos)); addBlock(pos, capture(world, pos));
return blocks.size() <= AllConfigs.SERVER.kinetics.maxBlocksMoved.get(); if (blocks.size() <= AllConfigs.SERVER.kinetics.maxBlocksMoved.get())
return true;
else
throw AssemblyException.structureTooLarge();
} }
protected void movePistonHead(World world, BlockPos pos, List<BlockPos> frontier, Set<BlockPos> visited, protected void movePistonHead(World world, BlockPos pos, Queue<BlockPos> frontier, Set<BlockPos> visited,
BlockState state) { BlockState state) {
Direction direction = state.get(MechanicalPistonHeadBlock.FACING); Direction direction = state.get(MechanicalPistonHeadBlock.FACING);
BlockPos offset = pos.offset(direction.getOpposite()); BlockPos offset = pos.offset(direction.getOpposite());
@ -374,7 +368,7 @@ public abstract class Contraption {
} }
} }
protected void movePistonPole(World world, BlockPos pos, List<BlockPos> frontier, Set<BlockPos> visited, protected void movePistonPole(World world, BlockPos pos, Queue<BlockPos> frontier, Set<BlockPos> visited,
BlockState state) { BlockState state) {
for (Direction d : Iterate.directionsInAxis(state.get(PistonExtensionPoleBlock.FACING) for (Direction d : Iterate.directionsInAxis(state.get(PistonExtensionPoleBlock.FACING)
.getAxis())) { .getAxis())) {
@ -397,7 +391,7 @@ public abstract class Contraption {
} }
} }
protected void moveGantryPinion(World world, BlockPos pos, List<BlockPos> frontier, Set<BlockPos> visited, protected void moveGantryPinion(World world, BlockPos pos, Queue<BlockPos> frontier, Set<BlockPos> visited,
BlockState state) { BlockState state) {
BlockPos offset = pos.offset(state.get(GantryPinionBlock.FACING)); BlockPos offset = pos.offset(state.get(GantryPinionBlock.FACING));
if (!visited.contains(offset)) if (!visited.contains(offset))
@ -413,7 +407,7 @@ public abstract class Contraption {
} }
} }
protected void moveGantryShaft(World world, BlockPos pos, List<BlockPos> frontier, Set<BlockPos> visited, protected void moveGantryShaft(World world, BlockPos pos, Queue<BlockPos> frontier, Set<BlockPos> visited,
BlockState state) { BlockState state) {
for (Direction d : Iterate.directions) { for (Direction d : Iterate.directions) {
BlockPos offset = pos.offset(d); BlockPos offset = pos.offset(d);
@ -429,7 +423,7 @@ public abstract class Contraption {
} }
} }
private void moveBearing(BlockPos pos, List<BlockPos> frontier, Set<BlockPos> visited, BlockState state) { private void moveBearing(BlockPos pos, Queue<BlockPos> frontier, Set<BlockPos> visited, BlockState state) {
Direction facing = state.get(MechanicalBearingBlock.FACING); Direction facing = state.get(MechanicalBearingBlock.FACING);
if (!canBeStabilized(facing, pos.subtract(anchor))) { if (!canBeStabilized(facing, pos.subtract(anchor))) {
BlockPos offset = pos.offset(facing); BlockPos offset = pos.offset(facing);
@ -440,7 +434,7 @@ public abstract class Contraption {
pendingSubContraptions.add(new BlockFace(pos, facing)); pendingSubContraptions.add(new BlockFace(pos, facing));
} }
private void moveBelt(BlockPos pos, List<BlockPos> frontier, Set<BlockPos> visited, BlockState state) { private void moveBelt(BlockPos pos, Queue<BlockPos> frontier, Set<BlockPos> visited, BlockState state) {
BlockPos nextPos = BeltBlock.nextSegmentPosition(state, pos, true); BlockPos nextPos = BeltBlock.nextSegmentPosition(state, pos, true);
BlockPos prevPos = BeltBlock.nextSegmentPosition(state, pos, false); BlockPos prevPos = BeltBlock.nextSegmentPosition(state, pos, false);
if (nextPos != null && !visited.contains(nextPos)) if (nextPos != null && !visited.contains(nextPos))
@ -461,7 +455,7 @@ public abstract class Contraption {
} }
} }
private void movePulley(World world, BlockPos pos, List<BlockPos> frontier, Set<BlockPos> visited) { private void movePulley(World world, BlockPos pos, Queue<BlockPos> frontier, Set<BlockPos> visited) {
int limit = AllConfigs.SERVER.kinetics.maxRopeLength.get(); int limit = AllConfigs.SERVER.kinetics.maxRopeLength.get();
BlockPos ropePos = pos; BlockPos ropePos = pos;
while (limit-- >= 0) { while (limit-- >= 0) {
@ -479,8 +473,8 @@ public abstract class Contraption {
} }
} }
private boolean moveMechanicalPiston(World world, BlockPos pos, List<BlockPos> frontier, Set<BlockPos> visited, private boolean moveMechanicalPiston(World world, BlockPos pos, Queue<BlockPos> frontier, Set<BlockPos> visited, BlockState state) throws AssemblyException {
BlockState state) { int limit = AllConfigs.SERVER.kinetics.maxPistonPoles.get();
Direction direction = state.get(MechanicalPistonBlock.FACING); Direction direction = state.get(MechanicalPistonBlock.FACING);
PistonState pistonState = state.get(MechanicalPistonBlock.STATE); PistonState pistonState = state.get(MechanicalPistonBlock.STATE);
if (pistonState == PistonState.MOVING) if (pistonState == PistonState.MOVING)
@ -503,7 +497,7 @@ public abstract class Contraption {
return true; return true;
} }
private boolean moveChassis(World world, BlockPos pos, Direction movementDirection, List<BlockPos> frontier, private boolean moveChassis(World world, BlockPos pos, Direction movementDirection, Queue<BlockPos> frontier,
Set<BlockPos> visited) { Set<BlockPos> visited) {
TileEntity te = world.getTileEntity(pos); TileEntity te = world.getTileEntity(pos);
if (!(te instanceof ChassisTileEntity)) if (!(te instanceof ChassisTileEntity))
@ -588,8 +582,8 @@ public abstract class Contraption {
return globalPos.subtract(anchor); return globalPos.subtract(anchor);
} }
protected boolean movementAllowed(World world, BlockPos pos) { protected boolean movementAllowed(BlockState state, World world, BlockPos pos) {
return BlockMovementTraits.movementAllowed(world, pos); return BlockMovementTraits.movementAllowed(state, world, pos);
} }
protected boolean isAnchoringBlockAt(BlockPos pos) { protected boolean isAnchoringBlockAt(BlockPos pos) {

View file

@ -0,0 +1,28 @@
package com.simibubi.create.content.contraptions.components.structureMovement;
import com.simibubi.create.content.contraptions.goggles.IHaveGoggleInformation;
import com.simibubi.create.foundation.utility.Lang;
import net.minecraft.util.text.TextFormatting;
import java.util.Arrays;
import java.util.List;
public interface IDisplayAssemblyExceptions {
default boolean addExceptionToTooltip(List<String> tooltip) {
AssemblyException e = getLastAssemblyException();
if (e == null)
return false;
if (!tooltip.isEmpty())
tooltip.add("");
tooltip.add(IHaveGoggleInformation.spacing + TextFormatting.GOLD + Lang.translate("gui.assembly.exception"));
String text = e.getFormattedText();
Arrays.stream(text.split("\n")).forEach(l -> tooltip.add(IHaveGoggleInformation.spacing + TextFormatting.GRAY + l));
return true;
}
AssemblyException getLastAssemblyException();
}

View file

@ -4,6 +4,7 @@ import org.apache.commons.lang3.tuple.Pair;
import com.simibubi.create.AllTags.AllBlockTags; import com.simibubi.create.AllTags.AllBlockTags;
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionType; import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionType;
import com.simibubi.create.content.contraptions.components.structureMovement.AssemblyException;
import com.simibubi.create.content.contraptions.components.structureMovement.Contraption; import com.simibubi.create.content.contraptions.components.structureMovement.Contraption;
import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.CompoundNBT;
@ -28,7 +29,7 @@ public class BearingContraption extends Contraption {
} }
@Override @Override
public boolean assemble(World world, BlockPos pos) { public boolean assemble(World world, BlockPos pos) throws AssemblyException {
BlockPos offset = pos.offset(facing); BlockPos offset = pos.offset(facing);
if (!searchMovedStructure(world, offset, null)) if (!searchMovedStructure(world, offset, null))
return false; return false;

View file

@ -1,12 +1,10 @@
package com.simibubi.create.content.contraptions.components.structureMovement.bearing; package com.simibubi.create.content.contraptions.components.structureMovement.bearing;
import java.util.List;
import org.apache.commons.lang3.tuple.Pair;
import com.simibubi.create.content.contraptions.base.KineticTileEntity; import com.simibubi.create.content.contraptions.base.KineticTileEntity;
import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity; import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity;
import com.simibubi.create.content.contraptions.components.structureMovement.AssemblyException;
import com.simibubi.create.content.contraptions.components.structureMovement.ControlledContraptionEntity; import com.simibubi.create.content.contraptions.components.structureMovement.ControlledContraptionEntity;
import com.simibubi.create.content.contraptions.components.structureMovement.IDisplayAssemblyExceptions;
import com.simibubi.create.content.contraptions.components.structureMovement.bearing.ClockworkContraption.HandType; import com.simibubi.create.content.contraptions.components.structureMovement.bearing.ClockworkContraption.HandType;
import com.simibubi.create.foundation.advancement.AllTriggers; import com.simibubi.create.foundation.advancement.AllTriggers;
import com.simibubi.create.foundation.gui.AllIcons; import com.simibubi.create.foundation.gui.AllIcons;
@ -16,7 +14,6 @@ import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.ScrollOpt
import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.AngleHelper;
import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.foundation.utility.ServerSpeedProvider; import com.simibubi.create.foundation.utility.ServerSpeedProvider;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.CompoundNBT;
import net.minecraft.state.properties.BlockStateProperties; import net.minecraft.state.properties.BlockStateProperties;
@ -25,8 +22,11 @@ import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis; import net.minecraft.util.Direction.Axis;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.MathHelper;
import org.apache.commons.lang3.tuple.Pair;
public class ClockworkBearingTileEntity extends KineticTileEntity implements IBearingTileEntity { import java.util.List;
public class ClockworkBearingTileEntity extends KineticTileEntity implements IBearingTileEntity, IDisplayAssemblyExceptions {
protected ControlledContraptionEntity hourHand; protected ControlledContraptionEntity hourHand;
protected ControlledContraptionEntity minuteHand; protected ControlledContraptionEntity minuteHand;
@ -37,6 +37,7 @@ public class ClockworkBearingTileEntity extends KineticTileEntity implements IBe
protected boolean running; protected boolean running;
protected boolean assembleNextTick; protected boolean assembleNextTick;
protected AssemblyException lastException;
protected ScrollOptionBehaviour<ClockHands> operationMode; protected ScrollOptionBehaviour<ClockHands> operationMode;
@ -105,6 +106,11 @@ public class ClockworkBearingTileEntity extends KineticTileEntity implements IBe
applyRotations(); applyRotations();
} }
@Override
public AssemblyException getLastAssemblyException() {
return lastException;
}
protected void applyRotations() { protected void applyRotations() {
BlockState blockState = getBlockState(); BlockState blockState = getBlockState();
Axis axis = Axis.X; Axis axis = Axis.X;
@ -199,8 +205,15 @@ public class ClockworkBearingTileEntity extends KineticTileEntity implements IBe
Direction direction = getBlockState().get(BlockStateProperties.FACING); Direction direction = getBlockState().get(BlockStateProperties.FACING);
// Collect Construct // Collect Construct
Pair<ClockworkContraption, ClockworkContraption> contraption = Pair<ClockworkContraption, ClockworkContraption> contraption;
ClockworkContraption.assembleClockworkAt(world, pos, direction); try {
contraption = ClockworkContraption.assembleClockworkAt(world, pos, direction);
lastException = null;
} catch (AssemblyException e) {
lastException = e;
sendData();
return;
}
if (contraption == null) if (contraption == null)
return; return;
if (contraption.getLeft() == null) if (contraption.getLeft() == null)
@ -284,6 +297,7 @@ public class ClockworkBearingTileEntity extends KineticTileEntity implements IBe
compound.putBoolean("Running", running); compound.putBoolean("Running", running);
compound.putFloat("HourAngle", hourAngle); compound.putFloat("HourAngle", hourAngle);
compound.putFloat("MinuteAngle", minuteAngle); compound.putFloat("MinuteAngle", minuteAngle);
AssemblyException.write(compound, lastException);
super.write(compound, clientPacket); super.write(compound, clientPacket);
} }
@ -295,6 +309,7 @@ public class ClockworkBearingTileEntity extends KineticTileEntity implements IBe
running = compound.getBoolean("Running"); running = compound.getBoolean("Running");
hourAngle = compound.getFloat("HourAngle"); hourAngle = compound.getFloat("HourAngle");
minuteAngle = compound.getFloat("MinuteAngle"); minuteAngle = compound.getFloat("MinuteAngle");
lastException = AssemblyException.read(compound);
super.read(compound, clientPacket); super.read(compound, clientPacket);
if (!clientPacket) if (!clientPacket)

View file

@ -7,13 +7,18 @@ import java.util.Set;
import org.apache.commons.lang3.tuple.Pair; import org.apache.commons.lang3.tuple.Pair;
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionType; import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionType;
import com.simibubi.create.content.contraptions.components.structureMovement.AssemblyException;
import com.simibubi.create.content.contraptions.components.structureMovement.Contraption; import com.simibubi.create.content.contraptions.components.structureMovement.Contraption;
import com.simibubi.create.foundation.utility.NBTHelper; import com.simibubi.create.foundation.utility.NBTHelper;
import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.CompoundNBT;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World; import net.minecraft.world.World;
import org.apache.commons.lang3.tuple.Pair;
import java.util.HashSet;
import java.util.Queue;
import java.util.Set;
public class ClockworkContraption extends Contraption { public class ClockworkContraption extends Contraption {
@ -38,7 +43,7 @@ public class ClockworkContraption extends Contraption {
} }
public static Pair<ClockworkContraption, ClockworkContraption> assembleClockworkAt(World world, BlockPos pos, public static Pair<ClockworkContraption, ClockworkContraption> assembleClockworkAt(World world, BlockPos pos,
Direction direction) { Direction direction) throws AssemblyException {
int hourArmBlocks = 0; int hourArmBlocks = 0;
ClockworkContraption hourArm = new ClockworkContraption(); ClockworkContraption hourArm = new ClockworkContraption();
@ -81,21 +86,23 @@ public class ClockworkContraption extends Contraption {
} }
@Override @Override
public boolean assemble(World world, BlockPos pos) { public boolean assemble(World world, BlockPos pos) throws AssemblyException {
return searchMovedStructure(world, pos, facing); return searchMovedStructure(world, pos, facing);
} }
@Override @Override
public boolean searchMovedStructure(World world, BlockPos pos, Direction direction) { public boolean searchMovedStructure(World world, BlockPos pos, Direction direction) throws AssemblyException {
return super.searchMovedStructure(world, pos.offset(direction, offset + 1), null); return super.searchMovedStructure(world, pos.offset(direction, offset + 1), null);
} }
@Override @Override
protected boolean moveBlock(World world, BlockPos pos, Direction direction, List<BlockPos> frontier, protected boolean moveBlock(World world, Direction direction, Queue<BlockPos> frontier,
Set<BlockPos> visited) { Set<BlockPos> visited) throws AssemblyException {
if (ignoreBlocks.contains(pos)) if (ignoreBlocks.contains(frontier.peek())) {
frontier.poll();
return true; return true;
return super.moveBlock(world, pos, direction, frontier, visited); }
return super.moveBlock(world, direction, frontier, visited);
} }
@Override @Override

View file

@ -1,12 +1,10 @@
package com.simibubi.create.content.contraptions.components.structureMovement.bearing; package com.simibubi.create.content.contraptions.components.structureMovement.bearing;
import static net.minecraft.state.properties.BlockStateProperties.FACING;
import java.util.List;
import com.simibubi.create.content.contraptions.base.GeneratingKineticTileEntity; import com.simibubi.create.content.contraptions.base.GeneratingKineticTileEntity;
import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity; import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity;
import com.simibubi.create.content.contraptions.components.structureMovement.AssemblyException;
import com.simibubi.create.content.contraptions.components.structureMovement.ControlledContraptionEntity; import com.simibubi.create.content.contraptions.components.structureMovement.ControlledContraptionEntity;
import com.simibubi.create.content.contraptions.components.structureMovement.IDisplayAssemblyExceptions;
import com.simibubi.create.foundation.advancement.AllTriggers; import com.simibubi.create.foundation.advancement.AllTriggers;
import com.simibubi.create.foundation.item.TooltipHelper; import com.simibubi.create.foundation.item.TooltipHelper;
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
@ -14,7 +12,6 @@ import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.ScrollOpt
import com.simibubi.create.foundation.utility.AngleHelper; import com.simibubi.create.foundation.utility.AngleHelper;
import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.foundation.utility.ServerSpeedProvider; import com.simibubi.create.foundation.utility.ServerSpeedProvider;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.CompoundNBT;
import net.minecraft.state.properties.BlockStateProperties; import net.minecraft.state.properties.BlockStateProperties;
@ -23,7 +20,11 @@ import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.MathHelper;
public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity implements IBearingTileEntity { import java.util.List;
import static net.minecraft.state.properties.BlockStateProperties.FACING;
public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity implements IBearingTileEntity, IDisplayAssemblyExceptions {
protected ScrollOptionBehaviour<RotationMode> movementMode; protected ScrollOptionBehaviour<RotationMode> movementMode;
protected ControlledContraptionEntity movedContraption; protected ControlledContraptionEntity movedContraption;
@ -31,6 +32,7 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity imp
protected boolean running; protected boolean running;
protected boolean assembleNextTick; protected boolean assembleNextTick;
protected float clientAngleDiff; protected float clientAngleDiff;
protected AssemblyException lastException;
public MechanicalBearingTileEntity(TileEntityType<? extends MechanicalBearingTileEntity> type) { public MechanicalBearingTileEntity(TileEntityType<? extends MechanicalBearingTileEntity> type) {
super(type); super(type);
@ -62,6 +64,7 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity imp
public void write(CompoundNBT compound, boolean clientPacket) { public void write(CompoundNBT compound, boolean clientPacket) {
compound.putBoolean("Running", running); compound.putBoolean("Running", running);
compound.putFloat("Angle", angle); compound.putFloat("Angle", angle);
AssemblyException.write(compound, lastException);
super.write(compound, clientPacket); super.write(compound, clientPacket);
} }
@ -70,6 +73,7 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity imp
float angleBefore = angle; float angleBefore = angle;
running = compound.getBoolean("Running"); running = compound.getBoolean("Running");
angle = compound.getFloat("Angle"); angle = compound.getFloat("Angle");
lastException = AssemblyException.read(compound);
super.read(compound, clientPacket); super.read(compound, clientPacket);
if (!clientPacket) if (!clientPacket)
return; return;
@ -104,6 +108,11 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity imp
return speed; return speed;
} }
@Override
public AssemblyException getLastAssemblyException() {
return lastException;
}
protected boolean isWindmill() { protected boolean isWindmill() {
return false; return false;
} }
@ -120,9 +129,17 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity imp
Direction direction = getBlockState().get(FACING); Direction direction = getBlockState().get(FACING);
BearingContraption contraption = new BearingContraption(isWindmill(), direction); BearingContraption contraption = new BearingContraption(isWindmill(), direction);
try {
if (!contraption.assemble(world, pos)) if (!contraption.assemble(world, pos))
return; return;
lastException = null;
} catch (AssemblyException e) {
lastException = e;
sendData();
return;
}
if (isWindmill()) if (isWindmill())
AllTriggers.triggerForNearbyPlayers(AllTriggers.WINDMILL, world, pos, 5); AllTriggers.triggerForNearbyPlayers(AllTriggers.WINDMILL, world, pos, 5);
if (contraption.getSailBlocks() >= 16 * 8) if (contraption.getSailBlocks() >= 16 * 8)
@ -281,5 +298,4 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity imp
TooltipHelper.addHint(tooltip, "hint.empty_bearing"); TooltipHelper.addHint(tooltip, "hint.empty_bearing");
return true; return true;
} }
} }

View file

@ -64,16 +64,9 @@ public class SailBlock extends ProperDirectionalBlock {
public ActionResultType onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockRayTraceResult ray) { public ActionResultType onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockRayTraceResult ray) {
ItemStack heldItem = player.getHeldItem(hand); ItemStack heldItem = player.getHeldItem(hand);
if (AllBlocks.SAIL.isIn(heldItem) || AllBlocks.SAIL_FRAME.isIn(heldItem)) {
IPlacementHelper placementHelper = PlacementHelpers.get(placementHelperId); IPlacementHelper placementHelper = PlacementHelpers.get(placementHelperId);
PlacementOffset offset = placementHelper.getOffset(world, state, pos, ray); if (placementHelper.matchesItem(heldItem))
return placementHelper.getOffset(world, state, pos, ray).placeInWorld(world, (BlockItem) heldItem.getItem(), player, hand, ray);
if (!offset.isReplaceable(world))
return ActionResultType.PASS;
offset.placeInWorld(world, ((BlockItem) heldItem.getItem()).getBlock().getDefaultState(), player, heldItem);
return ActionResultType.SUCCESS;
}
if (heldItem.getItem() instanceof ShearsItem) { if (heldItem.getItem() instanceof ShearsItem) {
if (!world.isRemote) if (!world.isRemote)

View file

@ -1,6 +1,7 @@
package com.simibubi.create.content.contraptions.components.structureMovement.bearing; package com.simibubi.create.content.contraptions.components.structureMovement.bearing;
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionType; import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionType;
import com.simibubi.create.content.contraptions.components.structureMovement.AssemblyException;
import com.simibubi.create.content.contraptions.components.structureMovement.Contraption; import com.simibubi.create.content.contraptions.components.structureMovement.Contraption;
import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.CompoundNBT;
@ -20,7 +21,7 @@ public class StabilizedContraption extends Contraption {
} }
@Override @Override
public boolean assemble(World world, BlockPos pos) { public boolean assemble(World world, BlockPos pos) throws AssemblyException {
BlockPos offset = pos.offset(facing); BlockPos offset = pos.offset(facing);
if (!searchMovedStructure(world, offset, null)) if (!searchMovedStructure(world, offset, null))
return false; return false;

View file

@ -7,6 +7,7 @@ import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Queue;
import java.util.Set; import java.util.Set;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
@ -76,12 +77,12 @@ public class ChassisTileEntity extends SmartTileEntity {
} }
public List<ChassisTileEntity> collectChassisGroup() { public List<ChassisTileEntity> collectChassisGroup() {
List<BlockPos> frontier = new ArrayList<>(); Queue<BlockPos> frontier = new LinkedList<>();
List<ChassisTileEntity> collected = new ArrayList<>(); List<ChassisTileEntity> collected = new ArrayList<>();
Set<BlockPos> visited = new HashSet<>(); Set<BlockPos> visited = new HashSet<>();
frontier.add(pos); frontier.add(pos);
while (!frontier.isEmpty()) { while (!frontier.isEmpty()) {
BlockPos current = frontier.remove(0); BlockPos current = frontier.poll();
if (visited.contains(current)) if (visited.contains(current))
continue; continue;
visited.add(current); visited.add(current);
@ -96,7 +97,7 @@ public class ChassisTileEntity extends SmartTileEntity {
return collected; return collected;
} }
public boolean addAttachedChasses(List<BlockPos> frontier, Set<BlockPos> visited) { public boolean addAttachedChasses(Queue<BlockPos> frontier, Set<BlockPos> visited) {
BlockState state = getBlockState(); BlockState state = getBlockState();
if (!(state.getBlock() instanceof AbstractChassisBlock)) if (!(state.getBlock() instanceof AbstractChassisBlock))
return false; return false;
@ -166,7 +167,7 @@ public class ChassisTileEntity extends SmartTileEntity {
break; break;
// Ignore replaceable Blocks and Air-like // Ignore replaceable Blocks and Air-like
if (!BlockMovementTraits.movementNecessary(world, current)) if (!BlockMovementTraits.movementNecessary(currentState, world, current))
break; break;
if (BlockMovementTraits.isBrittle(currentState)) if (BlockMovementTraits.isBrittle(currentState))
break; break;
@ -207,7 +208,7 @@ public class ChassisTileEntity extends SmartTileEntity {
continue; continue;
if (!searchPos.withinDistance(pos, chassisRange + .5f)) if (!searchPos.withinDistance(pos, chassisRange + .5f))
continue; continue;
if (!BlockMovementTraits.movementNecessary(world, searchPos)) if (!BlockMovementTraits.movementNecessary(searchedState, world, searchPos))
continue; continue;
if (BlockMovementTraits.isBrittle(searchedState)) if (BlockMovementTraits.isBrittle(searchedState))
continue; continue;

View file

@ -1,9 +1,9 @@
package com.simibubi.create.content.contraptions.components.structureMovement.gantry; package com.simibubi.create.content.contraptions.components.structureMovement.gantry;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.content.contraptions.components.structureMovement.AssemblyException;
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionType; import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionType;
import com.simibubi.create.content.contraptions.components.structureMovement.TranslatingContraption; import com.simibubi.create.content.contraptions.components.structureMovement.TranslatingContraption;
import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.CompoundNBT;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
@ -21,7 +21,7 @@ public class GantryContraption extends TranslatingContraption {
} }
@Override @Override
public boolean assemble(World world, BlockPos pos) { public boolean assemble(World world, BlockPos pos) throws AssemblyException {
if (!searchMovedStructure(world, pos, null)) if (!searchMovedStructure(world, pos, null))
return false; return false;
startMoving(world); startMoving(world);

View file

@ -1,23 +1,26 @@
package com.simibubi.create.content.contraptions.components.structureMovement.gantry; package com.simibubi.create.content.contraptions.components.structureMovement.gantry;
import static net.minecraft.state.properties.BlockStateProperties.FACING;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.content.contraptions.base.KineticTileEntity; import com.simibubi.create.content.contraptions.base.KineticTileEntity;
import com.simibubi.create.content.contraptions.components.structureMovement.AssemblyException;
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionCollider; import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionCollider;
import com.simibubi.create.content.contraptions.components.structureMovement.IDisplayAssemblyExceptions;
import com.simibubi.create.content.contraptions.relays.advanced.GantryShaftBlock; import com.simibubi.create.content.contraptions.relays.advanced.GantryShaftBlock;
import com.simibubi.create.content.contraptions.relays.advanced.GantryShaftTileEntity; import com.simibubi.create.content.contraptions.relays.advanced.GantryShaftTileEntity;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntity;
import net.minecraft.tileentity.TileEntityType; import net.minecraft.tileentity.TileEntityType;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis; import net.minecraft.util.Direction.Axis;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
public class GantryPinionTileEntity extends KineticTileEntity { import static net.minecraft.state.properties.BlockStateProperties.FACING;
public class GantryPinionTileEntity extends KineticTileEntity implements IDisplayAssemblyExceptions {
boolean assembleNextTick; boolean assembleNextTick;
protected AssemblyException lastException;
public GantryPinionTileEntity(TileEntityType<?> typeIn) { public GantryPinionTileEntity(TileEntityType<?> typeIn) {
super(typeIn); super(typeIn);
@ -50,6 +53,11 @@ public class GantryPinionTileEntity extends KineticTileEntity {
} }
} }
@Override
public AssemblyException getLastAssemblyException() {
return lastException;
}
private void tryAssemble() { private void tryAssemble() {
BlockState blockState = getBlockState(); BlockState blockState = getBlockState();
if (!(blockState.getBlock() instanceof GantryPinionBlock)) if (!(blockState.getBlock() instanceof GantryPinionBlock))
@ -71,8 +79,17 @@ public class GantryPinionTileEntity extends KineticTileEntity {
if (pinionMovementSpeed < 0) if (pinionMovementSpeed < 0)
movementDirection = movementDirection.getOpposite(); movementDirection = movementDirection.getOpposite();
try {
lastException = null;
if (!contraption.assemble(world, pos)) if (!contraption.assemble(world, pos))
return; return;
sendData();
} catch (AssemblyException e) {
lastException = e;
sendData();
return;
}
if (ContraptionCollider.isCollidingWithWorld(world, contraption, pos.offset(movementDirection), if (ContraptionCollider.isCollidingWithWorld(world, contraption, pos.offset(movementDirection),
movementDirection)) movementDirection))
return; return;
@ -85,6 +102,18 @@ public class GantryPinionTileEntity extends KineticTileEntity {
world.addEntity(movedContraption); world.addEntity(movedContraption);
} }
@Override
protected void write(CompoundNBT compound, boolean clientPacket) {
AssemblyException.write(compound, lastException);
super.write(compound, clientPacket);
}
@Override
protected void read(CompoundNBT compound, boolean clientPacket) {
lastException = AssemblyException.read(compound);
super.read(compound, clientPacket);
}
@Override @Override
public float propagateRotationTo(KineticTileEntity target, BlockState stateFrom, BlockState stateTo, BlockPos diff, public float propagateRotationTo(KineticTileEntity target, BlockState stateFrom, BlockState stateTo, BlockPos diff,
boolean connectedViaAxes, boolean connectedViaCogs) { boolean connectedViaAxes, boolean connectedViaCogs) {

View file

@ -180,7 +180,7 @@ public class SuperGlueEntity extends Entity implements IEntityAdditionalSpawnDat
BlockState state = world.getBlockState(pos); BlockState state = world.getBlockState(pos);
if (BlockMovementTraits.isBlockAttachedTowards(world, pos, state, direction)) if (BlockMovementTraits.isBlockAttachedTowards(world, pos, state, direction))
return true; return true;
if (!BlockMovementTraits.movementNecessary(world, pos)) if (!BlockMovementTraits.movementNecessary(state, world, pos))
return false; return false;
if (BlockMovementTraits.notSupportive(state, direction)) if (BlockMovementTraits.notSupportive(state, direction))
return false; return false;

View file

@ -1,13 +1,9 @@
package com.simibubi.create.content.contraptions.components.structureMovement.glue; package com.simibubi.create.content.contraptions.components.structureMovement.glue;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.simibubi.create.AllItems; import com.simibubi.create.AllItems;
import com.simibubi.create.foundation.networking.AllPackets; import com.simibubi.create.foundation.networking.AllPackets;
import com.simibubi.create.foundation.utility.placement.IPlacementHelper;
import com.simibubi.create.foundation.utility.worldWrappers.RayTraceWorld; import com.simibubi.create.foundation.utility.worldWrappers.RayTraceWorld;
import net.minecraft.block.Blocks; import net.minecraft.block.Blocks;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType; import net.minecraft.entity.EntityType;
@ -15,12 +11,8 @@ import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.CompoundNBT;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;
import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.*;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.util.math.RayTraceContext;
import net.minecraft.util.math.RayTraceResult.Type; import net.minecraft.util.math.RayTraceResult.Type;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.IWorld; import net.minecraft.world.IWorld;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraftforge.event.world.BlockEvent.EntityPlaceEvent; import net.minecraftforge.event.world.BlockEvent.EntityPlaceEvent;
@ -28,6 +20,10 @@ import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod.EventBusSubscriber; import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
import net.minecraftforge.fml.network.PacketDistributor; import net.minecraftforge.fml.network.PacketDistributor;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@EventBusSubscriber @EventBusSubscriber
public class SuperGlueHandler { public class SuperGlueHandler {
@ -65,6 +61,8 @@ public class SuperGlueHandler {
return; return;
if (AllItems.WRENCH.isIn(placer.getHeldItemMainhand())) if (AllItems.WRENCH.isIn(placer.getHeldItemMainhand()))
return; return;
if (event.getPlacedAgainst() == IPlacementHelper.ID)
return;
double distance = placer.getAttribute(PlayerEntity.REACH_DISTANCE) double distance = placer.getAttribute(PlayerEntity.REACH_DISTANCE)
.getValue(); .getValue();

View file

@ -3,6 +3,7 @@ package com.simibubi.create.content.contraptions.components.structureMovement.mo
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllShapes; import com.simibubi.create.AllShapes;
import com.simibubi.create.AllTileEntities; import com.simibubi.create.AllTileEntities;
import com.simibubi.create.content.contraptions.components.structureMovement.AssemblyException;
import com.simibubi.create.content.contraptions.components.structureMovement.OrientedContraptionEntity; import com.simibubi.create.content.contraptions.components.structureMovement.OrientedContraptionEntity;
import com.simibubi.create.content.contraptions.components.structureMovement.mounted.CartAssemblerTileEntity.CartMovementMode; import com.simibubi.create.content.contraptions.components.structureMovement.mounted.CartAssemblerTileEntity.CartMovementMode;
import com.simibubi.create.content.contraptions.components.structureMovement.train.CouplingHandler; import com.simibubi.create.content.contraptions.components.structureMovement.train.CouplingHandler;
@ -229,14 +230,28 @@ public class CartAssemblerBlock extends AbstractRailBlock
.isCoupledThroughContraption()) .isCoupledThroughContraption())
return; return;
CartMovementMode mode =
getTileEntityOptional(world, pos).map(te -> CartMovementMode.values()[te.movementMode.value]) Optional<CartAssemblerTileEntity> assembler = getTileEntityOptional(world, pos);
CartMovementMode mode = assembler.map(te -> CartMovementMode.values()[te.movementMode.value])
.orElse(CartMovementMode.ROTATE); .orElse(CartMovementMode.ROTATE);
MountedContraption contraption = new MountedContraption(mode); MountedContraption contraption = new MountedContraption(mode);
try {
if (!contraption.assemble(world, pos)) if (!contraption.assemble(world, pos))
return; return;
assembler.ifPresent(te -> {
te.lastException = null;
te.sendData();
});
} catch (AssemblyException e) {
assembler.ifPresent(te -> {
te.lastException = e;
te.sendData();
});
return;
}
boolean couplingFound = contraption.connectedCart != null; boolean couplingFound = contraption.connectedCart != null;
Optional<Direction> initialOrientation = cart.getMotion() Optional<Direction> initialOrientation = cart.getMotion()
.length() < 1 / 512f ? Optional.empty() : Optional.of(cart.getAdjustedHorizontalFacing()); .length() < 1 / 512f ? Optional.empty() : Optional.of(cart.getAdjustedHorizontalFacing());

View file

@ -1,7 +1,7 @@
package com.simibubi.create.content.contraptions.components.structureMovement.mounted; package com.simibubi.create.content.contraptions.components.structureMovement.mounted;
import java.util.List; import com.simibubi.create.content.contraptions.components.structureMovement.AssemblyException;
import com.simibubi.create.content.contraptions.components.structureMovement.IDisplayAssemblyExceptions;
import com.simibubi.create.foundation.gui.AllIcons; import com.simibubi.create.foundation.gui.AllIcons;
import com.simibubi.create.foundation.tileEntity.SmartTileEntity; import com.simibubi.create.foundation.tileEntity.SmartTileEntity;
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
@ -11,17 +11,20 @@ import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.INamedIco
import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.ScrollOptionBehaviour; import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.ScrollOptionBehaviour;
import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.foundation.utility.VecHelper;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.state.properties.RailShape; import net.minecraft.state.properties.RailShape;
import net.minecraft.tileentity.TileEntityType; import net.minecraft.tileentity.TileEntityType;
import net.minecraft.util.Direction.Axis; import net.minecraft.util.Direction.Axis;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
public class CartAssemblerTileEntity extends SmartTileEntity { import java.util.List;
public class CartAssemblerTileEntity extends SmartTileEntity implements IDisplayAssemblyExceptions {
private static final int assemblyCooldown = 8; private static final int assemblyCooldown = 8;
protected ScrollOptionBehaviour<CartMovementMode> movementMode; protected ScrollOptionBehaviour<CartMovementMode> movementMode;
private int ticksSinceMinecartUpdate; private int ticksSinceMinecartUpdate;
protected AssemblyException lastException;
public CartAssemblerTileEntity(TileEntityType<? extends CartAssemblerTileEntity> type) { public CartAssemblerTileEntity(TileEntityType<? extends CartAssemblerTileEntity> type) {
super(type); super(type);
@ -44,6 +47,23 @@ public class CartAssemblerTileEntity extends SmartTileEntity {
behaviours.add(movementMode); behaviours.add(movementMode);
} }
@Override
public void write(CompoundNBT compound, boolean clientPacket) {
AssemblyException.write(compound, lastException);
super.write(compound, clientPacket);
}
@Override
protected void read(CompoundNBT compound, boolean clientPacket) {
lastException = AssemblyException.read(compound);
super.read(compound, clientPacket);
}
@Override
public AssemblyException getLastAssemblyException() {
return lastException;
}
protected ValueBoxTransform getMovementModeSlot() { protected ValueBoxTransform getMovementModeSlot() {
return new CartAssemblerValueBoxTransform(); return new CartAssemblerValueBoxTransform();
} }
@ -103,5 +123,4 @@ public class CartAssemblerTileEntity extends SmartTileEntity {
public boolean isMinecartUpdateValid() { public boolean isMinecartUpdateValid() {
return ticksSinceMinecartUpdate >= assemblyCooldown; return ticksSinceMinecartUpdate >= assemblyCooldown;
} }
} }

View file

@ -2,12 +2,13 @@ package com.simibubi.create.content.contraptions.components.structureMovement.mo
import static com.simibubi.create.content.contraptions.components.structureMovement.mounted.CartAssemblerBlock.RAIL_SHAPE; import static com.simibubi.create.content.contraptions.components.structureMovement.mounted.CartAssemblerBlock.RAIL_SHAPE;
import java.util.List; import java.util.Queue;
import org.apache.commons.lang3.tuple.Pair; import org.apache.commons.lang3.tuple.Pair;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionType; import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionType;
import com.simibubi.create.content.contraptions.components.structureMovement.AssemblyException;
import com.simibubi.create.content.contraptions.components.structureMovement.Contraption; import com.simibubi.create.content.contraptions.components.structureMovement.Contraption;
import com.simibubi.create.content.contraptions.components.structureMovement.mounted.CartAssemblerTileEntity.CartMovementMode; import com.simibubi.create.content.contraptions.components.structureMovement.mounted.CartAssemblerTileEntity.CartMovementMode;
import com.simibubi.create.foundation.utility.Iterate; import com.simibubi.create.foundation.utility.Iterate;
@ -52,7 +53,7 @@ public class MountedContraption extends Contraption {
} }
@Override @Override
public boolean assemble(World world, BlockPos pos) { public boolean assemble(World world, BlockPos pos) throws AssemblyException {
BlockState state = world.getBlockState(pos); BlockState state = world.getBlockState(pos);
if (!state.has(RAIL_SHAPE)) if (!state.has(RAIL_SHAPE))
return false; return false;
@ -70,7 +71,7 @@ public class MountedContraption extends Contraption {
} }
@Override @Override
protected boolean addToInitialFrontier(World world, BlockPos pos, Direction direction, List<BlockPos> frontier) { protected boolean addToInitialFrontier(World world, BlockPos pos, Direction direction, Queue<BlockPos> frontier) {
frontier.clear(); frontier.clear();
frontier.add(pos.up()); frontier.add(pos.up());
return true; return true;
@ -104,11 +105,10 @@ public class MountedContraption extends Contraption {
} }
@Override @Override
protected boolean movementAllowed(World world, BlockPos pos) { protected boolean movementAllowed(BlockState state, World world, BlockPos pos) {
BlockState blockState = world.getBlockState(pos); if (!pos.equals(anchor) && AllBlocks.CART_ASSEMBLER.has(state))
if (!pos.equals(anchor) && AllBlocks.CART_ASSEMBLER.has(blockState)) return testSecondaryCartAssembler(world, state, pos);
return testSecondaryCartAssembler(world, blockState, pos); return super.movementAllowed(state, world, pos);
return super.movementAllowed(world, pos);
} }
protected boolean testSecondaryCartAssembler(World world, BlockState state, BlockPos pos) { protected boolean testSecondaryCartAssembler(World world, BlockState state, BlockPos pos) {

View file

@ -1,24 +1,21 @@
package com.simibubi.create.content.contraptions.components.structureMovement.piston; package com.simibubi.create.content.contraptions.components.structureMovement.piston;
import java.util.List;
import com.simibubi.create.content.contraptions.base.KineticTileEntity; import com.simibubi.create.content.contraptions.base.KineticTileEntity;
import com.simibubi.create.content.contraptions.components.structureMovement.AbstractContraptionEntity; import com.simibubi.create.content.contraptions.components.structureMovement.*;
import com.simibubi.create.content.contraptions.components.structureMovement.ControlledContraptionEntity;
import com.simibubi.create.content.contraptions.components.structureMovement.IControlContraption;
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour; import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
import com.simibubi.create.foundation.tileEntity.behaviour.ValueBoxTransform; import com.simibubi.create.foundation.tileEntity.behaviour.ValueBoxTransform;
import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.ScrollOptionBehaviour; import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.ScrollOptionBehaviour;
import com.simibubi.create.foundation.utility.Lang; import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.foundation.utility.ServerSpeedProvider; import com.simibubi.create.foundation.utility.ServerSpeedProvider;
import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.CompoundNBT;
import net.minecraft.tileentity.TileEntityType; import net.minecraft.tileentity.TileEntityType;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
public abstract class LinearActuatorTileEntity extends KineticTileEntity implements IControlContraption { import java.util.List;
public abstract class LinearActuatorTileEntity extends KineticTileEntity implements IControlContraption, IDisplayAssemblyExceptions {
public float offset; public float offset;
public boolean running; public boolean running;
@ -27,6 +24,7 @@ public abstract class LinearActuatorTileEntity extends KineticTileEntity impleme
protected boolean forceMove; protected boolean forceMove;
protected ScrollOptionBehaviour<MovementMode> movementMode; protected ScrollOptionBehaviour<MovementMode> movementMode;
protected boolean waitingForSpeedChange; protected boolean waitingForSpeedChange;
protected AssemblyException lastException;
// Custom position sync // Custom position sync
protected float clientOffsetDiff; protected float clientOffsetDiff;
@ -80,7 +78,13 @@ public abstract class LinearActuatorTileEntity extends KineticTileEntity impleme
return; return;
} else { } else {
if (getSpeed() != 0) if (getSpeed() != 0)
try {
assemble(); assemble();
lastException = null;
} catch (AssemblyException e) {
lastException = e;
}
sendData();
} }
return; return;
} }
@ -153,6 +157,7 @@ public abstract class LinearActuatorTileEntity extends KineticTileEntity impleme
compound.putBoolean("Running", running); compound.putBoolean("Running", running);
compound.putBoolean("Waiting", waitingForSpeedChange); compound.putBoolean("Waiting", waitingForSpeedChange);
compound.putFloat("Offset", offset); compound.putFloat("Offset", offset);
AssemblyException.write(compound, lastException);
super.write(compound, clientPacket); super.write(compound, clientPacket);
if (clientPacket && forceMove) { if (clientPacket && forceMove) {
@ -169,6 +174,7 @@ public abstract class LinearActuatorTileEntity extends KineticTileEntity impleme
running = compound.getBoolean("Running"); running = compound.getBoolean("Running");
waitingForSpeedChange = compound.getBoolean("Waiting"); waitingForSpeedChange = compound.getBoolean("Waiting");
offset = compound.getFloat("Offset"); offset = compound.getFloat("Offset");
lastException = AssemblyException.read(compound);
super.read(compound, clientPacket); super.read(compound, clientPacket);
if (!clientPacket) if (!clientPacket)
@ -183,9 +189,14 @@ public abstract class LinearActuatorTileEntity extends KineticTileEntity impleme
movedContraption = null; movedContraption = null;
} }
@Override
public AssemblyException getLastAssemblyException() {
return lastException;
}
public abstract void disassemble(); public abstract void disassemble();
protected abstract void assemble(); protected abstract void assemble() throws AssemblyException;
protected abstract int getExtensionRange(); protected abstract int getExtensionRange();
@ -288,5 +299,4 @@ public abstract class LinearActuatorTileEntity extends KineticTileEntity impleme
public BlockPos getBlockPosition() { public BlockPos getBlockPosition() {
return pos; return pos;
} }
} }

View file

@ -2,6 +2,7 @@ package com.simibubi.create.content.contraptions.components.structureMovement.pi
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.content.contraptions.base.IRotate; import com.simibubi.create.content.contraptions.base.IRotate;
import com.simibubi.create.content.contraptions.components.structureMovement.AssemblyException;
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionCollider; import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionCollider;
import com.simibubi.create.content.contraptions.components.structureMovement.ControlledContraptionEntity; import com.simibubi.create.content.contraptions.components.structureMovement.ControlledContraptionEntity;
import com.simibubi.create.content.contraptions.components.structureMovement.DirectionalExtenderScrollOptionSlot; import com.simibubi.create.content.contraptions.components.structureMovement.DirectionalExtenderScrollOptionSlot;
@ -41,7 +42,7 @@ public class MechanicalPistonTileEntity extends LinearActuatorTileEntity {
} }
@Override @Override
public void assemble() { public void assemble() throws AssemblyException {
if (!(world.getBlockState(pos) if (!(world.getBlockState(pos)
.getBlock() instanceof MechanicalPistonBlock)) .getBlock() instanceof MechanicalPistonBlock))
return; return;

View file

@ -1,7 +1,8 @@
package com.simibubi.create.content.contraptions.components.structureMovement.piston; package com.simibubi.create.content.contraptions.components.structureMovement.piston;
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionType; import com.simibubi.create.content.contraptions.components.structureMovement.AssemblyException;
import com.simibubi.create.content.contraptions.components.structureMovement.BlockMovementTraits; import com.simibubi.create.content.contraptions.components.structureMovement.BlockMovementTraits;
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionType;
import com.simibubi.create.content.contraptions.components.structureMovement.TranslatingContraption; import com.simibubi.create.content.contraptions.components.structureMovement.TranslatingContraption;
import com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.*; import com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.*;
import com.simibubi.create.foundation.config.AllConfigs; import com.simibubi.create.foundation.config.AllConfigs;
@ -23,6 +24,7 @@ import org.apache.commons.lang3.tuple.Pair;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Queue;
import static com.simibubi.create.AllBlocks.MECHANICAL_PISTON_HEAD; import static com.simibubi.create.AllBlocks.MECHANICAL_PISTON_HEAD;
import static com.simibubi.create.AllBlocks.PISTON_EXTENSION_POLE; import static com.simibubi.create.AllBlocks.PISTON_EXTENSION_POLE;
@ -51,7 +53,7 @@ public class PistonContraption extends TranslatingContraption {
} }
@Override @Override
public boolean assemble(World world, BlockPos pos) { public boolean assemble(World world, BlockPos pos) throws AssemblyException {
if (!collectExtensions(world, pos, orientation)) if (!collectExtensions(world, pos, orientation))
return false; return false;
int count = blocks.size(); int count = blocks.size();
@ -66,7 +68,7 @@ public class PistonContraption extends TranslatingContraption {
return true; return true;
} }
private boolean collectExtensions(World world, BlockPos pos, Direction direction) { private boolean collectExtensions(World world, BlockPos pos, Direction direction) throws AssemblyException {
List<BlockInfo> poles = new ArrayList<>(); List<BlockInfo> poles = new ArrayList<>();
BlockPos actualStart = pos; BlockPos actualStart = pos;
BlockState nextBlock = world.getBlockState(actualStart.offset(direction)); BlockState nextBlock = world.getBlockState(actualStart.offset(direction));
@ -89,7 +91,7 @@ public class PistonContraption extends TranslatingContraption {
nextBlock = world.getBlockState(actualStart.offset(direction)); nextBlock = world.getBlockState(actualStart.offset(direction));
if (extensionsInFront > MechanicalPistonBlock.maxAllowedPistonPoles()) if (extensionsInFront > MechanicalPistonBlock.maxAllowedPistonPoles())
return false; throw AssemblyException.tooManyPistonPoles();
} }
} }
@ -112,7 +114,7 @@ public class PistonContraption extends TranslatingContraption {
nextBlock = world.getBlockState(end.offset(direction.getOpposite())); nextBlock = world.getBlockState(end.offset(direction.getOpposite()));
if (extensionsInFront + extensionsInBack > MechanicalPistonBlock.maxAllowedPistonPoles()) if (extensionsInFront + extensionsInBack > MechanicalPistonBlock.maxAllowedPistonPoles())
return false; throw AssemblyException.tooManyPistonPoles();
} }
anchor = pos.offset(direction, initialExtensionProgress + 1); anchor = pos.offset(direction, initialExtensionProgress + 1);
@ -124,7 +126,7 @@ public class PistonContraption extends TranslatingContraption {
1, 1); 1, 1);
if (extensionLength == 0) if (extensionLength == 0)
return false; throw AssemblyException.noPistonPoles();
bounds = new AxisAlignedBB(0, 0, 0, 0, 0, 0); bounds = new AxisAlignedBB(0, 0, 0, 0, 0, 0);
@ -144,7 +146,7 @@ public class PistonContraption extends TranslatingContraption {
} }
@Override @Override
protected boolean addToInitialFrontier(World world, BlockPos pos, Direction direction, List<BlockPos> frontier) { protected boolean addToInitialFrontier(World world, BlockPos pos, Direction direction, Queue<BlockPos> frontier) throws AssemblyException {
frontier.clear(); frontier.clear();
boolean sticky = isStickyPiston(world.getBlockState(pos.offset(orientation, -1))); boolean sticky = isStickyPiston(world.getBlockState(pos.offset(orientation, -1)));
boolean retracting = direction != orientation; boolean retracting = direction != orientation;
@ -154,17 +156,22 @@ public class PistonContraption extends TranslatingContraption {
if (offset == 1 && retracting) if (offset == 1 && retracting)
return true; return true;
BlockPos currentPos = pos.offset(orientation, offset + initialExtensionProgress); BlockPos currentPos = pos.offset(orientation, offset + initialExtensionProgress);
if (!world.isBlockPresent(currentPos)) if (retracting && World.isOutsideBuildHeight(currentPos))
return false;
if (!BlockMovementTraits.movementNecessary(world, currentPos))
return true; return true;
if (!world.isBlockPresent(currentPos))
throw AssemblyException.unloadedChunk(currentPos);
BlockState state = world.getBlockState(currentPos); BlockState state = world.getBlockState(currentPos);
if (!BlockMovementTraits.movementNecessary(state, world, currentPos))
return true;
if (BlockMovementTraits.isBrittle(state) && !(state.getBlock() instanceof CarpetBlock)) if (BlockMovementTraits.isBrittle(state) && !(state.getBlock() instanceof CarpetBlock))
return true; return true;
if (isPistonHead(state) && state.get(FACING) == direction.getOpposite()) if (isPistonHead(state) && state.get(FACING) == direction.getOpposite())
return true; return true;
if (!BlockMovementTraits.movementAllowed(world, currentPos)) if (!BlockMovementTraits.movementAllowed(state, world, currentPos))
return retracting; if (retracting)
return true;
else
throw AssemblyException.unmovableBlock(currentPos, state);
if (retracting && state.getPushReaction() == PushReaction.PUSH_ONLY) if (retracting && state.getPushReaction() == PushReaction.PUSH_ONLY)
return true; return true;
frontier.add(currentPos); frontier.add(currentPos);

View file

@ -7,7 +7,6 @@ import com.simibubi.create.content.contraptions.wrench.IWrenchable;
import com.simibubi.create.foundation.block.ProperDirectionalBlock; import com.simibubi.create.foundation.block.ProperDirectionalBlock;
import com.simibubi.create.foundation.utility.placement.IPlacementHelper; import com.simibubi.create.foundation.utility.placement.IPlacementHelper;
import com.simibubi.create.foundation.utility.placement.PlacementHelpers; import com.simibubi.create.foundation.utility.placement.PlacementHelpers;
import com.simibubi.create.foundation.utility.placement.PlacementOffset;
import com.simibubi.create.foundation.utility.placement.util.PoleHelper; import com.simibubi.create.foundation.utility.placement.util.PoleHelper;
import mcp.MethodsReturnNonnullByDefault; import mcp.MethodsReturnNonnullByDefault;
import net.minecraft.block.Block; import net.minecraft.block.Block;
@ -17,6 +16,7 @@ import net.minecraft.block.material.PushReaction;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.fluid.Fluids; import net.minecraft.fluid.Fluids;
import net.minecraft.fluid.IFluidState; import net.minecraft.fluid.IFluidState;
import net.minecraft.item.BlockItem;
import net.minecraft.item.BlockItemUseContext; import net.minecraft.item.BlockItemUseContext;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.state.StateContainer.Builder; import net.minecraft.state.StateContainer.Builder;
@ -114,26 +114,9 @@ public class PistonExtensionPoleBlock extends ProperDirectionalBlock implements
public ActionResultType onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockRayTraceResult ray) { public ActionResultType onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockRayTraceResult ray) {
ItemStack heldItem = player.getHeldItem(hand); ItemStack heldItem = player.getHeldItem(hand);
if (AllBlocks.PISTON_EXTENSION_POLE.isIn(heldItem) && !player.isSneaking()) {
IPlacementHelper placementHelper = PlacementHelpers.get(placementHelperId); IPlacementHelper placementHelper = PlacementHelpers.get(placementHelperId);
PlacementOffset offset = placementHelper.getOffset(world, state, pos, ray); if (placementHelper.matchesItem(heldItem) && !player.isSneaking())
return placementHelper.getOffset(world, state, pos, ray).placeInWorld(world, (BlockItem) heldItem.getItem(), player, hand, ray);
if (!offset.isReplaceable(world))
return ActionResultType.PASS;
offset.placeInWorld(world, AllBlocks.PISTON_EXTENSION_POLE.getDefaultState(), player, heldItem);
/*BlockPos newPos = new BlockPos(offset.getPos());
if (world.isRemote)
return ActionResultType.SUCCESS;
world.setBlockState(newPos, offset.getTransform().apply(AllBlocks.PISTON_EXTENSION_POLE.getDefaultState()));
if (!player.isCreative())
heldItem.shrink(1);*/
return ActionResultType.SUCCESS;
}
return ActionResultType.PASS; return ActionResultType.PASS;
} }

View file

@ -1,5 +1,6 @@
package com.simibubi.create.content.contraptions.components.structureMovement.pulley; package com.simibubi.create.content.contraptions.components.structureMovement.pulley;
import com.simibubi.create.content.contraptions.components.structureMovement.AssemblyException;
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionType; import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionType;
import com.simibubi.create.content.contraptions.components.structureMovement.TranslatingContraption; import com.simibubi.create.content.contraptions.components.structureMovement.TranslatingContraption;
@ -23,7 +24,7 @@ public class PulleyContraption extends TranslatingContraption {
} }
@Override @Override
public boolean assemble(World world, BlockPos pos) { public boolean assemble(World world, BlockPos pos) throws AssemblyException {
if (!searchMovedStructure(world, pos, null)) if (!searchMovedStructure(world, pos, null))
return false; return false;
startMoving(world); startMoving(world);

View file

@ -1,6 +1,7 @@
package com.simibubi.create.content.contraptions.components.structureMovement.pulley; package com.simibubi.create.content.contraptions.components.structureMovement.pulley;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.content.contraptions.components.structureMovement.AssemblyException;
import com.simibubi.create.content.contraptions.components.structureMovement.BlockMovementTraits; import com.simibubi.create.content.contraptions.components.structureMovement.BlockMovementTraits;
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionCollider; import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionCollider;
import com.simibubi.create.content.contraptions.components.structureMovement.ControlledContraptionEntity; import com.simibubi.create.content.contraptions.components.structureMovement.ControlledContraptionEntity;
@ -8,7 +9,6 @@ import com.simibubi.create.content.contraptions.components.structureMovement.pis
import com.simibubi.create.foundation.config.AllConfigs; import com.simibubi.create.foundation.config.AllConfigs;
import com.simibubi.create.foundation.tileEntity.behaviour.CenteredSideValueBoxTransform; import com.simibubi.create.foundation.tileEntity.behaviour.CenteredSideValueBoxTransform;
import com.simibubi.create.foundation.tileEntity.behaviour.ValueBoxTransform; import com.simibubi.create.foundation.tileEntity.behaviour.ValueBoxTransform;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks; import net.minecraft.block.Blocks;
import net.minecraft.block.IWaterLoggable; import net.minecraft.block.IWaterLoggable;
@ -42,7 +42,7 @@ public class PulleyTileEntity extends LinearActuatorTileEntity {
} }
@Override @Override
protected void assemble() { protected void assemble() throws AssemblyException {
if (!(world.getBlockState(pos) if (!(world.getBlockState(pos)
.getBlock() instanceof PulleyBlock)) .getBlock() instanceof PulleyBlock))
return; return;
@ -176,9 +176,10 @@ public class PulleyTileEntity extends LinearActuatorTileEntity {
return; return;
BlockPos posBelow = pos.down((int) (offset + getMovementSpeed()) + 1); BlockPos posBelow = pos.down((int) (offset + getMovementSpeed()) + 1);
if (!BlockMovementTraits.movementNecessary(world, posBelow)) BlockState state = world.getBlockState(posBelow);
if (!BlockMovementTraits.movementNecessary(state, world, posBelow))
return; return;
if (BlockMovementTraits.isBrittle(world.getBlockState(posBelow))) if (BlockMovementTraits.isBrittle(state))
return; return;
disassemble(); disassemble();

View file

@ -4,6 +4,7 @@ import com.mojang.blaze3d.systems.RenderSystem;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllItems; import com.simibubi.create.AllItems;
import com.simibubi.create.CreateClient; import com.simibubi.create.CreateClient;
import com.simibubi.create.content.contraptions.components.structureMovement.IDisplayAssemblyExceptions;
import com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock; import com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock;
import com.simibubi.create.content.contraptions.components.structureMovement.piston.PistonExtensionPoleBlock; import com.simibubi.create.content.contraptions.components.structureMovement.piston.PistonExtensionPoleBlock;
import com.simibubi.create.foundation.config.AllConfigs; import com.simibubi.create.foundation.config.AllConfigs;
@ -92,6 +93,14 @@ public class GoggleOverlayRenderer {
tooltip.remove(tooltip.size() - 1); tooltip.remove(tooltip.size() - 1);
} }
if (te instanceof IDisplayAssemblyExceptions) {
boolean exceptionAdded = ((IDisplayAssemblyExceptions) te).addExceptionToTooltip(tooltip);
if (exceptionAdded) {
hasHoveringInformation = true;
hoverAddedInformation = true;
}
}
// break early if goggle or hover returned false when present // break early if goggle or hover returned false when present
if ((hasGoggleInformation && !goggleAddedInformation) && (hasHoveringInformation && !hoverAddedInformation)) if ((hasGoggleInformation && !goggleAddedInformation) && (hasHoveringInformation && !hoverAddedInformation))
return; return;

View file

@ -9,13 +9,13 @@ import java.util.List;
public interface IHaveGoggleInformation { public interface IHaveGoggleInformation {
DecimalFormat decimalFormat = new DecimalFormat("#.##"); DecimalFormat decimalFormat = new DecimalFormat("#.##");
public static String spacing = " "; String spacing = " ";
/** /**
* this method will be called when looking at a TileEntity that implemented this interface * this method will be called when looking at a TileEntity that implemented this interface
* *
* @return {{@code true}} if the tooltip creation was successful and should be displayed, * @return {@code true} if the tooltip creation was successful and should be displayed,
* or {{@code false}} if the overlay should not be displayed * or {@code false} if the overlay should not be displayed
* */ * */
default boolean addToGoggleTooltip(List<String> tooltip, boolean isPlayerSneaking){ default boolean addToGoggleTooltip(List<String> tooltip, boolean isPlayerSneaking){
return false; return false;

View file

@ -1,9 +1,5 @@
package com.simibubi.create.content.contraptions.relays.advanced; package com.simibubi.create.content.contraptions.relays.advanced;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllShapes; import com.simibubi.create.AllShapes;
import com.simibubi.create.AllTileEntities; import com.simibubi.create.AllTileEntities;
@ -15,7 +11,6 @@ import com.simibubi.create.foundation.utility.placement.IPlacementHelper;
import com.simibubi.create.foundation.utility.placement.PlacementHelpers; import com.simibubi.create.foundation.utility.placement.PlacementHelpers;
import com.simibubi.create.foundation.utility.placement.PlacementOffset; import com.simibubi.create.foundation.utility.placement.PlacementOffset;
import com.simibubi.create.foundation.utility.placement.util.PoleHelper; import com.simibubi.create.foundation.utility.placement.util.PoleHelper;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.BlockRenderType; import net.minecraft.block.BlockRenderType;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
@ -44,6 +39,10 @@ import net.minecraft.world.IWorld;
import net.minecraft.world.IWorldReader; import net.minecraft.world.IWorldReader;
import net.minecraft.world.World; import net.minecraft.world.World;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;
public class GantryShaftBlock extends DirectionalKineticBlock { public class GantryShaftBlock extends DirectionalKineticBlock {
public static final IProperty<Part> PART = EnumProperty.create("part", Part.class); public static final IProperty<Part> PART = EnumProperty.create("part", Part.class);
@ -66,22 +65,14 @@ public class GantryShaftBlock extends DirectionalKineticBlock {
} }
@Override @Override
public ActionResultType onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, public ActionResultType onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockRayTraceResult ray) {
BlockRayTraceResult ray) {
ItemStack heldItem = player.getHeldItem(hand); ItemStack heldItem = player.getHeldItem(hand);
IPlacementHelper placementHelper = PlacementHelpers.get(placementHelperId); IPlacementHelper placementHelper = PlacementHelpers.get(placementHelperId);
if (!placementHelper.matchesItem(heldItem)) if (!placementHelper.matchesItem(heldItem))
return ActionResultType.PASS; return ActionResultType.PASS;
PlacementOffset offset = placementHelper.getOffset(world, state, pos, ray); return placementHelper.getOffset(world, state, pos, ray).placeInWorld(world, ((BlockItem) heldItem.getItem()), player, hand, ray);
if (!offset.isReplaceable(world))
return ActionResultType.PASS;
offset.placeInWorld(world, ((BlockItem) heldItem.getItem()).getBlock()
.getDefaultState(), player, heldItem);
return ActionResultType.SUCCESS;
} }
@Override @Override

View file

@ -1,7 +1,5 @@
package com.simibubi.create.content.contraptions.relays.advanced; package com.simibubi.create.content.contraptions.relays.advanced;
import java.util.function.Predicate;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllShapes; import com.simibubi.create.AllShapes;
import com.simibubi.create.AllTileEntities; import com.simibubi.create.AllTileEntities;
@ -13,11 +11,11 @@ import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.foundation.utility.placement.IPlacementHelper; import com.simibubi.create.foundation.utility.placement.IPlacementHelper;
import com.simibubi.create.foundation.utility.placement.PlacementHelpers; import com.simibubi.create.foundation.utility.placement.PlacementHelpers;
import com.simibubi.create.foundation.utility.placement.PlacementOffset; import com.simibubi.create.foundation.utility.placement.PlacementOffset;
import mcp.MethodsReturnNonnullByDefault; import mcp.MethodsReturnNonnullByDefault;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.BlockItem;
import net.minecraft.item.BlockItemUseContext; import net.minecraft.item.BlockItemUseContext;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntity;
@ -32,6 +30,8 @@ import net.minecraft.util.math.shapes.VoxelShape;
import net.minecraft.world.IBlockReader; import net.minecraft.world.IBlockReader;
import net.minecraft.world.World; import net.minecraft.world.World;
import java.util.function.Predicate;
public class SpeedControllerBlock extends HorizontalAxisKineticBlock implements ITE<SpeedControllerTileEntity> { public class SpeedControllerBlock extends HorizontalAxisKineticBlock implements ITE<SpeedControllerTileEntity> {
private static final int placementHelperId = PlacementHelpers.register(new PlacementHelper()); private static final int placementHelperId = PlacementHelpers.register(new PlacementHelper());
@ -67,19 +67,10 @@ public class SpeedControllerBlock extends HorizontalAxisKineticBlock implements
public ActionResultType onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, public ActionResultType onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand,
BlockRayTraceResult ray) { BlockRayTraceResult ray) {
IPlacementHelper helper = PlacementHelpers.get(placementHelperId);
ItemStack heldItem = player.getHeldItem(hand); ItemStack heldItem = player.getHeldItem(hand);
if (helper.matchesItem(heldItem)) { IPlacementHelper helper = PlacementHelpers.get(placementHelperId);
PlacementOffset offset = helper.getOffset(world, state, pos, ray); if (helper.matchesItem(heldItem))
return helper.getOffset(world, state, pos, ray).placeInWorld(world, (BlockItem) heldItem.getItem(), player, hand, ray);
if (!offset.isReplaceable(world))
return ActionResultType.PASS;
offset.placeInWorld(world, AllBlocks.LARGE_COGWHEEL.getDefaultState(), player, heldItem);
return ActionResultType.SUCCESS;
}
return ActionResultType.PASS; return ActionResultType.PASS;
} }

View file

@ -1,10 +1,5 @@
package com.simibubi.create.content.contraptions.relays.elementary; package com.simibubi.create.content.contraptions.relays.elementary;
import static com.simibubi.create.content.contraptions.base.RotatedPillarKineticBlock.AXIS;
import java.util.List;
import java.util.function.Predicate;
import com.simibubi.create.AllBlocks; import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllShapes; import com.simibubi.create.AllShapes;
import com.simibubi.create.content.contraptions.base.DirectionalKineticBlock; import com.simibubi.create.content.contraptions.base.DirectionalKineticBlock;
@ -16,13 +11,13 @@ import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.foundation.utility.placement.IPlacementHelper; import com.simibubi.create.foundation.utility.placement.IPlacementHelper;
import com.simibubi.create.foundation.utility.placement.PlacementHelpers; import com.simibubi.create.foundation.utility.placement.PlacementHelpers;
import com.simibubi.create.foundation.utility.placement.PlacementOffset; import com.simibubi.create.foundation.utility.placement.PlacementOffset;
import mcp.MethodsReturnNonnullByDefault; import mcp.MethodsReturnNonnullByDefault;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.BlockItem; import net.minecraft.item.BlockItem;
import net.minecraft.item.BlockItemUseContext; import net.minecraft.item.BlockItemUseContext;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemUseContext;
import net.minecraft.util.ActionResultType; import net.minecraft.util.ActionResultType;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis; import net.minecraft.util.Direction.Axis;
@ -31,6 +26,11 @@ import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult; import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.world.World; import net.minecraft.world.World;
import java.util.List;
import java.util.function.Predicate;
import static com.simibubi.create.content.contraptions.base.RotatedPillarKineticBlock.AXIS;
public class CogwheelBlockItem extends BlockItem { public class CogwheelBlockItem extends BlockItem {
boolean large; boolean large;
@ -47,49 +47,27 @@ public class CogwheelBlockItem extends BlockItem {
} }
@Override @Override
public ActionResultType tryPlace(BlockItemUseContext context) { public ActionResultType onItemUseFirst(ItemStack stack, ItemUseContext context) {
World world = context.getWorld(); World world = context.getWorld();
BlockPos pos = context.getPos() BlockPos pos = context.getPos();
.offset(context.getFace()
.getOpposite());
BlockState state = world.getBlockState(pos); BlockState state = world.getBlockState(pos);
IPlacementHelper helper = PlacementHelpers.get(placementHelperId); IPlacementHelper helper = PlacementHelpers.get(placementHelperId);
PlayerEntity player = context.getPlayer(); PlayerEntity player = context.getPlayer();
BlockRayTraceResult ray = new BlockRayTraceResult(context.getHitVec(), context.getFace(), pos, true);
if (helper.matchesState(state)) { if (helper.matchesState(state) && player != null && !player.isSneaking()) {
PlacementOffset offset = helper.getOffset(world, state, pos, return helper.getOffset(world, state, pos, ray).placeInWorld(world, this, player, context.getHand(), ray);
new BlockRayTraceResult(context.getHitVec(), context.getFace(), pos, true));
if (!offset.isReplaceable(world))
return super.tryPlace(context);
offset.placeInWorld(world, this, player, context.getItem());
triggerShiftingGearsAdvancement(world, new BlockPos(offset.getPos()), offset.getTransform()
.apply(getBlock().getDefaultState()), player);
return ActionResultType.SUCCESS;
} }
if (integratedCogHelperId != -1) { if (integratedCogHelperId != -1) {
helper = PlacementHelpers.get(integratedCogHelperId); helper = PlacementHelpers.get(integratedCogHelperId);
if (helper.matchesState(state)) { if (helper.matchesState(state) && player != null && !player.isSneaking()) {
PlacementOffset offset = helper.getOffset(world, state, pos, return helper.getOffset(world, state, pos, ray).placeInWorld(world, this, player, context.getHand(), ray);
new BlockRayTraceResult(context.getHitVec(), context.getFace(), pos, true));
if (!offset.isReplaceable(world))
return super.tryPlace(context);
offset.placeInWorld(world, this, player, context.getItem());
triggerShiftingGearsAdvancement(world, new BlockPos(offset.getPos()), offset.getTransform()
.apply(getBlock().getDefaultState()), player);
return ActionResultType.SUCCESS;
} }
} }
return super.tryPlace(context); return super.onItemUseFirst(stack, context);
} }
@Override @Override

View file

@ -7,7 +7,6 @@ import com.simibubi.create.content.contraptions.relays.encased.EncasedShaftBlock
import com.simibubi.create.foundation.advancement.AllTriggers; import com.simibubi.create.foundation.advancement.AllTriggers;
import com.simibubi.create.foundation.utility.placement.IPlacementHelper; import com.simibubi.create.foundation.utility.placement.IPlacementHelper;
import com.simibubi.create.foundation.utility.placement.PlacementHelpers; import com.simibubi.create.foundation.utility.placement.PlacementHelpers;
import com.simibubi.create.foundation.utility.placement.PlacementOffset;
import com.simibubi.create.foundation.utility.placement.util.PoleHelper; import com.simibubi.create.foundation.utility.placement.util.PoleHelper;
import mcp.MethodsReturnNonnullByDefault; import mcp.MethodsReturnNonnullByDefault;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
@ -77,26 +76,8 @@ public class ShaftBlock extends AbstractShaftBlock {
} }
IPlacementHelper helper = PlacementHelpers.get(placementHelperId); IPlacementHelper helper = PlacementHelpers.get(placementHelperId);
if (helper.getItemPredicate().test(heldItem)) { if (helper.matchesItem(heldItem))
PlacementOffset offset = helper.getOffset(world, state, pos, ray); return helper.getOffset(world, state, pos, ray).placeInWorld(world, (BlockItem) heldItem.getItem(), player, hand, ray);
if (!offset.isReplaceable(world))
return ActionResultType.PASS;
offset.placeInWorld(world, (BlockItem) heldItem.getItem(), player, heldItem);
/*BlockPos newPos = new BlockPos(offset.getPos());
if (world.isRemote)
return ActionResultType.SUCCESS;
Block block = ((BlockItem) heldItem.getItem()).getBlock();
world.setBlockState(newPos, offset.getTransform().apply(block.getDefaultState()));
if (!player.isCreative())
heldItem.shrink(1);*/
return ActionResultType.SUCCESS;
}
return ActionResultType.PASS; return ActionResultType.PASS;
} }

View file

@ -1,25 +1,42 @@
package com.simibubi.create.foundation.command; package com.simibubi.create.foundation.command;
import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.tree.CommandNode;
import com.mojang.brigadier.tree.LiteralCommandNode;
import net.minecraft.command.CommandSource; import net.minecraft.command.CommandSource;
import net.minecraft.command.Commands; import net.minecraft.command.Commands;
import net.minecraft.entity.player.PlayerEntity;
import java.util.Collections;
import java.util.function.Predicate;
public class AllCommands { public class AllCommands {
public static Predicate<CommandSource> sourceIsPlayer = (cs) -> cs.getEntity() instanceof PlayerEntity;
public static void register(CommandDispatcher<CommandSource> dispatcher) { public static void register(CommandDispatcher<CommandSource> dispatcher) {
dispatcher.register(Commands.literal("create")
LiteralCommandNode<CommandSource> createRoot = dispatcher.register(Commands.literal("create")
//general purpose //general purpose
.then(ToggleDebugCommand.register()) .then(ToggleDebugCommand.register())
.then(OverlayConfigCommand.register()) .then(OverlayConfigCommand.register())
.then(FixLightingCommand.register()) .then(FixLightingCommand.register())
.then(ReplaceInCommandBlocksCommand.register()) .then(ReplaceInCommandBlocksCommand.register())
.then(HighlightCommand.register())
//dev-util //dev-util
//Comment out for release //Comment out for release
.then(ClearBufferCacheCommand.register()) .then(ClearBufferCacheCommand.register())
.then(ChunkUtilCommand.register()) .then(ChunkUtilCommand.register())
// .then(KillTPSCommand.register()) //.then(KillTPSCommand.register())
);
CommandNode<CommandSource> c = dispatcher.findNode(Collections.singleton("c"));
if (c != null)
return;
dispatcher.register(Commands.literal("c")
.redirect(createRoot)
); );
} }
} }

View file

@ -0,0 +1,103 @@
package com.simibubi.create.foundation.command;
import com.mojang.brigadier.Command;
import com.mojang.brigadier.builder.ArgumentBuilder;
import com.simibubi.create.content.contraptions.components.structureMovement.AssemblyException;
import com.simibubi.create.content.contraptions.components.structureMovement.IDisplayAssemblyExceptions;
import com.simibubi.create.foundation.networking.AllPackets;
import net.minecraft.command.CommandSource;
import net.minecraft.command.Commands;
import net.minecraft.command.arguments.BlockPosArgument;
import net.minecraft.command.arguments.EntityArgument;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.ServerPlayerEntity;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.math.*;
import net.minecraft.util.text.StringTextComponent;
import net.minecraft.world.World;
import net.minecraftforge.fml.network.PacketDistributor;
import java.util.Collection;
public class HighlightCommand {
public static ArgumentBuilder<CommandSource, ?> register() {
return Commands.literal("highlight")
.requires(cs -> cs.hasPermissionLevel(0))
.requires(AllCommands.sourceIsPlayer)
.then(Commands.argument("pos", BlockPosArgument.blockPos())
.requires(AllCommands.sourceIsPlayer)
.executes(ctx -> {
BlockPos pos = BlockPosArgument.getLoadedBlockPos(ctx, "pos");
AllPackets.channel.send(
PacketDistributor.PLAYER.with(() -> (ServerPlayerEntity) ctx.getSource().getEntity()),
new HighlightPacket(pos)
);
return Command.SINGLE_SUCCESS;
})
.then(Commands.argument("players", EntityArgument.players())
.executes(ctx -> {
Collection<ServerPlayerEntity> players = EntityArgument.getPlayers(ctx, "players");
BlockPos pos = BlockPosArgument.getBlockPos(ctx, "pos");
for (ServerPlayerEntity p : players) {
AllPackets.channel.send(
PacketDistributor.PLAYER.with(() -> p),
new HighlightPacket(pos)
);
}
return players.size();
})
)
)
.executes(ctx -> {
ServerPlayerEntity player = ctx.getSource().asPlayer();
return highlightAssemblyExceptionFor(player, ctx.getSource());
});
}
private static void sendMissMessage(CommandSource source) {
source.sendFeedback(new StringTextComponent("Try looking at a Block that has failed to assemble a Contraption and try again."), true);
}
private static int highlightAssemblyExceptionFor(ServerPlayerEntity player, CommandSource source) {
double distance = player.getAttribute(PlayerEntity.REACH_DISTANCE).getValue();
Vec3d start = player.getEyePosition(1);
Vec3d look = player.getLook(1);
Vec3d end = start.add(look.x * distance, look.y * distance, look.z * distance);
World world = player.world;
BlockRayTraceResult ray = world.rayTraceBlocks(new RayTraceContext(start, end, RayTraceContext.BlockMode.OUTLINE, RayTraceContext.FluidMode.NONE, player));
if (ray.getType() == RayTraceResult.Type.MISS) {
sendMissMessage(source);
return 0;
}
BlockPos pos = ray.getPos();
TileEntity te = world.getTileEntity(pos);
if (!(te instanceof IDisplayAssemblyExceptions)) {
sendMissMessage(source);
return 0;
}
IDisplayAssemblyExceptions display = (IDisplayAssemblyExceptions) te;
AssemblyException exception = display.getLastAssemblyException();
if (exception == null) {
sendMissMessage(source);
return 0;
}
if (!exception.hasPosition()) {
source.sendFeedback(new StringTextComponent("Can't highlight a specific position for this issue"), true);
return Command.SINGLE_SUCCESS;
}
BlockPos p = exception.getPosition();
String command = "/create highlight " + p.getX() + " " + p.getY() + " " + p.getZ();
return player.server.getCommandManager().handleCommand(source, command);
}
}

View file

@ -0,0 +1,55 @@
package com.simibubi.create.foundation.command;
import com.simibubi.create.AllSpecialTextures;
import com.simibubi.create.CreateClient;
import com.simibubi.create.foundation.networking.SimplePacketBase;
import net.minecraft.client.Minecraft;
import net.minecraft.network.PacketBuffer;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.shapes.VoxelShapes;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.fml.DistExecutor;
import net.minecraftforge.fml.network.NetworkEvent;
import java.util.function.Supplier;
public class HighlightPacket extends SimplePacketBase {
private final BlockPos pos;
public HighlightPacket(BlockPos pos) {
this.pos = pos;
}
public HighlightPacket(PacketBuffer buffer) {
this.pos = BlockPos.fromLong(buffer.readLong());
}
@Override
public void write(PacketBuffer buffer) {
buffer.writeLong(pos.toLong());
}
@Override
public void handle(Supplier<NetworkEvent.Context> ctx) {
ctx.get().enqueueWork(() -> DistExecutor.runWhenOn(Dist.CLIENT, () -> () -> {
performHighlight(pos);
}));
ctx.get().setPacketHandled(true);
}
@OnlyIn(Dist.CLIENT)
public static void performHighlight(BlockPos pos) {
if (Minecraft.getInstance().world == null || !Minecraft.getInstance().world.isBlockPresent(pos))
return;
CreateClient.outliner.showAABB("highlightCommand", VoxelShapes.fullCube().getBoundingBox().offset(pos), 200)
.lineWidth(1 / 32f)
.colored(0xEeEeEe)
//.colored(0x243B50)
.withFaceTexture(AllSpecialTextures.SELECTION);
}
}

View file

@ -1,19 +1,11 @@
package com.simibubi.create.foundation.networking; package com.simibubi.create.foundation.networking;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.function.Supplier;
import com.simibubi.create.Create; import com.simibubi.create.Create;
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionDisassemblyPacket; import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionDisassemblyPacket;
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionStallPacket; import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionStallPacket;
import com.simibubi.create.content.contraptions.components.structureMovement.gantry.GantryContraptionUpdatePacket; import com.simibubi.create.content.contraptions.components.structureMovement.gantry.GantryContraptionUpdatePacket;
import com.simibubi.create.content.contraptions.components.structureMovement.glue.GlueEffectPacket; import com.simibubi.create.content.contraptions.components.structureMovement.glue.GlueEffectPacket;
import com.simibubi.create.content.contraptions.components.structureMovement.sync.ClientMotionPacket; import com.simibubi.create.content.contraptions.components.structureMovement.sync.*;
import com.simibubi.create.content.contraptions.components.structureMovement.sync.ContraptionFluidPacket;
import com.simibubi.create.content.contraptions.components.structureMovement.sync.ContraptionInteractionPacket;
import com.simibubi.create.content.contraptions.components.structureMovement.sync.ContraptionSeatMappingPacket;
import com.simibubi.create.content.contraptions.components.structureMovement.sync.LimbSwingUpdatePacket;
import com.simibubi.create.content.contraptions.components.structureMovement.train.CouplingCreationPacket; import com.simibubi.create.content.contraptions.components.structureMovement.train.CouplingCreationPacket;
import com.simibubi.create.content.contraptions.components.structureMovement.train.capability.MinecartControllerUpdatePacket; import com.simibubi.create.content.contraptions.components.structureMovement.train.capability.MinecartControllerUpdatePacket;
import com.simibubi.create.content.contraptions.fluids.actors.FluidSplashPacket; import com.simibubi.create.content.contraptions.fluids.actors.FluidSplashPacket;
@ -25,16 +17,12 @@ import com.simibubi.create.content.logistics.block.mechanicalArm.ArmPlacementPac
import com.simibubi.create.content.logistics.item.filter.FilterScreenPacket; import com.simibubi.create.content.logistics.item.filter.FilterScreenPacket;
import com.simibubi.create.content.logistics.packet.ConfigureFlexcratePacket; import com.simibubi.create.content.logistics.packet.ConfigureFlexcratePacket;
import com.simibubi.create.content.logistics.packet.ConfigureStockswitchPacket; import com.simibubi.create.content.logistics.packet.ConfigureStockswitchPacket;
import com.simibubi.create.content.schematics.packet.ConfigureSchematicannonPacket; import com.simibubi.create.content.schematics.packet.*;
import com.simibubi.create.content.schematics.packet.InstantSchematicPacket;
import com.simibubi.create.content.schematics.packet.SchematicPlacePacket;
import com.simibubi.create.content.schematics.packet.SchematicSyncPacket;
import com.simibubi.create.content.schematics.packet.SchematicUploadPacket;
import com.simibubi.create.foundation.command.ConfigureConfigPacket; import com.simibubi.create.foundation.command.ConfigureConfigPacket;
import com.simibubi.create.foundation.command.HighlightPacket;
import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringCountUpdatePacket; import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringCountUpdatePacket;
import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.ScrollValueUpdatePacket; import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.ScrollValueUpdatePacket;
import com.simibubi.create.foundation.utility.ServerSpeedProvider; import com.simibubi.create.foundation.utility.ServerSpeedProvider;
import net.minecraft.network.PacketBuffer; import net.minecraft.network.PacketBuffer;
import net.minecraft.util.ResourceLocation; import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
@ -46,8 +34,12 @@ import net.minecraftforge.fml.network.PacketDistributor;
import net.minecraftforge.fml.network.PacketDistributor.TargetPoint; import net.minecraftforge.fml.network.PacketDistributor.TargetPoint;
import net.minecraftforge.fml.network.simple.SimpleChannel; import net.minecraftforge.fml.network.simple.SimpleChannel;
import static net.minecraftforge.fml.network.NetworkDirection.PLAY_TO_SERVER; import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.function.Supplier;
import static net.minecraftforge.fml.network.NetworkDirection.PLAY_TO_CLIENT; import static net.minecraftforge.fml.network.NetworkDirection.PLAY_TO_CLIENT;
import static net.minecraftforge.fml.network.NetworkDirection.PLAY_TO_SERVER;
public enum AllPackets { public enum AllPackets {
@ -85,6 +77,7 @@ public enum AllPackets {
FLUID_SPLASH(FluidSplashPacket.class, FluidSplashPacket::new, PLAY_TO_CLIENT), FLUID_SPLASH(FluidSplashPacket.class, FluidSplashPacket::new, PLAY_TO_CLIENT),
CONTRAPTION_FLUID(ContraptionFluidPacket.class, ContraptionFluidPacket::new, PLAY_TO_CLIENT), CONTRAPTION_FLUID(ContraptionFluidPacket.class, ContraptionFluidPacket::new, PLAY_TO_CLIENT),
GANTRY_UPDATE(GantryContraptionUpdatePacket.class, GantryContraptionUpdatePacket::new, PLAY_TO_CLIENT), GANTRY_UPDATE(GantryContraptionUpdatePacket.class, GantryContraptionUpdatePacket::new, PLAY_TO_CLIENT),
BLOCK_HIGHLIGHT(HighlightPacket.class, HighlightPacket::new, PLAY_TO_CLIENT)
; ;

View file

@ -1,24 +1,18 @@
package com.simibubi.create.foundation.utility.outliner; package com.simibubi.create.foundation.utility.outliner;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.matrix.MatrixStack;
import com.simibubi.create.foundation.renderState.SuperRenderTypeBuffer; import com.simibubi.create.foundation.renderState.SuperRenderTypeBuffer;
import com.simibubi.create.foundation.tileEntity.behaviour.ValueBox; import com.simibubi.create.foundation.tileEntity.behaviour.ValueBox;
import com.simibubi.create.foundation.utility.outliner.LineOutline.EndChasingLineOutline; import com.simibubi.create.foundation.utility.outliner.LineOutline.EndChasingLineOutline;
import com.simibubi.create.foundation.utility.outliner.Outline.OutlineParams; import com.simibubi.create.foundation.utility.outliner.Outline.OutlineParams;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
import java.util.*;
public class Outliner { public class Outliner {
final Map<Object, OutlineEntry> outlines; final Map<Object, OutlineEntry> outlines;
@ -57,6 +51,13 @@ public class Outliner {
return entry.outline.getParams(); return entry.outline.getParams();
} }
public OutlineParams showAABB(Object slot, AxisAlignedBB bb, int ttl) {
createAABBOutlineIfMissing(slot, bb);
ChasingAABBOutline outline = getAndRefreshAABB(slot, ttl);
outline.prevBB = outline.targetBB = bb;
return outline.getParams();
}
public OutlineParams showAABB(Object slot, AxisAlignedBB bb) { public OutlineParams showAABB(Object slot, AxisAlignedBB bb) {
createAABBOutlineIfMissing(slot, bb); createAABBOutlineIfMissing(slot, bb);
ChasingAABBOutline outline = getAndRefreshAABB(slot); ChasingAABBOutline outline = getAndRefreshAABB(slot);
@ -112,6 +113,12 @@ public class Outliner {
return (ChasingAABBOutline) entry.getOutline(); return (ChasingAABBOutline) entry.getOutline();
} }
private ChasingAABBOutline getAndRefreshAABB(Object slot, int ttl) {
OutlineEntry entry = outlines.get(slot);
entry.ticksTillRemoval = ttl;
return (ChasingAABBOutline) entry.getOutline();
}
// Maintenance // Maintenance
public Outliner() { public Outliner() {

View file

@ -6,6 +6,7 @@ import com.simibubi.create.foundation.utility.Pair;
import com.simibubi.create.foundation.utility.VecHelper; import com.simibubi.create.foundation.utility.VecHelper;
import mcp.MethodsReturnNonnullByDefault; import mcp.MethodsReturnNonnullByDefault;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.util.Direction; import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
@ -22,6 +23,11 @@ import java.util.stream.Collectors;
@MethodsReturnNonnullByDefault @MethodsReturnNonnullByDefault
public interface IPlacementHelper { public interface IPlacementHelper {
/**
* used as an identifier in SuperGlueHandler to skip blocks placed by helpers
*/
BlockState ID = new BlockState(Blocks.AIR, null);
/** /**
* @return a predicate that gets tested with the items held in the players hands, * @return a predicate that gets tested with the items held in the players hands,
* should return true if this placement helper is active with the given item * should return true if this placement helper is active with the given item
@ -61,24 +67,6 @@ public interface IPlacementHelper {
CreateClient.outliner.showLine("placementArrowB" + center + target, start.add(offset), endB.add(offset)).lineWidth(1/16f); CreateClient.outliner.showLine("placementArrowB" + center + target, start.add(offset), endB.add(offset)).lineWidth(1/16f);
} }
/*@OnlyIn(Dist.CLIENT)
static void renderArrow(Vec3d center, Direction towards, BlockRayTraceResult ray) {
Direction hitFace = ray.getFace();
if (hitFace.getAxis() == towards.getAxis())
return;
//get the two perpendicular directions to form the arrow
Direction[] directions = Arrays.stream(Direction.Axis.values()).filter(axis -> axis != hitFace.getAxis() && axis != towards.getAxis()).map(Iterate::directionsInAxis).findFirst().orElse(new Direction[]{});
Vec3d startOffset = new Vec3d(towards.getDirectionVec());
Vec3d start = center.add(startOffset);
for (Direction dir : directions) {
Vec3d arrowOffset = new Vec3d(dir.getDirectionVec()).scale(.25);
Vec3d target = center.add(startOffset.scale(0.75)).add(arrowOffset);
CreateClient.outliner.showLine("placementArrow" + towards + dir, start, target).lineWidth(1/16f);
}
}*/
static List<Direction> orderedByDistanceOnlyAxis(BlockPos pos, Vec3d hit, Direction.Axis axis) { static List<Direction> orderedByDistanceOnlyAxis(BlockPos pos, Vec3d hit, Direction.Axis axis) {
return orderedByDistance(pos, hit, dir -> dir.getAxis() == axis); return orderedByDistance(pos, hit, dir -> dir.getAxis() == axis);
} }

View file

@ -1,15 +1,26 @@
package com.simibubi.create.foundation.utility.placement; package com.simibubi.create.foundation.utility.placement;
import net.minecraft.advancements.CriteriaTriggers;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.SoundType;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.ServerPlayerEntity;
import net.minecraft.fluid.Fluids; import net.minecraft.fluid.Fluids;
import net.minecraft.fluid.IFluidState; import net.minecraft.fluid.IFluidState;
import net.minecraft.item.BlockItem; import net.minecraft.item.BlockItem;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemUseContext;
import net.minecraft.state.properties.BlockStateProperties; import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.stats.Stats;
import net.minecraft.util.ActionResultType;
import net.minecraft.util.Hand;
import net.minecraft.util.SoundCategory;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.util.math.Vec3i; import net.minecraft.util.math.Vec3i;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.common.util.BlockSnapshot;
import net.minecraftforge.event.world.BlockEvent;
import java.util.function.Function; import java.util.function.Function;
@ -56,24 +67,48 @@ public class PlacementOffset {
return world.getBlockState(new BlockPos(pos)).getMaterial().isReplaceable(); return world.getBlockState(new BlockPos(pos)).getMaterial().isReplaceable();
} }
public void placeInWorld(World world, BlockItem blockItem, PlayerEntity player, ItemStack item) { public ActionResultType placeInWorld(World world, BlockItem blockItem, PlayerEntity player, Hand hand, BlockRayTraceResult ray) {
placeInWorld(world, blockItem.getBlock().getDefaultState(), player, item);
}
public void placeInWorld(World world, BlockState defaultState, PlayerEntity player, ItemStack item) { ItemUseContext context = new ItemUseContext(player, hand, ray);
if (world.isRemote)
return;
BlockPos newPos = new BlockPos(pos); BlockPos newPos = new BlockPos(pos);
BlockState state = stateTransform.apply(defaultState);
if (!world.isBlockModifiable(player, newPos))
return ActionResultType.PASS;
if (!isReplaceable(world))
return ActionResultType.PASS;
BlockState state = stateTransform.apply(blockItem.getBlock().getDefaultState());
if (state.has(BlockStateProperties.WATERLOGGED)) { if (state.has(BlockStateProperties.WATERLOGGED)) {
IFluidState fluidState = world.getFluidState(newPos); IFluidState fluidState = world.getFluidState(newPos);
state = state.with(BlockStateProperties.WATERLOGGED, fluidState.getFluid() == Fluids.WATER); state = state.with(BlockStateProperties.WATERLOGGED, fluidState.getFluid() == Fluids.WATER);
} }
BlockSnapshot snapshot = BlockSnapshot.getBlockSnapshot(world, newPos);
world.setBlockState(newPos, state); world.setBlockState(newPos, state);
BlockEvent.EntityPlaceEvent event = new BlockEvent.EntityPlaceEvent(snapshot, IPlacementHelper.ID, player);
if (MinecraftForge.EVENT_BUS.post(event)) {
snapshot.restore(true, false);
return ActionResultType.FAIL;
}
BlockState newState = world.getBlockState(newPos);
SoundType soundtype = newState.getSoundType(world, newPos, player);
world.playSound(player, newPos, soundtype.getPlaceSound(), SoundCategory.BLOCKS, (soundtype.getVolume() + 1.0F) / 2.0F, soundtype.getPitch() * 0.8F);
player.addStat(Stats.ITEM_USED.get(blockItem));
if (world.isRemote)
return ActionResultType.SUCCESS;
if (player instanceof ServerPlayerEntity)
CriteriaTriggers.PLACED_BLOCK.trigger((ServerPlayerEntity) player, newPos, context.getItem());
if (!player.isCreative()) if (!player.isCreative())
item.shrink(1); context.getItem().shrink(1);
return ActionResultType.SUCCESS;
} }
} }

View file

@ -172,6 +172,13 @@
"create.gui.goggles.at_current_speed": "at current speed", "create.gui.goggles.at_current_speed": "at current speed",
"create.gui.goggles.pole_length": "Pole Length:", "create.gui.goggles.pole_length": "Pole Length:",
"create.gui.assembly.exception": "This Contraption was unable to assemble:",
"create.gui.assembly.exception.unmovableBlock": "Unmovable Block (%4$s) at [%1$s %2$s %3$s]",
"create.gui.assembly.exception.chunkNotLoaded": "The Block at [%1$s %2$s %3$s] was not in a loaded chunk",
"create.gui.assembly.exception.structureTooLarge": "There are too many Blocks included in the contraption.\nThe configured maximum is: %1$s",
"create.gui.assembly.exception.tooManyPistonPoles": "There are too many extension Poles attached to this Piston.\nThe configured maximum is: %1$s",
"create.gui.assembly.exception.noPistonPoles": "The Piston is missing some extension Poles",
"create.gui.gauge.info_header": "Gauge Information:", "create.gui.gauge.info_header": "Gauge Information:",
"create.gui.speedometer.title": "Rotation Speed", "create.gui.speedometer.title": "Rotation Speed",
"create.gui.stressometer.title": "Network Stress", "create.gui.stressometer.title": "Network Stress",