/* * 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.miscgui.util; import io.github.moulberry.notenoughupdates.core.util.lerp.LerpUtils; import io.github.moulberry.notenoughupdates.util.Utils; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.util.ResourceLocation; import org.lwjgl.opengl.GL11; import org.lwjgl.util.vector.Vector2f; import java.util.ArrayList; import java.util.List; import java.util.ListIterator; import java.util.Random; public class OrbDisplay { private static final ResourceLocation TEXTURE = new ResourceLocation("notenoughupdates:custom_enchant_gui.png"); private static final int DEFAULT_COUNT = 30; private final List experienceOrbList = new ArrayList<>(); public ExperienceOrb spawnExperienceOrb(Random random, Vector2f start, Vector2f target, int baseType) { ExperienceOrb orb = new ExperienceOrb(); orb.position = new Vector2f(start); orb.positionLast = new Vector2f(orb.position); orb.velocity = new Vector2f( random.nextFloat() * 20 - 10, random.nextFloat() * 20 - 10 ); orb.target = new Vector2f(target); orb.type = baseType; orb.rotationDeg = random.nextInt(4) * 90; float v = random.nextFloat(); if (v > 0.6) { orb.type += 1; } if (v > 0.9) { orb.type += 1; } experienceOrbList.add(orb); return orb; } public void spawnExperienceOrbs(int startX, int startY, int targetX, int targetY, int baseType) { spawnExperienceOrbs(new Random(),new Vector2f(startX, startY), new Vector2f(targetX, targetY), baseType, DEFAULT_COUNT); } public void spawnExperienceOrbs(Random random, Vector2f start, Vector2f target, int baseType, int count) { for (int i = 0; i < count; i++) { spawnExperienceOrb(random, start, target, baseType); } } public void physicsTickOrbs() { for (ListIterator it = experienceOrbList.listIterator(); it.hasNext(); ) { ExperienceOrb orb = it.next(); Vector2f delta = Vector2f.sub(orb.target, orb.position, null); float length = delta.length(); // Remove close Orbs if (length < 8 && orb.velocity.lengthSquared() < 20) { it.remove(); continue; } // Update velocity Vector2f.add(orb.velocity, (Vector2f) delta.scale(2 / length), orb.velocity); orb.velocity.scale(0.9F); // Update position orb.positionLast.set(orb.position); Vector2f.add(orb.position, orb.velocity, orb.position); } } public void renderOrbs(float partialTicks) { Minecraft.getMinecraft().getTextureManager().bindTexture(TEXTURE); GlStateManager.disableDepth(); for (ExperienceOrb orb : experienceOrbList) { int orbX = Math.round(LerpUtils.lerp(orb.position.x, orb.positionLast.x, partialTicks)); int orbY = Math.round(LerpUtils.lerp(orb.position.y, orb.positionLast.y, partialTicks)); GlStateManager.pushMatrix(); GlStateManager.translate(orbX, orbY, 0); GlStateManager.rotate(orb.rotationDeg, 0, 0, 1); Vector2f delta = Vector2f.sub(orb.position, orb.target, null); float length = delta.length(); float velocitySquared = orb.velocity.lengthSquared(); float opacity = (float) Math.sqrt( Math.min( 1, Math.min(2, Math.max(0.5F, length / 16)) * Math.min(2, Math.max(0.5F, velocitySquared / 40)) )); GlStateManager.color(1, 1, 1, opacity); int orbU = (orb.type % 3) * 16; int orbV = (orb.type / 3) * 16 + 217; Utils.drawTexturedRect( -8, -8, 16, 16, orbU / 512f, (orbU + 16) / 512f, orbV / 512f, (orbV + 16) / 512f, GL11.GL_NEAREST ); GlStateManager.popMatrix(); } GlStateManager.enableDepth(); } }