Skip to content

Commit e464627

Browse files
committed
refactor mob health bar
1 parent a490c70 commit e464627

File tree

6 files changed

+361
-289
lines changed

6 files changed

+361
-289
lines changed
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package com.robertx22.mine_and_slash.a_libraries.neat;
2+
3+
import com.mojang.blaze3d.vertex.PoseStack;
4+
import com.mojang.blaze3d.vertex.VertexConsumer;
5+
import net.minecraft.ChatFormatting;
6+
import net.minecraft.client.Minecraft;
7+
import net.minecraft.client.gui.Font;
8+
import net.minecraft.client.renderer.MultiBufferSource;
9+
import net.minecraft.client.renderer.RenderType;
10+
import net.minecraft.resources.ResourceLocation;
11+
import org.joml.Matrix4f;
12+
13+
import java.util.function.Function;
14+
15+
public record EffectIcon(ResourceLocation location, int stack) {
16+
17+
public static EffectIcon of(ResourceLocation location, int stack){
18+
return new EffectIcon(location, stack);
19+
}
20+
21+
public void renderOnHealthBar(PoseStack poseStack, MultiBufferSource source, int size){
22+
VertexConsumer buffer = source.getBuffer(NeatRenderType.getHealthBarIconType(location));
23+
Matrix4f pose = new Matrix4f(poseStack.last().pose());
24+
int alpha = 200;
25+
int i = 255;
26+
Font font = Minecraft.getInstance().font;
27+
float fontScale = 0.5f * size / font.lineHeight;
28+
buffer.vertex(pose, 0, 0, 0.01f).color(i, i , i, alpha).uv(0, 0).endVertex();
29+
buffer.vertex(pose, 0, size, 0.01f).color(i, i , i, alpha).uv(0, 1).endVertex();
30+
buffer.vertex(pose, size, size, 0.01f).color(i, i , i, alpha).uv(1, 1).endVertex();
31+
buffer.vertex(pose, size, 0, 0.01f).color(i, i , i, alpha).uv(1, 0).endVertex();
32+
poseStack.pushPose();
33+
34+
//poseStack.translate(size - font.width(stack + ""), size - font.lineHeight, 0);
35+
poseStack.scale(fontScale, fontScale,1);
36+
font.drawInBatch(stack + "", 0, 0, ChatFormatting.WHITE.getColor(), false, new Matrix4f(poseStack.last().pose()), source, Font.DisplayMode.NORMAL, 0, 15728880);
37+
poseStack.popPose();
38+
39+
}
40+
}

src/main/java/com/robertx22/mine_and_slash/a_libraries/neat/HealthBarRenderer.java

Lines changed: 103 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,23 @@
22

33
import com.mojang.blaze3d.vertex.PoseStack;
44
import com.mojang.blaze3d.vertex.VertexConsumer;
5-
import com.mojang.math.Axis;
65
import com.robertx22.library_of_exile.util.UNICODE;
7-
import com.robertx22.library_of_exile.utils.CLOC;
86
import com.robertx22.mine_and_slash.config.forge.ServerContainer;
97
import com.robertx22.mine_and_slash.database.data.mob_affixes.MobAffix;
108
import com.robertx22.mine_and_slash.database.registry.ExileDB;
119
import com.robertx22.mine_and_slash.mmorpg.MMORPG;
1210
import com.robertx22.mine_and_slash.uncommon.datasaving.Load;
11+
import com.robertx22.mine_and_slash.uncommon.localization.Formatter;
1312
import com.robertx22.mine_and_slash.uncommon.utilityclasses.HealthUtils;
1413
import net.minecraft.ChatFormatting;
1514
import net.minecraft.client.Minecraft;
1615
import net.minecraft.client.gui.Font;
1716
import net.minecraft.client.renderer.MultiBufferSource;
18-
import net.minecraft.client.renderer.texture.OverlayTexture;
19-
import net.minecraft.client.resources.language.I18n;
17+
import net.minecraft.client.renderer.RenderType;
2018
import net.minecraft.core.registries.Registries;
19+
import net.minecraft.network.chat.CommonComponents;
20+
import net.minecraft.network.chat.Component;
21+
import net.minecraft.network.chat.MutableComponent;
2122
import net.minecraft.resources.ResourceLocation;
2223
import net.minecraft.tags.TagKey;
2324
import net.minecraft.util.Mth;
@@ -27,27 +28,33 @@
2728
import net.minecraft.world.entity.MobType;
2829
import net.minecraft.world.entity.monster.Monster;
2930
import net.minecraft.world.entity.player.Player;
30-
import net.minecraft.world.item.ItemDisplayContext;
3131
import net.minecraft.world.item.ItemStack;
3232
import net.minecraft.world.item.Items;
3333
import net.minecraft.world.level.ClipContext;
34-
import net.minecraft.world.level.Level;
3534
import net.minecraft.world.phys.AABB;
3635
import net.minecraft.world.phys.HitResult;
3736
import net.minecraft.world.phys.Vec3;
3837
import net.minecraft.world.scores.Team;
3938
import net.minecraftforge.registries.ForgeRegistries;
39+
import org.apache.commons.lang3.ArrayUtils;
40+
import org.apache.commons.lang3.tuple.Pair;
41+
import org.jetbrains.annotations.NotNull;
4042
import org.joml.Quaternionf;
4143

4244
import java.text.DecimalFormat;
43-
import java.util.Arrays;
45+
import java.util.ArrayList;
46+
import java.util.Collections;
4447
import java.util.List;
4548
import java.util.Optional;
4649
import java.util.stream.Collectors;
4750

4851
public class HealthBarRenderer {
4952

5053
private static final DecimalFormat HEALTH_FORMAT = new DecimalFormat("#.##");
54+
private static final TagKey<EntityType<?>> FORGE_BOSS_TAG =
55+
TagKey.create(Registries.ENTITY_TYPE, new ResourceLocation("forge", "bosses"));
56+
private static final TagKey<EntityType<?>> FABRIC_BOSS_TAG =
57+
TagKey.create(Registries.ENTITY_TYPE, new ResourceLocation("c", "bosses"));
5158

5259
private static Entity getEntityLookedAt(Entity e) {
5360
Entity foundEntity = null;
@@ -138,12 +145,6 @@ private static int getColor(LivingEntity entity, boolean colorByType, boolean bo
138145
}
139146
}
140147

141-
private static final TagKey<EntityType<?>> FORGE_BOSS_TAG =
142-
TagKey.create(Registries.ENTITY_TYPE, new ResourceLocation("forge", "bosses"));
143-
144-
private static final TagKey<EntityType<?>> FABRIC_BOSS_TAG =
145-
TagKey.create(Registries.ENTITY_TYPE, new ResourceLocation("c", "bosses"));
146-
147148
private static boolean isBoss(Entity entity) {
148149
return entity.getType().is(FORGE_BOSS_TAG) || entity.getType().is(FABRIC_BOSS_TAG);
149150
}
@@ -201,13 +202,18 @@ private static boolean shouldShowPlate(LivingEntity living, Entity cameraEntity)
201202
return visible;
202203
}
203204

204-
static List<ItemStack> getIcons(Entity e) {
205+
static List<EffectIcon> getIcons(Entity e) {
205206

206207
if (e instanceof LivingEntity en) {
207208
return Load.Unit(en).getStatusEffectsData().exileMap.entrySet().stream()
208-
.map(x -> new ItemStack(ExileDB.ExileEffects().get(x.getKey()).getEffectDisplayItem(), x.getValue().stacks)).collect(Collectors.toList());
209+
.map(x -> Pair.of(EffectIcon.of(ExileDB.ExileEffects().get(x.getKey()).getTexture(), x.getValue().stacks), x.getValue().ticks_left))
210+
.sorted((x, y) -> -Integer.compare(x.getValue(), y.getValue()))
211+
.map(Pair::getLeft)
212+
.filter(x -> x.location() == null)
213+
.peek(x -> System.out.println("found one!"))
214+
.collect(Collectors.toCollection(ArrayList::new));
209215
}
210-
return Arrays.asList();
216+
return Collections.EMPTY_LIST;
211217

212218
}
213219

@@ -231,68 +237,33 @@ public static void hookRender(Entity entity, PoseStack poseStack, MultiBufferSou
231237
final int barHeight = NeatConfig.instance.barHeight();
232238
final boolean boss = isBoss(living);
233239

234-
List<ItemStack> icons = getIcons(entity);
235-
236-
int lvl = Load.Unit(living).getLevel();
237-
int playerlvl = Load.Unit(mc.player).getLevel();
238-
int diffabove = lvl - playerlvl;
239-
240-
String lvltext = "Lvl " + lvl;
241-
242-
if (entity instanceof Player == false && diffabove > ServerContainer.get().LEVEL_DISTANCE_SKULL_SHOW.get()) {
243-
if (ServerContainer.get().SKULL_HIDES_LEVEL.get()) {
244-
lvltext = "Lvl " + ChatFormatting.RED + UNICODE.SKULL;
245-
} else {
246-
lvltext = "Lvl " + lvl + " " + ChatFormatting.RED + UNICODE.SKULL;
247-
}
248-
}
249-
250-
String prefix = "";
251-
String suffix = "";
240+
List<EffectIcon> icons = getIcons(entity);
252241

253-
for (MobAffix affix : Load.Unit(entity).getAffixData().getAffixes()) {
254-
255-
if (affix.type.isPrefix()) {
242+
MutableComponent name = getNameString(entity, living, mc);
256243

257-
prefix += CLOC.translate(affix.locName());
258-
} else {
259-
260-
suffix += CLOC.translate(affix.locName());
261-
262-
}
263-
}
264-
265-
String rar = I18n.get(Load.Unit(living).getMobRarity().locName().getString());
266-
267-
ChatFormatting color = Load.Unit(living).getMobRarity().textFormatting();
268-
269-
if (living instanceof Player) {
270-
rar = "";
271-
color = ChatFormatting.RED;
272-
}
273-
274-
String name = ChatFormatting.YELLOW + lvltext + " " + color + rar + " " + prefix + " " + living.getDisplayName().getString() + " " + suffix;
275-
276-
final float nameLen = (mc.font.width(name) + (icons.size() * 5)) * textScale;
244+
final float nameLen = (mc.font.width(name.getString()) + (icons.size() * 5)) * textScale;
277245
final float halfSize = Math.max(NeatConfig.instance.plateSize(), nameLen / 2.0F + 10.0F);
278246

279247
poseStack.pushPose();
248+
//System.out.println(living.getBbHeight());
249+
//System.out.println(NeatConfig.instance.heightAbove());
280250
poseStack.translate(0, living.getBbHeight() + NeatConfig.instance.heightAbove(), 0);
281251
poseStack.mulPose(cameraOrientation);
282252

283253
// Plate background, bars, and text operate with globalScale, but icons don't
284254
poseStack.pushPose();
285255
poseStack.scale(-globalScale, -globalScale, globalScale);
286-
256+
RenderType renderType = NeatRenderType.getHealthBarType();
257+
float padding = NeatConfig.instance.backgroundPadding();
258+
int bgHeight = NeatConfig.instance.backgroundHeight();
287259
// Background
288260
if (NeatConfig.instance.drawBackground()) {
289-
float padding = NeatConfig.instance.backgroundPadding();
290-
int bgHeight = NeatConfig.instance.backgroundHeight();
291-
VertexConsumer builder = buffers.getBuffer(NeatRenderType.BAR_TEXTURE_TYPE);
292-
builder.vertex(poseStack.last().pose(), -halfSize - padding, -bgHeight, 0.01F).color(0, 0, 0, 64).uv(0.0F, 0.0F).uv2(light).endVertex();
293-
builder.vertex(poseStack.last().pose(), -halfSize - padding, barHeight + padding, 0.01F).color(0, 0, 0, 64).uv(0.0F, 0.5F).uv2(light).endVertex();
294-
builder.vertex(poseStack.last().pose(), halfSize + padding, barHeight + padding, 0.01F).color(0, 0, 0, 64).uv(1.0F, 0.5F).uv2(light).endVertex();
295-
builder.vertex(poseStack.last().pose(), halfSize + padding, -bgHeight, 0.01F).color(0, 0, 0, 64).uv(1.0F, 0.0F).uv2(light).endVertex();
261+
262+
VertexConsumer builder = buffers.getBuffer(renderType);
263+
builder.vertex(poseStack.last().pose(), -halfSize - padding, -bgHeight, 0.01F).color(0, 0, 0, 64).uv(0.0F, 0.0F).endVertex();
264+
builder.vertex(poseStack.last().pose(), -halfSize - padding, barHeight + padding, 0.01F).color(0, 0, 0, 64).uv(0.0F, 0.5F).endVertex();
265+
builder.vertex(poseStack.last().pose(), halfSize + padding, barHeight + padding, 0.01F).color(0, 0, 0, 64).uv(1.0F, 0.5F).endVertex();
266+
builder.vertex(poseStack.last().pose(), halfSize + padding, -bgHeight, 0.01F).color(0, 0, 0, 64).uv(1.0F, 0.0F).endVertex();
296267
}
297268

298269
// Health Bar
@@ -306,18 +277,18 @@ public static void hookRender(Entity entity, PoseStack poseStack, MultiBufferSou
306277
float maxHealth = Math.max(living.getHealth(), living.getMaxHealth());
307278
float healthHalfSize = halfSize * (living.getHealth() / maxHealth);
308279

309-
VertexConsumer builder = buffers.getBuffer(NeatRenderType.BAR_TEXTURE_TYPE);
310-
builder.vertex(poseStack.last().pose(), -halfSize, 0, 0.001F).color(r, g, b, 127).uv(0.0F, 0.75F).uv2(light).endVertex();
311-
builder.vertex(poseStack.last().pose(), -halfSize, barHeight, 0.001F).color(r, g, b, 127).uv(0.0F, 1.0F).uv2(light).endVertex();
312-
builder.vertex(poseStack.last().pose(), -halfSize + 2 * healthHalfSize, barHeight, 0.001F).color(r, g, b, 127).uv(1.0F, 1.0F).uv2(light).endVertex();
313-
builder.vertex(poseStack.last().pose(), -halfSize + 2 * healthHalfSize, 0, 0.001F).color(r, g, b, 127).uv(1.0F, 0.75F).uv2(light).endVertex();
280+
VertexConsumer builder = buffers.getBuffer(renderType);
281+
builder.vertex(poseStack.last().pose(), -halfSize, 0, 0.001F).color(r, g, b, 127).uv(0.0F, 0.75F).endVertex();
282+
builder.vertex(poseStack.last().pose(), -halfSize, barHeight, 0.001F).color(r, g, b, 127).uv(0.0F, 1.0F).endVertex();
283+
builder.vertex(poseStack.last().pose(), -halfSize + 2 * healthHalfSize, barHeight, 0.001F).color(r, g, b, 127).uv(1.0F, 1.0F).endVertex();
284+
builder.vertex(poseStack.last().pose(), -halfSize + 2 * healthHalfSize, 0, 0.001F).color(r, g, b, 127).uv(1.0F, 0.75F).endVertex();
314285

315286
// Blank part of the bar
316287
if (healthHalfSize < halfSize) {
317-
builder.vertex(poseStack.last().pose(), -halfSize + 2 * healthHalfSize, 0, 0.001F).color(0, 0, 0, 127).uv(0.0F, 0.5F).uv2(light).endVertex();
318-
builder.vertex(poseStack.last().pose(), -halfSize + 2 * healthHalfSize, barHeight, 0.001F).color(0, 0, 0, 127).uv(0.0F, 0.75F).uv2(light).endVertex();
319-
builder.vertex(poseStack.last().pose(), halfSize, barHeight, 0.001F).color(0, 0, 0, 127).uv(1.0F, 0.75F).uv2(light).endVertex();
320-
builder.vertex(poseStack.last().pose(), halfSize, 0, 0.001F).color(0, 0, 0, 127).uv(1.0F, 0.5F).uv2(light).endVertex();
288+
builder.vertex(poseStack.last().pose(), -halfSize + 2 * healthHalfSize, 0, 0.001F).color(0, 0, 0, 127).uv(0.0F, 0.5F).endVertex();
289+
builder.vertex(poseStack.last().pose(), -halfSize + 2 * healthHalfSize, barHeight, 0.001F).color(0, 0, 0, 127).uv(0.0F, 0.75F).endVertex();
290+
builder.vertex(poseStack.last().pose(), halfSize, barHeight, 0.001F).color(0, 0, 0, 127).uv(1.0F, 0.75F).endVertex();
291+
builder.vertex(poseStack.last().pose(), halfSize, 0, 0.001F).color(0, 0, 0, 127).uv(1.0F, 0.5F).endVertex();
321292
}
322293
}
323294

@@ -368,17 +339,19 @@ public static void hookRender(Entity entity, PoseStack poseStack, MultiBufferSou
368339

369340
// Icons
370341
{
371-
final float zBump = -0.1F;
342+
final int size = 8;
343+
final float iconInterval = size * 0.2f;
372344
poseStack.pushPose();
345+
poseStack.scale(-globalScale, -globalScale, 1);
346+
poseStack.translate(halfSize + padding, bgHeight, 0);
347+
float horizontalOffset = icons.size() * size + (icons.size() - 1) * iconInterval;
348+
//todo: haven't handle the case like entity has insane amount of effects.
349+
// it will make the icon exceed the left of health bar.
350+
poseStack.translate(-horizontalOffset, 0, 0);
351+
for (int i = 0; i < icons.size(); i++) {
352+
if (i != 0) poseStack.translate(size + iconInterval, 0, 0);
353+
icons.get(i).renderOnHealthBar(poseStack, buffers, size);
373354

374-
float iconOffset = 2.85F;
375-
float zShift = 0F;
376-
377-
// todo
378-
for (ItemStack icon : icons) {
379-
renderIcon(living.level(), icon, poseStack, buffers, globalScale, halfSize, iconOffset, zShift);
380-
iconOffset += 5F;
381-
zShift += zBump;
382355
}
383356

384357

@@ -388,26 +361,53 @@ public static void hookRender(Entity entity, PoseStack poseStack, MultiBufferSou
388361
poseStack.popPose();
389362
}
390363

391-
private static void renderIcon(Level level, ItemStack icon, PoseStack poseStack,
392-
MultiBufferSource buffers, float globalScale, float halfSize, float leftShift, float zShift) {
393-
if (!icon.isEmpty()) {
394-
final float iconScale = 0.12F;
395-
poseStack.pushPose();
396-
// halfSize and co. are units operating under the assumption of globalScale,
397-
// but in the icon rendering section we don't use globalScale, so we need
398-
// to manually multiply it in to ensure the units line up.
399-
float dx = (halfSize - leftShift) * globalScale;
400-
float dy = 3F * globalScale;
401-
float dz = zShift * globalScale;
402-
// Need to negate X due to our rotation below
403-
poseStack.translate(-dx, dy, dz);
404-
poseStack.scale(iconScale, iconScale, iconScale);
405-
poseStack.mulPose(Axis.YP.rotationDegrees(180F));
406-
407-
408-
Minecraft.getInstance().getItemRenderer()
409-
.renderStatic(icon, ItemDisplayContext.NONE, 0xF000F0, OverlayTexture.NO_OVERLAY, poseStack, buffers, level, 0);
410-
poseStack.popPose();
364+
private static @NotNull MutableComponent getNameString(Entity entity, LivingEntity living, Minecraft mc) {
365+
int lvl = Load.Unit(living).getLevel();
366+
int playerlvl = Load.Unit(mc.player).getLevel();
367+
int diffabove = lvl - playerlvl;
368+
MutableComponent level = Component.literal(lvl + "");
369+
370+
if (entity instanceof Player == false && diffabove > ServerContainer.get().LEVEL_DISTANCE_SKULL_SHOW.get()) {
371+
if (ServerContainer.get().SKULL_HIDES_LEVEL.get()) {
372+
level = Component.literal(UNICODE.SKULL).withStyle(ChatFormatting.RED);
373+
} else {
374+
level = Component.literal(lvl + " " + UNICODE.SKULL).withStyle(ChatFormatting.RED);
375+
}
411376
}
377+
level = level.withStyle(ChatFormatting.YELLOW);
378+
379+
Component prefix = CommonComponents.EMPTY;
380+
Component name = living.getDisplayName();
381+
Component suffix = CommonComponents.EMPTY;
382+
383+
384+
for (MobAffix affix : Load.Unit(entity).getAffixData().getAffixes()) {
385+
386+
if (affix.type.isPrefix()) {
387+
prefix = affix.locName();
388+
} else {
389+
suffix = affix.locName();
390+
391+
}
392+
}
393+
ChatFormatting rarityColor;
394+
Component rarity;
395+
rarity = Load.Unit(living).getMobRarity().locName();
396+
397+
rarityColor = Load.Unit(living).getMobRarity().textFormatting();
398+
399+
if (living instanceof Player) {
400+
rarity = CommonComponents.EMPTY;
401+
rarityColor = ChatFormatting.RED;
402+
}
403+
List<Component> rarity1 = List.of(rarity, prefix, name, suffix);
404+
for (Component component : rarity1) {
405+
if (component instanceof MutableComponent){
406+
((MutableComponent) component).withStyle(rarityColor);
407+
}
408+
}
409+
Component[] array = rarity1.toArray(Component[]::new);
410+
return Formatter.MOB_NAME_TEMPLATE.locName((Object[]) ArrayUtils.addFirst(array, level)).withStyle(ChatFormatting.YELLOW);
412411
}
412+
413413
}

0 commit comments

Comments
 (0)