3151 lines
132 KiB
Java
3151 lines
132 KiB
Java
package net.minecraft.client.renderer;
|
|
|
|
import com.google.common.collect.Lists;
|
|
import com.google.common.collect.Maps;
|
|
import com.google.common.collect.Sets;
|
|
import com.google.gson.JsonSyntaxException;
|
|
import com.mojang.blaze3d.pipeline.RenderTarget;
|
|
import com.mojang.blaze3d.platform.GlStateManager;
|
|
import com.mojang.blaze3d.platform.Lighting;
|
|
import com.mojang.blaze3d.shaders.Uniform;
|
|
import com.mojang.blaze3d.systems.RenderSystem;
|
|
import com.mojang.blaze3d.vertex.BufferBuilder;
|
|
import com.mojang.blaze3d.vertex.BufferUploader;
|
|
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
|
|
import com.mojang.blaze3d.vertex.MeshData;
|
|
import com.mojang.blaze3d.vertex.PoseStack;
|
|
import com.mojang.blaze3d.vertex.SheetedDecalTextureGenerator;
|
|
import com.mojang.blaze3d.vertex.Tesselator;
|
|
import com.mojang.blaze3d.vertex.VertexBuffer;
|
|
import com.mojang.blaze3d.vertex.VertexConsumer;
|
|
import com.mojang.blaze3d.vertex.VertexFormat;
|
|
import com.mojang.blaze3d.vertex.VertexMultiConsumer;
|
|
import com.mojang.logging.LogUtils;
|
|
import com.mojang.math.Axis;
|
|
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
|
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
|
import it.unimi.dsi.fastutil.longs.Long2ObjectFunction;
|
|
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
|
|
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
|
|
import it.unimi.dsi.fastutil.longs.Long2ObjectMap.Entry;
|
|
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
|
import it.unimi.dsi.fastutil.objects.ObjectListIterator;
|
|
import java.io.IOException;
|
|
import java.util.Collection;
|
|
import java.util.Iterator;
|
|
import java.util.List;
|
|
import java.util.Locale;
|
|
import java.util.Map;
|
|
import java.util.Set;
|
|
import java.util.SortedSet;
|
|
import java.util.function.Supplier;
|
|
import net.fabricmc.api.EnvType;
|
|
import net.fabricmc.api.Environment;
|
|
import net.minecraft.CrashReport;
|
|
import net.minecraft.CrashReportCategory;
|
|
import net.minecraft.CrashReportDetail;
|
|
import net.minecraft.ReportedException;
|
|
import net.minecraft.Util;
|
|
import net.minecraft.client.Camera;
|
|
import net.minecraft.client.CloudStatus;
|
|
import net.minecraft.client.DeltaTracker;
|
|
import net.minecraft.client.GraphicsStatus;
|
|
import net.minecraft.client.Minecraft;
|
|
import net.minecraft.client.ParticleStatus;
|
|
import net.minecraft.client.PrioritizeChunkUpdates;
|
|
import net.minecraft.client.multiplayer.ClientLevel;
|
|
import net.minecraft.client.particle.Particle;
|
|
import net.minecraft.client.player.LocalPlayer;
|
|
import net.minecraft.client.renderer.blockentity.BlockEntityRenderDispatcher;
|
|
import net.minecraft.client.renderer.chunk.RenderRegionCache;
|
|
import net.minecraft.client.renderer.chunk.SectionRenderDispatcher;
|
|
import net.minecraft.client.renderer.culling.Frustum;
|
|
import net.minecraft.client.renderer.entity.EntityRenderDispatcher;
|
|
import net.minecraft.client.renderer.texture.TextureAtlas;
|
|
import net.minecraft.client.resources.model.ModelBakery;
|
|
import net.minecraft.client.resources.sounds.SimpleSoundInstance;
|
|
import net.minecraft.client.resources.sounds.SoundInstance;
|
|
import net.minecraft.core.BlockPos;
|
|
import net.minecraft.core.Direction;
|
|
import net.minecraft.core.Holder;
|
|
import net.minecraft.core.SectionPos;
|
|
import net.minecraft.core.particles.ItemParticleOption;
|
|
import net.minecraft.core.particles.ParticleOptions;
|
|
import net.minecraft.core.particles.ParticleTypes;
|
|
import net.minecraft.core.particles.SculkChargeParticleOptions;
|
|
import net.minecraft.core.particles.ShriekParticleOption;
|
|
import net.minecraft.core.particles.SimpleParticleType;
|
|
import net.minecraft.core.registries.BuiltInRegistries;
|
|
import net.minecraft.core.registries.Registries;
|
|
import net.minecraft.nbt.NbtOps;
|
|
import net.minecraft.network.chat.Component;
|
|
import net.minecraft.resources.ResourceLocation;
|
|
import net.minecraft.server.level.BlockDestructionProgress;
|
|
import net.minecraft.server.packs.resources.ResourceManager;
|
|
import net.minecraft.server.packs.resources.ResourceManagerReloadListener;
|
|
import net.minecraft.sounds.SoundEvent;
|
|
import net.minecraft.sounds.SoundEvents;
|
|
import net.minecraft.sounds.SoundSource;
|
|
import net.minecraft.tags.FluidTags;
|
|
import net.minecraft.util.FastColor;
|
|
import net.minecraft.util.Mth;
|
|
import net.minecraft.util.ParticleUtils;
|
|
import net.minecraft.util.RandomSource;
|
|
import net.minecraft.util.profiling.ProfilerFiller;
|
|
import net.minecraft.util.valueproviders.IntProvider;
|
|
import net.minecraft.util.valueproviders.UniformInt;
|
|
import net.minecraft.world.TickRateManager;
|
|
import net.minecraft.world.effect.MobEffects;
|
|
import net.minecraft.world.entity.Entity;
|
|
import net.minecraft.world.entity.LivingEntity;
|
|
import net.minecraft.world.item.BoneMealItem;
|
|
import net.minecraft.world.item.ItemStack;
|
|
import net.minecraft.world.item.Items;
|
|
import net.minecraft.world.item.JukeboxSong;
|
|
import net.minecraft.world.level.BlockAndTintGetter;
|
|
import net.minecraft.world.level.BlockGetter;
|
|
import net.minecraft.world.level.ChunkPos;
|
|
import net.minecraft.world.level.Level;
|
|
import net.minecraft.world.level.LevelReader;
|
|
import net.minecraft.world.level.LightLayer;
|
|
import net.minecraft.world.level.biome.Biome;
|
|
import net.minecraft.world.level.block.Block;
|
|
import net.minecraft.world.level.block.Blocks;
|
|
import net.minecraft.world.level.block.BrushableBlock;
|
|
import net.minecraft.world.level.block.CampfireBlock;
|
|
import net.minecraft.world.level.block.ComposterBlock;
|
|
import net.minecraft.world.level.block.MultifaceBlock;
|
|
import net.minecraft.world.level.block.PointedDripstoneBlock;
|
|
import net.minecraft.world.level.block.SculkShriekerBlock;
|
|
import net.minecraft.world.level.block.SoundType;
|
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
|
import net.minecraft.world.level.block.entity.trialspawner.TrialSpawner;
|
|
import net.minecraft.world.level.block.entity.vault.VaultBlockEntity;
|
|
import net.minecraft.world.level.block.state.BlockState;
|
|
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
|
|
import net.minecraft.world.level.border.WorldBorder;
|
|
import net.minecraft.world.level.levelgen.Heightmap;
|
|
import net.minecraft.world.level.lighting.LevelLightEngine;
|
|
import net.minecraft.world.level.material.FluidState;
|
|
import net.minecraft.world.level.material.FogType;
|
|
import net.minecraft.world.phys.AABB;
|
|
import net.minecraft.world.phys.BlockHitResult;
|
|
import net.minecraft.world.phys.HitResult;
|
|
import net.minecraft.world.phys.Vec3;
|
|
import net.minecraft.world.phys.shapes.CollisionContext;
|
|
import net.minecraft.world.phys.shapes.Shapes;
|
|
import net.minecraft.world.phys.shapes.VoxelShape;
|
|
import org.jetbrains.annotations.Nullable;
|
|
import org.joml.Matrix4f;
|
|
import org.joml.Matrix4fStack;
|
|
import org.joml.Quaternionf;
|
|
import org.joml.Vector3d;
|
|
import org.joml.Vector3f;
|
|
import org.joml.Vector4f;
|
|
import org.slf4j.Logger;
|
|
|
|
@Environment(EnvType.CLIENT)
|
|
public class LevelRenderer implements ResourceManagerReloadListener, AutoCloseable {
|
|
private static final Logger LOGGER = LogUtils.getLogger();
|
|
public static final int SECTION_SIZE = 16;
|
|
public static final int HALF_SECTION_SIZE = 8;
|
|
private static final float SKY_DISC_RADIUS = 512.0F;
|
|
private static final int MIN_FOG_DISTANCE = 32;
|
|
private static final int RAIN_RADIUS = 10;
|
|
private static final int RAIN_DIAMETER = 21;
|
|
private static final int TRANSPARENT_SORT_COUNT = 15;
|
|
private static final ResourceLocation MOON_LOCATION = ResourceLocation.withDefaultNamespace("textures/environment/moon_phases.png");
|
|
private static final ResourceLocation SUN_LOCATION = ResourceLocation.withDefaultNamespace("textures/environment/sun.png");
|
|
protected static final ResourceLocation CLOUDS_LOCATION = ResourceLocation.withDefaultNamespace("textures/environment/clouds.png");
|
|
private static final ResourceLocation END_SKY_LOCATION = ResourceLocation.withDefaultNamespace("textures/environment/end_sky.png");
|
|
private static final ResourceLocation FORCEFIELD_LOCATION = ResourceLocation.withDefaultNamespace("textures/misc/forcefield.png");
|
|
private static final ResourceLocation RAIN_LOCATION = ResourceLocation.withDefaultNamespace("textures/environment/rain.png");
|
|
private static final ResourceLocation SNOW_LOCATION = ResourceLocation.withDefaultNamespace("textures/environment/snow.png");
|
|
public static final Direction[] DIRECTIONS = Direction.values();
|
|
private final Minecraft minecraft;
|
|
private final EntityRenderDispatcher entityRenderDispatcher;
|
|
private final BlockEntityRenderDispatcher blockEntityRenderDispatcher;
|
|
private final RenderBuffers renderBuffers;
|
|
@Nullable
|
|
private ClientLevel level;
|
|
private final SectionOcclusionGraph sectionOcclusionGraph = new SectionOcclusionGraph();
|
|
private final ObjectArrayList<SectionRenderDispatcher.RenderSection> visibleSections = new ObjectArrayList<>(10000);
|
|
/**
|
|
* Global block entities; these are always rendered, even if off-screen.
|
|
* Any block entity is added to this if {@link net.minecraft.client.renderer.blockentity.BlockEntityRenderer#shouldRenderOffScreen(net.minecraft.world.level.block.entity.BlockEntity)} returns {@code true}.
|
|
*/
|
|
private final Set<BlockEntity> globalBlockEntities = Sets.<BlockEntity>newHashSet();
|
|
@Nullable
|
|
private ViewArea viewArea;
|
|
@Nullable
|
|
private VertexBuffer starBuffer;
|
|
@Nullable
|
|
private VertexBuffer skyBuffer;
|
|
@Nullable
|
|
private VertexBuffer darkBuffer;
|
|
private boolean generateClouds = true;
|
|
@Nullable
|
|
private VertexBuffer cloudBuffer;
|
|
private final RunningTrimmedMean frameTimes = new RunningTrimmedMean(100);
|
|
private int ticks;
|
|
private final Int2ObjectMap<BlockDestructionProgress> destroyingBlocks = new Int2ObjectOpenHashMap<>();
|
|
private final Long2ObjectMap<SortedSet<BlockDestructionProgress>> destructionProgress = new Long2ObjectOpenHashMap<>();
|
|
private final Map<BlockPos, SoundInstance> playingJukeboxSongs = Maps.<BlockPos, SoundInstance>newHashMap();
|
|
@Nullable
|
|
private RenderTarget entityTarget;
|
|
@Nullable
|
|
private PostChain entityEffect;
|
|
@Nullable
|
|
private RenderTarget translucentTarget;
|
|
@Nullable
|
|
private RenderTarget itemEntityTarget;
|
|
@Nullable
|
|
private RenderTarget particlesTarget;
|
|
@Nullable
|
|
private RenderTarget weatherTarget;
|
|
@Nullable
|
|
private RenderTarget cloudsTarget;
|
|
@Nullable
|
|
private PostChain transparencyChain;
|
|
private int lastCameraSectionX = Integer.MIN_VALUE;
|
|
private int lastCameraSectionY = Integer.MIN_VALUE;
|
|
private int lastCameraSectionZ = Integer.MIN_VALUE;
|
|
private double prevCamX = Double.MIN_VALUE;
|
|
private double prevCamY = Double.MIN_VALUE;
|
|
private double prevCamZ = Double.MIN_VALUE;
|
|
private double prevCamRotX = Double.MIN_VALUE;
|
|
private double prevCamRotY = Double.MIN_VALUE;
|
|
private int prevCloudX = Integer.MIN_VALUE;
|
|
private int prevCloudY = Integer.MIN_VALUE;
|
|
private int prevCloudZ = Integer.MIN_VALUE;
|
|
private Vec3 prevCloudColor = Vec3.ZERO;
|
|
@Nullable
|
|
private CloudStatus prevCloudsType;
|
|
@Nullable
|
|
private SectionRenderDispatcher sectionRenderDispatcher;
|
|
private int lastViewDistance = -1;
|
|
private int renderedEntities;
|
|
private int culledEntities;
|
|
private Frustum cullingFrustum;
|
|
private boolean captureFrustum;
|
|
@Nullable
|
|
private Frustum capturedFrustum;
|
|
private final Vector4f[] frustumPoints = new Vector4f[8];
|
|
private final Vector3d frustumPos = new Vector3d(0.0, 0.0, 0.0);
|
|
private double xTransparentOld;
|
|
private double yTransparentOld;
|
|
private double zTransparentOld;
|
|
private int rainSoundTime;
|
|
private final float[] rainSizeX = new float[1024];
|
|
private final float[] rainSizeZ = new float[1024];
|
|
|
|
public LevelRenderer(
|
|
Minecraft minecraft, EntityRenderDispatcher entityRenderDispatcher, BlockEntityRenderDispatcher blockEntityRenderDispatcher, RenderBuffers renderBuffers
|
|
) {
|
|
this.minecraft = minecraft;
|
|
this.entityRenderDispatcher = entityRenderDispatcher;
|
|
this.blockEntityRenderDispatcher = blockEntityRenderDispatcher;
|
|
this.renderBuffers = renderBuffers;
|
|
|
|
for (int i = 0; i < 32; i++) {
|
|
for (int j = 0; j < 32; j++) {
|
|
float f = j - 16;
|
|
float g = i - 16;
|
|
float h = Mth.sqrt(f * f + g * g);
|
|
this.rainSizeX[i << 5 | j] = -g / h;
|
|
this.rainSizeZ[i << 5 | j] = f / h;
|
|
}
|
|
}
|
|
|
|
this.createStars();
|
|
this.createLightSky();
|
|
this.createDarkSky();
|
|
}
|
|
|
|
private void renderSnowAndRain(LightTexture lightTexture, float partialTick, double camX, double camY, double camZ) {
|
|
float f = this.minecraft.level.getRainLevel(partialTick);
|
|
if (!(f <= 0.0F)) {
|
|
lightTexture.turnOnLightLayer();
|
|
Level level = this.minecraft.level;
|
|
int i = Mth.floor(camX);
|
|
int j = Mth.floor(camY);
|
|
int k = Mth.floor(camZ);
|
|
Tesselator tesselator = Tesselator.getInstance();
|
|
BufferBuilder bufferBuilder = null;
|
|
RenderSystem.disableCull();
|
|
RenderSystem.enableBlend();
|
|
RenderSystem.enableDepthTest();
|
|
int l = 5;
|
|
if (Minecraft.useFancyGraphics()) {
|
|
l = 10;
|
|
}
|
|
|
|
RenderSystem.depthMask(Minecraft.useShaderTransparency());
|
|
int m = -1;
|
|
float g = this.ticks + partialTick;
|
|
RenderSystem.setShader(GameRenderer::getParticleShader);
|
|
BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos();
|
|
|
|
for (int n = k - l; n <= k + l; n++) {
|
|
for (int o = i - l; o <= i + l; o++) {
|
|
int p = (n - k + 16) * 32 + o - i + 16;
|
|
double d = this.rainSizeX[p] * 0.5;
|
|
double e = this.rainSizeZ[p] * 0.5;
|
|
mutableBlockPos.set((double)o, camY, (double)n);
|
|
Biome biome = level.getBiome(mutableBlockPos).value();
|
|
if (biome.hasPrecipitation()) {
|
|
int q = level.getHeight(Heightmap.Types.MOTION_BLOCKING, o, n);
|
|
int r = j - l;
|
|
int s = j + l;
|
|
if (r < q) {
|
|
r = q;
|
|
}
|
|
|
|
if (s < q) {
|
|
s = q;
|
|
}
|
|
|
|
int t = q;
|
|
if (q < j) {
|
|
t = j;
|
|
}
|
|
|
|
if (r != s) {
|
|
RandomSource randomSource = RandomSource.create(o * o * 3121 + o * 45238971 ^ n * n * 418711 + n * 13761);
|
|
mutableBlockPos.set(o, r, n);
|
|
Biome.Precipitation precipitation = biome.getPrecipitationAt(mutableBlockPos);
|
|
if (precipitation == Biome.Precipitation.RAIN) {
|
|
if (m != 0) {
|
|
if (m >= 0) {
|
|
BufferUploader.drawWithShader(bufferBuilder.buildOrThrow());
|
|
}
|
|
|
|
m = 0;
|
|
RenderSystem.setShaderTexture(0, RAIN_LOCATION);
|
|
bufferBuilder = tesselator.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.PARTICLE);
|
|
}
|
|
|
|
int u = this.ticks & 131071;
|
|
int v = o * o * 3121 + o * 45238971 + n * n * 418711 + n * 13761 & 0xFF;
|
|
float h = 3.0F + randomSource.nextFloat();
|
|
float w = -(u + v + partialTick) / 32.0F * h;
|
|
float x = w % 32.0F;
|
|
double y = o + 0.5 - camX;
|
|
double z = n + 0.5 - camZ;
|
|
float aa = (float)Math.sqrt(y * y + z * z) / l;
|
|
float ab = ((1.0F - aa * aa) * 0.5F + 0.5F) * f;
|
|
mutableBlockPos.set(o, t, n);
|
|
int ac = getLightColor(level, mutableBlockPos);
|
|
bufferBuilder.addVertex((float)(o - camX - d + 0.5), (float)(s - camY), (float)(n - camZ - e + 0.5))
|
|
.setUv(0.0F, r * 0.25F + x)
|
|
.setColor(1.0F, 1.0F, 1.0F, ab)
|
|
.setLight(ac);
|
|
bufferBuilder.addVertex((float)(o - camX + d + 0.5), (float)(s - camY), (float)(n - camZ + e + 0.5))
|
|
.setUv(1.0F, r * 0.25F + x)
|
|
.setColor(1.0F, 1.0F, 1.0F, ab)
|
|
.setLight(ac);
|
|
bufferBuilder.addVertex((float)(o - camX + d + 0.5), (float)(r - camY), (float)(n - camZ + e + 0.5))
|
|
.setUv(1.0F, s * 0.25F + x)
|
|
.setColor(1.0F, 1.0F, 1.0F, ab)
|
|
.setLight(ac);
|
|
bufferBuilder.addVertex((float)(o - camX - d + 0.5), (float)(r - camY), (float)(n - camZ - e + 0.5))
|
|
.setUv(0.0F, s * 0.25F + x)
|
|
.setColor(1.0F, 1.0F, 1.0F, ab)
|
|
.setLight(ac);
|
|
} else if (precipitation == Biome.Precipitation.SNOW) {
|
|
if (m != 1) {
|
|
if (m >= 0) {
|
|
BufferUploader.drawWithShader(bufferBuilder.buildOrThrow());
|
|
}
|
|
|
|
m = 1;
|
|
RenderSystem.setShaderTexture(0, SNOW_LOCATION);
|
|
bufferBuilder = tesselator.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.PARTICLE);
|
|
}
|
|
|
|
float ad = -((this.ticks & 511) + partialTick) / 512.0F;
|
|
float ae = (float)(randomSource.nextDouble() + g * 0.01 * (float)randomSource.nextGaussian());
|
|
float h = (float)(randomSource.nextDouble() + g * (float)randomSource.nextGaussian() * 0.001);
|
|
double af = o + 0.5 - camX;
|
|
double y = n + 0.5 - camZ;
|
|
float ag = (float)Math.sqrt(af * af + y * y) / l;
|
|
float ah = ((1.0F - ag * ag) * 0.3F + 0.5F) * f;
|
|
mutableBlockPos.set(o, t, n);
|
|
int ai = getLightColor(level, mutableBlockPos);
|
|
int aj = ai >> 16 & 65535;
|
|
int ac = ai & 65535;
|
|
int ak = (aj * 3 + 240) / 4;
|
|
int al = (ac * 3 + 240) / 4;
|
|
bufferBuilder.addVertex((float)(o - camX - d + 0.5), (float)(s - camY), (float)(n - camZ - e + 0.5))
|
|
.setUv(0.0F + ae, r * 0.25F + ad + h)
|
|
.setColor(1.0F, 1.0F, 1.0F, ah)
|
|
.setUv2(al, ak);
|
|
bufferBuilder.addVertex((float)(o - camX + d + 0.5), (float)(s - camY), (float)(n - camZ + e + 0.5))
|
|
.setUv(1.0F + ae, r * 0.25F + ad + h)
|
|
.setColor(1.0F, 1.0F, 1.0F, ah)
|
|
.setUv2(al, ak);
|
|
bufferBuilder.addVertex((float)(o - camX + d + 0.5), (float)(r - camY), (float)(n - camZ + e + 0.5))
|
|
.setUv(1.0F + ae, s * 0.25F + ad + h)
|
|
.setColor(1.0F, 1.0F, 1.0F, ah)
|
|
.setUv2(al, ak);
|
|
bufferBuilder.addVertex((float)(o - camX - d + 0.5), (float)(r - camY), (float)(n - camZ - e + 0.5))
|
|
.setUv(0.0F + ae, s * 0.25F + ad + h)
|
|
.setColor(1.0F, 1.0F, 1.0F, ah)
|
|
.setUv2(al, ak);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (m >= 0) {
|
|
BufferUploader.drawWithShader(bufferBuilder.buildOrThrow());
|
|
}
|
|
|
|
RenderSystem.enableCull();
|
|
RenderSystem.disableBlend();
|
|
lightTexture.turnOffLightLayer();
|
|
}
|
|
}
|
|
|
|
public void tickRain(Camera camera) {
|
|
float f = this.minecraft.level.getRainLevel(1.0F) / (Minecraft.useFancyGraphics() ? 1.0F : 2.0F);
|
|
if (!(f <= 0.0F)) {
|
|
RandomSource randomSource = RandomSource.create(this.ticks * 312987231L);
|
|
LevelReader levelReader = this.minecraft.level;
|
|
BlockPos blockPos = BlockPos.containing(camera.getPosition());
|
|
BlockPos blockPos2 = null;
|
|
int i = (int)(100.0F * f * f) / (this.minecraft.options.particles().get() == ParticleStatus.DECREASED ? 2 : 1);
|
|
|
|
for (int j = 0; j < i; j++) {
|
|
int k = randomSource.nextInt(21) - 10;
|
|
int l = randomSource.nextInt(21) - 10;
|
|
BlockPos blockPos3 = levelReader.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, blockPos.offset(k, 0, l));
|
|
if (blockPos3.getY() > levelReader.getMinBuildHeight() && blockPos3.getY() <= blockPos.getY() + 10 && blockPos3.getY() >= blockPos.getY() - 10) {
|
|
Biome biome = levelReader.getBiome(blockPos3).value();
|
|
if (biome.getPrecipitationAt(blockPos3) == Biome.Precipitation.RAIN) {
|
|
blockPos2 = blockPos3.below();
|
|
if (this.minecraft.options.particles().get() == ParticleStatus.MINIMAL) {
|
|
break;
|
|
}
|
|
|
|
double d = randomSource.nextDouble();
|
|
double e = randomSource.nextDouble();
|
|
BlockState blockState = levelReader.getBlockState(blockPos2);
|
|
FluidState fluidState = levelReader.getFluidState(blockPos2);
|
|
VoxelShape voxelShape = blockState.getCollisionShape(levelReader, blockPos2);
|
|
double g = voxelShape.max(Direction.Axis.Y, d, e);
|
|
double h = fluidState.getHeight(levelReader, blockPos2);
|
|
double m = Math.max(g, h);
|
|
ParticleOptions particleOptions = !fluidState.is(FluidTags.LAVA) && !blockState.is(Blocks.MAGMA_BLOCK) && !CampfireBlock.isLitCampfire(blockState)
|
|
? ParticleTypes.RAIN
|
|
: ParticleTypes.SMOKE;
|
|
this.minecraft.level.addParticle(particleOptions, blockPos2.getX() + d, blockPos2.getY() + m, blockPos2.getZ() + e, 0.0, 0.0, 0.0);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (blockPos2 != null && randomSource.nextInt(3) < this.rainSoundTime++) {
|
|
this.rainSoundTime = 0;
|
|
if (blockPos2.getY() > blockPos.getY() + 1
|
|
&& levelReader.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, blockPos).getY() > Mth.floor((float)blockPos.getY())) {
|
|
this.minecraft.level.playLocalSound(blockPos2, SoundEvents.WEATHER_RAIN_ABOVE, SoundSource.WEATHER, 0.1F, 0.5F, false);
|
|
} else {
|
|
this.minecraft.level.playLocalSound(blockPos2, SoundEvents.WEATHER_RAIN, SoundSource.WEATHER, 0.2F, 1.0F, false);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public void close() {
|
|
if (this.entityEffect != null) {
|
|
this.entityEffect.close();
|
|
}
|
|
|
|
if (this.transparencyChain != null) {
|
|
this.transparencyChain.close();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void onResourceManagerReload(ResourceManager resourceManager) {
|
|
this.initOutline();
|
|
if (Minecraft.useShaderTransparency()) {
|
|
this.initTransparency();
|
|
}
|
|
}
|
|
|
|
public void initOutline() {
|
|
if (this.entityEffect != null) {
|
|
this.entityEffect.close();
|
|
}
|
|
|
|
ResourceLocation resourceLocation = ResourceLocation.withDefaultNamespace("shaders/post/entity_outline.json");
|
|
|
|
try {
|
|
this.entityEffect = new PostChain(
|
|
this.minecraft.getTextureManager(), this.minecraft.getResourceManager(), this.minecraft.getMainRenderTarget(), resourceLocation
|
|
);
|
|
this.entityEffect.resize(this.minecraft.getWindow().getWidth(), this.minecraft.getWindow().getHeight());
|
|
this.entityTarget = this.entityEffect.getTempTarget("final");
|
|
} catch (IOException var3) {
|
|
LOGGER.warn("Failed to load shader: {}", resourceLocation, var3);
|
|
this.entityEffect = null;
|
|
this.entityTarget = null;
|
|
} catch (JsonSyntaxException var4) {
|
|
LOGGER.warn("Failed to parse shader: {}", resourceLocation, var4);
|
|
this.entityEffect = null;
|
|
this.entityTarget = null;
|
|
}
|
|
}
|
|
|
|
private void initTransparency() {
|
|
this.deinitTransparency();
|
|
ResourceLocation resourceLocation = ResourceLocation.withDefaultNamespace("shaders/post/transparency.json");
|
|
|
|
try {
|
|
PostChain postChain = new PostChain(
|
|
this.minecraft.getTextureManager(), this.minecraft.getResourceManager(), this.minecraft.getMainRenderTarget(), resourceLocation
|
|
);
|
|
postChain.resize(this.minecraft.getWindow().getWidth(), this.minecraft.getWindow().getHeight());
|
|
RenderTarget renderTarget = postChain.getTempTarget("translucent");
|
|
RenderTarget renderTarget2 = postChain.getTempTarget("itemEntity");
|
|
RenderTarget renderTarget3 = postChain.getTempTarget("particles");
|
|
RenderTarget renderTarget4 = postChain.getTempTarget("weather");
|
|
RenderTarget renderTarget5 = postChain.getTempTarget("clouds");
|
|
this.transparencyChain = postChain;
|
|
this.translucentTarget = renderTarget;
|
|
this.itemEntityTarget = renderTarget2;
|
|
this.particlesTarget = renderTarget3;
|
|
this.weatherTarget = renderTarget4;
|
|
this.cloudsTarget = renderTarget5;
|
|
} catch (Exception var8) {
|
|
String string = var8 instanceof JsonSyntaxException ? "parse" : "load";
|
|
String string2 = "Failed to " + string + " shader: " + resourceLocation;
|
|
LevelRenderer.TransparencyShaderException transparencyShaderException = new LevelRenderer.TransparencyShaderException(string2, var8);
|
|
if (this.minecraft.getResourcePackRepository().getSelectedIds().size() > 1) {
|
|
Component component = (Component)this.minecraft
|
|
.getResourceManager()
|
|
.listPacks()
|
|
.findFirst()
|
|
.map(packResources -> Component.literal(packResources.packId()))
|
|
.orElse(null);
|
|
this.minecraft.options.graphicsMode().set(GraphicsStatus.FANCY);
|
|
this.minecraft.clearResourcePacksOnError(transparencyShaderException, component, null);
|
|
} else {
|
|
this.minecraft.options.graphicsMode().set(GraphicsStatus.FANCY);
|
|
this.minecraft.options.save();
|
|
LOGGER.error(LogUtils.FATAL_MARKER, string2, (Throwable)transparencyShaderException);
|
|
this.minecraft.emergencySaveAndCrash(new CrashReport(string2, transparencyShaderException));
|
|
}
|
|
}
|
|
}
|
|
|
|
private void deinitTransparency() {
|
|
if (this.transparencyChain != null) {
|
|
this.transparencyChain.close();
|
|
this.translucentTarget.destroyBuffers();
|
|
this.itemEntityTarget.destroyBuffers();
|
|
this.particlesTarget.destroyBuffers();
|
|
this.weatherTarget.destroyBuffers();
|
|
this.cloudsTarget.destroyBuffers();
|
|
this.transparencyChain = null;
|
|
this.translucentTarget = null;
|
|
this.itemEntityTarget = null;
|
|
this.particlesTarget = null;
|
|
this.weatherTarget = null;
|
|
this.cloudsTarget = null;
|
|
}
|
|
}
|
|
|
|
public void doEntityOutline() {
|
|
if (this.shouldShowEntityOutlines()) {
|
|
RenderSystem.enableBlend();
|
|
RenderSystem.blendFuncSeparate(
|
|
GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA, GlStateManager.SourceFactor.ZERO, GlStateManager.DestFactor.ONE
|
|
);
|
|
this.entityTarget.blitToScreen(this.minecraft.getWindow().getWidth(), this.minecraft.getWindow().getHeight(), false);
|
|
RenderSystem.disableBlend();
|
|
RenderSystem.defaultBlendFunc();
|
|
}
|
|
}
|
|
|
|
protected boolean shouldShowEntityOutlines() {
|
|
return !this.minecraft.gameRenderer.isPanoramicMode() && this.entityTarget != null && this.entityEffect != null && this.minecraft.player != null;
|
|
}
|
|
|
|
private void createDarkSky() {
|
|
if (this.darkBuffer != null) {
|
|
this.darkBuffer.close();
|
|
}
|
|
|
|
this.darkBuffer = new VertexBuffer(VertexBuffer.Usage.STATIC);
|
|
this.darkBuffer.bind();
|
|
this.darkBuffer.upload(buildSkyDisc(Tesselator.getInstance(), -16.0F));
|
|
VertexBuffer.unbind();
|
|
}
|
|
|
|
private void createLightSky() {
|
|
if (this.skyBuffer != null) {
|
|
this.skyBuffer.close();
|
|
}
|
|
|
|
this.skyBuffer = new VertexBuffer(VertexBuffer.Usage.STATIC);
|
|
this.skyBuffer.bind();
|
|
this.skyBuffer.upload(buildSkyDisc(Tesselator.getInstance(), 16.0F));
|
|
VertexBuffer.unbind();
|
|
}
|
|
|
|
private static MeshData buildSkyDisc(Tesselator tesselator, float y) {
|
|
float f = Math.signum(y) * 512.0F;
|
|
float g = 512.0F;
|
|
BufferBuilder bufferBuilder = tesselator.begin(VertexFormat.Mode.TRIANGLE_FAN, DefaultVertexFormat.POSITION);
|
|
bufferBuilder.addVertex(0.0F, y, 0.0F);
|
|
|
|
for (int i = -180; i <= 180; i += 45) {
|
|
bufferBuilder.addVertex(f * Mth.cos(i * (float) (Math.PI / 180.0)), y, 512.0F * Mth.sin(i * (float) (Math.PI / 180.0)));
|
|
}
|
|
|
|
return bufferBuilder.buildOrThrow();
|
|
}
|
|
|
|
private void createStars() {
|
|
if (this.starBuffer != null) {
|
|
this.starBuffer.close();
|
|
}
|
|
|
|
this.starBuffer = new VertexBuffer(VertexBuffer.Usage.STATIC);
|
|
this.starBuffer.bind();
|
|
this.starBuffer.upload(this.drawStars(Tesselator.getInstance()));
|
|
VertexBuffer.unbind();
|
|
}
|
|
|
|
private MeshData drawStars(Tesselator tesselator) {
|
|
RandomSource randomSource = RandomSource.create(10842L);
|
|
int i = 1500;
|
|
float f = 100.0F;
|
|
BufferBuilder bufferBuilder = tesselator.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION);
|
|
|
|
for (int j = 0; j < 1500; j++) {
|
|
float g = randomSource.nextFloat() * 2.0F - 1.0F;
|
|
float h = randomSource.nextFloat() * 2.0F - 1.0F;
|
|
float k = randomSource.nextFloat() * 2.0F - 1.0F;
|
|
float l = 0.15F + randomSource.nextFloat() * 0.1F;
|
|
float m = Mth.lengthSquared(g, h, k);
|
|
if (!(m <= 0.010000001F) && !(m >= 1.0F)) {
|
|
Vector3f vector3f = new Vector3f(g, h, k).normalize(100.0F);
|
|
float n = (float)(randomSource.nextDouble() * (float) Math.PI * 2.0);
|
|
Quaternionf quaternionf = new Quaternionf().rotateTo(new Vector3f(0.0F, 0.0F, -1.0F), vector3f).rotateZ(n);
|
|
bufferBuilder.addVertex(vector3f.add(new Vector3f(l, -l, 0.0F).rotate(quaternionf)));
|
|
bufferBuilder.addVertex(vector3f.add(new Vector3f(l, l, 0.0F).rotate(quaternionf)));
|
|
bufferBuilder.addVertex(vector3f.add(new Vector3f(-l, l, 0.0F).rotate(quaternionf)));
|
|
bufferBuilder.addVertex(vector3f.add(new Vector3f(-l, -l, 0.0F).rotate(quaternionf)));
|
|
}
|
|
}
|
|
|
|
return bufferBuilder.buildOrThrow();
|
|
}
|
|
|
|
/**
|
|
* @param level the level to set, or {@code null} to clear
|
|
*/
|
|
public void setLevel(@Nullable ClientLevel level) {
|
|
this.lastCameraSectionX = Integer.MIN_VALUE;
|
|
this.lastCameraSectionY = Integer.MIN_VALUE;
|
|
this.lastCameraSectionZ = Integer.MIN_VALUE;
|
|
this.entityRenderDispatcher.setLevel(level);
|
|
this.level = level;
|
|
if (level != null) {
|
|
this.allChanged();
|
|
} else {
|
|
if (this.viewArea != null) {
|
|
this.viewArea.releaseAllBuffers();
|
|
this.viewArea = null;
|
|
}
|
|
|
|
if (this.sectionRenderDispatcher != null) {
|
|
this.sectionRenderDispatcher.dispose();
|
|
}
|
|
|
|
this.sectionRenderDispatcher = null;
|
|
this.globalBlockEntities.clear();
|
|
this.sectionOcclusionGraph.waitAndReset(null);
|
|
this.visibleSections.clear();
|
|
}
|
|
}
|
|
|
|
public void graphicsChanged() {
|
|
if (Minecraft.useShaderTransparency()) {
|
|
this.initTransparency();
|
|
} else {
|
|
this.deinitTransparency();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Loads all renderers and sets up the basic options usage.
|
|
*/
|
|
public void allChanged() {
|
|
if (this.level != null) {
|
|
this.graphicsChanged();
|
|
this.level.clearTintCaches();
|
|
if (this.sectionRenderDispatcher == null) {
|
|
this.sectionRenderDispatcher = new SectionRenderDispatcher(
|
|
this.level, this, Util.backgroundExecutor(), this.renderBuffers, this.minecraft.getBlockRenderer(), this.minecraft.getBlockEntityRenderDispatcher()
|
|
);
|
|
} else {
|
|
this.sectionRenderDispatcher.setLevel(this.level);
|
|
}
|
|
|
|
this.generateClouds = true;
|
|
ItemBlockRenderTypes.setFancy(Minecraft.useFancyGraphics());
|
|
this.lastViewDistance = this.minecraft.options.getEffectiveRenderDistance();
|
|
if (this.viewArea != null) {
|
|
this.viewArea.releaseAllBuffers();
|
|
}
|
|
|
|
this.sectionRenderDispatcher.blockUntilClear();
|
|
synchronized (this.globalBlockEntities) {
|
|
this.globalBlockEntities.clear();
|
|
}
|
|
|
|
this.viewArea = new ViewArea(this.sectionRenderDispatcher, this.level, this.minecraft.options.getEffectiveRenderDistance(), this);
|
|
this.sectionOcclusionGraph.waitAndReset(this.viewArea);
|
|
this.visibleSections.clear();
|
|
Entity entity = this.minecraft.getCameraEntity();
|
|
if (entity != null) {
|
|
this.viewArea.repositionCamera(entity.getX(), entity.getZ());
|
|
}
|
|
}
|
|
}
|
|
|
|
public void resize(int width, int height) {
|
|
this.needsUpdate();
|
|
if (this.entityEffect != null) {
|
|
this.entityEffect.resize(width, height);
|
|
}
|
|
|
|
if (this.transparencyChain != null) {
|
|
this.transparencyChain.resize(width, height);
|
|
}
|
|
}
|
|
|
|
public String getSectionStatistics() {
|
|
int i = this.viewArea.sections.length;
|
|
int j = this.countRenderedSections();
|
|
return String.format(
|
|
Locale.ROOT,
|
|
"C: %d/%d %sD: %d, %s",
|
|
j,
|
|
i,
|
|
this.minecraft.smartCull ? "(s) " : "",
|
|
this.lastViewDistance,
|
|
this.sectionRenderDispatcher == null ? "null" : this.sectionRenderDispatcher.getStats()
|
|
);
|
|
}
|
|
|
|
public SectionRenderDispatcher getSectionRenderDispatcher() {
|
|
return this.sectionRenderDispatcher;
|
|
}
|
|
|
|
public double getTotalSections() {
|
|
return this.viewArea.sections.length;
|
|
}
|
|
|
|
public double getLastViewDistance() {
|
|
return this.lastViewDistance;
|
|
}
|
|
|
|
public int countRenderedSections() {
|
|
int i = 0;
|
|
|
|
for (SectionRenderDispatcher.RenderSection renderSection : this.visibleSections) {
|
|
if (!renderSection.getCompiled().hasNoRenderableLayers()) {
|
|
i++;
|
|
}
|
|
}
|
|
|
|
return i;
|
|
}
|
|
|
|
/**
|
|
* @return entity rendering statistics to display on the {@linkplain net.minecraft.client.gui.components.DebugScreenOverlay debug overlay}
|
|
*/
|
|
public String getEntityStatistics() {
|
|
return "E: "
|
|
+ this.renderedEntities
|
|
+ "/"
|
|
+ this.level.getEntityCount()
|
|
+ ", B: "
|
|
+ this.culledEntities
|
|
+ ", SD: "
|
|
+ this.level.getServerSimulationDistance();
|
|
}
|
|
|
|
private void setupRender(Camera camera, Frustum frustum, boolean hasCapturedFrustum, boolean isSpectator) {
|
|
Vec3 vec3 = camera.getPosition();
|
|
if (this.minecraft.options.getEffectiveRenderDistance() != this.lastViewDistance) {
|
|
this.allChanged();
|
|
}
|
|
|
|
this.level.getProfiler().push("camera");
|
|
double d = this.minecraft.player.getX();
|
|
double e = this.minecraft.player.getY();
|
|
double f = this.minecraft.player.getZ();
|
|
int i = SectionPos.posToSectionCoord(d);
|
|
int j = SectionPos.posToSectionCoord(e);
|
|
int k = SectionPos.posToSectionCoord(f);
|
|
if (this.lastCameraSectionX != i || this.lastCameraSectionY != j || this.lastCameraSectionZ != k) {
|
|
this.lastCameraSectionX = i;
|
|
this.lastCameraSectionY = j;
|
|
this.lastCameraSectionZ = k;
|
|
this.viewArea.repositionCamera(d, f);
|
|
}
|
|
|
|
this.sectionRenderDispatcher.setCamera(vec3);
|
|
this.level.getProfiler().popPush("cull");
|
|
this.minecraft.getProfiler().popPush("culling");
|
|
BlockPos blockPos = camera.getBlockPosition();
|
|
double g = Math.floor(vec3.x / 8.0);
|
|
double h = Math.floor(vec3.y / 8.0);
|
|
double l = Math.floor(vec3.z / 8.0);
|
|
if (g != this.prevCamX || h != this.prevCamY || l != this.prevCamZ) {
|
|
this.sectionOcclusionGraph.invalidate();
|
|
}
|
|
|
|
this.prevCamX = g;
|
|
this.prevCamY = h;
|
|
this.prevCamZ = l;
|
|
this.minecraft.getProfiler().popPush("update");
|
|
if (!hasCapturedFrustum) {
|
|
boolean bl = this.minecraft.smartCull;
|
|
if (isSpectator && this.level.getBlockState(blockPos).isSolidRender(this.level, blockPos)) {
|
|
bl = false;
|
|
}
|
|
|
|
Entity.setViewScale(Mth.clamp(this.minecraft.options.getEffectiveRenderDistance() / 8.0, 1.0, 2.5) * this.minecraft.options.entityDistanceScaling().get());
|
|
this.minecraft.getProfiler().push("section_occlusion_graph");
|
|
this.sectionOcclusionGraph.update(bl, camera, frustum, this.visibleSections);
|
|
this.minecraft.getProfiler().pop();
|
|
double m = Math.floor(camera.getXRot() / 2.0F);
|
|
double n = Math.floor(camera.getYRot() / 2.0F);
|
|
if (this.sectionOcclusionGraph.consumeFrustumUpdate() || m != this.prevCamRotX || n != this.prevCamRotY) {
|
|
this.applyFrustum(offsetFrustum(frustum));
|
|
this.prevCamRotX = m;
|
|
this.prevCamRotY = n;
|
|
}
|
|
}
|
|
|
|
this.minecraft.getProfiler().pop();
|
|
}
|
|
|
|
public static Frustum offsetFrustum(Frustum frustum) {
|
|
return new Frustum(frustum).offsetToFullyIncludeCameraCube(8);
|
|
}
|
|
|
|
private void applyFrustum(Frustum frustum) {
|
|
if (!Minecraft.getInstance().isSameThread()) {
|
|
throw new IllegalStateException("applyFrustum called from wrong thread: " + Thread.currentThread().getName());
|
|
} else {
|
|
this.minecraft.getProfiler().push("apply_frustum");
|
|
this.visibleSections.clear();
|
|
this.sectionOcclusionGraph.addSectionsInFrustum(frustum, this.visibleSections);
|
|
this.minecraft.getProfiler().pop();
|
|
}
|
|
}
|
|
|
|
public void addRecentlyCompiledSection(SectionRenderDispatcher.RenderSection renderSection) {
|
|
this.sectionOcclusionGraph.onSectionCompiled(renderSection);
|
|
}
|
|
|
|
private void captureFrustum(Matrix4f viewMatrix, Matrix4f projectionMatrix, double camX, double camY, double camZ, Frustum capturedFrustrum) {
|
|
this.capturedFrustum = capturedFrustrum;
|
|
Matrix4f matrix4f = new Matrix4f(projectionMatrix);
|
|
matrix4f.mul(viewMatrix);
|
|
matrix4f.invert();
|
|
this.frustumPos.x = camX;
|
|
this.frustumPos.y = camY;
|
|
this.frustumPos.z = camZ;
|
|
this.frustumPoints[0] = new Vector4f(-1.0F, -1.0F, -1.0F, 1.0F);
|
|
this.frustumPoints[1] = new Vector4f(1.0F, -1.0F, -1.0F, 1.0F);
|
|
this.frustumPoints[2] = new Vector4f(1.0F, 1.0F, -1.0F, 1.0F);
|
|
this.frustumPoints[3] = new Vector4f(-1.0F, 1.0F, -1.0F, 1.0F);
|
|
this.frustumPoints[4] = new Vector4f(-1.0F, -1.0F, 1.0F, 1.0F);
|
|
this.frustumPoints[5] = new Vector4f(1.0F, -1.0F, 1.0F, 1.0F);
|
|
this.frustumPoints[6] = new Vector4f(1.0F, 1.0F, 1.0F, 1.0F);
|
|
this.frustumPoints[7] = new Vector4f(-1.0F, 1.0F, 1.0F, 1.0F);
|
|
|
|
for (int i = 0; i < 8; i++) {
|
|
matrix4f.transform(this.frustumPoints[i]);
|
|
this.frustumPoints[i].div(this.frustumPoints[i].w());
|
|
}
|
|
}
|
|
|
|
public void prepareCullFrustum(Vec3 cameraPosition, Matrix4f frustumMatrix, Matrix4f projectionMatrix) {
|
|
this.cullingFrustum = new Frustum(frustumMatrix, projectionMatrix);
|
|
this.cullingFrustum.prepare(cameraPosition.x(), cameraPosition.y(), cameraPosition.z());
|
|
}
|
|
|
|
public void renderLevel(
|
|
DeltaTracker deltaTracker,
|
|
boolean renderBlockOutline,
|
|
Camera camera,
|
|
GameRenderer gameRenderer,
|
|
LightTexture lightTexture,
|
|
Matrix4f frustumMatrix,
|
|
Matrix4f projectionMatrix
|
|
) {
|
|
TickRateManager tickRateManager = this.minecraft.level.tickRateManager();
|
|
float f = deltaTracker.getGameTimeDeltaPartialTick(false);
|
|
RenderSystem.setShaderGameTime(this.level.getGameTime(), f);
|
|
this.blockEntityRenderDispatcher.prepare(this.level, camera, this.minecraft.hitResult);
|
|
this.entityRenderDispatcher.prepare(this.level, camera, this.minecraft.crosshairPickEntity);
|
|
ProfilerFiller profilerFiller = this.level.getProfiler();
|
|
profilerFiller.popPush("light_update_queue");
|
|
this.level.pollLightUpdates();
|
|
profilerFiller.popPush("light_updates");
|
|
this.level.getChunkSource().getLightEngine().runLightUpdates();
|
|
Vec3 vec3 = camera.getPosition();
|
|
double d = vec3.x();
|
|
double e = vec3.y();
|
|
double g = vec3.z();
|
|
profilerFiller.popPush("culling");
|
|
boolean bl = this.capturedFrustum != null;
|
|
Frustum frustum;
|
|
if (bl) {
|
|
frustum = this.capturedFrustum;
|
|
frustum.prepare(this.frustumPos.x, this.frustumPos.y, this.frustumPos.z);
|
|
} else {
|
|
frustum = this.cullingFrustum;
|
|
}
|
|
|
|
this.minecraft.getProfiler().popPush("captureFrustum");
|
|
if (this.captureFrustum) {
|
|
this.captureFrustum(frustumMatrix, projectionMatrix, vec3.x, vec3.y, vec3.z, bl ? new Frustum(frustumMatrix, projectionMatrix) : frustum);
|
|
this.captureFrustum = false;
|
|
}
|
|
|
|
profilerFiller.popPush("clear");
|
|
FogRenderer.setupColor(camera, f, this.minecraft.level, this.minecraft.options.getEffectiveRenderDistance(), gameRenderer.getDarkenWorldAmount(f));
|
|
FogRenderer.levelFogColor();
|
|
RenderSystem.clear(16640, Minecraft.ON_OSX);
|
|
float h = gameRenderer.getRenderDistance();
|
|
boolean bl2 = this.minecraft.level.effects().isFoggyAt(Mth.floor(d), Mth.floor(e)) || this.minecraft.gui.getBossOverlay().shouldCreateWorldFog();
|
|
profilerFiller.popPush("sky");
|
|
RenderSystem.setShader(GameRenderer::getPositionShader);
|
|
this.renderSky(frustumMatrix, projectionMatrix, f, camera, bl2, () -> FogRenderer.setupFog(camera, FogRenderer.FogMode.FOG_SKY, h, bl2, f));
|
|
profilerFiller.popPush("fog");
|
|
FogRenderer.setupFog(camera, FogRenderer.FogMode.FOG_TERRAIN, Math.max(h, 32.0F), bl2, f);
|
|
profilerFiller.popPush("terrain_setup");
|
|
this.setupRender(camera, frustum, bl, this.minecraft.player.isSpectator());
|
|
profilerFiller.popPush("compile_sections");
|
|
this.compileSections(camera);
|
|
profilerFiller.popPush("terrain");
|
|
this.renderSectionLayer(RenderType.solid(), d, e, g, frustumMatrix, projectionMatrix);
|
|
this.renderSectionLayer(RenderType.cutoutMipped(), d, e, g, frustumMatrix, projectionMatrix);
|
|
this.renderSectionLayer(RenderType.cutout(), d, e, g, frustumMatrix, projectionMatrix);
|
|
if (this.level.effects().constantAmbientLight()) {
|
|
Lighting.setupNetherLevel();
|
|
} else {
|
|
Lighting.setupLevel();
|
|
}
|
|
|
|
profilerFiller.popPush("entities");
|
|
this.renderedEntities = 0;
|
|
this.culledEntities = 0;
|
|
if (this.itemEntityTarget != null) {
|
|
this.itemEntityTarget.clear(Minecraft.ON_OSX);
|
|
this.itemEntityTarget.copyDepthFrom(this.minecraft.getMainRenderTarget());
|
|
this.minecraft.getMainRenderTarget().bindWrite(false);
|
|
}
|
|
|
|
if (this.weatherTarget != null) {
|
|
this.weatherTarget.clear(Minecraft.ON_OSX);
|
|
}
|
|
|
|
if (this.shouldShowEntityOutlines()) {
|
|
this.entityTarget.clear(Minecraft.ON_OSX);
|
|
this.minecraft.getMainRenderTarget().bindWrite(false);
|
|
}
|
|
|
|
Matrix4fStack matrix4fStack = RenderSystem.getModelViewStack();
|
|
matrix4fStack.pushMatrix();
|
|
matrix4fStack.mul(frustumMatrix);
|
|
RenderSystem.applyModelViewMatrix();
|
|
boolean bl3 = false;
|
|
PoseStack poseStack = new PoseStack();
|
|
MultiBufferSource.BufferSource bufferSource = this.renderBuffers.bufferSource();
|
|
|
|
for (Entity entity : this.level.entitiesForRendering()) {
|
|
if (this.entityRenderDispatcher.shouldRender(entity, frustum, d, e, g) || entity.hasIndirectPassenger(this.minecraft.player)) {
|
|
BlockPos blockPos = entity.blockPosition();
|
|
if ((this.level.isOutsideBuildHeight(blockPos.getY()) || this.isSectionCompiled(blockPos))
|
|
&& (entity != camera.getEntity() || camera.isDetached() || camera.getEntity() instanceof LivingEntity && ((LivingEntity)camera.getEntity()).isSleeping())
|
|
&& (!(entity instanceof LocalPlayer) || camera.getEntity() == entity)) {
|
|
this.renderedEntities++;
|
|
if (entity.tickCount == 0) {
|
|
entity.xOld = entity.getX();
|
|
entity.yOld = entity.getY();
|
|
entity.zOld = entity.getZ();
|
|
}
|
|
|
|
MultiBufferSource multiBufferSource;
|
|
if (this.shouldShowEntityOutlines() && this.minecraft.shouldEntityAppearGlowing(entity)) {
|
|
bl3 = true;
|
|
OutlineBufferSource outlineBufferSource = this.renderBuffers.outlineBufferSource();
|
|
multiBufferSource = outlineBufferSource;
|
|
int i = entity.getTeamColor();
|
|
outlineBufferSource.setColor(FastColor.ARGB32.red(i), FastColor.ARGB32.green(i), FastColor.ARGB32.blue(i), 255);
|
|
} else {
|
|
multiBufferSource = bufferSource;
|
|
}
|
|
|
|
float j = deltaTracker.getGameTimeDeltaPartialTick(!tickRateManager.isEntityFrozen(entity));
|
|
this.renderEntity(entity, d, e, g, j, poseStack, multiBufferSource);
|
|
}
|
|
}
|
|
}
|
|
|
|
bufferSource.endLastBatch();
|
|
this.checkPoseStack(poseStack);
|
|
bufferSource.endBatch(RenderType.entitySolid(TextureAtlas.LOCATION_BLOCKS));
|
|
bufferSource.endBatch(RenderType.entityCutout(TextureAtlas.LOCATION_BLOCKS));
|
|
bufferSource.endBatch(RenderType.entityCutoutNoCull(TextureAtlas.LOCATION_BLOCKS));
|
|
bufferSource.endBatch(RenderType.entitySmoothCutout(TextureAtlas.LOCATION_BLOCKS));
|
|
profilerFiller.popPush("blockentities");
|
|
|
|
for (SectionRenderDispatcher.RenderSection renderSection : this.visibleSections) {
|
|
List<BlockEntity> list = renderSection.getCompiled().getRenderableBlockEntities();
|
|
if (!list.isEmpty()) {
|
|
for (BlockEntity blockEntity : list) {
|
|
BlockPos blockPos2 = blockEntity.getBlockPos();
|
|
MultiBufferSource multiBufferSource2 = bufferSource;
|
|
poseStack.pushPose();
|
|
poseStack.translate(blockPos2.getX() - d, blockPos2.getY() - e, blockPos2.getZ() - g);
|
|
SortedSet<BlockDestructionProgress> sortedSet = this.destructionProgress.get(blockPos2.asLong());
|
|
if (sortedSet != null && !sortedSet.isEmpty()) {
|
|
int k = ((BlockDestructionProgress)sortedSet.last()).getProgress();
|
|
if (k >= 0) {
|
|
PoseStack.Pose pose = poseStack.last();
|
|
VertexConsumer vertexConsumer = new SheetedDecalTextureGenerator(
|
|
this.renderBuffers.crumblingBufferSource().getBuffer((RenderType)ModelBakery.DESTROY_TYPES.get(k)), pose, 1.0F
|
|
);
|
|
multiBufferSource2 = renderType -> {
|
|
VertexConsumer vertexConsumer2x = bufferSource.getBuffer(renderType);
|
|
return renderType.affectsCrumbling() ? VertexMultiConsumer.create(vertexConsumer, vertexConsumer2x) : vertexConsumer2x;
|
|
};
|
|
}
|
|
}
|
|
|
|
this.blockEntityRenderDispatcher.render(blockEntity, f, poseStack, multiBufferSource2);
|
|
poseStack.popPose();
|
|
}
|
|
}
|
|
}
|
|
|
|
synchronized (this.globalBlockEntities) {
|
|
for (BlockEntity blockEntity2 : this.globalBlockEntities) {
|
|
BlockPos blockPos3 = blockEntity2.getBlockPos();
|
|
poseStack.pushPose();
|
|
poseStack.translate(blockPos3.getX() - d, blockPos3.getY() - e, blockPos3.getZ() - g);
|
|
this.blockEntityRenderDispatcher.render(blockEntity2, f, poseStack, bufferSource);
|
|
poseStack.popPose();
|
|
}
|
|
}
|
|
|
|
this.checkPoseStack(poseStack);
|
|
bufferSource.endBatch(RenderType.solid());
|
|
bufferSource.endBatch(RenderType.endPortal());
|
|
bufferSource.endBatch(RenderType.endGateway());
|
|
bufferSource.endBatch(Sheets.solidBlockSheet());
|
|
bufferSource.endBatch(Sheets.cutoutBlockSheet());
|
|
bufferSource.endBatch(Sheets.bedSheet());
|
|
bufferSource.endBatch(Sheets.shulkerBoxSheet());
|
|
bufferSource.endBatch(Sheets.signSheet());
|
|
bufferSource.endBatch(Sheets.hangingSignSheet());
|
|
bufferSource.endBatch(Sheets.chestSheet());
|
|
this.renderBuffers.outlineBufferSource().endOutlineBatch();
|
|
if (bl3) {
|
|
this.entityEffect.process(deltaTracker.getGameTimeDeltaTicks());
|
|
this.minecraft.getMainRenderTarget().bindWrite(false);
|
|
}
|
|
|
|
profilerFiller.popPush("destroyProgress");
|
|
|
|
for (Entry<SortedSet<BlockDestructionProgress>> entry : this.destructionProgress.long2ObjectEntrySet()) {
|
|
BlockPos blockPos = BlockPos.of(entry.getLongKey());
|
|
double l = blockPos.getX() - d;
|
|
double m = blockPos.getY() - e;
|
|
double n = blockPos.getZ() - g;
|
|
if (!(l * l + m * m + n * n > 1024.0)) {
|
|
SortedSet<BlockDestructionProgress> sortedSet2 = (SortedSet<BlockDestructionProgress>)entry.getValue();
|
|
if (sortedSet2 != null && !sortedSet2.isEmpty()) {
|
|
int o = ((BlockDestructionProgress)sortedSet2.last()).getProgress();
|
|
poseStack.pushPose();
|
|
poseStack.translate(blockPos.getX() - d, blockPos.getY() - e, blockPos.getZ() - g);
|
|
PoseStack.Pose pose2 = poseStack.last();
|
|
VertexConsumer vertexConsumer2 = new SheetedDecalTextureGenerator(
|
|
this.renderBuffers.crumblingBufferSource().getBuffer((RenderType)ModelBakery.DESTROY_TYPES.get(o)), pose2, 1.0F
|
|
);
|
|
this.minecraft.getBlockRenderer().renderBreakingTexture(this.level.getBlockState(blockPos), blockPos, this.level, poseStack, vertexConsumer2);
|
|
poseStack.popPose();
|
|
}
|
|
}
|
|
}
|
|
|
|
this.checkPoseStack(poseStack);
|
|
HitResult hitResult = this.minecraft.hitResult;
|
|
if (renderBlockOutline && hitResult != null && hitResult.getType() == HitResult.Type.BLOCK) {
|
|
profilerFiller.popPush("outline");
|
|
BlockPos blockPos4 = ((BlockHitResult)hitResult).getBlockPos();
|
|
BlockState blockState = this.level.getBlockState(blockPos4);
|
|
if (!blockState.isAir() && this.level.getWorldBorder().isWithinBounds(blockPos4)) {
|
|
VertexConsumer vertexConsumer3 = bufferSource.getBuffer(RenderType.lines());
|
|
this.renderHitOutline(poseStack, vertexConsumer3, camera.getEntity(), d, e, g, blockPos4, blockState);
|
|
}
|
|
}
|
|
|
|
this.minecraft.debugRenderer.render(poseStack, bufferSource, d, e, g);
|
|
bufferSource.endLastBatch();
|
|
bufferSource.endBatch(Sheets.translucentCullBlockSheet());
|
|
bufferSource.endBatch(Sheets.bannerSheet());
|
|
bufferSource.endBatch(Sheets.shieldSheet());
|
|
bufferSource.endBatch(RenderType.armorEntityGlint());
|
|
bufferSource.endBatch(RenderType.glint());
|
|
bufferSource.endBatch(RenderType.glintTranslucent());
|
|
bufferSource.endBatch(RenderType.entityGlint());
|
|
bufferSource.endBatch(RenderType.entityGlintDirect());
|
|
bufferSource.endBatch(RenderType.waterMask());
|
|
this.renderBuffers.crumblingBufferSource().endBatch();
|
|
if (this.transparencyChain != null) {
|
|
bufferSource.endBatch(RenderType.lines());
|
|
bufferSource.endBatch();
|
|
this.translucentTarget.clear(Minecraft.ON_OSX);
|
|
this.translucentTarget.copyDepthFrom(this.minecraft.getMainRenderTarget());
|
|
profilerFiller.popPush("translucent");
|
|
this.renderSectionLayer(RenderType.translucent(), d, e, g, frustumMatrix, projectionMatrix);
|
|
profilerFiller.popPush("string");
|
|
this.renderSectionLayer(RenderType.tripwire(), d, e, g, frustumMatrix, projectionMatrix);
|
|
this.particlesTarget.clear(Minecraft.ON_OSX);
|
|
this.particlesTarget.copyDepthFrom(this.minecraft.getMainRenderTarget());
|
|
RenderStateShard.PARTICLES_TARGET.setupRenderState();
|
|
profilerFiller.popPush("particles");
|
|
this.minecraft.particleEngine.render(lightTexture, camera, f);
|
|
RenderStateShard.PARTICLES_TARGET.clearRenderState();
|
|
} else {
|
|
profilerFiller.popPush("translucent");
|
|
if (this.translucentTarget != null) {
|
|
this.translucentTarget.clear(Minecraft.ON_OSX);
|
|
}
|
|
|
|
this.renderSectionLayer(RenderType.translucent(), d, e, g, frustumMatrix, projectionMatrix);
|
|
bufferSource.endBatch(RenderType.lines());
|
|
bufferSource.endBatch();
|
|
profilerFiller.popPush("string");
|
|
this.renderSectionLayer(RenderType.tripwire(), d, e, g, frustumMatrix, projectionMatrix);
|
|
profilerFiller.popPush("particles");
|
|
this.minecraft.particleEngine.render(lightTexture, camera, f);
|
|
}
|
|
|
|
if (this.minecraft.options.getCloudsType() != CloudStatus.OFF) {
|
|
if (this.transparencyChain != null) {
|
|
this.cloudsTarget.clear(Minecraft.ON_OSX);
|
|
}
|
|
|
|
profilerFiller.popPush("clouds");
|
|
this.renderClouds(poseStack, frustumMatrix, projectionMatrix, f, d, e, g);
|
|
}
|
|
|
|
if (this.transparencyChain != null) {
|
|
RenderStateShard.WEATHER_TARGET.setupRenderState();
|
|
profilerFiller.popPush("weather");
|
|
this.renderSnowAndRain(lightTexture, f, d, e, g);
|
|
this.renderWorldBorder(camera);
|
|
RenderStateShard.WEATHER_TARGET.clearRenderState();
|
|
this.transparencyChain.process(deltaTracker.getGameTimeDeltaTicks());
|
|
this.minecraft.getMainRenderTarget().bindWrite(false);
|
|
} else {
|
|
RenderSystem.depthMask(false);
|
|
profilerFiller.popPush("weather");
|
|
this.renderSnowAndRain(lightTexture, f, d, e, g);
|
|
this.renderWorldBorder(camera);
|
|
RenderSystem.depthMask(true);
|
|
}
|
|
|
|
this.renderDebug(poseStack, bufferSource, camera);
|
|
bufferSource.endLastBatch();
|
|
matrix4fStack.popMatrix();
|
|
RenderSystem.applyModelViewMatrix();
|
|
RenderSystem.depthMask(true);
|
|
RenderSystem.disableBlend();
|
|
FogRenderer.setupNoFog();
|
|
}
|
|
|
|
/**
|
|
* Asserts that the specified {@code poseStack} is {@linkplain com.mojang.blaze3d.vertex.PoseStack#clear() clear}.
|
|
* @throws java.lang.IllegalStateException if the specified {@code poseStack} is not clear
|
|
*/
|
|
private void checkPoseStack(PoseStack poseStack) {
|
|
if (!poseStack.clear()) {
|
|
throw new IllegalStateException("Pose stack not empty");
|
|
}
|
|
}
|
|
|
|
private void renderEntity(Entity entity, double camX, double camY, double camZ, float partialTick, PoseStack poseStack, MultiBufferSource bufferSource) {
|
|
double d = Mth.lerp((double)partialTick, entity.xOld, entity.getX());
|
|
double e = Mth.lerp((double)partialTick, entity.yOld, entity.getY());
|
|
double f = Mth.lerp((double)partialTick, entity.zOld, entity.getZ());
|
|
float g = Mth.lerp(partialTick, entity.yRotO, entity.getYRot());
|
|
this.entityRenderDispatcher
|
|
.render(entity, d - camX, e - camY, f - camZ, g, partialTick, poseStack, bufferSource, this.entityRenderDispatcher.getPackedLightCoords(entity, partialTick));
|
|
}
|
|
|
|
private void renderSectionLayer(RenderType renderType, double x, double y, double z, Matrix4f frustrumMatrix, Matrix4f projectionMatrix) {
|
|
RenderSystem.assertOnRenderThread();
|
|
renderType.setupRenderState();
|
|
if (renderType == RenderType.translucent()) {
|
|
this.minecraft.getProfiler().push("translucent_sort");
|
|
double d = x - this.xTransparentOld;
|
|
double e = y - this.yTransparentOld;
|
|
double f = z - this.zTransparentOld;
|
|
if (d * d + e * e + f * f > 1.0) {
|
|
int i = SectionPos.posToSectionCoord(x);
|
|
int j = SectionPos.posToSectionCoord(y);
|
|
int k = SectionPos.posToSectionCoord(z);
|
|
boolean bl = i != SectionPos.posToSectionCoord(this.xTransparentOld)
|
|
|| k != SectionPos.posToSectionCoord(this.zTransparentOld)
|
|
|| j != SectionPos.posToSectionCoord(this.yTransparentOld);
|
|
this.xTransparentOld = x;
|
|
this.yTransparentOld = y;
|
|
this.zTransparentOld = z;
|
|
int l = 0;
|
|
|
|
for (SectionRenderDispatcher.RenderSection renderSection : this.visibleSections) {
|
|
if (l < 15 && (bl || renderSection.isAxisAlignedWith(i, j, k)) && renderSection.resortTransparency(renderType, this.sectionRenderDispatcher)) {
|
|
l++;
|
|
}
|
|
}
|
|
}
|
|
|
|
this.minecraft.getProfiler().pop();
|
|
}
|
|
|
|
this.minecraft.getProfiler().push("filterempty");
|
|
this.minecraft.getProfiler().popPush((Supplier<String>)(() -> "render_" + renderType));
|
|
boolean bl2 = renderType != RenderType.translucent();
|
|
ObjectListIterator<SectionRenderDispatcher.RenderSection> objectListIterator = this.visibleSections.listIterator(bl2 ? 0 : this.visibleSections.size());
|
|
ShaderInstance shaderInstance = RenderSystem.getShader();
|
|
shaderInstance.setDefaultUniforms(VertexFormat.Mode.QUADS, frustrumMatrix, projectionMatrix, this.minecraft.getWindow());
|
|
shaderInstance.apply();
|
|
Uniform uniform = shaderInstance.CHUNK_OFFSET;
|
|
|
|
while (bl2 ? objectListIterator.hasNext() : objectListIterator.hasPrevious()) {
|
|
SectionRenderDispatcher.RenderSection renderSection2 = bl2
|
|
? (SectionRenderDispatcher.RenderSection)objectListIterator.next()
|
|
: objectListIterator.previous();
|
|
if (!renderSection2.getCompiled().isEmpty(renderType)) {
|
|
VertexBuffer vertexBuffer = renderSection2.getBuffer(renderType);
|
|
BlockPos blockPos = renderSection2.getOrigin();
|
|
if (uniform != null) {
|
|
uniform.set((float)(blockPos.getX() - x), (float)(blockPos.getY() - y), (float)(blockPos.getZ() - z));
|
|
uniform.upload();
|
|
}
|
|
|
|
vertexBuffer.bind();
|
|
vertexBuffer.draw();
|
|
}
|
|
}
|
|
|
|
if (uniform != null) {
|
|
uniform.set(0.0F, 0.0F, 0.0F);
|
|
}
|
|
|
|
shaderInstance.clear();
|
|
VertexBuffer.unbind();
|
|
this.minecraft.getProfiler().pop();
|
|
renderType.clearRenderState();
|
|
}
|
|
|
|
private void renderDebug(PoseStack poseStack, MultiBufferSource buffer, Camera camera) {
|
|
if (this.minecraft.sectionPath || this.minecraft.sectionVisibility) {
|
|
double d = camera.getPosition().x();
|
|
double e = camera.getPosition().y();
|
|
double f = camera.getPosition().z();
|
|
|
|
for (SectionRenderDispatcher.RenderSection renderSection : this.visibleSections) {
|
|
SectionOcclusionGraph.Node node = this.sectionOcclusionGraph.getNode(renderSection);
|
|
if (node != null) {
|
|
BlockPos blockPos = renderSection.getOrigin();
|
|
poseStack.pushPose();
|
|
poseStack.translate(blockPos.getX() - d, blockPos.getY() - e, blockPos.getZ() - f);
|
|
Matrix4f matrix4f = poseStack.last().pose();
|
|
if (this.minecraft.sectionPath) {
|
|
VertexConsumer vertexConsumer = buffer.getBuffer(RenderType.lines());
|
|
int i = node.step == 0 ? 0 : Mth.hsvToRgb(node.step / 50.0F, 0.9F, 0.9F);
|
|
int j = i >> 16 & 0xFF;
|
|
int k = i >> 8 & 0xFF;
|
|
int l = i & 0xFF;
|
|
|
|
for (int m = 0; m < DIRECTIONS.length; m++) {
|
|
if (node.hasSourceDirection(m)) {
|
|
Direction direction = DIRECTIONS[m];
|
|
vertexConsumer.addVertex(matrix4f, 8.0F, 8.0F, 8.0F).setColor(j, k, l, 255).setNormal(direction.getStepX(), direction.getStepY(), direction.getStepZ());
|
|
vertexConsumer.addVertex(
|
|
matrix4f, (float)(8 - 16 * direction.getStepX()), (float)(8 - 16 * direction.getStepY()), (float)(8 - 16 * direction.getStepZ())
|
|
)
|
|
.setColor(j, k, l, 255)
|
|
.setNormal(direction.getStepX(), direction.getStepY(), direction.getStepZ());
|
|
}
|
|
}
|
|
}
|
|
|
|
if (this.minecraft.sectionVisibility && !renderSection.getCompiled().hasNoRenderableLayers()) {
|
|
VertexConsumer vertexConsumer = buffer.getBuffer(RenderType.lines());
|
|
int i = 0;
|
|
|
|
for (Direction direction2 : DIRECTIONS) {
|
|
for (Direction direction3 : DIRECTIONS) {
|
|
boolean bl = renderSection.getCompiled().facesCanSeeEachother(direction2, direction3);
|
|
if (!bl) {
|
|
i++;
|
|
vertexConsumer.addVertex(
|
|
matrix4f, (float)(8 + 8 * direction2.getStepX()), (float)(8 + 8 * direction2.getStepY()), (float)(8 + 8 * direction2.getStepZ())
|
|
)
|
|
.setColor(255, 0, 0, 255)
|
|
.setNormal(direction2.getStepX(), direction2.getStepY(), direction2.getStepZ());
|
|
vertexConsumer.addVertex(
|
|
matrix4f, (float)(8 + 8 * direction3.getStepX()), (float)(8 + 8 * direction3.getStepY()), (float)(8 + 8 * direction3.getStepZ())
|
|
)
|
|
.setColor(255, 0, 0, 255)
|
|
.setNormal(direction3.getStepX(), direction3.getStepY(), direction3.getStepZ());
|
|
}
|
|
}
|
|
}
|
|
|
|
if (i > 0) {
|
|
VertexConsumer vertexConsumer2 = buffer.getBuffer(RenderType.debugQuads());
|
|
float g = 0.5F;
|
|
float h = 0.2F;
|
|
vertexConsumer2.addVertex(matrix4f, 0.5F, 15.5F, 0.5F).setColor(0.9F, 0.9F, 0.0F, 0.2F);
|
|
vertexConsumer2.addVertex(matrix4f, 15.5F, 15.5F, 0.5F).setColor(0.9F, 0.9F, 0.0F, 0.2F);
|
|
vertexConsumer2.addVertex(matrix4f, 15.5F, 15.5F, 15.5F).setColor(0.9F, 0.9F, 0.0F, 0.2F);
|
|
vertexConsumer2.addVertex(matrix4f, 0.5F, 15.5F, 15.5F).setColor(0.9F, 0.9F, 0.0F, 0.2F);
|
|
vertexConsumer2.addVertex(matrix4f, 0.5F, 0.5F, 15.5F).setColor(0.9F, 0.9F, 0.0F, 0.2F);
|
|
vertexConsumer2.addVertex(matrix4f, 15.5F, 0.5F, 15.5F).setColor(0.9F, 0.9F, 0.0F, 0.2F);
|
|
vertexConsumer2.addVertex(matrix4f, 15.5F, 0.5F, 0.5F).setColor(0.9F, 0.9F, 0.0F, 0.2F);
|
|
vertexConsumer2.addVertex(matrix4f, 0.5F, 0.5F, 0.5F).setColor(0.9F, 0.9F, 0.0F, 0.2F);
|
|
vertexConsumer2.addVertex(matrix4f, 0.5F, 15.5F, 0.5F).setColor(0.9F, 0.9F, 0.0F, 0.2F);
|
|
vertexConsumer2.addVertex(matrix4f, 0.5F, 15.5F, 15.5F).setColor(0.9F, 0.9F, 0.0F, 0.2F);
|
|
vertexConsumer2.addVertex(matrix4f, 0.5F, 0.5F, 15.5F).setColor(0.9F, 0.9F, 0.0F, 0.2F);
|
|
vertexConsumer2.addVertex(matrix4f, 0.5F, 0.5F, 0.5F).setColor(0.9F, 0.9F, 0.0F, 0.2F);
|
|
vertexConsumer2.addVertex(matrix4f, 15.5F, 0.5F, 0.5F).setColor(0.9F, 0.9F, 0.0F, 0.2F);
|
|
vertexConsumer2.addVertex(matrix4f, 15.5F, 0.5F, 15.5F).setColor(0.9F, 0.9F, 0.0F, 0.2F);
|
|
vertexConsumer2.addVertex(matrix4f, 15.5F, 15.5F, 15.5F).setColor(0.9F, 0.9F, 0.0F, 0.2F);
|
|
vertexConsumer2.addVertex(matrix4f, 15.5F, 15.5F, 0.5F).setColor(0.9F, 0.9F, 0.0F, 0.2F);
|
|
vertexConsumer2.addVertex(matrix4f, 0.5F, 0.5F, 0.5F).setColor(0.9F, 0.9F, 0.0F, 0.2F);
|
|
vertexConsumer2.addVertex(matrix4f, 15.5F, 0.5F, 0.5F).setColor(0.9F, 0.9F, 0.0F, 0.2F);
|
|
vertexConsumer2.addVertex(matrix4f, 15.5F, 15.5F, 0.5F).setColor(0.9F, 0.9F, 0.0F, 0.2F);
|
|
vertexConsumer2.addVertex(matrix4f, 0.5F, 15.5F, 0.5F).setColor(0.9F, 0.9F, 0.0F, 0.2F);
|
|
vertexConsumer2.addVertex(matrix4f, 0.5F, 15.5F, 15.5F).setColor(0.9F, 0.9F, 0.0F, 0.2F);
|
|
vertexConsumer2.addVertex(matrix4f, 15.5F, 15.5F, 15.5F).setColor(0.9F, 0.9F, 0.0F, 0.2F);
|
|
vertexConsumer2.addVertex(matrix4f, 15.5F, 0.5F, 15.5F).setColor(0.9F, 0.9F, 0.0F, 0.2F);
|
|
vertexConsumer2.addVertex(matrix4f, 0.5F, 0.5F, 15.5F).setColor(0.9F, 0.9F, 0.0F, 0.2F);
|
|
}
|
|
}
|
|
|
|
poseStack.popPose();
|
|
}
|
|
}
|
|
}
|
|
|
|
if (this.capturedFrustum != null) {
|
|
poseStack.pushPose();
|
|
poseStack.translate(
|
|
(float)(this.frustumPos.x - camera.getPosition().x),
|
|
(float)(this.frustumPos.y - camera.getPosition().y),
|
|
(float)(this.frustumPos.z - camera.getPosition().z)
|
|
);
|
|
Matrix4f matrix4f2 = poseStack.last().pose();
|
|
VertexConsumer vertexConsumer3 = buffer.getBuffer(RenderType.debugQuads());
|
|
this.addFrustumQuad(vertexConsumer3, matrix4f2, 0, 1, 2, 3, 0, 1, 1);
|
|
this.addFrustumQuad(vertexConsumer3, matrix4f2, 4, 5, 6, 7, 1, 0, 0);
|
|
this.addFrustumQuad(vertexConsumer3, matrix4f2, 0, 1, 5, 4, 1, 1, 0);
|
|
this.addFrustumQuad(vertexConsumer3, matrix4f2, 2, 3, 7, 6, 0, 0, 1);
|
|
this.addFrustumQuad(vertexConsumer3, matrix4f2, 0, 4, 7, 3, 0, 1, 0);
|
|
this.addFrustumQuad(vertexConsumer3, matrix4f2, 1, 5, 6, 2, 1, 0, 1);
|
|
VertexConsumer vertexConsumer4 = buffer.getBuffer(RenderType.lines());
|
|
this.addFrustumVertex(vertexConsumer4, matrix4f2, 0);
|
|
this.addFrustumVertex(vertexConsumer4, matrix4f2, 1);
|
|
this.addFrustumVertex(vertexConsumer4, matrix4f2, 1);
|
|
this.addFrustumVertex(vertexConsumer4, matrix4f2, 2);
|
|
this.addFrustumVertex(vertexConsumer4, matrix4f2, 2);
|
|
this.addFrustumVertex(vertexConsumer4, matrix4f2, 3);
|
|
this.addFrustumVertex(vertexConsumer4, matrix4f2, 3);
|
|
this.addFrustumVertex(vertexConsumer4, matrix4f2, 0);
|
|
this.addFrustumVertex(vertexConsumer4, matrix4f2, 4);
|
|
this.addFrustumVertex(vertexConsumer4, matrix4f2, 5);
|
|
this.addFrustumVertex(vertexConsumer4, matrix4f2, 5);
|
|
this.addFrustumVertex(vertexConsumer4, matrix4f2, 6);
|
|
this.addFrustumVertex(vertexConsumer4, matrix4f2, 6);
|
|
this.addFrustumVertex(vertexConsumer4, matrix4f2, 7);
|
|
this.addFrustumVertex(vertexConsumer4, matrix4f2, 7);
|
|
this.addFrustumVertex(vertexConsumer4, matrix4f2, 4);
|
|
this.addFrustumVertex(vertexConsumer4, matrix4f2, 0);
|
|
this.addFrustumVertex(vertexConsumer4, matrix4f2, 4);
|
|
this.addFrustumVertex(vertexConsumer4, matrix4f2, 1);
|
|
this.addFrustumVertex(vertexConsumer4, matrix4f2, 5);
|
|
this.addFrustumVertex(vertexConsumer4, matrix4f2, 2);
|
|
this.addFrustumVertex(vertexConsumer4, matrix4f2, 6);
|
|
this.addFrustumVertex(vertexConsumer4, matrix4f2, 3);
|
|
this.addFrustumVertex(vertexConsumer4, matrix4f2, 7);
|
|
poseStack.popPose();
|
|
}
|
|
}
|
|
|
|
private void addFrustumVertex(VertexConsumer consumer, Matrix4f matrix, int vertexIndex) {
|
|
consumer.addVertex(matrix, this.frustumPoints[vertexIndex].x(), this.frustumPoints[vertexIndex].y(), this.frustumPoints[vertexIndex].z())
|
|
.setColor(-16777216)
|
|
.setNormal(0.0F, 0.0F, -1.0F);
|
|
}
|
|
|
|
private void addFrustumQuad(VertexConsumer consumer, Matrix4f matrix, int index1, int index2, int index3, int index4, int red, int green, int blue) {
|
|
float f = 0.25F;
|
|
consumer.addVertex(matrix, this.frustumPoints[index1].x(), this.frustumPoints[index1].y(), this.frustumPoints[index1].z())
|
|
.setColor((float)red, (float)green, (float)blue, 0.25F);
|
|
consumer.addVertex(matrix, this.frustumPoints[index2].x(), this.frustumPoints[index2].y(), this.frustumPoints[index2].z())
|
|
.setColor((float)red, (float)green, (float)blue, 0.25F);
|
|
consumer.addVertex(matrix, this.frustumPoints[index3].x(), this.frustumPoints[index3].y(), this.frustumPoints[index3].z())
|
|
.setColor((float)red, (float)green, (float)blue, 0.25F);
|
|
consumer.addVertex(matrix, this.frustumPoints[index4].x(), this.frustumPoints[index4].y(), this.frustumPoints[index4].z())
|
|
.setColor((float)red, (float)green, (float)blue, 0.25F);
|
|
}
|
|
|
|
public void captureFrustum() {
|
|
this.captureFrustum = true;
|
|
}
|
|
|
|
public void killFrustum() {
|
|
this.capturedFrustum = null;
|
|
}
|
|
|
|
public void tick() {
|
|
if (this.level.tickRateManager().runsNormally()) {
|
|
this.ticks++;
|
|
}
|
|
|
|
if (this.ticks % 20 == 0) {
|
|
Iterator<BlockDestructionProgress> iterator = this.destroyingBlocks.values().iterator();
|
|
|
|
while (iterator.hasNext()) {
|
|
BlockDestructionProgress blockDestructionProgress = (BlockDestructionProgress)iterator.next();
|
|
int i = blockDestructionProgress.getUpdatedRenderTick();
|
|
if (this.ticks - i > 400) {
|
|
iterator.remove();
|
|
this.removeProgress(blockDestructionProgress);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private void removeProgress(BlockDestructionProgress progress) {
|
|
long l = progress.getPos().asLong();
|
|
Set<BlockDestructionProgress> set = (Set<BlockDestructionProgress>)this.destructionProgress.get(l);
|
|
set.remove(progress);
|
|
if (set.isEmpty()) {
|
|
this.destructionProgress.remove(l);
|
|
}
|
|
}
|
|
|
|
private void renderEndSky(PoseStack poseStack) {
|
|
RenderSystem.enableBlend();
|
|
RenderSystem.depthMask(false);
|
|
RenderSystem.setShader(GameRenderer::getPositionTexColorShader);
|
|
RenderSystem.setShaderTexture(0, END_SKY_LOCATION);
|
|
Tesselator tesselator = Tesselator.getInstance();
|
|
|
|
for (int i = 0; i < 6; i++) {
|
|
poseStack.pushPose();
|
|
if (i == 1) {
|
|
poseStack.mulPose(Axis.XP.rotationDegrees(90.0F));
|
|
}
|
|
|
|
if (i == 2) {
|
|
poseStack.mulPose(Axis.XP.rotationDegrees(-90.0F));
|
|
}
|
|
|
|
if (i == 3) {
|
|
poseStack.mulPose(Axis.XP.rotationDegrees(180.0F));
|
|
}
|
|
|
|
if (i == 4) {
|
|
poseStack.mulPose(Axis.ZP.rotationDegrees(90.0F));
|
|
}
|
|
|
|
if (i == 5) {
|
|
poseStack.mulPose(Axis.ZP.rotationDegrees(-90.0F));
|
|
}
|
|
|
|
Matrix4f matrix4f = poseStack.last().pose();
|
|
BufferBuilder bufferBuilder = tesselator.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_TEX_COLOR);
|
|
bufferBuilder.addVertex(matrix4f, -100.0F, -100.0F, -100.0F).setUv(0.0F, 0.0F).setColor(-14145496);
|
|
bufferBuilder.addVertex(matrix4f, -100.0F, -100.0F, 100.0F).setUv(0.0F, 16.0F).setColor(-14145496);
|
|
bufferBuilder.addVertex(matrix4f, 100.0F, -100.0F, 100.0F).setUv(16.0F, 16.0F).setColor(-14145496);
|
|
bufferBuilder.addVertex(matrix4f, 100.0F, -100.0F, -100.0F).setUv(16.0F, 0.0F).setColor(-14145496);
|
|
BufferUploader.drawWithShader(bufferBuilder.buildOrThrow());
|
|
poseStack.popPose();
|
|
}
|
|
|
|
RenderSystem.depthMask(true);
|
|
RenderSystem.disableBlend();
|
|
}
|
|
|
|
public void renderSky(Matrix4f frustumMatrix, Matrix4f projectionMatrix, float partialTick, Camera camera, boolean isFoggy, Runnable skyFogSetup) {
|
|
skyFogSetup.run();
|
|
if (!isFoggy) {
|
|
FogType fogType = camera.getFluidInCamera();
|
|
if (fogType != FogType.POWDER_SNOW && fogType != FogType.LAVA && !this.doesMobEffectBlockSky(camera)) {
|
|
PoseStack poseStack = new PoseStack();
|
|
poseStack.mulPose(frustumMatrix);
|
|
if (this.minecraft.level.effects().skyType() == DimensionSpecialEffects.SkyType.END) {
|
|
this.renderEndSky(poseStack);
|
|
} else if (this.minecraft.level.effects().skyType() == DimensionSpecialEffects.SkyType.NORMAL) {
|
|
Vec3 vec3 = this.level.getSkyColor(this.minecraft.gameRenderer.getMainCamera().getPosition(), partialTick);
|
|
float f = (float)vec3.x;
|
|
float g = (float)vec3.y;
|
|
float h = (float)vec3.z;
|
|
FogRenderer.levelFogColor();
|
|
Tesselator tesselator = Tesselator.getInstance();
|
|
RenderSystem.depthMask(false);
|
|
RenderSystem.setShaderColor(f, g, h, 1.0F);
|
|
ShaderInstance shaderInstance = RenderSystem.getShader();
|
|
this.skyBuffer.bind();
|
|
this.skyBuffer.drawWithShader(poseStack.last().pose(), projectionMatrix, shaderInstance);
|
|
VertexBuffer.unbind();
|
|
RenderSystem.enableBlend();
|
|
float[] fs = this.level.effects().getSunriseColor(this.level.getTimeOfDay(partialTick), partialTick);
|
|
if (fs != null) {
|
|
RenderSystem.setShader(GameRenderer::getPositionColorShader);
|
|
RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F);
|
|
poseStack.pushPose();
|
|
poseStack.mulPose(Axis.XP.rotationDegrees(90.0F));
|
|
float i = Mth.sin(this.level.getSunAngle(partialTick)) < 0.0F ? 180.0F : 0.0F;
|
|
poseStack.mulPose(Axis.ZP.rotationDegrees(i));
|
|
poseStack.mulPose(Axis.ZP.rotationDegrees(90.0F));
|
|
float j = fs[0];
|
|
float k = fs[1];
|
|
float l = fs[2];
|
|
Matrix4f matrix4f = poseStack.last().pose();
|
|
BufferBuilder bufferBuilder = tesselator.begin(VertexFormat.Mode.TRIANGLE_FAN, DefaultVertexFormat.POSITION_COLOR);
|
|
bufferBuilder.addVertex(matrix4f, 0.0F, 100.0F, 0.0F).setColor(j, k, l, fs[3]);
|
|
int m = 16;
|
|
|
|
for (int n = 0; n <= 16; n++) {
|
|
float o = n * (float) (Math.PI * 2) / 16.0F;
|
|
float p = Mth.sin(o);
|
|
float q = Mth.cos(o);
|
|
bufferBuilder.addVertex(matrix4f, p * 120.0F, q * 120.0F, -q * 40.0F * fs[3]).setColor(fs[0], fs[1], fs[2], 0.0F);
|
|
}
|
|
|
|
BufferUploader.drawWithShader(bufferBuilder.buildOrThrow());
|
|
poseStack.popPose();
|
|
}
|
|
|
|
RenderSystem.blendFuncSeparate(
|
|
GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE, GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ZERO
|
|
);
|
|
poseStack.pushPose();
|
|
float i = 1.0F - this.level.getRainLevel(partialTick);
|
|
RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, i);
|
|
poseStack.mulPose(Axis.YP.rotationDegrees(-90.0F));
|
|
poseStack.mulPose(Axis.XP.rotationDegrees(this.level.getTimeOfDay(partialTick) * 360.0F));
|
|
Matrix4f matrix4f2 = poseStack.last().pose();
|
|
float k = 30.0F;
|
|
RenderSystem.setShader(GameRenderer::getPositionTexShader);
|
|
RenderSystem.setShaderTexture(0, SUN_LOCATION);
|
|
BufferBuilder bufferBuilder2 = tesselator.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_TEX);
|
|
bufferBuilder2.addVertex(matrix4f2, -k, 100.0F, -k).setUv(0.0F, 0.0F);
|
|
bufferBuilder2.addVertex(matrix4f2, k, 100.0F, -k).setUv(1.0F, 0.0F);
|
|
bufferBuilder2.addVertex(matrix4f2, k, 100.0F, k).setUv(1.0F, 1.0F);
|
|
bufferBuilder2.addVertex(matrix4f2, -k, 100.0F, k).setUv(0.0F, 1.0F);
|
|
BufferUploader.drawWithShader(bufferBuilder2.buildOrThrow());
|
|
k = 20.0F;
|
|
RenderSystem.setShaderTexture(0, MOON_LOCATION);
|
|
int r = this.level.getMoonPhase();
|
|
int s = r % 4;
|
|
int m = r / 4 % 2;
|
|
float t = (s + 0) / 4.0F;
|
|
float o = (m + 0) / 2.0F;
|
|
float p = (s + 1) / 4.0F;
|
|
float q = (m + 1) / 2.0F;
|
|
bufferBuilder2 = tesselator.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_TEX);
|
|
bufferBuilder2.addVertex(matrix4f2, -k, -100.0F, k).setUv(p, q);
|
|
bufferBuilder2.addVertex(matrix4f2, k, -100.0F, k).setUv(t, q);
|
|
bufferBuilder2.addVertex(matrix4f2, k, -100.0F, -k).setUv(t, o);
|
|
bufferBuilder2.addVertex(matrix4f2, -k, -100.0F, -k).setUv(p, o);
|
|
BufferUploader.drawWithShader(bufferBuilder2.buildOrThrow());
|
|
float u = this.level.getStarBrightness(partialTick) * i;
|
|
if (u > 0.0F) {
|
|
RenderSystem.setShaderColor(u, u, u, u);
|
|
FogRenderer.setupNoFog();
|
|
this.starBuffer.bind();
|
|
this.starBuffer.drawWithShader(poseStack.last().pose(), projectionMatrix, GameRenderer.getPositionShader());
|
|
VertexBuffer.unbind();
|
|
skyFogSetup.run();
|
|
}
|
|
|
|
RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F);
|
|
RenderSystem.disableBlend();
|
|
RenderSystem.defaultBlendFunc();
|
|
poseStack.popPose();
|
|
RenderSystem.setShaderColor(0.0F, 0.0F, 0.0F, 1.0F);
|
|
double d = this.minecraft.player.getEyePosition(partialTick).y - this.level.getLevelData().getHorizonHeight(this.level);
|
|
if (d < 0.0) {
|
|
poseStack.pushPose();
|
|
poseStack.translate(0.0F, 12.0F, 0.0F);
|
|
this.darkBuffer.bind();
|
|
this.darkBuffer.drawWithShader(poseStack.last().pose(), projectionMatrix, shaderInstance);
|
|
VertexBuffer.unbind();
|
|
poseStack.popPose();
|
|
}
|
|
|
|
RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F);
|
|
RenderSystem.depthMask(true);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private boolean doesMobEffectBlockSky(Camera camera) {
|
|
return !(camera.getEntity() instanceof LivingEntity livingEntity)
|
|
? false
|
|
: livingEntity.hasEffect(MobEffects.BLINDNESS) || livingEntity.hasEffect(MobEffects.DARKNESS);
|
|
}
|
|
|
|
public void renderClouds(PoseStack poseStack, Matrix4f frustumMatrix, Matrix4f projectionMatrix, float partialTick, double camX, double camY, double camZ) {
|
|
float f = this.level.effects().getCloudHeight();
|
|
if (!Float.isNaN(f)) {
|
|
float g = 12.0F;
|
|
float h = 4.0F;
|
|
double d = 2.0E-4;
|
|
double e = (this.ticks + partialTick) * 0.03F;
|
|
double i = (camX + e) / 12.0;
|
|
double j = f - (float)camY + 0.33F;
|
|
double k = camZ / 12.0 + 0.33F;
|
|
i -= Mth.floor(i / 2048.0) * 2048;
|
|
k -= Mth.floor(k / 2048.0) * 2048;
|
|
float l = (float)(i - Mth.floor(i));
|
|
float m = (float)(j / 4.0 - Mth.floor(j / 4.0)) * 4.0F;
|
|
float n = (float)(k - Mth.floor(k));
|
|
Vec3 vec3 = this.level.getCloudColor(partialTick);
|
|
int o = (int)Math.floor(i);
|
|
int p = (int)Math.floor(j / 4.0);
|
|
int q = (int)Math.floor(k);
|
|
if (o != this.prevCloudX
|
|
|| p != this.prevCloudY
|
|
|| q != this.prevCloudZ
|
|
|| this.minecraft.options.getCloudsType() != this.prevCloudsType
|
|
|| this.prevCloudColor.distanceToSqr(vec3) > 2.0E-4) {
|
|
this.prevCloudX = o;
|
|
this.prevCloudY = p;
|
|
this.prevCloudZ = q;
|
|
this.prevCloudColor = vec3;
|
|
this.prevCloudsType = this.minecraft.options.getCloudsType();
|
|
this.generateClouds = true;
|
|
}
|
|
|
|
if (this.generateClouds) {
|
|
this.generateClouds = false;
|
|
if (this.cloudBuffer != null) {
|
|
this.cloudBuffer.close();
|
|
}
|
|
|
|
this.cloudBuffer = new VertexBuffer(VertexBuffer.Usage.STATIC);
|
|
this.cloudBuffer.bind();
|
|
this.cloudBuffer.upload(this.buildClouds(Tesselator.getInstance(), i, j, k, vec3));
|
|
VertexBuffer.unbind();
|
|
}
|
|
|
|
FogRenderer.levelFogColor();
|
|
poseStack.pushPose();
|
|
poseStack.mulPose(frustumMatrix);
|
|
poseStack.scale(12.0F, 1.0F, 12.0F);
|
|
poseStack.translate(-l, m, -n);
|
|
if (this.cloudBuffer != null) {
|
|
this.cloudBuffer.bind();
|
|
int r = this.prevCloudsType == CloudStatus.FANCY ? 0 : 1;
|
|
|
|
for (int s = r; s < 2; s++) {
|
|
RenderType renderType = s == 0 ? RenderType.cloudsDepthOnly() : RenderType.clouds();
|
|
renderType.setupRenderState();
|
|
ShaderInstance shaderInstance = RenderSystem.getShader();
|
|
this.cloudBuffer.drawWithShader(poseStack.last().pose(), projectionMatrix, shaderInstance);
|
|
renderType.clearRenderState();
|
|
}
|
|
|
|
VertexBuffer.unbind();
|
|
}
|
|
|
|
poseStack.popPose();
|
|
}
|
|
}
|
|
|
|
private MeshData buildClouds(Tesselator tesselator, double x, double y, double z, Vec3 cloudColor) {
|
|
float f = 4.0F;
|
|
float g = 0.00390625F;
|
|
int i = 8;
|
|
int j = 4;
|
|
float h = 9.765625E-4F;
|
|
float k = Mth.floor(x) * 0.00390625F;
|
|
float l = Mth.floor(z) * 0.00390625F;
|
|
float m = (float)cloudColor.x;
|
|
float n = (float)cloudColor.y;
|
|
float o = (float)cloudColor.z;
|
|
float p = m * 0.9F;
|
|
float q = n * 0.9F;
|
|
float r = o * 0.9F;
|
|
float s = m * 0.7F;
|
|
float t = n * 0.7F;
|
|
float u = o * 0.7F;
|
|
float v = m * 0.8F;
|
|
float w = n * 0.8F;
|
|
float aa = o * 0.8F;
|
|
BufferBuilder bufferBuilder = tesselator.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_TEX_COLOR_NORMAL);
|
|
float ab = (float)Math.floor(y / 4.0) * 4.0F;
|
|
if (this.prevCloudsType == CloudStatus.FANCY) {
|
|
for (int ac = -3; ac <= 4; ac++) {
|
|
for (int ad = -3; ad <= 4; ad++) {
|
|
float ae = ac * 8;
|
|
float af = ad * 8;
|
|
if (ab > -5.0F) {
|
|
bufferBuilder.addVertex(ae + 0.0F, ab + 0.0F, af + 8.0F)
|
|
.setUv((ae + 0.0F) * 0.00390625F + k, (af + 8.0F) * 0.00390625F + l)
|
|
.setColor(s, t, u, 0.8F)
|
|
.setNormal(0.0F, -1.0F, 0.0F);
|
|
bufferBuilder.addVertex(ae + 8.0F, ab + 0.0F, af + 8.0F)
|
|
.setUv((ae + 8.0F) * 0.00390625F + k, (af + 8.0F) * 0.00390625F + l)
|
|
.setColor(s, t, u, 0.8F)
|
|
.setNormal(0.0F, -1.0F, 0.0F);
|
|
bufferBuilder.addVertex(ae + 8.0F, ab + 0.0F, af + 0.0F)
|
|
.setUv((ae + 8.0F) * 0.00390625F + k, (af + 0.0F) * 0.00390625F + l)
|
|
.setColor(s, t, u, 0.8F)
|
|
.setNormal(0.0F, -1.0F, 0.0F);
|
|
bufferBuilder.addVertex(ae + 0.0F, ab + 0.0F, af + 0.0F)
|
|
.setUv((ae + 0.0F) * 0.00390625F + k, (af + 0.0F) * 0.00390625F + l)
|
|
.setColor(s, t, u, 0.8F)
|
|
.setNormal(0.0F, -1.0F, 0.0F);
|
|
}
|
|
|
|
if (ab <= 5.0F) {
|
|
bufferBuilder.addVertex(ae + 0.0F, ab + 4.0F - 9.765625E-4F, af + 8.0F)
|
|
.setUv((ae + 0.0F) * 0.00390625F + k, (af + 8.0F) * 0.00390625F + l)
|
|
.setColor(m, n, o, 0.8F)
|
|
.setNormal(0.0F, 1.0F, 0.0F);
|
|
bufferBuilder.addVertex(ae + 8.0F, ab + 4.0F - 9.765625E-4F, af + 8.0F)
|
|
.setUv((ae + 8.0F) * 0.00390625F + k, (af + 8.0F) * 0.00390625F + l)
|
|
.setColor(m, n, o, 0.8F)
|
|
.setNormal(0.0F, 1.0F, 0.0F);
|
|
bufferBuilder.addVertex(ae + 8.0F, ab + 4.0F - 9.765625E-4F, af + 0.0F)
|
|
.setUv((ae + 8.0F) * 0.00390625F + k, (af + 0.0F) * 0.00390625F + l)
|
|
.setColor(m, n, o, 0.8F)
|
|
.setNormal(0.0F, 1.0F, 0.0F);
|
|
bufferBuilder.addVertex(ae + 0.0F, ab + 4.0F - 9.765625E-4F, af + 0.0F)
|
|
.setUv((ae + 0.0F) * 0.00390625F + k, (af + 0.0F) * 0.00390625F + l)
|
|
.setColor(m, n, o, 0.8F)
|
|
.setNormal(0.0F, 1.0F, 0.0F);
|
|
}
|
|
|
|
if (ac > -1) {
|
|
for (int ag = 0; ag < 8; ag++) {
|
|
bufferBuilder.addVertex(ae + ag + 0.0F, ab + 0.0F, af + 8.0F)
|
|
.setUv((ae + ag + 0.5F) * 0.00390625F + k, (af + 8.0F) * 0.00390625F + l)
|
|
.setColor(p, q, r, 0.8F)
|
|
.setNormal(-1.0F, 0.0F, 0.0F);
|
|
bufferBuilder.addVertex(ae + ag + 0.0F, ab + 4.0F, af + 8.0F)
|
|
.setUv((ae + ag + 0.5F) * 0.00390625F + k, (af + 8.0F) * 0.00390625F + l)
|
|
.setColor(p, q, r, 0.8F)
|
|
.setNormal(-1.0F, 0.0F, 0.0F);
|
|
bufferBuilder.addVertex(ae + ag + 0.0F, ab + 4.0F, af + 0.0F)
|
|
.setUv((ae + ag + 0.5F) * 0.00390625F + k, (af + 0.0F) * 0.00390625F + l)
|
|
.setColor(p, q, r, 0.8F)
|
|
.setNormal(-1.0F, 0.0F, 0.0F);
|
|
bufferBuilder.addVertex(ae + ag + 0.0F, ab + 0.0F, af + 0.0F)
|
|
.setUv((ae + ag + 0.5F) * 0.00390625F + k, (af + 0.0F) * 0.00390625F + l)
|
|
.setColor(p, q, r, 0.8F)
|
|
.setNormal(-1.0F, 0.0F, 0.0F);
|
|
}
|
|
}
|
|
|
|
if (ac <= 1) {
|
|
for (int ag = 0; ag < 8; ag++) {
|
|
bufferBuilder.addVertex(ae + ag + 1.0F - 9.765625E-4F, ab + 0.0F, af + 8.0F)
|
|
.setUv((ae + ag + 0.5F) * 0.00390625F + k, (af + 8.0F) * 0.00390625F + l)
|
|
.setColor(p, q, r, 0.8F)
|
|
.setNormal(1.0F, 0.0F, 0.0F);
|
|
bufferBuilder.addVertex(ae + ag + 1.0F - 9.765625E-4F, ab + 4.0F, af + 8.0F)
|
|
.setUv((ae + ag + 0.5F) * 0.00390625F + k, (af + 8.0F) * 0.00390625F + l)
|
|
.setColor(p, q, r, 0.8F)
|
|
.setNormal(1.0F, 0.0F, 0.0F);
|
|
bufferBuilder.addVertex(ae + ag + 1.0F - 9.765625E-4F, ab + 4.0F, af + 0.0F)
|
|
.setUv((ae + ag + 0.5F) * 0.00390625F + k, (af + 0.0F) * 0.00390625F + l)
|
|
.setColor(p, q, r, 0.8F)
|
|
.setNormal(1.0F, 0.0F, 0.0F);
|
|
bufferBuilder.addVertex(ae + ag + 1.0F - 9.765625E-4F, ab + 0.0F, af + 0.0F)
|
|
.setUv((ae + ag + 0.5F) * 0.00390625F + k, (af + 0.0F) * 0.00390625F + l)
|
|
.setColor(p, q, r, 0.8F)
|
|
.setNormal(1.0F, 0.0F, 0.0F);
|
|
}
|
|
}
|
|
|
|
if (ad > -1) {
|
|
for (int ag = 0; ag < 8; ag++) {
|
|
bufferBuilder.addVertex(ae + 0.0F, ab + 4.0F, af + ag + 0.0F)
|
|
.setUv((ae + 0.0F) * 0.00390625F + k, (af + ag + 0.5F) * 0.00390625F + l)
|
|
.setColor(v, w, aa, 0.8F)
|
|
.setNormal(0.0F, 0.0F, -1.0F);
|
|
bufferBuilder.addVertex(ae + 8.0F, ab + 4.0F, af + ag + 0.0F)
|
|
.setUv((ae + 8.0F) * 0.00390625F + k, (af + ag + 0.5F) * 0.00390625F + l)
|
|
.setColor(v, w, aa, 0.8F)
|
|
.setNormal(0.0F, 0.0F, -1.0F);
|
|
bufferBuilder.addVertex(ae + 8.0F, ab + 0.0F, af + ag + 0.0F)
|
|
.setUv((ae + 8.0F) * 0.00390625F + k, (af + ag + 0.5F) * 0.00390625F + l)
|
|
.setColor(v, w, aa, 0.8F)
|
|
.setNormal(0.0F, 0.0F, -1.0F);
|
|
bufferBuilder.addVertex(ae + 0.0F, ab + 0.0F, af + ag + 0.0F)
|
|
.setUv((ae + 0.0F) * 0.00390625F + k, (af + ag + 0.5F) * 0.00390625F + l)
|
|
.setColor(v, w, aa, 0.8F)
|
|
.setNormal(0.0F, 0.0F, -1.0F);
|
|
}
|
|
}
|
|
|
|
if (ad <= 1) {
|
|
for (int ag = 0; ag < 8; ag++) {
|
|
bufferBuilder.addVertex(ae + 0.0F, ab + 4.0F, af + ag + 1.0F - 9.765625E-4F)
|
|
.setUv((ae + 0.0F) * 0.00390625F + k, (af + ag + 0.5F) * 0.00390625F + l)
|
|
.setColor(v, w, aa, 0.8F)
|
|
.setNormal(0.0F, 0.0F, 1.0F);
|
|
bufferBuilder.addVertex(ae + 8.0F, ab + 4.0F, af + ag + 1.0F - 9.765625E-4F)
|
|
.setUv((ae + 8.0F) * 0.00390625F + k, (af + ag + 0.5F) * 0.00390625F + l)
|
|
.setColor(v, w, aa, 0.8F)
|
|
.setNormal(0.0F, 0.0F, 1.0F);
|
|
bufferBuilder.addVertex(ae + 8.0F, ab + 0.0F, af + ag + 1.0F - 9.765625E-4F)
|
|
.setUv((ae + 8.0F) * 0.00390625F + k, (af + ag + 0.5F) * 0.00390625F + l)
|
|
.setColor(v, w, aa, 0.8F)
|
|
.setNormal(0.0F, 0.0F, 1.0F);
|
|
bufferBuilder.addVertex(ae + 0.0F, ab + 0.0F, af + ag + 1.0F - 9.765625E-4F)
|
|
.setUv((ae + 0.0F) * 0.00390625F + k, (af + ag + 0.5F) * 0.00390625F + l)
|
|
.setColor(v, w, aa, 0.8F)
|
|
.setNormal(0.0F, 0.0F, 1.0F);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
int ac = 1;
|
|
int ad = 32;
|
|
|
|
for (int ah = -32; ah < 32; ah += 32) {
|
|
for (int ai = -32; ai < 32; ai += 32) {
|
|
bufferBuilder.addVertex(ah + 0, ab, ai + 32)
|
|
.setUv((ah + 0) * 0.00390625F + k, (ai + 32) * 0.00390625F + l)
|
|
.setColor(m, n, o, 0.8F)
|
|
.setNormal(0.0F, -1.0F, 0.0F);
|
|
bufferBuilder.addVertex(ah + 32, ab, ai + 32)
|
|
.setUv((ah + 32) * 0.00390625F + k, (ai + 32) * 0.00390625F + l)
|
|
.setColor(m, n, o, 0.8F)
|
|
.setNormal(0.0F, -1.0F, 0.0F);
|
|
bufferBuilder.addVertex(ah + 32, ab, ai + 0)
|
|
.setUv((ah + 32) * 0.00390625F + k, (ai + 0) * 0.00390625F + l)
|
|
.setColor(m, n, o, 0.8F)
|
|
.setNormal(0.0F, -1.0F, 0.0F);
|
|
bufferBuilder.addVertex(ah + 0, ab, ai + 0)
|
|
.setUv((ah + 0) * 0.00390625F + k, (ai + 0) * 0.00390625F + l)
|
|
.setColor(m, n, o, 0.8F)
|
|
.setNormal(0.0F, -1.0F, 0.0F);
|
|
}
|
|
}
|
|
}
|
|
|
|
return bufferBuilder.buildOrThrow();
|
|
}
|
|
|
|
private void compileSections(Camera camera) {
|
|
this.minecraft.getProfiler().push("populate_sections_to_compile");
|
|
LevelLightEngine levelLightEngine = this.level.getLightEngine();
|
|
RenderRegionCache renderRegionCache = new RenderRegionCache();
|
|
BlockPos blockPos = camera.getBlockPosition();
|
|
List<SectionRenderDispatcher.RenderSection> list = Lists.<SectionRenderDispatcher.RenderSection>newArrayList();
|
|
|
|
for (SectionRenderDispatcher.RenderSection renderSection : this.visibleSections) {
|
|
SectionPos sectionPos = SectionPos.of(renderSection.getOrigin());
|
|
if (renderSection.isDirty() && levelLightEngine.lightOnInSection(sectionPos)) {
|
|
boolean bl = false;
|
|
if (this.minecraft.options.prioritizeChunkUpdates().get() == PrioritizeChunkUpdates.NEARBY) {
|
|
BlockPos blockPos2 = renderSection.getOrigin().offset(8, 8, 8);
|
|
bl = blockPos2.distSqr(blockPos) < 768.0 || renderSection.isDirtyFromPlayer();
|
|
} else if (this.minecraft.options.prioritizeChunkUpdates().get() == PrioritizeChunkUpdates.PLAYER_AFFECTED) {
|
|
bl = renderSection.isDirtyFromPlayer();
|
|
}
|
|
|
|
if (bl) {
|
|
this.minecraft.getProfiler().push("build_near_sync");
|
|
this.sectionRenderDispatcher.rebuildSectionSync(renderSection, renderRegionCache);
|
|
renderSection.setNotDirty();
|
|
this.minecraft.getProfiler().pop();
|
|
} else {
|
|
list.add(renderSection);
|
|
}
|
|
}
|
|
}
|
|
|
|
this.minecraft.getProfiler().popPush("upload");
|
|
this.sectionRenderDispatcher.uploadAllPendingUploads();
|
|
this.minecraft.getProfiler().popPush("schedule_async_compile");
|
|
|
|
for (SectionRenderDispatcher.RenderSection renderSectionx : list) {
|
|
renderSectionx.rebuildSectionAsync(this.sectionRenderDispatcher, renderRegionCache);
|
|
renderSectionx.setNotDirty();
|
|
}
|
|
|
|
this.minecraft.getProfiler().pop();
|
|
}
|
|
|
|
private void renderWorldBorder(Camera camera) {
|
|
WorldBorder worldBorder = this.level.getWorldBorder();
|
|
double d = this.minecraft.options.getEffectiveRenderDistance() * 16;
|
|
if (!(camera.getPosition().x < worldBorder.getMaxX() - d)
|
|
|| !(camera.getPosition().x > worldBorder.getMinX() + d)
|
|
|| !(camera.getPosition().z < worldBorder.getMaxZ() - d)
|
|
|| !(camera.getPosition().z > worldBorder.getMinZ() + d)) {
|
|
double e = 1.0 - worldBorder.getDistanceToBorder(camera.getPosition().x, camera.getPosition().z) / d;
|
|
e = Math.pow(e, 4.0);
|
|
e = Mth.clamp(e, 0.0, 1.0);
|
|
double f = camera.getPosition().x;
|
|
double g = camera.getPosition().z;
|
|
double h = this.minecraft.gameRenderer.getDepthFar();
|
|
RenderSystem.enableBlend();
|
|
RenderSystem.enableDepthTest();
|
|
RenderSystem.blendFuncSeparate(
|
|
GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE, GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ZERO
|
|
);
|
|
RenderSystem.setShaderTexture(0, FORCEFIELD_LOCATION);
|
|
RenderSystem.depthMask(Minecraft.useShaderTransparency());
|
|
int i = worldBorder.getStatus().getColor();
|
|
float j = (i >> 16 & 0xFF) / 255.0F;
|
|
float k = (i >> 8 & 0xFF) / 255.0F;
|
|
float l = (i & 0xFF) / 255.0F;
|
|
RenderSystem.setShaderColor(j, k, l, (float)e);
|
|
RenderSystem.setShader(GameRenderer::getPositionTexShader);
|
|
RenderSystem.polygonOffset(-3.0F, -3.0F);
|
|
RenderSystem.enablePolygonOffset();
|
|
RenderSystem.disableCull();
|
|
float m = (float)(Util.getMillis() % 3000L) / 3000.0F;
|
|
float n = (float)(-Mth.frac(camera.getPosition().y * 0.5));
|
|
float o = n + (float)h;
|
|
BufferBuilder bufferBuilder = Tesselator.getInstance().begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_TEX);
|
|
double p = Math.max(Mth.floor(g - d), worldBorder.getMinZ());
|
|
double q = Math.min(Mth.ceil(g + d), worldBorder.getMaxZ());
|
|
float r = (Mth.floor(p) & 1) * 0.5F;
|
|
if (f > worldBorder.getMaxX() - d) {
|
|
float s = r;
|
|
|
|
for (double t = p; t < q; s += 0.5F) {
|
|
double u = Math.min(1.0, q - t);
|
|
float v = (float)u * 0.5F;
|
|
bufferBuilder.addVertex((float)(worldBorder.getMaxX() - f), (float)(-h), (float)(t - g)).setUv(m - s, m + o);
|
|
bufferBuilder.addVertex((float)(worldBorder.getMaxX() - f), (float)(-h), (float)(t + u - g)).setUv(m - (v + s), m + o);
|
|
bufferBuilder.addVertex((float)(worldBorder.getMaxX() - f), (float)h, (float)(t + u - g)).setUv(m - (v + s), m + n);
|
|
bufferBuilder.addVertex((float)(worldBorder.getMaxX() - f), (float)h, (float)(t - g)).setUv(m - s, m + n);
|
|
t++;
|
|
}
|
|
}
|
|
|
|
if (f < worldBorder.getMinX() + d) {
|
|
float s = r;
|
|
|
|
for (double t = p; t < q; s += 0.5F) {
|
|
double u = Math.min(1.0, q - t);
|
|
float v = (float)u * 0.5F;
|
|
bufferBuilder.addVertex((float)(worldBorder.getMinX() - f), (float)(-h), (float)(t - g)).setUv(m + s, m + o);
|
|
bufferBuilder.addVertex((float)(worldBorder.getMinX() - f), (float)(-h), (float)(t + u - g)).setUv(m + v + s, m + o);
|
|
bufferBuilder.addVertex((float)(worldBorder.getMinX() - f), (float)h, (float)(t + u - g)).setUv(m + v + s, m + n);
|
|
bufferBuilder.addVertex((float)(worldBorder.getMinX() - f), (float)h, (float)(t - g)).setUv(m + s, m + n);
|
|
t++;
|
|
}
|
|
}
|
|
|
|
p = Math.max(Mth.floor(f - d), worldBorder.getMinX());
|
|
q = Math.min(Mth.ceil(f + d), worldBorder.getMaxX());
|
|
r = (Mth.floor(p) & 1) * 0.5F;
|
|
if (g > worldBorder.getMaxZ() - d) {
|
|
float s = r;
|
|
|
|
for (double t = p; t < q; s += 0.5F) {
|
|
double u = Math.min(1.0, q - t);
|
|
float v = (float)u * 0.5F;
|
|
bufferBuilder.addVertex((float)(t - f), (float)(-h), (float)(worldBorder.getMaxZ() - g)).setUv(m + s, m + o);
|
|
bufferBuilder.addVertex((float)(t + u - f), (float)(-h), (float)(worldBorder.getMaxZ() - g)).setUv(m + v + s, m + o);
|
|
bufferBuilder.addVertex((float)(t + u - f), (float)h, (float)(worldBorder.getMaxZ() - g)).setUv(m + v + s, m + n);
|
|
bufferBuilder.addVertex((float)(t - f), (float)h, (float)(worldBorder.getMaxZ() - g)).setUv(m + s, m + n);
|
|
t++;
|
|
}
|
|
}
|
|
|
|
if (g < worldBorder.getMinZ() + d) {
|
|
float s = r;
|
|
|
|
for (double t = p; t < q; s += 0.5F) {
|
|
double u = Math.min(1.0, q - t);
|
|
float v = (float)u * 0.5F;
|
|
bufferBuilder.addVertex((float)(t - f), (float)(-h), (float)(worldBorder.getMinZ() - g)).setUv(m - s, m + o);
|
|
bufferBuilder.addVertex((float)(t + u - f), (float)(-h), (float)(worldBorder.getMinZ() - g)).setUv(m - (v + s), m + o);
|
|
bufferBuilder.addVertex((float)(t + u - f), (float)h, (float)(worldBorder.getMinZ() - g)).setUv(m - (v + s), m + n);
|
|
bufferBuilder.addVertex((float)(t - f), (float)h, (float)(worldBorder.getMinZ() - g)).setUv(m - s, m + n);
|
|
t++;
|
|
}
|
|
}
|
|
|
|
MeshData meshData = bufferBuilder.build();
|
|
if (meshData != null) {
|
|
BufferUploader.drawWithShader(meshData);
|
|
}
|
|
|
|
RenderSystem.enableCull();
|
|
RenderSystem.polygonOffset(0.0F, 0.0F);
|
|
RenderSystem.disablePolygonOffset();
|
|
RenderSystem.disableBlend();
|
|
RenderSystem.defaultBlendFunc();
|
|
RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F);
|
|
RenderSystem.depthMask(true);
|
|
}
|
|
}
|
|
|
|
private void renderHitOutline(
|
|
PoseStack poseStack, VertexConsumer consumer, Entity entity, double camX, double camY, double camZ, BlockPos pos, BlockState state
|
|
) {
|
|
renderShape(
|
|
poseStack,
|
|
consumer,
|
|
state.getShape(this.level, pos, CollisionContext.of(entity)),
|
|
pos.getX() - camX,
|
|
pos.getY() - camY,
|
|
pos.getZ() - camZ,
|
|
0.0F,
|
|
0.0F,
|
|
0.0F,
|
|
0.4F
|
|
);
|
|
}
|
|
|
|
private static Vec3 mixColor(float hue) {
|
|
float f = 5.99999F;
|
|
int i = (int)(Mth.clamp(hue, 0.0F, 1.0F) * 5.99999F);
|
|
float g = hue * 5.99999F - i;
|
|
|
|
return switch (i) {
|
|
case 0 -> new Vec3(1.0, g, 0.0);
|
|
case 1 -> new Vec3(1.0F - g, 1.0, 0.0);
|
|
case 2 -> new Vec3(0.0, 1.0, g);
|
|
case 3 -> new Vec3(0.0, 1.0 - g, 1.0);
|
|
case 4 -> new Vec3(g, 0.0, 1.0);
|
|
case 5 -> new Vec3(1.0, 0.0, 1.0 - g);
|
|
default -> throw new IllegalStateException("Unexpected value: " + i);
|
|
};
|
|
}
|
|
|
|
private static Vec3 shiftHue(float red, float green, float blue, float hue) {
|
|
Vec3 vec3 = mixColor(hue).scale(red);
|
|
Vec3 vec32 = mixColor((hue + 0.33333334F) % 1.0F).scale(green);
|
|
Vec3 vec33 = mixColor((hue + 0.6666667F) % 1.0F).scale(blue);
|
|
Vec3 vec34 = vec3.add(vec32).add(vec33);
|
|
double d = Math.max(Math.max(1.0, vec34.x), Math.max(vec34.y, vec34.z));
|
|
return new Vec3(vec34.x / d, vec34.y / d, vec34.z / d);
|
|
}
|
|
|
|
public static void renderVoxelShape(
|
|
PoseStack poseStack, VertexConsumer consumer, VoxelShape shape, double x, double y, double z, float red, float green, float blue, float alpha, boolean bl
|
|
) {
|
|
List<AABB> list = shape.toAabbs();
|
|
if (!list.isEmpty()) {
|
|
int i = bl ? list.size() : list.size() * 8;
|
|
renderShape(poseStack, consumer, Shapes.create((AABB)list.get(0)), x, y, z, red, green, blue, alpha);
|
|
|
|
for (int j = 1; j < list.size(); j++) {
|
|
AABB aABB = (AABB)list.get(j);
|
|
float f = (float)j / i;
|
|
Vec3 vec3 = shiftHue(red, green, blue, f);
|
|
renderShape(poseStack, consumer, Shapes.create(aABB), x, y, z, (float)vec3.x, (float)vec3.y, (float)vec3.z, alpha);
|
|
}
|
|
}
|
|
}
|
|
|
|
private static void renderShape(
|
|
PoseStack poseStack, VertexConsumer consumer, VoxelShape shape, double x, double y, double z, float red, float green, float blue, float alpha
|
|
) {
|
|
PoseStack.Pose pose = poseStack.last();
|
|
shape.forAllEdges((k, l, m, n, o, p) -> {
|
|
float q = (float)(n - k);
|
|
float r = (float)(o - l);
|
|
float s = (float)(p - m);
|
|
float t = Mth.sqrt(q * q + r * r + s * s);
|
|
q /= t;
|
|
r /= t;
|
|
s /= t;
|
|
consumer.addVertex(pose, (float)(k + x), (float)(l + y), (float)(m + z)).setColor(red, green, blue, alpha).setNormal(pose, q, r, s);
|
|
consumer.addVertex(pose, (float)(n + x), (float)(o + y), (float)(p + z)).setColor(red, green, blue, alpha).setNormal(pose, q, r, s);
|
|
});
|
|
}
|
|
|
|
public static void renderLineBox(
|
|
VertexConsumer consumer, double minX, double minY, double minZ, double maxX, double maxY, double maxZ, float red, float green, float blue, float alpha
|
|
) {
|
|
renderLineBox(new PoseStack(), consumer, minX, minY, minZ, maxX, maxY, maxZ, red, green, blue, alpha, red, green, blue);
|
|
}
|
|
|
|
public static void renderLineBox(PoseStack poseStack, VertexConsumer buffer, AABB box, float red, float green, float blue, float alpha) {
|
|
renderLineBox(poseStack, buffer, box.minX, box.minY, box.minZ, box.maxX, box.maxY, box.maxZ, red, green, blue, alpha, red, green, blue);
|
|
}
|
|
|
|
public static void renderLineBox(
|
|
PoseStack poseStack,
|
|
VertexConsumer consumer,
|
|
double minX,
|
|
double minY,
|
|
double minZ,
|
|
double maxX,
|
|
double maxY,
|
|
double maxZ,
|
|
float red,
|
|
float green,
|
|
float blue,
|
|
float alpha
|
|
) {
|
|
renderLineBox(poseStack, consumer, minX, minY, minZ, maxX, maxY, maxZ, red, green, blue, alpha, red, green, blue);
|
|
}
|
|
|
|
public static void renderLineBox(
|
|
PoseStack poseStack,
|
|
VertexConsumer consumer,
|
|
double minX,
|
|
double minY,
|
|
double minZ,
|
|
double maxX,
|
|
double maxY,
|
|
double maxZ,
|
|
float red,
|
|
float green,
|
|
float blue,
|
|
float alpha,
|
|
float red2,
|
|
float green2,
|
|
float blue2
|
|
) {
|
|
PoseStack.Pose pose = poseStack.last();
|
|
float f = (float)minX;
|
|
float g = (float)minY;
|
|
float h = (float)minZ;
|
|
float i = (float)maxX;
|
|
float j = (float)maxY;
|
|
float k = (float)maxZ;
|
|
consumer.addVertex(pose, f, g, h).setColor(red, green2, blue2, alpha).setNormal(pose, 1.0F, 0.0F, 0.0F);
|
|
consumer.addVertex(pose, i, g, h).setColor(red, green2, blue2, alpha).setNormal(pose, 1.0F, 0.0F, 0.0F);
|
|
consumer.addVertex(pose, f, g, h).setColor(red2, green, blue2, alpha).setNormal(pose, 0.0F, 1.0F, 0.0F);
|
|
consumer.addVertex(pose, f, j, h).setColor(red2, green, blue2, alpha).setNormal(pose, 0.0F, 1.0F, 0.0F);
|
|
consumer.addVertex(pose, f, g, h).setColor(red2, green2, blue, alpha).setNormal(pose, 0.0F, 0.0F, 1.0F);
|
|
consumer.addVertex(pose, f, g, k).setColor(red2, green2, blue, alpha).setNormal(pose, 0.0F, 0.0F, 1.0F);
|
|
consumer.addVertex(pose, i, g, h).setColor(red, green, blue, alpha).setNormal(pose, 0.0F, 1.0F, 0.0F);
|
|
consumer.addVertex(pose, i, j, h).setColor(red, green, blue, alpha).setNormal(pose, 0.0F, 1.0F, 0.0F);
|
|
consumer.addVertex(pose, i, j, h).setColor(red, green, blue, alpha).setNormal(pose, -1.0F, 0.0F, 0.0F);
|
|
consumer.addVertex(pose, f, j, h).setColor(red, green, blue, alpha).setNormal(pose, -1.0F, 0.0F, 0.0F);
|
|
consumer.addVertex(pose, f, j, h).setColor(red, green, blue, alpha).setNormal(pose, 0.0F, 0.0F, 1.0F);
|
|
consumer.addVertex(pose, f, j, k).setColor(red, green, blue, alpha).setNormal(pose, 0.0F, 0.0F, 1.0F);
|
|
consumer.addVertex(pose, f, j, k).setColor(red, green, blue, alpha).setNormal(pose, 0.0F, -1.0F, 0.0F);
|
|
consumer.addVertex(pose, f, g, k).setColor(red, green, blue, alpha).setNormal(pose, 0.0F, -1.0F, 0.0F);
|
|
consumer.addVertex(pose, f, g, k).setColor(red, green, blue, alpha).setNormal(pose, 1.0F, 0.0F, 0.0F);
|
|
consumer.addVertex(pose, i, g, k).setColor(red, green, blue, alpha).setNormal(pose, 1.0F, 0.0F, 0.0F);
|
|
consumer.addVertex(pose, i, g, k).setColor(red, green, blue, alpha).setNormal(pose, 0.0F, 0.0F, -1.0F);
|
|
consumer.addVertex(pose, i, g, h).setColor(red, green, blue, alpha).setNormal(pose, 0.0F, 0.0F, -1.0F);
|
|
consumer.addVertex(pose, f, j, k).setColor(red, green, blue, alpha).setNormal(pose, 1.0F, 0.0F, 0.0F);
|
|
consumer.addVertex(pose, i, j, k).setColor(red, green, blue, alpha).setNormal(pose, 1.0F, 0.0F, 0.0F);
|
|
consumer.addVertex(pose, i, g, k).setColor(red, green, blue, alpha).setNormal(pose, 0.0F, 1.0F, 0.0F);
|
|
consumer.addVertex(pose, i, j, k).setColor(red, green, blue, alpha).setNormal(pose, 0.0F, 1.0F, 0.0F);
|
|
consumer.addVertex(pose, i, j, h).setColor(red, green, blue, alpha).setNormal(pose, 0.0F, 0.0F, 1.0F);
|
|
consumer.addVertex(pose, i, j, k).setColor(red, green, blue, alpha).setNormal(pose, 0.0F, 0.0F, 1.0F);
|
|
}
|
|
|
|
public static void addChainedFilledBoxVertices(
|
|
PoseStack poseStack,
|
|
VertexConsumer consumer,
|
|
double minX,
|
|
double minY,
|
|
double minZ,
|
|
double maxX,
|
|
double maxY,
|
|
double maxZ,
|
|
float red,
|
|
float green,
|
|
float blue,
|
|
float alpha
|
|
) {
|
|
addChainedFilledBoxVertices(poseStack, consumer, (float)minX, (float)minY, (float)minZ, (float)maxX, (float)maxY, (float)maxZ, red, green, blue, alpha);
|
|
}
|
|
|
|
public static void addChainedFilledBoxVertices(
|
|
PoseStack poseStack,
|
|
VertexConsumer consumer,
|
|
float minX,
|
|
float minY,
|
|
float minZ,
|
|
float maxX,
|
|
float maxY,
|
|
float maxZ,
|
|
float red,
|
|
float green,
|
|
float blue,
|
|
float alpha
|
|
) {
|
|
Matrix4f matrix4f = poseStack.last().pose();
|
|
consumer.addVertex(matrix4f, minX, minY, minZ).setColor(red, green, blue, alpha);
|
|
consumer.addVertex(matrix4f, minX, minY, minZ).setColor(red, green, blue, alpha);
|
|
consumer.addVertex(matrix4f, minX, minY, minZ).setColor(red, green, blue, alpha);
|
|
consumer.addVertex(matrix4f, minX, minY, maxZ).setColor(red, green, blue, alpha);
|
|
consumer.addVertex(matrix4f, minX, maxY, minZ).setColor(red, green, blue, alpha);
|
|
consumer.addVertex(matrix4f, minX, maxY, maxZ).setColor(red, green, blue, alpha);
|
|
consumer.addVertex(matrix4f, minX, maxY, maxZ).setColor(red, green, blue, alpha);
|
|
consumer.addVertex(matrix4f, minX, minY, maxZ).setColor(red, green, blue, alpha);
|
|
consumer.addVertex(matrix4f, maxX, maxY, maxZ).setColor(red, green, blue, alpha);
|
|
consumer.addVertex(matrix4f, maxX, minY, maxZ).setColor(red, green, blue, alpha);
|
|
consumer.addVertex(matrix4f, maxX, minY, maxZ).setColor(red, green, blue, alpha);
|
|
consumer.addVertex(matrix4f, maxX, minY, minZ).setColor(red, green, blue, alpha);
|
|
consumer.addVertex(matrix4f, maxX, maxY, maxZ).setColor(red, green, blue, alpha);
|
|
consumer.addVertex(matrix4f, maxX, maxY, minZ).setColor(red, green, blue, alpha);
|
|
consumer.addVertex(matrix4f, maxX, maxY, minZ).setColor(red, green, blue, alpha);
|
|
consumer.addVertex(matrix4f, maxX, minY, minZ).setColor(red, green, blue, alpha);
|
|
consumer.addVertex(matrix4f, minX, maxY, minZ).setColor(red, green, blue, alpha);
|
|
consumer.addVertex(matrix4f, minX, minY, minZ).setColor(red, green, blue, alpha);
|
|
consumer.addVertex(matrix4f, minX, minY, minZ).setColor(red, green, blue, alpha);
|
|
consumer.addVertex(matrix4f, maxX, minY, minZ).setColor(red, green, blue, alpha);
|
|
consumer.addVertex(matrix4f, minX, minY, maxZ).setColor(red, green, blue, alpha);
|
|
consumer.addVertex(matrix4f, maxX, minY, maxZ).setColor(red, green, blue, alpha);
|
|
consumer.addVertex(matrix4f, maxX, minY, maxZ).setColor(red, green, blue, alpha);
|
|
consumer.addVertex(matrix4f, minX, maxY, minZ).setColor(red, green, blue, alpha);
|
|
consumer.addVertex(matrix4f, minX, maxY, minZ).setColor(red, green, blue, alpha);
|
|
consumer.addVertex(matrix4f, minX, maxY, maxZ).setColor(red, green, blue, alpha);
|
|
consumer.addVertex(matrix4f, maxX, maxY, minZ).setColor(red, green, blue, alpha);
|
|
consumer.addVertex(matrix4f, maxX, maxY, maxZ).setColor(red, green, blue, alpha);
|
|
consumer.addVertex(matrix4f, maxX, maxY, maxZ).setColor(red, green, blue, alpha);
|
|
consumer.addVertex(matrix4f, maxX, maxY, maxZ).setColor(red, green, blue, alpha);
|
|
}
|
|
|
|
public static void renderFace(
|
|
PoseStack poseStack,
|
|
VertexConsumer buffer,
|
|
Direction face,
|
|
float x1,
|
|
float y1,
|
|
float z1,
|
|
float x2,
|
|
float y2,
|
|
float z2,
|
|
float red,
|
|
float green,
|
|
float blue,
|
|
float alpha
|
|
) {
|
|
Matrix4f matrix4f = poseStack.last().pose();
|
|
switch (face) {
|
|
case DOWN:
|
|
buffer.addVertex(matrix4f, x1, y1, z1).setColor(red, green, blue, alpha);
|
|
buffer.addVertex(matrix4f, x2, y1, z1).setColor(red, green, blue, alpha);
|
|
buffer.addVertex(matrix4f, x2, y1, z2).setColor(red, green, blue, alpha);
|
|
buffer.addVertex(matrix4f, x1, y1, z2).setColor(red, green, blue, alpha);
|
|
break;
|
|
case UP:
|
|
buffer.addVertex(matrix4f, x1, y2, z1).setColor(red, green, blue, alpha);
|
|
buffer.addVertex(matrix4f, x1, y2, z2).setColor(red, green, blue, alpha);
|
|
buffer.addVertex(matrix4f, x2, y2, z2).setColor(red, green, blue, alpha);
|
|
buffer.addVertex(matrix4f, x2, y2, z1).setColor(red, green, blue, alpha);
|
|
break;
|
|
case NORTH:
|
|
buffer.addVertex(matrix4f, x1, y1, z1).setColor(red, green, blue, alpha);
|
|
buffer.addVertex(matrix4f, x1, y2, z1).setColor(red, green, blue, alpha);
|
|
buffer.addVertex(matrix4f, x2, y2, z1).setColor(red, green, blue, alpha);
|
|
buffer.addVertex(matrix4f, x2, y1, z1).setColor(red, green, blue, alpha);
|
|
break;
|
|
case SOUTH:
|
|
buffer.addVertex(matrix4f, x1, y1, z2).setColor(red, green, blue, alpha);
|
|
buffer.addVertex(matrix4f, x2, y1, z2).setColor(red, green, blue, alpha);
|
|
buffer.addVertex(matrix4f, x2, y2, z2).setColor(red, green, blue, alpha);
|
|
buffer.addVertex(matrix4f, x1, y2, z2).setColor(red, green, blue, alpha);
|
|
break;
|
|
case WEST:
|
|
buffer.addVertex(matrix4f, x1, y1, z1).setColor(red, green, blue, alpha);
|
|
buffer.addVertex(matrix4f, x1, y1, z2).setColor(red, green, blue, alpha);
|
|
buffer.addVertex(matrix4f, x1, y2, z2).setColor(red, green, blue, alpha);
|
|
buffer.addVertex(matrix4f, x1, y2, z1).setColor(red, green, blue, alpha);
|
|
break;
|
|
case EAST:
|
|
buffer.addVertex(matrix4f, x2, y1, z1).setColor(red, green, blue, alpha);
|
|
buffer.addVertex(matrix4f, x2, y2, z1).setColor(red, green, blue, alpha);
|
|
buffer.addVertex(matrix4f, x2, y2, z2).setColor(red, green, blue, alpha);
|
|
buffer.addVertex(matrix4f, x2, y1, z2).setColor(red, green, blue, alpha);
|
|
}
|
|
}
|
|
|
|
public void blockChanged(BlockGetter level, BlockPos pos, BlockState oldState, BlockState newState, int flags) {
|
|
this.setBlockDirty(pos, (flags & 8) != 0);
|
|
}
|
|
|
|
private void setBlockDirty(BlockPos pos, boolean reRenderOnMainThread) {
|
|
for (int i = pos.getZ() - 1; i <= pos.getZ() + 1; i++) {
|
|
for (int j = pos.getX() - 1; j <= pos.getX() + 1; j++) {
|
|
for (int k = pos.getY() - 1; k <= pos.getY() + 1; k++) {
|
|
this.setSectionDirty(SectionPos.blockToSectionCoord(j), SectionPos.blockToSectionCoord(k), SectionPos.blockToSectionCoord(i), reRenderOnMainThread);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Re-renders all blocks in the specified range.
|
|
*/
|
|
public void setBlocksDirty(int minX, int minY, int minZ, int maxX, int maxY, int maxZ) {
|
|
for (int i = minZ - 1; i <= maxZ + 1; i++) {
|
|
for (int j = minX - 1; j <= maxX + 1; j++) {
|
|
for (int k = minY - 1; k <= maxY + 1; k++) {
|
|
this.setSectionDirty(SectionPos.blockToSectionCoord(j), SectionPos.blockToSectionCoord(k), SectionPos.blockToSectionCoord(i));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public void setBlockDirty(BlockPos pos, BlockState oldState, BlockState newState) {
|
|
if (this.minecraft.getModelManager().requiresRender(oldState, newState)) {
|
|
this.setBlocksDirty(pos.getX(), pos.getY(), pos.getZ(), pos.getX(), pos.getY(), pos.getZ());
|
|
}
|
|
}
|
|
|
|
public void setSectionDirtyWithNeighbors(int sectionX, int sectionY, int sectionZ) {
|
|
for (int i = sectionZ - 1; i <= sectionZ + 1; i++) {
|
|
for (int j = sectionX - 1; j <= sectionX + 1; j++) {
|
|
for (int k = sectionY - 1; k <= sectionY + 1; k++) {
|
|
this.setSectionDirty(j, k, i);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public void setSectionDirty(int sectionX, int sectionY, int sectionZ) {
|
|
this.setSectionDirty(sectionX, sectionY, sectionZ, false);
|
|
}
|
|
|
|
private void setSectionDirty(int sectionX, int sectionY, int sectionZ, boolean reRenderOnMainThread) {
|
|
this.viewArea.setDirty(sectionX, sectionY, sectionZ, reRenderOnMainThread);
|
|
}
|
|
|
|
public void playJukeboxSong(Holder<JukeboxSong> song, BlockPos pos) {
|
|
if (this.level != null) {
|
|
this.stopJukeboxSong(pos);
|
|
JukeboxSong jukeboxSong = song.value();
|
|
SoundEvent soundEvent = jukeboxSong.soundEvent().value();
|
|
SoundInstance soundInstance = SimpleSoundInstance.forJukeboxSong(soundEvent, Vec3.atCenterOf(pos));
|
|
this.playingJukeboxSongs.put(pos, soundInstance);
|
|
this.minecraft.getSoundManager().play(soundInstance);
|
|
this.minecraft.gui.setNowPlaying(jukeboxSong.description());
|
|
this.notifyNearbyEntities(this.level, pos, true);
|
|
}
|
|
}
|
|
|
|
private void stopJukeboxSong(BlockPos pos) {
|
|
SoundInstance soundInstance = (SoundInstance)this.playingJukeboxSongs.remove(pos);
|
|
if (soundInstance != null) {
|
|
this.minecraft.getSoundManager().stop(soundInstance);
|
|
}
|
|
}
|
|
|
|
public void stopJukeboxSongAndNotifyNearby(BlockPos pos) {
|
|
this.stopJukeboxSong(pos);
|
|
if (this.level != null) {
|
|
this.notifyNearbyEntities(this.level, pos, false);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Notifies living entities in a 3 block range of the specified {@code pos} that a record is or isn't playing nearby, dependent on the specified {@code playing} parameter.
|
|
* This is used to make parrots start or stop partying.
|
|
*/
|
|
private void notifyNearbyEntities(Level level, BlockPos pos, boolean playing) {
|
|
for (LivingEntity livingEntity : level.getEntitiesOfClass(LivingEntity.class, new AABB(pos).inflate(3.0))) {
|
|
livingEntity.setRecordPlayingNearby(pos, playing);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param force if {@code true}, the particle will be created regardless of its distance from the camera and the {@linkplain #calculateParticleLevel(boolean) calculated particle level}
|
|
*/
|
|
public void addParticle(ParticleOptions options, boolean force, double x, double y, double z, double xSpeed, double ySpeed, double zSpeed) {
|
|
this.addParticle(options, force, false, x, y, z, xSpeed, ySpeed, zSpeed);
|
|
}
|
|
|
|
/**
|
|
* @param force if {@code true}, the particle will be created regardless of its distance from the camera and the {@linkplain #calculateParticleLevel(boolean) calculated particle level}
|
|
* @param decreased if {@code true}, and the {@linkplain net.minecraft.client.Options#particles particles option} is set to minimal, attempts to spawn the particle at a decreased level
|
|
*/
|
|
public void addParticle(ParticleOptions options, boolean force, boolean decreased, double x, double y, double z, double xSpeed, double ySpeed, double zSpeed) {
|
|
try {
|
|
this.addParticleInternal(options, force, decreased, x, y, z, xSpeed, ySpeed, zSpeed);
|
|
} catch (Throwable var19) {
|
|
CrashReport crashReport = CrashReport.forThrowable(var19, "Exception while adding particle");
|
|
CrashReportCategory crashReportCategory = crashReport.addCategory("Particle being added");
|
|
crashReportCategory.setDetail("ID", BuiltInRegistries.PARTICLE_TYPE.getKey(options.getType()));
|
|
crashReportCategory.setDetail(
|
|
"Parameters",
|
|
(CrashReportDetail<String>)(() -> ParticleTypes.CODEC
|
|
.encodeStart(this.level.registryAccess().createSerializationContext(NbtOps.INSTANCE), options)
|
|
.toString())
|
|
);
|
|
crashReportCategory.setDetail("Position", (CrashReportDetail<String>)(() -> CrashReportCategory.formatLocation(this.level, x, y, z)));
|
|
throw new ReportedException(crashReport);
|
|
}
|
|
}
|
|
|
|
private <T extends ParticleOptions> void addParticle(T options, double x, double y, double z, double xSpeed, double ySpeed, double zSpeed) {
|
|
this.addParticle(options, options.getType().getOverrideLimiter(), x, y, z, xSpeed, ySpeed, zSpeed);
|
|
}
|
|
|
|
/**
|
|
* @param force if {@code true}, the particle will be created regardless of its distance from the camera and the {@linkplain #calculateParticleLevel(boolean) calculated particle level}
|
|
*/
|
|
@Nullable
|
|
private Particle addParticleInternal(ParticleOptions options, boolean force, double x, double y, double z, double xSpeed, double ySpeed, double zSpeed) {
|
|
return this.addParticleInternal(options, force, false, x, y, z, xSpeed, ySpeed, zSpeed);
|
|
}
|
|
|
|
/**
|
|
* @param force if {@code true}, the particle will be created regardless of its distance from the camera and the {@linkplain #calculateParticleLevel(boolean) calculated particle level}
|
|
* @param decreased if {@code true}, and the {@linkplain net.minecraft.client.Options#particles particles option} is set to minimal, attempts to spawn the particle at a decreased level
|
|
*/
|
|
@Nullable
|
|
private Particle addParticleInternal(
|
|
ParticleOptions options, boolean force, boolean decreased, double x, double y, double z, double xSpeed, double ySpeed, double zSpeed
|
|
) {
|
|
Camera camera = this.minecraft.gameRenderer.getMainCamera();
|
|
ParticleStatus particleStatus = this.calculateParticleLevel(decreased);
|
|
if (force) {
|
|
return this.minecraft.particleEngine.createParticle(options, x, y, z, xSpeed, ySpeed, zSpeed);
|
|
} else if (camera.getPosition().distanceToSqr(x, y, z) > 1024.0) {
|
|
return null;
|
|
} else {
|
|
return particleStatus == ParticleStatus.MINIMAL ? null : this.minecraft.particleEngine.createParticle(options, x, y, z, xSpeed, ySpeed, zSpeed);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Calculates the level of particles to use based on the {@linkplain net.minecraft.client.Options#particles particles option} and the specified {@code decreased} parameter. This leads to randomly generating more or less particles than the set option.
|
|
*
|
|
* @param decreased if {@code true}, and the {@linkplain net.minecraft.client.Options#particles particles option} is set to minimal, has a 1 in 10 chance to return a decreased level and a further 1 in 3 chance to minimise it
|
|
*/
|
|
private ParticleStatus calculateParticleLevel(boolean decreased) {
|
|
ParticleStatus particleStatus = this.minecraft.options.particles().get();
|
|
if (decreased && particleStatus == ParticleStatus.MINIMAL && this.level.random.nextInt(10) == 0) {
|
|
particleStatus = ParticleStatus.DECREASED;
|
|
}
|
|
|
|
if (particleStatus == ParticleStatus.DECREASED && this.level.random.nextInt(3) == 0) {
|
|
particleStatus = ParticleStatus.MINIMAL;
|
|
}
|
|
|
|
return particleStatus;
|
|
}
|
|
|
|
public void clear() {
|
|
}
|
|
|
|
/**
|
|
* Handles a global level event. This includes playing sounds that should be heard by any player, regardless of position and dimension, such as the Wither spawning.
|
|
*
|
|
* @param type the type of level event to handle. This method only handles {@linkplain net.minecraft.world.level.block.LevelEvent#SOUND_WITHER_BOSS_SPAWN the wither boss spawn sound}, {@linkplain net.minecraft.world.level.block.LevelEvent#SOUND_DRAGON_DEATH the dragon's death sound}, and {@linkplain net.minecraft.world.level.block.LevelEvent#SOUND_END_PORTAL_SPAWN the end portal spawn sound}.
|
|
*/
|
|
public void globalLevelEvent(int type, BlockPos pos, int data) {
|
|
switch (type) {
|
|
case 1023:
|
|
case 1028:
|
|
case 1038:
|
|
Camera camera = this.minecraft.gameRenderer.getMainCamera();
|
|
if (camera.isInitialized()) {
|
|
double d = pos.getX() - camera.getPosition().x;
|
|
double e = pos.getY() - camera.getPosition().y;
|
|
double f = pos.getZ() - camera.getPosition().z;
|
|
double g = Math.sqrt(d * d + e * e + f * f);
|
|
double h = camera.getPosition().x;
|
|
double i = camera.getPosition().y;
|
|
double j = camera.getPosition().z;
|
|
if (g > 0.0) {
|
|
h += d / g * 2.0;
|
|
i += e / g * 2.0;
|
|
j += f / g * 2.0;
|
|
}
|
|
|
|
if (type == 1023) {
|
|
this.level.playLocalSound(h, i, j, SoundEvents.WITHER_SPAWN, SoundSource.HOSTILE, 1.0F, 1.0F, false);
|
|
} else if (type == 1038) {
|
|
this.level.playLocalSound(h, i, j, SoundEvents.END_PORTAL_SPAWN, SoundSource.HOSTILE, 1.0F, 1.0F, false);
|
|
} else {
|
|
this.level.playLocalSound(h, i, j, SoundEvents.ENDER_DRAGON_DEATH, SoundSource.HOSTILE, 5.0F, 1.0F, false);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public void levelEvent(int type, BlockPos pos, int data) {
|
|
RandomSource randomSource = this.level.random;
|
|
switch (type) {
|
|
case 1000:
|
|
this.level.playLocalSound(pos, SoundEvents.DISPENSER_DISPENSE, SoundSource.BLOCKS, 1.0F, 1.0F, false);
|
|
break;
|
|
case 1001:
|
|
this.level.playLocalSound(pos, SoundEvents.DISPENSER_FAIL, SoundSource.BLOCKS, 1.0F, 1.2F, false);
|
|
break;
|
|
case 1002:
|
|
this.level.playLocalSound(pos, SoundEvents.DISPENSER_LAUNCH, SoundSource.BLOCKS, 1.0F, 1.2F, false);
|
|
break;
|
|
case 1004:
|
|
this.level.playLocalSound(pos, SoundEvents.FIREWORK_ROCKET_SHOOT, SoundSource.NEUTRAL, 1.0F, 1.2F, false);
|
|
break;
|
|
case 1009:
|
|
if (data == 0) {
|
|
this.level
|
|
.playLocalSound(pos, SoundEvents.FIRE_EXTINGUISH, SoundSource.BLOCKS, 0.5F, 2.6F + (randomSource.nextFloat() - randomSource.nextFloat()) * 0.8F, false);
|
|
} else if (data == 1) {
|
|
this.level
|
|
.playLocalSound(
|
|
pos, SoundEvents.GENERIC_EXTINGUISH_FIRE, SoundSource.BLOCKS, 0.7F, 1.6F + (randomSource.nextFloat() - randomSource.nextFloat()) * 0.4F, false
|
|
);
|
|
}
|
|
break;
|
|
case 1010:
|
|
this.level.registryAccess().registryOrThrow(Registries.JUKEBOX_SONG).getHolder(data).ifPresent(reference -> this.playJukeboxSong(reference, pos));
|
|
break;
|
|
case 1011:
|
|
this.stopJukeboxSongAndNotifyNearby(pos);
|
|
break;
|
|
case 1015:
|
|
this.level
|
|
.playLocalSound(pos, SoundEvents.GHAST_WARN, SoundSource.HOSTILE, 10.0F, (randomSource.nextFloat() - randomSource.nextFloat()) * 0.2F + 1.0F, false);
|
|
break;
|
|
case 1016:
|
|
this.level
|
|
.playLocalSound(pos, SoundEvents.GHAST_SHOOT, SoundSource.HOSTILE, 10.0F, (randomSource.nextFloat() - randomSource.nextFloat()) * 0.2F + 1.0F, false);
|
|
break;
|
|
case 1017:
|
|
this.level
|
|
.playLocalSound(
|
|
pos, SoundEvents.ENDER_DRAGON_SHOOT, SoundSource.HOSTILE, 10.0F, (randomSource.nextFloat() - randomSource.nextFloat()) * 0.2F + 1.0F, false
|
|
);
|
|
break;
|
|
case 1018:
|
|
this.level
|
|
.playLocalSound(pos, SoundEvents.BLAZE_SHOOT, SoundSource.HOSTILE, 2.0F, (randomSource.nextFloat() - randomSource.nextFloat()) * 0.2F + 1.0F, false);
|
|
break;
|
|
case 1019:
|
|
this.level
|
|
.playLocalSound(
|
|
pos, SoundEvents.ZOMBIE_ATTACK_WOODEN_DOOR, SoundSource.HOSTILE, 2.0F, (randomSource.nextFloat() - randomSource.nextFloat()) * 0.2F + 1.0F, false
|
|
);
|
|
break;
|
|
case 1020:
|
|
this.level
|
|
.playLocalSound(
|
|
pos, SoundEvents.ZOMBIE_ATTACK_IRON_DOOR, SoundSource.HOSTILE, 2.0F, (randomSource.nextFloat() - randomSource.nextFloat()) * 0.2F + 1.0F, false
|
|
);
|
|
break;
|
|
case 1021:
|
|
this.level
|
|
.playLocalSound(
|
|
pos, SoundEvents.ZOMBIE_BREAK_WOODEN_DOOR, SoundSource.HOSTILE, 2.0F, (randomSource.nextFloat() - randomSource.nextFloat()) * 0.2F + 1.0F, false
|
|
);
|
|
break;
|
|
case 1022:
|
|
this.level
|
|
.playLocalSound(pos, SoundEvents.WITHER_BREAK_BLOCK, SoundSource.HOSTILE, 2.0F, (randomSource.nextFloat() - randomSource.nextFloat()) * 0.2F + 1.0F, false);
|
|
break;
|
|
case 1024:
|
|
this.level
|
|
.playLocalSound(pos, SoundEvents.WITHER_SHOOT, SoundSource.HOSTILE, 2.0F, (randomSource.nextFloat() - randomSource.nextFloat()) * 0.2F + 1.0F, false);
|
|
break;
|
|
case 1025:
|
|
this.level
|
|
.playLocalSound(pos, SoundEvents.BAT_TAKEOFF, SoundSource.NEUTRAL, 0.05F, (randomSource.nextFloat() - randomSource.nextFloat()) * 0.2F + 1.0F, false);
|
|
break;
|
|
case 1026:
|
|
this.level
|
|
.playLocalSound(pos, SoundEvents.ZOMBIE_INFECT, SoundSource.HOSTILE, 2.0F, (randomSource.nextFloat() - randomSource.nextFloat()) * 0.2F + 1.0F, false);
|
|
break;
|
|
case 1027:
|
|
this.level
|
|
.playLocalSound(
|
|
pos, SoundEvents.ZOMBIE_VILLAGER_CONVERTED, SoundSource.HOSTILE, 2.0F, (randomSource.nextFloat() - randomSource.nextFloat()) * 0.2F + 1.0F, false
|
|
);
|
|
break;
|
|
case 1029:
|
|
this.level.playLocalSound(pos, SoundEvents.ANVIL_DESTROY, SoundSource.BLOCKS, 1.0F, randomSource.nextFloat() * 0.1F + 0.9F, false);
|
|
break;
|
|
case 1030:
|
|
this.level.playLocalSound(pos, SoundEvents.ANVIL_USE, SoundSource.BLOCKS, 1.0F, randomSource.nextFloat() * 0.1F + 0.9F, false);
|
|
break;
|
|
case 1031:
|
|
this.level.playLocalSound(pos, SoundEvents.ANVIL_LAND, SoundSource.BLOCKS, 0.3F, this.level.random.nextFloat() * 0.1F + 0.9F, false);
|
|
break;
|
|
case 1032:
|
|
this.minecraft.getSoundManager().play(SimpleSoundInstance.forLocalAmbience(SoundEvents.PORTAL_TRAVEL, randomSource.nextFloat() * 0.4F + 0.8F, 0.25F));
|
|
break;
|
|
case 1033:
|
|
this.level.playLocalSound(pos, SoundEvents.CHORUS_FLOWER_GROW, SoundSource.BLOCKS, 1.0F, 1.0F, false);
|
|
break;
|
|
case 1034:
|
|
this.level.playLocalSound(pos, SoundEvents.CHORUS_FLOWER_DEATH, SoundSource.BLOCKS, 1.0F, 1.0F, false);
|
|
break;
|
|
case 1035:
|
|
this.level.playLocalSound(pos, SoundEvents.BREWING_STAND_BREW, SoundSource.BLOCKS, 1.0F, 1.0F, false);
|
|
break;
|
|
case 1039:
|
|
this.level.playLocalSound(pos, SoundEvents.PHANTOM_BITE, SoundSource.HOSTILE, 0.3F, this.level.random.nextFloat() * 0.1F + 0.9F, false);
|
|
break;
|
|
case 1040:
|
|
this.level
|
|
.playLocalSound(
|
|
pos, SoundEvents.ZOMBIE_CONVERTED_TO_DROWNED, SoundSource.HOSTILE, 2.0F, (randomSource.nextFloat() - randomSource.nextFloat()) * 0.2F + 1.0F, false
|
|
);
|
|
break;
|
|
case 1041:
|
|
this.level
|
|
.playLocalSound(
|
|
pos, SoundEvents.HUSK_CONVERTED_TO_ZOMBIE, SoundSource.HOSTILE, 2.0F, (randomSource.nextFloat() - randomSource.nextFloat()) * 0.2F + 1.0F, false
|
|
);
|
|
break;
|
|
case 1042:
|
|
this.level.playLocalSound(pos, SoundEvents.GRINDSTONE_USE, SoundSource.BLOCKS, 1.0F, this.level.random.nextFloat() * 0.1F + 0.9F, false);
|
|
break;
|
|
case 1043:
|
|
this.level.playLocalSound(pos, SoundEvents.BOOK_PAGE_TURN, SoundSource.BLOCKS, 1.0F, this.level.random.nextFloat() * 0.1F + 0.9F, false);
|
|
break;
|
|
case 1044:
|
|
this.level.playLocalSound(pos, SoundEvents.SMITHING_TABLE_USE, SoundSource.BLOCKS, 1.0F, this.level.random.nextFloat() * 0.1F + 0.9F, false);
|
|
break;
|
|
case 1045:
|
|
this.level.playLocalSound(pos, SoundEvents.POINTED_DRIPSTONE_LAND, SoundSource.BLOCKS, 2.0F, this.level.random.nextFloat() * 0.1F + 0.9F, false);
|
|
break;
|
|
case 1046:
|
|
this.level
|
|
.playLocalSound(pos, SoundEvents.POINTED_DRIPSTONE_DRIP_LAVA_INTO_CAULDRON, SoundSource.BLOCKS, 2.0F, this.level.random.nextFloat() * 0.1F + 0.9F, false);
|
|
break;
|
|
case 1047:
|
|
this.level
|
|
.playLocalSound(pos, SoundEvents.POINTED_DRIPSTONE_DRIP_WATER_INTO_CAULDRON, SoundSource.BLOCKS, 2.0F, this.level.random.nextFloat() * 0.1F + 0.9F, false);
|
|
break;
|
|
case 1048:
|
|
this.level
|
|
.playLocalSound(
|
|
pos, SoundEvents.SKELETON_CONVERTED_TO_STRAY, SoundSource.HOSTILE, 2.0F, (randomSource.nextFloat() - randomSource.nextFloat()) * 0.2F + 1.0F, false
|
|
);
|
|
break;
|
|
case 1049:
|
|
this.level.playLocalSound(pos, SoundEvents.CRAFTER_CRAFT, SoundSource.BLOCKS, 1.0F, 1.0F, false);
|
|
break;
|
|
case 1050:
|
|
this.level.playLocalSound(pos, SoundEvents.CRAFTER_FAIL, SoundSource.BLOCKS, 1.0F, 1.0F, false);
|
|
break;
|
|
case 1051:
|
|
this.level.playLocalSound(pos, SoundEvents.WIND_CHARGE_THROW, SoundSource.BLOCKS, 0.5F, 0.4F / (this.level.getRandom().nextFloat() * 0.4F + 0.8F), false);
|
|
case 2010:
|
|
this.shootParticles(data, pos, randomSource, ParticleTypes.WHITE_SMOKE);
|
|
break;
|
|
case 1500:
|
|
ComposterBlock.handleFill(this.level, pos, data > 0);
|
|
break;
|
|
case 1501:
|
|
this.level
|
|
.playLocalSound(pos, SoundEvents.LAVA_EXTINGUISH, SoundSource.BLOCKS, 0.5F, 2.6F + (randomSource.nextFloat() - randomSource.nextFloat()) * 0.8F, false);
|
|
|
|
for (int mx = 0; mx < 8; mx++) {
|
|
this.level
|
|
.addParticle(ParticleTypes.LARGE_SMOKE, pos.getX() + randomSource.nextDouble(), pos.getY() + 1.2, pos.getZ() + randomSource.nextDouble(), 0.0, 0.0, 0.0);
|
|
}
|
|
break;
|
|
case 1502:
|
|
this.level
|
|
.playLocalSound(
|
|
pos, SoundEvents.REDSTONE_TORCH_BURNOUT, SoundSource.BLOCKS, 0.5F, 2.6F + (randomSource.nextFloat() - randomSource.nextFloat()) * 0.8F, false
|
|
);
|
|
|
|
for (int mx = 0; mx < 5; mx++) {
|
|
double g = pos.getX() + randomSource.nextDouble() * 0.6 + 0.2;
|
|
double n = pos.getY() + randomSource.nextDouble() * 0.6 + 0.2;
|
|
double o = pos.getZ() + randomSource.nextDouble() * 0.6 + 0.2;
|
|
this.level.addParticle(ParticleTypes.SMOKE, g, n, o, 0.0, 0.0, 0.0);
|
|
}
|
|
break;
|
|
case 1503:
|
|
this.level.playLocalSound(pos, SoundEvents.END_PORTAL_FRAME_FILL, SoundSource.BLOCKS, 1.0F, 1.0F, false);
|
|
|
|
for (int mx = 0; mx < 16; mx++) {
|
|
double g = pos.getX() + (5.0 + randomSource.nextDouble() * 6.0) / 16.0;
|
|
double n = pos.getY() + 0.8125;
|
|
double o = pos.getZ() + (5.0 + randomSource.nextDouble() * 6.0) / 16.0;
|
|
this.level.addParticle(ParticleTypes.SMOKE, g, n, o, 0.0, 0.0, 0.0);
|
|
}
|
|
break;
|
|
case 1504:
|
|
PointedDripstoneBlock.spawnDripParticle(this.level, pos, this.level.getBlockState(pos));
|
|
break;
|
|
case 1505:
|
|
BoneMealItem.addGrowthParticles(this.level, pos, data);
|
|
this.level.playLocalSound(pos, SoundEvents.BONE_MEAL_USE, SoundSource.BLOCKS, 1.0F, 1.0F, false);
|
|
break;
|
|
case 2000:
|
|
this.shootParticles(data, pos, randomSource, ParticleTypes.SMOKE);
|
|
break;
|
|
case 2001:
|
|
BlockState blockState = Block.stateById(data);
|
|
if (!blockState.isAir()) {
|
|
SoundType soundType = blockState.getSoundType();
|
|
this.level.playLocalSound(pos, soundType.getBreakSound(), SoundSource.BLOCKS, (soundType.getVolume() + 1.0F) / 2.0F, soundType.getPitch() * 0.8F, false);
|
|
}
|
|
|
|
this.level.addDestroyBlockEffect(pos, blockState);
|
|
break;
|
|
case 2002:
|
|
case 2007:
|
|
Vec3 vec3 = Vec3.atBottomCenterOf(pos);
|
|
|
|
for (int j = 0; j < 8; j++) {
|
|
this.addParticle(
|
|
new ItemParticleOption(ParticleTypes.ITEM, new ItemStack(Items.SPLASH_POTION)),
|
|
vec3.x,
|
|
vec3.y,
|
|
vec3.z,
|
|
randomSource.nextGaussian() * 0.15,
|
|
randomSource.nextDouble() * 0.2,
|
|
randomSource.nextGaussian() * 0.15
|
|
);
|
|
}
|
|
|
|
float h = (data >> 16 & 0xFF) / 255.0F;
|
|
float k = (data >> 8 & 0xFF) / 255.0F;
|
|
float l = (data >> 0 & 0xFF) / 255.0F;
|
|
ParticleOptions particleOptions = type == 2007 ? ParticleTypes.INSTANT_EFFECT : ParticleTypes.EFFECT;
|
|
|
|
for (int mx = 0; mx < 100; mx++) {
|
|
double g = randomSource.nextDouble() * 4.0;
|
|
double n = randomSource.nextDouble() * Math.PI * 2.0;
|
|
double o = Math.cos(n) * g;
|
|
double p = 0.01 + randomSource.nextDouble() * 0.5;
|
|
double q = Math.sin(n) * g;
|
|
Particle particle = this.addParticleInternal(
|
|
particleOptions, particleOptions.getType().getOverrideLimiter(), vec3.x + o * 0.1, vec3.y + 0.3, vec3.z + q * 0.1, o, p, q
|
|
);
|
|
if (particle != null) {
|
|
float r = 0.75F + randomSource.nextFloat() * 0.25F;
|
|
particle.setColor(h * r, k * r, l * r);
|
|
particle.setPower((float)g);
|
|
}
|
|
}
|
|
|
|
this.level.playLocalSound(pos, SoundEvents.SPLASH_POTION_BREAK, SoundSource.NEUTRAL, 1.0F, randomSource.nextFloat() * 0.1F + 0.9F, false);
|
|
break;
|
|
case 2003:
|
|
double d = pos.getX() + 0.5;
|
|
double e = pos.getY();
|
|
double f = pos.getZ() + 0.5;
|
|
|
|
for (int i = 0; i < 8; i++) {
|
|
this.addParticle(
|
|
new ItemParticleOption(ParticleTypes.ITEM, new ItemStack(Items.ENDER_EYE)),
|
|
d,
|
|
e,
|
|
f,
|
|
randomSource.nextGaussian() * 0.15,
|
|
randomSource.nextDouble() * 0.2,
|
|
randomSource.nextGaussian() * 0.15
|
|
);
|
|
}
|
|
|
|
for (double g = 0.0; g < Math.PI * 2; g += Math.PI / 20) {
|
|
this.addParticle(ParticleTypes.PORTAL, d + Math.cos(g) * 5.0, e - 0.4, f + Math.sin(g) * 5.0, Math.cos(g) * -5.0, 0.0, Math.sin(g) * -5.0);
|
|
this.addParticle(ParticleTypes.PORTAL, d + Math.cos(g) * 5.0, e - 0.4, f + Math.sin(g) * 5.0, Math.cos(g) * -7.0, 0.0, Math.sin(g) * -7.0);
|
|
}
|
|
break;
|
|
case 2004:
|
|
for (int sx = 0; sx < 20; sx++) {
|
|
double t = pos.getX() + 0.5 + (randomSource.nextDouble() - 0.5) * 2.0;
|
|
double u = pos.getY() + 0.5 + (randomSource.nextDouble() - 0.5) * 2.0;
|
|
double v = pos.getZ() + 0.5 + (randomSource.nextDouble() - 0.5) * 2.0;
|
|
this.level.addParticle(ParticleTypes.SMOKE, t, u, v, 0.0, 0.0, 0.0);
|
|
this.level.addParticle(ParticleTypes.FLAME, t, u, v, 0.0, 0.0, 0.0);
|
|
}
|
|
break;
|
|
case 2006:
|
|
for (int m = 0; m < 200; m++) {
|
|
float ab = randomSource.nextFloat() * 4.0F;
|
|
float ag = randomSource.nextFloat() * (float) (Math.PI * 2);
|
|
double n = Mth.cos(ag) * ab;
|
|
double o = 0.01 + randomSource.nextDouble() * 0.5;
|
|
double p = Mth.sin(ag) * ab;
|
|
Particle particle2 = this.addParticleInternal(ParticleTypes.DRAGON_BREATH, false, pos.getX() + n * 0.1, pos.getY() + 0.3, pos.getZ() + p * 0.1, n, o, p);
|
|
if (particle2 != null) {
|
|
particle2.setPower(ab);
|
|
}
|
|
}
|
|
|
|
if (data == 1) {
|
|
this.level.playLocalSound(pos, SoundEvents.DRAGON_FIREBALL_EXPLODE, SoundSource.HOSTILE, 1.0F, randomSource.nextFloat() * 0.1F + 0.9F, false);
|
|
}
|
|
break;
|
|
case 2008:
|
|
this.level.addParticle(ParticleTypes.EXPLOSION, pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5, 0.0, 0.0, 0.0);
|
|
break;
|
|
case 2009:
|
|
for (int mx = 0; mx < 8; mx++) {
|
|
this.level
|
|
.addParticle(ParticleTypes.CLOUD, pos.getX() + randomSource.nextDouble(), pos.getY() + 1.2, pos.getZ() + randomSource.nextDouble(), 0.0, 0.0, 0.0);
|
|
}
|
|
break;
|
|
case 2011:
|
|
ParticleUtils.spawnParticleInBlock(this.level, pos, data, ParticleTypes.HAPPY_VILLAGER);
|
|
break;
|
|
case 2012:
|
|
ParticleUtils.spawnParticleInBlock(this.level, pos, data, ParticleTypes.HAPPY_VILLAGER);
|
|
break;
|
|
case 2013:
|
|
ParticleUtils.spawnSmashAttackParticles(this.level, pos, data);
|
|
break;
|
|
case 3000:
|
|
this.level.addParticle(ParticleTypes.EXPLOSION_EMITTER, true, pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5, 0.0, 0.0, 0.0);
|
|
this.level
|
|
.playLocalSound(
|
|
pos,
|
|
SoundEvents.END_GATEWAY_SPAWN,
|
|
SoundSource.BLOCKS,
|
|
10.0F,
|
|
(1.0F + (this.level.random.nextFloat() - this.level.random.nextFloat()) * 0.2F) * 0.7F,
|
|
false
|
|
);
|
|
break;
|
|
case 3001:
|
|
this.level.playLocalSound(pos, SoundEvents.ENDER_DRAGON_GROWL, SoundSource.HOSTILE, 64.0F, 0.8F + this.level.random.nextFloat() * 0.3F, false);
|
|
break;
|
|
case 3002:
|
|
if (data >= 0 && data < Direction.Axis.VALUES.length) {
|
|
ParticleUtils.spawnParticlesAlongAxis(Direction.Axis.VALUES[data], this.level, pos, 0.125, ParticleTypes.ELECTRIC_SPARK, UniformInt.of(10, 19));
|
|
} else {
|
|
ParticleUtils.spawnParticlesOnBlockFaces(this.level, pos, ParticleTypes.ELECTRIC_SPARK, UniformInt.of(3, 5));
|
|
}
|
|
break;
|
|
case 3003:
|
|
ParticleUtils.spawnParticlesOnBlockFaces(this.level, pos, ParticleTypes.WAX_ON, UniformInt.of(3, 5));
|
|
this.level.playLocalSound(pos, SoundEvents.HONEYCOMB_WAX_ON, SoundSource.BLOCKS, 1.0F, 1.0F, false);
|
|
break;
|
|
case 3004:
|
|
ParticleUtils.spawnParticlesOnBlockFaces(this.level, pos, ParticleTypes.WAX_OFF, UniformInt.of(3, 5));
|
|
break;
|
|
case 3005:
|
|
ParticleUtils.spawnParticlesOnBlockFaces(this.level, pos, ParticleTypes.SCRAPE, UniformInt.of(3, 5));
|
|
break;
|
|
case 3006:
|
|
int s = data >> 6;
|
|
if (s > 0) {
|
|
if (randomSource.nextFloat() < 0.3F + s * 0.1F) {
|
|
float l = 0.15F + 0.02F * s * s * randomSource.nextFloat();
|
|
float w = 0.4F + 0.3F * s * randomSource.nextFloat();
|
|
this.level.playLocalSound(pos, SoundEvents.SCULK_BLOCK_CHARGE, SoundSource.BLOCKS, l, w, false);
|
|
}
|
|
|
|
byte b = (byte)(data & 63);
|
|
IntProvider intProvider = UniformInt.of(0, s);
|
|
float x = 0.005F;
|
|
Supplier<Vec3> supplier = () -> new Vec3(
|
|
Mth.nextDouble(randomSource, -0.005F, 0.005F), Mth.nextDouble(randomSource, -0.005F, 0.005F), Mth.nextDouble(randomSource, -0.005F, 0.005F)
|
|
);
|
|
if (b == 0) {
|
|
for (Direction direction : Direction.values()) {
|
|
float y = direction == Direction.DOWN ? (float) Math.PI : 0.0F;
|
|
double p = direction.getAxis() == Direction.Axis.Y ? 0.65 : 0.57;
|
|
ParticleUtils.spawnParticlesOnBlockFace(this.level, pos, new SculkChargeParticleOptions(y), intProvider, direction, supplier, p);
|
|
}
|
|
} else {
|
|
for (Direction direction2 : MultifaceBlock.unpack(b)) {
|
|
float z = direction2 == Direction.UP ? (float) Math.PI : 0.0F;
|
|
double o = 0.35;
|
|
ParticleUtils.spawnParticlesOnBlockFace(this.level, pos, new SculkChargeParticleOptions(z), intProvider, direction2, supplier, 0.35);
|
|
}
|
|
}
|
|
} else {
|
|
this.level.playLocalSound(pos, SoundEvents.SCULK_BLOCK_CHARGE, SoundSource.BLOCKS, 1.0F, 1.0F, false);
|
|
boolean bl = this.level.getBlockState(pos).isCollisionShapeFullBlock(this.level, pos);
|
|
int aa = bl ? 40 : 20;
|
|
float x = bl ? 0.45F : 0.25F;
|
|
float ab = 0.07F;
|
|
|
|
for (int ac = 0; ac < aa; ac++) {
|
|
float ad = 2.0F * randomSource.nextFloat() - 1.0F;
|
|
float z = 2.0F * randomSource.nextFloat() - 1.0F;
|
|
float ae = 2.0F * randomSource.nextFloat() - 1.0F;
|
|
this.level
|
|
.addParticle(
|
|
ParticleTypes.SCULK_CHARGE_POP, pos.getX() + 0.5 + ad * x, pos.getY() + 0.5 + z * x, pos.getZ() + 0.5 + ae * x, ad * 0.07F, z * 0.07F, ae * 0.07F
|
|
);
|
|
}
|
|
}
|
|
break;
|
|
case 3007:
|
|
for (int af = 0; af < 10; af++) {
|
|
this.level.addParticle(new ShriekParticleOption(af * 5), false, pos.getX() + 0.5, pos.getY() + SculkShriekerBlock.TOP_Y, pos.getZ() + 0.5, 0.0, 0.0, 0.0);
|
|
}
|
|
|
|
BlockState blockState3 = this.level.getBlockState(pos);
|
|
boolean bl2 = blockState3.hasProperty(BlockStateProperties.WATERLOGGED) && (Boolean)blockState3.getValue(BlockStateProperties.WATERLOGGED);
|
|
if (!bl2) {
|
|
this.level
|
|
.playLocalSound(
|
|
pos.getX() + 0.5,
|
|
pos.getY() + SculkShriekerBlock.TOP_Y,
|
|
pos.getZ() + 0.5,
|
|
SoundEvents.SCULK_SHRIEKER_SHRIEK,
|
|
SoundSource.BLOCKS,
|
|
2.0F,
|
|
0.6F + this.level.random.nextFloat() * 0.4F,
|
|
false
|
|
);
|
|
}
|
|
break;
|
|
case 3008:
|
|
BlockState blockState2 = Block.stateById(data);
|
|
if (blockState2.getBlock() instanceof BrushableBlock brushableBlock) {
|
|
this.level.playLocalSound(pos, brushableBlock.getBrushCompletedSound(), SoundSource.PLAYERS, 1.0F, 1.0F, false);
|
|
}
|
|
|
|
this.level.addDestroyBlockEffect(pos, blockState2);
|
|
break;
|
|
case 3009:
|
|
ParticleUtils.spawnParticlesOnBlockFaces(this.level, pos, ParticleTypes.EGG_CRACK, UniformInt.of(3, 6));
|
|
break;
|
|
case 3011:
|
|
TrialSpawner.addSpawnParticles(this.level, pos, randomSource, TrialSpawner.FlameParticle.decode(data).particleType);
|
|
break;
|
|
case 3012:
|
|
this.level
|
|
.playLocalSound(
|
|
pos, SoundEvents.TRIAL_SPAWNER_SPAWN_MOB, SoundSource.BLOCKS, 1.0F, (randomSource.nextFloat() - randomSource.nextFloat()) * 0.2F + 1.0F, true
|
|
);
|
|
TrialSpawner.addSpawnParticles(this.level, pos, randomSource, TrialSpawner.FlameParticle.decode(data).particleType);
|
|
break;
|
|
case 3013:
|
|
this.level
|
|
.playLocalSound(
|
|
pos, SoundEvents.TRIAL_SPAWNER_DETECT_PLAYER, SoundSource.BLOCKS, 1.0F, (randomSource.nextFloat() - randomSource.nextFloat()) * 0.2F + 1.0F, true
|
|
);
|
|
TrialSpawner.addDetectPlayerParticles(this.level, pos, randomSource, data, ParticleTypes.TRIAL_SPAWNER_DETECTED_PLAYER);
|
|
break;
|
|
case 3014:
|
|
this.level
|
|
.playLocalSound(
|
|
pos, SoundEvents.TRIAL_SPAWNER_EJECT_ITEM, SoundSource.BLOCKS, 1.0F, (randomSource.nextFloat() - randomSource.nextFloat()) * 0.2F + 1.0F, true
|
|
);
|
|
TrialSpawner.addEjectItemParticles(this.level, pos, randomSource);
|
|
break;
|
|
case 3015:
|
|
if (this.level.getBlockEntity(pos) instanceof VaultBlockEntity vaultBlockEntity) {
|
|
VaultBlockEntity.Client.emitActivationParticles(
|
|
this.level,
|
|
vaultBlockEntity.getBlockPos(),
|
|
vaultBlockEntity.getBlockState(),
|
|
vaultBlockEntity.getSharedData(),
|
|
data == 0 ? ParticleTypes.SMALL_FLAME : ParticleTypes.SOUL_FIRE_FLAME
|
|
);
|
|
this.level
|
|
.playLocalSound(pos, SoundEvents.VAULT_ACTIVATE, SoundSource.BLOCKS, 1.0F, (randomSource.nextFloat() - randomSource.nextFloat()) * 0.2F + 1.0F, true);
|
|
}
|
|
break;
|
|
case 3016:
|
|
VaultBlockEntity.Client.emitDeactivationParticles(this.level, pos, data == 0 ? ParticleTypes.SMALL_FLAME : ParticleTypes.SOUL_FIRE_FLAME);
|
|
this.level
|
|
.playLocalSound(pos, SoundEvents.VAULT_DEACTIVATE, SoundSource.BLOCKS, 1.0F, (randomSource.nextFloat() - randomSource.nextFloat()) * 0.2F + 1.0F, true);
|
|
break;
|
|
case 3017:
|
|
TrialSpawner.addEjectItemParticles(this.level, pos, randomSource);
|
|
break;
|
|
case 3018:
|
|
for (int sx = 0; sx < 10; sx++) {
|
|
double t = randomSource.nextGaussian() * 0.02;
|
|
double u = randomSource.nextGaussian() * 0.02;
|
|
double v = randomSource.nextGaussian() * 0.02;
|
|
this.level
|
|
.addParticle(
|
|
ParticleTypes.POOF, pos.getX() + randomSource.nextDouble(), pos.getY() + randomSource.nextDouble(), pos.getZ() + randomSource.nextDouble(), t, u, v
|
|
);
|
|
}
|
|
|
|
this.level
|
|
.playLocalSound(pos, SoundEvents.COBWEB_PLACE, SoundSource.BLOCKS, 1.0F, (randomSource.nextFloat() - randomSource.nextFloat()) * 0.2F + 1.0F, true);
|
|
break;
|
|
case 3019:
|
|
this.level
|
|
.playLocalSound(
|
|
pos, SoundEvents.TRIAL_SPAWNER_DETECT_PLAYER, SoundSource.BLOCKS, 1.0F, (randomSource.nextFloat() - randomSource.nextFloat()) * 0.2F + 1.0F, true
|
|
);
|
|
TrialSpawner.addDetectPlayerParticles(this.level, pos, randomSource, data, ParticleTypes.TRIAL_SPAWNER_DETECTED_PLAYER_OMINOUS);
|
|
break;
|
|
case 3020:
|
|
this.level
|
|
.playLocalSound(
|
|
pos,
|
|
SoundEvents.TRIAL_SPAWNER_OMINOUS_ACTIVATE,
|
|
SoundSource.BLOCKS,
|
|
data == 0 ? 0.3F : 1.0F,
|
|
(randomSource.nextFloat() - randomSource.nextFloat()) * 0.2F + 1.0F,
|
|
true
|
|
);
|
|
TrialSpawner.addDetectPlayerParticles(this.level, pos, randomSource, 0, ParticleTypes.TRIAL_SPAWNER_DETECTED_PLAYER_OMINOUS);
|
|
TrialSpawner.addBecomeOminousParticles(this.level, pos, randomSource);
|
|
break;
|
|
case 3021:
|
|
this.level
|
|
.playLocalSound(
|
|
pos, SoundEvents.TRIAL_SPAWNER_SPAWN_ITEM, SoundSource.BLOCKS, 1.0F, (randomSource.nextFloat() - randomSource.nextFloat()) * 0.2F + 1.0F, true
|
|
);
|
|
TrialSpawner.addSpawnParticles(this.level, pos, randomSource, TrialSpawner.FlameParticle.decode(data).particleType);
|
|
}
|
|
}
|
|
|
|
public void destroyBlockProgress(int breakerId, BlockPos pos, int progress) {
|
|
if (progress >= 0 && progress < 10) {
|
|
BlockDestructionProgress blockDestructionProgress = this.destroyingBlocks.get(breakerId);
|
|
if (blockDestructionProgress != null) {
|
|
this.removeProgress(blockDestructionProgress);
|
|
}
|
|
|
|
if (blockDestructionProgress == null
|
|
|| blockDestructionProgress.getPos().getX() != pos.getX()
|
|
|| blockDestructionProgress.getPos().getY() != pos.getY()
|
|
|| blockDestructionProgress.getPos().getZ() != pos.getZ()) {
|
|
blockDestructionProgress = new BlockDestructionProgress(breakerId, pos);
|
|
this.destroyingBlocks.put(breakerId, blockDestructionProgress);
|
|
}
|
|
|
|
blockDestructionProgress.setProgress(progress);
|
|
blockDestructionProgress.updateTick(this.ticks);
|
|
this.destructionProgress
|
|
.computeIfAbsent(
|
|
blockDestructionProgress.getPos().asLong(),
|
|
(Long2ObjectFunction<? extends SortedSet<BlockDestructionProgress>>)(l -> Sets.<BlockDestructionProgress>newTreeSet())
|
|
)
|
|
.add(blockDestructionProgress);
|
|
} else {
|
|
BlockDestructionProgress blockDestructionProgressx = this.destroyingBlocks.remove(breakerId);
|
|
if (blockDestructionProgressx != null) {
|
|
this.removeProgress(blockDestructionProgressx);
|
|
}
|
|
}
|
|
}
|
|
|
|
public boolean hasRenderedAllSections() {
|
|
return this.sectionRenderDispatcher.isQueueEmpty();
|
|
}
|
|
|
|
public void onChunkLoaded(ChunkPos chunkPos) {
|
|
this.sectionOcclusionGraph.onChunkLoaded(chunkPos);
|
|
}
|
|
|
|
public void needsUpdate() {
|
|
this.sectionOcclusionGraph.invalidate();
|
|
this.generateClouds = true;
|
|
}
|
|
|
|
public void updateGlobalBlockEntities(Collection<BlockEntity> blockEntitiesToRemove, Collection<BlockEntity> blockEntitiesToAdd) {
|
|
synchronized (this.globalBlockEntities) {
|
|
this.globalBlockEntities.removeAll(blockEntitiesToRemove);
|
|
this.globalBlockEntities.addAll(blockEntitiesToAdd);
|
|
}
|
|
}
|
|
|
|
public static int getLightColor(BlockAndTintGetter level, BlockPos pos) {
|
|
return getLightColor(level, level.getBlockState(pos), pos);
|
|
}
|
|
|
|
public static int getLightColor(BlockAndTintGetter level, BlockState state, BlockPos pos) {
|
|
if (state.emissiveRendering(level, pos)) {
|
|
return 15728880;
|
|
} else {
|
|
int i = level.getBrightness(LightLayer.SKY, pos);
|
|
int j = level.getBrightness(LightLayer.BLOCK, pos);
|
|
int k = state.getLightEmission();
|
|
if (j < k) {
|
|
j = k;
|
|
}
|
|
|
|
return i << 20 | j << 4;
|
|
}
|
|
}
|
|
|
|
public boolean isSectionCompiled(BlockPos pos) {
|
|
SectionRenderDispatcher.RenderSection renderSection = this.viewArea.getRenderSectionAt(pos);
|
|
return renderSection != null && renderSection.compiled.get() != SectionRenderDispatcher.CompiledSection.UNCOMPILED;
|
|
}
|
|
|
|
@Nullable
|
|
public RenderTarget entityTarget() {
|
|
return this.entityTarget;
|
|
}
|
|
|
|
@Nullable
|
|
public RenderTarget getTranslucentTarget() {
|
|
return this.translucentTarget;
|
|
}
|
|
|
|
@Nullable
|
|
public RenderTarget getItemEntityTarget() {
|
|
return this.itemEntityTarget;
|
|
}
|
|
|
|
@Nullable
|
|
public RenderTarget getParticlesTarget() {
|
|
return this.particlesTarget;
|
|
}
|
|
|
|
@Nullable
|
|
public RenderTarget getWeatherTarget() {
|
|
return this.weatherTarget;
|
|
}
|
|
|
|
@Nullable
|
|
public RenderTarget getCloudsTarget() {
|
|
return this.cloudsTarget;
|
|
}
|
|
|
|
private void shootParticles(int direction, BlockPos pos, RandomSource random, SimpleParticleType particleType) {
|
|
Direction direction2 = Direction.from3DDataValue(direction);
|
|
int i = direction2.getStepX();
|
|
int j = direction2.getStepY();
|
|
int k = direction2.getStepZ();
|
|
double d = pos.getX() + i * 0.6 + 0.5;
|
|
double e = pos.getY() + j * 0.6 + 0.5;
|
|
double f = pos.getZ() + k * 0.6 + 0.5;
|
|
|
|
for (int l = 0; l < 10; l++) {
|
|
double g = random.nextDouble() * 0.2 + 0.01;
|
|
double h = d + i * 0.01 + (random.nextDouble() - 0.5) * k * 0.5;
|
|
double m = e + j * 0.01 + (random.nextDouble() - 0.5) * j * 0.5;
|
|
double n = f + k * 0.01 + (random.nextDouble() - 0.5) * i * 0.5;
|
|
double o = i * g + random.nextGaussian() * 0.01;
|
|
double p = j * g + random.nextGaussian() * 0.01;
|
|
double q = k * g + random.nextGaussian() * 0.01;
|
|
this.addParticle(particleType, h, m, n, o, p, q);
|
|
}
|
|
}
|
|
|
|
@Environment(EnvType.CLIENT)
|
|
public static class TransparencyShaderException extends RuntimeException {
|
|
public TransparencyShaderException(String message, Throwable cause) {
|
|
super(message, cause);
|
|
}
|
|
}
|
|
}
|