1 package com.irtimaled.bbor.client;
3 import com.irtimaled.bbor.client.interop.ClientInterop;
4 import com.irtimaled.bbor.client.models.BoundingBoxBeacon;
5 import com.irtimaled.bbor.client.models.BoundingBoxBedrockCeiling;
6 import com.irtimaled.bbor.client.models.BoundingBoxBiomeBorder;
7 import com.irtimaled.bbor.client.models.BoundingBoxConduit;
8 import com.irtimaled.bbor.client.models.BoundingBoxFlowerForest;
9 import com.irtimaled.bbor.client.models.BoundingBoxLine;
10 import com.irtimaled.bbor.client.models.BoundingBoxMobSpawner;
11 import com.irtimaled.bbor.client.models.BoundingBoxSlimeChunk;
12 import com.irtimaled.bbor.client.models.BoundingBoxSpawnableBlocks;
13 import com.irtimaled.bbor.client.models.BoundingBoxSpawningSphere;
14 import com.irtimaled.bbor.client.models.BoundingBoxSphere;
15 import com.irtimaled.bbor.client.models.BoundingBoxWorldSpawn;
16 import com.irtimaled.bbor.client.models.Point;
17 import com.irtimaled.bbor.client.providers.BeaconProvider;
18 import com.irtimaled.bbor.client.providers.BedrockCeilingProvider;
19 import com.irtimaled.bbor.client.providers.BiomeBorderProvider;
20 import com.irtimaled.bbor.client.providers.ConduitProvider;
21 import com.irtimaled.bbor.client.providers.CustomBeaconProvider;
22 import com.irtimaled.bbor.client.providers.CustomBoxProvider;
23 import com.irtimaled.bbor.client.providers.CustomLineProvider;
24 import com.irtimaled.bbor.client.providers.CustomSphereProvider;
25 import com.irtimaled.bbor.client.providers.FlowerForestProvider;
26 import com.irtimaled.bbor.client.providers.IBoundingBoxProvider;
27 import com.irtimaled.bbor.client.providers.ICachingProvider;
28 import com.irtimaled.bbor.client.providers.MobSpawnerProvider;
29 import com.irtimaled.bbor.client.providers.SlimeChunkProvider;
30 import com.irtimaled.bbor.client.providers.SpawnableBlocksProvider;
31 import com.irtimaled.bbor.client.providers.SpawningSphereProvider;
32 import com.irtimaled.bbor.client.providers.WorldSpawnProvider;
33 import com.irtimaled.bbor.client.renderers.AbstractRenderer;
34 import com.irtimaled.bbor.client.renderers.BeaconRenderer;
35 import com.irtimaled.bbor.client.renderers.BiomeBorderRenderer;
36 import com.irtimaled.bbor.client.renderers.ConduitRenderer;
37 import com.irtimaled.bbor.client.renderers.CuboidRenderer;
38 import com.irtimaled.bbor.client.renderers.FlowerForestRenderer;
39 import com.irtimaled.bbor.client.renderers.LineRenderer;
40 import com.irtimaled.bbor.client.renderers.MobSpawnerRenderer;
41 import com.irtimaled.bbor.client.renderers.RenderHelper;
42 import com.irtimaled.bbor.client.renderers.RenderQueue;
43 import com.irtimaled.bbor.client.renderers.SlimeChunkRenderer;
44 import com.irtimaled.bbor.client.renderers.SpawnableBlocksRenderer;
45 import com.irtimaled.bbor.client.renderers.SpawningSphereRenderer;
46 import com.irtimaled.bbor.client.renderers.SphereRenderer;
47 import com.irtimaled.bbor.client.renderers.WorldSpawnRenderer;
48 import com.irtimaled.bbor.common.MathHelper;
49 import com.irtimaled.bbor.common.TypeHelper;
50 import com.irtimaled.bbor.common.models.AbstractBoundingBox;
51 import com.irtimaled.bbor.common.models.BoundingBoxCuboid;
52 import com.irtimaled.bbor.common.models.DimensionId;
53 import net.minecraft.client.util.math.MatrixStack;
55 import java.util.Comparator;
56 import java.util.HashMap;
57 import java.util.HashSet;
60 import java.util.concurrent.atomic.AtomicLong;
61 import java.util.stream.Stream;
63 public class ClientRenderer {
64 private static final int CHUNK_SIZE = 16;
65 private static final Map<Class<? extends AbstractBoundingBox>, AbstractRenderer> boundingBoxRendererMap = new HashMap<>();
67 private static boolean active;
68 private static final Set<IBoundingBoxProvider> providers = new HashSet<>();
70 private static AtomicLong lastDurationNanos = new AtomicLong(0L);
72 public static boolean getActive() {
76 public static void toggleActive() {
83 static void deactivate() {
88 registerRenderer(BoundingBoxSlimeChunk.class, new SlimeChunkRenderer());
89 registerRenderer(BoundingBoxWorldSpawn.class, new WorldSpawnRenderer());
90 registerRenderer(BoundingBoxCuboid.class, new CuboidRenderer());
91 registerRenderer(BoundingBoxMobSpawner.class, new MobSpawnerRenderer());
92 registerRenderer(BoundingBoxSpawningSphere.class, new SpawningSphereRenderer());
93 registerRenderer(BoundingBoxBeacon.class, new BeaconRenderer());
94 registerRenderer(BoundingBoxBiomeBorder.class, new BiomeBorderRenderer());
95 registerRenderer(BoundingBoxConduit.class, new ConduitRenderer());
96 registerRenderer(BoundingBoxSpawnableBlocks.class, new SpawnableBlocksRenderer());
97 registerRenderer(BoundingBoxLine.class, new LineRenderer());
98 registerRenderer(BoundingBoxSphere.class, new SphereRenderer());
99 registerRenderer(BoundingBoxFlowerForest.class, new FlowerForestRenderer());
100 registerRenderer(BoundingBoxBedrockCeiling.class, new CuboidRenderer());
102 registerProvider(new SlimeChunkProvider());
103 registerProvider(new WorldSpawnProvider());
104 registerProvider(new SpawningSphereProvider());
105 registerProvider(new BeaconProvider());
106 registerProvider(new CustomBoxProvider());
107 registerProvider(new CustomBeaconProvider());
108 registerProvider(new BiomeBorderProvider());
109 registerProvider(new MobSpawnerProvider());
110 registerProvider(new ConduitProvider());
111 registerProvider(new SpawnableBlocksProvider());
112 registerProvider(new CustomLineProvider());
113 registerProvider(new CustomSphereProvider());
114 registerProvider(new FlowerForestProvider());
115 registerProvider(new BedrockCeilingProvider());
118 public static <T extends AbstractBoundingBox> void registerProvider(IBoundingBoxProvider<T> provider) {
119 providers.add(provider);
122 public static <T extends AbstractBoundingBox> void registerRenderer(Class<? extends T> type, AbstractRenderer<T> renderer) {
123 boundingBoxRendererMap.put(type, renderer);
126 private static boolean isWithinRenderDistance(AbstractBoundingBox boundingBox) {
127 int renderDistanceBlocks = ClientInterop.getRenderDistanceChunks() * CHUNK_SIZE;
128 int minX = MathHelper.floor(Player.getX() - renderDistanceBlocks);
129 int maxX = MathHelper.floor(Player.getX() + renderDistanceBlocks);
130 int minZ = MathHelper.floor(Player.getZ() - renderDistanceBlocks);
131 int maxZ = MathHelper.floor(Player.getZ() + renderDistanceBlocks);
133 return boundingBox.intersectsBounds(minX, minZ, maxX, maxZ);
136 public static void render(MatrixStack matrixStack, DimensionId dimensionId) {
139 long startTime = System.nanoTime();
141 RenderHelper.beforeRender();
143 getBoundingBoxes(dimensionId).forEach(key -> {
144 AbstractRenderer renderer = boundingBoxRendererMap.get(key.getClass());
145 if (renderer != null) renderer.render(matrixStack, key);
148 RenderQueue.renderDeferred();
150 RenderHelper.afterRender();
152 lastDurationNanos.set(System.nanoTime() - startTime);
155 public static Stream<AbstractBoundingBox> getBoundingBoxes(DimensionId dimensionId) {
156 Stream.Builder<AbstractBoundingBox> boundingBoxes = Stream.builder();
157 for (IBoundingBoxProvider<?> provider : providers) {
158 if (provider.canProvide(dimensionId)) {
159 for (AbstractBoundingBox boundingBox : provider.get(dimensionId)) {
160 if (isWithinRenderDistance(boundingBox)) {
161 boundingBoxes.accept(boundingBox);
167 Point point = Player.getPoint();
168 return boundingBoxes.build()
170 .comparingDouble((AbstractBoundingBox boundingBox) -> boundingBox.getDistance(point.getX(), point.getY(), point.getZ())).reversed());
173 public static void clear() {
174 for(IBoundingBoxProvider<?> provider : providers) {
175 TypeHelper.doIfType(provider, ICachingProvider.class, ICachingProvider::clearCache);
179 public static long getLastDurationNanos() {
180 return lastDurationNanos.get();