/*
* Copyright (C) 2022-2023 NotEnoughUpdates contributors
*
* This file is part of NotEnoughUpdates.
*
* NotEnoughUpdates 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.
*
* NotEnoughUpdates 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 NotEnoughUpdates. If not, see .
*/
package io.github.moulberry.notenoughupdates.overlays;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
import io.github.moulberry.notenoughupdates.core.config.Position;
import io.github.moulberry.notenoughupdates.core.util.lerp.LerpUtils;
import io.github.moulberry.notenoughupdates.util.Utils;
import io.github.moulberry.notenoughupdates.util.XPInformation;
import lombok.var;
import net.minecraft.client.Minecraft;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.EnumChatFormatting;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.function.Supplier;
public class MiningSkillOverlay
extends TextOverlay { //Im sure there is a much better way to do this besides making another class ¯\_(ツ)_/¯
private long lastUpdate = -1;
private int compactLast = -1;
private int compact = -1;
private int compactTier = -1;
private String compactTierAmount = "1";
private float minedPerSecondLast = 0;
private float minedPerSecond = 0;
private final LinkedList compactQueue = new LinkedList<>();
private XPInformation.SkillInfo skillInfo = null;
private XPInformation.SkillInfo skillInfoLast = null;
private float lastTotalXp = -1;
private boolean isMining = false;
private final LinkedList xpGainQueue = new LinkedList<>();
private float xpGainHourLast = -1;
private float xpGainHour = -1;
private int xpGainTimer = 0;
private final String skillType = "Mining";
public MiningSkillOverlay(
Position position,
Supplier> dummyStrings,
Supplier styleSupplier
) {
super(position, dummyStrings, styleSupplier);
}
private float interp(float now, float last) {
float interp = now;
if (last >= 0 && last != now) {
float factor = (System.currentTimeMillis() - lastUpdate) / 1000f;
factor = LerpUtils.clampZeroOne(factor);
interp = last + (now - last) * factor;
}
return interp;
}
@Override
public boolean isEnabled() {
return NotEnoughUpdates.INSTANCE.config.skillOverlays.miningSkillOverlay;
}
@Override
public void update() {
if (!isEnabled()) {
compact = -1;
overlayStrings = null;
return;
}
lastUpdate = System.currentTimeMillis();
compactLast = compact;
xpGainHourLast = xpGainHour;
compact = -1;
if (Minecraft.getMinecraft().thePlayer == null) return;
ItemStack stack = Minecraft.getMinecraft().thePlayer.getHeldItem();
if (stack != null && stack.hasTagCompound()) {
NBTTagCompound tag = stack.getTagCompound();
if (tag.hasKey("ExtraAttributes", 10)) {
NBTTagCompound ea = tag.getCompoundTag("ExtraAttributes");
if (ea.hasKey("compact_blocks", 99)) {
compact = ea.getInteger("compact_blocks");
compactQueue.add(0, compact);
}
}
}
if (compact < 100) {
compactTier = 1;
} else if (compact < 500) {
compactTier = 2;
} else if (compact < 1500) {
compactTier = 3;
} else if (compact < 5000) {
compactTier = 4;
} else if (compact < 15000) {
compactTier = 5;
} else if (compact < 50000) {
compactTier = 6;
} else if (compact < 150000) {
compactTier = 7;
} else if (compact < 500000) {
compactTier = 8;
} else if (compact < 1000000) {
compactTier = 9;
} else if (compact > 1000000) {
compactTier = 10;
}
switch (compactTier) {
case 1:
compactTierAmount = "100";
break;
case 2:
compactTierAmount = "500";
break;
case 3:
compactTierAmount = "1,500";
break;
case 4:
compactTierAmount = "5,000";
break;
case 5:
compactTierAmount = "15,000";
break;
case 6:
compactTierAmount = "50,000";
break;
case 7:
compactTierAmount = "150,000";
break;
case 8:
compactTierAmount = "500,000";
break;
case 9:
compactTierAmount = "1,000,000";
break;
case 10:
compactTierAmount = "Maxed";
break;
}
String internalname = NotEnoughUpdates.INSTANCE.manager.getInternalNameForItem(stack);
skillInfoLast = skillInfo;
var s = NotEnoughUpdates.INSTANCE.config.skillOverlays.miningText;
skillInfo = XPInformation.getInstance().getSkillInfo(
skillType,
s.contains(2) ||
s.contains(3) ||
s.contains(4) ||
s.contains(5) ||
s.contains(7)
);
if (skillInfo != null) {
float totalXp = (float) skillInfo.totalXp;
if (lastTotalXp > 0) {
float delta = totalXp - lastTotalXp;
if (delta > 0 && delta < 1000) {
xpGainTimer = NotEnoughUpdates.INSTANCE.config.skillOverlays.miningPauseTimer;
xpGainQueue.add(0, delta);
while (xpGainQueue.size() > 30) {
xpGainQueue.removeLast();
}
float totalGain = 0;
for (float f : xpGainQueue) totalGain += f;
xpGainHour = totalGain * (60 * 60) / xpGainQueue.size();
isMining = true;
} else if (xpGainTimer > 0) {
xpGainTimer--;
xpGainQueue.add(0, 0f);
while (xpGainQueue.size() > 30) {
xpGainQueue.removeLast();
}
float totalGain = 0;
for (float f : xpGainQueue) totalGain += f;
xpGainHour = totalGain * (60 * 60) / xpGainQueue.size();
isMining = true;
} else if (delta <= 0) {
isMining = false;
}
}
lastTotalXp = totalXp;
}
while (compactQueue.size() >= 4) {
compactQueue.removeLast();
}
if (compactQueue.isEmpty()) {
minedPerSecond = -1;
minedPerSecondLast = 0;
} else {
minedPerSecondLast = minedPerSecond;
int last = compactQueue.getLast();
int first = compactQueue.getFirst();
minedPerSecond = (first - last) / 3f;
}
if (compact != -1) {
overlayStrings = new ArrayList<>();
} else {
overlayStrings = null;
}
}
@Override
public void updateFrequent() {
super.updateFrequent();
if (compact < 0) {
overlayStrings = null;
} else {
HashMap lineMap = new HashMap<>();
overlayStrings = new ArrayList<>();
NumberFormat format = NumberFormat.getIntegerInstance();
if (compact >= 0) {
int counterInterp = (int) interp(compact, compactLast);
lineMap.put(
0,
EnumChatFormatting.AQUA + "Compact: " + EnumChatFormatting.YELLOW + format.format(counterInterp)
);
}
if (compact >= 0) {
if (minedPerSecondLast == minedPerSecond && minedPerSecond <= 0) {
lineMap.put(1, EnumChatFormatting.AQUA + "Blocks/m: " + EnumChatFormatting.YELLOW + "N/A");
} else {
float cpsInterp = interp(minedPerSecond, minedPerSecondLast);
lineMap.put(1, EnumChatFormatting.AQUA + "Blocks/m: " + EnumChatFormatting.YELLOW +
String.format("%,.2f", cpsInterp * 60));
}
}
if (compactTier <= 9) {
int counterInterp = (int) interp(compact, compactLast);
lineMap.put(
8,
EnumChatFormatting.AQUA + "Compact Progress: " + EnumChatFormatting.YELLOW + format.format(counterInterp) +
"/" + compactTierAmount
);
}
if (compactTier == 10) {
lineMap.put(8, EnumChatFormatting.AQUA + "Compact Progress: " + EnumChatFormatting.RED + compactTierAmount);
}
float xpInterp = xpGainHour;
if (xpGainHourLast == xpGainHour && xpGainHour <= 0) {
lineMap.put(5, EnumChatFormatting.AQUA + "XP/h: " + EnumChatFormatting.YELLOW + "N/A");
} else {
xpInterp = interp(xpGainHour, xpGainHourLast);
lineMap.put(5, EnumChatFormatting.AQUA + "XP/h: " + EnumChatFormatting.YELLOW +
format.format(xpInterp) + (isMining ? "" : EnumChatFormatting.RED + " (PAUSED)"));
}
if (skillInfo != null && skillInfo.level < 60) {
StringBuilder levelStr = new StringBuilder(EnumChatFormatting.AQUA + "Mining" + ": "); //yes ik its spelt wrong
levelStr.append(EnumChatFormatting.YELLOW)
.append(skillInfo.level)
.append(EnumChatFormatting.GRAY)
.append(" [");
float progress = (float) (skillInfo.currentXp / skillInfo.currentXpMax);
if (skillInfoLast != null && skillInfo.currentXpMax == skillInfoLast.currentXpMax) {
progress = interp(progress, (float) (skillInfoLast.currentXp / skillInfoLast.currentXpMax));
}
float lines = 25;
for (int i = 0; i < lines; i++) {
if (i / lines < progress) {
levelStr.append(EnumChatFormatting.YELLOW);
} else {
levelStr.append(EnumChatFormatting.DARK_GRAY);
}
levelStr.append('|');
}
levelStr.append(EnumChatFormatting.GRAY)
.append("] ")
.append(EnumChatFormatting.YELLOW)
.append((int) (progress * 100))
.append("%");
int current = (int) skillInfo.currentXp;
if (skillInfoLast != null && skillInfo.currentXpMax == skillInfoLast.currentXpMax) {
current = (int) interp(current, (float) skillInfoLast.currentXp);
}
int remaining = (int) (skillInfo.currentXpMax - skillInfo.currentXp);
if (skillInfoLast != null && skillInfo.currentXpMax == skillInfoLast.currentXpMax) {
remaining = (int) interp(remaining, (int) (skillInfoLast.currentXpMax - skillInfoLast.currentXp));
}
lineMap.put(2, levelStr.toString());
lineMap.put(3, EnumChatFormatting.AQUA + "Current XP: " + EnumChatFormatting.YELLOW + format.format(current));
if (remaining < 0) {
lineMap.put(4, EnumChatFormatting.AQUA + "Remaining XP: " + EnumChatFormatting.YELLOW + "MAXED!");
lineMap.put(7, EnumChatFormatting.AQUA + "ETA: " + EnumChatFormatting.YELLOW + "MAXED!");
} else {
lineMap.put(
4,
EnumChatFormatting.AQUA + "Remaining XP: " + EnumChatFormatting.YELLOW + format.format(remaining)
);
if (xpGainHour < 1000) {
lineMap.put(7, EnumChatFormatting.AQUA + "ETA: " + EnumChatFormatting.YELLOW + "N/A");
} else {
lineMap.put(
7,
EnumChatFormatting.AQUA + "ETA: " + EnumChatFormatting.YELLOW +
Utils.prettyTime((long) (remaining) * 1000 * 60 * 60 / (long) xpInterp)
);
}
}
}
if (skillInfo != null && skillInfo.level == 60) {
int current = (int) skillInfo.currentXp;
if (skillInfoLast != null && skillInfo.currentXpMax == skillInfoLast.currentXpMax) {
current = (int) interp(current, (float) skillInfoLast.currentXp);
}
lineMap.put(
2,
EnumChatFormatting.AQUA + "Mining: " + EnumChatFormatting.YELLOW + "60 " + EnumChatFormatting.RED + "(Maxed)"
);
lineMap.put(3, EnumChatFormatting.AQUA + "Current XP: " + EnumChatFormatting.YELLOW + format.format(current));
}
float yaw = Minecraft.getMinecraft().thePlayer.rotationYawHead;
yaw %= 360;
if (yaw < 0) yaw += 360;
if (yaw > 180) yaw -= 360;
lineMap.put(6, EnumChatFormatting.AQUA + "Yaw: " + EnumChatFormatting.YELLOW +
String.format("%.2f", yaw) + EnumChatFormatting.BOLD + "\u1D52");
for (int strIndex : NotEnoughUpdates.INSTANCE.config.skillOverlays.miningText) {
if (lineMap.get(strIndex) != null) {
overlayStrings.add(lineMap.get(strIndex));
}
}
if (overlayStrings != null && overlayStrings.isEmpty()) overlayStrings = null;
}
}
}