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

369 lines
17 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;
2023-06-12 05:22:01 +00:00
import baritone.Baritone;
import baritone.api.BaritoneAPI;
2018-10-08 22:11:07 +00:00
import baritone.api.event.events.RenderEvent;
2019-09-07 00:31:41 +00:00
import baritone.api.pathing.goals.*;
2018-10-09 01:37:52 +00:00
import baritone.api.utils.BetterBlockPos;
2019-04-18 01:10:47 +00:00
import baritone.api.utils.Helper;
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.path.PathExecutor;
2023-06-12 05:22:01 +00:00
import com.mojang.realmsclient.util.Pair;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.renderer.GlStateManager;
2018-12-03 22:42:05 +00:00
import net.minecraft.client.renderer.tileentity.TileEntityBeaconRenderer;
import net.minecraft.entity.Entity;
import net.minecraft.init.Blocks;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
2023-06-12 05:22:01 +00:00
import net.minecraft.util.math.Vec3d;
2019-09-19 19:53:15 +00:00
import java.awt.*;
2023-06-12 18:16:37 +00:00
import java.util.Arrays;
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;
2019-09-07 00:22:55 +00:00
import static org.lwjgl.opengl.GL11.*;
/**
* @author Brady
* @since 8/9/2018
*/
public final class PathRenderer implements IRenderer {
2019-09-19 20:40:46 +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) {
float partialTicks = event.getPartialTicks();
Goal goal = behavior.getGoal();
if (Helper.mc.currentScreen instanceof GuiClick) {
((GuiClick) Helper.mc.currentScreen).onRender();
2019-02-27 02:34:11 +00:00
}
int thisPlayerDimension = behavior.baritone.getPlayerContext().world().provider.getDimensionType().getId();
int currentRenderViewDimension = BaritoneAPI.getProvider().getPrimaryBaritone().getPlayerContext().world().provider.getDimensionType().getId();
if (thisPlayerDimension != currentRenderViewDimension) {
// this is a path for a bot in a different dimension, don't render it
return;
}
Entity renderView = Helper.mc.getRenderViewEntity();
if (renderView.world != BaritoneAPI.getProvider().getPrimaryBaritone().getPlayerContext().world()) {
System.out.println("I have no idea what's going on");
System.out.println("The primary baritone is in a different world than the render view entity");
System.out.println("Not rendering the path");
return;
}
if (goal != null && settings.renderGoal.value) {
2023-06-12 18:16:37 +00:00
drawGoal(renderView, goal, partialTicks, settings.colorGoalBox.value);
2018-10-08 22:11:07 +00:00
}
if (!settings.renderPath.value) {
return;
}
2019-04-09 04:32:47 +00:00
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
if (current != null && settings.renderSelectionBoxes.value) {
drawManySelectionBoxes(renderView, current.toBreak(), settings.colorBlocksToBreak.value);
drawManySelectionBoxes(renderView, current.toPlace(), settings.colorBlocksToPlace.value);
drawManySelectionBoxes(renderView, current.toWalkInto(), settings.colorBlocksToWalkInto.value);
2019-04-09 04:32:47 +00:00
}
2018-10-08 22:11:07 +00:00
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
// Render the current path, if there is one
if (current != null && current.getPath() != null) {
int renderBegin = Math.max(current.getPosition() - 3, 0);
2023-06-11 07:33:35 +00:00
drawPath(current.getPath().positions(), renderBegin, settings.colorCurrentPath.value, settings.fadePath.value, 10, 20);
2018-10-08 22:11:07 +00:00
}
2018-10-08 22:11:07 +00:00
if (next != null && next.getPath() != null) {
2023-06-11 07:33:35 +00:00
drawPath(next.getPath().positions(), 0, settings.colorNextPath.value, settings.fadePath.value, 10, 20);
}
2023-06-15 07:32:26 +00:00
drawPath(behavior.baritone.elytra.path.subList(Math.max(behavior.baritone.elytra.playerNear - 30, 0), Math.min(behavior.baritone.elytra.playerNear + 30, behavior.baritone.elytra.path.size())), 0, Color.RED, false, 0, 0);
2023-06-11 07:33:35 +00:00
if (behavior.baritone.elytra.goal != null) {
2023-06-14 21:08:34 +00:00
drawGoal(renderView, new GoalBlock(behavior.baritone.elytra.goal), partialTicks, Color.GREEN);
2018-10-08 22:11:07 +00:00
}
2023-06-12 05:22:01 +00:00
if (!behavior.baritone.elytra.lines.isEmpty() && Baritone.settings().renderRaytraces.value) {
IRenderer.startLines(Color.BLUE, settings.pathRenderLineWidthPixels.value, settings.renderPathIgnoreDepth.value);
boolean orig = settings.renderPathAsLine.value;
settings.renderPathAsLine.value = true;
for (Pair<Vec3d, Vec3d> line : behavior.baritone.elytra.lines) {
2023-06-14 21:08:34 +00:00
emitLine(line.first().x, line.first().y, line.first().z, line.second().x, line.second().y, line.second().z);
2023-06-12 05:22:01 +00:00
tessellator.draw();
}
settings.renderPathAsLine.value = orig;
IRenderer.endLines(settings.renderPathIgnoreDepth.value);
}
2018-10-08 22:11:07 +00:00
// If there is a path calculation currently running, render the path calculation process
2018-11-14 22:19:24 +00:00
behavior.getInProgress().ifPresent(currentlyRunning -> {
2018-10-08 22:11:07 +00:00
currentlyRunning.bestPathSoFar().ifPresent(p -> {
2023-06-11 07:33:35 +00:00
drawPath(p.positions(), 0, settings.colorBestPathSoFar.value, settings.fadePath.value, 10, 20);
2018-10-08 22:11:07 +00:00
});
currentlyRunning.pathToMostRecentNodeConsidered().ifPresent(mr -> {
2023-06-11 07:33:35 +00:00
drawPath(mr.positions(), 0, settings.colorMostRecentConsidered.value, settings.fadePath.value, 10, 20);
drawManySelectionBoxes(renderView, Collections.singletonList(mr.getDest()), settings.colorMostRecentConsidered.value);
2018-10-08 22:11:07 +00:00
});
});
}
2023-06-11 07:33:35 +00:00
public static void drawPath(List<BetterBlockPos> positions, int startIndex, Color color, boolean fadeOut, int fadeStart0, int fadeEnd0) {
IRenderer.startLines(color, settings.pathRenderLineWidthPixels.value, settings.renderPathIgnoreDepth.value);
2018-09-17 00:51:39 +00:00
int fadeStart = fadeStart0 + startIndex;
int fadeEnd = fadeEnd0 + startIndex;
for (int i = startIndex, next; i < positions.size() - 1; i = next) {
BetterBlockPos start = positions.get(i);
BetterBlockPos end = positions.get(next = i + 1);
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;
2023-06-11 07:33:35 +00:00
/*while (next + 1 < positions.size() && (!fadeOut || next + 1 < fadeStart) &&
2019-09-07 00:41:27 +00:00
(dirX == positions.get(next + 1).x - end.x &&
dirY == positions.get(next + 1).y - end.y &&
dirZ == positions.get(next + 1).z - end.z)) {
end = positions.get(++next);
2023-06-11 07:33:35 +00:00
}*/
2018-08-14 04:05:35 +00:00
if (fadeOut) {
2018-08-14 04:05:35 +00:00
float alpha;
2018-08-14 04:05:35 +00:00
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
}
IRenderer.glColor(color, alpha);
2018-08-14 04:05:35 +00:00
}
2023-06-12 18:16:37 +00:00
emitLine(start.x, start.y, start.z, end.x, end.y, end.z);
}
IRenderer.endLines(settings.renderPathIgnoreDepth.value);
}
2023-06-12 18:16:37 +00:00
public static void emitLine(double x1, double y1, double z1, double x2, double y2, double z2) {
double vpX = renderManager.viewerPosX;
double vpY = renderManager.viewerPosY;
double vpZ = renderManager.viewerPosZ;
boolean renderPathAsFrickinThingy = !settings.renderPathAsLine.value;
2019-08-30 18:55:25 +00:00
buffer.pos(x1 + 0.5D - vpX, y1 + 0.5D - vpY, z1 + 0.5D - vpZ).color(color[0], color[1], color[2], color[3]).endVertex();
buffer.pos(x2 + 0.5D - vpX, y2 + 0.5D - vpY, z2 + 0.5D - vpZ).color(color[0], color[1], color[2], color[3]).endVertex();
2019-08-30 18:55:25 +00:00
if (renderPathAsFrickinThingy) {
buffer.pos(x2 + 0.5D - vpX, y2 + 0.5D - vpY, z2 + 0.5D - vpZ).color(color[0], color[1], color[2], color[3]).endVertex();
buffer.pos(x2 + 0.5D - vpX, y2 + 0.53D - vpY, z2 + 0.5D - vpZ).color(color[0], color[1], color[2], color[3]).endVertex();
2023-06-12 18:16:37 +00:00
buffer.pos(x2 + 0.5D - vpX, y2 + 0.53D - vpY, z2 + 0.5D - vpZ).color(color[0], color[1], color[2], color[3]).endVertex();
buffer.pos(x1 + 0.5D - vpX, y1 + 0.53D - vpY, z1 + 0.5D - vpZ).color(color[0], color[1], color[2], color[3]).endVertex();
2023-06-12 18:16:37 +00:00
buffer.pos(x1 + 0.5D - vpX, y1 + 0.53D - vpY, z1 + 0.5D - vpZ).color(color[0], color[1], color[2], color[3]).endVertex();
buffer.pos(x1 + 0.5D - vpX, y1 + 0.5D - vpY, z1 + 0.5D - vpZ).color(color[0], color[1], color[2], color[3]).endVertex();
2019-08-30 18:55:25 +00:00
}
}
2019-02-27 20:00:39 +00:00
public static void drawManySelectionBoxes(Entity player, Collection<BlockPos> positions, Color color) {
IRenderer.startLines(color, settings.pathRenderLineWidthPixels.value, settings.renderSelectionBoxesIgnoreDepth.value);
2019-02-28 23:26:09 +00:00
2018-08-09 23:44:41 +00:00
//BlockPos blockpos = movingObjectPositionIn.getBlockPos();
BlockStateInterface bsi = new BlockStateInterface(BaritoneAPI.getProvider().getPrimaryBaritone().getPlayerContext()); // TODO this assumes same dimension between primary baritone and render view? is this safe?
2018-08-10 01:25:43 +00:00
positions.forEach(pos -> {
IBlockState state = bsi.get0(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)) {
2018-11-14 21:46:16 +00:00
toDraw = Blocks.DIRT.getDefaultState().getSelectedBoundingBox(player.world, pos);
2018-08-09 23:44:41 +00:00
} else {
2018-11-14 21:46:16 +00:00
toDraw = state.getSelectedBoundingBox(player.world, pos);
2018-08-09 23:44:41 +00:00
}
2018-10-10 02:34:53 +00:00
2023-06-12 18:16:37 +00:00
IRenderer.emitAABB(toDraw, .002D);
});
2018-08-16 00:53:42 +00:00
IRenderer.endLines(settings.renderSelectionBoxesIgnoreDepth.value);
2019-02-28 23:26:09 +00:00
}
2023-06-12 18:16:37 +00:00
public static void drawGoal(Entity player, Goal goal, float partialTicks, Color color) {
drawGoal(player, goal, partialTicks, color, true);
}
public static void drawGoal(Entity player, Goal goal, float partialTicks, Color color, boolean setupRender) {
double renderPosX = renderManager.viewerPosX;
double renderPosY = renderManager.viewerPosY;
double renderPosZ = renderManager.viewerPosZ;
double minX, maxX;
double minZ, maxZ;
double minY, maxY;
2021-05-25 17:34:17 +00:00
double y, y1, y2;
2021-05-25 19:43:32 +00:00
if (!settings.renderGoalAnimated.value) {
2021-05-25 17:41:36 +00:00
// y = 1 causes rendering issues when the player is at the same y as the top of a block for some reason
y = 0.999F;
2023-01-15 09:02:52 +00:00
} else {
2021-05-25 17:34:17 +00:00
y = MathHelper.cos((float) (((float) ((System.nanoTime() / 100000L) % 20000L)) / 20000F * Math.PI * 2));
}
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;
if (goal instanceof GoalGetToBlock || goal instanceof GoalTwoBlocks) {
2018-09-08 03:43:12 +00:00
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;
if (goal instanceof GoalGetToBlock || goal instanceof GoalTwoBlocks) {
2018-09-08 03:43:12 +00:00
y1 -= 0.5;
y2 -= 0.5;
maxY--;
}
2023-06-12 18:16:37 +00:00
drawDankLitGoalBox(color, minX, maxX, minZ, maxZ, minY, maxY, y1, y2, setupRender);
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
if (settings.renderGoalXZBeacon.value) {
glPushAttrib(GL_LIGHTING_BIT);
Helper.mc.getTextureManager().bindTexture(TileEntityBeaconRenderer.TEXTURE_BEACON_BEAM);
2018-12-03 22:42:05 +00:00
if (settings.renderGoalIgnoreDepth.value) {
2018-12-03 22:42:05 +00:00
GlStateManager.disableDepth();
}
TileEntityBeaconRenderer.renderBeamSegment(
2019-09-07 00:41:27 +00:00
goalPos.getX() - renderPosX,
-renderPosY,
goalPos.getZ() - renderPosZ,
settings.renderGoalAnimated.value ? partialTicks : 0,
2019-09-07 00:41:27 +00:00
1.0,
settings.renderGoalAnimated.value ? player.world.getTotalWorldTime() : 0,
2019-09-07 00:41:27 +00:00
0,
256,
color.getColorComponents(null)
2018-12-03 22:42:05 +00:00
);
if (settings.renderGoalIgnoreDepth.value) {
2018-12-03 22:42:05 +00:00
GlStateManager.enableDepth();
}
glPopAttrib();
2018-12-03 22:42:05 +00:00
return;
}
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;
2023-06-12 18:16:37 +00:00
drawDankLitGoalBox(color, minX, maxX, minZ, maxZ, minY, maxY, y1, y2, setupRender);
2018-09-08 21:16:54 +00:00
} else if (goal instanceof GoalComposite) {
2023-06-12 18:16:37 +00:00
// Simple way to determine if goals can be batched, without having some sort of GoalRenderer
boolean batch = Arrays.stream(((GoalComposite) goal).goals()).allMatch(IGoalRenderPos.class::isInstance);
if (batch) {
IRenderer.startLines(color, settings.goalRenderLineWidthPixels.value, settings.renderGoalIgnoreDepth.value);
}
2018-09-08 01:23:32 +00:00
for (Goal g : ((GoalComposite) goal).goals()) {
2023-06-12 18:16:37 +00:00
drawGoal(player, g, partialTicks, color, !batch);
}
if (batch) {
IRenderer.endLines(settings.renderGoalIgnoreDepth.value);
2018-09-08 01:23:32 +00:00
}
2019-08-30 18:55:25 +00:00
} else if (goal instanceof GoalInverted) {
2023-06-12 18:16:37 +00:00
drawGoal(player, ((GoalInverted) goal).origin, partialTicks, settings.colorInvertedGoalBox.value);
2019-05-03 05:48:37 +00:00
} else if (goal instanceof GoalYLevel) {
GoalYLevel goalpos = (GoalYLevel) goal;
minX = player.posX - settings.yLevelBoxSize.value - renderPosX;
minZ = player.posZ - settings.yLevelBoxSize.value - renderPosZ;
maxX = player.posX + settings.yLevelBoxSize.value - renderPosX;
maxZ = player.posZ + settings.yLevelBoxSize.value - renderPosZ;
2019-05-03 05:48:37 +00:00
minY = ((GoalYLevel) goal).level - renderPosY;
maxY = minY + 2;
y1 = 1 + y + goalpos.level - renderPosY;
y2 = 1 - y + goalpos.level - renderPosY;
2023-06-12 18:16:37 +00:00
drawDankLitGoalBox(color, minX, maxX, minZ, maxZ, minY, maxY, y1, y2, setupRender);
2018-08-16 22:34:23 +00:00
}
2023-06-12 18:16:37 +00:00
}
2018-08-16 00:53:42 +00:00
private static void drawDankLitGoalBox(Color colorIn, double minX, double maxX, double minZ, double maxZ, double minY, double maxY, double y1, double y2, boolean setupRender) {
2023-06-12 18:16:37 +00:00
if (setupRender) {
IRenderer.startLines(colorIn, settings.goalRenderLineWidthPixels.value, settings.renderGoalIgnoreDepth.value);
2023-06-12 18:16:37 +00:00
}
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.pos(minX, minY, minZ).color(color[0], color[1], color[2], color[3]).endVertex();
buffer.pos(minX, maxY, minZ).color(color[0], color[1], color[2], color[3]).endVertex();
buffer.pos(maxX, minY, minZ).color(color[0], color[1], color[2], color[3]).endVertex();
buffer.pos(maxX, maxY, minZ).color(color[0], color[1], color[2], color[3]).endVertex();
buffer.pos(maxX, minY, maxZ).color(color[0], color[1], color[2], color[3]).endVertex();
buffer.pos(maxX, maxY, maxZ).color(color[0], color[1], color[2], color[3]).endVertex();
buffer.pos(minX, minY, maxZ).color(color[0], color[1], color[2], color[3]).endVertex();
buffer.pos(minX, maxY, maxZ).color(color[0], color[1], color[2], color[3]).endVertex();
2023-06-12 18:16:37 +00:00
if (setupRender) {
IRenderer.endLines(settings.renderGoalIgnoreDepth.value);
}
}
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.pos(minX, y, minZ).color(color[0], color[1], color[2], color[3]).endVertex();
buffer.pos(maxX, y, minZ).color(color[0], color[1], color[2], color[3]).endVertex();
2023-06-12 18:16:37 +00:00
buffer.pos(maxX, y, minZ).color(color[0], color[1], color[2], color[3]).endVertex();
buffer.pos(maxX, y, maxZ).color(color[0], color[1], color[2], color[3]).endVertex();
2023-06-12 18:16:37 +00:00
buffer.pos(maxX, y, maxZ).color(color[0], color[1], color[2], color[3]).endVertex();
buffer.pos(minX, y, maxZ).color(color[0], color[1], color[2], color[3]).endVertex();
2023-06-12 18:16:37 +00:00
buffer.pos(minX, y, maxZ).color(color[0], color[1], color[2], color[3]).endVertex();
buffer.pos(minX, y, minZ).color(color[0], color[1], color[2], color[3]).endVertex();
2018-10-08 22:06:41 +00:00
}
}
}