Add drill highlighting

This commit is contained in:
Mrbysco 2024-03-13 01:50:37 +01:00
parent 5a1eabeac4
commit f390ffd47f
3 changed files with 169 additions and 0 deletions

View file

@ -12,34 +12,46 @@ package de.ellpeck.actuallyadditions.mod.event;
import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.VertexConsumer;
import de.ellpeck.actuallyadditions.mod.ActuallyAdditions; import de.ellpeck.actuallyadditions.mod.ActuallyAdditions;
import de.ellpeck.actuallyadditions.mod.blocks.IHudDisplay; import de.ellpeck.actuallyadditions.mod.blocks.IHudDisplay;
import de.ellpeck.actuallyadditions.mod.config.CommonConfig; import de.ellpeck.actuallyadditions.mod.config.CommonConfig;
import de.ellpeck.actuallyadditions.mod.data.WorldData; import de.ellpeck.actuallyadditions.mod.data.WorldData;
import de.ellpeck.actuallyadditions.mod.inventory.gui.EnergyDisplay; import de.ellpeck.actuallyadditions.mod.inventory.gui.EnergyDisplay;
import de.ellpeck.actuallyadditions.mod.items.DrillItem;
import de.ellpeck.actuallyadditions.mod.items.ItemDrillUpgrade;
import de.ellpeck.actuallyadditions.mod.tile.IEnergyDisplay; import de.ellpeck.actuallyadditions.mod.tile.IEnergyDisplay;
import de.ellpeck.actuallyadditions.mod.tile.TileEntityBase; import de.ellpeck.actuallyadditions.mod.tile.TileEntityBase;
import de.ellpeck.actuallyadditions.mod.util.AssetUtil;
import de.ellpeck.actuallyadditions.mod.util.StackUtil; import de.ellpeck.actuallyadditions.mod.util.StackUtil;
import net.minecraft.ChatFormatting; import net.minecraft.ChatFormatting;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.Font; import net.minecraft.client.gui.Font;
import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.core.BlockPos;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.HitResult; import net.minecraft.world.phys.HitResult;
import net.minecraft.world.phys.Vec3;
import net.neoforged.api.distmarker.Dist; import net.neoforged.api.distmarker.Dist;
import net.neoforged.api.distmarker.OnlyIn; import net.neoforged.api.distmarker.OnlyIn;
import net.neoforged.bus.api.SubscribeEvent; import net.neoforged.bus.api.SubscribeEvent;
import net.neoforged.neoforge.client.event.RenderGuiOverlayEvent; import net.neoforged.neoforge.client.event.RenderGuiOverlayEvent;
import net.neoforged.neoforge.client.event.RenderHighlightEvent;
import net.neoforged.neoforge.client.gui.overlay.GuiOverlayManager; import net.neoforged.neoforge.client.gui.overlay.GuiOverlayManager;
import net.neoforged.neoforge.event.TickEvent; import net.neoforged.neoforge.event.TickEvent;
import net.neoforged.neoforge.event.entity.player.ItemTooltipEvent; import net.neoforged.neoforge.event.entity.player.ItemTooltipEvent;
import java.util.List;
@OnlyIn(Dist.CLIENT) @OnlyIn(Dist.CLIENT)
public class ClientEvents { public class ClientEvents {
@ -227,6 +239,46 @@ public class ClientEvents {
} }
} }
@SubscribeEvent
public void renderBlockHighlight(RenderHighlightEvent.Block event) {
Minecraft mc = Minecraft.getInstance();
Player player = mc.player;
if (mc.player == null)
return;
ItemStack stack = player.getMainHandItem();
if (stack.getItem() instanceof DrillItem drillItem) {
if (!player.isShiftKeyDown() && drillItem.getHasUpgrade(stack, ItemDrillUpgrade.UpgradeType.THREE_BY_THREE)) {
Level level = player.level();
Vec3 vec3 = event.getCamera().getPosition();
double d0 = vec3.x();
double d1 = vec3.y();
double d2 = vec3.z();
BlockHitResult blockHitResult = event.getTarget();
BlockPos targetPos = blockHitResult.getBlockPos();
BlockState blockState = level.getBlockState(targetPos);
VertexConsumer lineConsumer = event.getMultiBufferSource().getBuffer(RenderType.lines());
if (stack.isCorrectToolForDrops(blockState)) {
int radius = 0;
if (drillItem.getHasUpgrade(stack, ItemDrillUpgrade.UpgradeType.FIVE_BY_FIVE)) {
radius = 2;
} else if (drillItem.getHasUpgrade(stack, ItemDrillUpgrade.UpgradeType.THREE_BY_THREE)) {
radius = 1;
}
if (radius == 0) return; //No radius, no need to render extra hitboxes
List<BlockPos> coords = drillItem.gatherBreakingPositions(stack, radius, level, targetPos, blockHitResult.getDirection(), player);
for (BlockPos blockPos : coords) {
if (blockPos.equals(targetPos)) continue; //Let the original event draw this one!
AssetUtil.renderHitOutline(event.getPoseStack(), lineConsumer, player, d0, d1, d2, level, blockPos, level.getBlockState(blockPos));
}
}
}
}
}
/* @SubscribeEvent //TODO someday move the laser rendering to a new system /* @SubscribeEvent //TODO someday move the laser rendering to a new system
public void onRenderStage(final RenderLevelStageEvent event) { public void onRenderStage(final RenderLevelStageEvent event) {
if(event.getStage() == RenderLevelStageEvent.Stage.AFTER_SOLID_BLOCKS) { if(event.getStage() == RenderLevelStageEvent.Stage.AFTER_SOLID_BLOCKS) {

View file

@ -54,6 +54,7 @@ import net.neoforged.neoforge.items.IItemHandler;
import net.neoforged.neoforge.items.IItemHandlerModifiable; import net.neoforged.neoforge.items.IItemHandlerModifiable;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import java.util.ArrayList;
import java.util.List; import java.util.List;
public class DrillItem extends ItemEnergy { public class DrillItem extends ItemEnergy {
@ -457,6 +458,77 @@ public class DrillItem extends ItemEnergy {
return true; return true;
} }
/**
* Generate a list of block positions that can be broken taking radius, poker and side into account
* @param stack The Drill
* @param radius The Radius to break Blocks in (0 means only 1 Block will be broken!)
* @param world The World
* @param aPos The position of the block being broken
* @param side The side of the block being broken
* @param player The Player who breaks the Blocks
* @return A list of block positions that can be broken
*/
public List<BlockPos> gatherBreakingPositions(ItemStack stack, int radius, Level world, BlockPos aPos, Direction side, Player player) {
int energyStored = this.getEnergyStored(stack);
List<BlockPos> positions = new ArrayList<>();
int xRange = radius;
int yRange = radius;
int zRange = 0;
//Corrects Blocks to hit depending on Side of original Block hit
if (side.getAxis() == Direction.Axis.Y) {
zRange = radius;
yRange = 0;
}
if (side.getAxis() == Direction.Axis.X) {
xRange = 0;
zRange = radius;
}
//Not defined later because main Block is getting broken below
BlockState state = world.getBlockState(aPos);
float mainHardness = state.getDestroySpeed(world, aPos);
//Break Middle Block first
int use = this.getEnergyUsePerBlock(stack);
if (energyStored < use) {
return positions;
}
if (radius == 2 && side.getAxis() != Direction.Axis.Y) {
aPos = aPos.above();
BlockState theState = world.getBlockState(aPos);
if (theState.getDestroySpeed(world, aPos) <= mainHardness + 5.0F) {
positions.add(aPos.immutable());
}
}
//Break Blocks around
if (radius > 0 && mainHardness >= 0.2F) {
for (int xPos = aPos.getX() - xRange; xPos <= aPos.getX() + xRange; xPos++) {
for (int yPos = aPos.getY() - yRange; yPos <= aPos.getY() + yRange; yPos++) {
for (int zPos = aPos.getZ() - zRange; zPos <= aPos.getZ() + zRange; zPos++) {
if (!(aPos.getX() == xPos && aPos.getY() == yPos && aPos.getZ() == zPos)) {
if (energyStored >= use) {
//Only break Blocks around that are (about) as hard or softer
BlockPos thePos = new BlockPos(xPos, yPos, zPos);
BlockState theState = world.getBlockState(thePos);
if (theState.getDestroySpeed(world, thePos) <= mainHardness + 5.0F) {
energyStored -= use;
positions.add(thePos.immutable());
}
} else {
return positions;
}
}
}
}
}
}
return positions;
}
/** /**
* Tries to harvest a certain Block * Tries to harvest a certain Block
* Breaks the Block, drops Particles etc. * Breaks the Block, drops Particles etc.

View file

@ -36,13 +36,19 @@ import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.renderer.texture.TextureManager; import net.minecraft.client.renderer.texture.TextureManager;
import net.minecraft.client.resources.language.I18n; import net.minecraft.client.resources.language.I18n;
import net.minecraft.client.resources.model.BakedModel; import net.minecraft.client.resources.model.BakedModel;
import net.minecraft.core.BlockPos;
import net.minecraft.core.NonNullList; import net.minecraft.core.NonNullList;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.Mth;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.item.ItemDisplayContext; import net.minecraft.world.item.ItemDisplayContext;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.Vec3;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape;
import net.neoforged.api.distmarker.Dist; import net.neoforged.api.distmarker.Dist;
import net.neoforged.api.distmarker.OnlyIn; import net.neoforged.api.distmarker.OnlyIn;
import net.neoforged.neoforge.client.ClientHooks; import net.neoforged.neoforge.client.ClientHooks;
@ -423,4 +429,43 @@ public final class AssetUtil {
} }
return new float[]{0.0f, (pos -= 170.0f) * 3.0f, 255.0f - pos * 3.0f}; return new float[]{0.0f, (pos -= 170.0f) * 3.0f, 255.0f - pos * 3.0f};
} }
@OnlyIn(Dist.CLIENT)
public static void renderHitOutline(PoseStack poseStack, VertexConsumer consumer, Entity entity,
double camX, double camY, double camZ, Level level, BlockPos pos, BlockState state) {
renderShape(poseStack, consumer, state.getShape(level, pos, CollisionContext.of(entity)),
(double) pos.getX() - camX,
(double) pos.getY() - camY,
(double) pos.getZ() - camZ,
0.0F,
0.0F,
0.0F,
0.4F
);
}
@OnlyIn(Dist.CLIENT)
private static void renderShape(PoseStack poseStack, VertexConsumer consumer, VoxelShape shape,
double x, double y, double z, float red, float green, float blue, float alpha) {
PoseStack.Pose posestack$pose = poseStack.last();
shape.forAllEdges(
(minX, minY, minZ, maxX, maxY, maxZ) -> {
float f = (float) (maxX - minX);
float f1 = (float) (maxY - minY);
float f2 = (float) (maxZ - minZ);
float f3 = Mth.sqrt(f * f + f1 * f1 + f2 * f2);
f /= f3;
f1 /= f3;
f2 /= f3;
consumer.vertex(posestack$pose.pose(), (float) (minX + x), (float) (minY + y), (float) (minZ + z))
.color(red, green, blue, alpha)
.normal(posestack$pose.normal(), f, f1, f2)
.endVertex();
consumer.vertex(posestack$pose.pose(), (float) (maxX + x), (float) (maxY + y), (float) (maxZ + z))
.color(red, green, blue, alpha)
.normal(posestack$pose.normal(), f, f1, f2)
.endVertex();
}
);
}
} }