]> git.lizzy.rs Git - BoundingBoxOutlineReloaded.git/blob - src/main/java/com/irtimaled/bbor/client/ClientRenderer.java
General performance improvements
[BoundingBoxOutlineReloaded.git] / src / main / java / com / irtimaled / bbor / client / ClientRenderer.java
1 package com.irtimaled.bbor.client;
2
3 import com.irtimaled.bbor.client.interop.ClientInterop;
4 import com.irtimaled.bbor.client.models.Point;
5 import com.irtimaled.bbor.client.providers.BeaconProvider;
6 import com.irtimaled.bbor.client.providers.BedrockCeilingProvider;
7 import com.irtimaled.bbor.client.providers.BiomeBorderProvider;
8 import com.irtimaled.bbor.client.providers.ConduitProvider;
9 import com.irtimaled.bbor.client.providers.CustomBeaconProvider;
10 import com.irtimaled.bbor.client.providers.CustomBoxProvider;
11 import com.irtimaled.bbor.client.providers.CustomLineProvider;
12 import com.irtimaled.bbor.client.providers.CustomSphereProvider;
13 import com.irtimaled.bbor.client.providers.FlowerForestProvider;
14 import com.irtimaled.bbor.client.providers.IBoundingBoxProvider;
15 import com.irtimaled.bbor.client.providers.ICachingProvider;
16 import com.irtimaled.bbor.client.providers.MobSpawnerProvider;
17 import com.irtimaled.bbor.client.providers.SlimeChunkProvider;
18 import com.irtimaled.bbor.client.providers.SpawnableBlocksProvider;
19 import com.irtimaled.bbor.client.providers.SpawningSphereProvider;
20 import com.irtimaled.bbor.client.providers.WorldSpawnProvider;
21 import com.irtimaled.bbor.client.renderers.AbstractRenderer;
22 import com.irtimaled.bbor.client.renderers.RenderHelper;
23 import com.irtimaled.bbor.client.renderers.RenderQueue;
24 import com.irtimaled.bbor.common.MathHelper;
25 import com.irtimaled.bbor.common.TypeHelper;
26 import com.irtimaled.bbor.common.models.AbstractBoundingBox;
27 import com.irtimaled.bbor.common.models.DimensionId;
28 import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
29 import net.minecraft.client.util.math.MatrixStack;
30
31 import java.util.ArrayList;
32 import java.util.Comparator;
33 import java.util.HashSet;
34 import java.util.LinkedList;
35 import java.util.List;
36 import java.util.Map;
37 import java.util.Set;
38 import java.util.concurrent.atomic.AtomicLong;
39
40 public class ClientRenderer {
41     private static final int CHUNK_SIZE = 16;
42     private static final Map<Class<? extends AbstractBoundingBox>, AbstractRenderer> boundingBoxRendererMap = new Object2ObjectOpenHashMap<>();
43
44     private static boolean active;
45     private static final Set<IBoundingBoxProvider> providers = new HashSet<>();
46
47     private static AtomicLong lastDurationNanos = new AtomicLong(0L);
48
49     public static boolean getActive() {
50         return active;
51     }
52
53     public static void toggleActive() {
54         active = !active;
55         if (!active) return;
56
57         Player.setActiveY();
58     }
59
60     static void deactivate() {
61         active = false;
62     }
63
64     static {
65
66
67
68
69
70
71
72
73
74         registerProvider(new SlimeChunkProvider());
75         registerProvider(new WorldSpawnProvider());
76         registerProvider(new SpawningSphereProvider());
77         registerProvider(new BeaconProvider());
78         registerProvider(new CustomBoxProvider());
79         registerProvider(new CustomBeaconProvider());
80         registerProvider(new BiomeBorderProvider());
81         registerProvider(new MobSpawnerProvider());
82         registerProvider(new ConduitProvider());
83         registerProvider(new SpawnableBlocksProvider());
84         registerProvider(new CustomLineProvider());
85         registerProvider(new CustomSphereProvider());
86         registerProvider(new FlowerForestProvider());
87         registerProvider(new BedrockCeilingProvider());
88     }
89
90     public static <T extends AbstractBoundingBox> void registerProvider(IBoundingBoxProvider<T> provider) {
91         providers.add(provider);
92     }
93
94     public static <T extends AbstractBoundingBox> AbstractRenderer<T> registerRenderer(Class<? extends T> type, AbstractRenderer<T> renderer) {
95         boundingBoxRendererMap.put(type, renderer);
96         return renderer;
97     }
98
99     public static AbstractRenderer getRenderer(Class<? extends AbstractBoundingBox> clazz) {
100         return boundingBoxRendererMap.get(clazz);
101     }
102
103     private static boolean isWithinRenderDistance(AbstractBoundingBox boundingBox) {
104         int renderDistanceBlocks = ClientInterop.getRenderDistanceChunks() * CHUNK_SIZE;
105         int minX = MathHelper.floor(Player.getX() - renderDistanceBlocks);
106         int maxX = MathHelper.floor(Player.getX() + renderDistanceBlocks);
107         int minZ = MathHelper.floor(Player.getZ() - renderDistanceBlocks);
108         int maxZ = MathHelper.floor(Player.getZ() + renderDistanceBlocks);
109
110         return boundingBox.intersectsBounds(minX, minZ, maxX, maxZ);
111     }
112
113     public static void render(MatrixStack matrixStack, DimensionId dimensionId) {
114         if (!active) return;
115
116         long startTime = System.nanoTime();
117         matrixStack.push();
118         RenderHelper.beforeRender();
119
120         getBoundingBoxes(dimensionId).forEach(key -> {
121             AbstractRenderer renderer = key.getRenderer();
122             if (renderer != null) renderer.render(matrixStack, key);
123         });
124
125         RenderQueue.renderDeferred();
126
127         RenderHelper.afterRender();
128         matrixStack.pop();
129         lastDurationNanos.set(System.nanoTime() - startTime);
130     }
131
132     public static List<AbstractBoundingBox> getBoundingBoxes(DimensionId dimensionId) {
133         List<AbstractBoundingBox> tmp = new LinkedList<>();
134         for (IBoundingBoxProvider<?> provider : providers) {
135             if (provider.canProvide(dimensionId)) {
136                 for (AbstractBoundingBox boundingBox : provider.get(dimensionId)) {
137                     if (isWithinRenderDistance(boundingBox)) {
138                         tmp.add(boundingBox);
139                     }
140                 }
141             }
142         }
143
144         Point point = Player.getPoint();
145         final ArrayList<AbstractBoundingBox> result = new ArrayList<>(tmp);
146         result.sort(Comparator.comparingDouble((AbstractBoundingBox boundingBox) -> boundingBox.getDistance(point.getX(), point.getY(), point.getZ())).reversed());
147
148         return result;
149     }
150
151     public static void clear() {
152         for(IBoundingBoxProvider<?> provider : providers) {
153             TypeHelper.doIfType(provider, ICachingProvider.class, ICachingProvider::clearCache);
154         }
155     }
156
157     public static long getLastDurationNanos() {
158         return lastDurationNanos.get();
159     }
160
161
162 }