baritone/src/main/java/baritone/utils/PathRenderer.java

348 lines
16 KiB
Java
Raw Normal View History

/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
2018-08-22 20:15:56 +00:00
package baritone.utils;
2018-08-22 20:15:56 +00:00
import baritone.Baritone;
2018-10-08 22:11:07 +00:00
import baritone.api.event.events.RenderEvent;
2018-10-10 02:34:53 +00:00
import baritone.api.pathing.calc.IPath;
import baritone.api.pathing.goals.Goal;
2018-09-25 01:32:39 +00:00
import baritone.api.pathing.goals.GoalComposite;
import baritone.api.pathing.goals.GoalTwoBlocks;
import baritone.api.pathing.goals.GoalXZ;
2018-10-09 01:37:52 +00:00
import baritone.api.utils.BetterBlockPos;
2018-09-25 01:32:39 +00:00
import baritone.api.utils.interfaces.IGoalRenderPos;
2018-10-08 22:11:07 +00:00
import baritone.behavior.PathingBehavior;
import baritone.pathing.calc.AbstractNodeCostSearch;
import baritone.pathing.path.PathExecutor;
import net.minecraft.block.state.IBlockState;
2018-08-09 23:44:41 +00:00
import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Blocks;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import java.awt.*;
2018-08-09 23:44:41 +00:00
import java.util.Collection;
2018-10-08 22:11:07 +00:00
import java.util.Collections;
import java.util.List;
2018-08-10 01:25:43 +00:00
import static org.lwjgl.opengl.GL11.*;
/**
* @author Brady
* @since 8/9/2018 4:39 PM
*/
public final class PathRenderer implements Helper {
2018-08-10 01:25:43 +00:00
private static final Tessellator TESSELLATOR = Tessellator.getInstance();
private static final BufferBuilder BUFFER = TESSELLATOR.getBuffer();
2018-08-09 23:44:41 +00:00
2018-09-17 03:16:05 +00:00
private PathRenderer() {}
2018-10-08 22:11:07 +00:00
public static void render(RenderEvent event, PathingBehavior behavior) {
// System.out.println("Render passing");
// System.out.println(event.getPartialTicks());
float partialTicks = event.getPartialTicks();
Goal goal = behavior.getGoal();
EntityPlayerSP player = mc.player;
if (goal != null && Baritone.settings().renderGoal.value) {
2018-10-11 00:05:51 +00:00
drawLitDankGoalBox(player, goal, partialTicks, Baritone.settings().colorGoalBox.get());
2018-10-08 22:11:07 +00:00
}
if (!Baritone.settings().renderPath.get()) {
return;
}
2018-10-11 00:05:51 +00:00
//drawManySelectionBoxes(player, Collections.singletonList(behavior.pathStart()), partialTicks, Color.WHITE);
2018-10-08 22:11:07 +00:00
//long start = System.nanoTime();
PathExecutor current = behavior.getCurrent(); // this should prevent most race conditions?
PathExecutor next = behavior.getNext(); // like, now it's not possible for current!=null to be true, then suddenly false because of another thread
// TODO is this enough, or do we need to acquire a lock here?
// TODO benchmark synchronized in render loop
// Render the current path, if there is one
if (current != null && current.getPath() != null) {
int renderBegin = Math.max(current.getPosition() - 3, 0);
2018-10-11 00:05:51 +00:00
drawPath(current.getPath(), renderBegin, player, partialTicks, Baritone.settings().colorCurrentPath.get(), Baritone.settings().fadePath.get(), 10, 20);
2018-10-08 22:11:07 +00:00
}
if (next != null && next.getPath() != null) {
2018-10-11 00:05:51 +00:00
drawPath(next.getPath(), 0, player, partialTicks, Baritone.settings().colorNextPath.get(), Baritone.settings().fadePath.get(), 10, 20);
2018-10-08 22:11:07 +00:00
}
//long split = System.nanoTime();
if (current != null) {
2018-10-11 00:05:51 +00:00
drawManySelectionBoxes(player, current.toBreak(), partialTicks, Baritone.settings().colorBlocksToBreak.get());
drawManySelectionBoxes(player, current.toPlace(), partialTicks, Baritone.settings().colorBlocksToPlace.get());
drawManySelectionBoxes(player, current.toWalkInto(), partialTicks, Baritone.settings().colorBlocksToWalkInto.get());
2018-10-08 22:11:07 +00:00
}
// If there is a path calculation currently running, render the path calculation process
AbstractNodeCostSearch.getCurrentlyRunning().ifPresent(currentlyRunning -> {
currentlyRunning.bestPathSoFar().ifPresent(p -> {
2018-10-11 00:05:51 +00:00
drawPath(p, 0, player, partialTicks, Baritone.settings().colorBestPathSoFar.get(), Baritone.settings().fadePath.get(), 10, 20);
2018-10-08 22:11:07 +00:00
});
currentlyRunning.pathToMostRecentNodeConsidered().ifPresent(mr -> {
2018-10-11 00:05:51 +00:00
drawPath(mr, 0, player, partialTicks, Baritone.settings().colorMostRecentConsidered.get(), Baritone.settings().fadePath.get(), 10, 20);
drawManySelectionBoxes(player, Collections.singletonList(mr.getDest()), partialTicks, Baritone.settings().colorMostRecentConsidered.get());
2018-10-08 22:11:07 +00:00
});
});
//long end = System.nanoTime();
//System.out.println((end - split) + " " + (split - start));
// if (end - start > 0) {
// System.out.println("Frame took " + (split - start) + " " + (end - split));
//}
}
2018-09-17 00:51:39 +00:00
public static void drawPath(IPath path, int startIndex, EntityPlayerSP player, float partialTicks, Color color, boolean fadeOut, int fadeStart0, int fadeEnd0) {
GlStateManager.enableBlend();
2018-08-10 01:25:43 +00:00
GlStateManager.tryBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO);
GlStateManager.color(color.getColorComponents(null)[0], color.getColorComponents(null)[1], color.getColorComponents(null)[2], 0.4F);
2018-08-20 02:12:37 +00:00
GlStateManager.glLineWidth(Baritone.settings().pathRenderLineWidthPixels.get());
GlStateManager.disableTexture2D();
GlStateManager.depthMask(false);
2018-10-11 03:38:24 +00:00
if (Baritone.settings().renderPathIgnoreDepth.get()) {
GlStateManager.disableDepth();
}
2018-08-16 22:14:00 +00:00
List<BetterBlockPos> positions = path.positions();
int next;
2018-08-09 23:44:41 +00:00
Tessellator tessellator = Tessellator.getInstance();
2018-09-17 00:51:39 +00:00
int fadeStart = fadeStart0 + startIndex;
int fadeEnd = fadeEnd0 + startIndex;
for (int i = startIndex; i < positions.size() - 1; i = next) {
BetterBlockPos start = positions.get(i);
next = i + 1;
BetterBlockPos end = positions.get(next);
2018-08-14 04:05:35 +00:00
int dirX = end.x - start.x;
int dirY = end.y - start.y;
int dirZ = end.z - start.z;
while (next + 1 < positions.size() && (!fadeOut || next + 1 < fadeStart) && (dirX == positions.get(next + 1).x - end.x && dirY == positions.get(next + 1).y - end.y && dirZ == positions.get(next + 1).z - end.z)) {
next++;
end = positions.get(next);
}
2018-10-03 15:14:15 +00:00
double x1 = start.x;
double y1 = start.y;
double z1 = start.z;
double x2 = end.x;
double y2 = end.y;
double z2 = end.z;
2018-08-14 04:05:35 +00:00
if (fadeOut) {
float alpha;
if (i <= fadeStart) {
alpha = 0.4F;
} else {
if (i > fadeEnd) {
break;
}
2018-08-16 00:53:42 +00:00
alpha = 0.4F * (1.0F - (float) (i - fadeStart) / (float) (fadeEnd - fadeStart));
2018-08-14 04:05:35 +00:00
}
GlStateManager.color(color.getColorComponents(null)[0], color.getColorComponents(null)[1], color.getColorComponents(null)[2], alpha);
}
2018-08-10 01:25:43 +00:00
drawLine(player, x1, y1, z1, x2, y2, z2, partialTicks);
2018-08-09 23:44:41 +00:00
tessellator.draw();
}
2018-10-11 03:38:24 +00:00
if (Baritone.settings().renderPathIgnoreDepth.get()) {
GlStateManager.enableDepth();
}
2018-08-09 23:44:41 +00:00
//GlStateManager.color(0.0f, 0.0f, 0.0f, 0.4f);
GlStateManager.depthMask(true);
GlStateManager.enableTexture2D();
GlStateManager.disableBlend();
}
2018-08-10 01:25:43 +00:00
public static void drawLine(EntityPlayer player, double bp1x, double bp1y, double bp1z, double bp2x, double bp2y, double bp2z, float partialTicks) {
double d0 = player.lastTickPosX + (player.posX - player.lastTickPosX) * (double) partialTicks;
double d1 = player.lastTickPosY + (player.posY - player.lastTickPosY) * (double) partialTicks;
double d2 = player.lastTickPosZ + (player.posZ - player.lastTickPosZ) * (double) partialTicks;
2018-08-10 01:25:43 +00:00
BUFFER.begin(GL_LINE_STRIP, DefaultVertexFormats.POSITION);
BUFFER.pos(bp1x + 0.5D - d0, bp1y + 0.5D - d1, bp1z + 0.5D - d2).endVertex();
BUFFER.pos(bp2x + 0.5D - d0, bp2y + 0.5D - d1, bp2z + 0.5D - d2).endVertex();
BUFFER.pos(bp2x + 0.5D - d0, bp2y + 0.53D - d1, bp2z + 0.5D - d2).endVertex();
BUFFER.pos(bp1x + 0.5D - d0, bp1y + 0.53D - d1, bp1z + 0.5D - d2).endVertex();
BUFFER.pos(bp1x + 0.5D - d0, bp1y + 0.5D - d1, bp1z + 0.5D - d2).endVertex();
}
2018-08-09 23:44:41 +00:00
public static void drawManySelectionBoxes(EntityPlayer player, Collection<BlockPos> positions, float partialTicks, Color color) {
GlStateManager.enableBlend();
2018-08-09 23:44:41 +00:00
GlStateManager.tryBlendFuncSeparate(770, 771, 1, 0);
GlStateManager.color(color.getColorComponents(null)[0], color.getColorComponents(null)[1], color.getColorComponents(null)[2], 0.4F);
2018-08-20 02:12:37 +00:00
GlStateManager.glLineWidth(Baritone.settings().pathRenderLineWidthPixels.get());
GlStateManager.disableTexture2D();
GlStateManager.depthMask(false);
2018-10-10 02:34:53 +00:00
if (Baritone.settings().renderSelectionBoxesIgnoreDepth.get()) {
GlStateManager.disableDepth();
}
2018-08-10 01:25:43 +00:00
float expand = 0.002F;
2018-08-09 23:44:41 +00:00
//BlockPos blockpos = movingObjectPositionIn.getBlockPos();
2018-08-10 01:25:43 +00:00
double renderPosX = player.lastTickPosX + (player.posX - player.lastTickPosX) * (double) partialTicks;
double renderPosY = player.lastTickPosY + (player.posY - player.lastTickPosY) * (double) partialTicks;
double renderPosZ = player.lastTickPosZ + (player.posZ - player.lastTickPosZ) * (double) partialTicks;
positions.forEach(pos -> {
2018-11-13 21:14:29 +00:00
IBlockState state = BlockStateInterface.get(Baritone.INSTANCE.getPlayerContext(), pos);
2018-08-09 23:44:41 +00:00
AxisAlignedBB toDraw;
2018-08-10 01:25:43 +00:00
if (state.getBlock().equals(Blocks.AIR)) {
toDraw = Blocks.DIRT.getDefaultState().getSelectedBoundingBox(Minecraft.getMinecraft().world, pos);
2018-08-09 23:44:41 +00:00
} else {
toDraw = state.getSelectedBoundingBox(Minecraft.getMinecraft().world, pos);
}
2018-08-10 01:25:43 +00:00
toDraw = toDraw.expand(expand, expand, expand).offset(-renderPosX, -renderPosY, -renderPosZ);
BUFFER.begin(GL_LINE_STRIP, DefaultVertexFormats.POSITION);
BUFFER.pos(toDraw.minX, toDraw.minY, toDraw.minZ).endVertex();
BUFFER.pos(toDraw.maxX, toDraw.minY, toDraw.minZ).endVertex();
BUFFER.pos(toDraw.maxX, toDraw.minY, toDraw.maxZ).endVertex();
BUFFER.pos(toDraw.minX, toDraw.minY, toDraw.maxZ).endVertex();
BUFFER.pos(toDraw.minX, toDraw.minY, toDraw.minZ).endVertex();
TESSELLATOR.draw();
BUFFER.begin(GL_LINE_STRIP, DefaultVertexFormats.POSITION);
BUFFER.pos(toDraw.minX, toDraw.maxY, toDraw.minZ).endVertex();
BUFFER.pos(toDraw.maxX, toDraw.maxY, toDraw.minZ).endVertex();
BUFFER.pos(toDraw.maxX, toDraw.maxY, toDraw.maxZ).endVertex();
BUFFER.pos(toDraw.minX, toDraw.maxY, toDraw.maxZ).endVertex();
BUFFER.pos(toDraw.minX, toDraw.maxY, toDraw.minZ).endVertex();
TESSELLATOR.draw();
BUFFER.begin(GL_LINES, DefaultVertexFormats.POSITION);
BUFFER.pos(toDraw.minX, toDraw.minY, toDraw.minZ).endVertex();
BUFFER.pos(toDraw.minX, toDraw.maxY, toDraw.minZ).endVertex();
BUFFER.pos(toDraw.maxX, toDraw.minY, toDraw.minZ).endVertex();
BUFFER.pos(toDraw.maxX, toDraw.maxY, toDraw.minZ).endVertex();
BUFFER.pos(toDraw.maxX, toDraw.minY, toDraw.maxZ).endVertex();
BUFFER.pos(toDraw.maxX, toDraw.maxY, toDraw.maxZ).endVertex();
BUFFER.pos(toDraw.minX, toDraw.minY, toDraw.maxZ).endVertex();
BUFFER.pos(toDraw.minX, toDraw.maxY, toDraw.maxZ).endVertex();
TESSELLATOR.draw();
});
2018-08-09 23:44:41 +00:00
2018-10-10 02:34:53 +00:00
if (Baritone.settings().renderSelectionBoxesIgnoreDepth.get()) {
GlStateManager.enableDepth();
}
2018-08-16 00:53:42 +00:00
GlStateManager.depthMask(true);
GlStateManager.enableTexture2D();
GlStateManager.disableBlend();
}
2018-08-16 22:34:23 +00:00
public static void drawLitDankGoalBox(EntityPlayer player, Goal goal, float partialTicks, Color color) {
2018-08-16 00:53:42 +00:00
double renderPosX = player.lastTickPosX + (player.posX - player.lastTickPosX) * (double) partialTicks;
double renderPosY = player.lastTickPosY + (player.posY - player.lastTickPosY) * (double) partialTicks;
double renderPosZ = player.lastTickPosZ + (player.posZ - player.lastTickPosZ) * (double) partialTicks;
2018-08-16 22:34:23 +00:00
double minX;
double maxX;
double minZ;
double maxZ;
double minY;
double maxY;
double y1;
double y2;
2018-09-08 01:23:32 +00:00
if (goal instanceof IGoalRenderPos) {
BlockPos goalPos = ((IGoalRenderPos) goal).getGoalPos();
2018-08-16 22:34:23 +00:00
minX = goalPos.getX() + 0.002 - renderPosX;
maxX = goalPos.getX() + 1 - 0.002 - renderPosX;
minZ = goalPos.getZ() + 0.002 - renderPosZ;
maxZ = goalPos.getZ() + 1 - 0.002 - renderPosZ;
2018-09-08 01:23:32 +00:00
double y = MathHelper.cos((float) (((float) ((System.nanoTime() / 100000L) % 20000L)) / 20000F * Math.PI * 2));
2018-09-08 03:43:12 +00:00
if (goal instanceof GoalTwoBlocks) {
y /= 2;
}
2018-08-16 22:34:23 +00:00
y1 = 1 + y + goalPos.getY() - renderPosY;
y2 = 1 - y + goalPos.getY() - renderPosY;
minY = goalPos.getY() - renderPosY;
maxY = minY + 2;
2018-09-08 03:43:12 +00:00
if (goal instanceof GoalTwoBlocks) {
y1 -= 0.5;
y2 -= 0.5;
maxY--;
}
2018-08-16 22:34:23 +00:00
} else if (goal instanceof GoalXZ) {
GoalXZ goalPos = (GoalXZ) goal;
2018-08-16 00:53:42 +00:00
2018-08-16 22:34:23 +00:00
minX = goalPos.getX() + 0.002 - renderPosX;
maxX = goalPos.getX() + 1 - 0.002 - renderPosX;
minZ = goalPos.getZ() + 0.002 - renderPosZ;
maxZ = goalPos.getZ() + 1 - 0.002 - renderPosZ;
2018-08-16 00:53:42 +00:00
2018-08-16 22:34:23 +00:00
y1 = 0;
y2 = 0;
minY = 0 - renderPosY;
maxY = 256 - renderPosY;
2018-09-08 21:16:54 +00:00
} else if (goal instanceof GoalComposite) {
2018-09-08 01:23:32 +00:00
for (Goal g : ((GoalComposite) goal).goals()) {
drawLitDankGoalBox(player, g, partialTicks, color);
}
2018-08-16 22:34:23 +00:00
return;
2018-09-08 21:16:54 +00:00
} else {
return;
2018-08-16 22:34:23 +00:00
}
2018-08-16 00:53:42 +00:00
2018-08-18 02:30:41 +00:00
GlStateManager.enableBlend();
GlStateManager.tryBlendFuncSeparate(770, 771, 1, 0);
GlStateManager.color(color.getColorComponents(null)[0], color.getColorComponents(null)[1], color.getColorComponents(null)[2], 0.6F);
2018-08-20 02:12:37 +00:00
GlStateManager.glLineWidth(Baritone.settings().goalRenderLineWidthPixels.get());
2018-08-18 02:30:41 +00:00
GlStateManager.disableTexture2D();
GlStateManager.depthMask(false);
2018-10-08 22:06:41 +00:00
if (Baritone.settings().renderGoalIgnoreDepth.get()) {
GlStateManager.disableDepth();
2018-08-16 22:34:23 +00:00
}
2018-10-08 22:06:41 +00:00
renderHorizontalQuad(minX, maxX, minZ, maxZ, y1);
renderHorizontalQuad(minX, maxX, minZ, maxZ, y2);
2018-08-16 00:53:42 +00:00
BUFFER.begin(GL_LINES, DefaultVertexFormats.POSITION);
BUFFER.pos(minX, minY, minZ).endVertex();
BUFFER.pos(minX, maxY, minZ).endVertex();
BUFFER.pos(maxX, minY, minZ).endVertex();
BUFFER.pos(maxX, maxY, minZ).endVertex();
BUFFER.pos(maxX, minY, maxZ).endVertex();
BUFFER.pos(maxX, maxY, maxZ).endVertex();
BUFFER.pos(minX, minY, maxZ).endVertex();
BUFFER.pos(minX, maxY, maxZ).endVertex();
TESSELLATOR.draw();
2018-10-08 22:06:41 +00:00
if (Baritone.settings().renderGoalIgnoreDepth.get()) {
GlStateManager.enableDepth();
}
GlStateManager.depthMask(true);
GlStateManager.enableTexture2D();
GlStateManager.disableBlend();
}
2018-10-08 22:06:41 +00:00
private static void renderHorizontalQuad(double minX, double maxX, double minZ, double maxZ, double y) {
if (y != 0) {
BUFFER.begin(GL_LINE_LOOP, DefaultVertexFormats.POSITION);
BUFFER.pos(minX, y, minZ).endVertex();
BUFFER.pos(maxX, y, minZ).endVertex();
BUFFER.pos(maxX, y, maxZ).endVertex();
BUFFER.pos(minX, y, maxZ).endVertex();
TESSELLATOR.draw();
}
}
}