mirror of
https://github.com/Creators-of-Create/Create.git
synced 2024-11-11 04:22:00 +01:00
Assisted Placement, Part II
- helpers now respect waterlogging - add placement helpers for rsc's cogwheel as well as machines with integrated cogwheels
This commit is contained in:
parent
e2437d1a5c
commit
f45c0ca182
7 changed files with 221 additions and 38 deletions
|
@ -68,20 +68,21 @@ public class SailBlock extends ProperDirectionalBlock {
|
|||
IPlacementHelper placementHelper = PlacementHelpers.get(placementHelperId);
|
||||
PlacementOffset offset = placementHelper.getOffset(world, state, pos, ray);
|
||||
|
||||
if (!offset.isSuccessful())
|
||||
if (!offset.isReplaceable(world))
|
||||
return ActionResultType.PASS;
|
||||
|
||||
BlockState blockState = ((BlockItem) heldItem.getItem()).getBlock()
|
||||
offset.placeInWorld(world, ((BlockItem) heldItem.getItem()).getBlock().getDefaultState(), player, heldItem);
|
||||
|
||||
/*BlockState blockState = ((BlockItem) heldItem.getItem()).getBlock()
|
||||
.getDefaultState()
|
||||
.with(FACING, state.get(FACING));
|
||||
BlockPos offsetPos = new BlockPos(offset.getPos());
|
||||
if (!world.isRemote && world.getBlockState(offsetPos)
|
||||
.getMaterial()
|
||||
.isReplaceable()) {
|
||||
if (!world.isRemote && world.getBlockState(offsetPos).getMaterial().isReplaceable()) {
|
||||
world.setBlockState(offsetPos, blockState);
|
||||
if (!player.isCreative())
|
||||
heldItem.shrink(1);
|
||||
}
|
||||
}*/
|
||||
|
||||
return ActionResultType.SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -227,7 +228,7 @@ public class SailBlock extends ProperDirectionalBlock {
|
|||
if (directions.isEmpty())
|
||||
return PlacementOffset.fail();
|
||||
else {
|
||||
return PlacementOffset.success(pos.offset(directions.get(0)));
|
||||
return PlacementOffset.success(pos.offset(directions.get(0)), s -> s.with(FACING, state.get(FACING)));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -118,20 +118,19 @@ public class PistonExtensionPoleBlock extends ProperDirectionalBlock implements
|
|||
IPlacementHelper placementHelper = PlacementHelpers.get(placementHelperId);
|
||||
PlacementOffset offset = placementHelper.getOffset(world, state, pos, ray);
|
||||
|
||||
if (!offset.isSuccessful())
|
||||
if (!offset.isReplaceable(world))
|
||||
return ActionResultType.PASS;
|
||||
|
||||
BlockPos newPos = new BlockPos(offset.getPos());
|
||||
offset.placeInWorld(world, AllBlocks.PISTON_EXTENSION_POLE.getDefaultState(), player, heldItem);
|
||||
|
||||
if (!world.getBlockState(newPos).getMaterial().isReplaceable())
|
||||
return ActionResultType.PASS;
|
||||
/*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);
|
||||
heldItem.shrink(1);*/
|
||||
|
||||
return ActionResultType.SUCCESS;
|
||||
}
|
||||
|
|
|
@ -1,21 +1,38 @@
|
|||
package com.simibubi.create.content.contraptions.relays.advanced;
|
||||
|
||||
import com.simibubi.create.AllBlocks;
|
||||
import com.simibubi.create.AllShapes;
|
||||
import com.simibubi.create.AllTileEntities;
|
||||
import com.simibubi.create.content.contraptions.base.HorizontalAxisKineticBlock;
|
||||
import com.simibubi.create.content.contraptions.relays.elementary.CogWheelBlock;
|
||||
|
||||
import com.simibubi.create.content.contraptions.relays.elementary.CogwheelBlockItem;
|
||||
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.BlockItemUseContext;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.ActionResultType;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.Direction.Axis;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.BlockRayTraceResult;
|
||||
import net.minecraft.util.math.shapes.ISelectionContext;
|
||||
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 {
|
||||
|
||||
private static final int placementHelperId = PlacementHelpers.register(new PlacementHelper());
|
||||
|
||||
public SpeedControllerBlock(Properties properties) {
|
||||
super(properties);
|
||||
}
|
||||
|
@ -33,9 +50,60 @@ public class SpeedControllerBlock extends HorizontalAxisKineticBlock {
|
|||
return super.getStateForPlacement(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
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;
|
||||
|
||||
}
|
||||
|
||||
return ActionResultType.PASS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VoxelShape getShape(BlockState state, IBlockReader worldIn, BlockPos pos, ISelectionContext context) {
|
||||
return AllShapes.SPEED_CONTROLLER.get(state.get(HORIZONTAL_AXIS));
|
||||
}
|
||||
|
||||
@MethodsReturnNonnullByDefault
|
||||
private static class PlacementHelper implements IPlacementHelper {
|
||||
@Override
|
||||
public Predicate<ItemStack> getItemPredicate() {
|
||||
return AllBlocks.LARGE_COGWHEEL::isIn;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Predicate<BlockState> getStatePredicate() {
|
||||
return AllBlocks.ROTATION_SPEED_CONTROLLER::has;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlacementOffset getOffset(World world, BlockState state, BlockPos pos, BlockRayTraceResult ray) {
|
||||
BlockPos newPos = pos.up();
|
||||
if (!world.getBlockState(newPos).getMaterial().isReplaceable())
|
||||
return PlacementOffset.fail();
|
||||
|
||||
Axis newAxis = state.get(HORIZONTAL_AXIS) == Axis.X ? Axis.Z : Axis.X;
|
||||
|
||||
if (CogwheelBlockItem.DiagonalCogHelper.hasLargeCogwheelNeighbor(world, newPos, newAxis) || CogwheelBlockItem.DiagonalCogHelper.hasSmallCogwheelNeighbor(world, newPos, newAxis))
|
||||
return PlacementOffset.fail();
|
||||
|
||||
return PlacementOffset.success(newPos, s -> s.with(CogWheelBlock.AXIS, newAxis));
|
||||
}
|
||||
|
||||
@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(HORIZONTAL_AXIS) == Axis.X ? Axis.Z : Axis.X));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,9 @@ package com.simibubi.create.content.contraptions.relays.elementary;
|
|||
|
||||
import com.simibubi.create.AllBlocks;
|
||||
import com.simibubi.create.AllShapes;
|
||||
import com.simibubi.create.content.contraptions.base.DirectionalKineticBlock;
|
||||
import com.simibubi.create.content.contraptions.base.HorizontalKineticBlock;
|
||||
import com.simibubi.create.content.contraptions.base.IRotate;
|
||||
import com.simibubi.create.foundation.advancement.AllTriggers;
|
||||
import com.simibubi.create.foundation.utility.Iterate;
|
||||
import com.simibubi.create.foundation.utility.VecHelper;
|
||||
|
@ -32,43 +35,51 @@ public class CogwheelBlockItem extends BlockItem {
|
|||
boolean large;
|
||||
|
||||
private final int placementHelperId;
|
||||
private final int integratedCogHelperId;
|
||||
|
||||
public CogwheelBlockItem(CogWheelBlock block, Properties builder) {
|
||||
super(block, builder);
|
||||
large = block.isLarge;
|
||||
|
||||
placementHelperId = PlacementHelpers.register(large ? new LargeCogHelper() : new SmallCogHelper());
|
||||
integratedCogHelperId = large ? PlacementHelpers.register(new IntegratedCogHelper()) : -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActionResultType tryPlace(BlockItemUseContext context) {
|
||||
IPlacementHelper helper = PlacementHelpers.get(placementHelperId);
|
||||
World world = context.getWorld();
|
||||
BlockPos pos = context.getPos().offset(context.getFace().getOpposite());
|
||||
BlockState state = world.getBlockState(pos);
|
||||
|
||||
if (!helper.getStatePredicate().test(state))
|
||||
return super.tryPlace(context);
|
||||
IPlacementHelper helper = PlacementHelpers.get(placementHelperId);
|
||||
|
||||
PlacementOffset offset = helper.getOffset(world, state, pos, new BlockRayTraceResult(context.getHitVec(), context.getFace(), pos, true));
|
||||
if (helper.matchesState(state)) {
|
||||
PlacementOffset offset = helper.getOffset(world, state, pos, new BlockRayTraceResult(context.getHitVec(), context.getFace(), pos, true));
|
||||
|
||||
if (!offset.isSuccessful())
|
||||
return super.tryPlace(context);
|
||||
if (!offset.isReplaceable(world))
|
||||
return super.tryPlace(context);
|
||||
|
||||
BlockPos newPos = new BlockPos(offset.getPos());
|
||||
offset.placeInWorld(world, this, context.getPlayer(), context.getItem());
|
||||
|
||||
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 (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, context.getPlayer(), context.getItem());
|
||||
|
||||
return ActionResultType.SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
return super.tryPlace(context);
|
||||
|
||||
/*if (!(placedOnState.getBlock() instanceof CogWheelBlock))
|
||||
return super.tryPlace(context);
|
||||
|
@ -218,7 +229,7 @@ public class CogwheelBlockItem extends BlockItem {
|
|||
}
|
||||
|
||||
@MethodsReturnNonnullByDefault
|
||||
private abstract static class DiagonalCogHelper implements IPlacementHelper {
|
||||
public abstract static class DiagonalCogHelper implements IPlacementHelper {
|
||||
|
||||
@Override
|
||||
public Predicate<BlockState> getStatePredicate() {
|
||||
|
@ -254,7 +265,7 @@ public class CogwheelBlockItem extends BlockItem {
|
|||
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) {
|
||||
static public boolean hasLargeCogwheelNeighbor(World world, BlockPos pos, Direction.Axis axis) {
|
||||
for (Direction dir : Iterate.directions) {
|
||||
if (dir.getAxis() == axis)
|
||||
continue;
|
||||
|
@ -266,7 +277,7 @@ public class CogwheelBlockItem extends BlockItem {
|
|||
return false;
|
||||
}
|
||||
|
||||
protected boolean hasSmallCogwheelNeighbor(World world, BlockPos pos, Direction.Axis axis) {
|
||||
static public boolean hasSmallCogwheelNeighbor(World world, BlockPos pos, Direction.Axis axis) {
|
||||
for (Direction dir : Iterate.directions) {
|
||||
if (dir.getAxis() == axis)
|
||||
continue;
|
||||
|
@ -278,4 +289,58 @@ public class CogwheelBlockItem extends BlockItem {
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@MethodsReturnNonnullByDefault
|
||||
public static class IntegratedCogHelper implements IPlacementHelper {
|
||||
|
||||
@Override
|
||||
public Predicate<ItemStack> getItemPredicate() {
|
||||
return AllBlocks.LARGE_COGWHEEL::isIn;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Predicate<BlockState> getStatePredicate() {
|
||||
return s -> !AllBlocks.COGWHEEL.has(s) && s.getBlock() instanceof IRotate && ((IRotate) s.getBlock()).hasIntegratedCogwheel(null, null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlacementOffset getOffset(World world, BlockState state, BlockPos pos, BlockRayTraceResult ray) {
|
||||
Direction face = ray.getFace();
|
||||
Axis newAxis;
|
||||
|
||||
if (state.has(HorizontalKineticBlock.HORIZONTAL_FACING))
|
||||
newAxis = state.get(HorizontalKineticBlock.HORIZONTAL_FACING).getAxis();
|
||||
else if (state.has(DirectionalKineticBlock.FACING))
|
||||
newAxis = state.get(DirectionalKineticBlock.FACING).getAxis();
|
||||
else
|
||||
newAxis = Axis.Y;
|
||||
|
||||
if (face.getAxis() == newAxis)
|
||||
return PlacementOffset.fail();
|
||||
|
||||
List<Direction> directions = IPlacementHelper.orderedByDistanceExceptAxis(pos, ray.getHitVec(), face.getAxis(), newAxis);
|
||||
|
||||
for (Direction d : directions) {
|
||||
BlockPos newPos = pos.offset(face).offset(d);
|
||||
|
||||
if (!world.getBlockState(newPos).getMaterial().isReplaceable())
|
||||
continue;
|
||||
|
||||
if (DiagonalCogHelper.hasLargeCogwheelNeighbor(world, newPos, newAxis) || DiagonalCogHelper.hasSmallCogwheelNeighbor(world, newPos, newAxis))
|
||||
return PlacementOffset.fail();
|
||||
|
||||
return PlacementOffset.success(newPos, s -> s.with(CogWheelBlock.AXIS, newAxis));
|
||||
}
|
||||
|
||||
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, offset.getTransform().apply(AllBlocks.LARGE_COGWHEEL.getDefaultState()).get(AXIS)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,6 @@ 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.entity.player.PlayerEntity;
|
||||
import net.minecraft.item.BlockItem;
|
||||
|
@ -81,13 +80,12 @@ public class ShaftBlock extends AbstractShaftBlock {
|
|||
if (helper.getItemPredicate().test(heldItem)) {
|
||||
PlacementOffset offset = helper.getOffset(world, state, pos, ray);
|
||||
|
||||
if (!offset.isSuccessful())
|
||||
if (!offset.isReplaceable(world))
|
||||
return ActionResultType.PASS;
|
||||
|
||||
BlockPos newPos = new BlockPos(offset.getPos());
|
||||
offset.placeInWorld(world, (BlockItem) heldItem.getItem(), player, heldItem);
|
||||
|
||||
if (!world.getBlockState(newPos).getMaterial().isReplaceable())
|
||||
return ActionResultType.PASS;
|
||||
/*BlockPos newPos = new BlockPos(offset.getPos());
|
||||
|
||||
if (world.isRemote)
|
||||
return ActionResultType.SUCCESS;
|
||||
|
@ -95,7 +93,7 @@ public class ShaftBlock extends AbstractShaftBlock {
|
|||
Block block = ((BlockItem) heldItem.getItem()).getBlock();
|
||||
world.setBlockState(newPos, offset.getTransform().apply(block.getDefaultState()));
|
||||
if (!player.isCreative())
|
||||
heldItem.shrink(1);
|
||||
heldItem.shrink(1);*/
|
||||
|
||||
return ActionResultType.SUCCESS;
|
||||
}
|
||||
|
|
|
@ -95,6 +95,14 @@ public interface IPlacementHelper {
|
|||
return orderedByDistance(pos, hit, ((Predicate<Direction>) dir -> dir.getAxis() != axis).and(includeDirection));
|
||||
}
|
||||
|
||||
static List<Direction> orderedByDistanceExceptAxis(BlockPos pos, Vec3d hit, Direction.Axis first, Direction.Axis second) {
|
||||
return orderedByDistanceExceptAxis(pos, hit, first, d -> d.getAxis() != second);
|
||||
}
|
||||
|
||||
static List<Direction> orderedByDistanceExceptAxis(BlockPos pos, Vec3d hit, Direction.Axis first, Direction.Axis second, Predicate<Direction> includeDirection) {
|
||||
return orderedByDistanceExceptAxis(pos, hit, first, ((Predicate<Direction>) d -> d.getAxis() != second).and(includeDirection));
|
||||
}
|
||||
|
||||
static List<Direction> orderedByDistance(BlockPos pos, Vec3d hit) {
|
||||
return orderedByDistance(pos, hit, _$ -> true);
|
||||
}
|
||||
|
@ -108,4 +116,12 @@ public interface IPlacementHelper {
|
|||
.map(Pair::getFirst)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
default boolean matchesItem(ItemStack item) {
|
||||
return getItemPredicate().test(item);
|
||||
}
|
||||
|
||||
default boolean matchesState(BlockState state) {
|
||||
return getStatePredicate().test(state);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,15 @@
|
|||
package com.simibubi.create.foundation.utility.placement;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
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.ItemStack;
|
||||
import net.minecraft.state.properties.BlockStateProperties;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Vec3i;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
|
@ -40,4 +48,32 @@ public class PlacementOffset {
|
|||
public Function<BlockState, BlockState> getTransform() {
|
||||
return stateTransform;
|
||||
}
|
||||
|
||||
public boolean isReplaceable(World world) {
|
||||
if (!success)
|
||||
return false;
|
||||
|
||||
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;
|
||||
|
||||
BlockPos newPos = new BlockPos(pos);
|
||||
BlockState state = stateTransform.apply(defaultState);
|
||||
if (state.has(BlockStateProperties.WATERLOGGED)) {
|
||||
IFluidState fluidState = world.getFluidState(newPos);
|
||||
state = state.with(BlockStateProperties.WATERLOGGED, fluidState.getFluid() == Fluids.WATER);
|
||||
}
|
||||
|
||||
world.setBlockState(newPos, state);
|
||||
|
||||
if (!player.isCreative())
|
||||
item.shrink(1);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue