X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Fmain%2Fjava%2Fcom%2Firtimaled%2Fbbor%2Fclient%2FClientRenderer.java;h=554dcdc064f97d3ed2739751cb1e58d4494d19f7;hb=5e8953ae97badb54c36f66faabda137b3350c57b;hp=11a9ec9afd1c28b8a7b5e8e06e1bf65d11900e7e;hpb=bbec7a251967851d56ea63a46a51e2e36141b40b;p=BoundingBoxOutlineReloaded.git diff --git a/src/main/java/com/irtimaled/bbor/client/ClientRenderer.java b/src/main/java/com/irtimaled/bbor/client/ClientRenderer.java index 11a9ec9..554dcdc 100644 --- a/src/main/java/com/irtimaled/bbor/client/ClientRenderer.java +++ b/src/main/java/com/irtimaled/bbor/client/ClientRenderer.java @@ -1,170 +1,161 @@ package com.irtimaled.bbor.client; -import com.irtimaled.bbor.client.renderers.*; -import com.irtimaled.bbor.common.BoundingBoxCache; -import com.irtimaled.bbor.common.BoundingBoxType; -import com.irtimaled.bbor.common.Dimensions; +import com.irtimaled.bbor.client.interop.ClientInterop; +import com.irtimaled.bbor.client.models.Point; +import com.irtimaled.bbor.client.providers.BeaconProvider; +import com.irtimaled.bbor.client.providers.BedrockCeilingProvider; +import com.irtimaled.bbor.client.providers.BiomeBorderProvider; +import com.irtimaled.bbor.client.providers.ConduitProvider; +import com.irtimaled.bbor.client.providers.CustomBeaconProvider; +import com.irtimaled.bbor.client.providers.CustomBoxProvider; +import com.irtimaled.bbor.client.providers.CustomLineProvider; +import com.irtimaled.bbor.client.providers.CustomSphereProvider; +import com.irtimaled.bbor.client.providers.FlowerForestProvider; +import com.irtimaled.bbor.client.providers.IBoundingBoxProvider; +import com.irtimaled.bbor.client.providers.ICachingProvider; +import com.irtimaled.bbor.client.providers.MobSpawnerProvider; +import com.irtimaled.bbor.client.providers.SlimeChunkProvider; +import com.irtimaled.bbor.client.providers.SpawnableBlocksProvider; +import com.irtimaled.bbor.client.providers.SpawningSphereProvider; +import com.irtimaled.bbor.client.providers.WorldSpawnProvider; +import com.irtimaled.bbor.client.renderers.AbstractRenderer; +import com.irtimaled.bbor.client.renderers.RenderHelper; +import com.irtimaled.bbor.client.renderers.RenderQueue; import com.irtimaled.bbor.common.MathHelper; -import com.irtimaled.bbor.common.models.*; -import com.irtimaled.bbor.config.ConfigManager; -import net.minecraft.client.Minecraft; -import org.lwjgl.opengl.GL11; - -import java.util.*; +import com.irtimaled.bbor.common.TypeHelper; +import com.irtimaled.bbor.common.models.AbstractBoundingBox; +import com.irtimaled.bbor.common.models.DimensionId; +import it.unimi.dsi.fastutil.objects.Object2ObjectMaps; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import net.fabricmc.api.EnvType; +import net.fabricmc.loader.api.FabricLoader; +import net.minecraft.client.util.math.MatrixStack; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.atomic.AtomicLong; +import java.util.function.Supplier; public class ClientRenderer { private static final int CHUNK_SIZE = 16; - private static final Map, AbstractRenderer> boundingBoxRendererMap = new HashMap<>(); - - private final GetCache getCache; - private long seed; - private Set spawnChunkBoundingBoxes = new HashSet<>(); - - ClientRenderer(GetCache getCache) { - this.getCache = getCache; - boundingBoxRendererMap.put(BoundingBoxVillage.class, new VillageRenderer()); - boundingBoxRendererMap.put(BoundingBoxSlimeChunk.class, new SlimeChunkRenderer()); - boundingBoxRendererMap.put(BoundingBoxWorldSpawn.class, new WorldSpawnRenderer()); - boundingBoxRendererMap.put(BoundingBoxStructure.class, new StructureRenderer()); - boundingBoxRendererMap.put(BoundingBoxMobSpawner.class, new MobSpawnerRenderer()); - } - - private boolean isWithinRenderDistance(AbstractBoundingBox boundingBox) { - Coords minCoords = boundingBox.getMinCoords(); - Coords maxCoords = boundingBox.getMaxCoords(); - int renderDistanceBlocks = getRenderDistanceChunks() * CHUNK_SIZE; - int minX = MathHelper.floor(PlayerCoords.getX() - renderDistanceBlocks); - int maxX = MathHelper.floor(PlayerCoords.getX() + renderDistanceBlocks); - int minZ = MathHelper.floor(PlayerCoords.getZ() - renderDistanceBlocks); - int maxZ = MathHelper.floor(PlayerCoords.getZ() + renderDistanceBlocks); - - return maxCoords.getX() >= minX && - maxCoords.getZ() >= minZ && - minCoords.getX() <= maxX && - minCoords.getZ() <= maxZ; - } - - public void render(int dimensionId, Boolean outerBoxesOnly) { - Map> boundingBoxes = getBoundingBoxes(dimensionId); + private static final Map, AbstractRenderer> boundingBoxRendererMap = Object2ObjectMaps.synchronize(new Object2ObjectOpenHashMap<>()); - GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); - GL11.glLineWidth(2.0f); - GL11.glDisable(GL11.GL_TEXTURE_2D); - GL11.glDisable(GL11.GL_CULL_FACE); + private static boolean active; + private static final Set providers = new HashSet<>(); - if (ConfigManager.alwaysVisible.get()) { - GL11.glClear(GL11.GL_DEPTH_BUFFER_BIT); - } - for (Map.Entry> entry : boundingBoxes.entrySet()) { - AbstractBoundingBox key = entry.getKey(); - if (!key.shouldRender()) continue; - - AbstractRenderer renderer = boundingBoxRendererMap.get(key.getClass()); - if (renderer == null) continue; - - if (!outerBoxesOnly) { - Set children = entry.getValue(); - if (children != null) { - children.forEach(renderer::render); - continue; - } - } - renderer.render(key); - } + private static AtomicLong lastDurationNanos = new AtomicLong(0L); - GL11.glPolygonMode(GL11.GL_FRONT_AND_BACK, GL11.GL_FILL); - GL11.glEnable(GL11.GL_CULL_FACE); - GL11.glEnable(GL11.GL_TEXTURE_2D); + public static boolean getActive() { + return active; } - private Map> getBoundingBoxes(int dimensionId) { - Map> boundingBoxes = new HashMap<>(); - if (dimensionId == Dimensions.OVERWORLD) { - if (BoundingBoxType.SlimeChunks.shouldRender()) { - addSlimeChunks(boundingBoxes); - } + public static void toggleActive() { + active = !active; + if (!active) return; - for (AbstractBoundingBox boundingBox : spawnChunkBoundingBoxes) { - if (boundingBox.shouldRender() && isWithinRenderDistance(boundingBox)) { - boundingBoxes.put(boundingBox, null); - } - } - } + Player.setActiveY(); + } - BoundingBoxCache cache = getCache.apply(dimensionId); - if (cache != null) { - for (Map.Entry> entry : cache.getBoundingBoxes().entrySet()) { - AbstractBoundingBox key = entry.getKey(); - if (key.shouldRender() && isWithinRenderDistance(key)) { - boundingBoxes.put(key, entry.getValue()); - } - } - } - return boundingBoxes; + static void deactivate() { + active = false; } - private void addSlimeChunks(Map> boundingBoxes) { - int renderDistanceChunks = getRenderDistanceChunks(); - int playerChunkX = MathHelper.floor(PlayerCoords.getX() / 16.0D); - int playerChunkZ = MathHelper.floor(PlayerCoords.getZ() / 16.0D); - for (int chunkX = playerChunkX - renderDistanceChunks; chunkX <= playerChunkX + renderDistanceChunks; ++chunkX) { - for (int chunkZ = playerChunkZ - renderDistanceChunks; chunkZ <= playerChunkZ + renderDistanceChunks; ++chunkZ) { - if (isSlimeChunk(chunkX, chunkZ)) { - int chunkXStart = chunkX << 4; - int chunkZStart = chunkZ << 4; - Coords minCoords = new Coords(chunkXStart, 1, chunkZStart); - Coords maxCoords = new Coords(chunkXStart + 15, 38, chunkZStart + 15); - boundingBoxes.put(BoundingBoxSlimeChunk.from(minCoords, maxCoords), null); - } - } + static { + if (FabricLoader.getInstance().getEnvironmentType() == EnvType.CLIENT) { + registerProvider(new SlimeChunkProvider()); + registerProvider(new WorldSpawnProvider()); + registerProvider(new SpawningSphereProvider()); + registerProvider(new BeaconProvider()); + registerProvider(new CustomBoxProvider()); + registerProvider(new CustomBeaconProvider()); + registerProvider(new BiomeBorderProvider()); + registerProvider(new MobSpawnerProvider()); + registerProvider(new ConduitProvider()); + registerProvider(new SpawnableBlocksProvider()); + registerProvider(new CustomLineProvider()); + registerProvider(new CustomSphereProvider()); + registerProvider(new FlowerForestProvider()); + registerProvider(new BedrockCeilingProvider()); } } - private int getRenderDistanceChunks() { - return Minecraft.getInstance().gameSettings.renderDistanceChunks; + public static void registerProvider(IBoundingBoxProvider provider) { + providers.add(provider); } - private boolean isSlimeChunk(int chunkX, int chunkZ) { - Random r = new Random(seed + - (long) (chunkX * chunkX * 4987142) + - (long) (chunkX * 5947611) + - (long) (chunkZ * chunkZ) * 4392871L + - (long) (chunkZ * 389711) ^ 987234911L); - return r.nextInt(10) == 0; + public static AbstractRenderer registerRenderer(Class type, Supplier> renderer) { + if (FabricLoader.getInstance().getEnvironmentType() != EnvType.CLIENT) return null; + final AbstractRenderer renderer1 = renderer.get(); + boundingBoxRendererMap.put(type, renderer1); + return renderer1; } - void setWorldData(long seed, int spawnX, int spawnZ) { - this.seed = seed; - spawnChunkBoundingBoxes = getSpawnChunkBoundingBoxes(spawnX, spawnZ); + public static AbstractRenderer getRenderer(Class clazz) { + return boundingBoxRendererMap.get(clazz); } - private Set getSpawnChunkBoundingBoxes(int spawnX, int spawnZ) { - Set boundingBoxes = new HashSet<>(); - boundingBoxes.add(getWorldSpawnBoundingBox(spawnX, spawnZ)); - boundingBoxes.add(buildSpawnChunksBoundingBox(spawnX, spawnZ, 12, BoundingBoxType.SpawnChunks)); - boundingBoxes.add(buildSpawnChunksBoundingBox(spawnX, spawnZ, 16, BoundingBoxType.LazySpawnChunks)); - return boundingBoxes; + private static boolean isWithinRenderDistance(AbstractBoundingBox boundingBox) { + int renderDistanceBlocks = ClientInterop.getRenderDistanceChunks() * CHUNK_SIZE; + int minX = MathHelper.floor(Player.getX() - renderDistanceBlocks); + int maxX = MathHelper.floor(Player.getX() + renderDistanceBlocks); + int minZ = MathHelper.floor(Player.getZ() - renderDistanceBlocks); + int maxZ = MathHelper.floor(Player.getZ() + renderDistanceBlocks); + + return boundingBox.intersectsBounds(minX, minZ, maxX, maxZ); } - private AbstractBoundingBox getWorldSpawnBoundingBox(int spawnX, int spawnZ) { - Coords minCoords = new Coords(spawnX - 10, 0, spawnZ - 10); - Coords maxCoords = new Coords(spawnX + 10, 0, spawnZ + 10); + public static void render(MatrixStack matrixStack, DimensionId dimensionId) { + if (!active) return; - return BoundingBoxWorldSpawn.from(minCoords, maxCoords, BoundingBoxType.WorldSpawn); + long startTime = System.nanoTime(); + matrixStack.push(); + RenderHelper.beforeRender(); + + for (AbstractBoundingBox key : getBoundingBoxes(dimensionId)) { + AbstractRenderer renderer = key.getRenderer(); + if (renderer != null) renderer.render(matrixStack, key); + } + + RenderQueue.renderDeferred(); + + RenderHelper.afterRender(); + matrixStack.pop(); + lastDurationNanos.set(System.nanoTime() - startTime); } - private AbstractBoundingBox buildSpawnChunksBoundingBox(int spawnX, int spawnZ, int size, BoundingBoxType type) { - double midOffset = CHUNK_SIZE * (size / 2.0); - double midX = Math.round((float) (spawnX / (double) CHUNK_SIZE)) * (double) CHUNK_SIZE; - double midZ = Math.round((float) (spawnZ / (double) CHUNK_SIZE)) * (double) CHUNK_SIZE; - Coords maxCoords = new Coords(midX + midOffset, 0, midZ + midOffset); - if ((spawnX / (double) CHUNK_SIZE) % 1.0D == 0.5D) { - midX -= (double) CHUNK_SIZE; + public static List getBoundingBoxes(DimensionId dimensionId) { + List tmp = new LinkedList<>(); + for (IBoundingBoxProvider provider : providers) { + if (provider.canProvide(dimensionId)) { + for (AbstractBoundingBox boundingBox : provider.get(dimensionId)) { + if (boundingBox.isVisibleCulling() && isWithinRenderDistance(boundingBox)) { + tmp.add(boundingBox); + } + } + } } - if ((spawnZ / (double) CHUNK_SIZE) % 1.0D == 0.5D) { - midZ -= (double) CHUNK_SIZE; + + Point point = Player.getPoint(); + final ArrayList result = new ArrayList<>(tmp); + result.sort(Comparator.comparingDouble((AbstractBoundingBox boundingBox) -> boundingBox.getDistance(point.getX(), point.getY(), point.getZ())).reversed()); + + return result; + } + + public static void clear() { + for(IBoundingBoxProvider provider : providers) { + TypeHelper.doIfType(provider, ICachingProvider.class, ICachingProvider::clearCache); } - Coords minCoords = new Coords(midX - midOffset, 0, midZ - midOffset); - return BoundingBoxWorldSpawn.from(minCoords, maxCoords, type); } + + public static long getLastDurationNanos() { + return lastDurationNanos.get(); + } + + }