/*
* Copyright (C) 2022 NotEnoughUpdates contributors
*
* This file is part of NotEnoughUpdates.
*
* NotEnoughUpdates is free software: you can redistribute it
* and/or modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation, either
* version 3 of the License, or (at your option) any later version.
*
* NotEnoughUpdates is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with NotEnoughUpdates. If not, see .
*/
package io.github.moulberry.notenoughupdates.miscfeatures;
import io.github.moulberry.notenoughupdates.autosubscribe.NEUAutoSubscribe;
import io.github.moulberry.notenoughupdates.util.ReverseWorldRenderer;
import io.github.moulberry.notenoughupdates.util.SpecialColour;
import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.client.renderer.vertex.VertexFormat;
import net.minecraft.client.renderer.vertex.VertexFormatElement;
import net.minecraft.entity.Entity;
import net.minecraft.util.AxisAlignedBB;
import net.minecraft.util.BlockPos;
import net.minecraftforge.client.event.RenderWorldLastEvent;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.common.gameevent.TickEvent;
import org.lwjgl.opengl.GL11;
import java.awt.*;
import java.nio.ByteBuffer;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@NEUAutoSubscribe
public class NullzeeSphere {
public static boolean enabled = false;
public static float size = 20;
public static BlockPos centerPos = new BlockPos(0, 0, 0);
public static ReverseWorldRenderer overlayVBO = null;
public ReverseWorldRenderer getOverlayVBO() {
if (overlayVBO != null) return overlayVBO;
EntityPlayerSP p = Minecraft.getMinecraft().thePlayer;
if (p == null) return null;
//per vertex = 6
//per size = 4
//per block = 8
//total per block = 196
Set circleOffsets = getCircleOffsets(size);
ReverseWorldRenderer worldRenderer = new ReverseWorldRenderer(196 * circleOffsets.size());
worldRenderer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_COLOR);
String col = SpecialColour.special(0, 180, 0xffff9900);
for (BlockPos offset : circleOffsets) {
BlockPos overlayPos = new BlockPos(offset.getX(), offset.getY(), offset.getZ());
AxisAlignedBB bb = new AxisAlignedBB(
overlayPos.getX(),
overlayPos.getY(),
overlayPos.getZ(),
overlayPos.getX() + 1,
overlayPos.getY() + 1,
overlayPos.getZ() + 1
).expand(0.001f, 0.001f, 0.001f);
uploadFilledBoundingBox(bb, 1f, col, worldRenderer);
}
overlayVBO = worldRenderer;
return overlayVBO;
}
public Set getCircleOffsets(float radius) {
Set circleOffsets = new HashSet<>();
int radiusI = (int) Math.ceil(radius) + 1;
for (int x = -radiusI; x <= radiusI; x++) {
for (int y = -radiusI; y <= radiusI; y++) {
for (int z = -radiusI; z <= radiusI; z++) {
float distSq = x * x + y * y + z * z;
if (distSq >= (radius - 0.5) * (radius - 0.5) && distSq <= (radius + 0.5) * (radius + 0.5)) {
circleOffsets.add(new BlockPos(x, y, z));
}
}
}
}
return circleOffsets;
}
long lastUpdate = 0;
private static double posLastUpdateX;
private static double posLastUpdateY;
private static double posLastUpdateZ;
@SubscribeEvent
public void onTick(TickEvent.ClientTickEvent event) {
if (!enabled) return;
EntityPlayerSP p = Minecraft.getMinecraft().thePlayer;
if (p == null) return;
if (event.phase == TickEvent.Phase.START) {
double dX = p.posX - posLastUpdateX;
double dY = p.posY - posLastUpdateY;
double dZ = p.posZ - posLastUpdateZ;
if (dX * dX + dY * dY + dZ * dZ < 1) {
return;
}
posLastUpdateX = p.posX;
posLastUpdateY = p.posY;
posLastUpdateZ = p.posZ;
long currentTime = System.currentTimeMillis();
if (currentTime - lastUpdate < 250) {
return;
}
lastUpdate = currentTime;
ReverseWorldRenderer worldRenderer = getOverlayVBO();
if (worldRenderer != null) {
worldRenderer.setTranslation(0, 0, 0);
worldRenderer.sortVertexData(
(float) p.posX - centerPos.getX(),
(float) p.posY - centerPos.getY(),
(float) p.posZ - centerPos.getZ()
);
}
}
}
@SubscribeEvent
public void onRenderLast(RenderWorldLastEvent event) {
if (!enabled) return;
Entity viewer = Minecraft.getMinecraft().getRenderViewEntity();
double viewerX = viewer.lastTickPosX + (viewer.posX - viewer.lastTickPosX) * event.partialTicks;
double viewerY = viewer.lastTickPosY + (viewer.posY - viewer.lastTickPosY) * event.partialTicks;
double viewerZ = viewer.lastTickPosZ + (viewer.posZ - viewer.lastTickPosZ) * event.partialTicks;
GlStateManager.enableBlend();
GlStateManager.tryBlendFuncSeparate(770, 771, 1, 0);
GlStateManager.disableTexture2D();
GlStateManager.translate(-viewerX, -viewerY, -viewerZ);
GL11.glPolygonOffset(5, 5);
ReverseWorldRenderer worldRenderer = getOverlayVBO();
if (worldRenderer != null && worldRenderer.getVertexCount() > 0) {
GlStateManager.translate(centerPos.getX(), centerPos.getY(), centerPos.getZ());
VertexFormat vertexformat = worldRenderer.getVertexFormat();
int stride = vertexformat.getNextOffset();
ByteBuffer bytebuffer = worldRenderer.getByteBuffer();
List list = vertexformat.getElements();
for (int index = 0; index < list.size(); index++) {
VertexFormatElement vertexformatelement = list.get(index);
vertexformatelement.getUsage().preDraw(vertexformat, index, stride, bytebuffer);
}
GL11.glDrawArrays(worldRenderer.getDrawMode(), 0, worldRenderer.getVertexCount());
for (int index = 0; index < list.size(); index++) {
VertexFormatElement vertexformatelement = list.get(index);
vertexformatelement.getUsage().postDraw(vertexformat, index, stride, bytebuffer);
}
GlStateManager.translate(-centerPos.getX(), -centerPos.getY(), -centerPos.getZ());
}
GL11.glPolygonOffset(0, 0);
GlStateManager.translate(viewerX, viewerY, viewerZ);
GlStateManager.enableTexture2D();
}
public static void uploadFilledBoundingBox(
AxisAlignedBB p_181561_0_,
float alpha,
String special,
ReverseWorldRenderer worldrenderer
) {
Color c = new Color(SpecialColour.specialToChromaRGB(special), true);
//vertical
worldrenderer
.pos(p_181561_0_.minX, p_181561_0_.minY, p_181561_0_.minZ)
.color(c.getRed() / 255f, c.getGreen() / 255f, c.getBlue() / 255f, c.getAlpha() / 255f * alpha)
.endVertex();
worldrenderer
.pos(p_181561_0_.maxX, p_181561_0_.minY, p_181561_0_.minZ)
.color(c.getRed() / 255f, c.getGreen() / 255f, c.getBlue() / 255f, c.getAlpha() / 255f * alpha)
.endVertex();
worldrenderer
.pos(p_181561_0_.maxX, p_181561_0_.minY, p_181561_0_.maxZ)
.color(c.getRed() / 255f, c.getGreen() / 255f, c.getBlue() / 255f, c.getAlpha() / 255f * alpha)
.endVertex();
worldrenderer
.pos(p_181561_0_.minX, p_181561_0_.minY, p_181561_0_.maxZ)
.color(c.getRed() / 255f, c.getGreen() / 255f, c.getBlue() / 255f, c.getAlpha() / 255f * alpha)
.endVertex();
worldrenderer
.pos(p_181561_0_.minX, p_181561_0_.maxY, p_181561_0_.maxZ)
.color(c.getRed() / 255f, c.getGreen() / 255f, c.getBlue() / 255f, c.getAlpha() / 255f * alpha)
.endVertex();
worldrenderer
.pos(p_181561_0_.maxX, p_181561_0_.maxY, p_181561_0_.maxZ)
.color(c.getRed() / 255f, c.getGreen() / 255f, c.getBlue() / 255f, c.getAlpha() / 255f * alpha)
.endVertex();
worldrenderer
.pos(p_181561_0_.maxX, p_181561_0_.maxY, p_181561_0_.minZ)
.color(c.getRed() / 255f, c.getGreen() / 255f, c.getBlue() / 255f, c.getAlpha() / 255f * alpha)
.endVertex();
worldrenderer
.pos(p_181561_0_.minX, p_181561_0_.maxY, p_181561_0_.minZ)
.color(c.getRed() / 255f, c.getGreen() / 255f, c.getBlue() / 255f, c.getAlpha() / 255f * alpha)
.endVertex();
//x
worldrenderer.pos(p_181561_0_.minX, p_181561_0_.minY, p_181561_0_.maxZ)
.color(
c.getRed() / 255f * 0.8f,
c.getGreen() / 255f * 0.8f,
c.getBlue() / 255f * 0.8f,
c.getAlpha() / 255f * alpha
).endVertex();
worldrenderer.pos(p_181561_0_.minX, p_181561_0_.maxY, p_181561_0_.maxZ)
.color(
c.getRed() / 255f * 0.8f,
c.getGreen() / 255f * 0.8f,
c.getBlue() / 255f * 0.8f,
c.getAlpha() / 255f * alpha
).endVertex();
worldrenderer.pos(p_181561_0_.minX, p_181561_0_.maxY, p_181561_0_.minZ)
.color(
c.getRed() / 255f * 0.8f,
c.getGreen() / 255f * 0.8f,
c.getBlue() / 255f * 0.8f,
c.getAlpha() / 255f * alpha
).endVertex();
worldrenderer.pos(p_181561_0_.minX, p_181561_0_.minY, p_181561_0_.minZ)
.color(
c.getRed() / 255f * 0.8f,
c.getGreen() / 255f * 0.8f,
c.getBlue() / 255f * 0.8f,
c.getAlpha() / 255f * alpha
).endVertex();
worldrenderer.pos(p_181561_0_.maxX, p_181561_0_.minY, p_181561_0_.minZ)
.color(
c.getRed() / 255f * 0.8f,
c.getGreen() / 255f * 0.8f,
c.getBlue() / 255f * 0.8f,
c.getAlpha() / 255f * alpha
).endVertex();
worldrenderer.pos(p_181561_0_.maxX, p_181561_0_.maxY, p_181561_0_.minZ)
.color(
c.getRed() / 255f * 0.8f,
c.getGreen() / 255f * 0.8f,
c.getBlue() / 255f * 0.8f,
c.getAlpha() / 255f * alpha
).endVertex();
worldrenderer.pos(p_181561_0_.maxX, p_181561_0_.maxY, p_181561_0_.maxZ)
.color(
c.getRed() / 255f * 0.8f,
c.getGreen() / 255f * 0.8f,
c.getBlue() / 255f * 0.8f,
c.getAlpha() / 255f * alpha
).endVertex();
worldrenderer.pos(p_181561_0_.maxX, p_181561_0_.minY, p_181561_0_.maxZ)
.color(
c.getRed() / 255f * 0.8f,
c.getGreen() / 255f * 0.8f,
c.getBlue() / 255f * 0.8f,
c.getAlpha() / 255f * alpha
).endVertex();
//z
worldrenderer.pos(p_181561_0_.minX, p_181561_0_.maxY, p_181561_0_.minZ)
.color(
c.getRed() / 255f * 0.9f,
c.getGreen() / 255f * 0.9f,
c.getBlue() / 255f * 0.9f,
c.getAlpha() / 255f * alpha
).endVertex();
worldrenderer.pos(p_181561_0_.maxX, p_181561_0_.maxY, p_181561_0_.minZ)
.color(
c.getRed() / 255f * 0.9f,
c.getGreen() / 255f * 0.9f,
c.getBlue() / 255f * 0.9f,
c.getAlpha() / 255f * alpha
).endVertex();
worldrenderer.pos(p_181561_0_.maxX, p_181561_0_.minY, p_181561_0_.minZ)
.color(
c.getRed() / 255f * 0.9f,
c.getGreen() / 255f * 0.9f,
c.getBlue() / 255f * 0.9f,
c.getAlpha() / 255f * alpha
).endVertex();
worldrenderer.pos(p_181561_0_.minX, p_181561_0_.minY, p_181561_0_.minZ)
.color(
c.getRed() / 255f * 0.9f,
c.getGreen() / 255f * 0.9f,
c.getBlue() / 255f * 0.9f,
c.getAlpha() / 255f * alpha
).endVertex();
worldrenderer.pos(p_181561_0_.minX, p_181561_0_.minY, p_181561_0_.maxZ)
.color(
c.getRed() / 255f * 0.9f,
c.getGreen() / 255f * 0.9f,
c.getBlue() / 255f * 0.9f,
c.getAlpha() / 255f * alpha
).endVertex();
worldrenderer.pos(p_181561_0_.maxX, p_181561_0_.minY, p_181561_0_.maxZ)
.color(
c.getRed() / 255f * 0.9f,
c.getGreen() / 255f * 0.9f,
c.getBlue() / 255f * 0.9f,
c.getAlpha() / 255f * alpha
).endVertex();
worldrenderer.pos(p_181561_0_.maxX, p_181561_0_.maxY, p_181561_0_.maxZ)
.color(
c.getRed() / 255f * 0.9f,
c.getGreen() / 255f * 0.9f,
c.getBlue() / 255f * 0.9f,
c.getAlpha() / 255f * alpha
).endVertex();
worldrenderer.pos(p_181561_0_.minX, p_181561_0_.maxY, p_181561_0_.maxZ)
.color(
c.getRed() / 255f * 0.9f,
c.getGreen() / 255f * 0.9f,
c.getBlue() / 255f * 0.9f,
c.getAlpha() / 255f * alpha
).endVertex();
}
}