1212import com .google .common .collect .Maps ;
1313import com .mojang .blaze3d .pipeline .RenderPipeline ;
1414import com .mojang .blaze3d .textures .GpuTextureView ;
15- import it .unimi .dsi .fastutil .objects .Object2ObjectOpenHashMap ;
16- import it .unimi .dsi .fastutil .objects .ObjectIterator ;
1715import it .unimi .dsi .fastutil .objects .ObjectOpenHashSet ;
1816import lombok .Getter ;
1917import net .minecraft .client .Minecraft ;
2220import net .minecraft .client .gui .render .TextureSetup ;
2321import net .minecraft .client .gui .render .state .BlitRenderState ;
2422import net .minecraft .client .multiplayer .PlayerInfo ;
23+ import net .minecraft .client .player .AbstractClientPlayer ;
2524import net .minecraft .client .player .LocalPlayer ;
2625import net .minecraft .client .renderer .RenderPipelines ;
2726import net .minecraft .client .renderer .texture .TextureAtlasSprite ;
4039import net .minecraft .world .level .saveddata .maps .MapId ;
4140import net .minecraft .world .level .saveddata .maps .MapItemSavedData ;
4241import net .minecraft .world .phys .Vec3 ;
42+ import org .apache .logging .log4j .Logger ;
4343import org .joml .Matrix3x2f ;
4444import org .joml .Matrix3x2fStack ;
4545
4646import java .math .BigDecimal ;
4747import java .math .RoundingMode ;
48+ import java .util .Collection ;
4849import java .util .Comparator ;
50+ import java .util .HashMap ;
4951import java .util .LinkedHashMap ;
52+ import java .util .List ;
5053import java .util .Map ;
5154import java .util .NavigableMap ;
5255import java .util .Objects ;
5558
5659public 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}
0 commit comments