package com.smartmobculling.mixin;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.Camera;
import net.minecraft.client.render.WorldRenderer;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.entity.Entity;
import net.minecraft.entity.mob.MobEntity;
import net.minecraft.util.math.Vec3d;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(WorldRenderer.class)
public class SmartMobCullingMixin {
@Inject(
method = "renderEntity",
at = @At("HEAD"),
cancellable = true
)
private void smartmobculling$skipInvisibleMobs(
Entity entity,
double cameraX,
double cameraY,
double cameraZ,
float tickDelta,
MatrixStack matrices,
VertexConsumerProvider vertexConsumers,
CallbackInfo ci
) {
if (!(entity instanceof MobEntity)) {
return;
}
MinecraftClient client = MinecraftClient.getInstance();
if (client.world == null || client.player == null) {
return;
}
Camera camera = client.gameRenderer.getCamera();
Vec3d cameraPos = camera.getPos();
Vec3d entityPos = entity.getBoundingBox().getCenter();
Vec3d toEntity = entityPos.subtract(cameraPos);
if (toEntity.lengthSquared() < 0.0001) {
return;
}
toEntity = toEntity.normalize();
float yaw = camera.getYaw();
float pitch = camera.getPitch();
double yawRad = Math.toRadians(yaw);
double pitchRad = Math.toRadians(pitch);
Vec3d forward = new Vec3d(
-Math.sin(yawRad) * Math.cos(pitchRad),
-Math.sin(pitchRad),
Math.cos(yawRad) * Math.cos(pitchRad)
);
double dot = forward.dotProduct(toEntity);
// Моб находится позади направления камеры.
if (dot < -0.15) {
ci.cancel();
}
}
}