From 1b172089ce502803f7644611afd618ce00dcb860 Mon Sep 17 00:00:00 2001 From: BuildTools Date: Sat, 29 May 2021 22:02:37 +0800 Subject: PRE28 --- .../notenoughupdates/MorusIntegration.java | 60 --- .../notenoughupdates/NEUEventListener.java | 18 +- .../notenoughupdates/NotEnoughUpdates.java | 63 ++- .../notenoughupdates/core/BackgroundBlur.java | 6 +- .../notenoughupdates/core/GuiElementColour.java | 4 +- .../notenoughupdates/core/GuiElementTextField.java | 68 ++- .../core/config/KeybindHelper.java | 4 +- .../notenoughupdates/dungeons/DungeonWin.java | 2 + .../notenoughupdates/gamemodes/SBGamemodes.java | 2 +- .../miscfeatures/DamageCommas.java | 5 +- .../miscfeatures/FancyPortals.java | 303 ++++++++++++ .../miscfeatures/FishingHelper.java | 549 +++++++++++++++++++++ .../miscfeatures/ItemCooldowns.java | 6 +- .../miscfeatures/ItemCustomizeManager.java | 1 + .../miscfeatures/NPCRetexturing.java | 1 - .../notenoughupdates/miscfeatures/SlotLocking.java | 295 ++++++++--- .../miscfeatures/StorageManager.java | 8 +- .../notenoughupdates/miscgui/GuiEnchantColour.java | 31 +- .../notenoughupdates/miscgui/GuiItemCustomize.java | 92 +++- .../miscgui/InventoryStorageSelector.java | 18 +- .../notenoughupdates/miscgui/StorageOverlay.java | 10 +- .../mixins/MixinEntityPlayerSP.java | 5 + .../mixins/MixinEntityRenderer.java | 47 +- .../notenoughupdates/mixins/MixinItemRenderer.java | 14 +- .../notenoughupdates/mixins/MixinItemStack.java | 25 +- .../mixins/MixinLoadingScreenRenderer.java | 22 + .../notenoughupdates/mixins/MixinMinecraft.java | 14 + .../mixins/MixinNetHandlerPlayClient.java | 27 +- .../notenoughupdates/mixins/MixinRenderFish.java | 21 +- .../notenoughupdates/mixins/MixinWorldClient.java | 25 + .../notenoughupdates/options/NEUConfig.java | 277 +++++++++-- .../moulberry/notenoughupdates/util/SBInfo.java | 13 +- .../moulberry/notenoughupdates/util/Utils.java | 22 + .../notenoughupdates/fishing_warning_exclam.png | Bin 0 -> 5807 bytes .../assets/notenoughupdates/groundplane.png | Bin 0 -> 40868 bytes .../portal_panoramas/nether/pansc-1.png | Bin 0 -> 82574 bytes .../portal_panoramas/nether/pansc-2.png | Bin 0 -> 1228306 bytes .../portal_panoramas/nether/pansc-3.png | Bin 0 -> 646267 bytes .../portal_panoramas/nether/pansc-4.png | Bin 0 -> 668239 bytes .../portal_panoramas/nether/pansc-5.png | Bin 0 -> 531635 bytes .../portal_panoramas/nether/pansc-6.png | Bin 0 -> 275559 bytes .../assets/notenoughupdates/slotlocking/bound.png | Bin 0 -> 5619 bytes .../notenoughupdates/storage_gui/storage_gui_3.png | Bin 3374 -> 7861 bytes .../storage_gui/storage_preview_3.png | Bin 7160 -> 4373 bytes src/main/resources/mixins.notenoughupdates.json | 4 +- src/main/resources/notenoughupdates_at.cfg | 5 +- 46 files changed, 1785 insertions(+), 282 deletions(-) delete mode 100644 src/main/java/io/github/moulberry/notenoughupdates/MorusIntegration.java create mode 100644 src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/FancyPortals.java create mode 100644 src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/FishingHelper.java create mode 100644 src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinLoadingScreenRenderer.java create mode 100644 src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinWorldClient.java create mode 100644 src/main/resources/assets/notenoughupdates/fishing_warning_exclam.png create mode 100644 src/main/resources/assets/notenoughupdates/groundplane.png create mode 100644 src/main/resources/assets/notenoughupdates/portal_panoramas/nether/pansc-1.png create mode 100644 src/main/resources/assets/notenoughupdates/portal_panoramas/nether/pansc-2.png create mode 100644 src/main/resources/assets/notenoughupdates/portal_panoramas/nether/pansc-3.png create mode 100644 src/main/resources/assets/notenoughupdates/portal_panoramas/nether/pansc-4.png create mode 100644 src/main/resources/assets/notenoughupdates/portal_panoramas/nether/pansc-5.png create mode 100644 src/main/resources/assets/notenoughupdates/portal_panoramas/nether/pansc-6.png create mode 100644 src/main/resources/assets/notenoughupdates/slotlocking/bound.png (limited to 'src') diff --git a/src/main/java/io/github/moulberry/notenoughupdates/MorusIntegration.java b/src/main/java/io/github/moulberry/notenoughupdates/MorusIntegration.java deleted file mode 100644 index 8ec4263a..00000000 --- a/src/main/java/io/github/moulberry/notenoughupdates/MorusIntegration.java +++ /dev/null @@ -1,60 +0,0 @@ -package io.github.moulberry.notenoughupdates; - -import io.github.moulberry.morus.MorusSubstitutor; -import net.minecraft.client.Minecraft; -import net.minecraft.item.ItemStack; - -import java.util.HashMap; -import java.util.Map; - -public class MorusIntegration { - - private static MorusIntegration INSTANCE = new MorusIntegration(); - - public static MorusIntegration getInstance() { - return INSTANCE; - } - - private HashMap itemDrops = null; - private HashMap inventoryItems = null; - - public void tick() { - if(itemDrops == null) { - itemDrops = new HashMap<>(); - for(String item : NotEnoughUpdates.INSTANCE.manager.getItemInformation().keySet()) { - itemDrops.put(item, 0); - } - } - - HashMap newInventoryItems = getInventoryItems(); - if(inventoryItems != null) { - for(String internal : newInventoryItems.keySet()) { - int newAmount = newInventoryItems.get(internal); - int oldAmount = inventoryItems.getOrDefault(internal, 0); - if(newAmount > oldAmount) { - itemDrops.put(internal, itemDrops.getOrDefault(internal, 0)+newAmount-oldAmount); - } - } - } - inventoryItems = newInventoryItems; - - for(Map.Entry entry : itemDrops.entrySet()) { - MorusSubstitutor.putSubstiution("notenoughupdates", "itemdrops."+entry.getKey().toLowerCase(), ""+entry.getValue()); - } - - } - - public HashMap getInventoryItems() { - HashMap inventoryItems = new HashMap<>(); - if(Minecraft.getMinecraft().thePlayer != null) { - for(ItemStack stack : Minecraft.getMinecraft().thePlayer.inventory.mainInventory) { - String internalname = NotEnoughUpdates.INSTANCE.manager.getInternalNameForItem(stack); - if(internalname != null) { - inventoryItems.put(internalname, inventoryItems.getOrDefault(internalname, 0)+stack.stackSize); - } - } - } - return inventoryItems; - } - -} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NEUEventListener.java b/src/main/java/io/github/moulberry/notenoughupdates/NEUEventListener.java index 081a0c1d..98300e73 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/NEUEventListener.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/NEUEventListener.java @@ -32,6 +32,8 @@ import net.minecraft.client.gui.inventory.GuiEditSign; import net.minecraft.client.gui.inventory.GuiInventory; import net.minecraft.client.network.NetworkPlayerInfo; import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.entity.Entity; +import net.minecraft.entity.item.EntityArmorStand; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.event.ClickEvent; import net.minecraft.init.Blocks; @@ -240,7 +242,6 @@ public class NEUEventListener { DungeonWin.tick(); if(longUpdate) { - CrystalOverlay.tick(); DwarvenMinesTextures.tick(); FairySouls.tick(); @@ -260,9 +261,6 @@ public class NEUEventListener { NotEnoughUpdates.INSTANCE.overlay.redrawItems(); CapeManager.onTickSlow(); - for(EntityPlayer player : Minecraft.getMinecraft().theWorld.playerEntities) { - NotEnoughUpdates.profileViewer.putNameUuid(player.getName(), player.getUniqueID().toString().replace("-", "")); - } NotEnoughUpdates.profileViewer.putNameUuid(Minecraft.getMinecraft().thePlayer.getName(), Minecraft.getMinecraft().thePlayer.getUniqueID().toString().replace("-", "")); @@ -286,9 +284,6 @@ public class NEUEventListener { if(neu.hasSkyblockScoreboard()) { SBInfo.getInstance().tick(); - if(Loader.isModLoaded("morus")) { - MorusIntegration.getInstance().tick(); - } lastSkyblockScoreboard = currentTime; if(!joinedSB) { joinedSB = true; @@ -702,7 +697,7 @@ public class NEUEventListener { * 2) When a /viewrecipe command fails (i.e. player does not have recipe unlocked, will open the custom recipe GUI) * 3) Replaces lobby join notifications when streamer mode is active */ - @SubscribeEvent(priority = EventPriority.LOW) + @SubscribeEvent(priority = EventPriority.LOW, receiveCanceled = true) public void onGuiChat(ClientChatReceivedEvent e) { if(e.type == 2) { e.message = processChatComponent(e.message); @@ -1380,9 +1375,10 @@ public class NEUEventListener { boolean customAhActive = event.gui instanceof CustomAHGui || neu.manager.auctionManager.customAH.isRenderOverAuctionView(); if(storageOverlayActive) { - event.setCanceled(true); - StorageOverlay.getInstance().keyboardInput(); - return; + if(StorageOverlay.getInstance().keyboardInput()) { + event.setCanceled(true); + return; + } } if(tradeWindowActive || customAhActive) { diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java b/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java index 8e0c1444..f9965300 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java @@ -73,9 +73,11 @@ import java.lang.management.ManagementFactory; import java.nio.charset.StandardCharsets; import java.util.*; import java.util.List; +import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; @Mod(modid = NotEnoughUpdates.MODID, version = NotEnoughUpdates.VERSION, clientSideOnly = true) public class NotEnoughUpdates { @@ -706,6 +708,7 @@ public class NotEnoughUpdates { } }); + private ScheduledExecutorService devES = Executors.newSingleThreadScheduledExecutor(); private static final String[] devFailStrings = {"No.", "I said no.", "You aren't allowed to use this.", "Are you sure you want to use this? Type 'Yes' in chat.", "Lmao you thought", "Ok please stop", "What do you want from me?", "This command almost certainly does nothing useful for you", @@ -716,7 +719,8 @@ public class NotEnoughUpdates { SimpleCommand devTestCommand = new SimpleCommand("neudevtest", new SimpleCommand.ProcessCommandRunnable() { @Override public void processCommand(ICommandSender sender, String[] args) { - if(!Minecraft.getMinecraft().thePlayer.getName().equalsIgnoreCase("Moulberry")) { + if(!Minecraft.getMinecraft().thePlayer.getName().equalsIgnoreCase("Moulberry") && + !Minecraft.getMinecraft().thePlayer.getName().equalsIgnoreCase("LucyCoconut")) { if(devFailIndex >= devFailStrings.length) { throw new Error("L") { @Override @@ -741,6 +745,14 @@ public class NotEnoughUpdates { Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED+devFailStrings[devFailIndex++])); return; } + /*if(args.length == 1) { + DupePOC.doDupe(args[0]); + return; + }*/ + if(args.length == 2 && args[0].equalsIgnoreCase("pt")) { + EnumParticleTypes t = EnumParticleTypes.valueOf(args[1]); + FishingHelper.type = t; + } if(args.length == 1 && args[0].equalsIgnoreCase("dev")) { NotEnoughUpdates.INSTANCE.config.hidden.dev = true; return; @@ -749,6 +761,51 @@ public class NotEnoughUpdates { saveConfig(); return; } + if(args.length == 1 && args[0].equalsIgnoreCase("center")) { + double x = Math.floor(Minecraft.getMinecraft().thePlayer.posX) + 0.5f; + double z = Math.floor(Minecraft.getMinecraft().thePlayer.posZ) + 0.5f; + Minecraft.getMinecraft().thePlayer.setPosition(x, Minecraft.getMinecraft().thePlayer.posY, z); + return; + } + if(args.length == 1 && args[0].equalsIgnoreCase("pansc")) { + Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.GREEN+"Taking panorama screenshot")); + + AtomicInteger perspective = new AtomicInteger(0); + FancyPortals.perspectiveId = 0; + + EntityPlayerSP p = Minecraft.getMinecraft().thePlayer; + p.prevRotationYaw = p.rotationYaw = 0; + p.prevRotationPitch = p.rotationPitch = 90; + devES.schedule(new Runnable() { + @Override + public void run() { + Minecraft.getMinecraft().addScheduledTask(() -> { + ScreenShotHelper.saveScreenshot(new File("C:/Users/James/Desktop/"), "pansc-"+perspective.get()+".png", + Minecraft.getMinecraft().displayWidth, Minecraft.getMinecraft().displayHeight, + Minecraft.getMinecraft().getFramebuffer()); + }); + if(perspective.incrementAndGet() >= 6) { + FancyPortals.perspectiveId = -1; + return; + } + devES.schedule(() -> { + FancyPortals.perspectiveId = perspective.get(); + if(FancyPortals.perspectiveId == 5) { + p.prevRotationYaw = p.rotationYaw = 0; + p.prevRotationPitch = p.rotationPitch = -90; + } else if(FancyPortals.perspectiveId >= 1 && FancyPortals.perspectiveId <= 4) { + float yaw = 90*FancyPortals.perspectiveId-180; + if(yaw > 180) yaw -= 360; + p.prevRotationYaw = p.rotationYaw = yaw; + p.prevRotationPitch = p.rotationPitch = 0; + } + devES.schedule(this, 3000L, TimeUnit.MILLISECONDS); + }, 100L, TimeUnit.MILLISECONDS); + } + }, 3000L, TimeUnit.MILLISECONDS); + + return; + } Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.GREEN+"Executing dubious code")); /*Minecraft.getMinecraft().thePlayer.rotationYaw = 0; Minecraft.getMinecraft().thePlayer.rotationPitch = 0; @@ -1070,6 +1127,7 @@ public class NotEnoughUpdates { StorageManager.getInstance().loadConfig(new File(neuDir, "storageItems.json")); FairySouls.load(new File(neuDir, "collected_fairy_souls.json"), gson); PetInfoOverlay.loadConfig(new File(neuDir, "petCache.json")); + SlotLocking.getInstance().loadConfig(new File(neuDir, "slotLocking.json")); if(config == null) { config = new NEUConfig(); @@ -1093,12 +1151,14 @@ public class NotEnoughUpdates { MinecraftForge.EVENT_BUS.register(new DwarvenMinesTextures()); MinecraftForge.EVENT_BUS.register(new DwarvenMinesWaypoints()); MinecraftForge.EVENT_BUS.register(new FuelBar()); + //MinecraftForge.EVENT_BUS.register(new FancyPortals()); MinecraftForge.EVENT_BUS.register(XPInformation.getInstance()); MinecraftForge.EVENT_BUS.register(OverlayManager.petInfoOverlay); MinecraftForge.EVENT_BUS.register(OverlayManager.timersOverlay); MinecraftForge.EVENT_BUS.register(new NullzeeSphere()); MinecraftForge.EVENT_BUS.register(InventoryStorageSelector.getInstance()); MinecraftForge.EVENT_BUS.register(SlotLocking.getInstance()); + MinecraftForge.EVENT_BUS.register(FishingHelper.getInstance()); if(Minecraft.getMinecraft().getResourceManager() instanceof IReloadableResourceManager) { ((IReloadableResourceManager)Minecraft.getMinecraft().getResourceManager()).registerReloadListener(CustomSkulls.getInstance()); @@ -1174,6 +1234,7 @@ public class NotEnoughUpdates { try { StorageManager.getInstance().saveConfig(new File(neuDir, "storageItems.json")); } catch(Exception ignored) {} try { FairySouls.save(new File(neuDir, "collected_fairy_souls.json"), gson); } catch(Exception ignored) {} try { PetInfoOverlay.saveConfig(new File(neuDir, "petCache.json")); } catch(Exception ignored) {} + try { SlotLocking.getInstance().saveConfig(new File(neuDir, "slotLocking.json")); } catch(Exception ignored) {} } /** diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/BackgroundBlur.java b/src/main/java/io/github/moulberry/notenoughupdates/core/BackgroundBlur.java index bc8ea93a..d27e6bd7 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/core/BackgroundBlur.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/core/BackgroundBlur.java @@ -157,7 +157,7 @@ public class BackgroundBlur { try { blurShaderHorz = new Shader(Minecraft.getMinecraft().getResourceManager(), "blur", - Minecraft.getMinecraft().getFramebuffer(), blurOutputHorz); + output, blurOutputHorz); blurShaderHorz.getShaderManager().getShaderUniform("BlurDir").set(1, 0); blurShaderHorz.setProjectionMatrix(createProjectionMatrix(width, height)); } catch(Exception e) { } @@ -177,11 +177,11 @@ public class BackgroundBlur { blurShaderVert.getShaderManager().getShaderUniform("Radius").set(blurFactor); GL11.glPushMatrix(); - /*GL30.glBindFramebuffer(GL30.GL_READ_FRAMEBUFFER, Minecraft.getMinecraft().getFramebuffer().framebufferObject); + GL30.glBindFramebuffer(GL30.GL_READ_FRAMEBUFFER, Minecraft.getMinecraft().getFramebuffer().framebufferObject); GL30.glBindFramebuffer(GL30.GL_DRAW_FRAMEBUFFER, output.framebufferObject); GL30.glBlitFramebuffer(0, 0, width, height, 0, 0, output.framebufferWidth, output.framebufferHeight, - GL11.GL_COLOR_BUFFER_BIT, GL11.GL_NEAREST);*/ + GL11.GL_COLOR_BUFFER_BIT, GL11.GL_NEAREST); blurShaderHorz.loadShader(0); blurShaderVert.loadShader(0); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/GuiElementColour.java b/src/main/java/io/github/moulberry/notenoughupdates/core/GuiElementColour.java index fb75ea23..3ab47531 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/core/GuiElementColour.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/core/GuiElementColour.java @@ -217,13 +217,13 @@ public class GuiElementColour extends GuiElement { if(opacitySlider) { TextRenderUtils.drawStringCenteredScaledMaxWidth(EnumChatFormatting.GRAY.toString()+Math.round(c.getAlpha()/255f*100)+"", Minecraft.getMinecraft().fontRendererObj, - x+5+64+5+15+5, y+5+64+5+5, true, 13, -1); + x+5+64+5+valueOffset+5, y+5+64+5+5, true, 13, -1); } if(chromaSpeed > 0) { TextRenderUtils.drawStringCenteredScaledMaxWidth(EnumChatFormatting.GRAY.toString()+ (int)ChromaColour.getSecondsForSpeed(chromaSpeed)+"s", Minecraft.getMinecraft().fontRendererObj, - x+5+64+5+valueOffset+15+6, y+5+64+5+5, true, 13, -1); + x+5+64+5+valueOffset+opacityOffset+6, y+5+64+5+5, true, 13, -1); } hexField.setSize(48, 10); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/GuiElementTextField.java b/src/main/java/io/github/moulberry/notenoughupdates/core/GuiElementTextField.java index 965c705d..aded91e6 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/core/GuiElementTextField.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/core/GuiElementTextField.java @@ -16,6 +16,7 @@ import java.util.regex.Pattern; public class GuiElementTextField { + public static final int SCISSOR_TEXT = 0b10000000; public static final int DISABLE_BG = 0b1000000; public static final int SCALE_TEXT = 0b100000; public static final int NUM_ONLY = 0b10000; @@ -73,6 +74,18 @@ public class GuiElementTextField { return textField.getText(); } + public String getTextDisplay() { + String textNoColour = getText(); + while(true) { + Matcher matcher = PATTERN_CONTROL_CODE.matcher(textNoColour); + if(!matcher.find()) break; + String code = matcher.group(1); + textNoColour = matcher.replaceFirst("\u00B6"+code); + } + + return textNoColour; + } + public void setPrependText(String text) { this.prependText = text; } @@ -130,13 +143,7 @@ public class GuiElementTextField { return (options & SCALE_TEXT) != 0; } - private float getStringWidth(String str) { - if(isScaling()) { - return Minecraft.getMinecraft().fontRendererObj.getStringWidth(str)*getScaleFactor(str); - } else { - return Minecraft.getMinecraft().fontRendererObj.getStringWidth(str); - } - } + private static final Pattern PATTERN_CONTROL_CODE = Pattern.compile("(?i)\\u00A7([^\\u00B6]|$)(?!\\u00B6)"); public int getCursorPos(int mouseX, int mouseY) { int xComp = mouseX - x; @@ -148,12 +155,11 @@ public class GuiElementTextField { int lineNum = Math.round(((yComp - (searchBarYSize-8)/2))/extraSize); - Pattern patternControlCode = Pattern.compile("(?i)\\u00A7([^\\u00B6]|$)(?!\\u00B6)"); String text = renderText; String textNoColour = renderText; if((options & COLOUR) != 0) { while(true) { - Matcher matcher = patternControlCode.matcher(text); + Matcher matcher = PATTERN_CONTROL_CODE.matcher(text); if(!matcher.find() || matcher.groupCount() < 1) break; String code = matcher.group(1); if(code.isEmpty()) { @@ -164,7 +170,7 @@ public class GuiElementTextField { } } while(true) { - Matcher matcher = patternControlCode.matcher(textNoColour); + Matcher matcher = PATTERN_CONTROL_CODE.matcher(textNoColour); if(!matcher.find() || matcher.groupCount() < 1) break; String code = matcher.group(1); textNoColour = matcher.replaceFirst("\u00B6"+code); @@ -351,6 +357,10 @@ public class GuiElementTextField { if((options & FORCE_CAPS) != 0) typedChar = Character.toUpperCase(typedChar); if((options & NO_SPACE) != 0 && typedChar == ' ') return; + if(typedChar == '\u00B6') { + typedChar = '\u00A7'; + } + textField.setFocused(true); textField.textboxKeyTyped(typedChar, keyCode); @@ -368,6 +378,19 @@ public class GuiElementTextField { textField.setCursorPosition(pos+1); } } + } else if(typedChar == '*') { + int pos = textField.getCursorPosition()-2; + if(pos >= 0 && pos < textField.getText().length()) { + if(textField.getText().charAt(pos) == '*') { + String before = textField.getText().substring(0, pos); + String after = ""; + if(pos+2 < textField.getText().length()) { + after = textField.getText().substring(pos+2); + } + textField.setText(before + "\u272A" + after); + textField.setCursorPosition(pos+1); + } + } } } @@ -415,13 +438,11 @@ public class GuiElementTextField { } //bar text - Pattern patternControlCode = Pattern.compile("(?i)\\u00A7([^\\u00B6\n]|$)(?!\\u00B6)"); - String text = renderText; String textNoColor = renderText; if((options & COLOUR) != 0) { while(true) { - Matcher matcher = patternControlCode.matcher(text); + Matcher matcher = PATTERN_CONTROL_CODE.matcher(text); if(!matcher.find() || matcher.groupCount() < 1) break; String code = matcher.group(1); if(code.isEmpty()) { @@ -432,7 +453,7 @@ public class GuiElementTextField { } } while(true) { - Matcher matcher = patternControlCode.matcher(textNoColor); + Matcher matcher = PATTERN_CONTROL_CODE.matcher(textNoColor); if(!matcher.find() || matcher.groupCount() < 1) break; String code = matcher.group(1); textNoColor = matcher.replaceFirst("\u00B6"+code); @@ -450,12 +471,21 @@ public class GuiElementTextField { float newLen = Minecraft.getMinecraft().fontRendererObj.getStringWidth(texts[yOffI])*scale; xStartOffset = (int)((searchBarXSize-newLen)/2f); - TextRenderUtils.drawStringCenteredScaledMaxWidth(texts[yOffI], Minecraft.getMinecraft().fontRendererObj, x+searchBarXSize/2f, + TextRenderUtils.drawStringCenteredScaledMaxWidth(Utils.chromaStringByColourCode(texts[yOffI]), Minecraft.getMinecraft().fontRendererObj, x+searchBarXSize/2f, y+searchBarYSize/2f+yOff, false, searchBarXSize-2, customTextColour); } else { - Minecraft.getMinecraft().fontRendererObj.drawString(StringUtils.trimToWidth(texts[yOffI], searchBarXSize-10), x + 5, - y+(searchBarYSize-8)/2+yOff, customTextColour); + if((options & SCISSOR_TEXT) != 0) { + GlScissorStack.push(x+5, 0, x+searchBarXSize, scaledresolution.getScaledHeight(), scaledresolution); + Minecraft.getMinecraft().fontRendererObj.drawString(Utils.chromaStringByColourCode(texts[yOffI]), x + 5, + y+(searchBarYSize-8)/2+yOff, customTextColour); + GlScissorStack.pop(scaledresolution); + } else { + String toRender = Minecraft.getMinecraft().fontRendererObj.trimStringToWidth(Utils.chromaStringByColourCode(texts[yOffI]), searchBarXSize-10); + Minecraft.getMinecraft().fontRendererObj.drawString(toRender, x + 5, + y+(searchBarYSize-8)/2+yOff, customTextColour); + } + } } @@ -482,7 +512,6 @@ public class GuiElementTextField { String selectedText = textField.getSelectedText(); if(!selectedText.isEmpty()) { - System.out.println("Start"); int leftIndex = Math.min(textField.getCursorPosition()+prependText.length(), textField.getSelectionEnd()+prependText.length()); int rightIndex = Math.max(textField.getCursorPosition()+prependText.length(), textField.getSelectionEnd()+prependText.length()); @@ -526,9 +555,6 @@ public class GuiElementTextField { continue; } - //String c2 = bold ? EnumChatFormatting.BOLD.toString() : "" + c; - - System.out.println("Adding len for char:"+c+":"+Integer.toHexString(c)); int len = Minecraft.getMinecraft().fontRendererObj.getStringWidth(String.valueOf(c)); if(bold) len++; if(i >= leftIndex && i < rightIndex) { diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/config/KeybindHelper.java b/src/main/java/io/github/moulberry/notenoughupdates/core/config/KeybindHelper.java index 306bc95e..7ebacac1 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/core/config/KeybindHelper.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/core/config/KeybindHelper.java @@ -13,7 +13,9 @@ public class KeybindHelper { return "Button "+(keyCode+101); } else { String keyName = Keyboard.getKeyName(keyCode); - if(keyName.equalsIgnoreCase("LMENU")) { + if(keyName == null) { + keyName = "???"; + } else if(keyName.equalsIgnoreCase("LMENU")) { keyName = "LALT"; } else if(keyName.equalsIgnoreCase("RMENU")) { keyName = "RALT"; diff --git a/src/main/java/io/github/moulberry/notenoughupdates/dungeons/DungeonWin.java b/src/main/java/io/github/moulberry/notenoughupdates/dungeons/DungeonWin.java index 651f75b7..ab4d1b7b 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/dungeons/DungeonWin.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/dungeons/DungeonWin.java @@ -175,6 +175,8 @@ public class DungeonWin { } if(currentTime - lastDungeonFinish > 100 && currentTime - lastDungeonFinish < 10000) { if(hideChat) { + if(text.size() > 50) text.clear(); + e.setCanceled(true); if(unformatted.contains("\u25AC")) { hideChat = false; diff --git a/src/main/java/io/github/moulberry/notenoughupdates/gamemodes/SBGamemodes.java b/src/main/java/io/github/moulberry/notenoughupdates/gamemodes/SBGamemodes.java index 5e1634e9..18324154 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/gamemodes/SBGamemodes.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/gamemodes/SBGamemodes.java @@ -81,7 +81,7 @@ public class SBGamemodes { } public enum IronmanMode { - NORMAL("Normal", "Normal"), + NORMAL("Normal"), IRONMAN(EnumChatFormatting.WHITE+"Ironman\n" + "You are NOT allowed to trade or use the auction house.", "You ", "Auction House", "Auctions Browser", "Auction View"), 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 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 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 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 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 hookEntities = new HashMap<>(); + public final HashMap> chains = new HashMap<>(); + + private long lastCastRodMillis = 0; + private int pingDelayTicks = 0; + private final List 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> 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 toRemoveEnt = new HashSet<>(); + for(Map.Entry entry : hookEntities.entrySet()) { + if(entry.getValue().isDead) { + toRemoveEnt.add(entry.getKey()); + } + } + hookEntities.keySet().removeAll(toRemoveEnt); + + Set toRemoveChain = new HashSet<>(); + for(Map.Entry> 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 possibleHooks1 = new ArrayList<>(); + final List 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> entry : chains.entrySet()) { + WakeChain chain = entry.getKey(); + + if(currentTime - chain.lastUpdate > 200) continue; + + double updateAngle; + List 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 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 == Min