superb-warfare/src/main/java/com/atsuishio/superbwarfare/client/tooltip/ClientGunImageTooltip.java
2024-12-24 15:56:11 +08:00

438 lines
19 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package com.atsuishio.superbwarfare.client.tooltip;
import com.atsuishio.superbwarfare.client.tooltip.component.GunImageComponent;
import com.atsuishio.superbwarfare.init.ModKeyMappings;
import com.atsuishio.superbwarfare.init.ModPerks;
import com.atsuishio.superbwarfare.init.ModTags;
import com.atsuishio.superbwarfare.perk.AmmoPerk;
import com.atsuishio.superbwarfare.perk.Perk;
import com.atsuishio.superbwarfare.perk.PerkHelper;
import com.atsuishio.superbwarfare.tools.GunsTool;
import com.atsuishio.superbwarfare.tools.ItemNBTTool;
import com.atsuishio.superbwarfare.tools.TooltipTool;
import net.minecraft.ChatFormatting;
import net.minecraft.client.gui.Font;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.gui.screens.inventory.tooltip.ClientTooltipComponent;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component;
import net.minecraft.util.Mth;
import net.minecraft.world.item.ItemStack;
import org.jetbrains.annotations.NotNull;
import java.text.DecimalFormat;
// TODO 等nbt重置后修改nbt位置
public class ClientGunImageTooltip implements ClientTooltipComponent {
protected final int width;
protected final int height;
protected final ItemStack stack;
public ClientGunImageTooltip(GunImageComponent tooltip) {
this.width = tooltip.width;
this.height = tooltip.height;
this.stack = tooltip.stack;
}
@Override
public void renderImage(@NotNull Font font, int x, int y, GuiGraphics guiGraphics) {
guiGraphics.pose().pushPose();
renderDamageAndRpmTooltip(font, guiGraphics, x, y);
renderLevelAndUpgradePointTooltip(font, guiGraphics, x, y + 10);
int yo = 20;
if (shouldRenderBypassAndHeadshotTooltip()) {
renderBypassAndHeadshotTooltip(font, guiGraphics, x, y + yo);
yo += 10;
}
if (shouldRenderEditTooltip()) {
renderWeaponEditTooltip(font, guiGraphics, x, y + yo);
yo += 20;
}
if (shouldRenderPerks()) {
if (!Screen.hasShiftDown()) {
renderPerksShortcut(font, guiGraphics, x, y + yo);
} else {
renderPerks(font, guiGraphics, x, y + yo);
}
}
guiGraphics.pose().popPose();
}
protected boolean shouldRenderBypassAndHeadshotTooltip() {
return GunsTool.getGunDoubleTag(stack, "BypassesArmor", 0) > 0 || GunsTool.getGunDoubleTag(stack, "Headshot", 0) > 0;
}
protected boolean shouldRenderEditTooltip() {
return stack.is(ModTags.Items.CAN_CUSTOM_GUN);
}
protected boolean shouldRenderPerks() {
return PerkHelper.getPerkByType(stack, Perk.Type.AMMO) != null || PerkHelper.getPerkByType(stack, Perk.Type.DAMAGE) != null || PerkHelper.getPerkByType(stack, Perk.Type.FUNCTIONAL) != null;
}
/**
* 渲染武器伤害和射速
*/
protected void renderDamageAndRpmTooltip(Font font, GuiGraphics guiGraphics, int x, int y) {
guiGraphics.drawString(font, getDamageComponent(), x, y, 0xFFFFFF);
int xo = font.width(getDamageComponent().getVisualOrderText());
guiGraphics.drawString(font, getRpmComponent(), x + xo + 16, y, 0xFFFFFF);
}
/**
* 获取武器伤害的文本组件
*/
protected Component getDamageComponent() {
double damage = GunsTool.getGunDoubleTag(stack, "Damage", 0) * TooltipTool.perkDamage(stack);
return Component.translatable("des.superbwarfare.tips.damage").withStyle(ChatFormatting.GRAY)
.append(Component.literal("").withStyle(ChatFormatting.RESET))
.append(Component.literal(new DecimalFormat("##.#").format(damage) + (TooltipTool.heBullet(stack) ? " + "
+ new DecimalFormat("##.#").format(0.8 * damage * (1 + 0.1 * TooltipTool.heBulletLevel(stack))) : "")).withStyle(ChatFormatting.GREEN));
}
/**
* 获取武器射速的文本组件
*/
protected Component getRpmComponent() {
if (!stack.is(ModTags.Items.IS_AUTO_WEAPON)) {
return Component.literal("");
} else {
return Component.translatable("des.superbwarfare.tips.rpm").withStyle(ChatFormatting.GRAY)
.append(Component.literal("").withStyle(ChatFormatting.RESET))
.append(Component.literal(new DecimalFormat("##").format(GunsTool.getGunIntTag(stack, "RPM", 0) + ItemNBTTool.getDouble(stack, "customRpm", 0)))
.withStyle(ChatFormatting.GREEN));
}
}
/**
* 渲染武器等级和强化点数
*/
protected void renderLevelAndUpgradePointTooltip(Font font, GuiGraphics guiGraphics, int x, int y) {
guiGraphics.drawString(font, getLevelComponent(), x, y, 0xFFFFFF);
int xo = font.width(getLevelComponent().getVisualOrderText());
guiGraphics.drawString(font, getUpgradePointComponent(), x + xo + 16, y, 0xFFFFFF);
}
/**
* 获取武器等级文本组件
*/
protected Component getLevelComponent() {
int level = ItemNBTTool.getInt(stack, "Level", 0);
double rate = ItemNBTTool.getDouble(stack, "Exp", 0) / (20 * Math.pow(level, 2) + 160 * level + 20);
ChatFormatting formatting;
if (level < 10) {
formatting = ChatFormatting.WHITE;
} else if (level < 20) {
formatting = ChatFormatting.AQUA;
} else if (level < 30) {
formatting = ChatFormatting.LIGHT_PURPLE;
} else if (level < 40) {
formatting = ChatFormatting.GOLD;
} else {
formatting = ChatFormatting.RED;
}
return Component.translatable("des.superbwarfare.tips.level").withStyle(ChatFormatting.GRAY)
.append(Component.literal("").withStyle(ChatFormatting.RESET))
.append(Component.literal(level + "").withStyle(formatting).withStyle(ChatFormatting.BOLD))
.append(Component.literal("").withStyle(ChatFormatting.RESET))
.append(Component.literal(" (" + new DecimalFormat("#0.00").format(rate * 100) + "%)").withStyle(ChatFormatting.GRAY));
}
/**
* 获取武器强化点数文本组件
*/
protected Component getUpgradePointComponent() {
int upgradePoint = Mth.floor(ItemNBTTool.getDouble(stack, "UpgradePoint", 0));
return Component.translatable("des.superbwarfare.tips.upgrade_point").withStyle(ChatFormatting.GRAY)
.append(Component.literal("").withStyle(ChatFormatting.RESET))
.append(Component.literal(String.valueOf(upgradePoint)).withStyle(ChatFormatting.WHITE).withStyle(ChatFormatting.BOLD));
}
/**
* 渲染武器穿甲比例和爆头倍率
*/
protected void renderBypassAndHeadshotTooltip(Font font, GuiGraphics guiGraphics, int x, int y) {
guiGraphics.drawString(font, getBypassComponent(), x, y, 0xFFFFFF);
int xo = font.width(getBypassComponent().getVisualOrderText());
guiGraphics.drawString(font, getHeadshotComponent(), x + xo + 16, y, 0xFFFFFF);
}
/**
* 获取武器穿甲比例文本组件
*/
protected Component getBypassComponent() {
double perkBypassArmorRate = 0;
var perk = PerkHelper.getPerkByType(stack, Perk.Type.AMMO);
if (perk instanceof AmmoPerk ammoPerk) {
int level = PerkHelper.getItemPerkLevel(perk, stack);
perkBypassArmorRate = ammoPerk.bypassArmorRate + (perk == ModPerks.AP_BULLET.get() ? 0.05f * (level - 1) : 0);
}
double bypassRate = Math.max(GunsTool.getGunDoubleTag(stack, "BypassesArmor", 0) + perkBypassArmorRate, 0);
return Component.translatable("des.superbwarfare.tips.bypass").withStyle(ChatFormatting.GRAY)
.append(Component.literal("").withStyle(ChatFormatting.RESET))
.append(Component.literal(new DecimalFormat("##.##").format(bypassRate * 100) + "%").withStyle(ChatFormatting.GOLD));
}
/**
* 获取武器爆头倍率文本组件
*/
protected Component getHeadshotComponent() {
double headshot = GunsTool.getGunDoubleTag(stack, "Headshot", 0);
return Component.translatable("des.superbwarfare.tips.headshot").withStyle(ChatFormatting.GRAY)
.append(Component.literal("").withStyle(ChatFormatting.RESET))
.append(Component.literal(new DecimalFormat("##.#").format(headshot) + "x").withStyle(ChatFormatting.AQUA));
}
/**
* 渲染武器改装信息
*/
protected void renderWeaponEditTooltip(Font font, GuiGraphics guiGraphics, int x, int y) {
guiGraphics.drawString(font, getEditComponent(), x, y + 10, 0xFFFFFF);
}
/**
* 获取武器改装信息文本组件
*/
protected Component getEditComponent() {
return Component.translatable("des.superbwarfare.tips.edit", "[" + ModKeyMappings.EDIT_MODE.getKey().getDisplayName().getString() + "]")
.withStyle(ChatFormatting.LIGHT_PURPLE).withStyle(ChatFormatting.ITALIC);
}
/**
* 渲染武器模组缩略图
*/
protected void renderPerksShortcut(Font font, GuiGraphics guiGraphics, int x, int y) {
guiGraphics.pose().pushPose();
int xOffset = -20;
Perk ammoPerk = PerkHelper.getPerkByType(stack, Perk.Type.AMMO);
if (ammoPerk != null && PerkHelper.getPerkItem(ammoPerk).isPresent()) {
xOffset += 20;
var ammoItem = PerkHelper.getPerkItem(ammoPerk).get().get();
ItemStack perkStack = ammoItem.getDefaultInstance();
CompoundTag ammoTag = PerkHelper.getPerkTag(stack, Perk.Type.AMMO);
if (!ammoTag.isEmpty()) {
int level = PerkHelper.getItemPerkLevel(ammoPerk, stack);
perkStack.setCount(level);
}
guiGraphics.renderItem(perkStack, x + xOffset, y + 2);
guiGraphics.renderItemDecorations(font, perkStack, x + xOffset, y + 2);
}
Perk funcPerk = PerkHelper.getPerkByType(stack, Perk.Type.FUNCTIONAL);
if (funcPerk != null && PerkHelper.getPerkItem(funcPerk).isPresent()) {
xOffset += 20;
var funcItem = PerkHelper.getPerkItem(funcPerk).get().get();
ItemStack perkStack = funcItem.getDefaultInstance();
CompoundTag funcTag = PerkHelper.getPerkTag(stack, Perk.Type.FUNCTIONAL);
if (!funcTag.isEmpty()) {
int level = PerkHelper.getItemPerkLevel(funcPerk, stack);
perkStack.setCount(level);
}
guiGraphics.renderItem(perkStack, x + xOffset, y + 2);
guiGraphics.renderItemDecorations(font, perkStack, x + xOffset, y + 2);
}
Perk damagePerk = PerkHelper.getPerkByType(stack, Perk.Type.DAMAGE);
if (damagePerk != null && PerkHelper.getPerkItem(damagePerk).isPresent()) {
xOffset += 20;
var damageItem = PerkHelper.getPerkItem(damagePerk).get().get();
ItemStack perkStack = damageItem.getDefaultInstance();
CompoundTag damageTag = PerkHelper.getPerkTag(stack, Perk.Type.DAMAGE);
if (!damageTag.isEmpty()) {
int level = PerkHelper.getItemPerkLevel(damagePerk, stack);
perkStack.setCount(level);
}
guiGraphics.renderItem(perkStack, x + xOffset, y + 2);
guiGraphics.renderItemDecorations(font, perkStack, x + xOffset, y + 2);
}
guiGraphics.pose().popPose();
}
/**
* 渲染武器模组详细信息
*/
protected void renderPerks(Font font, GuiGraphics guiGraphics, int x, int y) {
guiGraphics.pose().pushPose();
guiGraphics.drawString(font, Component.translatable("perk.superbwarfare.tips").withStyle(ChatFormatting.GOLD).withStyle(ChatFormatting.UNDERLINE), x, y + 10, 0xFFFFFF);
int yOffset = -5;
Perk ammoPerk = PerkHelper.getPerkByType(stack, Perk.Type.AMMO);
if (ammoPerk != null && PerkHelper.getPerkItem(ammoPerk).isPresent()) {
yOffset += 25;
var ammoItem = PerkHelper.getPerkItem(ammoPerk).get().get();
guiGraphics.renderItem(ammoItem.getDefaultInstance(), x, y + 4 + yOffset);
CompoundTag ammoTag = PerkHelper.getPerkTag(stack, Perk.Type.AMMO);
if (!ammoTag.isEmpty()) {
var ids = ammoTag.getString("id").split(":");
if (ids.length > 1) {
String id = ids[1];
var ammoComponent = Component.translatable("item.superbwarfare." + id).withStyle(ChatFormatting.YELLOW)
.append(Component.literal(" ").withStyle(ChatFormatting.RESET))
.append(Component.literal(" Lvl. " + ammoTag.getInt("level")).withStyle(ChatFormatting.WHITE));
var ammoDesComponent = Component.translatable("des.superbwarfare." + id).withStyle(ChatFormatting.GRAY);
guiGraphics.drawString(font, ammoComponent, x + 20, y + yOffset + 2, 0xFFFFFF);
guiGraphics.drawString(font, ammoDesComponent, x + 20, y + yOffset + 12, 0xFFFFFF);
}
}
}
Perk funcPerk = PerkHelper.getPerkByType(stack, Perk.Type.FUNCTIONAL);
if (funcPerk != null && PerkHelper.getPerkItem(funcPerk).isPresent()) {
yOffset += 25;
var funcItem = PerkHelper.getPerkItem(funcPerk).get().get();
guiGraphics.renderItem(funcItem.getDefaultInstance(), x, y + 4 + yOffset);
CompoundTag funcTag = PerkHelper.getPerkTag(stack, Perk.Type.FUNCTIONAL);
if (!funcTag.isEmpty()) {
var ids = funcTag.getString("id").split(":");
if (ids.length > 1) {
String id = ids[1];
var funcComponent = Component.translatable("item.superbwarfare." + id).withStyle(ChatFormatting.GREEN)
.append(Component.literal(" ").withStyle(ChatFormatting.RESET))
.append(Component.literal(" Lvl. " + funcTag.getInt("level")).withStyle(ChatFormatting.WHITE));
var funcDesComponent = Component.translatable("des.superbwarfare." + id).withStyle(ChatFormatting.GRAY);
guiGraphics.drawString(font, funcComponent, x + 20, y + yOffset + 2, 0xFFFFFF);
guiGraphics.drawString(font, funcDesComponent, x + 20, y + yOffset + 12, 0xFFFFFF);
}
}
}
Perk damagePerk = PerkHelper.getPerkByType(stack, Perk.Type.DAMAGE);
if (damagePerk != null && PerkHelper.getPerkItem(damagePerk).isPresent()) {
yOffset += 25;
var damageItem = PerkHelper.getPerkItem(damagePerk).get().get();
guiGraphics.renderItem(damageItem.getDefaultInstance(), x, y + 4 + yOffset);
CompoundTag damageTag = PerkHelper.getPerkTag(stack, Perk.Type.DAMAGE);
if (!damageTag.isEmpty()) {
var ids = damageTag.getString("id").split(":");
if (ids.length > 1) {
String id = ids[1];
var damageComponent = Component.translatable("item.superbwarfare." + id).withStyle(ChatFormatting.RED)
.append(Component.literal(" ").withStyle(ChatFormatting.RESET))
.append(Component.literal(" Lvl. " + damageTag.getInt("level")).withStyle(ChatFormatting.WHITE));
var damageDesComponent = Component.translatable("des.superbwarfare." + id).withStyle(ChatFormatting.GRAY);
guiGraphics.drawString(font, damageComponent, x + 20, y + yOffset + 2, 0xFFFFFF);
guiGraphics.drawString(font, damageDesComponent, x + 20, y + yOffset + 12, 0xFFFFFF);
}
}
}
guiGraphics.pose().popPose();
}
protected int getDefaultMaxWidth(Font font) {
int width = font.width(getDamageComponent().getVisualOrderText()) + font.width(getRpmComponent().getVisualOrderText()) + 16;
width = Math.max(width, font.width(getLevelComponent().getVisualOrderText()) + font.width(getUpgradePointComponent().getVisualOrderText()) + 16);
if (shouldRenderBypassAndHeadshotTooltip()) {
width = Math.max(width, font.width(getBypassComponent().getVisualOrderText()) + font.width(getHeadshotComponent().getVisualOrderText()) + 16);
}
if (shouldRenderEditTooltip()) {
width = Math.max(width, font.width(getEditComponent().getVisualOrderText()) + 16);
}
return width + 4;
}
protected int getMaxPerkDesWidth(Font font) {
if (!shouldRenderPerks()) return 0;
int width = 0;
CompoundTag ammoTag = PerkHelper.getPerkTag(stack, Perk.Type.AMMO);
if (!ammoTag.isEmpty()) {
var ids = ammoTag.getString("id").split(":");
if (ids.length > 1) {
String id = ids[1];
var ammoDesComponent = Component.translatable("des.superbwarfare." + id).withStyle(ChatFormatting.GRAY);
width = Math.max(width, font.width(ammoDesComponent));
}
}
CompoundTag funcTag = PerkHelper.getPerkTag(stack, Perk.Type.FUNCTIONAL);
if (!funcTag.isEmpty()) {
var ids = funcTag.getString("id").split(":");
if (ids.length > 1) {
String id = ids[1];
var funcDesComponent = Component.translatable("des.superbwarfare." + id).withStyle(ChatFormatting.GRAY);
width = Math.max(width, font.width(funcDesComponent));
}
}
CompoundTag damageTag = PerkHelper.getPerkTag(stack, Perk.Type.DAMAGE);
if (!damageTag.isEmpty()) {
var ids = damageTag.getString("id").split(":");
if (ids.length > 1) {
String id = ids[1];
var damageDesComponent = Component.translatable("des.superbwarfare." + id).withStyle(ChatFormatting.GRAY);
width = Math.max(width, font.width(damageDesComponent));
}
}
return width + 25;
}
@Override
public int getHeight() {
int height = Math.max(20, this.height);
if (shouldRenderBypassAndHeadshotTooltip()) height += 10;
if (shouldRenderEditTooltip()) height += 20;
if (shouldRenderPerks()) {
if (!Screen.hasShiftDown()) {
height += 16;
} else {
height += 16;
if (PerkHelper.getPerkByType(stack, Perk.Type.AMMO) != null) {
height += 25;
}
if (PerkHelper.getPerkByType(stack, Perk.Type.FUNCTIONAL) != null) {
height += 25;
}
if (PerkHelper.getPerkByType(stack, Perk.Type.DAMAGE) != null) {
height += 25;
}
}
}
return height;
}
@Override
public int getWidth(@NotNull Font font) {
if (Screen.hasShiftDown()) {
int width = getMaxPerkDesWidth(font);
return width == 0 ? Math.max(this.width, getDefaultMaxWidth(font)) : Math.max(width, getDefaultMaxWidth(font));
} else {
return getDefaultMaxWidth(font);
}
}
}