[Feature] AirSelectionItem allows Items to highlight/use air blocks

This commit is contained in:
Frank 2023-06-14 01:22:55 +02:00
parent 296696d23b
commit 75ccdf38d5
3 changed files with 89 additions and 41 deletions

View file

@ -0,0 +1,60 @@
package org.betterx.bclib.interfaces;
import net.minecraft.util.Mth;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.InteractionResultHolder;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.context.UseOnContext;
import net.minecraft.world.level.ClipBlockStateContext;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.Vec3;
public interface AirSelectionItem {
default boolean renderAirSelection() {
return true;
}
default int airSelectionColor() {
return 0xBFF6FA70;
}
default BlockHitResult getAirSelectionHit(Level level, Player player) {
if (renderAirSelection()) {
final var vec = new Vec3(0, 0, 1)
.xRot(-player.getXRot() * Mth.DEG_TO_RAD)
.yRot(-player.getYHeadRot() * Mth.DEG_TO_RAD);
return level.isBlockInLine(new ClipBlockStateContext(
player.getEyePosition(),
player.getEyePosition().add(vec.scale(4.9)),
BlockBehaviour.BlockStateBase::isAir
));
}
return null;
}
default InteractionResultHolder<ItemStack> useOnAir(Level level, Player player, InteractionHand interactionHand) {
final BlockHitResult hit = getAirSelectionHit(level, player);
if (hit != null) {
var result = this.useOn(new UseOnContext(player, interactionHand, hit));
if (result == InteractionResult.SUCCESS)
return InteractionResultHolder.success(player.getItemInHand(interactionHand));
else if (result == InteractionResult.FAIL)
return InteractionResultHolder.fail(player.getItemInHand(interactionHand));
else if (result == InteractionResult.PASS)
return InteractionResultHolder.pass(player.getItemInHand(interactionHand));
else if (result == InteractionResult.CONSUME)
return InteractionResultHolder.consume(player.getItemInHand(interactionHand));
}
return InteractionResultHolder.pass(player.getItemInHand(interactionHand));
}
InteractionResult useOn(UseOnContext useOnContext);
}

View file

@ -3,6 +3,7 @@ package org.betterx.bclib.items;
import de.ambertation.wunderlib.math.Bounds;
import org.betterx.bclib.client.models.ModelsHelper;
import org.betterx.bclib.commands.PlaceCommand;
import org.betterx.bclib.interfaces.AirSelectionItem;
import org.betterx.bclib.interfaces.ItemModelProvider;
import org.betterx.bclib.util.BlocksHelper;
import org.betterx.ui.ColorUtil;
@ -20,7 +21,6 @@ import net.minecraft.network.chat.Style;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.util.Mth;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.InteractionResultHolder;
@ -28,7 +28,6 @@ import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.context.UseOnContext;
import net.minecraft.world.level.ClipBlockStateContext;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.JigsawBlock;
@ -36,11 +35,8 @@ import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.JigsawBlockEntity;
import net.minecraft.world.level.block.entity.RandomizableContainerBlockEntity;
import net.minecraft.world.level.block.entity.StructureBlockEntity;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.levelgen.structure.pools.StructureTemplatePool;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.Vec3;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
@ -48,7 +44,7 @@ import net.fabricmc.api.Environment;
import java.util.HashSet;
import java.util.Set;
public class DebugDataItem extends Item implements ItemModelProvider {
public class DebugDataItem extends Item implements ItemModelProvider, AirSelectionItem {
public static final ResourceLocation DEFAULT_ICON = new ResourceLocation("stick");
@ -134,7 +130,7 @@ public class DebugDataItem extends Item implements ItemModelProvider {
if (predicate.test(level.getBlockState(pos))) {
level.setBlock(pos, newState, BlocksHelper.SET_SILENT);
floodFillStructureEntityBounds(level, bounds, pos.above(), entity, predicate, newState, visited);
floodFillStructureEntityBounds(level, bounds, pos.below(), entity, predicate, newState, visited);
floodFillStructureEntityBounds(level, bounds, pos.north(), entity, predicate, newState, visited);
@ -177,6 +173,11 @@ public class DebugDataItem extends Item implements ItemModelProvider {
this.placeInAir = placeInAir;
}
public boolean renderAirSelection() {
return placeInAir;
}
@Override
public boolean isFoil(ItemStack itemStack) {
return true;
@ -218,32 +219,7 @@ public class DebugDataItem extends Item implements ItemModelProvider {
@Override
public InteractionResultHolder<ItemStack> use(Level level, Player player, InteractionHand interactionHand) {
if (placeInAir) {
final var vec = new Vec3(0, 0, 1)
.xRot(-player.getXRot() * Mth.DEG_TO_RAD)
.yRot(-player.getYHeadRot() * Mth.DEG_TO_RAD);
BlockHitResult hit = level.isBlockInLine(new ClipBlockStateContext(
player.getEyePosition(),
player.getEyePosition().add(vec.scale(4.9)),
BlockBehaviour.BlockStateBase::isAir
));
if (hit != null) {
var result = this.useOn(new UseOnContext(player, interactionHand, hit));
if (result == InteractionResult.SUCCESS)
return InteractionResultHolder.success(player.getItemInHand(interactionHand));
else if (result == InteractionResult.FAIL)
return InteractionResultHolder.fail(player.getItemInHand(interactionHand));
else if (result == InteractionResult.PASS)
return InteractionResultHolder.pass(player.getItemInHand(interactionHand));
else if (result == InteractionResult.CONSUME)
return InteractionResultHolder.consume(player.getItemInHand(interactionHand));
}
}
return InteractionResultHolder.pass(player.getItemInHand(interactionHand));
return AirSelectionItem.super.useOnAir(level, player, interactionHand);
}
public static DebugDataItem forLootTable(ResourceLocation table, Item icon) {

View file

@ -1,16 +1,20 @@
package org.betterx.bclib.mixin.client;
import org.betterx.bclib.BCLib;
import org.betterx.bclib.items.DebugDataItem;
import org.betterx.bclib.interfaces.AirSelectionItem;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.VertexConsumer;
import net.minecraft.client.Camera;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.*;
import net.minecraft.core.BlockPos;
import net.minecraft.util.FastColor;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.HitResult;
import net.minecraft.world.phys.Vec3;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape;
@ -66,18 +70,26 @@ public abstract class LevelRendererMixin {
if (BCLib.isDevEnvironment() && minecraft.hitResult instanceof BlockHitResult blockHitResult) {
//will render a block outline when empty blocks are targeted
ItemStack item = minecraft.player.getMainHandItem();
if (item != null && (item.getItem() instanceof DebugDataItem ddi) && ddi.placeInAir) {
final var pos = blockHitResult.getBlockPos();
final var state = Blocks.DIRT.defaultBlockState();
MultiBufferSource.BufferSource bufferSource = this.renderBuffers.bufferSource();
VertexConsumer consumer = bufferSource.getBuffer(RenderType.lines());
Vec3 camPos = camera.getPosition();
if (item != null
&& (item.getItem() instanceof AirSelectionItem airSelect)
&& airSelect.renderAirSelection()
&& blockHitResult.getType() == HitResult.Type.MISS
) {
final BlockPos pos = blockHitResult.getBlockPos();
final BlockState state = Blocks.DIRT.defaultBlockState();
final int color = airSelect.airSelectionColor();
final MultiBufferSource.BufferSource bufferSource = this.renderBuffers.bufferSource();
final VertexConsumer consumer = bufferSource.getBuffer(RenderType.lines());
final Vec3 camPos = camera.getPosition();
this.renderShape(
poseStack, consumer,
state.getShape(minecraft.level, pos, CollisionContext.of(camera.getEntity())),
pos.getX() - camPos.x(), pos.getY() - camPos.y(), pos.getZ() - camPos.z(),
246.0f / 0xff, 250.0f / 0xff, 112.0f / 0xff, 0.75F
FastColor.ARGB32.red(color) / (float) 0xff,
FastColor.ARGB32.green(color) / (float) 0xff,
FastColor.ARGB32.blue(color) / (float) 0xff,
FastColor.ARGB32.alpha(color) / (float) 0xff
);
}
}