aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures
diff options
context:
space:
mode:
authorohowe <42757516+carelesshippo@users.noreply.github.com>2021-06-02 11:55:36 -0600
committerohowe <42757516+carelesshippo@users.noreply.github.com>2021-06-02 11:55:36 -0600
commiteeb5c45d71997cb259fc35330490a19db7865603 (patch)
tree65771b27ed837896fa3140dec1af78306accebcd /src/main/java/io/github/moulberry/notenoughupdates/miscfeatures
parent4d9e538ced80728bca74491698347333f515bfcc (diff)
parent1b172089ce502803f7644611afd618ce00dcb860 (diff)
downloadnotenoughupdates-eeb5c45d71997cb259fc35330490a19db7865603.tar.gz
notenoughupdates-eeb5c45d71997cb259fc35330490a19db7865603.tar.bz2
notenoughupdates-eeb5c45d71997cb259fc35330490a19db7865603.zip
Merge branch 'Moulberry:master' into master
Diffstat (limited to 'src/main/java/io/github/moulberry/notenoughupdates/miscfeatures')
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/DamageCommas.java5
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/FancyPortals.java303
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/FishingHelper.java549
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/ItemCooldowns.java6
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/ItemCustomizeManager.java1
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/NPCRetexturing.java1
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/SlotLocking.java295
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/StorageManager.java8
8 files changed, 1087 insertions, 81 deletions
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/DamageCommas.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/DamageCommas.java
index c2f778a5..553a5d40 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/DamageCommas.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/DamageCommas.java
@@ -13,6 +13,7 @@ public class DamageCommas {
private static final HashMap<Integer, ChatComponentText> replacementMap = new HashMap<>();
+ //From [MVP++] HY7:
private static final EnumChatFormatting[] colours = {EnumChatFormatting.RED, EnumChatFormatting.GOLD, EnumChatFormatting.YELLOW, EnumChatFormatting.WHITE};
public static void tick() {
@@ -31,8 +32,8 @@ public class DamageCommas {
return component;
}
- if(formatted.length() >= 7 && formatted.startsWith("\u00A7f\u2727") &&
- formatted.endsWith("\u2727\u00a7r")) {
+ if(formatted.length() >= 7 && (formatted.startsWith("\u00A7f\u2727") || formatted.startsWith("\u00A7f\u2694")) &&
+ (formatted.endsWith("\u2727\u00a7r") || formatted.endsWith("\u2694\u00a7r"))) {
if(NotEnoughUpdates.INSTANCE.config.misc.damageIndicatorStyle == 2) {
String numbers = Utils.cleanColour(formatted.substring(3, formatted.length()-3)).trim().replaceAll("[^0-9]", "");
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/FancyPortals.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/FancyPortals.java
new file mode 100644
index 00000000..a9be6fd5
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/FancyPortals.java
@@ -0,0 +1,303 @@
+package io.github.moulberry.notenoughupdates.miscfeatures;
+
+import io.github.moulberry.notenoughupdates.cosmetics.CapeNode;
+import io.github.moulberry.notenoughupdates.util.ReverseWorldRenderer;
+import io.github.moulberry.notenoughupdates.util.TexLoc;
+import io.github.moulberry.notenoughupdates.util.Utils;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.entity.EntityPlayerSP;
+import net.minecraft.client.gui.Gui;
+import net.minecraft.client.gui.ScaledResolution;
+import net.minecraft.client.multiplayer.WorldClient;
+import net.minecraft.client.renderer.GlStateManager;
+import net.minecraft.client.renderer.RenderGlobal;
+import net.minecraft.client.renderer.WorldRenderer;
+import net.minecraft.client.renderer.chunk.CompiledChunk;
+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.entity.EntityLiving;
+import net.minecraft.entity.EntityLivingBase;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.network.play.server.S07PacketRespawn;
+import net.minecraft.util.BlockPos;
+import net.minecraft.util.MathHelper;
+import net.minecraft.util.ResourceLocation;
+import net.minecraftforge.client.event.GuiScreenEvent;
+import net.minecraftforge.client.event.RenderLivingEvent;
+import net.minecraftforge.client.event.RenderWorldLastEvent;
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
+import org.lwjgl.input.Keyboard;
+import org.lwjgl.opengl.GL11;
+import org.lwjgl.util.glu.Project;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
+
+import java.nio.ByteBuffer;
+import java.util.List;
+
+public class FancyPortals {
+
+ private static ResourceLocation[] RENDERS = new ResourceLocation[6];
+
+ static {
+ for(int i=0; i<6; i++) {
+ RENDERS[i] = new ResourceLocation("notenoughupdates:portal_panoramas/nether/pansc-"+(i+1)+".png");
+ }
+ }
+
+ public static int perspectiveId = -1;
+ public static boolean overridePerspective() {
+ if(perspectiveId >= 0 && !Keyboard.isKeyDown(Keyboard.KEY_K)) {
+ if(perspectiveId == 0) {
+ GlStateManager.matrixMode(5889);
+ GlStateManager.loadIdentity();
+ GlStateManager.ortho(0.0D, 7, 7, 0.0D, -100D, 100D);
+ GlStateManager.scale(1, 1, -1);
+ GlStateManager.matrixMode(5888);
+ GlStateManager.loadIdentity();
+ GlStateManager.translate(3.5F, 3.5F, -1.0F);
+ GlStateManager.rotate(-90, 1, 0, 0);
+ } else if(perspectiveId <= 4) {
+ GlStateManager.matrixMode(5889);
+ GlStateManager.loadIdentity();
+ Project.gluPerspective(90, 1, 0.05F, 160 * MathHelper.SQRT_2);
+ GlStateManager.matrixMode(5888);
+ GlStateManager.loadIdentity();
+ GlStateManager.rotate(perspectiveId*90, 0, 1, 0);
+ GlStateManager.translate(0, -3.5f, 0);
+ } else {
+ GlStateManager.matrixMode(5889);
+ GlStateManager.loadIdentity();
+ Project.gluPerspective(90, 1, 0.05F, 160 * MathHelper.SQRT_2);
+ GlStateManager.matrixMode(5888);
+ GlStateManager.loadIdentity();
+ GlStateManager.rotate(-90, 1, 0, 0);
+ GlStateManager.translate(0, -3.5f, 0);
+ }
+
+ return true;
+ }
+ return false;
+ }
+
+ private static WorldRenderer surfaceWorldRenderer = null;
+
+ private static WorldRenderer getSurfaceWorldRenderer() {
+ if(surfaceWorldRenderer != null && !Keyboard.isKeyDown(Keyboard.KEY_O)) {
+ return surfaceWorldRenderer;
+ }
+
+ surfaceWorldRenderer = createSurfaceWorldRenderer();
+
+ return surfaceWorldRenderer;
+ }
+
+ private static void drawPoint(WorldRenderer worldRenderer, int x, int y) {
+ float xDist = 1-Math.abs(x-50)/50f;
+ float yDist = 1-Math.abs(y-50)/50f;
+ float distToEdge = Math.min(xDist, yDist);
+
+ float z = 0.4142f;
+ if(distToEdge < 1/3.5f) {
+ if(y > 50 && yDist < xDist) {
+ float circleH = 1.414f - distToEdge*3.5f*1.414f;
+ z = (float)Math.sqrt(2f-circleH*circleH);
+ z *= 0.4142f / 1.4142f;
+ } else {
+ float circleH = 1 - distToEdge*3.5f;
+ z = (float)Math.sqrt(2f-circleH*circleH)-1;
+ }
+ }
+
+ worldRenderer.pos(x*7/100f, y*7/100f, z).tex(x/100f, y/100f).endVertex();
+ }
+
+ private static WorldRenderer createSurfaceWorldRenderer() {
+ WorldRenderer worldRenderer = new WorldRenderer(20*100*100);
+ worldRenderer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX);
+
+ for(int x=0; x<100; x++) {
+ for(int y=0; y<100; y++) {
+ drawPoint(worldRenderer, x, y);
+ drawPoint(worldRenderer, x, y+1);
+ drawPoint(worldRenderer, x+1, y+1);
+ drawPoint(worldRenderer, x+1, y);
+ }
+ }
+
+ return worldRenderer;
+ }
+
+ private static long overridingRenderMillis = -1;
+
+ public static void onRespawnPacket(S07PacketRespawn packet) {
+ if(true) return;
+ if (packet.getDimensionID() != Minecraft.getMinecraft().thePlayer.dimension) {
+ overridingRenderMillis = System.currentTimeMillis();
+ }
+ }
+
+ public static boolean shouldRenderLoadingScreen() {
+ return false;
+ }
+
+ public static boolean shouldRenderWorldOverlay() {
+ if(overridingRenderMillis > 0) {
+ if(Minecraft.getMinecraft().theWorld != null && Minecraft.getMinecraft().thePlayer != null) {
+ RenderGlobal renderGlobal = Minecraft.getMinecraft().renderGlobal;
+ int loaded = 0;
+ for(RenderGlobal.ContainerLocalRenderInformation info : renderGlobal.renderInfos) {
+ CompiledChunk compiledchunk = info.renderChunk.compiledChunk;
+
+ if (compiledchunk != CompiledChunk.DUMMY && !compiledchunk.isEmpty()) {
+ if(++loaded >= 5) {
+ overridingRenderMillis = -1;
+ return false;
+ }
+ }
+ }
+ }
+ if(System.currentTimeMillis() - overridingRenderMillis > 1000) {
+ overridingRenderMillis = -1;
+ return false;
+ }
+ return true;
+ }
+ return false;
+ }
+
+ public static void onUpdateCameraAndRender(float partialTicks, long nanoTime) {
+ if(overridingRenderMillis > 0) {
+ if(Minecraft.getMinecraft().theWorld != null && Minecraft.getMinecraft().thePlayer != null) {
+ Minecraft.getMinecraft().thePlayer.timeInPortal = 0.3f;
+ Minecraft.getMinecraft().thePlayer.prevTimeInPortal = 0.3f;
+ }
+
+ GlStateManager.rotate(90, 0, 1, 0);
+ renderWorld();
+
+ Minecraft.getMinecraft().ingameGUI.renderGameOverlay(partialTicks);
+ }
+ }
+
+ @SubscribeEvent
+ public void onRenderEntityYeeter(RenderLivingEvent.Pre<EntityLivingBase> event) {
+ /*if(!Keyboard.isKeyDown(Keyboard.KEY_G)) return;
+ event.setCanceled(true);
+ if(event.entity instanceof EntityPlayer) {
+ EntityPlayer player = (EntityPlayer) event.entity;
+ if(player.getUniqueID().version() == 4) {
+ event.setCanceled(true);
+ }
+ }*/
+ }
+
+ private static void renderWorld() {
+ for(int i=5; i>=0; i--) {
+ GlStateManager.pushMatrix();
+
+ GlStateManager.disableDepth();
+ GlStateManager.disableLighting();
+
+
+ GlStateManager.rotate(180, 0, 0, 1);
+ GlStateManager.rotate(-90, 0, 1, 0);
+
+ if(i != 0) GlStateManager.translate(0, -3.49, 0);
+
+ switch (i) {
+ case 1:
+ GlStateManager.rotate(90.0F, 0.0F, 1.0F, 0.0F); break;
+ case 2:
+ GlStateManager.rotate(180.0F, 0.0F, 1.0F, 0.0F); break;
+ case 3:
+ GlStateManager.rotate(-90.0F, 0.0F, 1.0F, 0.0F); break;
+ case 5:
+ GlStateManager.rotate(90.0F, 1.0F, 0.0F, 0.0F); break;
+ case 0:
+ GlStateManager.rotate(-90.0F, 1.0F, 0.0F, 0.0F); break;
+ }
+
+ Minecraft.getMinecraft().getTextureManager().bindTexture(RENDERS[i]);
+ GlStateManager.color(1, 1, 1, 1);
+ if(i != 0) GlStateManager.translate(0, 0, 3.49);
+
+ if(i != 0) {
+ GlStateManager.translate(-3.5f, -3.5f, 0);
+ WorldRenderer worldRenderer = getSurfaceWorldRenderer();
+ VertexFormat vertexformat = worldRenderer.getVertexFormat();
+ int stride = vertexformat.getNextOffset();
+ ByteBuffer bytebuffer = worldRenderer.getByteBuffer();
+ List<VertexFormatElement> 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);
+ }
+ } else {
+ Utils.drawTexturedRect(-3.5f, -3.5f, 7, 7, i == 0 ? GL11.GL_NEAREST : GL11.GL_LINEAR);
+ }
+
+ GlStateManager.enableDepth();
+
+ GlStateManager.popMatrix();
+ }
+ }
+
+ @SubscribeEvent
+ public void onRenderLast(RenderWorldLastEvent event) {
+ if(true) return;
+ if(!Minecraft.getMinecraft().getFramebuffer().isStencilEnabled())
+ Minecraft.getMinecraft().getFramebuffer().enableStencil();
+
+ GL11.glEnable(GL11.GL_STENCIL_TEST);
+ GL11.glStencilFunc(GL11.GL_ALWAYS, 1, 0xFF);
+ GL11.glStencilOp(GL11.GL_ZERO, GL11.GL_ZERO, GL11.GL_REPLACE);
+ GL11.glStencilMask(0xFF);
+ GL11.glClear(GL11.GL_STENCIL_BUFFER_BIT);
+ GlStateManager.enableDepth();
+ GlStateManager.enableCull();
+ GlStateManager.cullFace(GL11.GL_BACK);
+
+ GL11.glColorMask(false, false, false, false);
+
+ 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.pushMatrix();
+
+ GlStateManager.translate(-viewerX+12+5/16f, -viewerY+100, -viewerZ+39);
+ GlStateManager.rotate(90, 0, 1, 0);
+ Gui.drawRect(0, 5, 3, 0, 0xffffffff);
+ GlStateManager.rotate(180, 0, 1, 0);
+ GlStateManager.translate(-3, 0, -6/16f);
+ Gui.drawRect(0, 5, 3, 0, 0xffffffff);
+
+ GlStateManager.popMatrix();
+
+
+ GL11.glColorMask(true, true, true, true);
+
+ // Only pass stencil test if equal to 1
+ GL11.glStencilMask(0x00);
+ GL11.glStencilFunc(GL11.GL_EQUAL, 1, 0xFF);
+
+ GlStateManager.translate(-viewerX+12, -viewerY+100, -viewerZ+37.5f);
+
+ renderWorld();
+
+ GL11.glDisable(GL11.GL_STENCIL_TEST);
+ GlStateManager.enableCull();
+ }
+
+
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/FishingHelper.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/FishingHelper.java
new file mode 100644
index 00000000..2c59fcd8
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/FishingHelper.java
@@ -0,0 +1,549 @@
+package io.github.moulberry.notenoughupdates.miscfeatures;
+
+import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import io.github.moulberry.notenoughupdates.util.SpecialColour;
+import io.github.moulberry.notenoughupdates.util.Utils;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.audio.ISound;
+import net.minecraft.client.audio.PositionedSound;
+import net.minecraft.client.audio.PositionedSoundRecord;
+import net.minecraft.client.particle.EntityFX;
+import net.minecraft.client.renderer.GlStateManager;
+import net.minecraft.entity.Entity;
+import net.minecraft.entity.projectile.EntityFishHook;
+import net.minecraft.init.Items;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.EnumParticleTypes;
+import net.minecraft.util.ResourceLocation;
+import net.minecraftforge.event.entity.player.PlayerInteractEvent;
+import net.minecraftforge.event.world.WorldEvent;
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
+import net.minecraftforge.fml.common.gameevent.TickEvent;
+import org.lwjgl.opengl.GL11;
+
+import java.util.*;
+
+public class FishingHelper {
+
+ private static final FishingHelper INSTANCE = new FishingHelper();
+
+ public static FishingHelper getInstance() {
+ return INSTANCE;
+ }
+
+ public static class WakeChain {
+ public int particleNum = 0;
+ public long lastUpdate;
+ public double currentAngle;
+ public double currentX;
+ public double currentZ;
+
+ public final HashMap<Integer, Double> distances = new HashMap<>();
+
+ public WakeChain(long lastUpdate, double currentAngle, double currentX, double currentZ) {
+ this.lastUpdate = lastUpdate;
+ this.currentAngle = currentAngle;
+ this.currentX = currentX;
+ this.currentZ = currentZ;
+ }
+ }
+
+ private enum PlayerWarningState {
+ NOTHING,
+ FISH_INCOMING,
+ FISH_HOOKED
+ }
+ private PlayerWarningState warningState = PlayerWarningState.NOTHING;
+ private int hookedWarningStateTicks = 0;
+
+ public final HashMap<Integer, EntityFishHook> hookEntities = new HashMap<>();
+ public final HashMap<WakeChain, List<Integer>> chains = new HashMap<>();
+
+ private long lastCastRodMillis = 0;
+ private int pingDelayTicks = 0;
+ private final List<Integer> pingDelayList = new ArrayList<>();
+ private int buildupSoundDelay = 0;
+
+ private static final ResourceLocation FISHING_WARNING_EXCLAM = new ResourceLocation("notenoughupdates:fishing_warning_exclam.png");
+ public void onRenderBobber(EntityFishHook hook) {
+ if(Minecraft.getMinecraft().thePlayer.fishEntity == hook && warningState != PlayerWarningState.NOTHING) {
+ GlStateManager.disableCull();
+ GlStateManager.disableLighting();
+ GL11.glDepthFunc(GL11.GL_ALWAYS);
+ GlStateManager.scale(1, -1, 1);
+
+ float offset = warningState == PlayerWarningState.FISH_HOOKED ? 0.5f : 0f;
+
+ float centerOffset = 0.5f/8f;
+ Minecraft.getMinecraft().getTextureManager().bindTexture(FISHING_WARNING_EXCLAM);
+ Utils.drawTexturedRect(centerOffset - 4f/8f, -20/8f, 1f, 2f, 0+offset, 0.5f+offset, 0, 1, GL11.GL_NEAREST);
+
+ GlStateManager.scale(1, -1, 1);
+ GL11.glDepthFunc(GL11.GL_LEQUAL);
+ GlStateManager.enableLighting();
+ GlStateManager.enableCull();
+ }
+ }
+
+ public void addEntity(int entityId, Entity entity) {
+ if(entity instanceof EntityFishHook) {
+ hookEntities.put(entityId, (EntityFishHook) entity);
+
+ if(((EntityFishHook) entity).angler == Minecraft.getMinecraft().thePlayer) {
+ long currentTime = System.currentTimeMillis();
+ long delay = currentTime - lastCastRodMillis;
+ if(delay > 0 && delay < 500) {
+ if(delay > 300) delay = 300;
+ pingDelayList.add(0, (int)delay);
+ }
+ }
+ }
+ }
+
+ public void removeEntity(int entityId) {
+ hookEntities.remove(entityId);
+ }
+
+ @SubscribeEvent
+ public void onWorldUnload(WorldEvent.Unload event) {
+ hookEntities.clear();
+ chains.clear();
+ }
+
+ @SubscribeEvent
+ public void onPlayerInteract(PlayerInteractEvent event) {
+ if(event.action == PlayerInteractEvent.Action.RIGHT_CLICK_AIR &&
+ event.entityPlayer == Minecraft.getMinecraft().thePlayer) {
+
+ ItemStack heldItem = event.entityPlayer.getHeldItem();
+
+ if(heldItem != null && heldItem.getItem() == Items.fishing_rod) {
+ long currentTime = System.currentTimeMillis();
+ if(currentTime - lastCastRodMillis > 500) {
+ lastCastRodMillis = currentTime;
+ }
+ }
+
+ }
+ }
+
+ private int tickCounter = 0;
+ @SubscribeEvent
+ public void onTick(TickEvent.ClientTickEvent event) {
+ if(Minecraft.getMinecraft().thePlayer != null && event.phase == TickEvent.Phase.END) {
+ if(buildupSoundDelay > 0) buildupSoundDelay--;
+
+ if(NotEnoughUpdates.INSTANCE.config.fishing.incomingFishWarning) {
+ if(Minecraft.getMinecraft().thePlayer.fishEntity != null) {
+ if(!pingDelayList.isEmpty()) {
+ while(pingDelayList.size() > 5) pingDelayList.remove(pingDelayList.size()-1);
+
+ int totalMS = 0;
+ for(int delay : pingDelayList) {
+ totalMS += delay;
+ }
+
+ int averageMS = totalMS / pingDelayList.size();
+ pingDelayTicks = (int)Math.ceil(averageMS/50f);
+ }
+ }
+
+ if(hookedWarningStateTicks > 0) {
+ hookedWarningStateTicks--;
+ warningState = PlayerWarningState.FISH_HOOKED;
+ } else {
+ warningState = PlayerWarningState.NOTHING;
+ if(Minecraft.getMinecraft().thePlayer.fishEntity != null) {
+ int fishEntityId = Minecraft.getMinecraft().thePlayer.fishEntity.getEntityId();
+ for(Map.Entry<WakeChain, List<Integer>> entry : chains.entrySet()) {
+ if(entry.getKey().particleNum >= 3 && entry.getValue().contains(fishEntityId)) {
+ warningState = PlayerWarningState.FISH_INCOMING;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if(tickCounter++ >= 20) {
+ long currentTime = System.currentTimeMillis();
+ tickCounter = 0;
+
+ Set<Integer> toRemoveEnt = new HashSet<>();
+ for(Map.Entry<Integer, EntityFishHook> entry : hookEntities.entrySet()) {
+ if(entry.getValue().isDead) {
+ toRemoveEnt.add(entry.getKey());
+ }
+ }
+ hookEntities.keySet().removeAll(toRemoveEnt);
+
+ Set<WakeChain> toRemoveChain = new HashSet<>();
+ for(Map.Entry<WakeChain, List<Integer>> entry : chains.entrySet()) {
+ if(currentTime - entry.getKey().lastUpdate > 200 ||
+ entry.getValue().isEmpty() ||
+ Collections.disjoint(entry.getValue(), hookEntities.keySet())) {
+ toRemoveChain.add(entry.getKey());
+ }
+ }
+ chains.keySet().removeAll(toRemoveChain);
+ }
+ }
+ }
+
+ private double calculateAngleFromOffsets(double xOffset, double zOffset) {
+ double angleX = Math.toDegrees(Math.acos(xOffset / 0.04f));
+ double angleZ = Math.toDegrees(Math.asin(zOffset / 0.04f));
+
+ if(xOffset < 0) {
+ angleZ = 180 - angleZ;
+ }
+ if(zOffset < 0) {
+ angleX = 360 - angleX;
+ }
+
+ angleX %= 360;
+ angleZ %= 360;
+ if(angleX < 0) angleX += 360;
+ if(angleZ < 0) angleZ += 360;
+
+ double dist = angleX - angleZ;
+ if(dist < -180) dist += 360;
+ if(dist > 180) dist -= 360;
+
+ return angleZ + dist/2;
+ }
+
+ private boolean checkAngleWithinRange(double angle1, double angle2, double range) {
+ double dist = Math.abs(angle1 - angle2);
+ if(dist > 180) dist = 360 - dist;
+
+ return dist <= range;
+ }
+
+ private enum HookPossibleRet {
+ NOT_POSSIBLE,
+ EITHER,
+ ANGLE1,
+ ANGLE2
+ }
+
+ private HookPossibleRet isHookPossible(EntityFishHook hook, double particleX, double particleY, double particleZ, double angle1, double angle2) {
+ double dY = particleY - hook.posY;
+ if(Math.abs(dY) > 0.5f) {
+ return HookPossibleRet.NOT_POSSIBLE;
+ }
+
+ double dX = particleX - hook.posX;
+ double dZ = particleZ - hook.posZ;
+ double dist = Math.sqrt(dX*dX + dZ*dZ);
+
+ if(dist < 0.2) {
+ return HookPossibleRet.EITHER;
+ } else {
+ float angleAllowance = (float)Math.toDegrees(Math.atan2(0.03125f, dist))*1.5f;
+ float angleHook = (float) Math.toDegrees(Math.atan2(dX, dZ));
+ angleHook %= 360;
+ if(angleHook < 0) angleHook += 360;
+
+ if(checkAngleWithinRange(angle1, angleHook, angleAllowance)) {
+ return HookPossibleRet.ANGLE1;
+ } else if(checkAngleWithinRange(angle2, angleHook, angleAllowance)) {
+ return HookPossibleRet.ANGLE2;
+ }
+ }
+ return HookPossibleRet.NOT_POSSIBLE;
+ }
+
+ public static EnumParticleTypes type = EnumParticleTypes.BARRIER;
+
+ private static final float ZERO_PITCH = 1.0f;
+ private static final float MAX_PITCH = 0.1f;
+ private static final float MAX_DISTANCE = 5f;
+ private float calculatePitchFromDistance(float d) {
+ if(d < 0.1f) d = 0.1f;
+ if(d > MAX_DISTANCE) d = MAX_DISTANCE;
+
+ return 1/(d + (1/(ZERO_PITCH-MAX_PITCH))) * (1 - d/MAX_DISTANCE) + MAX_PITCH;
+ }
+
+ public boolean onSpawnParticle(EnumParticleTypes particleType, double x, double y, double z, double xOffset, double yOffset, double zOffset) {
+ if(!NotEnoughUpdates.INSTANCE.config.fishing.hideOtherPlayerAll &&
+ !NotEnoughUpdates.INSTANCE.config.fishing.enableCustomParticles &&
+ !NotEnoughUpdates.INSTANCE.config.fishing.incomingFishWarning) {
+ return false;
+ }
+ if(hookEntities.isEmpty()) {
+ return false;
+ }
+
+ if(particleType == EnumParticleTypes.WATER_WAKE && Math.abs(yOffset - 0.01f) < 0.001f) {
+ double angle1 = calculateAngleFromOffsets(xOffset, -zOffset);
+ double angle2 = calculateAngleFromOffsets(-xOffset, zOffset);
+
+ final List<Integer> possibleHooks1 = new ArrayList<>();
+ final List<Integer> possibleHooks2 = new ArrayList<>();
+
+ for(EntityFishHook hook : hookEntities.values()) {
+ if(hook.isDead) continue;
+ if(possibleHooks1.contains(hook.getEntityId())) continue;
+ if(possibleHooks2.contains(hook.getEntityId())) continue;
+
+ HookPossibleRet ret = isHookPossible(hook, x, y, z, angle1, angle2);
+ if(ret == HookPossibleRet.ANGLE1) {
+ possibleHooks1.add(hook.getEntityId());
+ } else if(ret == HookPossibleRet.ANGLE2) {
+ possibleHooks2.add(hook.getEntityId());
+ } else if(ret == HookPossibleRet.EITHER) {
+ possibleHooks1.add(hook.getEntityId());
+ possibleHooks2.add(hook.getEntityId());
+ }
+ }
+
+ if(!possibleHooks1.isEmpty() || !possibleHooks2.isEmpty()) {
+ long currentTime = System.currentTimeMillis();
+
+ boolean isMainPlayer = false;
+
+ boolean foundChain = false;
+ for(Map.Entry<WakeChain, List<Integer>> entry : chains.entrySet()) {
+ WakeChain chain = entry.getKey();
+
+ if(currentTime - chain.lastUpdate > 200) continue;
+
+ double updateAngle;
+ List<Integer> possibleHooks;
+ if(checkAngleWithinRange(chain.currentAngle, angle1, 16)) {
+ possibleHooks = possibleHooks1;
+ updateAngle = angle1;
+ } else if(checkAngleWithinRange(chain.currentAngle, angle2, 16)) {
+ possibleHooks = possibleHooks2;
+ updateAngle = angle2;
+ } else {
+ continue;
+ }
+
+ if(!Collections.disjoint(entry.getValue(), possibleHooks)) {
+ HashSet<Integer> newHooks = new HashSet<>();
+
+ for(int hookEntityId : possibleHooks) {
+ if(entry.getValue().contains(hookEntityId) && chain.distances.containsKey(hookEntityId)) {
+ EntityFishHook entity = hookEntities.get(hookEntityId);
+
+ if(entity != null && !entity.isDead) {
+ double oldDistance = chain.distances.get(hookEntityId);
+
+ double dX = entity.posX - x;
+ double dZ = entity.posZ - z;
+ double newDistance = Math.sqrt(dX*dX + dZ*dZ);
+
+ double delta = oldDistance - newDistance;
+
+ if(newDistance < 0.2 || (delta > -0.1 && delta < 0.3)) {
+ if(NotEnoughUpdates.INSTANCE.config.fishing.incomingFishWarning &&
+ Minecraft.getMinecraft().thePlayer.fishEntity != null &&
+ Minecraft.getMinecraft().thePlayer.fishEntity.getEntityId() == hookEntityId &&
+ chain.particleNum > 3) {
+
+ if(newDistance <= 0.2f + 0.1f*pingDelayTicks) {
+ if(NotEnoughUpdates.INSTANCE.config.fishing.incomingFishHookedSounds &&
+ hookedWarningStateTicks <= 0) {
+ Minecraft.getMinecraft().getSoundHandler().playSound(
+ PositionedSoundRecord.create(new ResourceLocation("note.pling"), 2f));
+ }
+
+ hookedWarningStateTicks = 12;
+ } else if(newDistance >= 0.4f + 0.1f*pingDelayTicks) {
+ if(NotEnoughUpdates.INSTANCE.config.fishing.incomingFishIncSounds &&
+ buildupSoundDelay <= 0) {
+ ISound sound = new PositionedSound(new ResourceLocation("note.pling")) {{
+ volume = 0.1f;
+ pitch = calculatePitchFromDistance((float)newDistance - (0.3f+0.1f*pingDelayTicks));
+ repeat = false;
+ repeatDelay = 0;
+ attenuationType = ISound.AttenuationType.NONE;
+ }};
+ Minecraft.getMinecraft().getSoundHandler().playSound(sound);
+ buildupSoundDelay = 4;
+ }
+ }
+ }
+
+ chain.distances.put(hookEntityId, newDistance);
+ newHooks.add(hookEntityId);
+ }
+ }
+
+ }
+ }
+ if(newHooks.isEmpty()) {
+ continue;
+ }
+
+ entry.getValue().retainAll(newHooks);
+ chain.distances.keySet().retainAll(newHooks);
+
+ for(int i : entry.getValue()) {
+ EntityFishHook hook = hookEntities.get(i);
+ if(hook != null && hook.angler == Minecraft.getMinecraft().thePlayer) {
+ isMainPlayer = true;
+ break;
+ }
+ }
+
+ chain.lastUpdate = currentTime;
+ chain.particleNum++;
+ chain.currentAngle = updateAngle;
+
+ foundChain = true;
+ }
+ }
+
+
+ if(!foundChain) {
+ possibleHooks1.removeAll(possibleHooks2);
+ if(!possibleHooks1.isEmpty()) {
+ for(int i : possibleHooks1) {
+ EntityFishHook hook = hookEntities.get(i);
+ if(hook != null && hook.angler == Minecraft.getMinecraft().thePlayer) {
+ isMainPlayer = true;
+ break;
+ }
+ }
+
+ WakeChain chain = new WakeChain(currentTime, angle1, x, z);
+ for(int hookEntityId : possibleHooks1) {
+ EntityFishHook entity = hookEntities.get(hookEntityId);
+
+ if(entity != null && !entity.isDead) {
+ double dX = entity.posX - x;
+ double dZ = entity.posZ - z;
+ double newDistance = Math.sqrt(dX*dX + dZ*dZ);
+ chain.distances.put(hookEntityId, newDistance);
+ }
+ }
+ chains.put(chain, possibleHooks1);
+ } else if(!possibleHooks2.isEmpty()) {
+ for(int i : possibleHooks2) {
+ EntityFishHook hook = hookEntities.get(i);
+ if(hook != null && hook.angler == Minecraft.getMinecraft().thePlayer) {
+ isMainPlayer = true;
+ break;
+ }
+ }
+
+ WakeChain chain = new WakeChain(currentTime, angle2, x, z);
+ for(int hookEntityId : possibleHooks2) {
+ EntityFishHook entity = hookEntities.get(hookEntityId);
+
+ if(entity != null && !entity.isDead) {
+ double dX = entity.posX - x;
+ double dZ = entity.posZ - z;
+ double newDistance = Math.sqrt(dX*dX + dZ*dZ);
+ chain.distances.put(hookEntityId, newDistance);
+ }
+ }
+ chains.put(chain, possibleHooks2);
+ }