/* * Decompiled with CFR 0.152. * * Could not load the following classes: * org.joml.Matrix4f * org.joml.Matrix4fc * org.joml.Vector3f * org.joml.Vector3fc * org.joml.Vector4f * org.joml.Vector4fc */ package net.minecraft.client.renderer; import com.mojang.blaze3d.buffers.GpuBuffer; import com.mojang.blaze3d.buffers.GpuBufferSlice; import com.mojang.blaze3d.pipeline.RenderPipeline; import com.mojang.blaze3d.pipeline.RenderTarget; import com.mojang.blaze3d.systems.RenderPass; import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.textures.GpuTextureView; import com.mojang.blaze3d.vertex.BufferBuilder; import com.mojang.blaze3d.vertex.ByteBufferBuilder; import com.mojang.blaze3d.vertex.DefaultVertexFormat; import com.mojang.blaze3d.vertex.MeshData; import com.mojang.blaze3d.vertex.VertexFormat; import java.util.ArrayList; import java.util.Collections; import java.util.OptionalDouble; import java.util.OptionalInt; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.RenderPipelines; import net.minecraft.client.renderer.state.WorldBorderRenderState; import net.minecraft.client.renderer.texture.AbstractTexture; import net.minecraft.client.renderer.texture.TextureManager; import net.minecraft.resources.Identifier; import net.minecraft.util.ARGB; import net.minecraft.util.Mth; import net.minecraft.util.Util; import net.minecraft.world.level.border.WorldBorder; import net.minecraft.world.phys.Vec3; import org.joml.Matrix4f; import org.joml.Matrix4fc; import org.joml.Vector3f; import org.joml.Vector3fc; import org.joml.Vector4f; import org.joml.Vector4fc; public class WorldBorderRenderer { public static final Identifier FORCEFIELD_LOCATION = Identifier.withDefaultNamespace("textures/misc/forcefield.png"); private boolean needsRebuild = true; private double lastMinX; private double lastMinZ; private double lastBorderMinX; private double lastBorderMaxX; private double lastBorderMinZ; private double lastBorderMaxZ; private final GpuBuffer worldBorderBuffer = RenderSystem.getDevice().createBuffer(() -> "World border vertex buffer", 40, 16 * DefaultVertexFormat.POSITION_TEX.getVertexSize()); private final RenderSystem.AutoStorageIndexBuffer indices = RenderSystem.getSequentialBuffer(VertexFormat.Mode.QUADS); private void rebuildWorldBorderBuffer(WorldBorderRenderState state, double renderDistance, double cameraZ, double cameraX, float halfHeightY, float v1, float v0) { try (ByteBufferBuilder byteBufferBuilder = ByteBufferBuilder.exactlySized(DefaultVertexFormat.POSITION_TEX.getVertexSize() * 4 * 4);){ double borderMinX = state.minX; double borderMaxX = state.maxX; double borderMinZ = state.minZ; double borderMaxZ = state.maxZ; double minZ = Math.max((double)Mth.floor(cameraZ - renderDistance), borderMinZ); double maxZ = Math.min((double)Mth.ceil(cameraZ + renderDistance), borderMaxZ); float u0z = (float)(Mth.floor(minZ) & 1) * 0.5f; float u1z = (float)(maxZ - minZ) / 2.0f; double minX = Math.max((double)Mth.floor(cameraX - renderDistance), borderMinX); double maxX = Math.min((double)Mth.ceil(cameraX + renderDistance), borderMaxX); float u0x = (float)(Mth.floor(minX) & 1) * 0.5f; float u1x = (float)(maxX - minX) / 2.0f; BufferBuilder bufferBuilder = new BufferBuilder(byteBufferBuilder, VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_TEX); bufferBuilder.addVertex(0.0f, -halfHeightY, (float)(borderMaxZ - minZ)).setUv(u0x, v1); bufferBuilder.addVertex((float)(maxX - minX), -halfHeightY, (float)(borderMaxZ - minZ)).setUv(u1x + u0x, v1); bufferBuilder.addVertex((float)(maxX - minX), halfHeightY, (float)(borderMaxZ - minZ)).setUv(u1x + u0x, v0); bufferBuilder.addVertex(0.0f, halfHeightY, (float)(borderMaxZ - minZ)).setUv(u0x, v0); bufferBuilder.addVertex(0.0f, -halfHeightY, 0.0f).setUv(u0z, v1); bufferBuilder.addVertex(0.0f, -halfHeightY, (float)(maxZ - minZ)).setUv(u1z + u0z, v1); bufferBuilder.addVertex(0.0f, halfHeightY, (float)(maxZ - minZ)).setUv(u1z + u0z, v0); bufferBuilder.addVertex(0.0f, halfHeightY, 0.0f).setUv(u0z, v0); bufferBuilder.addVertex((float)(maxX - minX), -halfHeightY, 0.0f).setUv(u0x, v1); bufferBuilder.addVertex(0.0f, -halfHeightY, 0.0f).setUv(u1x + u0x, v1); bufferBuilder.addVertex(0.0f, halfHeightY, 0.0f).setUv(u1x + u0x, v0); bufferBuilder.addVertex((float)(maxX - minX), halfHeightY, 0.0f).setUv(u0x, v0); bufferBuilder.addVertex((float)(borderMaxX - minX), -halfHeightY, (float)(maxZ - minZ)).setUv(u0z, v1); bufferBuilder.addVertex((float)(borderMaxX - minX), -halfHeightY, 0.0f).setUv(u1z + u0z, v1); bufferBuilder.addVertex((float)(borderMaxX - minX), halfHeightY, 0.0f).setUv(u1z + u0z, v0); bufferBuilder.addVertex((float)(borderMaxX - minX), halfHeightY, (float)(maxZ - minZ)).setUv(u0z, v0); try (MeshData meshData = bufferBuilder.buildOrThrow();){ RenderSystem.getDevice().createCommandEncoder().writeToBuffer(this.worldBorderBuffer.slice(), meshData.vertexBuffer()); } this.lastBorderMinX = borderMinX; this.lastBorderMaxX = borderMaxX; this.lastBorderMinZ = borderMinZ; this.lastBorderMaxZ = borderMaxZ; this.lastMinX = minX; this.lastMinZ = minZ; this.needsRebuild = false; } } public void extract(WorldBorder border, float deltaPartialTick, Vec3 cameraPos, double renderDistance, WorldBorderRenderState state) { state.minX = border.getMinX(deltaPartialTick); state.maxX = border.getMaxX(deltaPartialTick); state.minZ = border.getMinZ(deltaPartialTick); state.maxZ = border.getMaxZ(deltaPartialTick); if (cameraPos.x < state.maxX - renderDistance && cameraPos.x > state.minX + renderDistance && cameraPos.z < state.maxZ - renderDistance && cameraPos.z > state.minZ + renderDistance || cameraPos.x < state.minX - renderDistance || cameraPos.x > state.maxX + renderDistance || cameraPos.z < state.minZ - renderDistance || cameraPos.z > state.maxZ + renderDistance) { state.alpha = 0.0; return; } state.alpha = 1.0 - border.getDistanceToBorder(cameraPos.x, cameraPos.z) / renderDistance; state.alpha = Math.pow(state.alpha, 4.0); state.alpha = Mth.clamp(state.alpha, 0.0, 1.0); state.tint = border.getStatus().getColor(); } public void render(WorldBorderRenderState state, Vec3 cameraPos, double renderDistance, double depthFar) { GpuTextureView depthTexture; GpuTextureView colorTexture; if (state.alpha <= 0.0) { return; } double cameraX = cameraPos.x; double cameraZ = cameraPos.z; float halfHeightY = (float)depthFar; float red = (float)ARGB.red(state.tint) / 255.0f; float green = (float)ARGB.green(state.tint) / 255.0f; float blue = (float)ARGB.blue(state.tint) / 255.0f; float offset = (float)(Util.getMillis() % 3000L) / 3000.0f; float v0 = (float)(-Mth.frac(cameraPos.y * 0.5)); float v1 = v0 + halfHeightY; if (this.shouldRebuildWorldBorderBuffer(state)) { this.rebuildWorldBorderBuffer(state, renderDistance, cameraZ, cameraX, halfHeightY, v1, v0); } TextureManager textureManager = Minecraft.getInstance().getTextureManager(); AbstractTexture abstractTexture = textureManager.getTexture(FORCEFIELD_LOCATION); RenderPipeline renderPipeline = RenderPipelines.WORLD_BORDER; RenderTarget mainRenderTarget = Minecraft.getInstance().getMainRenderTarget(); RenderTarget weatherTarget = Minecraft.getInstance().levelRenderer.getWeatherTarget(); if (weatherTarget != null) { colorTexture = weatherTarget.getColorTextureView(); depthTexture = weatherTarget.getDepthTextureView(); } else { colorTexture = mainRenderTarget.getColorTextureView(); depthTexture = mainRenderTarget.getDepthTextureView(); } GpuBuffer indexBuffer = this.indices.getBuffer(6); GpuBufferSlice dynamicTransforms = RenderSystem.getDynamicUniforms().writeTransform((Matrix4fc)RenderSystem.getModelViewMatrix(), (Vector4fc)new Vector4f(red, green, blue, (float)state.alpha), (Vector3fc)new Vector3f((float)(this.lastMinX - cameraX), (float)(-cameraPos.y), (float)(this.lastMinZ - cameraZ)), (Matrix4fc)new Matrix4f().translation(offset, offset, 0.0f)); try (RenderPass renderPass = RenderSystem.getDevice().createCommandEncoder().createRenderPass(() -> "World border", colorTexture, OptionalInt.empty(), depthTexture, OptionalDouble.empty());){ renderPass.setPipeline(renderPipeline); RenderSystem.bindDefaultUniforms(renderPass); renderPass.setUniform("DynamicTransforms", dynamicTransforms); renderPass.setIndexBuffer(indexBuffer, this.indices.type()); renderPass.bindTexture("Sampler0", abstractTexture.getTextureView(), abstractTexture.getSampler()); renderPass.setVertexBuffer(0, this.worldBorderBuffer); ArrayList draws = new ArrayList(); for (WorldBorderRenderState.DistancePerDirection distancePerDirection : state.closestBorder(cameraX, cameraZ)) { if (!(distancePerDirection.distance() < renderDistance)) continue; int sideIndex = distancePerDirection.direction().get2DDataValue(); draws.add(new RenderPass.Draw(0, this.worldBorderBuffer, indexBuffer, this.indices.type(), 6 * sideIndex, 6)); } renderPass.drawMultipleIndexed(draws, null, null, Collections.emptyList(), this); } } public void invalidate() { this.needsRebuild = true; } private boolean shouldRebuildWorldBorderBuffer(WorldBorderRenderState state) { return this.needsRebuild || state.minX != this.lastBorderMinX || state.minZ != this.lastBorderMinZ || state.maxX != this.lastBorderMaxX || state.maxZ != this.lastBorderMaxZ; } }