/*
* 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.KeybindHelper;
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.client.audio.ISound;
import net.minecraft.client.audio.PositionedSound;
import net.minecraft.client.audio.SoundCategory;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.EnumChatFormatting;
import net.minecraft.util.ResourceLocation;
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 FishingSkillOverlay
extends TextOverlay { //Im sure there is a much better way to do this besides making another class ¯\_(ツ)_/¯
private long lastUpdate = -1;
private long timer = -1;
private int expertiseLast = -1;
private int expertise = -1;
private int expertiseTier = -1;
private String expertiseTierAmount = "1";
private float fishedPerSecondLast = 0;
private float fishedPerSecond = 0;
private final LinkedList expertiseQueue = new LinkedList<>();
private XPInformation.SkillInfo skillInfo = null;
private XPInformation.SkillInfo skillInfoLast = null;
private float lastTotalXp = -1;
private boolean isFishing = false;
private final LinkedList xpGainQueue = new LinkedList<>();
private float xpGainHourLast = -1;
private float xpGainHour = -1;
private int xpGainTimer = 0;
private final String skillType = "Fishing";
public FishingSkillOverlay(
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() {
// NopoTheGamer named this variable
return NotEnoughUpdates.INSTANCE.config.skillOverlays.FishingSkillOverlay;
}
@Override
public void update() {
if (!isEnabled()) {
expertise = -1;
overlayStrings = null;
return;
}
lastUpdate = System.currentTimeMillis();
expertiseLast = expertise;
xpGainHourLast = xpGainHour;
expertise = -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("expertise_kills", 99)) {
expertise = ea.getInteger("expertise_kills");
expertiseQueue.add(0, expertise);
}
}
}
if (expertise < 50) {
expertiseTier = 1;
} else if (expertise < 100) {
expertiseTier = 2;
} else if (expertise < 250) {
expertiseTier = 3;
} else if (expertise < 500) {
expertiseTier = 4;
} else if (expertise < 1000) {
expertiseTier = 5;
} else if (expertise < 2500) {
expertiseTier = 6;
} else if (expertise < 5500) {
expertiseTier = 7;
} else if (expertise < 10000) {
expertiseTier = 8;
} else if (expertise < 15000) {
expertiseTier = 9;
} else if (expertise > 15000) {
expertiseTier = 10;
}
switch (expertiseTier) {
case 1:
expertiseTierAmount = "50";
break;
case 2:
expertiseTierAmount = "100";
break;
case 3:
expertiseTierAmount = "250";
break;
case 4:
expertiseTierAmount = "500";
break;
case 5:
expertiseTierAmount = "1,000";
break;
case 6:
expertiseTierAmount = "2,500";
break;
case 7:
expertiseTierAmount = "5,500";
break;
case 8:
expertiseTierAmount = "10,000";
break;
case 9:
expertiseTierAmount = "15,000";
break;
case 10:
expertiseTierAmount = "Maxed";
break;
}
String internalname = NotEnoughUpdates.INSTANCE.manager.getInternalNameForItem(stack);
skillInfoLast = skillInfo;
var s = NotEnoughUpdates.INSTANCE.config.skillOverlays.fishingText;
skillInfo = XPInformation.getInstance().getSkillInfo(
skillType,
s.contains(1) ||
s.contains(2) ||
s.contains(3) ||
s.contains(4) ||
s.contains(5)
);
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.fishingPauseTimer;
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();
isFishing = 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();
isFishing = true;
} else if (delta <= 0) {
isFishing = false;
}
}
lastTotalXp = totalXp;
}
while (expertiseQueue.size() >= 4) {
expertiseQueue.removeLast();
}
if (expertiseQueue.isEmpty()) {
fishedPerSecond = -1;
fishedPerSecondLast = 0;
} else {
fishedPerSecondLast = fishedPerSecond;
int last = expertiseQueue.getLast();
int first = expertiseQueue.getFirst();
fishedPerSecond = (first - last) / 3f;
}
if (expertise != -1) {
overlayStrings = new ArrayList<>();
} else {
overlayStrings = null;
}
}
@Override
public void updateFrequent() {
super.updateFrequent();
if (expertise < 0) {
overlayStrings = null;
} else {
HashMap lineMap = new HashMap<>();
overlayStrings = new ArrayList<>();
NumberFormat format = NumberFormat.getIntegerInstance();
/*if(expertise >= 0) {
int counterInterp = (int)interp(expertise, expertiseLast);
lineMap.put(0, EnumChatFormatting.AQUA+"Expertise Kills: "+EnumChatFormatting.YELLOW+format.format(counterInterp));
}*/
/*if(expertise >= 0) {
if(fishedPerSecondLast == fishedPerSecond && fishedPerSecond <= 0) {
lineMap.put(7, EnumChatFormatting.AQUA+"Catches/m: "+EnumChatFormatting.YELLOW + "N/A");
} else {
//float cpsInterp = interp(fishedPerSecond, fishedPerSecondLast);
lineMap.put(7, EnumChatFormatting.AQUA+"Catches/m: "+EnumChatFormatting.YELLOW +
fishedPerSecond);
//String.format("%.2f", cpsInterp*60));
}
}*/
if (expertiseTier <= 9) {
int counterInterp = (int) interp(expertise, expertiseLast);
lineMap.put(
0,
EnumChatFormatting.AQUA + "Expertise: " + EnumChatFormatting.YELLOW + format.format(counterInterp) + "/" +
expertiseTierAmount
);
}
if (expertiseTier == 10) {
int counterInterp = (int) interp(expertise, expertiseLast);
lineMap.put(
0,
EnumChatFormatting.AQUA + "Expertise: " + EnumChatFormatting.YELLOW + format.format(counterInterp) + " " +
EnumChatFormatting.RED + expertiseTierAmount
);
}
float xpInterp = xpGainHour;
if (xpGainHourLast == xpGainHour && xpGainHour <= 0) {
lineMap.put(4, EnumChatFormatting.AQUA + "XP/h: " + EnumChatFormatting.YELLOW + "N/A");
} else {
xpInterp = interp(xpGainHour, xpGainHourLast);
lineMap.put(4, EnumChatFormatting.AQUA + "XP/h: " + EnumChatFormatting.YELLOW +
format.format(xpInterp) + (isFishing ? "" : EnumChatFormatting.RED + " (PAUSED)"));
}
if (skillInfo != null && skillInfo.level < 50) {
StringBuilder levelStr = new StringBuilder(EnumChatFormatting.AQUA + skillType + ": ");
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(1, levelStr.toString());
lineMap.put(2, EnumChatFormatting.AQUA + "Current XP: " + EnumChatFormatting.YELLOW + format.format(current));
if (remaining < 0) {
lineMap.put(3, EnumChatFormatting.AQUA + "Remaining XP: " + EnumChatFormatting.YELLOW + "MAXED!");
lineMap.put(5, EnumChatFormatting.AQUA + "ETA: " + EnumChatFormatting.YELLOW + "MAXED!");
} else {
lineMap.put(
3,
EnumChatFormatting.AQUA + "Remaining XP: " + EnumChatFormatting.YELLOW + format.format(remaining)
);
if (xpGainHour < 1000) {
lineMap.put(5, EnumChatFormatting.AQUA + "ETA: " + EnumChatFormatting.YELLOW + "N/A");
} else {
lineMap.put(
5,
EnumChatFormatting.AQUA + "ETA: " + EnumChatFormatting.YELLOW +
Utils.prettyTime((long) (remaining) * 1000 * 60 * 60 / (long) xpInterp)
);
}
}
}
if (skillInfo != null && skillInfo.level == 50) {
int current = (int) skillInfo.currentXp;
if (skillInfoLast != null && skillInfo.currentXpMax == skillInfoLast.currentXpMax) {
current = (int) interp(current, (float) skillInfoLast.currentXp);
}
lineMap.put(
1,
EnumChatFormatting.AQUA + "Fishing: " + EnumChatFormatting.YELLOW + "50 " + EnumChatFormatting.RED + "(Maxed)"
);
lineMap.put(2, 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+"\u00b0");*/
int key = NotEnoughUpdates.INSTANCE.config.skillOverlays.fishKey;
ISound sound = new PositionedSound(new ResourceLocation("random.orb")) {{
volume = 50;
repeat = false;
repeatDelay = 0;
attenuationType = ISound.AttenuationType.NONE;
}};
int funnyCustomTimer = 1000 * NotEnoughUpdates.INSTANCE.config.skillOverlays.customFishTimer;
if (KeybindHelper.isKeyPressed(key) && timer != 0 && System.currentTimeMillis() - timer > 1000) {
timer = 0;
} else if (KeybindHelper.isKeyPressed(key) && timer == 0) {
timer = System.currentTimeMillis();
}
if (timer >= 1) {
lineMap.put(
6,
EnumChatFormatting.AQUA + "Timer: " + EnumChatFormatting.YELLOW +
Utils.prettyTime(System.currentTimeMillis() - (timer))
);
}
if (timer <= 0) {
lineMap.put(6, EnumChatFormatting.AQUA + "Timer: " + EnumChatFormatting.RED + "(Stopped)");
}
if (System.currentTimeMillis() - timer > funnyCustomTimer &&
System.currentTimeMillis() - timer < (funnyCustomTimer + 100) && funnyCustomTimer != 0) {
float oldLevel = Minecraft.getMinecraft().gameSettings.getSoundLevel(SoundCategory.PLAYERS);
Minecraft.getMinecraft().gameSettings.setSoundLevel(SoundCategory.PLAYERS, 1);
Minecraft.getMinecraft().getSoundHandler().playSound(sound);
Minecraft.getMinecraft().gameSettings.setSoundLevel(SoundCategory.PLAYERS, oldLevel);
}
for (int strIndex : NotEnoughUpdates.INSTANCE.config.skillOverlays.fishingText) {
if (lineMap.get(strIndex) != null) {
overlayStrings.add(lineMap.get(strIndex));
}
}
if (overlayStrings != null && overlayStrings.isEmpty()) overlayStrings = null;
}
}
}