Files
OpenPrestige/src/main/java/dev/zprestige/prestige/module/visual/TwoDESP.java
T

570 lines
29 KiB
Java

package dev.zprestige.prestige.module.visual;
import dev.zprestige.prestige.BoolSetting;
import dev.zprestige.prestige.ColorSetting;
import dev.zprestige.prestige.EnumSetting;
import dev.zprestige.prestige.FloatSetting;
import dev.zprestige.prestige.IntSetting;
import dev.zprestige.prestige.Module;
import dev.zprestige.prestige.MultiSetting;
import dev.zprestige.prestige.Subscribe;
import dev.zprestige.prestige.client.Prestige;
import dev.zprestige.prestige.combat.TwoDEspTarget;
import dev.zprestige.prestige.data.CameraMatrices;
import dev.zprestige.prestige.event.ClientTickEvent;
import dev.zprestige.prestige.event.FrustumSetupEvent;
import dev.zprestige.prestige.event.Render2DEvent;
import dev.zprestige.prestige.math.TwoDEspBox;
import dev.zprestige.prestige.render.MsdfFont;
import dev.zprestige.prestige.render.Render2D;
import dev.zprestige.prestige.render.BufferSource;
import dev.zprestige.prestige.render.ShapeRenderer;
import dev.zprestige.prestige.render.BlurredRoundedRectShader;
import dev.zprestige.prestige.render.RoundedRectShader;
import java.awt.Color;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.UUID;
import java.util.Map.Entry;
import java.util.function.Predicate;
import net.minecraft.client.gui.screen.ChatScreen;
import net.minecraft.client.render.Frustum;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.math.Vec3d;
import org.joml.Matrix4f;
import org.joml.Vector4f;
public class TwoDESP extends Module {
private BoolSetting showInvisibles;
private EnumSetting style;
private FloatSetting rounding;
private FloatSetting lineWidth;
private MultiSetting features;
private FloatSetting fillAlpha;
private FloatSetting glowStrength;
private BoolSetting animated;
private FloatSetting animationSpeed;
private EnumSetting healthPosition;
private BoolSetting healthText;
private BoolSetting healthShine;
private FloatSetting fadeSpeed;
private IntSetting maxDistance;
private IntSetting limit;
private BoolSetting menuColor;
private ColorSetting boxColor;
private ColorSetting gradientColor;
private ColorSetting friendColor;
private ColorSetting healthHigh;
private ColorSetting healthLow;
private Frustum frustum;
private long lastFrameTime = 0L;
private long frameCounter = 0L;
private Map visibleTargets = new LinkedHashMap();
private Map animatedBoxes = new HashMap();
public TwoDESP() {
dev.zprestige.prestige.ui.bridge.Bootstrap.pre(this);
this.healthText
.visibleWhen(
(Predicate<Boolean>)ignored -> this.features.isSelected("Health Bar")
);
this.healthHigh
.visibleWhen(
(Predicate<Color>)ignored -> this.features.isSelected("Health Bar")
);
this.healthShine
.visibleWhen(
(Predicate<Boolean>)ignored -> this.features.isSelected("Health Bar")
);
this.animationSpeed
.visibleWhen(
(Predicate<Float>)ignored -> this.features.isSelected("Gradient") && this.animated.getValue()
);
this.healthPosition
.visibleWhen(
(Predicate<String>)ignored -> this.features.isSelected("Health Bar")
);
this.fillAlpha
.visibleWhen((Predicate<Float>)ignored -> this.features.isSelected("Fill"));
this.animated
.visibleWhen(
(Predicate<Boolean>)ignored -> this.features.isSelected("Gradient")
);
this.boxColor.visibleWhen((Predicate<Color>)ignored -> !this.menuColor.getValue());
this.gradientColor
.visibleWhen(
(Predicate<Color>)ignored -> this.features.isSelected("Gradient")
);
this.healthLow
.visibleWhen(
(Predicate<Color>)ignored -> this.features.isSelected("Health Bar")
);
this.glowStrength
.visibleWhen((Predicate<Float>)ignored -> this.features.isSelected("Glow"));
}
@Subscribe
public void onClientTick(ClientTickEvent event) {
if (mc.world == null || mc.player == null) {
this.visibleTargets.clear();
this.animatedBoxes.clear();
} else {
this.visibleTargets.clear();
int maxRange = this.maxDistance.getValue();
boolean includeInvisible = this.showInvisibles.getValue();
ArrayList candidates = new ArrayList();
for (PlayerEntity player : mc.world.getPlayers()) {
if (player != mc.player && Prestige.botFilter.isValidTarget(player) && !player.isRemoved()) {
float distance = mc.player.distanceTo(player);
if (!(distance > maxRange) && (includeInvisible || !player.isInvisible())) {
TwoDEspTarget espTarget = new TwoDEspTarget();
espTarget.player = player;
espTarget.name = player.getName().getString();
espTarget.health = player.getHealth() + player.getAbsorptionAmount();
espTarget.maxHealth = Math.max(1.0F, player.getMaxHealth());
espTarget.width = player.getWidth();
espTarget.height = player.getHeight();
espTarget.distance = distance;
espTarget.friend = Prestige.friendManager.isFriend(espTarget.name);
candidates.add(espTarget);
}
}
}
candidates.sort(Comparator.comparingDouble(candidate -> ((dev.zprestige.prestige.combat.TwoDEspTarget)candidate).distance));
for (int index = 0; index < candidates.size() && index < this.limit.getValue(); index++) {
TwoDEspTarget nearest = (TwoDEspTarget)candidates.get(index);
this.visibleTargets.put(nearest.player.getUuid(), nearest);
}
}
}
@Subscribe
public void onFrustumSetup(FrustumSetupEvent event) {
this.frustum = event.getFrustum();
}
@Subscribe
public void onRender2D(Render2DEvent event) {
if (mc.world != null && mc.player != null) {
if (mc.currentScreen == null || mc.currentScreen instanceof ChatScreen) {
this.frameCounter++;
long now = System.currentTimeMillis();
float deltaSeconds = this.lastFrameTime == 0L ? 0.0F : Math.min(0.1F, (float)(now - this.lastFrameTime) / 1000.0F);
this.lastFrameTime = now;
float fadeStep = 1.0F - (float)Math.exp(-deltaSeconds * this.fadeSpeed.getValue());
int screenWidth = mc.getWindow().getScaledWidth();
int screenHeight = mc.getWindow().getScaledHeight();
MsdfFont font = Prestige.fontManager.getDefaultFont();
Matrix4f matrix = new Matrix4f();
Color baseColor = this.menuColor.getValue()
? Prestige.moduleManager.getMenu().getMenuColor().getValue()
: this.boxColor.getValue();
Color secondaryColor = this.gradientColor.getValue();
float gradientPhase = this.features.isSelected("Gradient") && this.animated.getValue()
? (float)((Math.sin(now / 1000.0 * this.animationSpeed.getValue().floatValue()) + 1.0) * 0.5)
: 0.0F;
for (Entry entry : (Iterable<Entry>)(this.visibleTargets.entrySet())) {
UUID uuid = (UUID)entry.getKey();
TwoDEspTarget espTarget = (TwoDEspTarget)entry.getValue();
PlayerEntity player = espTarget.player;
if (player != null && !player.isRemoved() && (this.frustum == null || this.frustum.isVisible(player.getBoundingBox()))) {
Vec3d renderPos = Render2D.getInterpolatedPos(player);
float upperBound = espTarget.width;
float[] screenBounds = this.projectBoundingBox(renderPos, upperBound, espTarget.height);
if (screenBounds != null) {
float rawCoord = screenBounds[0];
upperBound = screenWidth + 20;
float minX = clamp(rawCoord, -20.0F, upperBound);
rawCoord = screenBounds[1];
upperBound = screenHeight + 20;
float minY = clamp(rawCoord, -20.0F, upperBound);
rawCoord = screenBounds[2];
upperBound = screenWidth + 20;
float maxX = clamp(rawCoord, -20.0F, upperBound);
rawCoord = screenBounds[3];
upperBound = screenHeight + 20;
float maxY = clamp(rawCoord, -20.0F, upperBound);
if (!(maxX - minX < 3.0F) && !(maxY - minY < 3.0F)) {
TwoDEspBox box = (TwoDEspBox)this.animatedBoxes.get(uuid);
if (box == null) {
box = new TwoDEspBox();
box.alpha = 0.0F;
this.animatedBoxes.put(uuid, box);
}
box.minX = minX;
box.minY = minY;
box.maxX = maxX;
box.maxY = maxY;
box.alpha = lerp(box.alpha, 1.0F, fadeStep);
box.lastFrame = this.frameCounter;
box.target = espTarget;
this.renderTarget(event.renderer, event.context, matrix, font, espTarget, box, baseColor, secondaryColor, gradientPhase, now);
}
}
}
}
Iterator boxIterator = this.animatedBoxes.entrySet().iterator();
while (boxIterator.hasNext()) {
TwoDEspBox fadingBox = (TwoDEspBox)((Entry)boxIterator.next()).getValue();
if (fadingBox.lastFrame != this.frameCounter) {
fadingBox.alpha = lerp(fadingBox.alpha, 0.0F, fadeStep);
if (!(fadingBox.alpha < 0.02F) && fadingBox.target != null) {
this.renderTarget(event.renderer, event.context, matrix, font, fadingBox.target, fadingBox, baseColor, secondaryColor, gradientPhase, now);
} else {
boxIterator.remove();
}
}
}
}
}
}
@Override
public void onDisable() {
this.animatedBoxes.clear();
this.visibleTargets.clear();
this.lastFrameTime = 0L;
}
private void renderTarget(BufferSource buffers, CameraMatrices context, Matrix4f matrix, MsdfFont font, TwoDEspTarget espTarget, TwoDEspBox box, Color baseColor, Color secondaryColor, float gradientPhase, long now) {
float alpha = clamp01(box.alpha);
if (!(alpha < 0.02F)) {
float minX = box.minX;
float minY = box.minY;
float maxX = box.maxX;
float maxY = box.maxY;
float boxWidth = maxX - minX;
float boxHeight = maxY - minY;
Color primaryColor = espTarget.friend ? this.friendColor.getValue() : baseColor;
boolean useGradient = this.features.isSelected("Gradient");
Color topColor = primaryColor;
Color bottomColor = useGradient && !espTarget.friend ? secondaryColor : primaryColor;
if (useGradient && this.animated.getValue() && !espTarget.friend) {
Color animatedTop = lerpColor(primaryColor, secondaryColor, gradientPhase);
Color animatedBottom = lerpColor(secondaryColor, primaryColor, gradientPhase);
topColor = animatedTop;
bottomColor = animatedBottom;
}
Color fadedTop = scaleAlpha(topColor, alpha);
Color fadedBottom = scaleAlpha(bottomColor, alpha);
float strokeWidth = this.lineWidth.getValue();
float radius = Math.min(this.rounding.getValue(), Math.min(boxWidth, boxHeight) * 0.4F);
if (radius < 0.0F) {
radius = 0.0F;
}
if (this.features.isSelected("Glow")) {
this.drawGlow(matrix, minX, minY, maxX, maxY, primaryColor, alpha, radius);
}
if (this.features.isSelected("Fill")) {
Render2D.drawRoundedRect(matrix, minX, minY, maxX, maxY, scaleAlpha(primaryColor, alpha * this.fillAlpha.getValue()), radius);
}
switch (this.style.getValue()) {
case "Box":
this.drawBox(matrix, minX, minY, maxX, maxY, fadedTop, fadedBottom, strokeWidth, radius);
break;
case "Corners":
this.drawCorners(matrix, minX, minY, maxX, maxY, fadedTop, fadedBottom, strokeWidth);
break;
case "Brackets":
this.drawBrackets(matrix, minX, minY, maxX, maxY, fadedTop, fadedBottom, strokeWidth);
}
if (this.features.isSelected("Health Bar")) {
this.drawHealthBar(matrix, font, minX, minY, maxX, maxY, espTarget.health, espTarget.maxHealth, alpha, now);
}
if (this.features.isSelected("Name Tag")) {
this.drawNameTag(buffers, context, matrix, font, minX, minY, maxX, espTarget.name, alpha);
}
if (this.features.isSelected("Distance")) {
this.drawDistanceTag(buffers, context, matrix, font, minX, maxY, maxX, espTarget.distance, alpha);
}
}
}
private void drawBox(Matrix4f matrix, float minX, float minY, float maxX, float maxY, Color topColor, Color bottomColor, float strokeWidth, float radius) {
Color outlineColor = averageColor(topColor, bottomColor);
drawRoundedOutline(matrix, minX - 0.5F, minY - 0.5F, maxX + 0.5F, maxY + 0.5F, new Color(0, 0, 0, Math.round(80.0F * (outlineColor.getAlpha() / 255.0F))), radius + 0.5F, 1.0F);
drawRoundedOutline(matrix, minX, minY, maxX, maxY, outlineColor, radius, strokeWidth);
}
private void drawCorners(Matrix4f matrix, float minX, float minY, float maxX, float maxY, Color topColor, Color bottomColor, float strokeWidth) {
float cornerLength = clamp(Math.min(maxX - minX, maxY - minY) * 0.28F, 4.0F, 22.0F);
float halfWidth = strokeWidth * 0.5F;
Color shadowColor = new Color(0, 0, 0, Math.round(120.0F * (topColor.getAlpha() / 255.0F)));
this.drawShadowedRect(matrix, minX - halfWidth, minY - halfWidth, minX + cornerLength, minY + halfWidth, topColor, shadowColor);
this.drawShadowedRect(matrix, minX - halfWidth, minY - halfWidth, minX + halfWidth, minY + cornerLength, topColor, shadowColor);
this.drawShadowedRect(matrix, maxX - cornerLength, minY - halfWidth, maxX + halfWidth, minY + halfWidth, topColor, shadowColor);
this.drawShadowedRect(matrix, maxX - halfWidth, minY - halfWidth, maxX + halfWidth, minY + cornerLength, topColor, shadowColor);
this.drawShadowedRect(matrix, minX - halfWidth, maxY - halfWidth, minX + cornerLength, maxY + halfWidth, bottomColor, shadowColor);
this.drawShadowedRect(matrix, minX - halfWidth, maxY - cornerLength, minX + halfWidth, maxY + halfWidth, bottomColor, shadowColor);
this.drawShadowedRect(matrix, maxX - cornerLength, maxY - halfWidth, maxX + halfWidth, maxY + halfWidth, bottomColor, shadowColor);
this.drawShadowedRect(matrix, maxX - halfWidth, maxY - cornerLength, maxX + halfWidth, maxY + halfWidth, bottomColor, shadowColor);
}
private void drawBrackets(Matrix4f matrix, float minX, float minY, float maxX, float maxY, Color topColor, Color bottomColor, float strokeWidth) {
float bracketLength = clamp((maxY - minY) * 0.35F, 5.0F, 26.0F);
float halfWidth = strokeWidth * 0.5F;
float centerY = (minY + maxY) * 0.5F;
Color shadowColor = new Color(0, 0, 0, Math.round(120.0F * (topColor.getAlpha() / 255.0F)));
this.drawShadowedRect(matrix, minX - halfWidth, minY - halfWidth, minX + halfWidth, minY + bracketLength, topColor, shadowColor);
this.drawShadowedRect(matrix, minX - halfWidth, centerY - bracketLength * 0.4F, minX + halfWidth, centerY + bracketLength * 0.4F, averageColor(topColor, bottomColor), shadowColor);
this.drawShadowedRect(matrix, minX - halfWidth, maxY - bracketLength, minX + halfWidth, maxY + halfWidth, bottomColor, shadowColor);
this.drawShadowedRect(matrix, maxX - halfWidth, minY - halfWidth, maxX + halfWidth, minY + bracketLength, topColor, shadowColor);
this.drawShadowedRect(matrix, maxX - halfWidth, centerY - bracketLength * 0.4F, maxX + halfWidth, centerY + bracketLength * 0.4F, averageColor(topColor, bottomColor), shadowColor);
this.drawShadowedRect(matrix, maxX - halfWidth, maxY - bracketLength, maxX + halfWidth, maxY + halfWidth, bottomColor, shadowColor);
}
private void drawShadowedRect(Matrix4f matrix, float x1, float y1, float x2, float y2, Color color, Color shadowColor) {
Render2D.drawRect(matrix, x1 - 0.5F, y1 - 0.5F, x2 + 0.5F, y2 + 0.5F, shadowColor);
Render2D.drawRect(matrix, x1, y1, x2, y2, color);
}
private void drawGlow(Matrix4f matrix, float minX, float minY, float maxX, float maxY, Color color, float alpha, float radius) {
float layers = 4.0F;
float strength = this.glowStrength.getValue();
for (int layer = 1; layer <= layers; layer++) {
float progress = layer / layers;
float expand = strength * progress;
float layerAlpha = alpha * 0.14F * (1.0F - progress);
Render2D.drawRoundedRect(matrix, minX - expand, minY - expand, maxX + expand, maxY + expand, new Color(color.getRed(), color.getGreen(), color.getBlue(), toAlphaByte(layerAlpha)), radius + expand);
}
}
private static void drawRoundedOutline(Matrix4f matrix, float x1, float y1, float x2, float y2, Color color, float radius, float thickness) {
ShapeRenderer.drawRoundedRectOutline(Render2D.currentBuffers, Render2D.currentContext, matrix, x1, y1, x2, y2, color, radius, thickness);
}
private void drawHealthBar(Matrix4f matrix, MsdfFont font, float minX, float minY, float maxX, float maxY, float health, float maxHealth, float alpha, long now) {
float healthFraction = clamp01(health / maxHealth);
Color highColor = this.healthHigh.getValue();
Color lowColor = this.healthLow.getValue();
Color fillColor = lerpColor(lowColor, highColor, healthFraction);
Color backgroundColor = new Color(0, 0, 0, toAlphaByte(alpha * 0.63F));
String position = this.healthPosition.getValue();
float barThickness = 2.6F;
float barGap = 3.0F;
float barRadius = 1.6F;
boolean vertical = position.equals("Left") || position.equals("Right");
float barMinX;
float barMinY;
float barMaxX;
float barMaxY;
if (vertical) {
if (position.equals("Left")) {
barMaxX = minX - barGap;
barMinX = barMaxX - barThickness;
} else {
barMinX = maxX + barGap;
barMaxX = barMinX + barThickness;
}
barMinY = minY;
barMaxY = maxY;
} else {
if (position.equals("Top")) {
barMaxY = minY - barGap;
barMinY = barMaxY - barThickness;
} else {
barMinY = maxY + barGap;
barMaxY = barMinY + barThickness;
}
barMinX = minX;
barMaxX = maxX;
}
Render2D.drawRoundedRect(matrix, barMinX - 0.6F, barMinY - 0.6F, barMaxX + 0.6F, barMaxY + 0.6F, backgroundColor, barRadius);
if (vertical) {
float fillHeight = (barMaxY - barMinY) * healthFraction;
float fillTop = barMaxY - fillHeight;
if (fillHeight > 1.0F) {
ShapeRenderer.drawGradientRoundedRect(matrix, barMinX, fillTop, barMaxX, barMaxY, scaleAlpha(lowColor, alpha), scaleAlpha(lowColor, alpha), scaleAlpha(fillColor, alpha), scaleAlpha(fillColor, alpha), new Vector4f(barRadius));
}
if (this.healthShine.getValue() && fillHeight > 4.0F) {
float shinePhase = (float)(now % 1600L / 1600.0);
float shineCenterY = fillTop + (barMaxY - fillTop) * shinePhase;
float shineHeight = Math.min(8.0F, fillHeight * 0.35F);
Render2D.drawRect(matrix, barMinX, shineCenterY - shineHeight * 0.5F, barMaxX, shineCenterY + shineHeight * 0.5F, new Color(255, 255, 255, toAlphaByte(alpha * 0.28F * (1.0F - Math.abs(shinePhase - 0.5F) * 2.0F))));
}
} else {
float fillWidth = (barMaxX - barMinX) * healthFraction;
float fillRight = barMinX + fillWidth;
if (fillWidth > 1.0F) {
ShapeRenderer.drawGradientRoundedRect(matrix, barMinX, barMinY, fillRight, barMaxY, scaleAlpha(lowColor, alpha), scaleAlpha(fillColor, alpha), scaleAlpha(fillColor, alpha), scaleAlpha(lowColor, alpha), new Vector4f(barRadius));
}
if (this.healthShine.getValue() && fillWidth > 4.0F) {
float sweepPhase = (float)(now % 1600L / 1600.0);
float shineCenterX = barMinX + fillWidth * sweepPhase;
float shineWidth = Math.min(8.0F, fillWidth * 0.35F);
Render2D.drawRect(matrix, shineCenterX - shineWidth * 0.5F, barMinY, shineCenterX + shineWidth * 0.5F, barMaxY, new Color(255, 255, 255, toAlphaByte(alpha * 0.28F * (1.0F - Math.abs(sweepPhase - 0.5F) * 2.0F))));
}
}
if (this.healthText.getValue()) {
String hpText = String.valueOf(Math.round(health));
Color textBackground = new Color(0, 0, 0, toAlphaByte(alpha * 0.55F));
float textScale = 0.5F;
float textWidth = font.getTextWidth(hpText) * textScale;
float textHeight = font.getLineHeight() * textScale;
float textY;
float textX;
if (vertical) {
textX = (barMinX + barMaxX) * 0.5F - textWidth * 0.5F;
textY = barMaxY + 2.0F;
} else {
textX = (barMinX + barMaxX) * 0.5F - textWidth * 0.5F;
textY = position.equals("Top") ? barMinY - textHeight - 2.0F : barMaxY + 2.0F;
}
Render2D.drawRoundedRect(matrix, textX - 2.0F, textY - 1.0F, textX + textWidth + 2.0F, textY + textHeight + 1.0F, textBackground, 1.5F);
font.drawTextScaled(matrix, hpText, textX, textY, textScale, scaleAlpha(new Color(240, 240, 245), alpha));
}
}
private void drawNameTag(BufferSource buffers, CameraMatrices context, Matrix4f matrix, MsdfFont font, float minX, float minY, float maxX, String playerName, float alpha) {
float textWidth = font.getTextWidth(playerName);
float lineHeight = font.getLineHeight();
float paddingX = 4.0F;
float paddingY = 1.5F;
float labelWidth = textWidth + paddingX * 2.0F;
float labelLeft = ((minX + maxX) * 0.5F) - labelWidth * 0.5F;
float labelRight = labelLeft + labelWidth;
float labelBottom = minY - 3.0F;
float labelTop = labelBottom - (lineHeight + paddingY * 2.0F);
this.drawLabelBackground(buffers, context, matrix, labelLeft, labelTop, labelRight, labelBottom, alpha);
font.drawText(matrix, playerName, labelLeft + paddingX, labelTop + paddingY, scaleAlpha(new Color(240, 240, 250), alpha));
}
private void drawDistanceTag(BufferSource buffers, CameraMatrices context, Matrix4f matrix, MsdfFont font, float minX, float maxY, float maxX, float distance, float alpha) {
int wholeMeters = (int)distance;
int tenths = (int)(distance * 10.0F) - wholeMeters * 10;
if (tenths < 0) {
tenths = -tenths;
}
String distanceText = wholeMeters + "." + tenths + "m";
float textScale = 0.75F;
float textWidth = font.getTextWidth(distanceText) * textScale;
float textHeight = font.getLineHeight() * textScale;
float paddingX = 3.5F;
float paddingY = 1.5F;
float labelWidth = textWidth + paddingX * 2.0F;
float labelLeft = ((minX + maxX) * 0.5F) - labelWidth * 0.5F;
float labelRight = labelLeft + labelWidth;
float labelTop = maxY + 3.0F;
this.drawLabelBackground(buffers, context, matrix, labelLeft, labelTop, labelRight, labelTop + textHeight + paddingY * 2.0F, alpha);
font.drawTextScaled(matrix, distanceText, labelLeft + paddingX, labelTop + paddingY, textScale, scaleAlpha(new Color(200, 200, 220), alpha));
}
private void drawLabelBackground(BufferSource buffers, CameraMatrices context, Matrix4f matrix, float x1, float y1, float x2, float y2, float alpha) {
float width = x2 - x1;
float height = y2 - y1;
if (this.features.isSelected("Blur Labels")) {
BlurredRoundedRectShader.drawBlurredRect(buffers, context, matrix, x1, y1, width, height, 5, 2.5F);
}
RoundedRectShader.drawRoundedRect(buffers, context, matrix, x1, y1, width, height, new Color(16, 16, 22, toAlphaByte(alpha * 0.72F)), 2.5F);
}
private float[] projectBoundingBox(Vec3d pos, float entityWidth, float entityHeight) {
double halfWidth = entityWidth * 0.5;
double fullHeight = entityHeight;
float minX = Float.POSITIVE_INFINITY;
float minY = Float.POSITIVE_INFINITY;
float maxX = Float.NEGATIVE_INFINITY;
float maxY = Float.NEGATIVE_INFINITY;
for (int corner = 0; corner < 8; corner++) {
Vec3d projected = Render2D.worldToScreen(new Vec3d(pos.x + ((corner & 1) == 0 ? -halfWidth : halfWidth), pos.y + ((corner & 2) == 0 ? 0.0 : fullHeight), pos.z + ((corner & 4) == 0 ? -halfWidth : halfWidth)));
if (projected.z < 0.0 || projected.z >= 1.0) {
return null;
}
float screenX = (float)projected.x;
float screenY = (float)projected.y;
if (screenX < minX) {
minX = screenX;
}
if (screenX > maxX) {
maxX = screenX;
}
if (screenY < minY) {
minY = screenY;
}
if (screenY > maxY) {
maxY = screenY;
}
}
return new float[]{minX, minY, maxX, maxY};
}
private static Color scaleAlpha(Color color, float factor) {
float baseAlpha = color.getAlpha();
int alpha = Math.round(baseAlpha * clamp01(factor));
return new Color(color.getRed(), color.getGreen(), color.getBlue(), clampByte(alpha));
}
private static Color lerpColor(Color startColor, Color endColor, float progress) {
progress = clamp01(progress);
int red = Math.round(startColor.getRed() + (endColor.getRed() - startColor.getRed()) * progress);
int green = Math.round(startColor.getGreen() + (endColor.getGreen() - startColor.getGreen()) * progress);
int blue = Math.round(startColor.getBlue() + (endColor.getBlue() - startColor.getBlue()) * progress);
int alpha = Math.round(startColor.getAlpha() + (endColor.getAlpha() - startColor.getAlpha()) * progress);
return new Color(clampByte(red), clampByte(green), clampByte(blue), clampByte(alpha));
}
private static Color averageColor(Color first, Color second) {
return new Color(
(first.getRed() + second.getRed()) / 2,
(first.getGreen() + second.getGreen()) / 2,
(first.getBlue() + second.getBlue()) / 2,
(first.getAlpha() + second.getAlpha()) / 2
);
}
private static float lerp(float current, float target, float factor) {
return current + (target - current) * clamp01(factor);
}
private static float clamp01(float value) {
return value < 0.0F ? 0.0F : (value > 1.0F ? 1.0F : value);
}
private static float clamp(float value, float min, float max) {
return value < min ? min : (value > max ? max : value);
}
private static int toAlphaByte(float fraction) {
int scaled = Math.round(fraction * 255.0F);
return scaled < 0 ? 0 : (scaled > 255 ? 255 : scaled);
}
private static int clampByte(int value) {
return value < 0 ? 0 : (value > 255 ? 255 : value);
}
}