]> git.lizzy.rs Git - BoundingBoxOutlineReloaded.git/blob - src/main/java/com/irtimaled/bbor/client/providers/BedrockCeilingProvider.java
Setup for 1.15.2-Fabric
[BoundingBoxOutlineReloaded.git] / src / main / java / com / irtimaled / bbor / client / providers / BedrockCeilingProvider.java
1 package com.irtimaled.bbor.client.providers;
2
3 import com.irtimaled.bbor.client.Player;
4 import com.irtimaled.bbor.client.config.BoundingBoxTypeHelper;
5 import com.irtimaled.bbor.client.interop.BedrockCeilingHelper;
6 import com.irtimaled.bbor.client.interop.ClientInterop;
7 import com.irtimaled.bbor.client.models.BoundingBoxBedrockCeiling;
8 import com.irtimaled.bbor.common.BoundingBoxType;
9 import com.irtimaled.bbor.common.MathHelper;
10 import com.irtimaled.bbor.common.models.Coords;
11 import com.irtimaled.bbor.common.models.DimensionId;
12
13 import java.util.*;
14
15 public class BedrockCeilingProvider implements IBoundingBoxProvider<BoundingBoxBedrockCeiling>, ICachingProvider {
16     private static final double CHUNK_SIZE = 16d;
17     private static Long lastGameTime = null;
18     private static final Map<String, BedrockChunk> chunks = new HashMap<>();
19
20     private static class BedrockChunk {
21         private final Set<BoundingBoxBedrockCeiling> boxes = new HashSet<>();
22
23         public BedrockChunk(int chunkX, int chunkZ) {
24             int chunkStartX = chunkX << 4;
25             int chunkStartZ = chunkZ << 4;
26
27             if (BedrockCeilingHelper.chunkLoaded(chunkX, chunkZ)) findBoxesFromBlockState(chunkStartX, chunkStartZ);
28             else findBoxesFromRNG(chunkX, chunkZ, chunkStartX, chunkStartZ);
29         }
30
31         private void findBoxesFromBlockState(int chunkStartX, int chunkStartZ) {
32             for (int x = 0; x < 16; x++) {
33                 for (int z = 0; z < 16; z++) {
34                     Coords coords = getCoordsFromBlockState(chunkStartX + x, chunkStartZ + z);
35                     if (coords != null) {
36                         boxes.add(new BoundingBoxBedrockCeiling(coords));
37                     }
38                 }
39             }
40         }
41
42         private Coords getCoordsFromBlockState(int x, int z) {
43             Coords coords = null;
44             for (int y = 127; y >= 123; y--) {
45                 if (BedrockCeilingHelper.isBedrock(x, y, z)) {
46                     if (coords == null) {
47                         coords = new Coords(x, y, z);
48                     } else {
49                         return null;
50                     }
51                 }
52             }
53             return coords;
54         }
55
56         private void findBoxesFromRNG(int chunkX, int chunkZ, int chunkStartX, int chunkStartZ) {
57             Random random = BedrockCeilingHelper.getRandomForChunk(chunkX, chunkZ);
58
59             // preseed 16x16x3 calls to nextDouble
60             for (int dummy = 0; dummy < 768; dummy++) {
61                 random.nextDouble();
62             }
63             for (int z = 0; z < 16; z++) {
64                 for (int x = 0; x < 16; x++) {
65                     Coords coords = getBlocksFromRNG(random, chunkStartX + x, chunkStartZ + z);
66
67                     if (coords != null) {
68                         boxes.add(new BoundingBoxBedrockCeiling(coords));
69                     }
70                 }
71             }
72         }
73
74         private Coords getBlocksFromRNG(Random random, int x, int z) {
75             int count = 0;
76             for (int y = 127; y >= 123; y--) {
77                 if (y >= 127 - random.nextInt(5)) {
78                     count++;
79                 }
80             }
81             for (int y = 4; y >= 0; y--) {
82                 random.nextInt(5);
83             }
84             return count == 1 ? new Coords(x, 127, z) : null;
85         }
86
87         public Collection<? extends BoundingBoxBedrockCeiling> getBlocks() {
88             return boxes;
89         }
90
91         public void clear() {
92             boxes.clear();
93         }
94     }
95
96     public void clearCache() {
97         chunks.values().forEach(BedrockChunk::clear);
98         chunks.clear();
99     }
100
101     @Override
102     public Iterable<BoundingBoxBedrockCeiling> get(DimensionId dimensionId) {
103         boolean shouldRecalculate = shouldRecalculate();
104
105         int renderDistanceChunks = ClientInterop.getRenderDistanceChunks() / 2;
106         int playerChunkX = MathHelper.floor(Player.getX() / CHUNK_SIZE);
107         int playerChunkZ = MathHelper.floor(Player.getZ() / CHUNK_SIZE);
108
109         Set<BoundingBoxBedrockCeiling> boxes = new HashSet<>();
110
111         for (int chunkX = playerChunkX - renderDistanceChunks; chunkX <= playerChunkX + renderDistanceChunks; chunkX++) {
112             for (int chunkZ = playerChunkZ - renderDistanceChunks; chunkZ <= playerChunkZ + renderDistanceChunks; chunkZ++) {
113                 String key = String.format("%d,%d", chunkX, chunkZ);
114                 if (shouldRecalculate || !chunks.containsKey(key)) {
115                     chunks.put(key, new BedrockChunk(chunkX, chunkZ));
116                 }
117                 BedrockChunk chunk = chunks.get(key);
118                 boxes.addAll(chunk.getBlocks());
119             }
120         }
121         return boxes;
122     }
123
124     public boolean shouldRecalculate() {
125         long gameTime = ClientInterop.getGameTime();
126         if (!((Long) gameTime).equals(lastGameTime) && gameTime % 2L == 0L) {
127             lastGameTime = gameTime;
128             return true;
129         }
130         return false;
131     }
132
133     @Override
134     public boolean canProvide(DimensionId dimensionId) {
135         return dimensionId == DimensionId.NETHER && BoundingBoxTypeHelper.shouldRender(BoundingBoxType.BedrockCeiling) && Player.getY() > 110;
136     }
137 }