Skip to content

Commit ee6a414

Browse files
committed
fix: Dungeon Map and Compact Tab List issues with player head drawings
1 parent ee4eea1 commit ee6a414

File tree

10 files changed

+175
-135
lines changed

10 files changed

+175
-135
lines changed

src/main/java/com/fix3dll/skyblockaddons/features/dungeonmap/DungeonMapManager.java

Lines changed: 103 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,6 @@
1212
import com.google.common.collect.Maps;
1313
import com.mojang.blaze3d.pipeline.RenderPipeline;
1414
import com.mojang.blaze3d.textures.GpuTextureView;
15-
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
16-
import it.unimi.dsi.fastutil.objects.ObjectIterator;
1715
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
1816
import lombok.Getter;
1917
import net.minecraft.client.Minecraft;
@@ -22,6 +20,7 @@
2220
import net.minecraft.client.gui.render.TextureSetup;
2321
import net.minecraft.client.gui.render.state.BlitRenderState;
2422
import net.minecraft.client.multiplayer.PlayerInfo;
23+
import net.minecraft.client.player.AbstractClientPlayer;
2524
import net.minecraft.client.player.LocalPlayer;
2625
import net.minecraft.client.renderer.RenderPipelines;
2726
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
@@ -40,13 +39,17 @@
4039
import net.minecraft.world.level.saveddata.maps.MapId;
4140
import net.minecraft.world.level.saveddata.maps.MapItemSavedData;
4241
import net.minecraft.world.phys.Vec3;
42+
import org.apache.logging.log4j.Logger;
4343
import org.joml.Matrix3x2f;
4444
import org.joml.Matrix3x2fStack;
4545

4646
import java.math.BigDecimal;
4747
import java.math.RoundingMode;
48+
import java.util.Collection;
4849
import java.util.Comparator;
50+
import java.util.HashMap;
4951
import java.util.LinkedHashMap;
52+
import java.util.List;
5053
import java.util.Map;
5154
import java.util.NavigableMap;
5255
import java.util.Objects;
@@ -55,8 +58,9 @@
5558

5659
public class DungeonMapManager {
5760

58-
private static final Minecraft MC = Minecraft.getInstance();
5961
private static final SkyblockAddons main = SkyblockAddons.getInstance();
62+
private static final Minecraft MC = Minecraft.getInstance();
63+
private static final Logger LOGGER = SkyblockAddons.getLogger();
6064

6165
public static final float MIN_ZOOM = 0.5F;
6266
public static final float MAX_ZOOM = 5F;
@@ -94,6 +98,7 @@ public class DungeonMapManager {
9498
/** The offset added to the player's z-coordinate when calculating their map marker coordinates */
9599
@Getter private static double markerOffsetZ = 0;
96100
private static final NavigableMap<Long, Vec3> previousLocations = new TreeMap<>();
101+
private static final HashMap<String, PlayerSkinInfo> cachedSkinInfo = new HashMap<>(5);
97102

98103
public static void drawDungeonsMap(GuiGraphics graphics, float scale, ButtonLocation buttonLocation) {
99104
if (buttonLocation == null && !main.getUtils().isInDungeon()) {
@@ -239,7 +244,7 @@ public static void drawDungeonsMap(GuiGraphics graphics, float scale, ButtonLoca
239244
drawMap(graphics, mapData, mapId, isScoreSummary, zoomScaleFactor);
240245
}
241246
} catch (Exception ex) {
242-
ex.printStackTrace();
247+
LOGGER.error(ex);
243248
}
244249
} else {
245250
if (rotate) {
@@ -249,7 +254,6 @@ public static void drawDungeonsMap(GuiGraphics graphics, float scale, ButtonLoca
249254

250255
graphics.blit(RenderPipelines.GUI_TEXTURED, DUNGEON_MAP, 0, 0, 0, 0, 128, 128, 128, 128);
251256
}
252-
// graphics.flush();
253257
graphics.disableScissor();
254258
poseStack.popMatrix();
255259
}
@@ -287,21 +291,17 @@ private static void drawMap(GuiGraphics graphics, MapItemSavedData mapData, MapI
287291
TreeSet<MapMarker> allMarkers = new TreeSet<>(MAP_MARKER_COMPARATOR);
288292

289293
// Grab all the teammates and try to correlate them to the map
290-
Object2ObjectOpenHashMap<String, DungeonPlayer> teammates = main.getDungeonManager().getTeammates();
291-
ObjectIterator<DungeonPlayer> iterator = teammates.values().iterator();
292-
while (MC.level != null) {
293-
DungeonPlayer teammate;
294-
if (iterator.hasNext()) {
295-
teammate = iterator.next();
296-
} else {
297-
teammate = null;
298-
}
299-
294+
HashMap<String, DungeonPlayer> teammates = main.getDungeonManager().getTeammates();
295+
for (AbstractClientPlayer clientPlayer : MC.level.players()) {
296+
DungeonPlayer dungeonTeammate = teammates.get(clientPlayer.getGameProfile().name());
300297
MapMarker playerMarker;
301-
if (teammate != null && MC.level.getPlayerByUUID(teammate.getEntityId()) instanceof Player player) {
302-
playerMarker = getMapMarkerForPlayer(teammate, player);
298+
299+
if (dungeonTeammate != null) {
300+
playerMarker = getMapMarkerForPlayer(dungeonTeammate, clientPlayer);
301+
} else if (clientPlayer == MC.player) {
302+
playerMarker = getMapMarkerForPlayer(null, clientPlayer);
303303
} else {
304-
playerMarker = getMapMarkerForPlayer(null, MC.player);
304+
playerMarker = null;
305305
}
306306

307307
if (playerMarker != null) {
@@ -310,28 +310,35 @@ private static void drawMap(GuiGraphics graphics, MapItemSavedData mapData, MapI
310310
}
311311
allMarkers.add(playerMarker);
312312
}
313-
314-
if (teammate == null) break;
315313
}
316314

317315
// Grab all the map icons to make sure we don't miss any that weren't correlated before
318-
for (Map.Entry<String, MapDecoration> decoration : savedMapDecorations.entrySet()) {
319-
String string = decoration.getKey();
320-
MapDecoration mapDecoration = decoration.getValue();
316+
for (Map.Entry<String, MapDecoration> decorationEntry : savedMapDecorations.entrySet()) {
317+
String decorationName = decorationEntry.getKey();
318+
MapDecoration mapDecoration = decorationEntry.getValue();
319+
321320
// If we replaced this marker with a smooth one OR this is the player's marker, lets skip.
322-
if (dontAddMarkerNames.contains(string) || mapDecoration.type().value() == MapDecorationTypes.FRAME.value()) {
321+
if (dontAddMarkerNames.contains(decorationName) || mapDecoration.type().value() == MapDecorationTypes.FRAME.value()) {
323322
continue;
324323
}
325324

326325
// Check if this marker key is linked to a player
327-
DungeonPlayer foundDungeonPlayer = null;
328326
boolean linkedToPlayer = false;
329327
for (DungeonPlayer dungeonPlayer : teammates.values()) {
330-
if (dungeonPlayer.getMapMarker() != null) {
328+
MapMarker mapMarker = dungeonPlayer.getMapMarker();
329+
330+
if (mapMarker != null) {
331331
String mapMarkerName = dungeonPlayer.getMapMarker().getMapMarkerName();
332-
if (mapMarkerName != null && mapMarkerName.equals(string)) {
332+
if (mapMarkerName != null && mapMarkerName.equals(decorationName)) {
333+
// This marker is linked to a player, lets update that marker's data to the server's
334+
mapMarker.setX(mapDecoration.x());
335+
mapMarker.setY(mapDecoration.y());
336+
mapMarker.setRotation(mapDecoration.rot());
337+
if (mapMarker.getPlayerName() == null) {
338+
mapMarker.setPlayerName(dungeonPlayer.getName());
339+
}
340+
allMarkers.add(mapMarker);
333341
linkedToPlayer = true;
334-
foundDungeonPlayer = dungeonPlayer;
335342
break;
336343
}
337344
}
@@ -342,29 +349,39 @@ private static void drawMap(GuiGraphics graphics, MapItemSavedData mapData, MapI
342349
allMarkers.add(
343350
new MapMarker(mapDecoration.type().value(), mapDecoration.x(), mapDecoration.y(), mapDecoration.rot())
344351
);
345-
} else {
346-
// This marker is linked to a player, lets update that marker's data to the server's
347-
MapMarker mapMarker = foundDungeonPlayer.getMapMarker();
348-
mapMarker.setX(mapDecoration.x());
349-
mapMarker.setY(mapDecoration.y());
350-
mapMarker.setRotation(mapDecoration.rot());
351-
allMarkers.add(mapMarker);
352352
}
353353
}
354354

355355
markerScale = 4.0F / markerScale;
356356

357+
boolean showPlayerHead = Feature.DUNGEONS_MAP_DISPLAY.isEnabled(FeatureSetting.SHOW_PLAYER_HEADS_ON_MAP);
358+
boolean unexpectedSkin;
359+
Collection<PlayerInfo> onlinePlayersInfo;
360+
if (showPlayerHead) {
361+
unexpectedSkin = unexpectedSkin();
362+
onlinePlayersInfo = MC.getConnection().getOnlinePlayers();
363+
} else {
364+
unexpectedSkin = false;
365+
onlinePlayersInfo = List.of();
366+
}
367+
357368
for (MapMarker marker : allMarkers) {
358-
String markerName = marker.getPlayerName();
359-
boolean showPlayerHead = Feature.DUNGEONS_MAP_DISPLAY.isEnabled(FeatureSetting.SHOW_PLAYER_HEADS_ON_MAP);
360-
361-
PlayerInfo markerPlayerInfo = null;
362-
if (showPlayerHead && markerName != null) {
363-
//noinspection DataFlowIssue
364-
for (PlayerInfo playerInfo : MC.getConnection().getOnlinePlayers()) {
365-
if (markerName.equals(playerInfo.getProfile().name())) {
366-
markerPlayerInfo = playerInfo;
367-
break;
369+
String markerPlayerName = marker.getPlayerName();
370+
PlayerSkinInfo markerSkinInfo = null;
371+
372+
if (showPlayerHead && markerPlayerName != null) {
373+
// Try to get the cached value.
374+
markerSkinInfo = cachedSkinInfo.get(markerPlayerName);
375+
// If the cached value does not exist, create it.
376+
if (markerSkinInfo == null || unexpectedSkin) {
377+
for (PlayerInfo playerInfo : onlinePlayersInfo) {
378+
if (markerPlayerName.equals(playerInfo.getProfile().name())) {
379+
markerSkinInfo = cachedSkinInfo.put(
380+
markerPlayerName,
381+
new PlayerSkinInfo(playerInfo.showHat(), playerInfo.getSkin().body().texturePath())
382+
);
383+
break;
384+
}
368385
}
369386
}
370387
}
@@ -374,27 +391,26 @@ private static void drawMap(GuiGraphics graphics, MapItemSavedData mapData, MapI
374391
poseStack.rotate((float) (Math.PI / 180.0) * marker.getRotation() * 360.0F / 16.0F);
375392
poseStack.scale(markerScale, markerScale);
376393

377-
if (markerPlayerInfo != null) {
394+
if (markerSkinInfo != null) {
378395
graphics.guiRenderState.submitGuiElement(
379396
new FillAbsoluteRenderState(RenderPipelines.GUI, TextureSetup.noTexture(), graphics.pose(), -1.2F, -1.2F, 1.2F, 1.2F, 0xFF000000, graphics.scissorStack.peek())
380397
);
381398

382399
int color = -1;
383-
if (Feature.SHOW_CRITICAL_DUNGEONS_TEAMMATES.isEnabled() && teammates.containsKey(markerName)) {
384-
DungeonPlayer dungeonPlayer = teammates.get(markerName);
400+
if (Feature.SHOW_CRITICAL_DUNGEONS_TEAMMATES.isEnabled() && teammates.containsKey(markerPlayerName)) {
401+
DungeonPlayer dungeonPlayer = teammates.get(markerPlayerName);
385402
if (dungeonPlayer.isLow()) {
386403
color = ARGB.colorFromFloat(1F, 1F, 1F, 0.5F);
387404
} else if (dungeonPlayer.isCritical()) {
388405
color = ARGB.colorFromFloat(1F, 1F, 0.5F, 0.5F);
389406
}
390407
}
391408

392-
ResourceLocation skin = markerPlayerInfo.getSkin().body().texturePath();
393409
poseStack.pushMatrix();
394410
poseStack.scale(0.25F, 0.25F);
395-
graphics.blit(RenderPipelines.GUI_TEXTURED, skin, -4, -4, 8.0F, 8, 8, 8, 8, 8, 64, 64, color);
396-
if (markerPlayerInfo.showHat()) {
397-
graphics.blit(RenderPipelines.GUI_TEXTURED, skin, -4, -4, 40.0F, 8, 8, 8, 8, 8, 64, 64, color);
411+
graphics.blit(RenderPipelines.GUI_TEXTURED, markerSkinInfo.bodySkinPath, -4, -4, 8.0F, 8, 8, 8, 8, 8, 64, 64, color);
412+
if (markerSkinInfo.showHat) {
413+
graphics.blit(RenderPipelines.GUI_TEXTURED, markerSkinInfo.bodySkinPath, -4, -4, 40.0F, 8, 8, 8, 8, 8, 64, 64, color);
398414
}
399415
poseStack.popMatrix();
400416
} else {
@@ -408,23 +424,21 @@ private static void drawMap(GuiGraphics graphics, MapItemSavedData mapData, MapI
408424

409425
if (textureAtlasSprite != null) {
410426
GpuTextureView atlasLocation = textureManager.getTexture(textureAtlasSprite.atlasLocation()).getTextureView();
411-
graphics.guiRenderState.submitGuiElement(
412-
new BlitRenderState(
413-
RenderPipelines.GUI_TEXTURED,
414-
TextureSetup.singleTexture(atlasLocation),
415-
new Matrix3x2f(poseStack),
416-
-1,
417-
-1,
418-
1,
419-
1,
420-
textureAtlasSprite.getU0(),
421-
textureAtlasSprite.getU1(),
422-
textureAtlasSprite.getV1(),
423-
textureAtlasSprite.getV0(),
424-
-1,
425-
graphics.scissorStack.peek()
426-
)
427-
);
427+
graphics.guiRenderState.submitGuiElement(new BlitRenderState(
428+
RenderPipelines.GUI_TEXTURED,
429+
TextureSetup.singleTexture(atlasLocation),
430+
new Matrix3x2f(poseStack),
431+
-1,
432+
-1,
433+
1,
434+
1,
435+
textureAtlasSprite.getU0(),
436+
textureAtlasSprite.getU1(),
437+
textureAtlasSprite.getV1(),
438+
textureAtlasSprite.getV0(),
439+
-1,
440+
graphics.scissorStack.peek()
441+
));
428442
}
429443
}
430444
poseStack.popMatrix();
@@ -440,6 +454,9 @@ public static MapMarker getMapMarkerForPlayer(DungeonPlayer dungeonPlayer, Playe
440454
} else {
441455
mapMarker = dungeonPlayer.getMapMarker();
442456
mapMarker.updateXZRot(player);
457+
if (mapMarker.getPlayerName() == null) {
458+
mapMarker.setPlayerName(player.getGameProfile().name());
459+
}
443460
}
444461
} else {
445462
mapMarker = new MapMarker(player);
@@ -537,11 +554,28 @@ public static void setMapZoom(float value) {
537554
main.getConfigValuesManager().saveConfig();
538555
}
539556

557+
public static void clearSkinCache() {
558+
cachedSkinInfo.clear();
559+
}
560+
540561
private static float transformXY(float xy, int widthHeight, float scale) {
541562
float minecraftScale = (float) MC.getWindow().getGuiScale();
542563
xy -= widthHeight / 2F * scale;
543564
xy = Math.round(xy * minecraftScale) / minecraftScale;
544565
return xy / scale;
545566
}
546567

568+
private static boolean unexpectedSkin() {
569+
LocalPlayer player = MC.player;
570+
if (player == null) return true;
571+
572+
PlayerSkinInfo cachedPlayerSkinInfo = cachedSkinInfo.get(player.getGameProfile().name());
573+
if (cachedPlayerSkinInfo == null) return true;
574+
575+
return player.getSkin().body().texturePath() != cachedPlayerSkinInfo.bodySkinPath;
576+
}
577+
578+
private record PlayerSkinInfo(boolean showHat, ResourceLocation bodySkinPath) {
579+
}
580+
547581
}

src/main/java/com/fix3dll/skyblockaddons/features/dungeons/DungeonManager.java

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,12 @@
1414
import com.fix3dll.skyblockaddons.utils.TextUtils;
1515
import com.fix3dll.skyblockaddons.utils.objects.Pair;
1616
import com.mojang.blaze3d.vertex.PoseStack;
17-
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
1817
import lombok.Getter;
1918
import lombok.Setter;
2019
import net.minecraft.client.Minecraft;
2120
import net.minecraft.client.multiplayer.ClientLevel;
2221
import net.minecraft.client.multiplayer.ClientPacketListener;
2322
import net.minecraft.client.multiplayer.PlayerInfo;
24-
import net.minecraft.client.player.AbstractClientPlayer;
2523
import net.minecraft.client.player.LocalPlayer;
2624
import net.minecraft.client.player.RemotePlayer;
2725
import net.minecraft.client.renderer.LightTexture;
@@ -33,12 +31,14 @@
3331
import net.minecraft.network.chat.MutableComponent;
3432
import net.minecraft.resources.ResourceLocation;
3533
import net.minecraft.world.entity.Entity;
34+
import net.minecraft.world.entity.player.Player;
3635
import net.minecraft.world.phys.Vec3;
3736
import org.apache.logging.log4j.Logger;
3837
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
3938

4039
import java.text.ParseException;
4140
import java.util.EnumMap;
41+
import java.util.HashMap;
4242
import java.util.List;
4343
import java.util.function.Function;
4444
import java.util.regex.Matcher;
@@ -80,7 +80,7 @@ public class DungeonManager {
8080
@Getter private final EnumMap<EssenceType, Integer> salvagedEssences = new EnumMap<>(EssenceType.class);
8181

8282
/** The current teammates of the dungeon game */
83-
@Getter private final Object2ObjectOpenHashMap<String, DungeonPlayer> teammates = new Object2ObjectOpenHashMap<>();
83+
@Getter private final HashMap<String, DungeonPlayer> teammates = new HashMap<>(4);
8484

8585
/** The current number of secrets found in the room */
8686
@Getter @Setter private int secrets = -1;
@@ -311,7 +311,7 @@ public void updateDungeonPlayer(String scoreboardLine) {
311311
try {
312312
health = TextUtils.NUMBER_FORMAT.parse(healthText).intValue();
313313
} catch (ParseException ex) {
314-
LOGGER.error("Failed to parse playerEntity "+ name + " health: " + healthText, ex);
314+
LOGGER.error("Failed to parse player '{}' health: {}", name, healthText, ex);
315315
return;
316316
}
317317
}
@@ -329,10 +329,12 @@ public void updateDungeonPlayer(String scoreboardLine) {
329329
}
330330
}
331331

332-
ClientPacketListener networkHandler = MC.getConnection();
333-
if (networkHandler == null) return;
332+
DungeonPlayer computedValue = teammates.computeIfPresent(name, (k, v) ->
333+
new DungeonPlayer(name, dungeonClass, healthColor, health, v.getEntityId())
334+
);
335+
if (computedValue != null) return; // already computed
334336

335-
for (PlayerInfo playerListEntry : networkHandler.getOnlinePlayers()) {
337+
for (PlayerInfo playerListEntry : MC.getConnection().getOnlinePlayers()) {
336338
String profileName = playerListEntry.getProfile().name();
337339

338340
if (profileName.startsWith(name)) {
@@ -425,13 +427,13 @@ public boolean onRenderNameTag(AvatarRenderState state,
425427

426428
if (level != null && main.getUtils().isOnSkyblock() && main.getUtils().isInDungeon() && (criticalOverlayEnabled || nameOverlayEnabled)) {
427429
Entity cameraEntity = MC.getCameraEntity();
428-
AbstractClientPlayer player = null;
430+
Player player = null;
429431
DungeonPlayer dungeonPlayer = null;
430432

431433

432434
for (DungeonPlayer teammate : teammates.values()) {
433435
if (TabStringType.usernameFromLine(nameTag.getString()).equals(teammate.getName())) {
434-
if (level.getEntity(teammate.getEntityId()) instanceof AbstractClientPlayer playerEntity) {
436+
if (level.getEntity(teammate.getEntityId()) instanceof Player playerEntity) {
435437
player = playerEntity;
436438
dungeonPlayer = teammate;
437439
break;

0 commit comments

Comments
 (0)