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.at_current_speed": "at current speed",
"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.speedometer.title": "Rotation Speed",
"create.gui.stressometer.title": "Network Stress",

View file

@ -823,6 +823,12 @@
"create.gui.goggles.kinetic_stats": "UNLOCALIZED: Kinetic Stats:",
"create.gui.goggles.at_current_speed": "UNLOCALIZED: at current speed",
"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.speedometer.title": "UNLOCALIZED: Rotation Speed",
"create.gui.stressometer.title": "UNLOCALIZED: Network Stress",

View file

@ -38,7 +38,7 @@ public abstract class GeneratingKineticTileEntity extends KineticTileEntity {
if (!(tileEntity instanceof KineticTileEntity))
return;
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;
}

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 static boolean movementNecessary(World world, BlockPos pos) {
BlockState state = world.getBlockState(pos);
public static boolean movementNecessary(BlockState state, World world, BlockPos pos) {
if (isBrittle(state))
return true;
if (state.getBlock() instanceof FenceGateBlock)
@ -68,18 +67,17 @@ public class BlockMovementTraits {
return true;
}
public static boolean movementAllowed(World world, BlockPos pos) {
BlockState blockState = world.getBlockState(pos);
Block block = blockState.getBlock();
public static boolean movementAllowed(BlockState state, World world, BlockPos pos) {
Block block = state.getBlock();
if (block instanceof AbstractChassisBlock)
return true;
if (blockState.getBlockHardness(world, pos) == -1)
if (state.getBlockHardness(world, pos) == -1)
return false;
if (AllBlockTags.NON_MOVABLE.matches(blockState))
if (AllBlockTags.NON_MOVABLE.matches(state))
return false;
// 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;
if (block instanceof MechanicalBearingBlock) {
TileEntity te = world.getTileEntity(pos);
@ -97,11 +95,11 @@ public class BlockMovementTraits {
return !((PulleyTileEntity) te).running;
}
if (AllBlocks.BELT.has(blockState))
if (AllBlocks.BELT.has(state))
return true;
if (blockState.getBlock() instanceof GrindstoneBlock)
if (state.getBlock() instanceof GrindstoneBlock)
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;
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.AllMovementBehaviours;
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.VecHelper;
import com.simibubi.create.foundation.utility.worldWrappers.WrappedWorld;
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.*;
import net.minecraft.block.material.PushReaction;
import net.minecraft.entity.Entity;
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.items.IItemHandlerModifiable;
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 {
@ -139,7 +120,7 @@ public abstract class Contraption {
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);
@ -154,7 +135,7 @@ public abstract class Contraption {
}
protected boolean addToInitialFrontier(World world, BlockPos pos, Direction forcedDirection,
List<BlockPos> frontier) {
Queue<BlockPos> frontier) throws AssemblyException {
return true;
}
@ -165,9 +146,9 @@ public abstract class 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();
List<BlockPos> frontier = new ArrayList<>();
Queue<BlockPos> frontier = new LinkedList<>();
Set<BlockPos> visited = new HashSet<>();
anchor = pos;
@ -181,10 +162,10 @@ public abstract class Contraption {
for (int limit = 100000; limit > 0; limit--) {
if (frontier.isEmpty())
return true;
if (!moveBlock(world, frontier.remove(0), forcedDirection, frontier, visited))
if (!moveBlock(world, forcedDirection, frontier, visited))
return false;
}
return false;
throw AssemblyException.structureTooLarge();
}
public void onEntityCreated(AbstractContraptionEntity entity) {
@ -196,8 +177,12 @@ public abstract class Contraption {
StabilizedContraption subContraption = new StabilizedContraption(face);
World world = entity.world;
BlockPos pos = blockFace.getPos();
if (!subContraption.assemble(world, pos))
try {
if (!subContraption.assemble(world, pos))
continue;
} catch (AssemblyException e) {
continue;
}
subContraption.removeBlocksFromWorld(world, BlockPos.ZERO);
OrientedContraptionEntity movedContraption =
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));
}
protected boolean moveBlock(World world, BlockPos pos, @Nullable Direction forcedDirection, List<BlockPos> frontier,
Set<BlockPos> visited) {
visited.add(pos);
frontier.remove(pos);
if (!world.isBlockPresent(pos))
/** move the first block in frontier queue */
protected boolean moveBlock(World world, @Nullable Direction forcedDirection, Queue<BlockPos> frontier,
Set<BlockPos> visited) throws AssemblyException {
BlockPos pos = frontier.poll();
if (pos == null)
return false;
visited.add(pos);
if (World.isOutsideBuildHeight(pos))
return true;
if (!world.isBlockPresent(pos))
throw AssemblyException.unloadedChunk(pos);
if (isAnchoringBlockAt(pos))
return true;
if (!BlockMovementTraits.movementNecessary(world, pos))
return true;
if (!movementAllowed(world, pos))
return false;
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
&& !moveChassis(world, pos, forcedDirection, frontier, visited))
return false;
@ -306,9 +296,10 @@ public abstract class Contraption {
}
// Cart assemblers attach themselves
BlockState stateBelow = world.getBlockState(pos.down());
if (!visited.contains(pos.down()) && AllBlocks.CART_ASSEMBLER.has(stateBelow))
frontier.add(pos.down());
BlockPos posDown = pos.down();
BlockState stateBelow = world.getBlockState(posDown);
if (!visited.contains(posDown) && AllBlocks.CART_ASSEMBLER.has(stateBelow))
frontier.add(posDown);
Map<Direction, SuperGlueEntity> superglue = SuperGlueHandler.gatherGlue(world, pos);
@ -318,9 +309,9 @@ public abstract class Contraption {
BlockState blockState = world.getBlockState(offsetPos);
if (isAnchoringBlockAt(offsetPos))
continue;
if (!movementAllowed(world, offsetPos)) {
if (!movementAllowed(blockState, world, offsetPos)) {
if (offset == forcedDirection)
return false;
throw AssemblyException.unmovableBlock(pos, state);
continue;
}
@ -349,10 +340,13 @@ public abstract class Contraption {
}
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) {
Direction direction = state.get(MechanicalPistonHeadBlock.FACING);
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) {
for (Direction d : Iterate.directionsInAxis(state.get(PistonExtensionPoleBlock.FACING)
.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) {
BlockPos offset = pos.offset(state.get(GantryPinionBlock.FACING));
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) {
for (Direction d : Iterate.directions) {
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);
if (!canBeStabilized(facing, pos.subtract(anchor))) {
BlockPos offset = pos.offset(facing);
@ -440,7 +434,7 @@ public abstract class Contraption {
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 prevPos = BeltBlock.nextSegmentPosition(state, pos, false);
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();
BlockPos ropePos = pos;
while (limit-- >= 0) {
@ -479,8 +473,8 @@ public abstract class Contraption {
}
}
private boolean moveMechanicalPiston(World world, BlockPos pos, List<BlockPos> frontier, Set<BlockPos> visited,
BlockState state) {
private boolean moveMechanicalPiston(World world, BlockPos pos, Queue<BlockPos> frontier, Set<BlockPos> visited, BlockState state) throws AssemblyException {
int limit = AllConfigs.SERVER.kinetics.maxPistonPoles.get();
Direction direction = state.get(MechanicalPistonBlock.FACING);
PistonState pistonState = state.get(MechanicalPistonBlock.STATE);
if (pistonState == PistonState.MOVING)
@ -503,7 +497,7 @@ public abstract class Contraption {
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) {
TileEntity te = world.getTileEntity(pos);
if (!(te instanceof ChassisTileEntity))
@ -588,8 +582,8 @@ public abstract class Contraption {
return globalPos.subtract(anchor);
}
protected boolean movementAllowed(World world, BlockPos pos) {
return BlockMovementTraits.movementAllowed(world, pos);
protected boolean movementAllowed(BlockState state, World world, BlockPos pos) {
return BlockMovementTraits.movementAllowed(state, world, 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.content.contraptions.components.structureMovement.ContraptionType;
import com.simibubi.create.content.contraptions.components.structureMovement.AssemblyException;
import com.simibubi.create.content.contraptions.components.structureMovement.Contraption;
import net.minecraft.nbt.CompoundNBT;
@ -28,7 +29,7 @@ public class BearingContraption extends Contraption {
}
@Override
public boolean assemble(World world, BlockPos pos) {
public boolean assemble(World world, BlockPos pos) throws AssemblyException {
BlockPos offset = pos.offset(facing);
if (!searchMovedStructure(world, offset, null))
return false;

View file

@ -1,12 +1,10 @@
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.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.IDisplayAssemblyExceptions;
import com.simibubi.create.content.contraptions.components.structureMovement.bearing.ClockworkContraption.HandType;
import com.simibubi.create.foundation.advancement.AllTriggers;
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.Lang;
import com.simibubi.create.foundation.utility.ServerSpeedProvider;
import net.minecraft.block.BlockState;
import net.minecraft.nbt.CompoundNBT;
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.math.BlockPos;
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 minuteHand;
@ -37,6 +37,7 @@ public class ClockworkBearingTileEntity extends KineticTileEntity implements IBe
protected boolean running;
protected boolean assembleNextTick;
protected AssemblyException lastException;
protected ScrollOptionBehaviour<ClockHands> operationMode;
@ -105,6 +106,11 @@ public class ClockworkBearingTileEntity extends KineticTileEntity implements IBe
applyRotations();
}
@Override
public AssemblyException getLastAssemblyException() {
return lastException;
}
protected void applyRotations() {
BlockState blockState = getBlockState();
Axis axis = Axis.X;
@ -199,8 +205,15 @@ public class ClockworkBearingTileEntity extends KineticTileEntity implements IBe
Direction direction = getBlockState().get(BlockStateProperties.FACING);
// Collect Construct
Pair<ClockworkContraption, ClockworkContraption> contraption =
ClockworkContraption.assembleClockworkAt(world, pos, direction);
Pair<ClockworkContraption, ClockworkContraption> contraption;
try {
contraption = ClockworkContraption.assembleClockworkAt(world, pos, direction);
lastException = null;
} catch (AssemblyException e) {
lastException = e;
sendData();
return;
}
if (contraption == null)
return;
if (contraption.getLeft() == null)
@ -284,6 +297,7 @@ public class ClockworkBearingTileEntity extends KineticTileEntity implements IBe
compound.putBoolean("Running", running);
compound.putFloat("HourAngle", hourAngle);
compound.putFloat("MinuteAngle", minuteAngle);
AssemblyException.write(compound, lastException);
super.write(compound, clientPacket);
}
@ -295,6 +309,7 @@ public class ClockworkBearingTileEntity extends KineticTileEntity implements IBe
running = compound.getBoolean("Running");
hourAngle = compound.getFloat("HourAngle");
minuteAngle = compound.getFloat("MinuteAngle");
lastException = AssemblyException.read(compound);
super.read(compound, clientPacket);
if (!clientPacket)

View file

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

View file

@ -1,12 +1,10 @@
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.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.IDisplayAssemblyExceptions;
import com.simibubi.create.foundation.advancement.AllTriggers;
import com.simibubi.create.foundation.item.TooltipHelper;
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.Lang;
import com.simibubi.create.foundation.utility.ServerSpeedProvider;
import net.minecraft.block.BlockState;
import net.minecraft.nbt.CompoundNBT;
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.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 ControlledContraptionEntity movedContraption;
@ -31,6 +32,7 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity imp
protected boolean running;
protected boolean assembleNextTick;
protected float clientAngleDiff;
protected AssemblyException lastException;
public MechanicalBearingTileEntity(TileEntityType<? extends MechanicalBearingTileEntity> type) {
super(type);
@ -62,6 +64,7 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity imp
public void write(CompoundNBT compound, boolean clientPacket) {
compound.putBoolean("Running", running);
compound.putFloat("Angle", angle);
AssemblyException.write(compound, lastException);
super.write(compound, clientPacket);
}
@ -70,6 +73,7 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity imp
float angleBefore = angle;
running = compound.getBoolean("Running");
angle = compound.getFloat("Angle");
lastException = AssemblyException.read(compound);
super.read(compound, clientPacket);
if (!clientPacket)
return;
@ -104,6 +108,11 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity imp
return speed;
}
@Override
public AssemblyException getLastAssemblyException() {
return lastException;
}
protected boolean isWindmill() {
return false;
}
@ -120,8 +129,16 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity imp
Direction direction = getBlockState().get(FACING);
BearingContraption contraption = new BearingContraption(isWindmill(), direction);
if (!contraption.assemble(world, pos))
try {
if (!contraption.assemble(world, pos))
return;
lastException = null;
} catch (AssemblyException e) {
lastException = e;
sendData();
return;
}
if (isWindmill())
AllTriggers.triggerForNearbyPlayers(AllTriggers.WINDMILL, world, pos, 5);
@ -281,5 +298,4 @@ public class MechanicalBearingTileEntity extends GeneratingKineticTileEntity imp
TooltipHelper.addHint(tooltip, "hint.empty_bearing");
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) {
ItemStack heldItem = player.getHeldItem(hand);
if (AllBlocks.SAIL.isIn(heldItem) || AllBlocks.SAIL_FRAME.isIn(heldItem)) {
IPlacementHelper placementHelper = PlacementHelpers.get(placementHelperId);
PlacementOffset offset = placementHelper.getOffset(world, state, pos, ray);
if (!offset.isReplaceable(world))
return ActionResultType.PASS;
offset.placeInWorld(world, ((BlockItem) heldItem.getItem()).getBlock().getDefaultState(), player, heldItem);
return ActionResultType.SUCCESS;
}
IPlacementHelper placementHelper = PlacementHelpers.get(placementHelperId);
if (placementHelper.matchesItem(heldItem))
return placementHelper.getOffset(world, state, pos, ray).placeInWorld(world, (BlockItem) heldItem.getItem(), player, hand, ray);
if (heldItem.getItem() instanceof ShearsItem) {
if (!world.isRemote)

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,13 +1,9 @@
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.foundation.networking.AllPackets;
import com.simibubi.create.foundation.utility.placement.IPlacementHelper;
import com.simibubi.create.foundation.utility.worldWrappers.RayTraceWorld;
import net.minecraft.block.Blocks;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
@ -15,12 +11,8 @@ import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.util.Direction;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.util.math.RayTraceContext;
import net.minecraft.util.math.*;
import net.minecraft.util.math.RayTraceResult.Type;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.IWorld;
import net.minecraft.world.World;
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.network.PacketDistributor;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@EventBusSubscriber
public class SuperGlueHandler {
@ -65,6 +61,8 @@ public class SuperGlueHandler {
return;
if (AllItems.WRENCH.isIn(placer.getHeldItemMainhand()))
return;
if (event.getPlacedAgainst() == IPlacementHelper.ID)
return;
double distance = placer.getAttribute(PlayerEntity.REACH_DISTANCE)
.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.AllShapes;
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.mounted.CartAssemblerTileEntity.CartMovementMode;
import com.simibubi.create.content.contraptions.components.structureMovement.train.CouplingHandler;
@ -229,13 +230,27 @@ public class CartAssemblerBlock extends AbstractRailBlock
.isCoupledThroughContraption())
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);
MountedContraption contraption = new MountedContraption(mode);
if (!contraption.assemble(world, pos))
try {
if (!contraption.assemble(world, pos))
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;
Optional<Direction> initialOrientation = cart.getMotion()

View file

@ -1,7 +1,7 @@
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.tileEntity.SmartTileEntity;
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.utility.Lang;
import com.simibubi.create.foundation.utility.VecHelper;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.state.properties.RailShape;
import net.minecraft.tileentity.TileEntityType;
import net.minecraft.util.Direction.Axis;
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;
protected ScrollOptionBehaviour<CartMovementMode> movementMode;
private int ticksSinceMinecartUpdate;
protected AssemblyException lastException;
public CartAssemblerTileEntity(TileEntityType<? extends CartAssemblerTileEntity> type) {
super(type);
@ -44,6 +47,23 @@ public class CartAssemblerTileEntity extends SmartTileEntity {
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() {
return new CartAssemblerValueBoxTransform();
}
@ -103,5 +123,4 @@ public class CartAssemblerTileEntity extends SmartTileEntity {
public boolean isMinecartUpdateValid() {
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 java.util.List;
import java.util.Queue;
import org.apache.commons.lang3.tuple.Pair;
import com.simibubi.create.AllBlocks;
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.mounted.CartAssemblerTileEntity.CartMovementMode;
import com.simibubi.create.foundation.utility.Iterate;
@ -52,7 +53,7 @@ public class MountedContraption extends Contraption {
}
@Override
public boolean assemble(World world, BlockPos pos) {
public boolean assemble(World world, BlockPos pos) throws AssemblyException {
BlockState state = world.getBlockState(pos);
if (!state.has(RAIL_SHAPE))
return false;
@ -70,7 +71,7 @@ public class MountedContraption extends Contraption {
}
@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.add(pos.up());
return true;
@ -104,11 +105,10 @@ public class MountedContraption extends Contraption {
}
@Override
protected boolean movementAllowed(World world, BlockPos pos) {
BlockState blockState = world.getBlockState(pos);
if (!pos.equals(anchor) && AllBlocks.CART_ASSEMBLER.has(blockState))
return testSecondaryCartAssembler(world, blockState, pos);
return super.movementAllowed(world, pos);
protected boolean movementAllowed(BlockState state, World world, BlockPos pos) {
if (!pos.equals(anchor) && AllBlocks.CART_ASSEMBLER.has(state))
return testSecondaryCartAssembler(world, state, pos);
return super.movementAllowed(state, world, 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;
import java.util.List;
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.ControlledContraptionEntity;
import com.simibubi.create.content.contraptions.components.structureMovement.IControlContraption;
import com.simibubi.create.content.contraptions.components.structureMovement.*;
import com.simibubi.create.foundation.tileEntity.TileEntityBehaviour;
import com.simibubi.create.foundation.tileEntity.behaviour.ValueBoxTransform;
import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.ScrollOptionBehaviour;
import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.foundation.utility.ServerSpeedProvider;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.tileentity.TileEntityType;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
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 boolean running;
@ -27,6 +24,7 @@ public abstract class LinearActuatorTileEntity extends KineticTileEntity impleme
protected boolean forceMove;
protected ScrollOptionBehaviour<MovementMode> movementMode;
protected boolean waitingForSpeedChange;
protected AssemblyException lastException;
// Custom position sync
protected float clientOffsetDiff;
@ -80,7 +78,13 @@ public abstract class LinearActuatorTileEntity extends KineticTileEntity impleme
return;
} else {
if (getSpeed() != 0)
assemble();
try {
assemble();
lastException = null;
} catch (AssemblyException e) {
lastException = e;
}
sendData();
}
return;
}
@ -153,6 +157,7 @@ public abstract class LinearActuatorTileEntity extends KineticTileEntity impleme
compound.putBoolean("Running", running);
compound.putBoolean("Waiting", waitingForSpeedChange);
compound.putFloat("Offset", offset);
AssemblyException.write(compound, lastException);
super.write(compound, clientPacket);
if (clientPacket && forceMove) {
@ -169,6 +174,7 @@ public abstract class LinearActuatorTileEntity extends KineticTileEntity impleme
running = compound.getBoolean("Running");
waitingForSpeedChange = compound.getBoolean("Waiting");
offset = compound.getFloat("Offset");
lastException = AssemblyException.read(compound);
super.read(compound, clientPacket);
if (!clientPacket)
@ -183,9 +189,14 @@ public abstract class LinearActuatorTileEntity extends KineticTileEntity impleme
movedContraption = null;
}
@Override
public AssemblyException getLastAssemblyException() {
return lastException;
}
public abstract void disassemble();
protected abstract void assemble();
protected abstract void assemble() throws AssemblyException;
protected abstract int getExtensionRange();
@ -288,5 +299,4 @@ public abstract class LinearActuatorTileEntity extends KineticTileEntity impleme
public BlockPos getBlockPosition() {
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.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.ControlledContraptionEntity;
import com.simibubi.create.content.contraptions.components.structureMovement.DirectionalExtenderScrollOptionSlot;
@ -41,7 +42,7 @@ public class MechanicalPistonTileEntity extends LinearActuatorTileEntity {
}
@Override
public void assemble() {
public void assemble() throws AssemblyException {
if (!(world.getBlockState(pos)
.getBlock() instanceof MechanicalPistonBlock))
return;

View file

@ -1,7 +1,8 @@
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.ContraptionType;
import com.simibubi.create.content.contraptions.components.structureMovement.TranslatingContraption;
import com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.*;
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.List;
import java.util.Queue;
import static com.simibubi.create.AllBlocks.MECHANICAL_PISTON_HEAD;
import static com.simibubi.create.AllBlocks.PISTON_EXTENSION_POLE;
@ -51,7 +53,7 @@ public class PistonContraption extends TranslatingContraption {
}
@Override
public boolean assemble(World world, BlockPos pos) {
public boolean assemble(World world, BlockPos pos) throws AssemblyException {
if (!collectExtensions(world, pos, orientation))
return false;
int count = blocks.size();
@ -66,7 +68,7 @@ public class PistonContraption extends TranslatingContraption {
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<>();
BlockPos actualStart = pos;
BlockState nextBlock = world.getBlockState(actualStart.offset(direction));
@ -89,7 +91,7 @@ public class PistonContraption extends TranslatingContraption {
nextBlock = world.getBlockState(actualStart.offset(direction));
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()));
if (extensionsInFront + extensionsInBack > MechanicalPistonBlock.maxAllowedPistonPoles())
return false;
throw AssemblyException.tooManyPistonPoles();
}
anchor = pos.offset(direction, initialExtensionProgress + 1);
@ -124,7 +126,7 @@ public class PistonContraption extends TranslatingContraption {
1, 1);
if (extensionLength == 0)
return false;
throw AssemblyException.noPistonPoles();
bounds = new AxisAlignedBB(0, 0, 0, 0, 0, 0);
@ -144,7 +146,7 @@ public class PistonContraption extends TranslatingContraption {
}
@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();
boolean sticky = isStickyPiston(world.getBlockState(pos.offset(orientation, -1)));
boolean retracting = direction != orientation;
@ -154,17 +156,22 @@ public class PistonContraption extends TranslatingContraption {
if (offset == 1 && retracting)
return true;
BlockPos currentPos = pos.offset(orientation, offset + initialExtensionProgress);
if (!world.isBlockPresent(currentPos))
return false;
if (!BlockMovementTraits.movementNecessary(world, currentPos))
if (retracting && World.isOutsideBuildHeight(currentPos))
return true;
if (!world.isBlockPresent(currentPos))
throw AssemblyException.unloadedChunk(currentPos);
BlockState state = world.getBlockState(currentPos);
if (!BlockMovementTraits.movementNecessary(state, world, currentPos))
return true;
if (BlockMovementTraits.isBrittle(state) && !(state.getBlock() instanceof CarpetBlock))
return true;
if (isPistonHead(state) && state.get(FACING) == direction.getOpposite())
return true;
if (!BlockMovementTraits.movementAllowed(world, currentPos))
return retracting;
if (!BlockMovementTraits.movementAllowed(state, world, currentPos))
if (retracting)
return true;
else
throw AssemblyException.unmovableBlock(currentPos, state);
if (retracting && state.getPushReaction() == PushReaction.PUSH_ONLY)
return true;
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.utility.placement.IPlacementHelper;
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 mcp.MethodsReturnNonnullByDefault;
import net.minecraft.block.Block;
@ -17,6 +16,7 @@ import net.minecraft.block.material.PushReaction;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.fluid.Fluids;
import net.minecraft.fluid.IFluidState;
import net.minecraft.item.BlockItem;
import net.minecraft.item.BlockItemUseContext;
import net.minecraft.item.ItemStack;
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) {
ItemStack heldItem = player.getHeldItem(hand);
if (AllBlocks.PISTON_EXTENSION_POLE.isIn(heldItem) && !player.isSneaking()) {
IPlacementHelper placementHelper = PlacementHelpers.get(placementHelperId);
PlacementOffset offset = placementHelper.getOffset(world, state, pos, 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;
}
IPlacementHelper placementHelper = PlacementHelpers.get(placementHelperId);
if (placementHelper.matchesItem(heldItem) && !player.isSneaking())
return placementHelper.getOffset(world, state, pos, ray).placeInWorld(world, (BlockItem) heldItem.getItem(), player, hand, ray);
return ActionResultType.PASS;
}

View file

@ -1,5 +1,6 @@
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.TranslatingContraption;
@ -23,7 +24,7 @@ public class PulleyContraption extends TranslatingContraption {
}
@Override
public boolean assemble(World world, BlockPos pos) {
public boolean assemble(World world, BlockPos pos) throws AssemblyException {
if (!searchMovedStructure(world, pos, null))
return false;
startMoving(world);

View file

@ -1,6 +1,7 @@
package com.simibubi.create.content.contraptions.components.structureMovement.pulley;
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.ContraptionCollider;
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.tileEntity.behaviour.CenteredSideValueBoxTransform;
import com.simibubi.create.foundation.tileEntity.behaviour.ValueBoxTransform;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.block.IWaterLoggable;
@ -42,7 +42,7 @@ public class PulleyTileEntity extends LinearActuatorTileEntity {
}
@Override
protected void assemble() {
protected void assemble() throws AssemblyException {
if (!(world.getBlockState(pos)
.getBlock() instanceof PulleyBlock))
return;
@ -176,9 +176,10 @@ public class PulleyTileEntity extends LinearActuatorTileEntity {
return;
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;
if (BlockMovementTraits.isBrittle(world.getBlockState(posBelow)))
if (BlockMovementTraits.isBrittle(state))
return;
disassemble();

View file

@ -4,6 +4,7 @@ import com.mojang.blaze3d.systems.RenderSystem;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllItems;
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.PistonExtensionPoleBlock;
import com.simibubi.create.foundation.config.AllConfigs;
@ -92,6 +93,14 @@ public class GoggleOverlayRenderer {
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
if ((hasGoggleInformation && !goggleAddedInformation) && (hasHoveringInformation && !hoverAddedInformation))
return;

View file

@ -9,13 +9,13 @@ import java.util.List;
public interface IHaveGoggleInformation {
DecimalFormat decimalFormat = new DecimalFormat("#.##");
public static String spacing = " ";
String spacing = " ";
/**
* 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,
* or {{@code false}} if the overlay should not 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
* */
default boolean addToGoggleTooltip(List<String> tooltip, boolean isPlayerSneaking){
return false;

View file

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

View file

@ -1,7 +1,5 @@
package com.simibubi.create.content.contraptions.relays.advanced;
import java.util.function.Predicate;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllShapes;
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.PlacementHelpers;
import com.simibubi.create.foundation.utility.placement.PlacementOffset;
import mcp.MethodsReturnNonnullByDefault;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.BlockItem;
import net.minecraft.item.BlockItemUseContext;
import net.minecraft.item.ItemStack;
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.World;
import java.util.function.Predicate;
public class SpeedControllerBlock extends HorizontalAxisKineticBlock implements ITE<SpeedControllerTileEntity> {
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,
BlockRayTraceResult ray) {
IPlacementHelper helper = PlacementHelpers.get(placementHelperId);
ItemStack heldItem = player.getHeldItem(hand);
if (helper.matchesItem(heldItem)) {
PlacementOffset offset = helper.getOffset(world, state, pos, ray);
if (!offset.isReplaceable(world))
return ActionResultType.PASS;
offset.placeInWorld(world, AllBlocks.LARGE_COGWHEEL.getDefaultState(), player, heldItem);
return ActionResultType.SUCCESS;
}
IPlacementHelper helper = PlacementHelpers.get(placementHelperId);
if (helper.matchesItem(heldItem))
return helper.getOffset(world, state, pos, ray).placeInWorld(world, (BlockItem) heldItem.getItem(), player, hand, ray);
return ActionResultType.PASS;
}

View file

@ -1,10 +1,5 @@
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.AllShapes;
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.PlacementHelpers;
import com.simibubi.create.foundation.utility.placement.PlacementOffset;
import mcp.MethodsReturnNonnullByDefault;
import net.minecraft.block.BlockState;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.BlockItem;
import net.minecraft.item.BlockItemUseContext;
import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemUseContext;
import net.minecraft.util.ActionResultType;
import net.minecraft.util.Direction;
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.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 {
boolean large;
@ -47,49 +47,27 @@ public class CogwheelBlockItem extends BlockItem {
}
@Override
public ActionResultType tryPlace(BlockItemUseContext context) {
public ActionResultType onItemUseFirst(ItemStack stack, ItemUseContext context) {
World world = context.getWorld();
BlockPos pos = context.getPos()
.offset(context.getFace()
.getOpposite());
BlockPos pos = context.getPos();
BlockState state = world.getBlockState(pos);
IPlacementHelper helper = PlacementHelpers.get(placementHelperId);
PlayerEntity player = context.getPlayer();
if (helper.matchesState(state)) {
PlacementOffset offset = helper.getOffset(world, state, pos,
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;
BlockRayTraceResult ray = new BlockRayTraceResult(context.getHitVec(), context.getFace(), pos, true);
if (helper.matchesState(state) && player != null && !player.isSneaking()) {
return helper.getOffset(world, state, pos, ray).placeInWorld(world, this, player, context.getHand(), ray);
}
if (integratedCogHelperId != -1) {
helper = PlacementHelpers.get(integratedCogHelperId);
if (helper.matchesState(state)) {
PlacementOffset offset = helper.getOffset(world, state, pos,
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 (helper.matchesState(state) && player != null && !player.isSneaking()) {
return helper.getOffset(world, state, pos, ray).placeInWorld(world, this, player, context.getHand(), ray);
}
}
return super.tryPlace(context);
return super.onItemUseFirst(stack, context);
}
@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.utility.placement.IPlacementHelper;
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 mcp.MethodsReturnNonnullByDefault;
import net.minecraft.block.BlockState;
@ -77,26 +76,8 @@ public class ShaftBlock extends AbstractShaftBlock {
}
IPlacementHelper helper = PlacementHelpers.get(placementHelperId);
if (helper.getItemPredicate().test(heldItem)) {
PlacementOffset offset = helper.getOffset(world, state, pos, 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;
}
if (helper.matchesItem(heldItem))
return helper.getOffset(world, state, pos, ray).placeInWorld(world, (BlockItem) heldItem.getItem(), player, hand, ray);
return ActionResultType.PASS;
}

View file

@ -1,25 +1,42 @@
package com.simibubi.create.foundation.command;
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.Commands;
import net.minecraft.entity.player.PlayerEntity;
import java.util.Collections;
import java.util.function.Predicate;
public class AllCommands {
public static void register(CommandDispatcher<CommandSource> dispatcher) {
dispatcher.register(Commands.literal("create")
//general purpose
.then(ToggleDebugCommand.register())
.then(OverlayConfigCommand.register())
.then(FixLightingCommand.register())
.then(ReplaceInCommandBlocksCommand.register())
public static Predicate<CommandSource> sourceIsPlayer = (cs) -> cs.getEntity() instanceof PlayerEntity;
//dev-util
//Comment out for release
.then(ClearBufferCacheCommand.register())
.then(ChunkUtilCommand.register())
// .then(KillTPSCommand.register())
public static void register(CommandDispatcher<CommandSource> dispatcher) {
LiteralCommandNode<CommandSource> createRoot = dispatcher.register(Commands.literal("create")
//general purpose
.then(ToggleDebugCommand.register())
.then(OverlayConfigCommand.register())
.then(FixLightingCommand.register())
.then(ReplaceInCommandBlocksCommand.register())
.then(HighlightCommand.register())
//dev-util
//Comment out for release
.then(ClearBufferCacheCommand.register())
.then(ChunkUtilCommand.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;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.function.Supplier;
import com.simibubi.create.Create;
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.gantry.GantryContraptionUpdatePacket;
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.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.sync.*;
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.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.packet.ConfigureFlexcratePacket;
import com.simibubi.create.content.logistics.packet.ConfigureStockswitchPacket;
import com.simibubi.create.content.schematics.packet.ConfigureSchematicannonPacket;
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.content.schematics.packet.*;
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.scrollvalue.ScrollValueUpdatePacket;
import com.simibubi.create.foundation.utility.ServerSpeedProvider;
import net.minecraft.network.PacketBuffer;
import net.minecraft.util.ResourceLocation;
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.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_SERVER;
public enum AllPackets {
@ -85,6 +77,7 @@ public enum AllPackets {
FLUID_SPLASH(FluidSplashPacket.class, FluidSplashPacket::new, PLAY_TO_CLIENT),
CONTRAPTION_FLUID(ContraptionFluidPacket.class, ContraptionFluidPacket::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;
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.simibubi.create.foundation.renderState.SuperRenderTypeBuffer;
import com.simibubi.create.foundation.tileEntity.behaviour.ValueBox;
import com.simibubi.create.foundation.utility.outliner.LineOutline.EndChasingLineOutline;
import com.simibubi.create.foundation.utility.outliner.Outline.OutlineParams;
import net.minecraft.client.Minecraft;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
import java.util.*;
public class Outliner {
final Map<Object, OutlineEntry> outlines;
@ -57,6 +51,13 @@ public class Outliner {
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) {
createAABBOutlineIfMissing(slot, bb);
ChasingAABBOutline outline = getAndRefreshAABB(slot);
@ -112,6 +113,12 @@ public class Outliner {
return (ChasingAABBOutline) entry.getOutline();
}
private ChasingAABBOutline getAndRefreshAABB(Object slot, int ttl) {
OutlineEntry entry = outlines.get(slot);
entry.ticksTillRemoval = ttl;
return (ChasingAABBOutline) entry.getOutline();
}
// Maintenance
public Outliner() {

View file

@ -6,6 +6,7 @@ import com.simibubi.create.foundation.utility.Pair;
import com.simibubi.create.foundation.utility.VecHelper;
import mcp.MethodsReturnNonnullByDefault;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
@ -22,6 +23,11 @@ import java.util.stream.Collectors;
@MethodsReturnNonnullByDefault
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,
* 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);
}
/*@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) {
return orderedByDistance(pos, hit, dir -> dir.getAxis() == axis);
}

View file

@ -1,15 +1,26 @@
package com.simibubi.create.foundation.utility.placement;
import net.minecraft.advancements.CriteriaTriggers;
import net.minecraft.block.BlockState;
import net.minecraft.block.SoundType;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.ServerPlayerEntity;
import net.minecraft.fluid.Fluids;
import net.minecraft.fluid.IFluidState;
import net.minecraft.item.BlockItem;
import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemUseContext;
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.BlockRayTraceResult;
import net.minecraft.util.math.Vec3i;
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;
@ -55,25 +66,49 @@ public class PlacementOffset {
return world.getBlockState(new BlockPos(pos)).getMaterial().isReplaceable();
}
public void placeInWorld(World world, BlockItem blockItem, PlayerEntity player, ItemStack item) {
placeInWorld(world, blockItem.getBlock().getDefaultState(), player, item);
}
public void placeInWorld(World world, BlockState defaultState, PlayerEntity player, ItemStack item) {
if (world.isRemote)
return;
public ActionResultType placeInWorld(World world, BlockItem blockItem, PlayerEntity player, Hand hand, BlockRayTraceResult ray) {
ItemUseContext context = new ItemUseContext(player, hand, ray);
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)) {
IFluidState fluidState = world.getFluidState(newPos);
state = state.with(BlockStateProperties.WATERLOGGED, fluidState.getFluid() == Fluids.WATER);
}
BlockSnapshot snapshot = BlockSnapshot.getBlockSnapshot(world, newPos);
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())
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.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.speedometer.title": "Rotation Speed",
"create.gui.stressometer.title": "Network Stress",