mirror of https://github.com/cabaletta/baritone
319 lines
13 KiB
Java
319 lines
13 KiB
Java
/*
|
|
* 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/>.
|
|
*/
|
|
|
|
package baritone.utils;
|
|
|
|
import baritone.api.BaritoneAPI;
|
|
import baritone.api.event.events.RenderEvent;
|
|
import baritone.api.pathing.calc.IPath;
|
|
import baritone.api.pathing.goals.*;
|
|
import baritone.api.utils.BetterBlockPos;
|
|
import baritone.api.utils.Helper;
|
|
import baritone.api.utils.interfaces.IGoalRenderPos;
|
|
import baritone.behavior.PathingBehavior;
|
|
import baritone.pathing.path.PathExecutor;
|
|
import net.minecraft.block.state.IBlockState;
|
|
import net.minecraft.client.renderer.GlStateManager;
|
|
import net.minecraft.client.renderer.tileentity.TileEntityBeaconRenderer;
|
|
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
|
|
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;
|
|
|
|
import java.awt.*;
|
|
import java.util.Collection;
|
|
import java.util.Collections;
|
|
import java.util.List;
|
|
|
|
import static org.lwjgl.opengl.GL11.*;
|
|
|
|
/**
|
|
* @author Brady
|
|
* @since 8/9/2018
|
|
*/
|
|
public final class PathRenderer implements IRenderer {
|
|
|
|
private PathRenderer() {}
|
|
|
|
public static void render(RenderEvent event, PathingBehavior behavior) {
|
|
float partialTicks = event.getPartialTicks();
|
|
Goal goal = behavior.getGoal();
|
|
if (behavior.baritone.getPlayerContext().world() == null) {
|
|
return;
|
|
}
|
|
|
|
if (Helper.mc.currentScreen instanceof GuiClick && behavior.baritone == BaritoneAPI.getProvider().getPrimaryBaritone()) {
|
|
((GuiClick) Helper.mc.currentScreen).onRender();
|
|
}
|
|
|
|
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) {
|
|
drawDankLitGoalBox(renderView, goal, partialTicks, settings.colorGoalBox.value);
|
|
}
|
|
|
|
if (!settings.renderPath.value) {
|
|
return;
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
//drawManySelectionBoxes(player, Collections.singletonList(behavior.pathStart()), partialTicks, Color.WHITE);
|
|
|
|
// Render the current path, if there is one
|
|
if (current != null && current.getPath() != null) {
|
|
int renderBegin = Math.max(current.getPosition() - 3, 0);
|
|
drawPath(current.getPath(), renderBegin, settings.colorCurrentPath.value, settings.fadePath.value, 10, 20);
|
|
}
|
|
|
|
if (next != null && next.getPath() != null) {
|
|
drawPath(next.getPath(), 0, settings.colorNextPath.value, settings.fadePath.value, 10, 20);
|
|
}
|
|
|
|
// If there is a path calculation currently running, render the path calculation process
|
|
behavior.getInProgress().ifPresent(currentlyRunning -> {
|
|
currentlyRunning.bestPathSoFar().ifPresent(p -> {
|
|
drawPath(p, 0, settings.colorBestPathSoFar.value, settings.fadePath.value, 10, 20);
|
|
});
|
|
|
|
currentlyRunning.pathToMostRecentNodeConsidered().ifPresent(mr -> {
|
|
drawPath(mr, 0, settings.colorMostRecentConsidered.value, settings.fadePath.value, 10, 20);
|
|
drawManySelectionBoxes(renderView, Collections.singletonList(mr.getDest()), settings.colorMostRecentConsidered.value);
|
|
});
|
|
});
|
|
}
|
|
|
|
public static void drawPath(IPath path, int startIndex, Color color, boolean fadeOut, int fadeStart0, int fadeEnd0) {
|
|
IRenderer.startLines(color, settings.pathRenderLineWidthPixels.value, settings.renderPathIgnoreDepth.value);
|
|
|
|
int fadeStart = fadeStart0 + startIndex;
|
|
int fadeEnd = fadeEnd0 + startIndex;
|
|
|
|
List<BetterBlockPos> positions = path.positions();
|
|
for (int i = startIndex, next; i < positions.size() - 1; i = next) {
|
|
BetterBlockPos start = positions.get(i);
|
|
BetterBlockPos end = positions.get(next = i + 1);
|
|
|
|
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)) {
|
|
end = positions.get(++next);
|
|
}
|
|
|
|
if (fadeOut) {
|
|
float alpha;
|
|
|
|
if (i <= fadeStart) {
|
|
alpha = 0.4F;
|
|
} else {
|
|
if (i > fadeEnd) {
|
|
break;
|
|
}
|
|
alpha = 0.4F * (1.0F - (float) (i - fadeStart) / (float) (fadeEnd - fadeStart));
|
|
}
|
|
|
|
IRenderer.glColor(color, alpha);
|
|
}
|
|
|
|
drawLine(start.x, start.y, start.z, end.x, end.y, end.z);
|
|
|
|
tessellator.draw();
|
|
}
|
|
|
|
IRenderer.endLines(settings.renderPathIgnoreDepth.value);
|
|
}
|
|
|
|
public static void drawLine(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;
|
|
|
|
buffer.begin(renderPathAsFrickinThingy ? GL_LINE_STRIP : GL_LINES, DefaultVertexFormats.POSITION);
|
|
buffer.pos(x1 + 0.5D - vpX, y1 + 0.5D - vpY, z1 + 0.5D - vpZ).endVertex();
|
|
buffer.pos(x2 + 0.5D - vpX, y2 + 0.5D - vpY, z2 + 0.5D - vpZ).endVertex();
|
|
|
|
if (renderPathAsFrickinThingy) {
|
|
buffer.pos(x2 + 0.5D - vpX, y2 + 0.53D - vpY, z2 + 0.5D - vpZ).endVertex();
|
|
buffer.pos(x1 + 0.5D - vpX, y1 + 0.53D - vpY, z1 + 0.5D - vpZ).endVertex();
|
|
buffer.pos(x1 + 0.5D - vpX, y1 + 0.5D - vpY, z1 + 0.5D - vpZ).endVertex();
|
|
}
|
|
}
|
|
|
|
public static void drawManySelectionBoxes(Entity player, Collection<BlockPos> positions, Color color) {
|
|
IRenderer.startLines(color, settings.pathRenderLineWidthPixels.value, settings.renderSelectionBoxesIgnoreDepth.value);
|
|
|
|
//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?
|
|
|
|
positions.forEach(pos -> {
|
|
IBlockState state = bsi.get0(pos);
|
|
AxisAlignedBB toDraw;
|
|
|
|
if (state.getBlock().equals(Blocks.AIR)) {
|
|
toDraw = Blocks.DIRT.getDefaultState().getSelectedBoundingBox(player.world, pos);
|
|
} else {
|
|
toDraw = state.getSelectedBoundingBox(player.world, pos);
|
|
}
|
|
|
|
IRenderer.drawAABB(toDraw, .002D);
|
|
});
|
|
|
|
IRenderer.endLines(settings.renderSelectionBoxesIgnoreDepth.value);
|
|
}
|
|
|
|
public static void drawDankLitGoalBox(Entity player, Goal goal, float partialTicks, Color color) {
|
|
double renderPosX = renderManager.viewerPosX;
|
|
double renderPosY = renderManager.viewerPosY;
|
|
double renderPosZ = renderManager.viewerPosZ;
|
|
double minX, maxX;
|
|
double minZ, maxZ;
|
|
double minY, maxY;
|
|
double y1, y2;
|
|
double y = MathHelper.cos((float) (((float) ((System.nanoTime() / 100000L) % 20000L)) / 20000F * Math.PI * 2));
|
|
if (goal instanceof IGoalRenderPos) {
|
|
BlockPos goalPos = ((IGoalRenderPos) goal).getGoalPos();
|
|
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) {
|
|
y /= 2;
|
|
}
|
|
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) {
|
|
y1 -= 0.5;
|
|
y2 -= 0.5;
|
|
maxY--;
|
|
}
|
|
} else if (goal instanceof GoalXZ) {
|
|
GoalXZ goalPos = (GoalXZ) goal;
|
|
|
|
if (settings.renderGoalXZBeacon.value) {
|
|
glPushAttrib(GL_LIGHTING_BIT);
|
|
|
|
Helper.mc.getTextureManager().bindTexture(TileEntityBeaconRenderer.TEXTURE_BEACON_BEAM);
|
|
|
|
if (settings.renderGoalIgnoreDepth.value) {
|
|
GlStateManager.disableDepth();
|
|
}
|
|
|
|
TileEntityBeaconRenderer.renderBeamSegment(
|
|
goalPos.getX() - renderPosX,
|
|
-renderPosY,
|
|
goalPos.getZ() - renderPosZ,
|
|
partialTicks,
|
|
1.0,
|
|
player.world.getTotalWorldTime(),
|
|
0,
|
|
256,
|
|
color.getColorComponents(null)
|
|
);
|
|
|
|
if (settings.renderGoalIgnoreDepth.value) {
|
|
GlStateManager.enableDepth();
|
|
}
|
|
|
|
glPopAttrib();
|
|
return;
|
|
}
|
|
|
|
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;
|
|
|
|
y1 = 0;
|
|
y2 = 0;
|
|
minY = 0 - renderPosY;
|
|
maxY = 256 - renderPosY;
|
|
} else if (goal instanceof GoalComposite) {
|
|
for (Goal g : ((GoalComposite) goal).goals()) {
|
|
drawDankLitGoalBox(player, g, partialTicks, color);
|
|
}
|
|
return;
|
|
} else if (goal instanceof GoalInverted) {
|
|
drawDankLitGoalBox(player, ((GoalInverted) goal).origin, partialTicks, settings.colorInvertedGoalBox.value);
|
|
return;
|
|
} 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;
|
|
minY = ((GoalYLevel) goal).level - renderPosY;
|
|
maxY = minY + 2;
|
|
y1 = 1 + y + goalpos.level - renderPosY;
|
|
y2 = 1 - y + goalpos.level - renderPosY;
|
|
} else {
|
|
return;
|
|
}
|
|
|
|
IRenderer.startLines(color, settings.goalRenderLineWidthPixels.value, settings.renderGoalIgnoreDepth.value);
|
|
|
|
renderHorizontalQuad(minX, maxX, minZ, maxZ, y1);
|
|
renderHorizontalQuad(minX, maxX, minZ, maxZ, y2);
|
|
|
|
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();
|
|
|
|
IRenderer.endLines(settings.renderGoalIgnoreDepth.value);
|
|
}
|
|
|
|
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();
|
|
}
|
|
}
|
|
}
|