Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

General Block Protocol #241

Closed
wants to merge 3 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
223 changes: 118 additions & 105 deletions src/main/java/carpetextra/utils/BlockPlacer.java
Original file line number Diff line number Diff line change
@@ -1,118 +1,131 @@
package carpetextra.utils;

import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.ComparatorBlock;
import net.minecraft.block.DispenserBlock;
import net.minecraft.block.FacingBlock;
import net.minecraft.block.GlazedTerracottaBlock;
import net.minecraft.block.HorizontalFacingBlock;
import net.minecraft.block.ObserverBlock;
import net.minecraft.block.PistonBlock;
import net.minecraft.block.RepeaterBlock;
import net.minecraft.block.StairsBlock;
import net.minecraft.block.TrapdoorBlock;
import net.minecraft.block.enums.BlockHalf;
import net.minecraft.block.enums.ComparatorMode;
import net.minecraft.block.*;
import net.minecraft.block.enums.*;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemPlacementContext;
import net.minecraft.state.property.DirectionProperty;
import net.minecraft.state.property.Property;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;

public class BlockPlacer
{
public static BlockState alternativeBlockPlacement(Block block, ItemPlacementContext context)//World worldIn, BlockPos pos, EnumFacing facing, float hitX, float hitY, float hitZ, int meta, EntityLivingBase placer)
{
//actual alternative block placement code
public class BlockPlacer {
private static DirectionProperty getFirstDirectionProperty(BlockState state) {
for (Property<?> prop : state.getProperties()) {
if (prop instanceof DirectionProperty) {
return (DirectionProperty) prop;
}
}
return null;
}
private static boolean isBlockAttachableChest(Block originBlock, Direction facing, BlockPos checkPos, World world) {
BlockState checkState = world.getBlockState(checkPos);
if (checkState == null) {
return false;
}
if (originBlock.equals(checkState.getBlock())) {
return checkState.get(ChestBlock.FACING).equals(facing) && checkState.get(ChestBlock.CHEST_TYPE) == ChestType.SINGLE;
}
return false;
}
private static boolean isBlockOffsetNotReplaceableBlock(BlockPos checkPos, Direction facing, World world){
return !world.getBlockState(checkPos.offset(facing)).getMaterial().isReplaceable();
}

Direction facing;
Vec3d vec3d = context.getHitPos();
BlockPos pos = context.getBlockPos();
double hitX = vec3d.x - pos.getX();
if (hitX<2) // vanilla
return null;
int code = (int)(hitX-2)/2;
//
// now it would be great if hitX was adjusted in context to original range from 0.0 to 1.0
// since its actually using it. Its private - maybe with Reflections?
//
PlayerEntity placer = context.getPlayer();
World world = context.getWorld();
public static BlockState alternativeBlockPlacement(Block block, ItemPlacementContext context)//World worldIn, BlockPos pos, EnumFacing facing, float hitX, float hitY, float hitZ, int meta, EntityLivingBase placer)
{
//actual alternative block placement code

if (block instanceof GlazedTerracottaBlock)
{
facing = Direction.byId(code);
if(facing == Direction.UP || facing == Direction.DOWN)
{
facing = placer.getHorizontalFacing().getOpposite();
}
return block.getDefaultState().with(HorizontalFacingBlock.FACING, facing);
}
else if (block instanceof ObserverBlock)
{
return block.getDefaultState()
.with(FacingBlock.FACING, Direction.byId(code))
.with(ObserverBlock.POWERED, true);
}
else if (block instanceof RepeaterBlock)
{
facing = Direction.byId(code % 16);
if(facing == Direction.UP || facing == Direction.DOWN)
{
facing = placer.getHorizontalFacing().getOpposite();
}
return block.getDefaultState()
.with(HorizontalFacingBlock.FACING, facing)
.with(RepeaterBlock.DELAY, MathHelper.clamp(code / 16, 1, 4))
.with(RepeaterBlock.LOCKED, Boolean.FALSE);
}
else if (block instanceof TrapdoorBlock)
{
facing = Direction.byId(code % 16);
if(facing == Direction.UP || facing == Direction.DOWN)
{
facing = placer.getHorizontalFacing().getOpposite();
}
return block.getDefaultState()
.with(TrapdoorBlock.FACING, facing)
.with(TrapdoorBlock.OPEN, Boolean.FALSE)
.with(TrapdoorBlock.HALF, (code >= 16) ? BlockHalf.TOP : BlockHalf.BOTTOM)
.with(TrapdoorBlock.OPEN, world.isReceivingRedstonePower(pos));
}
else if (block instanceof ComparatorBlock)
{
facing = Direction.byId(code % 16);
if((facing == Direction.UP) || (facing == Direction.DOWN))
{
facing = placer.getHorizontalFacing().getOpposite();
}
ComparatorMode m = (hitX >= 16)?ComparatorMode.SUBTRACT: ComparatorMode.COMPARE;
return block.getDefaultState()
.with(HorizontalFacingBlock.FACING, facing)
.with(ComparatorBlock.POWERED, Boolean.FALSE)
.with(ComparatorBlock.MODE, m);
}
else if (block instanceof DispenserBlock)
{
return block.getDefaultState()
.with(DispenserBlock.FACING, Direction.byId(code))
.with(DispenserBlock.TRIGGERED, Boolean.FALSE);
}
else if (block instanceof PistonBlock)
{
return block.getDefaultState()
.with(FacingBlock.FACING, Direction.byId(code))
.with(PistonBlock.EXTENDED, Boolean.FALSE);
}
else if (block instanceof StairsBlock)
{
return block.getPlacementState(context)//worldIn, pos, facing, hitX, hitY, hitZ, meta, placer)
.with(StairsBlock.FACING, Direction.byId(code % 16))
.with(StairsBlock.HALF, ( hitX >= 16)?BlockHalf.TOP : BlockHalf.BOTTOM);
}
return null;
}
Direction facing;
Vec3d vec3d = context.getHitPos();
BlockPos pos = context.getBlockPos();
double hitX = vec3d.x - pos.getX();
BlockState state = block.getDefaultState();
DirectionProperty directionProperty = getFirstDirectionProperty(state);
if (hitX < 2 || !(block instanceof AbstractRailBlock || block instanceof PillarBlock) && directionProperty == null) // vanilla
return null;
int code = (int) (hitX - 2) / 2;

//
// now it would be great if hitX was adjusted in context to original range from 0.0 to 1.0
// since its actually using it. Its private - maybe with Reflections?
//
PlayerEntity placer = context.getPlayer();
World world = context.getWorld();
if (block instanceof AbstractRailBlock){
RailShape shapeEnumFound = RailShape.values()[code%RailShape.values().length]; //avoid NPE
if (block instanceof RailBlock)
{
return state.with(RailBlock.SHAPE,shapeEnumFound);
}
else if (block instanceof DetectorRailBlock)
{
return state.with(DetectorRailBlock.SHAPE,shapeEnumFound);
}
else
{
return state.with(PoweredRailBlock.SHAPE,shapeEnumFound);
}
} else if (block instanceof PillarBlock) {
return state.with(PillarBlock.AXIS, Direction.Axis.values()[code % Direction.Axis.VALUES.length]);
}
else
{
int FacingId = code % 16;
facing = Direction.byId(FacingId);
if (!directionProperty.getValues().contains(facing)) {
if (placer == null){
facing = Direction.NORTH;
} else {
facing = placer.getHorizontalFacing().getOpposite();
}
}
state = state.with(directionProperty, facing);
}
//check blocks with additional states first
if (block instanceof RepeaterBlock) {
state = state
.with(RepeaterBlock.DELAY, MathHelper.clamp(code / 16, 1, 4))
.with(RepeaterBlock.LOCKED, Boolean.FALSE);
} else if (block instanceof TrapdoorBlock) {
state = state
.with(TrapdoorBlock.OPEN, Boolean.FALSE)
.with(TrapdoorBlock.HALF, (code >= 16) ? BlockHalf.TOP : BlockHalf.BOTTOM)
.with(TrapdoorBlock.OPEN, world.isReceivingRedstonePower(pos));
} else if (block instanceof ComparatorBlock) {
ComparatorMode m = (hitX >= 16) ? ComparatorMode.SUBTRACT : ComparatorMode.COMPARE;
state = state
.with(ComparatorBlock.POWERED, Boolean.FALSE)
.with(ComparatorBlock.MODE, m);
} else if (block instanceof StairsBlock) {
state = block.getPlacementState(context); //worldIn, pos, facing, hitX, hitY, hitZ, meta, placer)
if(state == null) {return null;}
return state.with(StairsBlock.FACING, facing)
.with(StairsBlock.HALF, (hitX >= 16) ? BlockHalf.TOP : BlockHalf.BOTTOM);
} else if (block instanceof WallMountedBlock) {
return state.with(WallMountedBlock.FACE, (code >= 32) ? WallMountLocation.CEILING: (code >= 16) ? WallMountLocation.WALL : WallMountLocation.FLOOR).
with(WallMountedBlock.FACING, facing);
} else if (block instanceof WallSkullBlock){
return state.with(WallMountedBlock.FACING, facing);
}
else if (block instanceof ChestBlock)
{
if (isBlockAttachableChest(block, facing, pos.offset(facing.rotateYClockwise()), world)) {
return state.with(ChestBlock.CHEST_TYPE, ChestType.LEFT);
}
else if (isBlockAttachableChest(block, facing, pos.offset(facing.rotateYCounterclockwise()), world)) {
return state.with(ChestBlock.CHEST_TYPE, ChestType.RIGHT);
}
return state.with(ChestBlock.CHEST_TYPE, ChestType.SINGLE);
} else if (block instanceof BedBlock && isBlockOffsetNotReplaceableBlock(pos, facing, world)) {
return null;
} else if (block instanceof DoorBlock && isBlockOffsetNotReplaceableBlock(pos, Direction.UP, world)) {
return null;
}
return state;
}
}