145 lines
5.3 KiB
Java
145 lines
5.3 KiB
Java
package tschipp.carryon.common.carry;
|
|
|
|
import net.minecraft.core.BlockPos;
|
|
import net.minecraft.core.Direction;
|
|
import net.minecraft.core.Direction.Axis;
|
|
import net.minecraft.server.level.ServerPlayer;
|
|
import net.minecraft.sounds.SoundSource;
|
|
import net.minecraft.world.InteractionHand;
|
|
import net.minecraft.world.entity.Entity;
|
|
import net.minecraft.world.entity.Mob;
|
|
import net.minecraft.world.item.ItemStack;
|
|
import net.minecraft.world.item.context.BlockPlaceContext;
|
|
import net.minecraft.world.level.Level;
|
|
import net.minecraft.world.level.block.Block;
|
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
|
import net.minecraft.world.level.block.state.BlockState;
|
|
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
|
|
import net.minecraft.world.level.block.state.properties.DirectionProperty;
|
|
import net.minecraft.world.level.block.state.properties.EnumProperty;
|
|
import net.minecraft.world.level.block.state.properties.Property;
|
|
import net.minecraft.world.phys.BlockHitResult;
|
|
import net.minecraft.world.phys.Vec3;
|
|
import net.minecraft.world.phys.shapes.CollisionContext;
|
|
import tschipp.carryon.common.carry.CarryOnData.CarryType;
|
|
|
|
import javax.annotation.Nullable;
|
|
import java.util.function.BiFunction;
|
|
|
|
public class PlacementHandler
|
|
{
|
|
|
|
public static boolean tryPlaceBlock(ServerPlayer player, BlockPos pos, Direction facing, @Nullable BiFunction<BlockPos, BlockState, Boolean> placementCallback)
|
|
{
|
|
CarryOnData carry = CarryOnDataManager.getCarryData(player);
|
|
if (!carry.isCarrying(CarryOnData.CarryType.BLOCK))
|
|
return false;
|
|
|
|
if (player.tickCount == carry.getTick())
|
|
return false;
|
|
|
|
Level level = player.getLevel();
|
|
BlockState state = carry.getBlock();
|
|
|
|
BlockPlaceContext context = new BlockPlaceContext(player, InteractionHand.MAIN_HAND, ItemStack.EMPTY, BlockHitResult.miss(player.position(), facing, pos));
|
|
|
|
if (!level.getBlockState(pos).canBeReplaced(context))
|
|
pos = pos.relative(facing);
|
|
|
|
context = new BlockPlaceContext(player, InteractionHand.MAIN_HAND, ItemStack.EMPTY, BlockHitResult.miss(player.position(), facing, pos));
|
|
|
|
BlockEntity blockEntity = carry.getBlockEntity(pos);
|
|
|
|
boolean canPlace = state.canSurvive(level, pos) && level.mayInteract(player, pos) && level.getBlockState(pos).canBeReplaced(context) && level.isUnobstructed(state, pos, CollisionContext.of(player));
|
|
if (!canPlace)
|
|
return false;
|
|
|
|
state = getPlacementState(state, player, context, pos);
|
|
boolean doPlace = placementCallback == null ? true : placementCallback.apply(pos, state);
|
|
|
|
if (!doPlace)
|
|
return false;
|
|
|
|
level.setBlock(pos, state, 3);
|
|
if (blockEntity != null)
|
|
level.setBlockEntity(blockEntity);
|
|
carry.clear();
|
|
CarryOnDataManager.setCarryData(player, carry);
|
|
player.playSound(state.getSoundType().getPlaceSound(), 1.0f, 0.5f);
|
|
level.playSound(null, pos, state.getSoundType().getPlaceSound(), SoundSource.BLOCKS, 1.0f, 0.5f);
|
|
player.swing(InteractionHand.MAIN_HAND, true);
|
|
return true;
|
|
}
|
|
|
|
private static BlockState getPlacementState(BlockState state, ServerPlayer player, BlockPlaceContext context, BlockPos pos)
|
|
{
|
|
BlockState placementState = state.getBlock().getStateForPlacement(context);
|
|
System.out.println(placementState);
|
|
|
|
for (var prop : placementState.getProperties()) {
|
|
if (prop instanceof DirectionProperty) {
|
|
state = updateProperty(state, placementState, prop);
|
|
}
|
|
if (prop instanceof EnumProperty<?>) {
|
|
if (state.getValue(prop) instanceof Axis)
|
|
state = updateProperty(state, placementState, prop);
|
|
}
|
|
//TODO: Add config for state variant names, which should be taken from the placementState
|
|
if (prop.getName().equals("type")) {
|
|
state = updateProperty(state, placementState, prop);
|
|
}
|
|
}
|
|
|
|
System.out.println(state);
|
|
|
|
state = Block.updateFromNeighbourShapes(state, player.level, pos);
|
|
|
|
if (placementState.hasProperty(BlockStateProperties.WATERLOGGED))
|
|
state = state.setValue(BlockStateProperties.WATERLOGGED, placementState.getValue(BlockStateProperties.WATERLOGGED));
|
|
|
|
return state;
|
|
}
|
|
|
|
private static <T extends Comparable<T>, V extends T> BlockState updateProperty(BlockState state, BlockState otherState, Property<T> prop)
|
|
{
|
|
var val = otherState.getValue(prop);
|
|
return state.setValue(prop, val);
|
|
}
|
|
|
|
public static boolean tryPlaceEntity(ServerPlayer player, BlockPos pos, Direction facing, @Nullable BiFunction<Vec3, Entity, Boolean> placementCallback)
|
|
{
|
|
CarryOnData carry = CarryOnDataManager.getCarryData(player);
|
|
if (!carry.isCarrying(CarryType.ENTITY))
|
|
return false;
|
|
|
|
if (player.tickCount == carry.getTick())
|
|
return false;
|
|
|
|
Level level = player.getLevel();
|
|
|
|
BlockPlaceContext context = new BlockPlaceContext(player, InteractionHand.MAIN_HAND, ItemStack.EMPTY, BlockHitResult.miss(player.position(), facing, pos));
|
|
if (!level.getBlockState(pos).canBeReplaced(context))
|
|
pos = pos.relative(facing);
|
|
|
|
Vec3 placementPos = Vec3.atBottomCenterOf(pos);
|
|
|
|
|
|
Entity entity = carry.getEntity(level);
|
|
entity.setPos(placementPos);
|
|
|
|
boolean doPlace = placementCallback == null ? true : placementCallback.apply(placementPos, entity);
|
|
if (!doPlace)
|
|
return false;
|
|
|
|
level.addFreshEntity(entity);
|
|
if(entity instanceof Mob mob)
|
|
mob.playAmbientSound();
|
|
|
|
player.swing(InteractionHand.MAIN_HAND, true);
|
|
carry.clear();
|
|
CarryOnDataManager.setCarryData(player, carry);
|
|
return true;
|
|
}
|
|
|
|
}
|