mirror of
https://github.com/Creators-of-Create/Create.git
synced 2024-11-15 23:14:12 +01:00
Merge branch 'mc1.15/dev' into mc1.16/dev
# Conflicts: # src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/ContraptionCollider.java # src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/bearing/SailBlockPlacementHelper.java # src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/PistonExtensionPoleBlock.java # src/main/java/com/simibubi/create/content/contraptions/components/structureMovement/piston/PistonPolePlacementHelper.java # src/main/java/com/simibubi/create/content/contraptions/relays/belt/BeltBlock.java # src/main/java/com/simibubi/create/content/contraptions/relays/elementary/CogWheelBlock.java # src/main/java/com/simibubi/create/content/contraptions/relays/elementary/CogwheelBlockItem.java # src/main/java/com/simibubi/create/content/contraptions/relays/elementary/ShaftBlock.java # src/main/java/com/simibubi/create/events/ClientEvents.java
This commit is contained in:
commit
51229ce517
@ -82,6 +82,12 @@ public class ContraptionCollider {
|
|||||||
PlayerType playerType = getPlayerType(entity);
|
PlayerType playerType = getPlayerType(entity);
|
||||||
if (playerType == PlayerType.REMOTE)
|
if (playerType == PlayerType.REMOTE)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (playerType == PlayerType.SERVER && entity instanceof ServerPlayerEntity) {
|
||||||
|
((ServerPlayerEntity) entity).connection.floatingTickCount = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (playerType == PlayerType.CLIENT)
|
if (playerType == PlayerType.CLIENT)
|
||||||
if (skipClientPlayer)
|
if (skipClientPlayer)
|
||||||
continue;
|
continue;
|
||||||
@ -192,7 +198,7 @@ public class ContraptionCollider {
|
|||||||
totalResponse = VecHelper.rotate(totalResponse, yawOffset, Axis.Y);
|
totalResponse = VecHelper.rotate(totalResponse, yawOffset, Axis.Y);
|
||||||
rotationMatrix.transpose();
|
rotationMatrix.transpose();
|
||||||
|
|
||||||
if (temporalCollision && playerType != PlayerType.SERVER) {
|
if (temporalCollision) {
|
||||||
double idealVerticalMotion = motionResponse.y;
|
double idealVerticalMotion = motionResponse.y;
|
||||||
if (idealVerticalMotion != entityMotion.y) {
|
if (idealVerticalMotion != entityMotion.y) {
|
||||||
entity.setMotion(entityMotion.mul(1, 0, 1)
|
entity.setMotion(entityMotion.mul(1, 0, 1)
|
||||||
@ -222,11 +228,6 @@ public class ContraptionCollider {
|
|||||||
if (!hardCollision && surfaceCollision.isFalse())
|
if (!hardCollision && surfaceCollision.isFalse())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (playerType == PlayerType.SERVER && entity instanceof ServerPlayerEntity) {
|
|
||||||
((ServerPlayerEntity) entity).connection.floatingTickCount = 0;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector3d allowedMovement = getAllowedMovement(totalResponse, entity);
|
Vector3d allowedMovement = getAllowedMovement(totalResponse, entity);
|
||||||
entity.setPosition(entityPosition.x + allowedMovement.x, entityPosition.y + allowedMovement.y,
|
entity.setPosition(entityPosition.x + allowedMovement.x, entityPosition.y + allowedMovement.y,
|
||||||
entityPosition.z + allowedMovement.z);
|
entityPosition.z + allowedMovement.z);
|
||||||
@ -241,12 +242,10 @@ public class ContraptionCollider {
|
|||||||
contraptionEntity.collidingEntities.put(entity, new MutableInt(0));
|
contraptionEntity.collidingEntities.put(entity, new MutableInt(0));
|
||||||
if (entity instanceof ItemEntity)
|
if (entity instanceof ItemEntity)
|
||||||
entityMotion = entityMotion.mul(.5f, 1, .5f);
|
entityMotion = entityMotion.mul(.5f, 1, .5f);
|
||||||
if (playerType != PlayerType.SERVER) {
|
|
||||||
contactPointMotion = contraptionEntity.getContactPointMotion(entityPosition);
|
contactPointMotion = contraptionEntity.getContactPointMotion(entityPosition);
|
||||||
allowedMovement = getAllowedMovement(contactPointMotion, entity);
|
allowedMovement = getAllowedMovement(contactPointMotion, entity);
|
||||||
entity.setPosition(entityPosition.x + allowedMovement.x,
|
entity.setPosition(entityPosition.x + allowedMovement.x, entityPosition.y,
|
||||||
entityPosition.y, entityPosition.z + allowedMovement.z);
|
entityPosition.z + allowedMovement.z);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
entity.setMotion(entityMotion);
|
entity.setMotion(entityMotion);
|
||||||
@ -259,8 +258,7 @@ public class ContraptionCollider {
|
|||||||
float limbSwing = MathHelper.sqrt(d0 * d0 + d1 * d1) * 4.0F;
|
float limbSwing = MathHelper.sqrt(d0 * d0 + d1 * d1) * 4.0F;
|
||||||
if (limbSwing > 1.0F)
|
if (limbSwing > 1.0F)
|
||||||
limbSwing = 1.0F;
|
limbSwing = 1.0F;
|
||||||
AllPackets.channel
|
AllPackets.channel.sendToServer(new ClientMotionPacket(entityMotion, true, limbSwing));
|
||||||
.sendToServer(new ClientMotionPacket(entityMotion, true, limbSwing));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,28 +1,21 @@
|
|||||||
package com.simibubi.create.content.contraptions.components.structureMovement.bearing;
|
package com.simibubi.create.content.contraptions.components.structureMovement.bearing;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
|
|
||||||
import com.simibubi.create.AllBlocks;
|
import com.simibubi.create.AllBlocks;
|
||||||
import com.simibubi.create.AllShapes;
|
import com.simibubi.create.AllShapes;
|
||||||
import com.simibubi.create.foundation.block.ProperDirectionalBlock;
|
import com.simibubi.create.foundation.block.ProperDirectionalBlock;
|
||||||
import com.simibubi.create.foundation.utility.DyeHelper;
|
import com.simibubi.create.foundation.utility.DyeHelper;
|
||||||
import com.simibubi.create.foundation.utility.Iterate;
|
import com.simibubi.create.foundation.utility.Iterate;
|
||||||
|
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.Block;
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
import net.minecraft.entity.LivingEntity;
|
import net.minecraft.entity.LivingEntity;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
import net.minecraft.item.BlockItem;
|
import net.minecraft.item.*;
|
||||||
import net.minecraft.item.BlockItemUseContext;
|
|
||||||
import net.minecraft.item.DyeColor;
|
|
||||||
import net.minecraft.item.ItemStack;
|
|
||||||
import net.minecraft.item.ShearsItem;
|
|
||||||
import net.minecraft.util.ActionResultType;
|
import net.minecraft.util.ActionResultType;
|
||||||
import net.minecraft.util.Direction;
|
import net.minecraft.util.Direction;
|
||||||
import net.minecraft.util.Hand;
|
import net.minecraft.util.Hand;
|
||||||
@ -35,6 +28,13 @@ import net.minecraft.util.math.vector.Vector3d;
|
|||||||
import net.minecraft.world.IBlockReader;
|
import net.minecraft.world.IBlockReader;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
public class SailBlock extends ProperDirectionalBlock {
|
public class SailBlock extends ProperDirectionalBlock {
|
||||||
|
|
||||||
public static SailBlock frame(Properties properties) {
|
public static SailBlock frame(Properties properties) {
|
||||||
@ -45,7 +45,9 @@ public class SailBlock extends ProperDirectionalBlock {
|
|||||||
return new SailBlock(properties, false);
|
return new SailBlock(properties, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean frame;
|
private static final int placementHelperId = PlacementHelpers.register(new PlacementHelper());
|
||||||
|
|
||||||
|
private final boolean frame;
|
||||||
|
|
||||||
protected SailBlock(Properties p_i48415_1_, boolean frame) {
|
protected SailBlock(Properties p_i48415_1_, boolean frame) {
|
||||||
super(p_i48415_1_);
|
super(p_i48415_1_);
|
||||||
@ -55,24 +57,24 @@ public class SailBlock extends ProperDirectionalBlock {
|
|||||||
@Override
|
@Override
|
||||||
public BlockState getStateForPlacement(BlockItemUseContext context) {
|
public BlockState getStateForPlacement(BlockItemUseContext context) {
|
||||||
BlockState state = super.getStateForPlacement(context);
|
BlockState state = super.getStateForPlacement(context);
|
||||||
return state.with(FACING, state.get(FACING)
|
return state.with(FACING, state.get(FACING).getOpposite());
|
||||||
.getOpposite());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@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);
|
||||||
|
|
||||||
if (AllBlocks.SAIL.isIn(heldItem) || AllBlocks.SAIL_FRAME.isIn(heldItem)) {
|
if (AllBlocks.SAIL.isIn(heldItem) || AllBlocks.SAIL_FRAME.isIn(heldItem)) {
|
||||||
Direction offset =
|
IPlacementHelper placementHelper = PlacementHelpers.get(placementHelperId);
|
||||||
SailBlockPlacementHelper.getPlacementOffset(world, state.get(FACING), pos, ray.getHitVec());
|
PlacementOffset offset = placementHelper.getOffset(world, state, pos, ray);
|
||||||
if (offset == null)
|
|
||||||
return ActionResultType.SUCCESS;
|
if (!offset.isSuccessful())
|
||||||
|
return ActionResultType.PASS;
|
||||||
|
|
||||||
BlockState blockState = ((BlockItem) heldItem.getItem()).getBlock()
|
BlockState blockState = ((BlockItem) heldItem.getItem()).getBlock()
|
||||||
.getDefaultState()
|
.getDefaultState()
|
||||||
.with(FACING, state.get(FACING));
|
.with(FACING, state.get(FACING));
|
||||||
BlockPos offsetPos = pos.offset(offset);
|
BlockPos offsetPos = new BlockPos(offset.getPos());
|
||||||
if (!world.isRemote && world.getBlockState(offsetPos)
|
if (!world.isRemote && world.getBlockState(offsetPos)
|
||||||
.getMaterial()
|
.getMaterial()
|
||||||
.isReplaceable()) {
|
.isReplaceable()) {
|
||||||
@ -163,22 +165,19 @@ public class SailBlock extends ProperDirectionalBlock {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public VoxelShape getShape(BlockState state, IBlockReader p_220053_2_, BlockPos p_220053_3_,
|
public VoxelShape getShape(BlockState state, IBlockReader p_220053_2_, BlockPos p_220053_3_, ISelectionContext p_220053_4_) {
|
||||||
ISelectionContext p_220053_4_) {
|
|
||||||
return (frame ? AllShapes.SAIL_FRAME : AllShapes.SAIL).get(state.get(FACING));
|
return (frame ? AllShapes.SAIL_FRAME : AllShapes.SAIL).get(state.get(FACING));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public VoxelShape getCollisionShape(BlockState state, IBlockReader p_220071_2_, BlockPos p_220071_3_,
|
public VoxelShape getCollisionShape(BlockState state, IBlockReader p_220071_2_, BlockPos p_220071_3_, ISelectionContext p_220071_4_) {
|
||||||
ISelectionContext p_220071_4_) {
|
|
||||||
if (frame)
|
if (frame)
|
||||||
return AllShapes.SAIL_FRAME_COLLISION.get(state.get(FACING));
|
return AllShapes.SAIL_FRAME_COLLISION.get(state.get(FACING));
|
||||||
return getShape(state, p_220071_2_, p_220071_3_, p_220071_4_);
|
return getShape(state, p_220071_2_, p_220071_3_, p_220071_4_);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ItemStack getPickBlock(BlockState state, RayTraceResult target, IBlockReader world, BlockPos pos,
|
public ItemStack getPickBlock(BlockState state, RayTraceResult target, IBlockReader world, BlockPos pos, PlayerEntity player) {
|
||||||
PlayerEntity player) {
|
|
||||||
ItemStack pickBlock = super.getPickBlock(state, target, world, pos, player);
|
ItemStack pickBlock = super.getPickBlock(state, target, world, pos, player);
|
||||||
if (pickBlock.isEmpty())
|
if (pickBlock.isEmpty())
|
||||||
return AllBlocks.SAIL.get()
|
return AllBlocks.SAIL.get()
|
||||||
@ -209,4 +208,32 @@ public class SailBlock extends ProperDirectionalBlock {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@MethodsReturnNonnullByDefault
|
||||||
|
private static class PlacementHelper implements IPlacementHelper {
|
||||||
|
@Override
|
||||||
|
public Predicate<ItemStack> getItemPredicate() {
|
||||||
|
return i -> AllBlocks.SAIL.isIn(i) || AllBlocks.SAIL_FRAME.isIn(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Predicate<BlockState> getStatePredicate() {
|
||||||
|
return s -> s.getBlock() instanceof SailBlock;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PlacementOffset getOffset(World world, BlockState state, BlockPos pos, BlockRayTraceResult ray) {
|
||||||
|
List<Direction> directions = IPlacementHelper.orderedByDistanceExceptAxis(pos, ray.getHitVec(), state.get(SailBlock.FACING).getAxis(), dir -> world.getBlockState(pos.offset(dir)).getMaterial().isReplaceable());
|
||||||
|
|
||||||
|
if (directions.isEmpty())
|
||||||
|
return PlacementOffset.fail();
|
||||||
|
else {
|
||||||
|
return PlacementOffset.success(pos.offset(directions.get(0)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void renderAt(BlockPos pos, BlockState state, BlockRayTraceResult ray, PlacementOffset offset) {
|
||||||
|
IPlacementHelper.renderArrow(VecHelper.getCenterOf(pos), VecHelper.getCenterOf(offset.getPos()), state.get(FACING));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,101 +0,0 @@
|
|||||||
package com.simibubi.create.content.contraptions.components.structureMovement.bearing;
|
|
||||||
|
|
||||||
import com.simibubi.create.AllBlocks;
|
|
||||||
import com.simibubi.create.CreateClient;
|
|
||||||
import com.simibubi.create.foundation.utility.Iterate;
|
|
||||||
import com.simibubi.create.foundation.utility.VecHelper;
|
|
||||||
|
|
||||||
import net.minecraft.block.BlockState;
|
|
||||||
import net.minecraft.client.Minecraft;
|
|
||||||
import net.minecraft.client.entity.player.ClientPlayerEntity;
|
|
||||||
import net.minecraft.client.world.ClientWorld;
|
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
|
||||||
import net.minecraft.item.ItemStack;
|
|
||||||
import net.minecraft.util.Direction;
|
|
||||||
import net.minecraft.util.Hand;
|
|
||||||
import net.minecraft.util.math.BlockPos;
|
|
||||||
import net.minecraft.util.math.BlockRayTraceResult;
|
|
||||||
import net.minecraft.util.math.RayTraceResult;
|
|
||||||
import net.minecraft.util.math.vector.Vector3d;
|
|
||||||
import net.minecraft.world.World;
|
|
||||||
import net.minecraftforge.api.distmarker.Dist;
|
|
||||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
|
||||||
|
|
||||||
public class SailBlockPlacementHelper {
|
|
||||||
|
|
||||||
@OnlyIn(Dist.CLIENT)
|
|
||||||
public static void tick() {
|
|
||||||
Minecraft mc = Minecraft.getInstance();
|
|
||||||
RayTraceResult objectMouseOver = mc.objectMouseOver;
|
|
||||||
ClientWorld world = mc.world;
|
|
||||||
ClientPlayerEntity player = mc.player;
|
|
||||||
if (!(objectMouseOver instanceof BlockRayTraceResult))
|
|
||||||
return;
|
|
||||||
BlockRayTraceResult ray = (BlockRayTraceResult) objectMouseOver;
|
|
||||||
if (!isHoldingSail(player))
|
|
||||||
return;
|
|
||||||
BlockPos pos = ray.getPos();
|
|
||||||
BlockState blockState = world.getBlockState(pos);
|
|
||||||
if (!(blockState.getBlock() instanceof SailBlock))
|
|
||||||
return;
|
|
||||||
|
|
||||||
Direction sailFacing = blockState.get(SailBlock.FACING);
|
|
||||||
Direction offset = getPlacementOffset(world, sailFacing, pos, ray.getHitVec());
|
|
||||||
if (offset == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
Vector3d centerOf = VecHelper.getCenterOf(pos);
|
|
||||||
Vector3d offsetVec = Vector3d.of(offset.getDirectionVec());
|
|
||||||
|
|
||||||
if (!world.getBlockState(pos.offset(offset))
|
|
||||||
.getMaterial()
|
|
||||||
.isReplaceable())
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (Direction caretDirection : Iterate.directions) {
|
|
||||||
if (caretDirection.getAxis() == offset.getAxis())
|
|
||||||
continue;
|
|
||||||
if (caretDirection.getAxis() == sailFacing.getAxis())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
Vector3d otherOffset = Vector3d.of(caretDirection.getDirectionVec()).scale(.25f);
|
|
||||||
Vector3d start = offsetVec.scale(.75f)
|
|
||||||
.add(otherOffset);
|
|
||||||
Vector3d target = centerOf.add(offsetVec);
|
|
||||||
CreateClient.outliner.showLine("sailHelp" + caretDirection, centerOf.add(start), target)
|
|
||||||
.lineWidth(1 / 16f);
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean isHoldingSail(PlayerEntity player) {
|
|
||||||
for (Hand hand : Hand.values()) {
|
|
||||||
ItemStack heldItem = player.getHeldItem(hand);
|
|
||||||
if (AllBlocks.SAIL.isIn(heldItem) || AllBlocks.SAIL_FRAME.isIn(heldItem))
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Direction getPlacementOffset(World world, Direction sailDirection, BlockPos pos, Vector3d hit) {
|
|
||||||
Direction argMin = null;
|
|
||||||
float min = Float.MAX_VALUE;
|
|
||||||
Vector3d diffFromCentre = hit.subtract(VecHelper.getCenterOf(pos));
|
|
||||||
for (Direction side : Iterate.directions) {
|
|
||||||
if (side.getAxis() == sailDirection.getAxis())
|
|
||||||
continue;
|
|
||||||
if (!world.getBlockState(pos.offset(side))
|
|
||||||
.getMaterial()
|
|
||||||
.isReplaceable())
|
|
||||||
continue;
|
|
||||||
float distance = (float) Vector3d.of(side.getDirectionVec()).distanceTo(diffFromCentre);
|
|
||||||
if (distance > min)
|
|
||||||
continue;
|
|
||||||
min = distance;
|
|
||||||
argMin = side;
|
|
||||||
}
|
|
||||||
return argMin;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -77,7 +77,7 @@ public class PistonContraption extends TranslatingContraption {
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (blockState.get(MechanicalPistonBlock.STATE) == PistonState.EXTENDED) {
|
if (blockState.get(MechanicalPistonBlock.STATE) == PistonState.EXTENDED) {
|
||||||
while (PistonPolePlacementHelper.matchesAxis(nextBlock, direction.getAxis()) || isPistonHead(nextBlock) && nextBlock.get(FACING) == direction) {
|
while (PistonExtensionPoleBlock.PlacementHelper.get().matchesAxis(nextBlock, direction.getAxis()) || isPistonHead(nextBlock) && nextBlock.get(FACING) == direction) {
|
||||||
|
|
||||||
actualStart = actualStart.offset(direction);
|
actualStart = actualStart.offset(direction);
|
||||||
poles.add(new BlockInfo(actualStart, nextBlock.with(FACING, direction), null));
|
poles.add(new BlockInfo(actualStart, nextBlock.with(FACING, direction), null));
|
||||||
@ -104,7 +104,7 @@ public class PistonContraption extends TranslatingContraption {
|
|||||||
nextBlock = world.getBlockState(end.offset(direction.getOpposite()));
|
nextBlock = world.getBlockState(end.offset(direction.getOpposite()));
|
||||||
int extensionsInBack = 0;
|
int extensionsInBack = 0;
|
||||||
|
|
||||||
while (PistonPolePlacementHelper.matchesAxis(nextBlock, direction.getAxis())) {
|
while (PistonExtensionPoleBlock.PlacementHelper.get().matchesAxis(nextBlock, direction.getAxis())) {
|
||||||
end = end.offset(direction.getOpposite());
|
end = end.offset(direction.getOpposite());
|
||||||
poles.add(new BlockInfo(end, nextBlock.with(FACING, direction), null));
|
poles.add(new BlockInfo(end, nextBlock.with(FACING, direction), null));
|
||||||
extensionsInBack++;
|
extensionsInBack++;
|
||||||
|
@ -9,8 +9,11 @@ import com.simibubi.create.AllShapes;
|
|||||||
import com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.PistonState;
|
import com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.PistonState;
|
||||||
import com.simibubi.create.content.contraptions.wrench.IWrenchable;
|
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.Pair;
|
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;
|
import net.minecraft.block.Block;
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
import net.minecraft.block.IWaterLoggable;
|
import net.minecraft.block.IWaterLoggable;
|
||||||
@ -35,11 +38,17 @@ import net.minecraft.world.IBlockReader;
|
|||||||
import net.minecraft.world.IWorld;
|
import net.minecraft.world.IWorld;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
|
import static com.simibubi.create.content.contraptions.components.structureMovement.piston.MechanicalPistonBlock.*;
|
||||||
|
|
||||||
public class PistonExtensionPoleBlock extends ProperDirectionalBlock implements IWrenchable, IWaterLoggable {
|
public class PistonExtensionPoleBlock extends ProperDirectionalBlock implements IWrenchable, IWaterLoggable {
|
||||||
|
|
||||||
|
private static final int placementHelperId = PlacementHelpers.register(PlacementHelper.get());
|
||||||
|
|
||||||
public PistonExtensionPoleBlock(Properties properties) {
|
public PistonExtensionPoleBlock(Properties properties) {
|
||||||
super(properties);
|
super(properties);
|
||||||
setDefaultState(getDefaultState().with(FACING, Direction.UP)
|
setDefaultState(getDefaultState().with(FACING, Direction.UP).with(BlockStateProperties.WATERLOGGED, false));
|
||||||
.with(BlockStateProperties.WATERLOGGED, false));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -113,24 +122,21 @@ public class PistonExtensionPoleBlock extends ProperDirectionalBlock implements
|
|||||||
ItemStack heldItem = player.getHeldItem(hand);
|
ItemStack heldItem = player.getHeldItem(hand);
|
||||||
|
|
||||||
if (AllBlocks.PISTON_EXTENSION_POLE.isIn(heldItem) && !player.isSneaking()) {
|
if (AllBlocks.PISTON_EXTENSION_POLE.isIn(heldItem) && !player.isSneaking()) {
|
||||||
Pair<Direction, Integer> offset = PistonPolePlacementHelper.getPlacementOffset(world, state.get(FACING)
|
IPlacementHelper placementHelper = PlacementHelpers.get(placementHelperId);
|
||||||
.getAxis(), pos, ray.getHitVec());
|
PlacementOffset offset = placementHelper.getOffset(world, state, pos, ray);
|
||||||
|
|
||||||
if (offset == null || offset.getSecond() == 0)
|
if (!offset.isSuccessful())
|
||||||
return ActionResultType.PASS;
|
return ActionResultType.PASS;
|
||||||
|
|
||||||
BlockPos newPos = pos.offset(offset.getFirst(), offset.getSecond());
|
BlockPos newPos = new BlockPos(offset.getPos());
|
||||||
|
|
||||||
if (!world.getBlockState(newPos)
|
if (!world.getBlockState(newPos).getMaterial().isReplaceable())
|
||||||
.getMaterial()
|
|
||||||
.isReplaceable())
|
|
||||||
return ActionResultType.PASS;
|
return ActionResultType.PASS;
|
||||||
|
|
||||||
if (world.isRemote)
|
if (world.isRemote)
|
||||||
return ActionResultType.SUCCESS;
|
return ActionResultType.SUCCESS;
|
||||||
|
|
||||||
world.setBlockState(newPos, AllBlocks.PISTON_EXTENSION_POLE.getDefaultState()
|
world.setBlockState(newPos, offset.getTransform().apply(AllBlocks.PISTON_EXTENSION_POLE.getDefaultState()));
|
||||||
.with(FACING, state.get(FACING)));
|
|
||||||
if (!player.isCreative())
|
if (!player.isCreative())
|
||||||
heldItem.shrink(1);
|
heldItem.shrink(1);
|
||||||
|
|
||||||
@ -153,12 +159,33 @@ public class PistonExtensionPoleBlock extends ProperDirectionalBlock implements
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BlockState updatePostPlacement(BlockState state, Direction direction, BlockState neighbourState,
|
public BlockState updatePostPlacement(BlockState state, Direction direction, BlockState neighbourState, IWorld world, BlockPos pos, BlockPos neighbourPos) {
|
||||||
IWorld world, BlockPos pos, BlockPos neighbourPos) {
|
|
||||||
if (state.get(BlockStateProperties.WATERLOGGED)) {
|
if (state.get(BlockStateProperties.WATERLOGGED)) {
|
||||||
world.getPendingFluidTicks()
|
world.getPendingFluidTicks().scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickRate(world));
|
||||||
.scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickRate(world));
|
|
||||||
}
|
}
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@MethodsReturnNonnullByDefault
|
||||||
|
public static class PlacementHelper extends PoleHelper<Direction> {
|
||||||
|
|
||||||
|
private static final PlacementHelper instance = new PlacementHelper();
|
||||||
|
|
||||||
|
public static PlacementHelper get() {
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
private PlacementHelper(){
|
||||||
|
super(
|
||||||
|
AllBlocks.PISTON_EXTENSION_POLE::has,
|
||||||
|
state -> state.get(FACING).getAxis(),
|
||||||
|
FACING
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Predicate<ItemStack> getItemPredicate() {
|
||||||
|
return AllBlocks.PISTON_EXTENSION_POLE::isIn;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,130 +0,0 @@
|
|||||||
package com.simibubi.create.content.contraptions.components.structureMovement.piston;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
|
|
||||||
import com.simibubi.create.AllBlocks;
|
|
||||||
import com.simibubi.create.CreateClient;
|
|
||||||
import com.simibubi.create.foundation.utility.Iterate;
|
|
||||||
import com.simibubi.create.foundation.utility.Pair;
|
|
||||||
import com.simibubi.create.foundation.utility.VecHelper;
|
|
||||||
|
|
||||||
import net.minecraft.block.BlockState;
|
|
||||||
import net.minecraft.client.Minecraft;
|
|
||||||
import net.minecraft.client.world.ClientWorld;
|
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
|
||||||
import net.minecraft.util.Direction;
|
|
||||||
import net.minecraft.util.Hand;
|
|
||||||
import net.minecraft.util.math.BlockPos;
|
|
||||||
import net.minecraft.util.math.BlockRayTraceResult;
|
|
||||||
import net.minecraft.util.math.vector.Vector3d;
|
|
||||||
import net.minecraft.world.World;
|
|
||||||
import net.minecraftforge.api.distmarker.Dist;
|
|
||||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
|
||||||
|
|
||||||
public class PistonPolePlacementHelper {
|
|
||||||
|
|
||||||
@OnlyIn(Dist.CLIENT)
|
|
||||||
public static void tick() {
|
|
||||||
Minecraft mc = Minecraft.getInstance();
|
|
||||||
ClientWorld world = mc.world;
|
|
||||||
|
|
||||||
if (!(mc.objectMouseOver instanceof BlockRayTraceResult))
|
|
||||||
return;
|
|
||||||
|
|
||||||
BlockRayTraceResult ray = (BlockRayTraceResult) mc.objectMouseOver;
|
|
||||||
|
|
||||||
if (mc.player != null && !isHoldingPole(mc.player))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (mc.player.isSneaking())
|
|
||||||
return;
|
|
||||||
|
|
||||||
BlockPos pos = ray.getPos();
|
|
||||||
BlockState state = world.getBlockState(pos);
|
|
||||||
if (!(state.getBlock() instanceof PistonExtensionPoleBlock))
|
|
||||||
return;
|
|
||||||
|
|
||||||
Pair<Direction, Integer> offset = getPlacementOffset(world, state.get(PistonExtensionPoleBlock.FACING).getAxis(), pos, ray.getHitVec());
|
|
||||||
if (offset == null || offset.getSecond() == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
Direction hitFace = ray.getFace();
|
|
||||||
|
|
||||||
if (hitFace.getAxis() == offset.getFirst().getAxis())
|
|
||||||
return;
|
|
||||||
|
|
||||||
Vector3d hitCenter = VecHelper.getCenterOf(pos).add(Vector3d.of(hitFace.getDirectionVec()).scale(0.3));
|
|
||||||
|
|
||||||
//get the two perpendicular directions to form the arrow
|
|
||||||
Direction[] directions = Arrays.stream(Direction.Axis.values()).filter(axis -> axis != hitFace.getAxis() && axis != offset.getFirst().getAxis()).map(Iterate::directionsInAxis).findFirst().orElse(new Direction[]{});
|
|
||||||
Vector3d startOffset = Vector3d.of(offset.getFirst().getDirectionVec());
|
|
||||||
Vector3d start = hitCenter.add(startOffset);
|
|
||||||
for (Direction dir : directions) {
|
|
||||||
Vector3d arrowOffset = Vector3d.of(dir.getDirectionVec()).scale(.25);
|
|
||||||
Vector3d target = hitCenter.add(startOffset.scale(0.75)).add(arrowOffset);
|
|
||||||
CreateClient.outliner.showLine("poleHelp" + offset.getFirst() + dir, start, target).lineWidth(1/16f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// first indicates the direction that the position needs to be offset into
|
|
||||||
// second indicates by how many blocks the position needs to be offset by; is 0 if there was no valid position on either end of the pole
|
|
||||||
public static Pair<Direction, Integer> getPlacementOffset(World world, Direction.Axis poleAxis, BlockPos pos, Vector3d hit) {
|
|
||||||
Pair<Direction, Integer> offset = null;
|
|
||||||
double min = Double.MAX_VALUE;
|
|
||||||
Vector3d localPos = hit.subtract(VecHelper.getCenterOf(pos));
|
|
||||||
|
|
||||||
//find target direction
|
|
||||||
for (Direction dir : Iterate.directionsInAxis(poleAxis)) {
|
|
||||||
double distance = Vector3d.of(dir.getDirectionVec()).distanceTo(localPos);
|
|
||||||
if (distance > min)
|
|
||||||
continue;
|
|
||||||
min = distance;
|
|
||||||
offset = Pair.of(dir, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (offset == null)//??
|
|
||||||
return null;
|
|
||||||
|
|
||||||
//check for space at the end of the pole
|
|
||||||
int poles = attachedPoles(world, pos, offset.getFirst());
|
|
||||||
BlockState state = world.getBlockState(pos.offset(offset.getFirst(), poles + 1));
|
|
||||||
|
|
||||||
if (state.getMaterial().isReplaceable()) {
|
|
||||||
offset.setSecond(poles + 1);
|
|
||||||
return offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
//check the other end of the pole
|
|
||||||
offset.setFirst(offset.getFirst().getOpposite());
|
|
||||||
poles = attachedPoles(world, pos, offset.getFirst());
|
|
||||||
state = world.getBlockState(pos.offset(offset.getFirst(), poles + 1));
|
|
||||||
|
|
||||||
if (state.getMaterial().isReplaceable()) {
|
|
||||||
offset.setSecond(poles + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int attachedPoles(World world, BlockPos pos, Direction direction) {
|
|
||||||
BlockPos checkPos = pos.offset(direction);
|
|
||||||
BlockState state = world.getBlockState(checkPos);
|
|
||||||
int count = 0;
|
|
||||||
while (matchesAxis(state, direction.getAxis())) {
|
|
||||||
count++;
|
|
||||||
checkPos = checkPos.offset(direction);
|
|
||||||
state = world.getBlockState(checkPos);
|
|
||||||
}
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
//checks if the given state is a piston pole on the given axis
|
|
||||||
public static boolean matchesAxis(BlockState state, Direction.Axis axis) {
|
|
||||||
return AllBlocks.PISTON_EXTENSION_POLE.has(state) && state.get(PistonExtensionPoleBlock.FACING).getAxis() == axis;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean isHoldingPole(PlayerEntity player) {
|
|
||||||
return Arrays.stream(Hand.values()).anyMatch(hand -> AllBlocks.PISTON_EXTENSION_POLE.isIn(player.getHeldItem(hand)));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -10,7 +10,6 @@ import com.simibubi.create.AllItems;
|
|||||||
import com.simibubi.create.CreateClient;
|
import com.simibubi.create.CreateClient;
|
||||||
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.content.contraptions.components.structureMovement.piston.PistonPolePlacementHelper;
|
|
||||||
import com.simibubi.create.foundation.config.AllConfigs;
|
import com.simibubi.create.foundation.config.AllConfigs;
|
||||||
import com.simibubi.create.foundation.gui.GuiGameElement;
|
import com.simibubi.create.foundation.gui.GuiGameElement;
|
||||||
import com.simibubi.create.foundation.tileEntity.behaviour.ValueBox;
|
import com.simibubi.create.foundation.tileEntity.behaviour.ValueBox;
|
||||||
@ -18,7 +17,6 @@ import com.simibubi.create.foundation.utility.Iterate;
|
|||||||
import com.simibubi.create.foundation.utility.Lang;
|
import com.simibubi.create.foundation.utility.Lang;
|
||||||
import com.simibubi.create.foundation.utility.outliner.Outline;
|
import com.simibubi.create.foundation.utility.outliner.Outline;
|
||||||
import com.simibubi.create.foundation.utility.outliner.Outliner.OutlineEntry;
|
import com.simibubi.create.foundation.utility.outliner.Outliner.OutlineEntry;
|
||||||
|
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.client.gui.screen.Screen;
|
import net.minecraft.client.gui.screen.Screen;
|
||||||
@ -106,7 +104,7 @@ public class GoggleOverlayRenderer {
|
|||||||
int poles = 1;
|
int poles = 1;
|
||||||
boolean pistonFound = false;
|
boolean pistonFound = false;
|
||||||
for (Direction dir : directions) {
|
for (Direction dir : directions) {
|
||||||
int attachedPoles = PistonPolePlacementHelper.attachedPoles(world, pos, dir);
|
int attachedPoles = PistonExtensionPoleBlock.PlacementHelper.get().attachedPoles(world, pos, dir);
|
||||||
poles += attachedPoles;
|
poles += attachedPoles;
|
||||||
pistonFound |= world.getBlockState(pos.offset(dir, attachedPoles + 1))
|
pistonFound |= world.getBlockState(pos.offset(dir, attachedPoles + 1))
|
||||||
.getBlock() instanceof MechanicalPistonBlock;
|
.getBlock() instanceof MechanicalPistonBlock;
|
||||||
|
@ -437,9 +437,15 @@ public class BeltBlock extends HorizontalKineticBlock implements ITE<BeltTileEnt
|
|||||||
return;
|
return;
|
||||||
if (isMoving)
|
if (isMoving)
|
||||||
return;
|
return;
|
||||||
TileEntity belt = world.getTileEntity(pos);
|
|
||||||
if (belt instanceof BeltTileEntity)
|
TileEntity te = world.getTileEntity(pos);
|
||||||
belt.remove();
|
if (te instanceof BeltTileEntity) {
|
||||||
|
BeltTileEntity beltTileEntity = (BeltTileEntity) te;
|
||||||
|
if (beltTileEntity.isController())
|
||||||
|
beltTileEntity.getInventory()
|
||||||
|
.ejectAll();
|
||||||
|
world.removeTileEntity(pos);
|
||||||
|
}
|
||||||
|
|
||||||
// Destroy chain
|
// Destroy chain
|
||||||
for (boolean forward : Iterate.trueAndFalse) {
|
for (boolean forward : Iterate.trueAndFalse) {
|
||||||
@ -453,13 +459,13 @@ public class BeltBlock extends HorizontalKineticBlock implements ITE<BeltTileEnt
|
|||||||
boolean hasPulley = false;
|
boolean hasPulley = false;
|
||||||
TileEntity tileEntity = world.getTileEntity(currentPos);
|
TileEntity tileEntity = world.getTileEntity(currentPos);
|
||||||
if (tileEntity instanceof BeltTileEntity) {
|
if (tileEntity instanceof BeltTileEntity) {
|
||||||
BeltTileEntity te = (BeltTileEntity) tileEntity;
|
BeltTileEntity belt = (BeltTileEntity) tileEntity;
|
||||||
if (te.isController())
|
if (belt.isController())
|
||||||
te.getInventory()
|
belt.getInventory()
|
||||||
.ejectAll();
|
.ejectAll();
|
||||||
|
|
||||||
te.remove();
|
belt.remove();
|
||||||
hasPulley = te.hasPulley();
|
hasPulley = belt.hasPulley();
|
||||||
}
|
}
|
||||||
|
|
||||||
BlockState shaftState = AllBlocks.SHAFT.getDefaultState()
|
BlockState shaftState = AllBlocks.SHAFT.getDefaultState()
|
||||||
|
@ -5,7 +5,6 @@ import com.simibubi.create.AllShapes;
|
|||||||
import com.simibubi.create.content.contraptions.base.IRotate;
|
import com.simibubi.create.content.contraptions.base.IRotate;
|
||||||
import com.simibubi.create.content.contraptions.relays.advanced.SpeedControllerBlock;
|
import com.simibubi.create.content.contraptions.relays.advanced.SpeedControllerBlock;
|
||||||
import com.simibubi.create.foundation.utility.Iterate;
|
import com.simibubi.create.foundation.utility.Iterate;
|
||||||
|
|
||||||
import net.minecraft.block.Block;
|
import net.minecraft.block.Block;
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
import net.minecraft.fluid.FluidState;
|
import net.minecraft.fluid.FluidState;
|
||||||
@ -69,9 +68,7 @@ public class CogWheelBlock extends AbstractShaftBlock {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BlockState getStateForPlacement(BlockItemUseContext context) {
|
public BlockState getStateForPlacement(BlockItemUseContext context) {
|
||||||
BlockPos placedOnPos = context.getPos()
|
BlockPos placedOnPos = context.getPos().offset(context.getFace().getOpposite());
|
||||||
.offset(context.getFace()
|
|
||||||
.getOpposite());
|
|
||||||
World world = context.getWorld();
|
World world = context.getWorld();
|
||||||
BlockState placedAgainst = world.getBlockState(placedOnPos);
|
BlockState placedAgainst = world.getBlockState(placedOnPos);
|
||||||
Block block = placedAgainst.getBlock();
|
Block block = placedAgainst.getBlock();
|
||||||
@ -80,7 +77,8 @@ public class CogWheelBlock extends AbstractShaftBlock {
|
|||||||
.down());
|
.down());
|
||||||
FluidState FluidState = context.getWorld().getFluidState(context.getPos());
|
FluidState FluidState = context.getWorld().getFluidState(context.getPos());
|
||||||
if (AllBlocks.ROTATION_SPEED_CONTROLLER.has(stateBelow) && isLarge) {
|
if (AllBlocks.ROTATION_SPEED_CONTROLLER.has(stateBelow) && isLarge) {
|
||||||
return this.getDefaultState().with(BlockStateProperties.WATERLOGGED, Boolean.valueOf(FluidState.getFluid() == Fluids.WATER))
|
return this.getDefaultState()
|
||||||
|
.with(BlockStateProperties.WATERLOGGED, FluidState.getFluid() == Fluids.WATER)
|
||||||
.with(AXIS, stateBelow.get(SpeedControllerBlock.HORIZONTAL_AXIS) == Axis.X ? Axis.Z : Axis.X);
|
.with(AXIS, stateBelow.get(SpeedControllerBlock.HORIZONTAL_AXIS) == Axis.X ? Axis.Z : Axis.X);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,10 +87,11 @@ public class CogWheelBlock extends AbstractShaftBlock {
|
|||||||
Axis preferredAxis = getPreferredAxis(context);
|
Axis preferredAxis = getPreferredAxis(context);
|
||||||
if (preferredAxis != null)
|
if (preferredAxis != null)
|
||||||
return this.getDefaultState()
|
return this.getDefaultState()
|
||||||
.with(AXIS, preferredAxis).with(BlockStateProperties.WATERLOGGED, Boolean.valueOf(FluidState.getFluid() == Fluids.WATER));
|
.with(AXIS, preferredAxis)
|
||||||
|
.with(BlockStateProperties.WATERLOGGED, FluidState.getFluid() == Fluids.WATER);
|
||||||
return this.getDefaultState()
|
return this.getDefaultState()
|
||||||
.with(AXIS, context.getFace()
|
.with(AXIS, context.getFace().getAxis())
|
||||||
.getAxis()).with(BlockStateProperties.WATERLOGGED, Boolean.valueOf(FluidState.getFluid() == Fluids.WATER));
|
.with(BlockStateProperties.WATERLOGGED, FluidState.getFluid() == Fluids.WATER);
|
||||||
}
|
}
|
||||||
|
|
||||||
return getDefaultState().with(AXIS, ((IRotate) block).getRotationAxis(placedAgainst));
|
return getDefaultState().with(AXIS, ((IRotate) block).getRotationAxis(placedAgainst));
|
||||||
|
@ -1,38 +1,77 @@
|
|||||||
package com.simibubi.create.content.contraptions.relays.elementary;
|
package com.simibubi.create.content.contraptions.relays.elementary;
|
||||||
|
|
||||||
import com.simibubi.create.AllBlocks;
|
import com.simibubi.create.AllBlocks;
|
||||||
|
import com.simibubi.create.AllShapes;
|
||||||
import com.simibubi.create.foundation.advancement.AllTriggers;
|
import com.simibubi.create.foundation.advancement.AllTriggers;
|
||||||
import com.simibubi.create.foundation.utility.Iterate;
|
import com.simibubi.create.foundation.utility.Iterate;
|
||||||
import com.simibubi.create.foundation.utility.VecHelper;
|
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.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.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;
|
||||||
import net.minecraft.util.Direction.AxisDirection;
|
import net.minecraft.util.Direction.AxisDirection;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.util.math.vector.Vector3d;
|
import net.minecraft.util.math.vector.Vector3d;
|
||||||
|
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.relays.elementary.CogWheelBlock.AXIS;
|
||||||
|
|
||||||
public class CogwheelBlockItem extends BlockItem {
|
public class CogwheelBlockItem extends BlockItem {
|
||||||
|
|
||||||
boolean large;
|
boolean large;
|
||||||
|
|
||||||
|
private final int placementHelperId;
|
||||||
|
|
||||||
public CogwheelBlockItem(CogWheelBlock block, Properties builder) {
|
public CogwheelBlockItem(CogWheelBlock block, Properties builder) {
|
||||||
super(block, builder);
|
super(block, builder);
|
||||||
large = block.isLarge;
|
large = block.isLarge;
|
||||||
|
|
||||||
|
placementHelperId = PlacementHelpers.register(large ? new LargeCogHelper() : new SmallCogHelper());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ActionResultType tryPlace(BlockItemUseContext context) {
|
public ActionResultType tryPlace(BlockItemUseContext context) {
|
||||||
Direction face = context.getFace();
|
IPlacementHelper helper = PlacementHelpers.get(placementHelperId);
|
||||||
BlockPos placedOnPos = context.getPos().offset(face.getOpposite());
|
World world = context.getWorld();
|
||||||
BlockState placedOnState = context.getWorld().getBlockState(placedOnPos);
|
BlockPos pos = context.getPos().offset(context.getFace().getOpposite());
|
||||||
|
BlockState state = world.getBlockState(pos);
|
||||||
|
|
||||||
if (!(placedOnState.getBlock() instanceof CogWheelBlock))
|
if (!helper.getStatePredicate().test(state))
|
||||||
|
return super.tryPlace(context);
|
||||||
|
|
||||||
|
PlacementOffset offset = helper.getOffset(world, state, pos, new BlockRayTraceResult(context.getHitVec(), context.getFace(), pos, true));
|
||||||
|
|
||||||
|
if (!offset.isSuccessful())
|
||||||
|
return super.tryPlace(context);
|
||||||
|
|
||||||
|
BlockPos newPos = new BlockPos(offset.getPos());
|
||||||
|
|
||||||
|
if (!world.getBlockState(newPos).getMaterial().isReplaceable())
|
||||||
|
return ActionResultType.PASS;
|
||||||
|
|
||||||
|
if (world.isRemote)
|
||||||
|
return ActionResultType.SUCCESS;
|
||||||
|
|
||||||
|
world.setBlockState(newPos, offset.getTransform().apply(this.getBlock().getDefaultState()));
|
||||||
|
if (context.getPlayer() != null && !context.getPlayer().isCreative()) {
|
||||||
|
context.getItem().shrink(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ActionResultType.SUCCESS;
|
||||||
|
|
||||||
|
/*if (!(placedOnState.getBlock() instanceof CogWheelBlock))
|
||||||
return super.tryPlace(context);
|
return super.tryPlace(context);
|
||||||
if (face.getAxis() == placedOnState.get(CogWheelBlock.AXIS))
|
if (face.getAxis() == placedOnState.get(CogWheelBlock.AXIS))
|
||||||
return super.tryPlace(context);
|
return super.tryPlace(context);
|
||||||
@ -67,7 +106,7 @@ public class CogwheelBlockItem extends BlockItem {
|
|||||||
return ActionResultType.FAIL;
|
return ActionResultType.FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return super.tryPlace(context);
|
return super.tryPlace(context);*/
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -107,4 +146,137 @@ public class CogwheelBlockItem extends BlockItem {
|
|||||||
return super.placeBlock(context, state);
|
return super.placeBlock(context, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@MethodsReturnNonnullByDefault
|
||||||
|
private static class SmallCogHelper extends DiagonalCogHelper {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Predicate<ItemStack> getItemPredicate() {
|
||||||
|
return AllBlocks.COGWHEEL::isIn;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PlacementOffset getOffset(World world, BlockState state, BlockPos pos, BlockRayTraceResult ray) {
|
||||||
|
if (hitOnShaft(state, ray))
|
||||||
|
return PlacementOffset.fail();
|
||||||
|
|
||||||
|
if (!((CogWheelBlock) state.getBlock()).isLarge) {
|
||||||
|
List<Direction> directions = IPlacementHelper.orderedByDistanceExceptAxis(pos, ray.getHitVec(), state.get(AXIS));
|
||||||
|
|
||||||
|
for (Direction dir : directions) {
|
||||||
|
BlockPos newPos = pos.offset(dir);
|
||||||
|
|
||||||
|
if (hasLargeCogwheelNeighbor(world, newPos, state.get(AXIS)))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!world.getBlockState(newPos).getMaterial().isReplaceable())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
return PlacementOffset.success(newPos, s -> s.with(AXIS, state.get(AXIS)));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return PlacementOffset.fail();
|
||||||
|
}
|
||||||
|
|
||||||
|
return super.getOffset(world, state, pos, ray);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void renderAt(BlockPos pos, BlockState state, BlockRayTraceResult ray, PlacementOffset offset) {
|
||||||
|
IPlacementHelper.renderArrow(VecHelper.getCenterOf(pos), VecHelper.getCenterOf(offset.getPos()), Direction.getFacingFromAxis(Direction.AxisDirection.POSITIVE, state.get(AXIS)), ((CogWheelBlock) state.getBlock()).isLarge ? 1.5D : 0.75D);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@MethodsReturnNonnullByDefault
|
||||||
|
private static class LargeCogHelper extends DiagonalCogHelper {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Predicate<ItemStack> getItemPredicate() {
|
||||||
|
return AllBlocks.LARGE_COGWHEEL::isIn;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PlacementOffset getOffset(World world, BlockState state, BlockPos pos, BlockRayTraceResult ray) {
|
||||||
|
if (hitOnShaft(state, ray))
|
||||||
|
return PlacementOffset.fail();
|
||||||
|
|
||||||
|
if (((CogWheelBlock) state.getBlock()).isLarge) {
|
||||||
|
Direction side = IPlacementHelper.orderedByDistanceOnlyAxis(pos, ray.getHitVec(), state.get(AXIS)).get(0);
|
||||||
|
List<Direction> directions = IPlacementHelper.orderedByDistanceExceptAxis(pos, ray.getHitVec(), state.get(AXIS));
|
||||||
|
for (Direction dir : directions) {
|
||||||
|
BlockPos newPos = pos.offset(dir).offset(side);
|
||||||
|
if (!world.getBlockState(newPos).getMaterial().isReplaceable())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
return PlacementOffset.success(newPos, s -> s.with(AXIS, dir.getAxis()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return PlacementOffset.fail();
|
||||||
|
}
|
||||||
|
|
||||||
|
return super.getOffset(world, state, pos, ray);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@MethodsReturnNonnullByDefault
|
||||||
|
private abstract static class DiagonalCogHelper implements IPlacementHelper {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Predicate<BlockState> getStatePredicate() {
|
||||||
|
return s -> s.getBlock() instanceof CogWheelBlock;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PlacementOffset getOffset(World world, BlockState state, BlockPos pos, BlockRayTraceResult ray) {
|
||||||
|
//diagonal gears of different size
|
||||||
|
Direction closest = IPlacementHelper.orderedByDistanceExceptAxis(pos, ray.getHitVec(), state.get(AXIS)).get(0);
|
||||||
|
List<Direction> directions = IPlacementHelper.orderedByDistanceExceptAxis(pos, ray.getHitVec(), state.get(AXIS), d -> d.getAxis() != closest.getAxis());
|
||||||
|
|
||||||
|
for (Direction dir : directions) {
|
||||||
|
BlockPos newPos = pos.offset(dir).offset(closest);
|
||||||
|
if (!world.getBlockState(newPos).getMaterial().isReplaceable())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (AllBlocks.COGWHEEL.has(state) && hasSmallCogwheelNeighbor(world, newPos, state.get(AXIS)))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
return PlacementOffset.success(newPos, s -> s.with(AXIS, state.get(AXIS)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return PlacementOffset.fail();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void renderAt(BlockPos pos, BlockState state, BlockRayTraceResult ray, PlacementOffset offset) {
|
||||||
|
IPlacementHelper.renderArrow(VecHelper.getCenterOf(pos), VecHelper.getCenterOf(offset.getPos()), Direction.getFacingFromAxis(Direction.AxisDirection.POSITIVE, state.get(AXIS)), 1D);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean hitOnShaft(BlockState state, BlockRayTraceResult ray) {
|
||||||
|
return AllShapes.SIX_VOXEL_POLE.get(state.get(AXIS)).getBoundingBox().grow(0.001).contains(ray.getHitVec().subtract(ray.getHitVec().align(Iterate.axisSet)));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean hasLargeCogwheelNeighbor(World world, BlockPos pos, Direction.Axis axis) {
|
||||||
|
for (Direction dir : Iterate.directions) {
|
||||||
|
if (dir.getAxis() == axis)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (AllBlocks.LARGE_COGWHEEL.has(world.getBlockState(pos.offset(dir))))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean hasSmallCogwheelNeighbor(World world, BlockPos pos, Direction.Axis axis) {
|
||||||
|
for (Direction dir : Iterate.directions) {
|
||||||
|
if (dir.getAxis() == axis)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (AllBlocks.COGWHEEL.has(world.getBlockState(pos.offset(dir))))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,14 +5,18 @@ import com.simibubi.create.AllShapes;
|
|||||||
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
|
import com.simibubi.create.content.contraptions.base.KineticTileEntity;
|
||||||
import com.simibubi.create.content.contraptions.relays.encased.EncasedShaftBlock;
|
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.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;
|
||||||
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.fluid.FluidState;
|
import net.minecraft.item.BlockItem;
|
||||||
import net.minecraft.fluid.Fluids;
|
|
||||||
import net.minecraft.item.BlockItemUseContext;
|
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.util.ActionResultType;
|
import net.minecraft.util.ActionResultType;
|
||||||
|
import net.minecraft.util.Direction;
|
||||||
import net.minecraft.util.Hand;
|
import net.minecraft.util.Hand;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.util.math.BlockRayTraceResult;
|
import net.minecraft.util.math.BlockRayTraceResult;
|
||||||
@ -21,8 +25,12 @@ 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 ShaftBlock extends AbstractShaftBlock {
|
public class ShaftBlock extends AbstractShaftBlock {
|
||||||
|
|
||||||
|
private static final int placementHelperId = PlacementHelpers.register(new PlacementHelper());
|
||||||
|
|
||||||
public ShaftBlock(Properties properties) {
|
public ShaftBlock(Properties properties) {
|
||||||
super(properties);
|
super(properties);
|
||||||
}
|
}
|
||||||
@ -48,7 +56,7 @@ public class ShaftBlock extends AbstractShaftBlock {
|
|||||||
|
|
||||||
@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 p_225533_6_) {
|
BlockRayTraceResult ray) {
|
||||||
if (player.isSneaking() || !player.isAllowEdit())
|
if (player.isSneaking() || !player.isAllowEdit())
|
||||||
return ActionResultType.PASS;
|
return ActionResultType.PASS;
|
||||||
|
|
||||||
@ -69,6 +77,52 @@ public class ShaftBlock extends AbstractShaftBlock {
|
|||||||
return ActionResultType.SUCCESS;
|
return ActionResultType.SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IPlacementHelper helper = PlacementHelpers.get(placementHelperId);
|
||||||
|
if (helper.getItemPredicate().test(heldItem)) {
|
||||||
|
PlacementOffset offset = helper.getOffset(world, state, pos, ray);
|
||||||
|
|
||||||
|
if (!offset.isSuccessful())
|
||||||
|
return ActionResultType.PASS;
|
||||||
|
|
||||||
|
BlockPos newPos = new BlockPos(offset.getPos());
|
||||||
|
|
||||||
|
if (!world.getBlockState(newPos).getMaterial().isReplaceable())
|
||||||
|
return ActionResultType.PASS;
|
||||||
|
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@MethodsReturnNonnullByDefault
|
||||||
|
private static class PlacementHelper extends PoleHelper<Direction.Axis> {
|
||||||
|
//used for extending a shaft in its axis, like the piston poles. works with shafts and cogs
|
||||||
|
|
||||||
|
private PlacementHelper(){
|
||||||
|
super(
|
||||||
|
state -> state.getBlock() instanceof AbstractShaftBlock,
|
||||||
|
state -> state.get(AXIS),
|
||||||
|
AXIS
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Predicate<ItemStack> getItemPredicate() {
|
||||||
|
return i -> i.getItem() instanceof BlockItem && ((BlockItem) i.getItem()).getBlock() instanceof AbstractShaftBlock;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Predicate<BlockState> getStatePredicate() {
|
||||||
|
return AllBlocks.SHAFT::has;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -177,16 +177,16 @@ public abstract class ArmInteractionPoint {
|
|||||||
return point;
|
return point;
|
||||||
}
|
}
|
||||||
|
|
||||||
CompoundNBT serialize() {
|
CompoundNBT serialize(BlockPos anchor) {
|
||||||
CompoundNBT nbt = new CompoundNBT();
|
CompoundNBT nbt = new CompoundNBT();
|
||||||
nbt.put("Pos", NBTUtil.writeBlockPos(pos));
|
nbt.put("Pos", NBTUtil.writeBlockPos(pos.subtract(anchor)));
|
||||||
NBTHelper.writeEnum(nbt, "Mode", mode);
|
NBTHelper.writeEnum(nbt, "Mode", mode);
|
||||||
return nbt;
|
return nbt;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ArmInteractionPoint deserialize(IBlockReader world, CompoundNBT nbt) {
|
static ArmInteractionPoint deserialize(IBlockReader world, BlockPos anchor, CompoundNBT nbt) {
|
||||||
BlockPos pos = NBTUtil.readBlockPos(nbt.getCompound("Pos"));
|
BlockPos pos = NBTUtil.readBlockPos(nbt.getCompound("Pos"));
|
||||||
ArmInteractionPoint interactionPoint = createAt(world, pos);
|
ArmInteractionPoint interactionPoint = createAt(world, pos.add(anchor));
|
||||||
if (interactionPoint == null)
|
if (interactionPoint == null)
|
||||||
return null;
|
return null;
|
||||||
interactionPoint.mode = NBTHelper.readEnum(nbt, "Mode", Mode.class);
|
interactionPoint.mode = NBTHelper.readEnum(nbt, "Mode", Mode.class);
|
||||||
|
@ -37,7 +37,7 @@ public class ArmPlacementPacket extends SimplePacketBase {
|
|||||||
CompoundNBT nbt = new CompoundNBT();
|
CompoundNBT nbt = new CompoundNBT();
|
||||||
ListNBT pointsNBT = new ListNBT();
|
ListNBT pointsNBT = new ListNBT();
|
||||||
points.stream()
|
points.stream()
|
||||||
.map(ArmInteractionPoint::serialize)
|
.map(aip -> aip.serialize(pos))
|
||||||
.forEach(pointsNBT::add);
|
.forEach(pointsNBT::add);
|
||||||
nbt.put("Points", pointsNBT);
|
nbt.put("Points", pointsNBT);
|
||||||
buffer.writeCompoundTag(nbt);
|
buffer.writeCompoundTag(nbt);
|
||||||
|
@ -370,7 +370,7 @@ public class ArmTileEntity extends KineticTileEntity {
|
|||||||
|
|
||||||
boolean hasBlazeBurner = false;
|
boolean hasBlazeBurner = false;
|
||||||
for (INBT inbt : interactionPointTag) {
|
for (INBT inbt : interactionPointTag) {
|
||||||
ArmInteractionPoint point = ArmInteractionPoint.deserialize(world, (CompoundNBT) inbt);
|
ArmInteractionPoint point = ArmInteractionPoint.deserialize(world, pos, (CompoundNBT) inbt);
|
||||||
if (point == null)
|
if (point == null)
|
||||||
continue;
|
continue;
|
||||||
if (point.mode == Mode.DEPOSIT)
|
if (point.mode == Mode.DEPOSIT)
|
||||||
@ -402,10 +402,10 @@ public class ArmTileEntity extends KineticTileEntity {
|
|||||||
} else {
|
} else {
|
||||||
ListNBT pointsNBT = new ListNBT();
|
ListNBT pointsNBT = new ListNBT();
|
||||||
inputs.stream()
|
inputs.stream()
|
||||||
.map(ArmInteractionPoint::serialize)
|
.map(aip -> aip.serialize(pos))
|
||||||
.forEach(pointsNBT::add);
|
.forEach(pointsNBT::add);
|
||||||
outputs.stream()
|
outputs.stream()
|
||||||
.map(ArmInteractionPoint::serialize)
|
.map(aip -> aip.serialize(pos))
|
||||||
.forEach(pointsNBT::add);
|
.forEach(pointsNBT::add);
|
||||||
compound.put("InteractionPoints", pointsNBT);
|
compound.put("InteractionPoints", pointsNBT);
|
||||||
}
|
}
|
||||||
|
@ -1,17 +1,12 @@
|
|||||||
package com.simibubi.create.events;
|
package com.simibubi.create.events;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import com.mojang.blaze3d.matrix.MatrixStack;
|
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||||
import com.simibubi.create.AllFluids;
|
import com.simibubi.create.AllFluids;
|
||||||
import com.simibubi.create.Create;
|
import com.simibubi.create.Create;
|
||||||
import com.simibubi.create.CreateClient;
|
import com.simibubi.create.CreateClient;
|
||||||
import com.simibubi.create.content.contraptions.KineticDebugger;
|
import com.simibubi.create.content.contraptions.KineticDebugger;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionHandler;
|
import com.simibubi.create.content.contraptions.components.structureMovement.ContraptionHandler;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.bearing.SailBlockPlacementHelper;
|
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.chassis.ChassisRangeDisplay;
|
import com.simibubi.create.content.contraptions.components.structureMovement.chassis.ChassisRangeDisplay;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.piston.PistonPolePlacementHelper;
|
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.train.CouplingHandlerClient;
|
import com.simibubi.create.content.contraptions.components.structureMovement.train.CouplingHandlerClient;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.train.CouplingPhysics;
|
import com.simibubi.create.content.contraptions.components.structureMovement.train.CouplingPhysics;
|
||||||
import com.simibubi.create.content.contraptions.components.structureMovement.train.CouplingRenderer;
|
import com.simibubi.create.content.contraptions.components.structureMovement.train.CouplingRenderer;
|
||||||
@ -36,7 +31,7 @@ import com.simibubi.create.foundation.tileEntity.behaviour.linked.LinkRenderer;
|
|||||||
import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.ScrollValueRenderer;
|
import com.simibubi.create.foundation.tileEntity.behaviour.scrollvalue.ScrollValueRenderer;
|
||||||
import com.simibubi.create.foundation.utility.AnimationTickHolder;
|
import com.simibubi.create.foundation.utility.AnimationTickHolder;
|
||||||
import com.simibubi.create.foundation.utility.ServerSpeedProvider;
|
import com.simibubi.create.foundation.utility.ServerSpeedProvider;
|
||||||
|
import com.simibubi.create.foundation.utility.placement.PlacementHelpers;
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.client.renderer.ActiveRenderInfo;
|
import net.minecraft.client.renderer.ActiveRenderInfo;
|
||||||
import net.minecraft.client.renderer.IRenderTypeBuffer;
|
import net.minecraft.client.renderer.IRenderTypeBuffer;
|
||||||
@ -61,6 +56,9 @@ import net.minecraftforge.event.world.WorldEvent;
|
|||||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||||
import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
|
import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
@EventBusSubscriber(value = Dist.CLIENT)
|
@EventBusSubscriber(value = Dist.CLIENT)
|
||||||
public class ClientEvents {
|
public class ClientEvents {
|
||||||
|
|
||||||
@ -103,8 +101,7 @@ public class ClientEvents {
|
|||||||
ExtendoGripRenderHandler.tick();
|
ExtendoGripRenderHandler.tick();
|
||||||
// CollisionDebugger.tick();
|
// CollisionDebugger.tick();
|
||||||
ArmInteractionPointHandler.tick();
|
ArmInteractionPointHandler.tick();
|
||||||
SailBlockPlacementHelper.tick();
|
PlacementHelpers.tick();
|
||||||
PistonPolePlacementHelper.tick();
|
|
||||||
CreateClient.outliner.tickOutlines();
|
CreateClient.outliner.tickOutlines();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@ import net.minecraft.util.Direction.Axis;
|
|||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.EnumSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class Iterate {
|
public class Iterate {
|
||||||
@ -15,6 +16,7 @@ public class Iterate {
|
|||||||
public static final Direction[] directions = Direction.values();
|
public static final Direction[] directions = Direction.values();
|
||||||
public static final Direction[] horizontalDirections = getHorizontals();
|
public static final Direction[] horizontalDirections = getHorizontals();
|
||||||
public static final Axis[] axes = Axis.values();
|
public static final Axis[] axes = Axis.values();
|
||||||
|
public static final EnumSet<Direction.Axis> axisSet = EnumSet.allOf(Direction.Axis.class);
|
||||||
|
|
||||||
private static Direction[] getHorizontals() {
|
private static Direction[] getHorizontals() {
|
||||||
Direction[] directions = new Direction[4];
|
Direction[] directions = new Direction[4];
|
||||||
|
@ -0,0 +1,111 @@
|
|||||||
|
package com.simibubi.create.foundation.utility.placement;
|
||||||
|
|
||||||
|
import com.simibubi.create.CreateClient;
|
||||||
|
import com.simibubi.create.foundation.utility.Iterate;
|
||||||
|
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.item.ItemStack;
|
||||||
|
import net.minecraft.util.Direction;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import net.minecraft.util.math.BlockRayTraceResult;
|
||||||
|
import net.minecraft.util.math.Vec3d;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@MethodsReturnNonnullByDefault
|
||||||
|
public interface IPlacementHelper {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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
|
||||||
|
*/
|
||||||
|
Predicate<ItemStack> getItemPredicate();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return a predicate that gets tested with the blockstate the player is looking at
|
||||||
|
* should return true if this placement helper is active with the given blockstate
|
||||||
|
*/
|
||||||
|
Predicate<BlockState> getStatePredicate();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return PlacementOffset.fail() if no valid offset could be found.
|
||||||
|
* PlacementOffset.success(newPos) with newPos being the new position the block should be placed at
|
||||||
|
*/
|
||||||
|
PlacementOffset getOffset(World world, BlockState state, BlockPos pos, BlockRayTraceResult ray);
|
||||||
|
|
||||||
|
//only gets called when placementOffset is successful
|
||||||
|
default void renderAt(BlockPos pos, BlockState state, BlockRayTraceResult ray, PlacementOffset offset) {
|
||||||
|
IPlacementHelper.renderArrow(VecHelper.getCenterOf(pos), VecHelper.getCenterOf(offset.getPos()), ray.getFace());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void renderArrow(Vec3d center, Vec3d target, Direction arrowPlane) {
|
||||||
|
renderArrow(center, target, arrowPlane, 1D);
|
||||||
|
}
|
||||||
|
static void renderArrow(Vec3d center, Vec3d target, Direction arrowPlane, double distanceFromCenter) {
|
||||||
|
Vec3d direction = target.subtract(center).normalize();
|
||||||
|
Vec3d facing = new Vec3d(arrowPlane.getDirectionVec());
|
||||||
|
Vec3d start = center.add(direction);
|
||||||
|
Vec3d offset = direction.scale(distanceFromCenter-1);
|
||||||
|
Vec3d offsetA = direction.crossProduct(facing).normalize().scale(.25);
|
||||||
|
Vec3d offsetB = facing.crossProduct(direction).normalize().scale(.25);
|
||||||
|
Vec3d endA = center.add(direction.scale(.75)).add(offsetA);
|
||||||
|
Vec3d endB = center.add(direction.scale(.75)).add(offsetB);
|
||||||
|
CreateClient.outliner.showLine("placementArrowA" + center + target, start.add(offset), endA.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) {
|
||||||
|
return orderedByDistance(pos, hit, dir -> dir.getAxis() == axis);
|
||||||
|
}
|
||||||
|
|
||||||
|
static List<Direction> orderedByDistanceOnlyAxis(BlockPos pos, Vec3d hit, Direction.Axis axis, Predicate<Direction> includeDirection) {
|
||||||
|
return orderedByDistance(pos, hit, ((Predicate<Direction>) dir -> dir.getAxis() == axis).and(includeDirection));
|
||||||
|
}
|
||||||
|
|
||||||
|
static List<Direction> orderedByDistanceExceptAxis(BlockPos pos, Vec3d hit, Direction.Axis axis) {
|
||||||
|
return orderedByDistance(pos, hit, dir -> dir.getAxis() != axis);
|
||||||
|
}
|
||||||
|
|
||||||
|
static List<Direction> orderedByDistanceExceptAxis(BlockPos pos, Vec3d hit, Direction.Axis axis, Predicate<Direction> includeDirection) {
|
||||||
|
return orderedByDistance(pos, hit, ((Predicate<Direction>) dir -> dir.getAxis() != axis).and(includeDirection));
|
||||||
|
}
|
||||||
|
|
||||||
|
static List<Direction> orderedByDistance(BlockPos pos, Vec3d hit) {
|
||||||
|
return orderedByDistance(pos, hit, _$ -> true);
|
||||||
|
}
|
||||||
|
|
||||||
|
static List<Direction> orderedByDistance(BlockPos pos, Vec3d hit, Predicate<Direction> includeDirection) {
|
||||||
|
Vec3d centerToHit = hit.subtract(VecHelper.getCenterOf(pos));
|
||||||
|
return Arrays.stream(Iterate.directions)
|
||||||
|
.filter(includeDirection)
|
||||||
|
.map(dir -> Pair.of(dir, new Vec3d(dir.getDirectionVec()).distanceTo(centerToHit)))
|
||||||
|
.sorted(Comparator.comparingDouble(Pair::getSecond))
|
||||||
|
.map(Pair::getFirst)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,74 @@
|
|||||||
|
package com.simibubi.create.foundation.utility.placement;
|
||||||
|
|
||||||
|
import net.minecraft.block.BlockState;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.client.world.ClientWorld;
|
||||||
|
import net.minecraft.util.Hand;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import net.minecraft.util.math.BlockRayTraceResult;
|
||||||
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
|
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class PlacementHelpers {
|
||||||
|
|
||||||
|
private static final List<IPlacementHelper> helpers = new ArrayList<>();
|
||||||
|
|
||||||
|
public static int register(IPlacementHelper helper) {
|
||||||
|
helpers.add(helper);
|
||||||
|
return helpers.size() - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IPlacementHelper get(int id) {
|
||||||
|
if (id < 0 || id >= helpers.size())
|
||||||
|
throw new ArrayIndexOutOfBoundsException("id " + id + " for placement helper not known");
|
||||||
|
|
||||||
|
return helpers.get(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@OnlyIn(Dist.CLIENT)
|
||||||
|
public static void tick() {
|
||||||
|
Minecraft mc = Minecraft.getInstance();
|
||||||
|
ClientWorld world = mc.world;
|
||||||
|
|
||||||
|
if (world == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!(mc.objectMouseOver instanceof BlockRayTraceResult))
|
||||||
|
return;
|
||||||
|
|
||||||
|
BlockRayTraceResult ray = (BlockRayTraceResult) mc.objectMouseOver;
|
||||||
|
|
||||||
|
if (mc.player == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
List<IPlacementHelper> filteredForHeldItem = helpers.stream().filter(helper -> Arrays.stream(Hand.values()).anyMatch(hand -> helper.getItemPredicate().test(mc.player.getHeldItem(hand)))).collect(Collectors.toList());
|
||||||
|
if (filteredForHeldItem.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (mc.player.isSneaking())//for now, disable all helpers when sneaking TODO add helpers that respect sneaking but still show position
|
||||||
|
return;
|
||||||
|
|
||||||
|
BlockPos pos = ray.getPos();
|
||||||
|
BlockState state = world.getBlockState(pos);
|
||||||
|
|
||||||
|
List<IPlacementHelper> filteredForState = filteredForHeldItem.stream().filter(helper -> helper.getStatePredicate().test(state)).collect(Collectors.toList());
|
||||||
|
|
||||||
|
if (filteredForState.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (IPlacementHelper h : filteredForState) {
|
||||||
|
PlacementOffset offset = h.getOffset(world, state, pos, ray);
|
||||||
|
|
||||||
|
if (offset.isSuccessful()) {
|
||||||
|
h.renderAt(pos, state, ray, offset);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,43 @@
|
|||||||
|
package com.simibubi.create.foundation.utility.placement;
|
||||||
|
|
||||||
|
import net.minecraft.block.BlockState;
|
||||||
|
import net.minecraft.util.math.Vec3i;
|
||||||
|
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
public class PlacementOffset {
|
||||||
|
|
||||||
|
private final boolean success;
|
||||||
|
private final Vec3i pos;
|
||||||
|
private final Function<BlockState, BlockState> stateTransform;
|
||||||
|
|
||||||
|
private PlacementOffset(boolean success, Vec3i pos, Function<BlockState, BlockState> transform) {
|
||||||
|
this.success = success;
|
||||||
|
this.pos = pos;
|
||||||
|
this.stateTransform = transform == null ? Function.identity() : transform;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PlacementOffset fail() {
|
||||||
|
return new PlacementOffset(false, Vec3i.NULL_VECTOR, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PlacementOffset success(Vec3i pos) {
|
||||||
|
return new PlacementOffset(true, pos, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PlacementOffset success(Vec3i pos, Function<BlockState, BlockState> transform) {
|
||||||
|
return new PlacementOffset(true, pos, transform);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isSuccessful() {
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vec3i getPos() {
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Function<BlockState, BlockState> getTransform() {
|
||||||
|
return stateTransform;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,77 @@
|
|||||||
|
package com.simibubi.create.foundation.utility.placement.util;
|
||||||
|
|
||||||
|
import com.simibubi.create.foundation.utility.VecHelper;
|
||||||
|
import com.simibubi.create.foundation.utility.placement.IPlacementHelper;
|
||||||
|
import com.simibubi.create.foundation.utility.placement.PlacementOffset;
|
||||||
|
import mcp.MethodsReturnNonnullByDefault;
|
||||||
|
import net.minecraft.block.BlockState;
|
||||||
|
import net.minecraft.state.IProperty;
|
||||||
|
import net.minecraft.util.Direction;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import net.minecraft.util.math.BlockRayTraceResult;
|
||||||
|
import net.minecraft.util.math.Vec3d;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
|
@MethodsReturnNonnullByDefault
|
||||||
|
public abstract class PoleHelper<T extends Comparable<T>> implements IPlacementHelper {
|
||||||
|
|
||||||
|
protected final Predicate<BlockState> statePredicate;
|
||||||
|
protected final IProperty<T> property;
|
||||||
|
protected final Function<BlockState, Direction.Axis> axisFunction;
|
||||||
|
|
||||||
|
public PoleHelper(Predicate<BlockState> statePredicate, Function<BlockState, Direction.Axis> axisFunction, IProperty<T> property) {
|
||||||
|
this.statePredicate = statePredicate;
|
||||||
|
this.axisFunction = axisFunction;
|
||||||
|
this.property = property;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean matchesAxis(BlockState state, Direction.Axis axis) {
|
||||||
|
if (!statePredicate.test(state))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return axisFunction.apply(state) == axis;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int attachedPoles(World world, BlockPos pos, Direction direction) {
|
||||||
|
BlockPos checkPos = pos.offset(direction);
|
||||||
|
BlockState state = world.getBlockState(checkPos);
|
||||||
|
int count = 0;
|
||||||
|
while (matchesAxis(state, direction.getAxis())) {
|
||||||
|
count++;
|
||||||
|
checkPos = checkPos.offset(direction);
|
||||||
|
state = world.getBlockState(checkPos);
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Predicate<BlockState> getStatePredicate() {
|
||||||
|
return this.statePredicate;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PlacementOffset getOffset(World world, BlockState state, BlockPos pos, BlockRayTraceResult ray) {
|
||||||
|
List<Direction> directions = IPlacementHelper.orderedByDistance(pos, ray.getHitVec(), dir -> dir.getAxis() == axisFunction.apply(state));
|
||||||
|
for (Direction dir : directions) {
|
||||||
|
int poles = attachedPoles(world, pos, dir);
|
||||||
|
BlockPos newPos = pos.offset(dir, poles + 1);
|
||||||
|
BlockState newState = world.getBlockState(newPos);
|
||||||
|
|
||||||
|
if (newState.getMaterial().isReplaceable())
|
||||||
|
return PlacementOffset.success(newPos, bState -> bState.with(property, state.get(property)));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return PlacementOffset.fail();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void renderAt(BlockPos pos, BlockState state, BlockRayTraceResult ray, PlacementOffset offset) {
|
||||||
|
Vec3d centerOffset = new Vec3d(ray.getFace().getDirectionVec()).scale(.3);
|
||||||
|
IPlacementHelper.renderArrow(VecHelper.getCenterOf(pos).add(centerOffset), VecHelper.getCenterOf(offset.getPos()).add(centerOffset), ray.getFace(), 0.75D);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user