4747import lombok .RequiredArgsConstructor ;
4848import lombok .experimental .Accessors ;
4949import lombok .extern .slf4j .Slf4j ;
50- import net .minecraft .Util ;
5150import net .minecraft .client .Minecraft ;
5251import net .minecraft .client .gui .GuiGraphics ;
5352import net .minecraft .client .gui .components .AbstractSliderButton ;
5453import net .minecraft .client .gui .screens .Screen ;
54+ import net .minecraft .client .renderer .BiomeColors ;
5555import net .minecraft .client .renderer .texture .DynamicTexture ;
5656import net .minecraft .core .BlockPos ;
5757import net .minecraft .core .Direction ;
@@ -108,8 +108,27 @@ public void render(GuiGraphics guiGraphics, int mouseX, int mouseY, float partia
108108 for (LazyTile tile : tiles .values ()) {
109109 tile .render (guiGraphics , (float ) playerPos .x (), (float ) playerPos .z (), scale , partialTick , caveY , atSurface );
110110 }
111+ int x = getWorldX (mouseX );
112+ int z = getWorldZ (mouseY );
113+ {
114+ guiGraphics .pose ().pushPose ();
115+ guiGraphics .pose ().translate ((float ) -playerPos .x (), (float ) -playerPos .z (), 0 );
116+ int tileX = x / TILE_SIZE ;
117+ int tileY = z / TILE_SIZE ;
118+ if (x < 0 && x % TILE_SIZE != 0 ) {
119+ tileX -= 1 ;
120+ }
121+ if (z < 0 && z % TILE_SIZE != 0 ) {
122+ tileY -= 1 ;
123+ }
124+ guiGraphics .pose ().translate (tileX * TILE_SIZE , tileY * TILE_SIZE , 0 );
125+ guiGraphics .fill (0 , 0 , TILE_SIZE , TILE_SIZE , 0x33FFFFFF );
126+ guiGraphics .renderOutline (0 , 0 , TILE_SIZE , TILE_SIZE , 0x33FFFFFF );
127+ guiGraphics .pose ().popPose ();
128+ }
111129
112130 guiGraphics .pose ().popPose ();
131+
113132 renderMapWaypoints (guiGraphics , mouseX , mouseY );
114133
115134 guiGraphics .pose ().last ().pose ().rotate ((float ) (((minecraft .player .getVisualRotationYInDegrees () + 180 ) / 180 ) * Math .PI ), 0 , 0 , 1 );
@@ -120,17 +139,19 @@ public void render(GuiGraphics guiGraphics, int mouseX, int mouseY, float partia
120139 guiGraphics .pose ().popPose ();
121140 super .render (guiGraphics , mouseX , mouseY , partialTick );
122141
123- if (mouseX > -1 && mouseY > -1 ) {
124- int x = getWorldX (mouseX );
125- int z = getWorldZ (mouseY );
126- guiGraphics .drawCenteredString (font , AxolotlClientWaypoints .tr ("position" , String .valueOf (x ), String .valueOf (getY (x , z )), String .valueOf (z )), width / 2 , height - 15 , Colors .GRAY .toInt ());
127- }
142+ guiGraphics .drawCenteredString (font , AxolotlClientWaypoints .tr ("position" , String .valueOf (x ), String .valueOf (getY (x , z )), String .valueOf (z )), width / 2 , height - 15 , Colors .GRAY .toInt ());
128143 }
129144
130145 private int getY (int x , int z ) {
131146 int tileX = x / TILE_SIZE ;
132147 int tileY = z / TILE_SIZE ;
133- var tile = tiles .get (new Vector2i (tileX - 1 , tileY - 1 ));
148+ if (x < 0 && x % TILE_SIZE != 0 ) {
149+ tileX -= 1 ;
150+ }
151+ if (z < 0 && z % TILE_SIZE != 0 ) {
152+ tileY -= 1 ;
153+ }
154+ var tile = tiles .get (new Vector2i (tileX , tileY ));
134155 ChunkAccess c ;
135156 if (tile == null || tile .tile == null ) {
136157 c = minecraft .level .getChunk (SectionPos .blockToSectionCoord (x ), SectionPos .blockToSectionCoord (z ), ChunkStatus .FULL , false );
@@ -233,13 +254,11 @@ private void createTiles() {
233254 Map <Vector2i , LazyTile > loadedTiles = new HashMap <>(tiles );
234255 tiles .clear ();
235256 tiles .put (new Vector2i (playerTile .tilePosX (), playerTile .tilePosY ()), playerTile );
236- minecraft .execute (() -> {
237- triggerNeighbourLoad (playerTile , atSurface , caveY , playerTile );
238- loadedTiles .forEach ((v , t ) -> {
239- if (!tiles .containsKey (v )) {
240- tiles .put (v , t );
241- }
242- });
257+ triggerNeighbourLoad (playerTile , atSurface , caveY , playerTile );
258+ loadedTiles .forEach ((v , t ) -> {
259+ if (!tiles .containsKey (v )) {
260+ tiles .put (v , t );
261+ }
243262 });
244263 }
245264 }
@@ -290,32 +309,46 @@ private static LazyTile createTile(Minecraft minecraft, int anchorX, int anchorZ
290309 var level = minecraft .level ;
291310 int tileX = anchorX / TILE_SIZE ;
292311 int tileY = anchorZ / TILE_SIZE ;
312+ if (anchorX < 0 && anchorX % TILE_SIZE != 0 ) {
313+ tileX -= 1 ;
314+ }
315+ if (anchorZ < 0 && anchorZ % TILE_SIZE != 0 ) {
316+ tileY -= 1 ;
317+ }
293318 ChunkAccess tileChunk = level .getChunk (tileX , tileY , ChunkStatus .FULL , false );
294319 if (tileChunk != null ) {
295- return new LazyTile (tileX , tileY , () -> {
296- var t = Tile .create (tileX , tileY , tileChunk );
297- t .update (caveY , atSurface , level );
298- return t ;
299- });
320+ int finalTileX = tileX ;
321+ int finalTileY = tileY ;
322+ return new LazyTile (tileX , tileY , () -> Tile .create (finalTileX , finalTileY , tileChunk ));
300323 }
301324 return null ;
302325 }
303326
304327 public static void saveLoadedChunkTile (ChunkPos pos ) {
305328 Minecraft minecraft = Minecraft .getInstance ();
306- var tile = createTile (minecraft , pos .getMinBlockX (), pos .getMinBlockZ (), true , 0 );
307- if (tile != null ) {
308- tile .load (0 , true )
309- .thenRun (() -> {
310- var dir = getCurrentLevelMapSaveDir ();
311- try {
312- Files .createDirectories (dir );
313-
314- saveTile (tile , dir );
315- } catch (IOException e ) {
316- log .error ("Failed to create world map save dir!" , e );
317- }
318- });
329+ var anchorX = pos .getMinBlockX ();
330+ var anchorZ = pos .getMinBlockZ ();
331+ anchorZ = anchorZ - anchorZ % TILE_SIZE ;
332+ anchorX = anchorX - anchorX % TILE_SIZE ;
333+ var level = minecraft .level ;
334+ int tileX = anchorX / TILE_SIZE ;
335+ int tileY = anchorZ / TILE_SIZE ;
336+ if (anchorX < 0 && anchorX % TILE_SIZE != 0 ) {
337+ tileX -= 1 ;
338+ }
339+ if (anchorZ < 0 && anchorZ % TILE_SIZE != 0 ) {
340+ tileY -= 1 ;
341+ }
342+ ChunkAccess tileChunk = level .getChunk (tileX , tileY , ChunkStatus .FULL , false );
343+ if (tileChunk != null ) {
344+ var dir = getCurrentLevelMapSaveDir ();
345+ var out = dir .resolve ("%d_%d%s" .formatted (tileX , tileY , Tile .FILE_EXTENSION ));
346+ try {
347+ Files .createDirectories (dir );
348+ new LevelChunkStorage .Entry (tileChunk ).write (out );
349+ } catch (IOException e ) {
350+ log .warn ("Failed to save tile at {}, {}" , tileX , tileY , e );
351+ }
319352 }
320353 }
321354
@@ -377,7 +410,7 @@ protected void init() {
377410 btn -> minecraft .setScreen (AxolotlClientWaypoints .createOptionsScreen (this )), AxolotlClientWaypoints .tr ("options" )));
378411 var slider = addRenderableWidget (new AbstractSliderButton (width - 150 , 20 , 150 , 20 , AxolotlClientWaypoints .tr ("player_y" ), 0 ) {
379412 final int min = minecraft .level .getMinBuildHeight ();
380- final int max = minecraft .level .getMaxBuildHeight ()+ 1 ;
413+ final int max = minecraft .level .getMaxBuildHeight () + 1 ;
381414
382415 @ Override
383416 protected void updateMessage () {
@@ -395,7 +428,7 @@ protected void applyValue() {
395428 if (value == 0 || Math .floor ((max - min ) * value ) == 0 ) {
396429 collectPlayerYData ();
397430 }
398- CompletableFuture . runAsync (() -> tiles . values (). forEach ( t -> t . update ( caveY , atSurface , minecraft . level )) );
431+ updateTiles ( );
399432 }
400433 });
401434 addRenderableWidget (new DropdownButton (width - 20 , 0 , 20 , 20 ,
@@ -408,7 +441,7 @@ protected void applyValue() {
408441 slider .active = allowsCaves ;
409442 if (!allowsCaves ) {
410443 atSurface = true ;
411- CompletableFuture . runAsync (() -> tiles . values (). forEach ( t -> t . update ( caveY , atSurface , minecraft . level )) );
444+ updateTiles ( );
412445 } else {
413446 slider .applyValue ();
414447 }
@@ -417,17 +450,21 @@ protected void applyValue() {
417450 AxolotlClientWaypoints .NETWORK_LISTENER .postReceive .add (optionUpdate );
418451 optionUpdate .run ();
419452 if (tiles .isEmpty ()) {
420- minecraft . submit (() -> {
421- if (! initializedOnce ) {
422- collectPlayerYData ();
423- }
453+ if (! initializedOnce ) {
454+ collectPlayerYData ();
455+ }
456+ CompletableFuture . runAsync (() -> {
424457 loadSavedTiles ();
425458 createTiles ();
426459 });
427460 }
428461 initializedOnce = true ;
429462 }
430463
464+ private void updateTiles () {
465+ CompletableFuture .runAsync (() -> tiles .values ().forEach (t -> t .update (caveY , atSurface , minecraft .level )));
466+ }
467+
431468 private void loadSavedTiles () {
432469 var dir = getCurrentLevelMapSaveDir ();
433470 if (Files .exists (dir )) {
@@ -518,7 +555,11 @@ public void render(GuiGraphics guiGraphics, float playerX, float playerZ, float
518555 if (pos .x + TILE_SIZE * scale >= 0 && pos .x < guiGraphics .guiWidth () && pos .y + TILE_SIZE * scale >= 0 && pos .y < guiGraphics .guiHeight ()) {
519556 if (tile == null ) {
520557 if (!loaded ) {
521- load (caveY , atSurface );
558+ load ().thenRunAsync (() -> {
559+ if (tile != null ) {
560+ tile .update (caveY , atSurface , Minecraft .getInstance ().level );
561+ }
562+ });
522563 }
523564 } else {
524565 // FIXME - floating point precision errors?
@@ -528,13 +569,10 @@ public void render(GuiGraphics guiGraphics, float playerX, float playerZ, float
528569 guiGraphics .pose ().popPose ();
529570 }
530571
531- public CompletableFuture <?> load (int caveY , boolean atSurface ) {
572+ public CompletableFuture <?> load () {
532573 if (!loaded ) {
533574 loaded = true ;
534- return Minecraft .getInstance ().submit (supplier ).thenApplyAsync (t -> {
535- t .update (caveY , atSurface , Minecraft .getInstance ().level );
536- return t ;
537- }, Util .backgroundExecutor ()).thenApply (t -> tile = t );
575+ return Minecraft .getInstance ().submit (supplier ).thenApply (t -> tile = t );
538576 }
539577 return CompletableFuture .completedFuture (null );
540578 }
@@ -657,46 +695,34 @@ public void update(int caveY, boolean atSurface, Level level) {
657695 e += y ;
658696 var mapColor = blockState .getMapColor (level , mutableBlockPos );
659697
660- MapColor . Brightness brightness ;
698+ int color ;
661699 if (mapColor == MapColor .WATER ) {
662- double f = fluidDepth * 0.1 + ( x + z & 1 ) * 0.2 ;
663- if ( f < 0.5 ) {
664- brightness = MapColor . Brightness . HIGH ;
665- } else if ( f > 0.9 ) {
666- brightness = MapColor . Brightness . LOW ;
667- } else {
668- brightness = MapColor . Brightness . NORMAL ;
669- }
700+ var floorBlock = levelChunk . getBlockState ( mutableBlockPos2 ) ;
701+ var floorColor = floorBlock . getMapColor ( level , mutableBlockPos2 ). col ;
702+ int biomeColor = BiomeColors . getAverageWaterColor ( level , mutableBlockPos ) ;
703+ float shade = level . getShade ( Direction . UP , true );
704+ int waterColor = biomeColor ;
705+ waterColor = ARGB . colorFromFloat ( 1f , ARGB . redFloat ( waterColor ) * shade , ARGB . greenFloat ( waterColor ) * shade , ARGB . blueFloat ( waterColor ) * shade );
706+ waterColor = ARGB . average ( waterColor , ARGB . scaleRGB ( floorColor , 1f - fluidDepth / 15f )) ;
707+ color = waterColor ;
670708 } else {
671709 double f = (e - d ) * 4.0 / (1 + 4 ) + ((x + z & 1 ) - 0.5 ) * 0.4 ;
710+ MapColor .Brightness brightness ;
672711 if (f > 0.6 ) {
673712 brightness = MapColor .Brightness .HIGH ;
674713 } else if (f < -0.6 ) {
675714 brightness = MapColor .Brightness .LOW ;
676715 } else {
677716 brightness = MapColor .Brightness .NORMAL ;
678717 }
718+ color = mapColor .calculateRGBColor (brightness );
679719 }
680720
681721 d = e ;
682- /*if (Minimap.useTextureSampling.get()) {
683- if (z >= 0 && !blockState.isAir()) {
684- final int fz = z, fx = x;
685- TextureSampler.getSample(blockState, level, mutableBlockPos, brightness).thenAccept(color -> {
686- color = ARGB.opaque(color);
687- if (Integer.rotateRight(pixels.getPixelRGBA(fx, fz), 4) != color) {
688- pixels.setPixelRGBA(fx, fz, Integer.rotateLeft(color, 4));
689- tex.upload();
690- }
691- });
692- }
693- } else*/
694- {
695- int color = mapColor .calculateRGBColor (brightness );
696- if (z >= 0 && Integer .rotateRight (pixels .getPixelRGBA (x , z ), 4 ) != color ) {
697- pixels .setPixelRGBA (x , z , ARGB .opaque (color ));
698- updated = true ;
699- }
722+
723+ if (z >= 0 && Integer .rotateRight (pixels .getPixelRGBA (x , z ), 4 ) != color ) {
724+ pixels .setPixelRGBA (x , z , ARGB .opaque (color ));
725+ updated = true ;
700726 }
701727 }
702728 }
0 commit comments