22
33import com .irtimaled .bbor .client .renderers .*;
44import com .irtimaled .bbor .common .BoundingBoxCache ;
5+ import com .irtimaled .bbor .common .BoundingBoxType ;
56import com .irtimaled .bbor .common .models .*;
67import com .irtimaled .bbor .config .ConfigManager ;
78import net .minecraft .client .Minecraft ;
89import net .minecraft .util .math .BlockPos ;
10+ import net .minecraft .util .math .ChunkPos ;
911import net .minecraft .util .math .MathHelper ;
1012import net .minecraft .world .dimension .DimensionType ;
1113import org .lwjgl .opengl .GL11 ;
1214
13- import java .util .HashMap ;
14- import java .util .Map ;
15- import java .util .Set ;
15+ import java .util .*;
1616
1717import static com .irtimaled .bbor .client .Constants .CHUNK_SIZE ;
1818
1919public class ClientRenderer {
2020 private final GetCache getCache ;
2121 private static final Map <Class <? extends BoundingBox >, Renderer > boundingBoxRendererMap = new HashMap <>();
22+ private long seed ;
23+ private Set <BoundingBox > spawnChunkBoundingBoxes = new HashSet <>();
2224
2325 ClientRenderer (GetCache getCache ) {
2426 this .getCache = getCache ;
@@ -42,9 +44,12 @@ private boolean isWithinRenderDistance(BlockPos minBlockPos, BlockPos maxBlockPo
4244 minBlockPos .getZ () <= maxZ ;
4345 }
4446
47+ private boolean isWithinRenderDistance (BoundingBox boundingBox ) {
48+ return isWithinRenderDistance (boundingBox .getMinBlockPos (), boundingBox .getMaxBlockPos ());
49+ }
50+
4551 public void render (DimensionType dimensionType , Boolean outerBoxesOnly ) {
46- BoundingBoxCache cache = getCache .apply (dimensionType );
47- if (cache == null ) return ;
52+ Map <BoundingBox , Set <BoundingBox >> boundingBoxes = getBoundingBoxes (dimensionType );
4853
4954 GL11 .glBlendFunc (GL11 .GL_SRC_ALPHA , GL11 .GL_ONE_MINUS_SRC_ALPHA );
5055 GL11 .glLineWidth (2.0f );
@@ -54,17 +59,17 @@ public void render(DimensionType dimensionType, Boolean outerBoxesOnly) {
5459 if (ConfigManager .alwaysVisible .get ()) {
5560 GL11 .glClear (GL11 .GL_DEPTH_BUFFER_BIT );
5661 }
57- for (Map .Entry <BoundingBox , Set <BoundingBox >> entry : cache . getBoundingBoxes () .entrySet ()) {
62+ for (Map .Entry <BoundingBox , Set <BoundingBox >> entry : boundingBoxes .entrySet ()) {
5863 BoundingBox key = entry .getKey ();
59- if (!key .shouldRender () || ! isWithinRenderDistance ( key . getMinBlockPos (), key . getMaxBlockPos ()) ) continue ;
64+ if (!key .shouldRender ()) continue ;
6065
6166 Renderer renderer = boundingBoxRendererMap .get (key .getClass ());
6267 if (renderer == null ) continue ;
6368
6469 if (!outerBoxesOnly ) {
65- Set <BoundingBox > boundingBoxes = entry .getValue ();
66- if (boundingBoxes != null ) {
67- boundingBoxes .forEach (renderer ::render );
70+ Set <BoundingBox > children = entry .getValue ();
71+ if (children != null ) {
72+ children .forEach (renderer ::render );
6873 continue ;
6974 }
7075 }
@@ -75,4 +80,89 @@ public void render(DimensionType dimensionType, Boolean outerBoxesOnly) {
7580 GL11 .glEnable (GL11 .GL_CULL_FACE );
7681 GL11 .glEnable (GL11 .GL_TEXTURE_2D );
7782 }
83+
84+ private Map <BoundingBox , Set <BoundingBox >> getBoundingBoxes (DimensionType dimensionType ) {
85+ Map <BoundingBox , Set <BoundingBox >> boundingBoxes = new HashMap <>();
86+ if (dimensionType == DimensionType .OVERWORLD ) {
87+ if (BoundingBoxType .SlimeChunks .shouldRender ()) {
88+ addSlimeChunks (boundingBoxes );
89+ }
90+
91+ for (BoundingBox boundingBox : spawnChunkBoundingBoxes ) {
92+ if (boundingBox .shouldRender () && isWithinRenderDistance (boundingBox )) {
93+ boundingBoxes .put (boundingBox , null );
94+ }
95+ }
96+ }
97+
98+ BoundingBoxCache cache = getCache .apply (dimensionType );
99+ if (cache != null ) {
100+ for (Map .Entry <BoundingBox , Set <BoundingBox >> entry : cache .getBoundingBoxes ().entrySet ()) {
101+ BoundingBox key = entry .getKey ();
102+ if (key .shouldRender () && isWithinRenderDistance (key )) {
103+ boundingBoxes .put (key , entry .getValue ());
104+ }
105+ }
106+ }
107+ return boundingBoxes ;
108+ }
109+
110+ private void addSlimeChunks (Map <BoundingBox , Set <BoundingBox >> boundingBoxes ) {
111+ Minecraft minecraft = Minecraft .getInstance ();
112+ int renderDistanceChunks = minecraft .gameSettings .renderDistanceChunks ;
113+ int playerChunkX = MathHelper .floor (PlayerData .getX () / 16.0D );
114+ int playerChunkZ = MathHelper .floor (PlayerData .getZ () / 16.0D );
115+ for (int chunkX = playerChunkX - renderDistanceChunks ; chunkX <= playerChunkX + renderDistanceChunks ; ++chunkX ) {
116+ for (int chunkZ = playerChunkZ - renderDistanceChunks ; chunkZ <= playerChunkZ + renderDistanceChunks ; ++chunkZ ) {
117+ if (isSlimeChunk (chunkX , chunkZ )) {
118+ ChunkPos chunk = new ChunkPos (chunkX , chunkZ );
119+ BlockPos minBlockPos = new BlockPos (chunk .getXStart (), 1 , chunk .getZStart ());
120+ BlockPos maxBlockPos = new BlockPos (chunk .getXEnd (), 38 , chunk .getZEnd ());
121+ boundingBoxes .put (BoundingBoxSlimeChunk .from (minBlockPos , maxBlockPos ), null );
122+ }
123+ }
124+ }
125+ }
126+
127+ private boolean isSlimeChunk (int chunkX , int chunkZ ) {
128+ Random r = new Random (seed +
129+ (long ) (chunkX * chunkX * 4987142 ) +
130+ (long ) (chunkX * 5947611 ) +
131+ (long ) (chunkZ * chunkZ ) * 4392871L +
132+ (long ) (chunkZ * 389711 ) ^ 987234911L );
133+ return r .nextInt (10 ) == 0 ;
134+ }
135+
136+ void setWorldData (long seed , int spawnX , int spawnZ ) {
137+ this .seed = seed ;
138+ spawnChunkBoundingBoxes = getSpawnChunkBoundingBoxes (spawnX , spawnZ );
139+ }
140+
141+ private Set <BoundingBox > getSpawnChunkBoundingBoxes (int spawnX , int spawnZ ) {
142+ Set <BoundingBox > boundingBoxes = new HashSet <>();
143+ boundingBoxes .add (getWorldSpawnBoundingBox (spawnX , spawnZ ));
144+ boundingBoxes .add (buildSpawnChunksBoundingBox (spawnX , spawnZ , 12 , BoundingBoxType .SpawnChunks ));
145+ boundingBoxes .add (buildSpawnChunksBoundingBox (spawnX , spawnZ , 16 , BoundingBoxType .LazySpawnChunks ));
146+ return boundingBoxes ;
147+ }
148+
149+ private BoundingBox getWorldSpawnBoundingBox (int spawnX , int spawnZ ) {
150+ BlockPos minBlockPos = new BlockPos (spawnX - 10 , 0 , spawnZ - 10 );
151+ BlockPos maxBlockPos = new BlockPos (spawnX + 10 , 0 , spawnZ + 10 );
152+
153+ return BoundingBoxWorldSpawn .from (minBlockPos , maxBlockPos , BoundingBoxType .WorldSpawn );
154+ }
155+
156+ private BoundingBox buildSpawnChunksBoundingBox (int spawnX , int spawnZ , int size , BoundingBoxType type ) {
157+ double midOffset = CHUNK_SIZE * (size / 2.0 );
158+ double midX = Math .round ((float ) (spawnX / (double ) CHUNK_SIZE )) * (double ) CHUNK_SIZE ;
159+ double midZ = Math .round ((float ) (spawnZ / (double ) CHUNK_SIZE )) * (double ) CHUNK_SIZE ;
160+ BlockPos minBlockPos = new BlockPos (midX - midOffset , 0 , midZ - midOffset );
161+ if (spawnX / (double ) CHUNK_SIZE % 0.5D == 0.0D && spawnZ / (double ) CHUNK_SIZE % 0.5D == 0.0D ) {
162+ midX += (double ) CHUNK_SIZE ;
163+ midZ += (double ) CHUNK_SIZE ;
164+ }
165+ BlockPos maxBlockPos = new BlockPos (midX + midOffset , 0 , midZ + midOffset );
166+ return BoundingBoxWorldSpawn .from (minBlockPos , maxBlockPos , type );
167+ }
78168}
0 commit comments