summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/NEUEventListener.java64
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java5
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/core/GuiElementBoolean.java2
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/core/config/Config.java4
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/core/config/Position.java114
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorButton.java15
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorButton.java66
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorDropdown.java16
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiPositionEditor.java109
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/core/config/struct/ConfigProcessor.java4
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/cosmetics/CapeManager.java4
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/cosmetics/NEUCape.java14
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/dungeons/DungeonMap.java7
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/dungeons/GuiDungeonMapEditor.java111
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CommissionOverlay.java164
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CrystalOverlay.java327
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CustomItemEffects.java29
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/DwarvenMinesTextures.java90
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/FairySouls.java2
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/ItemCooldowns.java135
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/MiningStuff.java2
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscgui/AccessoryBagOverlay.java36
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinEffectRenderer.java39
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinItemStack.java1
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinNetHandlerPlayClient.java2
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinPlayerControllerMP.java2
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinRenderItem.java55
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/options/NEUConfig.java167
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/options/NEUConfigEditor.java2
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/profileviewer/ProfileViewer.java5
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/textoverlays/TextOverlay.java90
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/textoverlays/TextOverlayStyle.java10
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/util/ReverseWorldRenderer.java552
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/util/Utils.java11
-rw-r--r--src/main/resources/assets/notenoughupdates/capes/furf.pngbin10380 -> 15699 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/capes/furf_preview.pngbin0 -> 11892 bytes
36 files changed, 2067 insertions, 189 deletions
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NEUEventListener.java b/src/main/java/io/github/moulberry/notenoughupdates/NEUEventListener.java
index e0a487b6..59d71520 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/NEUEventListener.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/NEUEventListener.java
@@ -3,20 +3,20 @@ package io.github.moulberry.notenoughupdates;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
-import io.github.moulberry.notenoughupdates.auction.APIManager;
import io.github.moulberry.notenoughupdates.auction.CustomAHGui;
+import io.github.moulberry.notenoughupdates.core.config.Position;
import io.github.moulberry.notenoughupdates.cosmetics.CapeManager;
import io.github.moulberry.notenoughupdates.dungeons.DungeonBlocks;
import io.github.moulberry.notenoughupdates.dungeons.DungeonWin;
import io.github.moulberry.notenoughupdates.gamemodes.SBGamemodes;
-import io.github.moulberry.notenoughupdates.miscfeatures.BetterContainers;
-import io.github.moulberry.notenoughupdates.miscfeatures.FairySouls;
-import io.github.moulberry.notenoughupdates.miscfeatures.StreamerMode;
+import io.github.moulberry.notenoughupdates.miscfeatures.*;
import io.github.moulberry.notenoughupdates.miscgui.*;
import io.github.moulberry.notenoughupdates.profileviewer.GuiProfileViewer;
+import io.github.moulberry.notenoughupdates.textoverlays.TextOverlay;
+import io.github.moulberry.notenoughupdates.textoverlays.TextOverlayStyle;
+import io.github.moulberry.notenoughupdates.util.Constants;
import io.github.moulberry.notenoughupdates.util.RequestFocusListener;
import io.github.moulberry.notenoughupdates.util.SBInfo;
-import io.github.moulberry.notenoughupdates.util.Constants;
import io.github.moulberry.notenoughupdates.util.Utils;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.FontRenderer;
@@ -58,8 +58,8 @@ import java.awt.datatransfer.StringSelection;
import java.io.File;
import java.io.IOException;
import java.text.NumberFormat;
-import java.util.*;
import java.util.List;
+import java.util.*;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
@@ -71,7 +71,7 @@ import static io.github.moulberry.notenoughupdates.util.GuiTextures.dungeon_ches
public class NEUEventListener {
- private NotEnoughUpdates neu;
+ private final NotEnoughUpdates neu;
private boolean hoverInv = false;
private boolean focusInv = false;
@@ -135,16 +135,26 @@ public class NEUEventListener {
private long notificationDisplayMillis = 0;
private List<String> notificationLines = null;
- private static Pattern BAD_ITEM_REGEX = Pattern.compile("x[0-9]{1,2}$");
+ private static final Pattern BAD_ITEM_REGEX = Pattern.compile("x[0-9]{1,2}$");
+
+ public static Class<? extends TextOverlay> dontRenderOverlay = null;
+ private final List<TextOverlay> textOverlays = new ArrayList<>();
+ {
+ textOverlays.add(new CommissionOverlay(NotEnoughUpdates.INSTANCE.config.mining.overlayPosition, () -> {
+ int style = NotEnoughUpdates.INSTANCE.config.mining.overlayStyle;
+ if(style >= 0 && style < TextOverlayStyle.values().length) {
+ return TextOverlayStyle.values()[style];
+ }
+ return TextOverlayStyle.BACKGROUND;
+ }));
+ }
/**
* 1)Will send the cached message from #sendChatMessage when at least 200ms has passed since the last message.
* This is used in order to prevent the mod spamming messages.
* 2)Adds unique items to the collection log
*/
- private HashMap<String, Long> newItemAddMap = new HashMap<>();
private long lastLongUpdate = 0;
- private long lastVeryLongUpdate = 0;
private long lastSkyblockScoreboard = 0;
@SubscribeEvent
public void onTick(TickEvent.ClientTickEvent event) {
@@ -163,7 +173,12 @@ public class NEUEventListener {
}
DungeonWin.tick();
if(longUpdate) {
+ CrystalOverlay.tick();
+ DwarvenMinesTextures.tick();
FairySouls.tick();
+ for(TextOverlay overlay : textOverlays) {
+ overlay.tick();
+ }
if(TradeWindow.hypixelTradeWindowActive()) {
for(int i=0; i<16; i++) {
int x = i % 4;
@@ -270,8 +285,8 @@ public class NEUEventListener {
neu.manager.auctionManager.markNeedsUpdate();
}
}
- if(longUpdate && neu.hasSkyblockScoreboard()) {
- /*if(neu.manager.getCurrentProfile() == null || neu.manager.getCurrentProfile().length() == 0) {
+ /*if(longUpdate && neu.hasSkyblockScoreboard()) {
+ if(neu.manager.getCurrentProfile() == null || neu.manager.getCurrentProfile().length() == 0) {
ProfileViewer.Profile profile = NotEnoughUpdates.profileViewer.getProfile(Minecraft.getMinecraft().thePlayer.getUniqueID().toString().replace("-", ""),
callback->{});
if(profile != null) {
@@ -324,11 +339,11 @@ public class NEUEventListener {
}
}
newItemAddMap.keySet().retainAll(newItem);
- }*/
- }
+ }
+ }*/
}
- private void processUniqueStack(ItemStack stack, HashSet<String> newItem) {
+ /*private void processUniqueStack(ItemStack stack, HashSet<String> newItem) {
if(stack != null && stack.hasTagCompound()) {
String internalname = neu.manager.getInternalNameForItem(stack);
if(internalname != null) {
@@ -344,13 +359,13 @@ public class NEUEventListener {
} else {
newItemAddMap.put(internalname, System.currentTimeMillis());
}
- }*/
+ }
}
}
- }
+ }*/
@SubscribeEvent(priority= EventPriority.HIGHEST)
- public void onRenderEntitySpecials(RenderLivingEvent.Specials.Pre event) {
+ public void onRenderEntitySpecials(RenderLivingEvent.Specials.Pre<EntityPlayer> event) {
if(Minecraft.getMinecraft().currentScreen instanceof GuiProfileViewer) {
if(((GuiProfileViewer)Minecraft.getMinecraft().currentScreen).getEntityPlayer() == event.entity) {
event.setCanceled(true);
@@ -371,6 +386,13 @@ public class NEUEventListener {
long timeRemaining = 15000 - (System.currentTimeMillis() - notificationDisplayMillis);
if(event.type == RenderGameOverlayEvent.ElementType.ALL) {
DungeonWin.render(event.partialTicks);
+ for(TextOverlay overlay : textOverlays) {
+ if(dontRenderOverlay != null && dontRenderOverlay.isAssignableFrom(overlay.getClass())) {
+ continue;
+ }
+ overlay.render();
+ }
+ dontRenderOverlay = null;
}
if(event.type == RenderGameOverlayEvent.ElementType.ALL &&
timeRemaining > 0 && notificationLines != null && notificationLines.size() > 0) {
@@ -393,7 +415,7 @@ public class NEUEventListener {
Gui.drawRect(midX-width/2+2, sr.getScaledHeight()*3/4-height/2+2,
midX+width/2-2, sr.getScaledHeight()*3/4+height/2-2, 0xFFC8C8C8);
- Minecraft.getMinecraft().fontRendererObj.drawString((timeRemaining/1000)+"s", midX-width/2+3,
+ Minecraft.getMinecraft().fontRendererObj.drawString((timeRemaining/1000)+"s", midX-width/2f+3,
topY+3, 0xFF000000, false);
Utils.drawStringCentered(notificationLines.get(0), Minecraft.getMinecraft().fontRendererObj,
@@ -542,7 +564,6 @@ public class NEUEventListener {
}
}
}, 200, TimeUnit.MILLISECONDS);
- return;
}
}
}
@@ -653,7 +674,6 @@ public class NEUEventListener {
focusInv = true;
}
} catch(NullPointerException npe) {
- npe.printStackTrace();
focusInv = !hoverPane;
}
}
@@ -1609,7 +1629,7 @@ public class NEUEventListener {
}
}
}*/
- if(!Keyboard.isKeyDown(Keyboard.KEY_LCONTROL)/* || /*!neu.config.hidden.dev*/) return;
+ if(!Keyboard.isKeyDown(Keyboard.KEY_LCONTROL) || !neu.config.hidden.dev) return;
if(event.toolTip.size()>0&&event.toolTip.get(event.toolTip.size()-1).startsWith(EnumChatFormatting.DARK_GRAY + "NBT: ")) {
event.toolTip.remove(event.toolTip.size()-1);
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java b/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java
index 6b787964..ad42fcfd 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java
@@ -99,7 +99,7 @@ public class NotEnoughUpdates {
//Stolen from Biscut and used for detecting whether in skyblock
private static final Set<String> SKYBLOCK_IN_ALL_LANGUAGES = Sets.newHashSet("SKYBLOCK","\u7A7A\u5C9B\u751F\u5B58", "\u7A7A\u5CF6\u751F\u5B58");
- private GuiScreen openGui = null;
+ public GuiScreen openGui = null;
SimpleCommand collectionLogCommand = new SimpleCommand("neucl", new SimpleCommand.ProcessCommandRunnable() {
public void processCommand(ICommandSender sender, String[] args) {
@@ -903,6 +903,9 @@ public class NotEnoughUpdates {
MinecraftForge.EVENT_BUS.register(new SunTzu());
MinecraftForge.EVENT_BUS.register(new MiningStuff());
MinecraftForge.EVENT_BUS.register(new FairySouls());
+ MinecraftForge.EVENT_BUS.register(new CrystalOverlay());
+ MinecraftForge.EVENT_BUS.register(new ItemCooldowns());
+ MinecraftForge.EVENT_BUS.register(new DwarvenMinesTextures());
ClientCommandHandler.instance.registerCommand(collectionLogCommand);
ClientCommandHandler.instance.registerCommand(cosmeticsCommand);
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/GuiElementBoolean.java b/src/main/java/io/github/moulberry/notenoughupdates/core/GuiElementBoolean.java
index 85f88a9f..bfd95612 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/core/GuiElementBoolean.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/core/GuiElementBoolean.java
@@ -103,7 +103,7 @@ public class GuiElementBoolean extends GuiElement {
if(Mouse.getEventButton() == 0) {
if(Mouse.getEventButtonState()) {
previewValue = !value;
- } else {
+ } else if(previewValue == !value) {
value = !value;
toggleCallback.accept(value);
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/config/Config.java b/src/main/java/io/github/moulberry/notenoughupdates/core/config/Config.java
index 572c9af6..8be828bd 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/core/config/Config.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/core/config/Config.java
@@ -1,4 +1,8 @@
package io.github.moulberry.notenoughupdates.core.config;
public class Config {
+
+ public void executeRunnable(int runnableId) {
+ }
+
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/config/Position.java b/src/main/java/io/github/moulberry/notenoughupdates/core/config/Position.java
new file mode 100644
index 00000000..b30aa680
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/core/config/Position.java
@@ -0,0 +1,114 @@
+package io.github.moulberry.notenoughupdates.core.config;
+
+import com.google.gson.annotations.Expose;
+import net.minecraft.client.gui.ScaledResolution;
+
+public class Position {
+
+ @Expose
+ private int x;
+ @Expose
+ private int y;
+
+ public Position(int x, int y) {
+ this.x = x;
+ this.y = y;
+ }
+
+ public Position clone() {
+ return new Position(x, y);
+ }
+
+ public int getRawX() {
+ return x;
+ }
+
+ public int getRawY() {
+ return y;
+ }
+
+ public int getAbsX(ScaledResolution scaledResolution) {
+ if(x < 0) {
+ return scaledResolution.getScaledWidth() + x;
+ } else {
+ return x;
+ }
+ }
+
+ public int getAbsY(ScaledResolution scaledResolution) {
+ if(y < 0) {
+ return scaledResolution.getScaledHeight() + y;
+ } else {
+ return y;
+ }
+ }
+
+ public int moveX(int deltaX, int objWidth, ScaledResolution scaledResolution) {
+ int screenWidth = scaledResolution.getScaledWidth();
+ boolean wasPositiveX = this.x >= 0;
+ this.x += deltaX;
+
+ if(wasPositiveX) {
+ if(this.x < 2) {
+ deltaX += 2-this.x;
+ this.x = 2;
+ }
+ if(this.x > screenWidth-2) {
+ deltaX += screenWidth-2-this.x;
+ this.x = screenWidth-2;
+ }
+ } else {
+ if(this.x+objWidth > -2) {
+ deltaX += -2-objWidth-this.x;
+ this.x = -2-objWidth;
+ }
+ if(this.x+screenWidth < 2) {
+ deltaX += 2-screenWidth-this.x;
+ this.x = 2-screenWidth;
+ }
+ }
+
+ if(this.x >= 0 && this.x+objWidth/2 > screenWidth/2) {
+ this.x -= screenWidth;
+ }
+ if(this.x < 0 && this.x+objWidth/2 <= -screenWidth/2) {
+ this.x += screenWidth;
+ }
+ return deltaX;
+ }
+
+ public int moveY(int deltaY, int objHeight, ScaledResolution scaledResolution) {
+ int screenHeight = scaledResolution.getScaledHeight();
+ boolean wasPositiveY = this.y >= 0;
+ this.y += deltaY;
+
+ if(wasPositiveY) {
+ if(this.y < 2) {
+ deltaY += 2-this.y;
+ this.y = 2;
+ }
+ if(this.y > screenHeight-2) {
+ deltaY += screenHeight-2-this.y;
+ this.y = screenHeight-2;
+ }
+ } else {
+ if(this.y+objHeight > -2) {
+ deltaY += -2-objHeight-this.y;
+ this.y = -2-objHeight;
+ }
+ if(this.y+screenHeight < 2) {
+ deltaY += 2-screenHeight-this.y;
+ this.y = 2-screenHeight;
+ }
+ }
+
+ if(this.y >= 0 && this.y-objHeight/2 > screenHeight/2) {
+ this.y -= screenHeight;
+ }
+ if(this.y < 0 && this.y-objHeight/2 <= -screenHeight/2) {
+ this.y += screenHeight;
+ }
+ return deltaY;
+ }
+
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorButton.java b/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorButton.java
new file mode 100644
index 00000000..5fe7fcb4
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/core/config/annotations/ConfigEditorButton.java
@@ -0,0 +1,15 @@
+package io.github.moulberry.notenoughupdates.core.config.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.FIELD)
+public @interface ConfigEditorButton {
+
+ int runnableId();
+ String buttonText() default "";
+
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorButton.java b/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorButton.java
new file mode 100644
index 00000000..03a01ef2
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorButton.java
@@ -0,0 +1,66 @@
+package io.github.moulberry.notenoughupdates.core.config.gui;
+
+import io.github.moulberry.notenoughupdates.core.ChromaColour;
+import io.github.moulberry.notenoughupdates.core.config.Config;
+import io.github.moulberry.notenoughupdates.core.config.struct.ConfigProcessor;
+import io.github.moulberry.notenoughupdates.core.util.render.RenderUtils;
+import io.github.moulberry.notenoughupdates.core.util.render.TextRenderUtils;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.renderer.GlStateManager;
+import net.minecraftforge.client.ClientCommandHandler;
+import org.lwjgl.input.Mouse;
+
+import static io.github.moulberry.notenoughupdates.util.GuiTextures.button_tex;
+import static io.github.moulberry.notenoughupdates.util.GuiTextures.button_white;
+
+public class GuiOptionEditorButton extends GuiOptionEditor {
+
+ private int runnableId;
+ private String buttonText;
+ private Config config;
+
+ public GuiOptionEditorButton(ConfigProcessor.ProcessedOption option, int runnableId, String buttonText, Config config) {
+ super(option);
+ this.runnableId = runnableId;
+ this.config = config;
+
+ this.buttonText = buttonText;
+ if(this.buttonText != null && this.buttonText.isEmpty()) this.buttonText = null;
+ }
+
+ @Override
+ public void render(int x, int y, int width) {
+ super.render(x, y, width);
+
+ int height = getHeight();
+
+ GlStateManager.color(1, 1, 1, 1);
+ Minecraft.getMinecraft().getTextureManager().bindTexture(button_tex);
+ RenderUtils.drawTexturedRect(x+width/6-24, y+height-7-14, 48, 16);
+
+ if(buttonText != null) {
+ TextRenderUtils.drawStringCenteredScaledMaxWidth(buttonText, Minecraft.getMinecraft().fontRendererObj,
+ x+width/6, y+height-7-6,
+ false, 44, 0xFF303030);
+ }
+ }
+
+ @Override
+ public boolean mouseInput(int x, int y, int width, int mouseX, int mouseY) {
+ if(Mouse.getEventButtonState()) {
+ int height = getHeight();
+ if(mouseX > x+width/6-24 && mouseX < x+width/6+24 &&
+ mouseY > y+height-7-14 && mouseY < y+height-7+2) {
+ config.executeRunnable(runnableId);
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ @Override
+ public boolean keyboardInput() {
+ return false;
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorDropdown.java b/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorDropdown.java
index 20779e01..a3e36919 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorDropdown.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiOptionEditorDropdown.java
@@ -41,11 +41,11 @@ public class GuiOptionEditorDropdown extends GuiOptionEditor {
selectedString = values[selected];
}
- RenderUtils.drawFloatingRectWithAlpha(left, top, dropdownWidth, 14, 0xff, false);
- TextRenderUtils.drawStringScaled("\u25BC", fr, left+dropdownWidth-10, y+height-7-15, false, 0xff404040, 2);
+ RenderUtils.drawFloatingRectDark(left, top, dropdownWidth, 14, false);
+ TextRenderUtils.drawStringScaled("\u25BC", fr, left+dropdownWidth-10, y+height-7-15, false, 0xffa0a0a0, 2);
TextRenderUtils.drawStringScaledMaxWidth(selectedString, fr, left+3, top+3, false,
- dropdownWidth-16, 0xff404040);
+ dropdownWidth-16, 0xffa0a0a0);
//fr.drawString(selectedString, left+3, top+3, 0xff404040);
}
}
@@ -67,8 +67,8 @@ public class GuiOptionEditorDropdown extends GuiOptionEditor {
int dropdownHeight = 13 + 12*values.length;
- int main = 0xffc0c0c0;
- int blue = 0xff3365bd;
+ int main = 0xff202026;
+ int blue = 0xff2355ad;
Gui.drawRect(left, top, left+1, top+dropdownHeight, blue); //Left
Gui.drawRect(left+1, top, left+dropdownWidth, top+1, blue); //Top
Gui.drawRect(left+dropdownWidth-1, top+1, left+dropdownWidth, top+dropdownHeight, blue); //Right
@@ -82,15 +82,15 @@ public class GuiOptionEditorDropdown extends GuiOptionEditor {
if(option.isEmpty()) {
option = "<NONE>";
}
- TextRenderUtils.drawStringScaledMaxWidth(option, fr, left+3, top+3+dropdownY, false, dropdownWidth-6, 0xff404040);
+ TextRenderUtils.drawStringScaledMaxWidth(option, fr, left+3, top+3+dropdownY, false, dropdownWidth-6, 0xffa0a0a0);
dropdownY += 12;
}
- TextRenderUtils.drawStringScaled("\u25B2", fr, left+dropdownWidth-10, y+height-7-15, false, 0xff404040, 2);
+ TextRenderUtils.drawStringScaled("\u25B2", fr, left+dropdownWidth-10, y+height-7-15, false, 0xffa0a0a0, 2);
TextRenderUtils.drawStringScaledMaxWidth(selectedString, fr, left+3, top+3, false,
- dropdownWidth-16, 0xff404040);
+ dropdownWidth-16, 0xffa0a0a0);
}
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiPositionEditor.java b/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiPositionEditor.java
new file mode 100644
index 00000000..117a97bd
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/core/config/gui/GuiPositionEditor.java
@@ -0,0 +1,109 @@
+package io.github.moulberry.notenoughupdates.core.config.gui;
+
+import io.github.moulberry.notenoughupdates.core.config.Position;
+import io.github.moulberry.notenoughupdates.core.util.render.RenderUtils;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.Gui;
+import net.minecraft.client.gui.GuiScreen;
+import net.minecraft.client.gui.ScaledResolution;
+
+import java.io.IOException;
+
+public class GuiPositionEditor extends GuiScreen {
+
+ private Position position;
+ private Position originalPosition;
+ private int elementWidth;
+ private int elementHeight;
+ private Runnable renderCallback;
+ private Runnable positionChangedCallback;
+ private Runnable closedCallback;
+ private boolean clicked = false;
+ private int grabbedX = 0;
+ private int grabbedY = 0;
+
+ private int oldMouseX = 0;
+ private int oldMouseY = 0;
+
+ public GuiPositionEditor(Position position, int elementWidth, int elementHeight,
+ Runnable renderCallback,
+ Runnable positionChangedCallback,
+ Runnable closedCallback) {
+ this.position = position;
+ this.originalPosition = position.clone();
+ this.elementWidth = elementWidth;
+ this.elementHeight = elementHeight;
+ this.renderCallback = renderCallback;
+ this.positionChangedCallback = positionChangedCallback;
+ this.closedCallback = closedCallback;
+ }
+
+ @Override
+ public void onGuiClosed() {
+ super.onGuiClosed();
+ closedCallback.run();
+ }
+
+ @Override
+ public void drawScreen(int mouseX, int mouseY, float partialTicks) {
+ super.drawScreen(mouseX, mouseY, partialTicks);
+ ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft());
+
+ this.width = scaledResolution.getScaledWidth();
+ this.height = scaledResolution.getScaledHeight();
+
+ drawDefaultBackground();
+
+ if(clicked) {
+ grabbedX += position.moveX(mouseX - grabbedX, elementWidth, scaledResolution);
+ grabbedY += position.moveY(mouseY - grabbedY, elementHeight, scaledResolution);
+ }
+
+ renderCallback.run();
+
+ int x = position.getAbsX(scaledResolution);
+ int y = position.getAbsY(scaledResolution);
+
+ Gui.drawRect(x, y, x+elementWidth, y+elementHeight, 0x80404040);
+ }
+
+ @Override
+ protected void mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException {
+ super.mouseClicked(mouseX, mouseY, mouseButton);
+
+ if(mouseButton == 0) {
+ ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft());
+
+ int x = position.getAbsX(scaledResolution);
+ int y = position.getAbsY(scaledResolution);
+
+ if(mouseX >= x && mouseY >= y &&
+ mouseX <= x+elementWidth && mouseY <= y+elementHeight) {
+ clicked = true;
+ grabbedX = mouseX;
+ grabbedY = mouseY;
+ }
+ }
+ }
+
+ @Override
+ protected void mouseReleased(int mouseX, int mouseY, int state) {
+ super.mouseReleased(mouseX, mouseY, state);
+ clicked = false;
+ }
+
+ @Override
+ protected void mouseClickMove(int mouseX, int mouseY, int clickedMouseButton, long timeSinceLastClick) {
+ super.mouseClickMove(mouseX, mouseY, clickedMouseButton, timeSinceLastClick);
+
+ ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft());
+ if(clicked) {
+ oldMouseX = mouseX;
+ oldMouseY = mouseY;
+
+ grabbedX += position.moveX(mouseX - grabbedX, elementWidth, scaledResolution);
+ grabbedY += position.moveY(mouseY - grabbedY, elementHeight, scaledResolution);
+ positionChangedCallback.run();
+ }
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/core/config/struct/ConfigProcessor.java b/src/main/java/io/github/moulberry/notenoughupdates/core/config/struct/ConfigProcessor.java
index f91b8410..513e32bb 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/core/config/struct/ConfigProcessor.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/core/config/struct/ConfigProcessor.java
@@ -101,6 +101,10 @@ public class ConfigProcessor {
GuiOptionEditor editor = null;
Class<?> optionType = optionField.getType();
+ if(optionField.isAnnotationPresent(ConfigEditorButton.class)) {
+ ConfigEditorButton configEditorAnnotation = optionField.getAnnotation(ConfigEditorButton.class);
+ editor = new GuiOptionEditorButton(option, configEditorAnnotation.runnableId(), configEditorAnnotation.buttonText(), config);
+ }
if(optionType.isAssignableFrom(boolean.class) &&
optionField.isAnnotationPresent(ConfigEditorBoolean.class)) {
editor = new GuiOptionEditorBoolean(option);
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/CapeManager.java b/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/CapeManager.java
index 777a91cc..da93b059 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/CapeManager.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/CapeManager.java
@@ -44,8 +44,8 @@ public class CapeManager {
private HashSet<String> availableCapes = new HashSet<>();
private String[] capes = new String[]{"patreon1", "patreon2", "fade", "contrib", "nullzee",
- "gravy", "space", "mcworld", "lava", "packshq", "mbstaff", "thebakery", "negative", "void", "ironmoon", "krusty" };
- public Boolean[] specialCapes = new Boolean[]{ true, true, false, true, true, true, false, false, false, true, true, true, false, false, true, false };
+ "gravy", "space", "mcworld", "lava", "packshq", "mbstaff", "thebakery", "negative", "void", "ironmoon", "krusty", "furf" };
+ public Boolean[] specialCapes = new Boolean[]{ true, true, false, true, true, true, false, false, false, true, true, true, false, false, true, false, true };
public static CapeManager getInstance() {
return INSTANCE;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/NEUCape.java b/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/NEUCape.java
index d93b8bb0..3af37cdd 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/NEUCape.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/cosmetics/NEUCape.java
@@ -734,15 +734,23 @@ public class NEUCape {
newPosition.y = node.lastPosition.y + (node.position.y - node.lastPosition.y) * partialRenderTick;
newPosition.z = node.lastPosition.z + (node.position.z - node.lastPosition.z) * partialRenderTick;
- if(node.oldRenderPosition[node.oldRenderPosition.length-1] == null) {
+ int length = node.oldRenderPosition.length;
+ int fps = Minecraft.getDebugFPS();
+ if(fps < 50) {
+ length = 2;
+ } else if(fps < 100) {
+ length = 2+(int)((fps-50)/50f*3);
+ }
+
+ if(node.oldRenderPosition[length-1] == null) {
node.renderPosition = newPosition;
} else {
Vector3f accum = new Vector3f();
- for(int i=0; i<node.oldRenderPosition.length; i++) {
+ for(int i=0; i<length; i++) {
Vector3f.add(accum, node.oldRenderPosition[i], accum);
Vector3f.add(accum, avgPositionFixed, accum);
}
- accum.scale(1/(float)node.oldRenderPosition.length);
+ accum.scale(1/(float)length);
float blendFactor = 0.5f+0.3f*y/(float)(nodes.size()-1); //0.5/0.5 -> 0.8/0.2 //0-1
accum.scale(blendFactor);
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/dungeons/DungeonMap.java b/src/main/java/io/github/moulberry/notenoughupdates/dungeons/DungeonMap.java
index 59cbfee5..be2b030a 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/dungeons/DungeonMap.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/dungeons/DungeonMap.java
@@ -3,6 +3,7 @@ package io.github.moulberry.notenoughupdates.dungeons;
import com.google.common.collect.Iterables;
import com.google.gson.JsonObject;
import io.github.moulberry.notenoughupdates.core.BackgroundBlur;
+import io.github.moulberry.notenoughupdates.core.config.Position;
import io.github.moulberry.notenoughupdates.util.NEUResourceManager;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
import io.github.moulberry.notenoughupdates.util.SpecialColour;
@@ -1465,8 +1466,10 @@ public class DungeonMap {
}
}
- renderMap((int)(NotEnoughUpdates.INSTANCE.config.dungeonMap.dmCenterX/100*Minecraft.getMinecraft().displayWidth/2),
- (int)(NotEnoughUpdates.INSTANCE.config.dungeonMap.dmCenterY/100*Minecraft.getMinecraft().displayHeight/2),
+ Position pos = NotEnoughUpdates.INSTANCE.config.dungeonMap.dmPosition;
+
+ int size = 80 + Math.round(40*NotEnoughUpdates.INSTANCE.config.dungeonMap.dmBorderSize);
+ renderMap(pos.getAbsX(event.resolution)+size/2, pos.getAbsY(event.resolution)+size/2,
colourMap, decorations, roomSizeBlocks, actualPlayers, true, event.partialTicks);
}
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/dungeons/GuiDungeonMapEditor.java b/src/main/java/io/github/moulberry/notenoughupdates/dungeons/GuiDungeonMapEditor.java
index 5677bf9e..cd951830 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/dungeons/GuiDungeonMapEditor.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/dungeons/GuiDungeonMapEditor.java
@@ -1,5 +1,8 @@
package io.github.moulberry.notenoughupdates.dungeons;
+import io.github.moulberry.notenoughupdates.core.config.gui.GuiPositionEditor;
+import io.github.moulberry.notenoughupdates.core.util.render.RenderUtils;
+import io.github.moulberry.notenoughupdates.core.util.render.TextRenderUtils;
import io.github.moulberry.notenoughupdates.options.NEUConfig;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
import io.github.moulberry.notenoughupdates.core.GuiElementColour;
@@ -43,16 +46,6 @@ public class GuiDungeonMapEditor extends GuiScreen {
private List<Button> buttons = new ArrayList<>();
- private static final int colourEditorBG = new Color(80, 80, 80, 220).getRGB();
- private static ResourceLocation colourPickerLocation = new ResourceLocation("notenoughupdates:dynamic/colourpicker");
- private static ResourceLocation colourPickerBarValueLocation = new ResourceLocation("notenoughupdates:dynamic/colourpickervalue");
- private static ResourceLocation colourPickerBarOpacityLocation = new ResourceLocation("notenoughupdates:dynamic/colourpickeropacity");
-
- private GuiElementTextField hexField = new GuiElementTextField("",
- GuiElementTextField.SCALE_TEXT | GuiElementTextField.FORCE_CAPS | GuiElementTextField.NO_SPACE);
-
- private GuiElementTextField xField = new GuiElementTextField("", GuiElementTextField.NUM_ONLY | GuiElementTextField.NO_SPACE);
- private GuiElementTextField yField = new GuiElementTextField("", GuiElementTextField.NUM_ONLY | GuiElementTextField.NO_SPACE);
private GuiElementTextField blurField = new GuiElementTextField("", GuiElementTextField.NUM_ONLY | GuiElementTextField.NO_SPACE);
private GuiElementColour activeColourEditor = null;
@@ -178,30 +171,6 @@ public class GuiDungeonMapEditor extends GuiScreen {
//buttons.add(new Button(30, 52, 56, "XLarge", options.dmBorderSize));
{
- double val = NotEnoughUpdates.INSTANCE.config.dungeonMap.dmCenterX;
- String strVal;
- if(val % 1 == 0) {
- strVal = Integer.toString((int)val);
- } else {
- strVal = Double.toString(val);
- strVal = strVal.replaceAll("(\\.\\d\\d\\d)(?:\\d)+", "$1");
- strVal = strVal.replaceAll("0+$", "");
- }
- xField.setText(strVal);
- }
- {
- double val = NotEnoughUpdates.INSTANCE.config.dungeonMap.dmCenterY;
- String strVal;
- if(val % 1 == 0) {
- strVal = Integer.toString((int)val);
- } else {
- strVal = Double.toString(val);
- strVal = strVal.replaceAll("(\\.\\d\\d\\d)(?:\\d)+", "$1");
- strVal = strVal.replaceAll("0+$", "");
- }
- yField.setText(strVal);
- }
- {
double val = NotEnoughUpdates.INSTANCE.config.dungeonMap.dmBackgroundBlur;
String strVal;
if(val % 1 == 0) {
@@ -329,10 +298,8 @@ public class GuiDungeonMapEditor extends GuiScreen {
Utils.drawStringCenteredScaledMaxWidth("Chroma Type", Minecraft.getMinecraft().fontRendererObj,
guiLeft+108+139, guiTop+175, false, 60, 0xFFB4B4B4);
- Utils.drawStringCenteredScaledMaxWidth("X (%)", Minecraft.getMinecraft().fontRendererObj,
- guiLeft+44, guiTop+209, false, 60, 0xFFB4B4B4);
- Utils.drawStringCenteredScaledMaxWidth("Y (%)", Minecraft.getMinecraft().fontRendererObj,
- guiLeft+108, guiTop+209, false, 60, 0xFFB4B4B4);
+ Utils.drawStringCenteredScaledMaxWidth("Edit Map Position", Minecraft.getMinecraft().fontRendererObj,
+ guiLeft+76, guiTop+209, false, 200, 0xFFB4B4B4);
try {
drawSlider(NEUConfig.DungeonMap.class.getDeclaredField("dmBorderSize"), guiLeft+76, guiTop+45);
@@ -358,11 +325,13 @@ public class GuiDungeonMapEditor extends GuiScreen {
buttons.get(28-6).text = options.dmChromaBorder ? "Scroll" : "Normal";
blurField.setSize(48, 16);
- xField.setSize(48, 16);
- yField.setSize(48, 16);
blurField.render(guiLeft+20+139, guiTop+181);
- xField.render(guiLeft+20, guiTop+215);
- yField.render(guiLeft+84, guiTop+215);
+
+ GlStateManager.color(1, 1, 1, 1);
+ Minecraft.getMinecraft().getTextureManager().bindTexture(button_tex);
+ RenderUtils.drawTexturedRect(guiLeft+52, guiTop+215, 48, 16);
+ TextRenderUtils.drawStringCenteredScaledMaxWidth("Edit", fontRendererObj, guiLeft+76, guiTop+223,
+ false, 48, 0xFF303030);
Map<String, Vec4b> decorations = new HashMap<>();
Vec4b vec4b = new Vec4b((byte)3, (byte)(((50)-64)*2), (byte)(((40)-64)*2), (byte)((60)*16/360));
@@ -465,8 +434,6 @@ public class GuiDungeonMapEditor extends GuiScreen {
mouseY >= guiTop+button.y && mouseY <= guiTop+button.y+16) {
buttonClicked(mouseX, mouseY, button.id);
- xField.otherComponentClick();
- yField.otherComponentClick();
blurField.otherComponentClick();
return;
}
@@ -493,27 +460,37 @@ public class GuiDungeonMapEditor extends GuiScreen {
if(mouseY > guiTop+181 && mouseY < guiTop+181+16) {
if(mouseX > guiLeft+20+139 && mouseX < guiLeft+20+139+48) {
blurField.mouseClicked(mouseX, mouseY, mouseButton);
- xField.otherComponentClick();
- yField.otherComponentClick();
return;
}
} else if(mouseY > guiTop+215 && mouseY < guiTop+215+16) {
- if(mouseX > guiLeft+20 && mouseX < guiLeft+20+48) {
- xField.mouseClicked(mouseX, mouseY, mouseButton);
- yField.otherComponentClick();
- blurField.otherComponentClick();
- return;
- } else if(mouseX > guiLeft+84 && mouseX < guiLeft+84+48) {
- yField.mouseClicked(mouseX, mouseY, mouseButton);
- xField.otherComponentClick();
- blurField.otherComponentClick();
+ if(mouseX > guiLeft+52 && mouseX < guiLeft+100) {
+ int size = 80 + Math.round(40*NotEnoughUpdates.INSTANCE.config.dungeonMap.dmBorderSize);
+
+ Map<String, Vec4b> decorations = new HashMap<>();
+ Vec4b vec4b = new Vec4b((byte)3, (byte)(((50)-64)*2), (byte)(((40)-64)*2), (byte)((60)*16/360));
+ decorations.put(Minecraft.getMinecraft().thePlayer.getName(), vec4b);
+
+ HashSet<String> players = new HashSet<>();
+ players.add(Minecraft.getMinecraft().thePlayer.getName());
+ GlStateManager.color(1, 1, 1, 1);
+
+ ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft());
+
+ Minecraft.getMinecraft().displayGuiScreen(new GuiPositionEditor(
+ NotEnoughUpdates.INSTANCE.config.dungeonMap.dmPosition,
+ size, size, () -> {
+ demoMap.renderMap(NotEnoughUpdates.INSTANCE.config.dungeonMap.dmPosition.getAbsX(scaledResolution)+size/2,
+ NotEnoughUpdates.INSTANCE.config.dungeonMap.dmPosition.getAbsY(scaledResolution)+size/2,
+ NotEnoughUpdates.INSTANCE.colourMap, decorations, 0,
+ players, false, 0);
+ }, () -> {
+ }, () -> NotEnoughUpdates.INSTANCE.openGui = new GuiDungeonMapEditor()
+ ));
return;
}
}
blurField.otherComponentClick();
- xField.otherComponentClick();
- yField.otherComponentClick();
}
@Override
@@ -540,25 +517,7 @@ public class GuiDungeonMapEditor extends GuiScreen {
protected void keyTyped(char typedChar, int keyCode) throws IOException {
super.keyTyped(typedChar, keyCode);
- if(xField.getFocus()) {
- xField.keyTyped(typedChar, keyCode);
-
- try {
- xField.setCustomBorderColour(-1);
- NotEnoughUpdates.INSTANCE.config.dungeonMap.dmCenterX = Float.parseFloat(xField.getText());
- } catch(Exception e) {
- xField.setCustomBorderColour(Color.RED.getRGB());
- }
- } else if(yField.getFocus()) {
- yField.keyTyped(typedChar, keyCode);
-
- try {
- yField.setCustomBorderColour(-1);
- NotEnoughUpdates.INSTANCE.config.dungeonMap.dmCenterY = Float.parseFloat(yField.getText());
- } catch(Exception e) {
- yField.setCustomBorderColour(Color.RED.getRGB());
- }
- } else if(blurField.getFocus()) {
+ if(blurField.getFocus()) {
blurField.keyTyped(typedChar, keyCode);
try {
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CommissionOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CommissionOverlay.java
new file mode 100644
index 00000000..33cf9c4b
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CommissionOverlay.java
@@ -0,0 +1,164 @@
+package io.github.moulberry.notenoughupdates.miscfeatures;
+
+import com.google.common.collect.ComparisonChain;
+import com.google.common.collect.Ordering;
+import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import io.github.moulberry.notenoughupdates.core.config.Position;
+import io.github.moulberry.notenoughupdates.core.util.StringUtils;
+import io.github.moulberry.notenoughupdates.core.util.lerp.LerpUtils;
+import io.github.moulberry.notenoughupdates.textoverlays.TextOverlay;
+import io.github.moulberry.notenoughupdates.textoverlays.TextOverlayStyle;
+import io.github.moulberry.notenoughupdates.util.SBInfo;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.network.NetworkPlayerInfo;
+import net.minecraft.scoreboard.ScorePlayerTeam;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.world.WorldSettings;
+import net.minecraftforge.fml.relauncher.Side;
+import net.minecraftforge.fml.relauncher.SideOnly;
+
+import java.util.*;
+import java.util.function.Supplier;
+
+import static net.minecraft.util.EnumChatFormatting.*;
+
+public class CommissionOverlay extends TextOverlay {
+
+ public CommissionOverlay(Position position, Supplier<TextOverlayStyle> styleSupplier) {
+ super(position, styleSupplier);
+ }
+
+ @Override
+ public void update() {
+ overlayStrings = new ArrayList<>();
+
+ if(SBInfo.getInstance().getLocation() == null) return;
+ if(!SBInfo.getInstance().getLocation().equals("mining_3")) return;
+
+ Map<String, Float> commissionProgress = new LinkedHashMap<>();
+ List<String> forgeStrings = new ArrayList<>();
+ String mithrilPowder = null;
+
+ boolean commissions = false;
+ boolean forges = false;
+ List<NetworkPlayerInfo> players = playerOrdering.sortedCopy(Minecraft.getMinecraft().thePlayer.sendQueue.getPlayerInfoMap());
+ for(NetworkPlayerInfo info : players) {
+ String name = Minecraft.getMinecraft().ingameGUI.getTabList().getPlayerName(info);
+ if(name.contains("Mithril Powder")) {
+ mithrilPowder = trimIgnoreColour(name);
+ }
+ if(name.equals(RESET.toString()+BLUE+BOLD+"Forges"+RESET)) {
+ commissions = false;
+ forges = true;
+ continue;
+ } else if(name.equals(RESET.toString()+BLUE+BOLD+"Commissions"+RESET)) {
+ commissions = true;
+ forges = false;
+ continue;
+ }
+ String clean = StringUtils.cleanColour(name);
+ if(forges && clean.startsWith(" ")) {
+ if(name.contains("LOCKED")) continue;
+ if(NotEnoughUpdates.INSTANCE.config.mining.hideEmptyForges && name.contains("EMPTY")) continue;
+ forgeStrings.add(DARK_AQUA+"Forge "+trimIgnoreColour(name));
+ } else if(commissions && clean.startsWith(" ")) {
+ String[] split = clean.trim().split(": ");
+ if(split.length == 2) {
+ if(split[1].endsWith("%")) {
+ try {
+ float progress = Float.parseFloat(split[1].replace("%", ""))/100;
+ progress = LerpUtils.clampZeroOne(progress);
+ commissionProgress.put(split[0], progress);
+ } catch(Exception ignored) {}
+ } else {
+ commissionProgress.put(split[0], 1.0f);
+ }
+ }
+ } else {
+ commissions = false;
+ forges = false;
+ }
+ }
+
+ List<String> commissionsStrings = new ArrayList<>();
+ for(Map.Entry<String, Float> entry : commissionProgress.entrySet()) {
+ if(entry.getValue() >= 1) {
+ commissionsStrings.add(DARK_AQUA+entry.getKey() + ": " + GREEN + "DONE");
+ } else {
+ EnumChatFormatting col = RED;
+ if(entry.getValue() >= 0.75) {
+ col = GREEN;
+ } else if(entry.getValue() >= 0.5) {
+ col = YELLOW;
+ } else if(entry.getValue() >= 0.25) {
+ col = GOLD;
+ }
+
+ String valS = String.valueOf(entry.getValue()*100);
+ int periodIndex = valS.indexOf('.');//1.3
+ if(periodIndex > 0) {
+ valS = valS.substring(0, Math.min(valS.length(), periodIndex+2));
+ }
+ if(valS.endsWith("0")) {
+ valS = valS.substring(0, Math.max(0, valS.length()-2));
+ }
+
+ commissionsStrings.add(DARK_AQUA+entry.getKey() + ": " + col+valS+"%");
+ }
+ }
+ boolean hasAny = false;
+ if(NotEnoughUpdates.INSTANCE.config.mining.commissionsOverlay) {
+ overlayStrings.addAll(commissionsStrings);
+ hasAny = true;
+ }
+ if(NotEnoughUpdates.INSTANCE.config.mining.powderOverlay) {
+ if(mithrilPowder != null) {
+ if(hasAny) overlayStrings.add(null);
+ overlayStrings.add(DARK_AQUA+mithrilPowder);
+ hasAny = true;
+ }
+ }
+ if(NotEnoughUpdates.INSTANCE.config.mining.forgeOverlay) {
+ if(hasAny) overlayStrings.add(null);
+ overlayStrings.addAll(forgeStrings);
+ }
+ }
+
+ private String trimIgnoreColour(String str) {
+ str = str.trim();
+ boolean colourCodeLast = false;
+ for(int i=0; i<str.length(); i++) {
+ char c = str.charAt(i);
+ if(colourCodeLast) {
+ colourCodeLast = false;
+ continue;
+ }
+ if(c == '\u00A7') {
+ colourCodeLast = true;
+ } else if(c != ' ') {
+ return str.substring(i);
+ }
+ }
+
+ return "";
+ }
+
+ private static final Ordering<NetworkPlayerInfo> playerOrdering = Ordering.from(new PlayerComparator());
+
+ @SideOnly(Side.CLIENT)
+ static class PlayerComparator implements Comparator<NetworkPlayerInfo> {
+ private PlayerComparator() { }
+
+ public int compare(NetworkPlayerInfo o1, NetworkPlayerInfo o2) {
+ ScorePlayerTeam team1 = o1.getPlayerTeam();
+ ScorePlayerTeam team2 = o2.getPlayerTeam();
+ return ComparisonChain.start().compareTrueFirst(
+ o1.getGameType() != WorldSettings.GameType.SPECTATOR,
+ o2.getGameType() != WorldSettings.GameType.SPECTATOR)
+ .compare(team1 != null ? team1.getRegisteredName() : "", team2 != null ? team2.getRegisteredName() : "")
+ .compare(o1.getGameProfile().getName(), o2.getGameProfile().getName()).result();
+ }
+ }
+
+
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CrystalOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CrystalOverlay.java
new file mode 100644
index 00000000..2c1d1fab
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CrystalOverlay.java
@@ -0,0 +1,327 @@
+package io.github.moulberry.notenoughupdates.miscfeatures;
+
+import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+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.Tessellator;
+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.item.EntityArmorStand;
+import net.minecraft.init.Items;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.util.AxisAlignedBB;
+import net.minecraft.util.BlockPos;
+import net.minecraftforge.client.event.RenderWorldLastEvent;
+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.awt.*;
+import java.nio.ByteBuffer;
+import java.util.*;
+import java.util.List;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+public class CrystalOverlay {
+
+ private enum CrystalType {
+ FARMING_MINION(8, 0xDAA520),
+ MINING_MINION(40, 0x6e5a49),
+ FORAGING_MINION(12, 0x01a552),
+ DESERT(16, 0xfff178),
+ FISHING(15, 0x1972a6),
+ WART(5, 0x821530),
+ WHEAT(6, 0xff9d00);
+
+ CrystalType(int radius, int rgb) {
+ this.radius = radius;
+ this.rgb = rgb;
+ }
+
+ public Set<BlockPos> getCircleOffsets() {
+ if(circleOffsets != null) return circleOffsets;
+ circleOffsets = new HashSet<>();
+
+ for(int x=-radius; x<=radius; x++) {
+ for(int y=-radius; y<=radius; y++) {
+ for(int z=-radius; z<=radius; z++) {
+ float distSq = (x-0.5f)*(x-0.5f) + y*y + (z-0.5f)*(z-0.5f);
+ if(distSq > (radius-1)*(radius-1) && distSq < radius*radius) {
+ circleOffsets.add(new BlockPos(x, y, z));
+ }
+ }
+ }
+ }
+
+ return circleOffsets;
+ }
+
+ public ReverseWorldRenderer getOverlayVBO() {
+ if(overlayVBO != null) return overlayVBO;
+
+ EntityPlayerSP p = Minecraft.getMinecraft().thePlayer;
+ if(p == null) return null;
+
+ if(!crystals.containsKey(this)) {
+ return null;
+ }
+
+ //per vertex = 6
+ //per size = 4
+ //per block = 8
+ //total per block = 196
+
+ ReverseWorldRenderer worldRenderer = new ReverseWorldRenderer(196*getCircleOffsets().size());
+ worldRenderer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_COLOR);
+
+ String col = SpecialColour.special(0, 180, rgb);
+ for(BlockPos offset : getCircleOffsets()) {
+ 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*(this.ordinal()+1), 0.001f*(this.ordinal()+1), 0.001f*(this.ordinal()+1));
+ uploadFilledBoundingBox(bb, 1f, col, worldRenderer);
+ }
+
+ overlayVBO = worldRenderer;
+ return overlayVBO;
+ }
+
+ ReverseWorldRenderer overlayVBO = null;
+ Set<BlockPos> circleOffsets = null;
+ int updates = 0;
+ int rgb;
+ int radius;
+ }
+
+ private static HashMap<String, CrystalType> skullId = new HashMap<>();
+ static {
+ skullId.put("d9c3168a-8654-3dd8-b297-4d3b7e55b95a", CrystalType.FARMING_MINION);
+ skullId.put("949d100c-aa74-3b09-a642-af5529f808aa", CrystalType.MINING_MINION);
+ skullId.put("bd79a474-cf07-3f8c-b5a4-98657c33520a", CrystalType.FORAGING_MINION);
+ skullId.put("2e474ee3-5361-3218-84db-880eb1cface1", CrystalType.FISHING);
+ }
+
+ public static long displayMillis = 0;
+
+ public static HashMap<CrystalType, BlockPos> crystals = new HashMap<>();
+
+ private static ExecutorService es = Executors.newSingleThreadExecutor();
+
+ public static void tick() {
+ if(Minecraft.getMinecraft().theWorld == null) return;
+
+ EntityPlayerSP p = Minecraft.getMinecraft().thePlayer;
+ if(p == null) return;
+
+ long currentTime = System.currentTimeMillis();
+
+ if(currentTime - displayMillis > 10*1000) {
+ displayMillis = -1;
+ }
+
+ ItemStack held = p.getHeldItem();
+ String internal = NotEnoughUpdates.INSTANCE.manager.getInternalNameForItem(held);
+ if(internal != null) {
+ if(internal.endsWith("_CRYSTAL")) {
+ displayMillis = System.currentTimeMillis();
+ }
+ }
+
+ if(displayMillis < 0) {
+ return;
+ }
+
+ Set<CrystalType> foundTypes = new HashSet<>();
+ for(Entity entity : Minecraft.getMinecraft().theWorld.loadedEntityList) {
+ if(entity instanceof EntityArmorStand) {
+ EntityArmorStand armorStand = (EntityArmorStand) entity;
+
+ if(armorStand.isChild() && armorStand.getEquipmentInSlot(4) != null) {
+ ItemStack helmet = armorStand.getEquipmentInSlot(4);
+
+ if(helmet.getItem() == Items.skull && helmet.hasTagCompound()) {
+ NBTTagCompound tag = helmet.getTagCompound();
+ if(tag.hasKey("SkullOwner", 10)) {
+ NBTTagCompound skullOwner = tag.getCompoundTag("SkullOwner");
+ if(skullOwner.hasKey("Id", 8)) {
+ String id = skullOwner.getString("Id");
+
+ if(skullId.containsKey(id)) {
+ CrystalType type = skullId.get(id);
+ foundTypes.add(type);
+ BlockPos pos = new BlockPos(armorStand.posX, armorStand.posY+0.5f, armorStand.posZ);
+
+ if(crystals.containsKey(type)) {
+ BlockPos old = crystals.get(type);
+ if(old.equals(pos)) {
+ type.updates = 0;
+ } else {
+ if(++type.updates >= 3) {
+ type.updates = 0;
+ crystals.put(type, pos);
+ }
+ }
+ } else {
+ crystals.put(type, pos);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ crystals.keySet().retainAll(foundTypes);
+ }
+
+ @SubscribeEvent
+ public void onTick(TickEvent.ClientTickEvent event) {
+ EntityPlayerSP p = Minecraft.getMinecraft().thePlayer;
+ if(p == null) return;
+
+ if(event.phase == TickEvent.Phase.START) {
+ for(CrystalType type : crystals.keySet()) {
+ ReverseWorldRenderer worldRenderer = type.getOverlayVBO();
+ if(worldRenderer != null) {
+ BlockPos crystal = crystals.get(type);
+
+ worldRenderer.setTranslation(0, 0,0 );
+ worldRenderer.sortVertexData(
+ (float)p.posX-crystal.getX(),
+ (float)p.posY-crystal.getY(),
+ (float)p.posZ-crystal.getZ());
+ }
+ }
+ }
+ }
+
+ @SubscribeEvent
+ public void onRenderLast(RenderWorldLastEvent event) {
+ if(displayMillis < 0) {
+ 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);
+ for(CrystalType type : crystals.keySet()) {
+ ReverseWorldRenderer worldRenderer = type.getOverlayVBO();
+ if(worldRenderer != null && worldRenderer.getVertexCount() > 0) {
+ BlockPos crystal = crystals.get(type);
+ GlStateManager.translate(crystal.getX(), crystal.getY(), crystal.getZ());
+
+ 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);
+ }
+
+ GlStateManager.translate(-crystal.getX(), -crystal.getY(), -crystal.getZ());
+ }
+ }
+ GL11.glPolygonOffset(0, 0);
+
+ GlStateManager.translate(viewerX, viewerY, viewerZ);
+
+ GlStateManager.enableTexture2D();
+ }
+
+ @SubscribeEvent
+ public void onWorldUnload(WorldEvent.Unload event) {
+ crystals.clear();
+ }
+
+ 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();
+ }
+
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CustomItemEffects.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CustomItemEffects.java
index 763da0b5..de0d7406 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CustomItemEffects.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CustomItemEffects.java
@@ -703,7 +703,6 @@ public class CustomItemEffects {
public static void drawFilledBoundingBox(AxisAlignedBB p_181561_0_, float alpha, String special) {
Color c = new Color(SpecialColour.specialToChromaRGB(special), true);
- GlStateManager.color(c.getRed()/255f, c.getGreen()/255f, c.getBlue()/255f, c.getAlpha()/255f*alpha);
GlStateManager.enableBlend();
GlStateManager.tryBlendFuncSeparate(770, 771, 1, 0);
@@ -712,6 +711,8 @@ public class CustomItemEffects {
Tessellator tessellator = Tessellator.getInstance();
WorldRenderer worldrenderer = tessellator.getWorldRenderer();
+ GlStateManager.color(c.getRed()/255f, c.getGreen()/255f, c.getBlue()/255f, c.getAlpha()/255f*alpha);
+
//vertical
worldrenderer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION);
worldrenderer.pos(p_181561_0_.minX, p_181561_0_.minY, p_181561_0_.minZ).endVertex();
@@ -720,18 +721,21 @@ public class CustomItemEffects {
worldrenderer.pos(p_181561_0_.minX, p_181561_0_.minY, p_181561_0_.maxZ).endVertex();
tessellator.draw();
worldrenderer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION);
- worldrenderer.pos(p_181561_0_.minX, p_181561_0_.maxY, p_181561_0_.minZ).endVertex();
- worldrenderer.pos(p_181561_0_.maxX, p_181561_0_.maxY, p_181561_0_.minZ).endVertex();
- worldrenderer.pos(p_181561_0_.maxX, p_181561_0_.maxY, p_181561_0_.maxZ).endVertex();
worldrenderer.pos(p_181561_0_.minX, p_181561_0_.maxY, p_181561_0_.maxZ).endVertex();
+ worldrenderer.pos(p_181561_0_.maxX, p_181561_0_.maxY, p_181561_0_.maxZ).endVertex();
+ worldrenderer.pos(p_181561_0_.maxX, p_181561_0_.maxY, p_181561_0_.minZ).endVertex();
+ worldrenderer.pos(p_181561_0_.minX, p_181561_0_.maxY, p_181561_0_.minZ).endVertex();
tessellator.draw();
- //x
+
+ GlStateManager.color(c.getRed()/255f*0.8f, c.getGreen()/255f*0.8f, c.getBlue()/255f*0.8f, c.getAlpha()/255f*alpha);
+
+ //x
worldrenderer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION);
- worldrenderer.pos(p_181561_0_.minX, p_181561_0_.minY, p_181561_0_.minZ).endVertex();
- worldrenderer.pos(p_181561_0_.minX, p_181561_0_.maxY, p_181561_0_.minZ).endVertex();
- worldrenderer.pos(p_181561_0_.minX, p_181561_0_.maxY, p_181561_0_.maxZ).endVertex();
worldrenderer.pos(p_181561_0_.minX, p_181561_0_.minY, p_181561_0_.maxZ).endVertex();
+ worldrenderer.pos(p_181561_0_.minX, p_181561_0_.maxY, p_181561_0_.maxZ).endVertex();
+ worldrenderer.pos(p_181561_0_.minX, p_181561_0_.maxY, p_181561_0_.minZ).endVertex();
+ worldrenderer.pos(p_181561_0_.minX, p_181561_0_.minY, p_181561_0_.minZ).endVertex();
tessellator.draw();
worldrenderer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION);
worldrenderer.pos(p_181561_0_.maxX, p_181561_0_.minY, p_181561_0_.minZ).endVertex();
@@ -740,12 +744,14 @@ public class CustomItemEffects {
worldrenderer.pos(p_181561_0_.maxX, p_181561_0_.minY, p_181561_0_.maxZ).endVertex();
tessellator.draw();
+
+ GlStateManager.color(c.getRed()/255f*0.9f, c.getGreen()/255f*0.9f, c.getBlue()/255f*0.9f, c.getAlpha()/255f*alpha);
//z
worldrenderer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION);
- worldrenderer.pos(p_181561_0_.minX, p_181561_0_.minY, p_181561_0_.minZ).endVertex();
- worldrenderer.pos(p_181561_0_.maxX, p_181561_0_.minY, p_181561_0_.minZ).endVertex();
- worldrenderer.pos(p_181561_0_.maxX, p_181561_0_.maxY, p_181561_0_.minZ).endVertex();
worldrenderer.pos(p_181561_0_.minX, p_181561_0_.maxY, p_181561_0_.minZ).endVertex();
+ worldrenderer.pos(p_181561_0_.maxX, p_181561_0_.maxY, p_181561_0_.minZ).endVertex();
+ worldrenderer.pos(p_181561_0_.maxX, p_181561_0_.minY, p_181561_0_.minZ).endVertex();
+ worldrenderer.pos(p_181561_0_.minX, p_181561_0_.minY, p_181561_0_.minZ).endVertex();
tessellator.draw();
worldrenderer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION);
worldrenderer.pos(p_181561_0_.minX, p_181561_0_.minY, p_181561_0_.maxZ).endVertex();
@@ -753,7 +759,6 @@ public class CustomItemEffects {
worldrenderer.pos(p_181561_0_.maxX, p_181561_0_.maxY, p_181561_0_.maxZ).endVertex();
worldrenderer.pos(p_181561_0_.minX, p_181561_0_.maxY, p_181561_0_.maxZ).endVertex();
tessellator.draw();
-
}
public static void drawFilledBoundingBoxSide(AxisAlignedBB p_181561_0_, EnumFacing facing, float alpha, String special) {
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/DwarvenMinesTextures.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/DwarvenMinesTextures.java
new file mode 100644
index 00000000..4a639287
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/DwarvenMinesTextures.java
@@ -0,0 +1,90 @@
+package io.github.moulberry.notenoughupdates.miscfeatures;
+
+import io.github.moulberry.notenoughupdates.util.SBInfo;
+import net.minecraft.client.Minecraft;
+import net.minecraft.world.ChunkCoordIntPair;
+import net.minecraft.world.biome.BiomeGenBase;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+public class DwarvenMinesTextures {
+
+ private static final byte biomeId1 = (byte)(BiomeGenBase.extremeHillsEdge.biomeID & 255);
+ private static final byte[] biomeMap1 = new byte[16*16];
+ private static final byte biomeId2 = (byte)(BiomeGenBase.extremeHillsPlus.biomeID & 255);
+ private static final byte[] biomeMap2 = new byte[16*16];
+ static {
+ Arrays.fill(biomeMap1, biomeId1);
+ Arrays.fill(biomeMap2, biomeId2);
+ }
+
+ public static void tick() {
+ if(Minecraft.getMinecraft().theWorld == null) return;
+
+ if(SBInfo.getInstance().getLocation() == null) return;
+ if(!SBInfo.getInstance().getLocation().equals("mining_3")) return;
+
+ int playerX = (int)Minecraft.getMinecraft().thePlayer.posX;
+ int playerZ = (int)Minecraft.getMinecraft().thePlayer.posZ;
+
+ for(int xC=-10; xC<=10; xC++) {
+ for(int zC=-10; zC<=10; zC++) {
+ ChunkCoordIntPair pair = new ChunkCoordIntPair(playerX/16+xC, playerZ/16+zC);
+
+ if(!ignoredChunks.contains(pair)) {
+ Minecraft.getMinecraft().theWorld.getChunkFromChunkCoords(pair.chunkXPos, pair.chunkZPos).setBiomeArray(biomeMap1);
+ } else {
+ Minecraft.getMinecraft().theWorld.getChunkFromChunkCoords(pair.chunkXPos, pair.chunkZPos).setBiomeArray(biomeMap2);
+ }
+ }
+ }
+ }
+
+ private static Set<ChunkCoordIntPair> ignoredChunks = new HashSet<>();
+ static {
+ ignoredChunks.add(new ChunkCoordIntPair(9, 3));
+ ignoredChunks.add(new ChunkCoordIntPair(6, 0));
+ ignoredChunks.add(new ChunkCoordIntPair(0, -4));
+ ignoredChunks.add(new ChunkCoordIntPair(1, -6));
+ ignoredChunks.add(new ChunkCoordIntPair(-1, -3));
+ ignoredChunks.add(new ChunkCoordIntPair(6, 5));
+ ignoredChunks.add(new ChunkCoordIntPair(-1, -2));
+ ignoredChunks.add(new ChunkCoordIntPair(8, -1));
+ ignoredChunks.add(new ChunkCoordIntPair(8, -2));
+ ignoredChunks.add(new ChunkCoordIntPair(6, 6));
+ ignoredChunks.add(new ChunkCoordIntPair(6, 1));
+ ignoredChunks.add(new ChunkCoordIntPair(9, -1));
+ ignoredChunks.add(new ChunkCoordIntPair(9, 4));
+ ignoredChunks.add(new ChunkCoordIntPair(8, 0));
+ ignoredChunks.add(new ChunkCoordIntPair(9, 2));
+ ignoredChunks.add(new ChunkCoordIntPair(1, -4));
+ ignoredChunks.add(new ChunkCoordIntPair(0, -6));
+ ignoredChunks.add(new ChunkCoordIntPair(-1, -5));
+ ignoredChunks.add(new ChunkCoordIntPair(9, 1));
+ ignoredChunks.add(new ChunkCoordIntPair(9, 6));
+ ignoredChunks.add(new ChunkCoordIntPair(-1, -6));
+ ignoredChunks.add(new ChunkCoordIntPair(6, 4));
+ ignoredChunks.add(new ChunkCoordIntPair(1, -3));
+ ignoredChunks.add(new ChunkCoordIntPair(9, 5));
+ ignoredChunks.add(new ChunkCoordIntPair(1, -2));
+ ignoredChunks.add(new ChunkCoordIntPair(0, -5));
+ ignoredChunks.add(new ChunkCoordIntPair(7, -1));
+ ignoredChunks.add(new ChunkCoordIntPair(7, -2));
+ ignoredChunks.add(new ChunkCoordIntPair(9, 0));
+ ignoredChunks.add(new ChunkCoordIntPair(6, 3));
+ ignoredChunks.add(new ChunkCoordIntPair(0, -3));
+ ignoredChunks.add(new ChunkCoordIntPair(-1, -4));
+ ignoredChunks.add(new ChunkCoordIntPair(1, -5));
+ ignoredChunks.add(new ChunkCoordIntPair(6, 2));
+ ignoredChunks.add(new ChunkCoordIntPair(0, -2));
+ ignoredChunks.add(new ChunkCoordIntPair(-2, -4));
+ ignoredChunks.add(new ChunkCoordIntPair(-2, -5));
+ ignoredChunks.add(new ChunkCoordIntPair(-2, -6));
+ ignoredChunks.add(new ChunkCoordIntPair(-1, -7));
+ ignoredChunks.add(new ChunkCoordIntPair(0, -7));
+ ignoredChunks.add(new ChunkCoordIntPair(1, -7));
+ }
+
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/FairySouls.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/FairySouls.java
index 70a701e0..b5a98704 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/FairySouls.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/FairySouls.java
@@ -106,6 +106,8 @@ public class FairySouls {
}
JsonObject fairySouls = Constants.FAIRYSOULS;
+ if(fairySouls == null) return;
+
String location = SBInfo.getInstance().getLocation();
if(location == null) {
currentSoulList = null;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/ItemCooldowns.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/ItemCooldowns.java
new file mode 100644
index 00000000..8edd9217
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/ItemCooldowns.java
@@ -0,0 +1,135 @@
+package io.github.moulberry.notenoughupdates.miscfeatures;
+
+import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import net.minecraft.block.state.IBlockState;
+import net.minecraft.client.Minecraft;
+import net.minecraft.item.ItemStack;
+import net.minecraft.network.play.server.S23PacketBlockChange;
+import net.minecraft.util.BlockPos;
+import net.minecraftforge.client.event.ClientChatReceivedEvent;
+import net.minecraftforge.event.world.WorldEvent;
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
+import net.minecraftforge.fml.common.gameevent.TickEvent;
+
+import java.util.*;
+import java.util.regex.Pattern;
+
+public class ItemCooldowns {
+
+ private static Map<ItemStack, Float> durabilityOverrideMap = new HashMap<>();
+ private static long pickaxeUseCooldownMillisRemaining = -1;
+ private static long treecapitatorCooldownMillisRemaining = -1;
+ private static long lastMillis = 0;
+
+ public static TreeMap<Long, BlockPos> blocksClicked = new TreeMap<>();
+
+ @SubscribeEvent
+ public void tick(TickEvent.ClientTickEvent event) {
+ if(event.phase == TickEvent.Phase.END) {
+ long currentTime = System.currentTimeMillis();
+
+ Long key;
+ while((key = blocksClicked.floorKey(currentTime - 1500)) != null) {
+ blocksClicked.remove(key);
+ }
+
+ long millisDelta = currentTime - lastMillis;
+ lastMillis = currentTime;
+
+ durabilityOverrideMap.clear();
+
+ if(pickaxeUseCooldownMillisRemaining >= 0) {
+ pickaxeUseCooldownMillisRemaining -= millisDelta;
+ }
+ if(treecapitatorCooldownMillisRemaining >= 0) {
+ treecapitatorCooldownMillisRemaining -= millisDelta;
+ }
+ }
+ }
+
+ @SubscribeEvent
+ public void onWorldUnload(WorldEvent.Unload event) {
+ blocksClicked.clear();
+ }
+
+ public static void blockClicked(BlockPos pos) {
+ long currentTime = System.currentTimeMillis();
+ blocksClicked.put(currentTime, pos);
+ }
+
+ public static void processBlockChangePacket(S23PacketBlockChange packetIn) {
+ BlockPos pos = packetIn.getBlockPosition();
+
+ if(blocksClicked.containsValue(pos)) {
+ IBlockState oldState = Minecraft.getMinecraft().theWorld.getBlockState(pos);
+ if(oldState.getBlock() != packetIn.getBlockState().getBlock()) {
+ onBlockMined(pos);
+ }
+ }
+ }
+
+ public static void onBlockMined(BlockPos pos) {
+ ItemStack held = Minecraft.getMinecraft().thePlayer.getHeldItem();
+ String internalname = NotEnoughUpdates.INSTANCE.manager.getInternalNameForItem(held);
+ if(internalname != null) {
+ if(treecapitatorCooldownMillisRemaining < 0 &&
+ (internalname.equals("TREECAPITATOR_AXE") || internalname.equals("JUNGLE_AXE"))) {
+ treecapitatorCooldownMillisRemaining = 2*1000;
+ }
+ }
+ }
+
+ private static Pattern PICKAXE_ABILITY_REGEX = Pattern.compile("\\u00a7r\\u00a7aYou used your " +
+ "\\u00a7r\\u00a7e.+ \\u00a7r\\u00a7aPickaxe Ability!\\u00a7r");
+
+ @SubscribeEvent
+ public void onChatMessage(ClientChatReceivedEvent event) {
+ if(PICKAXE_ABILITY_REGEX.matcher(event.message.getFormattedText()).matches()) {
+ pickaxeUseCooldownMillisRemaining = 120*1000;
+ }
+ }
+
+ public static float getDurabilityOverride(ItemStack stack) {
+ if(Minecraft.getMinecraft().theWorld == null) return -1;
+
+ if(durabilityOverrideMap.containsKey(stack)) {
+ return durabilityOverrideMap.get(stack);
+ }
+
+ String internalname = NotEnoughUpdates.INSTANCE.manager.getInternalNameForItem(stack);
+ if(internalname == null) {
+ durabilityOverrideMap.put(stack, -1f);
+ return -1;
+ }
+
+ if(internalname.endsWith("_PICKAXE") || internalname.contains("_DRILL_")) {
+ if(pickaxeUseCooldownMillisRemaining < 0) {
+ durabilityOverrideMap.put(stack, -1f);
+ return -1;
+ }
+
+ if(pickaxeUseCooldownMillisRemaining > 120*1000) {
+ return stack.getItemDamage();
+ }
+ float dura = (float)(pickaxeUseCooldownMillisRemaining/(120.0*1000.0));
+ durabilityOverrideMap.put(stack, dura);
+ return dura;
+ } else if(internalname.equals("TREECAPITATOR_AXE") || internalname.equals("JUNGLE_AXE")) {
+ if(treecapitatorCooldownMillisRemaining < 0) {
+ durabilityOverrideMap.put(stack, -1f);
+ return -1;
+ }
+
+ if(treecapitatorCooldownMillisRemaining > 2*1000) {
+ return stack.getItemDamage();
+ }
+ float dura = (float)(treecapitatorCooldownMillisRemaining/(2.0*1000.0));
+ durabilityOverrideMap.put(stack, dura);
+ return dura;
+ }
+
+ durabilityOverrideMap.put(stack, -1f);
+ return -1;
+ }
+
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/MiningStuff.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/MiningStuff.java
index 97bb8377..d803778b 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/MiningStuff.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/MiningStuff.java
@@ -109,8 +109,6 @@ public class MiningStuff {
overlayLoc.getY()+1-viewerY,
overlayLoc.getZ()+1-viewerZ).expand(0.01f, 0.01f, 0.01f);
- //181 / 195 / 135
-
GlStateManager.disableCull();
CustomItemEffects.drawFilledBoundingBox(bb, 1f, SpecialColour.special(0, 100, 0xff0000));
GlStateManager.enableCull();
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/AccessoryBagOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/AccessoryBagOverlay.java
index 75c9415c..c7e01bfa 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/AccessoryBagOverlay.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/AccessoryBagOverlay.java
@@ -4,7 +4,9 @@ import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import io.github.moulberry.notenoughupdates.core.util.StringUtils;
import io.github.moulberry.notenoughupdates.profileviewer.PlayerStats;
+import io.github.moulberry.notenoughupdates.textoverlays.TextOverlayStyle;
import io.github.moulberry.notenoughupdates.util.Constants;
import io.github.moulberry.notenoughupdates.util.Utils;
import net.minecraft.client.Minecraft;
@@ -172,7 +174,7 @@ public class AccessoryBagOverlay {
int yIndex = 0;
for(Map.Entry<Integer, Integer> entry : talismanCountRarity.descendingMap().entrySet()) {
String rarityName = rarityArrC[entry.getKey()];
- renderAlignedString(rarityName, EnumChatFormatting.WHITE.toString()+entry.getValue(), x+5, y+20+11*yIndex, 70);
+ Utils.renderAlignedString(rarityName, EnumChatFormatting.WHITE.toString()+entry.getValue(), x+5, y+20+11*yIndex, 70);
yIndex++;
}
}
@@ -201,7 +203,7 @@ public class AccessoryBagOverlay {
GlStateManager.color(1, 1, 1, 1);
GlStateManager.enableBlend();
GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA);
- renderAlignedString(statNamePretty, EnumChatFormatting.WHITE.toString()+val, x+5, y+20+11*yIndex, 70);
+ Utils.renderAlignedString(statNamePretty, EnumChatFormatting.WHITE.toString()+val, x+5, y+20+11*yIndex, 70);
yIndex++;
}
@@ -230,7 +232,7 @@ public class AccessoryBagOverlay {
GlStateManager.color(1, 1, 1, 1);
GlStateManager.enableBlend();
GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA);
- renderAlignedString(statNamePretty, EnumChatFormatting.WHITE.toString()+val, x+5, y+20+11*yIndex, 70);
+ Utils.renderAlignedString(statNamePretty, EnumChatFormatting.WHITE.toString()+val, x+5, y+20+11*yIndex, 70);
yIndex++;
}
@@ -291,7 +293,8 @@ public class AccessoryBagOverlay {
int yIndex = 0;
for(ItemStack duplicate : duplicates) {
- renderAlignedString(duplicate.getDisplayName(), "", x+5, y+20+11*yIndex, 70);
+ String s = duplicate.getDisplayName();
+ Utils.renderShadowedString(s, x+40, y+20+11*yIndex, 70);
if(duplicates.size() > 11) {
if(++yIndex >= 10) break;
} else {
@@ -382,8 +385,27 @@ public class AccessoryBagOverlay {
new Color(80, 80, 80).getRGB());
int yIndex = 0;
+ long currentTime = System.currentTimeMillis();
+ int marqueeOffset = (int)(currentTime/500 % 100);
for(ItemStack missingStack : missing) {
- renderAlignedString(missingStack.getDisplayName(), "", x+5, y+20+11*yIndex, 70);
+ String s = missingStack.getDisplayName();
+
+ //int marueeOffset
+ //if(s.length()) {
+
+ //}
+
+ s = Minecraft.getMinecraft().fontRendererObj.trimStringToWidth(s, 70);
+
+ String clean = StringUtils.cleanColourNotModifiers(s);
+ for(int xO = -1; xO <= 1; xO++) {
+ for(int yO = -1; yO <= 1; yO++) {
+ int col = 0xff202020;
+ //if(xO != 0 && yO != 0) col = 0xff252525;
+ Minecraft.getMinecraft().fontRendererObj.drawString(clean, x+5+xO, y+20+11*yIndex+yO, col, false);
+ }
+ }
+ Minecraft.getMinecraft().fontRendererObj.drawString(s, x+5, y+20+11*yIndex, 0xffffff, false);
if(missing.size() > 11) {
if(++yIndex >= 10) break;
} else {
@@ -674,7 +696,7 @@ public class AccessoryBagOverlay {
}
}
- private static void renderAlignedString(String first, String second, float x, float y, int length) {
+ /*private static void renderAlignedString(String first, String second, float x, float y, int length) {
FontRenderer fontRendererObj = Minecraft.getMinecraft().fontRendererObj;
if(fontRendererObj.getStringWidth(first + " " + second) >= length) {
@@ -718,7 +740,7 @@ public class AccessoryBagOverlay {
GlStateManager.color(1, 1, 1, 1);
fontRendererObj.drawString(second, x+length-secondLen, y, 4210752, false);
}
- }
+ }*/
private static final Pattern HEALTH_PATTERN_BONUS = Pattern.compile("^Health: (?:\\+|-)[0-9]+ HP \\([a-zA-Z]+ ((?:\\+|-)[0-9]+)");
private static final Pattern DEFENCE_PATTERN_BONUS = Pattern.compile("^Defense: (?:\\+|-)[0-9]+ \\([a-zA-Z]+ ((?:\\+|-)[0-9]+)");
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinEffectRenderer.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinEffectRenderer.java
index 68e0a7c3..e4c51618 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinEffectRenderer.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinEffectRenderer.java
@@ -3,6 +3,7 @@ package io.github.moulberry.notenoughupdates.mixins;
import io.github.moulberry.notenoughupdates.miscfeatures.CustomItemEffects;
import net.minecraft.client.particle.EffectRenderer;
import net.minecraft.client.particle.EntityFX;
+import net.minecraft.client.renderer.GlStateManager;
import org.lwjgl.util.vector.Vector3f;
import org.objectweb.asm.Opcodes;
import org.spongepowered.asm.mixin.Mixin;
@@ -13,43 +14,19 @@ import org.spongepowered.asm.mixin.injection.Redirect;
@Mixin(EffectRenderer.class)
public class MixinEffectRenderer {
- /*@Redirect(method="renderParticles", at=@At(
- value = "FIELD",
- opcode = Opcodes.PUTSTATIC,
- target = "Lnet/minecraft/client/particle/EntityFX;interpPosX:D")
- )
- public void renderParticles_interpPosX(double interpPosX) {
- Vector3f currentPosition = CustomItemEffects.INSTANCE.getCurrentPosition();
- if(currentPosition != null) {
- EntityFX.interpPosX = currentPosition.x;
- }
- EntityFX.interpPosX = interpPosX;
- }
-
@Redirect(method="renderParticles", at=@At(
- value = "FIELD",
- opcode = Opcodes.PUTSTATIC,
- target = "Lnet/minecraft/client/particle/EntityFX;interpPosY:D")
+ value = "INVOKE",
+ target = "Lnet/minecraft/client/renderer/GlStateManager;enableBlend()V")
)
- public void renderParticles_interpPosY(double interpPosY) {
- Vector3f currentPosition = CustomItemEffects.INSTANCE.getCurrentPosition();
- if(currentPosition != null) {
- EntityFX.interpPosY = currentPosition.y;
- }
- EntityFX.interpPosY = interpPosY;
- }
+ public void renderParticles_enableBlend() {
+ GlStateManager.enableBlend();
- @Redirect(method="renderParticles", at=@At(
- value = "FIELD",
- opcode = Opcodes.PUTSTATIC,
- target = "Lnet/minecraft/client/particle/EntityFX;interpPosZ:D")
- )
- public void renderParticles_interpPosZ(double interpPosZ) {
Vector3f currentPosition = CustomItemEffects.INSTANCE.getCurrentPosition();
if(currentPosition != null) {
+ EntityFX.interpPosX = currentPosition.x;
+ EntityFX.interpPosY = currentPosition.y;
EntityFX.interpPosZ = currentPosition.z;
}
- EntityFX.interpPosZ = interpPosZ;
- }*/
+ }
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinItemStack.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinItemStack.java
index 34f1ea62..c20ccebe 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinItemStack.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinItemStack.java
@@ -1,6 +1,7 @@
package io.github.moulberry.notenoughupdates.mixins;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import io.github.moulberry.notenoughupdates.miscfeatures.ItemCooldowns;
import io.github.moulberry.notenoughupdates.util.Utils;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinNetHandlerPlayClient.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinNetHandlerPlayClient.java
index c0e15d52..876338da 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinNetHandlerPlayClient.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinNetHandlerPlayClient.java
@@ -3,6 +3,7 @@ package io.github.moulberry.notenoughupdates.mixins;
import io.github.moulberry.notenoughupdates.miscfeatures.CustomItemEffects;
import io.github.moulberry.notenoughupdates.miscfeatures.EnchantingSolvers;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import io.github.moulberry.notenoughupdates.miscfeatures.ItemCooldowns;
import io.github.moulberry.notenoughupdates.miscfeatures.MiningStuff;
import net.minecraft.client.network.NetHandlerPlayClient;
import net.minecraft.entity.player.EntityPlayer;
@@ -36,6 +37,7 @@ public class MixinNetHandlerPlayClient {
@Inject(method="handleBlockChange", at=@At("HEAD"))
public void handleBlockChange(S23PacketBlockChange packetIn, CallbackInfo ci) {
MiningStuff.processBlockChangePacket(packetIn);
+ ItemCooldowns.processBlockChangePacket(packetIn);
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinPlayerControllerMP.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinPlayerControllerMP.java
index 0e978640..b821113b 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinPlayerControllerMP.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinPlayerControllerMP.java
@@ -1,6 +1,7 @@
package io.github.moulberry.notenoughupdates.mixins;
import io.github.moulberry.notenoughupdates.miscfeatures.FairySouls;
+import io.github.moulberry.notenoughupdates.miscfeatures.ItemCooldowns;
import io.github.moulberry.notenoughupdates.miscfeatures.MiningStuff;
import net.minecraft.client.multiplayer.PlayerControllerMP;
import net.minecraft.util.BlockPos;
@@ -16,6 +17,7 @@ public class MixinPlayerControllerMP {
@Inject(method="clickBlock", at=@At("HEAD"))
public void clickBlock(BlockPos loc, EnumFacing face, CallbackInfoReturnable<Boolean> cir) {
MiningStuff.blockClicked(loc);
+ ItemCooldowns.blockClicked(loc);
}
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinRenderItem.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinRenderItem.java
index 6e552e3c..afd44fd3 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinRenderItem.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinRenderItem.java
@@ -1,24 +1,65 @@
package io.github.moulberry.notenoughupdates.mixins;
+import io.github.moulberry.notenoughupdates.miscfeatures.ItemCooldowns;
import io.github.moulberry.notenoughupdates.miscfeatures.ItemRarityHalo;
+import net.minecraft.client.gui.FontRenderer;
+import net.minecraft.client.renderer.GlStateManager;
+import net.minecraft.client.renderer.Tessellator;
+import net.minecraft.client.renderer.WorldRenderer;
import net.minecraft.client.renderer.entity.RenderItem;
+import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.item.ItemStack;
import org.lwjgl.input.Keyboard;
import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin({RenderItem.class})
public abstract class MixinRenderItem {
- //Lnet/minecraft/client/renderer/entity/RenderItem;renderItem(Lnet/minecraft/item/ItemStack;Lnet/minecraft/client/resources/model/IBakedModel;)V
- @Inject(method="Lnet/minecraft/client/renderer/entity/RenderItem;renderItemIntoGUI(Lnet/minecraft/item/ItemStack;II)V",
- at=@At("HEAD"), cancellable = true)
- public void renderItemIntoGUI(ItemStack stack, int x, int y, CallbackInfo ci) {
- if(x == 0 && y == 0 || true) return;
- ItemRarityHalo.onItemRender(stack, x, y);
+ private static void func_181565_a(WorldRenderer w, int x, int y, float width, int height,
+ int r, int g, int b, int a) {
+ w.begin(7, DefaultVertexFormats.POSITION_COLOR);
+ w.pos((x + 0), (y + 0), 0.0D)
+ .color(r, g, b, a).endVertex();
+ w.pos((x + 0), (y + height), 0.0D)
+ .color(r, g, b, a).endVertex();
+ w.pos((x + width), (y + height), 0.0D)
+ .color(r, g, b, a).endVertex();
+ w.pos((x + width), (y + 0), 0.0D)
+ .color(r, g, b, a).endVertex();
+ Tessellator.getInstance().draw();
+ }
+
+ @Inject(method="renderItemOverlayIntoGUI", at=@At("RETURN"))
+ public void renderItemOverlayIntoGUI(FontRenderer fr, ItemStack stack, int xPosition, int yPosition, String text, CallbackInfo ci) {
+ if(stack == null) return;
+
+ float damageOverride = ItemCooldowns.getDurabilityOverride(stack);
- if(Keyboard.isKeyDown(Keyboard.KEY_H)) ci.cancel();
+ if(damageOverride >= 0) {
+ float barX = 13.0f - damageOverride * 13.0f;
+ int col = (int)Math.round(255.0D - damageOverride * 255.0D);
+ GlStateManager.disableLighting();
+ GlStateManager.disableDepth();
+ GlStateManager.disableTexture2D();
+ GlStateManager.disableAlpha();
+ GlStateManager.disableBlend();
+
+ Tessellator tessellator = Tessellator.getInstance();
+ WorldRenderer worldrenderer = tessellator.getWorldRenderer();
+ func_181565_a(worldrenderer, xPosition + 2, yPosition + 13, 13, 2, 0, 0, 0, 255);
+ func_181565_a(worldrenderer, xPosition + 2, yPosition + 13, 12, 1, (255 - col) / 4, 64, 0, 255);
+ func_181565_a(worldrenderer, xPosition + 2, yPosition + 13, barX, 1, 255 - col, col, 0, 255);
+
+ GlStateManager.enableAlpha();
+ GlStateManager.enableTexture2D();
+ GlStateManager.enableLighting();
+ GlStateManager.enableDepth();
+ }
}
+
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/options/NEUConfig.java b/src/main/java/io/github/moulberry/notenoughupdates/options/NEUConfig.java
index c2582508..163a35f0 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/options/NEUConfig.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/options/NEUConfig.java
@@ -1,14 +1,66 @@
package io.github.moulberry.notenoughupdates.options;
import com.google.common.collect.Lists;
+import com.google.gson.JsonObject;
import com.google.gson.annotations.Expose;
+import io.github.moulberry.notenoughupdates.NEUEventListener;
+import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import io.github.moulberry.notenoughupdates.core.GuiScreenElementWrapper;
import io.github.moulberry.notenoughupdates.core.config.Config;
+import io.github.moulberry.notenoughupdates.core.config.Position;
import io.github.moulberry.notenoughupdates.core.config.annotations.*;
+import io.github.moulberry.notenoughupdates.core.config.gui.GuiPositionEditor;
+import io.github.moulberry.notenoughupdates.dungeons.GuiDungeonMapEditor;
+import io.github.moulberry.notenoughupdates.miscfeatures.CommissionOverlay;
+import io.github.moulberry.notenoughupdates.textoverlays.TextOverlay;
+import io.github.moulberry.notenoughupdates.textoverlays.TextOverlayStyle;
+import net.minecraft.client.Minecraft;
+import net.minecraftforge.client.ClientCommandHandler;
import java.util.ArrayList;
+import java.util.regex.Pattern;
public class NEUConfig extends Config {
+ @Override
+ public void executeRunnable(int runnableId) {
+ switch (runnableId) {
+ case 0:
+ ClientCommandHandler.instance.executeCommand(Minecraft.getMinecraft().thePlayer, "/neumap");
+ return;
+ case 1:
+ final CommissionOverlay overlay = new CommissionOverlay(NotEnoughUpdates.INSTANCE.config.mining.overlayPosition, () -> {
+ int style = NotEnoughUpdates.INSTANCE.config.mining.overlayStyle;
+ if(style >= 0 && style < TextOverlayStyle.values().length) {
+ return TextOverlayStyle.values()[style];
+ }
+ return TextOverlayStyle.BACKGROUND;
+ });
+ overlay.tick();
+ JsonObject test = null;
+ if(overlay.overlayWidth <= 0 || overlay.overlayHeight <= 0) {
+ Minecraft.getMinecraft().displayGuiScreen(new GuiPositionEditor(
+ NotEnoughUpdates.INSTANCE.config.mining.overlayPosition,
+ 300, 100, () -> {
+ }, () -> {
+ }, () -> NotEnoughUpdates.INSTANCE.openGui = new GuiScreenElementWrapper(
+ new NEUConfigEditor(NotEnoughUpdates.INSTANCE.config))
+ ));
+ } else {
+ Minecraft.getMinecraft().displayGuiScreen(new GuiPositionEditor(
+ NotEnoughUpdates.INSTANCE.config.mining.overlayPosition,
+ overlay.overlayWidth+10, overlay.overlayHeight+10, () -> {
+ overlay.render();
+ NEUEventListener.dontRenderOverlay = CommissionOverlay.class;
+ }, () -> {
+ }, () -> NotEnoughUpdates.INSTANCE.openGui = new GuiScreenElementWrapper(
+ new NEUConfigEditor(NotEnoughUpdates.INSTANCE.config))
+ ));
+ }
+ return;
+ }
+ }
+
@Expose
@Category(
name = "Misc",
@@ -83,6 +135,13 @@ public class NEUConfig extends Config {
@Expose
@Category(
+ name = "Mining",
+ desc = "Mining"
+ )
+ public Mining mining = new Mining();
+
+ @Expose
+ @Category(
name = "NEU Auction House",
desc = "NEU Auction House"
)
@@ -123,6 +182,14 @@ public class NEUConfig extends Config {
)
public BuilderWand builderWand = new BuilderWand();
+
+ @Expose
+ @Category(
+ name = "Dungeon Map",
+ desc = "Dungeon Map"
+ )
+ public DungeonMapOpen dungeonMapOpen = new DungeonMapOpen();
+
@Expose
@Category(
name = "Dungeon Block Overlay",
@@ -671,6 +738,79 @@ public class NEUConfig extends Config {
public int supPower = 11;
}
+ public static class Mining {
+ @Expose
+ @ConfigOption(
+ name = "Puzzler Solver",
+ desc = "Show the correct block to mine for the puzzler puzzle in Dwarven Mines"
+ )
+ @ConfigEditorBoolean
+ public boolean puzzlerSolver = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Titanium Alert",
+ desc = "Show an alert whenever titanium appears nearby"
+ )
+ @ConfigEditorBoolean
+ public boolean titaniumAlert = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Overlay Position",
+ desc = "Change the position of the Dwarven Mines information overlay (commisions, powder & forge statuses)"
+ )
+ @ConfigEditorButton(
+ runnableId = 1,
+ buttonText = "Edit"
+ )
+ public Position overlayPosition = new Position(10, 100);
+
+ @Expose
+ @ConfigOption(
+ name = "Overlay Style",
+ desc = "Change the style of the Dwarven Mines information overlay"
+ )
+ @ConfigEditorDropdown(
+ values = {"Background", "No Shadow", "Shadow", "Full Shadow"}
+ )
+ public int overlayStyle = 0;
+
+ @Expose
+ @ConfigOption(
+ name = "Commissions Overlay",
+ desc = "Show current commissions on the screen while in Dwarven Mines"
+ )
+ @ConfigEditorBoolean
+ public boolean commissionsOverlay = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Powder Overlay",
+ desc = "Show powder count on the screen while in Dwarven Mines"
+ )
+ @ConfigEditorBoolean
+ public boolean powderOverlay = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Forges Overlay",
+ desc = "Show forge statuses on the screen while in Dwarven Mines"
+ )
+ @ConfigEditorBoolean
+ public boolean forgeOverlay = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Hide Empty Forges",
+ desc = "Hide empty forges in the information overlay"
+ )
+ @ConfigEditorBoolean
+ public boolean hideEmptyForges = true;
+
+
+ }
+
public static class NeuAuctionHouse {
@Expose
@ConfigOption(
@@ -855,6 +995,20 @@ public class NEUConfig extends Config {
public String wandOverlayColour = "00:50:64:224:208";
}
+ public static class DungeonMapOpen {
+ @Expose
+ @ConfigOption(
+ name = "Edit Dungeon Map",
+ desc = "The NEU dungeon map has it's own editor (/neumap).\n" +
+ "Click the button on the left to open it"
+ )
+ @ConfigEditorButton(
+ runnableId = 0,
+ buttonText = "Edit"
+ )
+ public int editDungeonMap = 0;
+ }
+
public static class DungeonBlock {
@Expose
@ConfigOption(
@@ -1218,17 +1372,10 @@ public class NEUConfig extends Config {
@Expose
@ConfigOption(
- name = "Center X (%)",
- desc = "The horizontal position of the map"
- )
- public double dmCenterX = 8.5;
-
- @Expose
- @ConfigOption(
- name = "Center Y (%)",
- desc = "The vertical position of the map"
+ name = "Position",
+ desc = "The position of the map"
)
- public double dmCenterY = 15.0;
+ public Position dmPosition = new Position(10, 10);
}
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/options/NEUConfigEditor.java b/src/main/java/io/github/moulberry/notenoughupdates/options/NEUConfigEditor.java
index 2a8a2c04..d870e858 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/options/NEUConfigEditor.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/options/NEUConfigEditor.java
@@ -39,7 +39,7 @@ public class NEUConfigEditor extends GuiElement {
};
private static final String[] socialsLink = new String[] {
"https://discord.gg/moulberry",
- "https://github.com/Moulberry/Hychat",
+ "https://github.com/Moulberry/NotEnoughUpdates",
"https://twitter.com/moulberry/",
"https://www.youtube.com/channel/UCPh-OKmRSS3IQi9p6YppLcw",
"https://patreon.com/moulberry"
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/ProfileViewer.java b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/ProfileViewer.java
index 724c0953..b9f9b03d 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/ProfileViewer.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/profileviewer/ProfileViewer.java
@@ -1047,9 +1047,8 @@ public class ProfileViewer {
}
public Profile getProfileReset(String uuid, Consumer<Profile> callback) {
- Profile profile = getProfile(uuid, callback);
- profile.resetCache();
- return profile;
+ if(uuidToProfileMap.containsKey(uuid)) uuidToProfileMap.get(uuid).resetCache();
+ return getProfile(uuid, callback);
}
private static JsonObject resourceCollection = null;
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/textoverlays/TextOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/textoverlays/TextOverlay.java
new file mode 100644
index 00000000..f111f20a
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/textoverlays/TextOverlay.java
@@ -0,0 +1,90 @@
+package io.github.moulberry.notenoughupdates.textoverlays;
+
+import io.github.moulberry.notenoughupdates.core.config.Position;
+import io.github.moulberry.notenoughupdates.core.util.StringUtils;
+import io.github.moulberry.notenoughupdates.util.Utils;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.Gui;
+import net.minecraft.client.gui.ScaledResolution;
+
+import java.awt.*;
+import java.util.List;
+import java.util.function.Supplier;
+
+public abstract class TextOverlay {
+
+ private Position position;
+ private Supplier<TextOverlayStyle> styleSupplier;
+ public int overlayWidth = -1;
+ public int overlayHeight = -1;
+ public List<String> overlayStrings = null;
+
+ private static final int PADDING_X = 5;
+ private static final int PADDING_Y = 5;
+
+ public TextOverlay(Position position, Supplier<TextOverlayStyle> styleSupplier) {
+ this.position = position;
+ this.styleSupplier = styleSupplier;
+ }
+
+ public void tick() {
+ update();
+
+ if(overlayStrings != null) {
+ overlayHeight = 0;
+ overlayWidth = 0;
+ for(String s : overlayStrings) {
+ if(s == null) {
+ overlayHeight += 3;
+ continue;
+ }
+ int sWidth = Minecraft.getMinecraft().fontRendererObj.getStringWidth(s);
+ if(sWidth > overlayWidth) {
+ overlayWidth = sWidth;
+ }
+ overlayHeight += 10;
+ }
+ overlayHeight -= 2;
+ }
+ }
+
+ public abstract void update();
+
+ public void render() {
+ if(overlayStrings != null) {
+ ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft());
+
+ int x = position.getAbsX(scaledResolution);
+ int y = position.getAbsY(scaledResolution);
+
+ TextOverlayStyle style = styleSupplier.get();
+
+ if(style == TextOverlayStyle.BACKGROUND) Gui.drawRect(x, y, x+overlayWidth+PADDING_X*2, y+overlayHeight+PADDING_Y*2, 0x80000000);
+
+ int yOff = 0;
+ for(String s : overlayStrings) {
+ if(s == null) {
+ yOff += 3;
+ } else {
+ if(style == TextOverlayStyle.FULL_SHADOW) {
+ String clean = Utils.cleanColourNotModifiers(s);
+ for(int xO=-2; xO<=2; xO++) {
+ for(int yO=-2; yO<=2; yO++) {
+ if(Math.abs(xO) != Math.abs(yO)) {
+ Minecraft.getMinecraft().fontRendererObj.drawString(clean,
+ x+PADDING_X+xO/2f, y+PADDING_Y+yOff+yO/2f,
+ new Color(0, 0, 0, 200/Math.max(Math.abs(xO), Math.abs(yO))).getRGB(), false);
+ }
+ }
+ }
+ }
+ Minecraft.getMinecraft().fontRendererObj.drawString(s,
+ x+PADDING_X, y+PADDING_Y+yOff, 0xffffff, style == TextOverlayStyle.MC_SHADOW);
+
+ yOff += 10;
+ }
+ }
+ }
+ }
+
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/textoverlays/TextOverlayStyle.java b/src/main/java/io/github/moulberry/notenoughupdates/textoverlays/TextOverlayStyle.java
new file mode 100644
index 00000000..7bd620b6
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/textoverlays/TextOverlayStyle.java
@@ -0,0 +1,10 @@
+package io.github.moulberry.notenoughupdates.textoverlays;
+
+public enum TextOverlayStyle {
+
+ BACKGROUND,
+ NO_SHADOW,
+ MC_SHADOW,
+ FULL_SHADOW
+
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/ReverseWorldRenderer.java b/src/main/java/io/github/moulberry/notenoughupdates/util/ReverseWorldRenderer.java
new file mode 100644
index 00000000..d9d9dd90
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/util/ReverseWorldRenderer.java
@@ -0,0 +1,552 @@
+package io.github.moulberry.notenoughupdates.util;
+
+import com.google.common.primitives.Floats;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.FloatBuffer;
+import java.nio.IntBuffer;
+import java.nio.ShortBuffer;
+import java.util.Arrays;
+import java.util.BitSet;
+import java.util.Comparator;
+
+import net.minecraft.client.renderer.GLAllocation;
+import net.minecraft.client.renderer.vertex.VertexFormat;
+import net.minecraft.client.renderer.vertex.VertexFormatElement;
+import net.minecraft.util.MathHelper;
+import net.minecraftforge.fml.relauncher.Side;
+import net.minecraftforge.fml.relauncher.SideOnly;
+import org.apache.logging.log4j.LogManager;
+
+@SideOnly(Side.CLIENT)
+public class ReverseWorldRenderer {
+ private ByteBuffer byteBuffer;
+ private IntBuffer rawIntBuffer;
+ private ShortBuffer rawShortBuffer;
+ private FloatBuffer rawFloatBuffer;
+ private int vertexCount;
+ private VertexFormatElement vertexFormatElement;
+ private int vertexFormatIndex;
+ /**
+ * None
+ */
+ private boolean noColor;
+ private int drawMode;
+ private double xOffset;
+ private double yOffset;
+ private double zOffset;
+ private VertexFormat vertexFormat;
+ private boolean isDrawing;
+
+ public ReverseWorldRenderer(int bufferSizeIn) {
+ this.byteBuffer = GLAllocation.createDirectByteBuffer(bufferSizeIn * 4);
+ this.rawIntBuffer = this.byteBuffer.asIntBuffer();
+ this.rawShortBuffer = this.byteBuffer.asShortBuffer();
+ this.rawFloatBuffer = this.byteBuffer.asFloatBuffer();
+ }
+
+ private void growBuffer(int p_181670_1_) {
+ if (p_181670_1_ > this.rawIntBuffer.remaining()) {
+ int i = this.byteBuffer.capacity();
+ int j = i % 2097152;
+ int k = j + (((this.rawIntBuffer.position() + p_181670_1_) * 4 - j) / 2097152 + 1) * 2097152;
+ LogManager.getLogger().warn("Needed to grow BufferBuilder buffer: Old size " + i + " bytes, new size " + k + " bytes.");
+ int l = this.rawIntBuffer.position();
+ ByteBuffer bytebuffer = GLAllocation.createDirectByteBuffer(k);
+ this.byteBuffer.position(0);
+ bytebuffer.put(this.byteBuffer);
+ bytebuffer.rewind();
+ this.byteBuffer = bytebuffer;
+ this.rawFloatBuffer = this.byteBuffer.asFloatBuffer().asReadOnlyBuffer();
+ this.rawIntBuffer = this.byteBuffer.asIntBuffer();
+ this.rawIntBuffer.position(l);
+ this.rawShortBuffer = this.byteBuffer.asShortBuffer();
+ this.rawShortBuffer.position(l << 1);
+ }
+ }
+
+ public void sortVertexData(float p_181674_1_, float p_181674_2_, float p_181674_3_) {
+ int i = this.vertexCount / 4;
+ final float[] afloat = new float[i];
+
+ for (int j = 0; j < i; ++j) {
+ afloat[j] = func_181665_a(this.rawFloatBuffer, (float) ((double) p_181674_1_ + this.xOffset), (float) ((double) p_181674_2_ + this.yOffset), (float) ((double) p_181674_3_ + this.zOffset), this.vertexFormat.func_181719_f(), j * this.vertexFormat.getNextOffset());
+ }
+
+ Integer[] ainteger = new Integer[i];
+
+ for (int k = 0; k < ainteger.length; ++k) {
+ ainteger[k] = Integer.valueOf(k);
+ }
+
+ Arrays.sort(ainteger, new Comparator<Integer>() {
+ public int compare(Integer p_compare_1_, Integer p_compare_2_) {
+ return -Floats.compare(afloat[p_compare_2_.intValue()], afloat[p_compare_1_.intValue()]);
+ }
+ });
+ BitSet bitset = new BitSet();
+ int l = this.vertexFormat.getNextOffset();
+ int[] aint = new int[l];
+
+ for (int l1 = 0; (l1 = bitset.nextClearBit(l1)) < ainteger.length; ++l1) {
+ int i1 = ainteger[l1].intValue();
+
+ if (i1 != l1) {
+ this.rawIntBuffer.limit(i1 * l + l);
+ this.rawIntBuffer.position(i1 * l);
+ this.rawIntBuffer.get(aint);
+ int j1 = i1;
+
+ for (int k1 = ainteger[i1].intValue(); j1 != l1; k1 = ainteger[k1].intValue()) {
+ this.rawIntBuffer.limit(k1 * l + l);
+ this.rawIntBuffer.position(k1 * l);
+ IntBuffer intbuffer = this.rawIntBuffer.slice();
+ this.rawIntBuffer.limit(j1 * l + l);
+ this.rawIntBuffer.position(j1 * l);
+ this.rawIntBuffer.put(intbuffer);
+ bitset.set(j1);
+ j1 = k1;
+ }
+
+ this.rawIntBuffer.limit(l1 * l + l);
+ this.rawIntBuffer.position(l1 * l);
+ this.rawIntBuffer.put(aint);
+ }
+
+ bitset.set(l1);
+ }
+ }
+
+ public State getVertexState() {
+ this.rawIntBuffer.rewind();
+ int i = this.getBufferSize();
+ this.rawIntBuffer.limit(i);
+ int[] aint = new int[i];
+ this.rawIntBuffer.get(aint);
+ this.rawIntBuffer.limit(this.rawIntBuffer.capacity());
+ this.rawIntBuffer.position(i);
+ return new State(aint, new VertexFormat(this.vertexFormat));
+ }
+
+ private int getBufferSize() {
+ return this.vertexCount * this.vertexFormat.func_181719_f();
+ }
+
+ private static float func_181665_a(FloatBuffer p_181665_0_, float p_181665_1_, float p_181665_2_, float p_181665_3_, int p_181665_4_, int p_181665_5_) {
+ float f = p_181665_0_.get(p_181665_5_ + p_181665_4_ * 0 + 0);
+ float f1 = p_181665_0_.get(p_181665_5_ + p_181665_4_ * 0 + 1);
+ float f2 = p_181665_0_.get(p_181665_5_ + p_181665_4_ * 0 + 2);
+ float f3 = p_181665_0_.get(p_181665_5_ + p_181665_4_ * 1 + 0);
+ float f4 = p_181665_0_.get(p_181665_5_ + p_181665_4_ * 1 + 1);
+ float f5 = p_181665_0_.get(p_181665_5_ + p_181665_4_ * 1 + 2);
+ float f6 = p_181665_0_.get(p_181665_5_ + p_181665_4_ * 2 + 0);
+ float f7 = p_181665_0_.get(p_181665_5_ + p_181665_4_ * 2 + 1);
+ float f8 = p_181665_0_.get(p_181665_5_ + p_181665_4_ * 2 + 2);
+ float f9 = p_181665_0_.get(p_181665_5_ + p_181665_4_ * 3 + 0);
+ float f10 = p_181665_0_.get(p_181665_5_ + p_181665_4_ * 3 + 1);
+ float f11 = p_181665_0_.get(p_181665_5_ + p_181665_4_ * 3 + 2);
+ float f12 = (f + f3 + f6 + f9) * 0.25F - p_181665_1_;
+ float f13 = (f1 + f4 + f7 + f10) * 0.25F - p_181665_2_;
+ float f14 = (f2 + f5 + f8 + f11) * 0.25F - p_181665_3_;
+ return f12 * f12 + f13 * f13 + f14 * f14;
+ }
+
+ public void setVertexState(State state) {
+ this.rawIntBuffer.clear();
+ this.growBuffer(state.getRawBuffer().length);
+ this.rawIntBuffer.put(state.getRawBuffer());
+ this.vertexCount = state.getVertexCount();
+ this.vertexFormat = new VertexFormat(state.getVertexFormat());
+ }
+
+ public void reset() {
+ this.vertexCount = 0;
+ this.vertexFormatElement = null;
+ this.vertexFormatIndex = 0;
+ }
+
+ public void begin(int glMode, VertexFormat format) {
+ if (this.isDrawing) {
+ throw new IllegalStateException("Already building!");
+ } else {
+ this.isDrawing = true;
+ this.reset();
+ this.drawMode = glMode;
+ this.vertexFormat = format;
+ this.vertexFormatElement = format.getElement(this.vertexFormatIndex);
+ this.noColor = false;
+ this.byteBuffer.limit(this.byteBuffer.capacity());
+ }
+ }
+
+ public ReverseWorldRenderer tex(double u, double v) {
+ int i = this.vertexCount * this.vertexFormat.getNextOffset() + this.vertexFormat.func_181720_d(this.vertexFormatIndex);
+
+ switch (this.vertexFormatElement.getType()) {
+ case FLOAT:
+ this.byteBuffer.putFloat(i, (float) u);
+ this.byteBuffer.putFloat(i + 4, (float) v);
+ break;
+ case UINT:
+ case INT:
+ this.byteBuffer.putInt(i, (int) u);
+ this.byteBuffer.putInt(i + 4, (int) v);
+ break;
+ case USHORT:
+ case SHORT:
+ this.byteBuffer.putShort(i, (short) ((int) v));
+ this.byteBuffer.putShort(i + 2, (short) ((int) u));
+ break;
+ case UBYTE:
+ case BYTE:
+ this.byteBuffer.put(i, (byte) ((int) v));
+ this.byteBuffer.put(i + 1, (byte) ((int) u));
+ }
+
+ this.nextVertexFormatIndex();
+ return this;
+ }
+
+ public ReverseWorldRenderer lightmap(int p_181671_1_, int p_181671_2_) {
+ int i = this.vertexCount * this.vertexFormat.getNextOffset() + this.vertexFormat.func_181720_d(this.vertexFormatIndex);
+
+ switch (this.vertexFormatElement.getType()) {
+ case FLOAT:
+ this.byteBuffer.putFloat(i, (float) p_181671_1_);
+ this.byteBuffer.putFloat(i + 4, (float) p_181671_2_);
+ break;
+ case UINT:
+ case INT:
+ this.byteBuffer.putInt(i, p_181671_1_);
+ this.byteBuffer.putInt(i + 4, p_181671_2_);
+ break;
+ case USHORT:
+ case SHORT:
+ this.byteBuffer.putShort(i, (short) p_181671_2_);
+ this.byteBuffer.putShort(i + 2, (short) p_181671_1_);
+ break;
+ case UBYTE:
+ case BYTE:
+ this.byteBuffer.put(i, (byte) p_181671_2_);
+ this.byteBuffer.put(i + 1, (byte) p_181671_1_);
+ }
+
+ this.nextVertexFormatIndex();
+ return this;
+ }
+
+ public void putBrightness4(int p_178962_1_, int p_178962_2_, int p_178962_3_, int p_178962_4_) {
+ int i = (this.vertexCount - 4) * this.vertexFormat.func_181719_f() + this.vertexFormat.getUvOffsetById(1) / 4;
+ int j = this.vertexFormat.getNextOffset() >> 2;
+ this.rawIntBuffer.put(i, p_178962_1_);
+ this.rawIntBuffer.put(i + j, p_178962_2_);
+ this.rawIntBuffer.put(i + j * 2, p_178962_3_);
+ this.rawIntBuffer.put(i + j * 3, p_178962_4_);
+ }
+
+ public void putPosition(double x, double y, double z) {
+ int i = this.vertexFormat.func_181719_f();
+ int j = (this.vertexCount - 4) * i;
+
+ for (int k = 0; k < 4; ++k) {
+ int l = j + k * i;
+ int i1 = l + 1;
+ int j1 = i1 + 1;
+ this.rawIntBuffer.put(l, Float.floatToRawIntBits((float) (x + this.xOffset) + Float.intBitsToFloat(this.rawIntBuffer.get(l))));
+ this.rawIntBuffer.put(i1, Float.floatToRawIntBits((float) (y + this.yOffset) + Float.intBitsToFloat(this.rawIntBuffer.get(i1))));
+ this.rawIntBuffer.put(j1, Float.floatToRawIntBits((float) (z + this.zOffset) + Float.intBitsToFloat(this.rawIntBuffer.get(j1))));
+ }
+ }
+
+ /**
+ * Takes in the pass the call list is being requested for. Args: renderPass
+ */
+ public int getColorIndex(int p_78909_1_) {
+ return ((this.vertexCount - p_78909_1_) * this.vertexFormat.getNextOffset() + this.vertexFormat.getColorOffset()) / 4;
+ }
+
+ public void putColorMultiplier(float red, float green, float blue, int p_178978_4_) {
+ int i = this.getColorIndex(p_178978_4_);
+ int j = -1;
+
+ if (!this.noColor) {
+ j = this.rawIntBuffer.get(i);
+
+ if (ByteOrder.nativeOrder() == ByteOrder.LITTLE_ENDIAN) {
+ int k = (int) ((float) (j & 255) * red);
+ int l = (int) ((float) (j >> 8 & 255) * green);
+ int i1 = (int) ((float) (j >> 16 & 255) * blue);
+ j = j & -16777216;
+ j = j | i1 << 16 | l << 8 | k;
+ } else {
+ int j1 = (int) ((float) (j >> 24 & 255) * red);
+ int k1 = (int) ((float) (j >> 16 & 255) * green);
+ int l1 = (int) ((float) (j >> 8 & 255) * blue);
+ j = j & 255;
+ j = j | j1 << 24 | k1 << 16 | l1 << 8;
+ }
+ }
+
+ this.rawIntBuffer.put(i, j);
+ }
+
+ private void putColor(int argb, int p_178988_2_) {
+ int i = this.getColorIndex(p_178988_2_);
+ int j = argb >> 16 & 255;
+ int k = argb >> 8 & 255;
+ int l = argb & 255;
+ int i1 = argb >> 24 & 255;
+ this.putColorRGBA(i, j, k, l, i1);
+ }
+
+ public void putColorRGB_F(float red, float green, float blue, int p_178994_4_) {
+ int i = this.getColorIndex(p_178994_4_);
+ int j = MathHelper.clamp_int((int) (red * 255.0F), 0, 255);
+ int k = MathHelper.clamp_int((int) (green * 255.0F), 0, 255);
+ int l = MathHelper.clamp_int((int) (blue * 255.0F), 0, 255);
+ this.putColorRGBA(i, j, k, l, 255);
+ }
+
+ public void putColorRGBA(int index, int red, int p_178972_3_, int p_178972_4_, int p_178972_5_) {
+ if (ByteOrder.nativeOrder() == ByteOrder.LITTLE_ENDIAN) {
+ this.rawIntBuffer.put(index, p_178972_5_ << 24 | p_178972_4_ << 16 | p_178972_3_ << 8 | red);
+ } else {
+ this.rawIntBuffer.put(index, red << 24 | p_178972_3_ << 16 | p_178972_4_ << 8 | p_178972_5_);
+ }
+ }
+
+ /**
+ * Disabels color processing.
+ */
+ public void noColor() {
+ this.noColor = true;
+ }
+
+ public ReverseWorldRenderer color(float red, float green, float blue, float alpha) {
+ return this.color((int) (red * 255.0F), (int) (green * 255.0F), (int) (blue * 255.0F), (int) (alpha * 255.0F));
+ }
+
+ public ReverseWorldRenderer color(int red, int green, int blue, int alpha) {
+ if (this.noColor) {
+ return this;
+ } else {
+ int i = this.vertexCount * this.vertexFormat.getNextOffset() + this.vertexFormat.func_181720_d(this.vertexFormatIndex);
+
+ switch (this.vertexFormatElement.getType()) {
+ case FLOAT:
+ this.byteBuffer.putFloat(i, (float) red / 255.0F);
+ this.byteBuffer.putFloat(i + 4, (float) green / 255.0F);
+ this.byteBuffer.putFloat(i + 8, (float) blue / 255.0F);
+ this.byteBuffer.putFloat(i + 12, (float) alpha / 255.0F);
+ break;
+ case UINT:
+ case INT:
+ this.byteBuffer.putFloat(i, (float) red);
+ this.byteBuffer.putFloat(i + 4, (float) green);
+ this.byteBuffer.putFloat(i + 8, (float) blue);
+ this.byteBuffer.putFloat(i + 12, (float) alpha);
+ break;
+ case USHORT:
+ case SHORT:
+ this.byteBuffer.putShort(i, (short) red);
+ this.byteBuffer.putShort(i + 2, (short) green);
+ this.byteBuffer.putShort(i + 4, (short) blue);
+ this.byteBuffer.putShort(i + 6, (short) alpha);
+ break;
+ case UBYTE:
+ case BYTE:
+
+ if (ByteOrder.nativeOrder() == ByteOrder.LITTLE_ENDIAN) {
+ this.byteBuffer.put(i, (byte) red);
+ this.byteBuffer.put(i + 1, (byte) green);
+ this.byteBuffer.put(i + 2, (byte) blue);
+ this.byteBuffer.put(i + 3, (byte) alpha);
+ } else {
+ this.byteBuffer.put(i, (byte) alpha);
+ this.byteBuffer.put(i + 1, (byte) blue);
+ this.byteBuffer.put(i + 2, (byte) green);
+ this.byteBuffer.put(i + 3, (byte) red);
+ }
+ }
+
+ this.nextVertexFormatIndex();
+ return this;
+ }
+ }
+
+ public void addVertexData(int[] vertexData) {
+ this.growBuffer(vertexData.length);
+ this.rawIntBuffer.position(this.getBufferSize());
+ this.rawIntBuffer.put(vertexData);
+ this.vertexCount += vertexData.length / this.vertexFormat.func_181719_f();
+ }
+
+ public void endVertex() {
+ ++this.vertexCount;
+ this.growBuffer(this.vertexFormat.func_181719_f());
+ }
+
+ public ReverseWorldRenderer pos(double x, double y, double z) {
+ int i = this.vertexCount * this.vertexFormat.getNextOffset() + this.vertexFormat.func_181720_d(this.vertexFormatIndex);
+
+ switch (this.vertexFormatElement.getType()) {
+ case FLOAT:
+ this.byteBuffer.putFloat(i, (float) (x + this.xOffset));
+ this.byteBuffer.putFloat(i + 4, (float) (y + this.yOffset));
+ this.byteBuffer.putFloat(i + 8, (float) (z + this.zOffset));
+ break;
+ case UINT:
+ case INT:
+ this.byteBuffer.putInt(i, Float.floatToRawIntBits((float) (x + this.xOffset)));
+ this.byteBuffer.putInt(i + 4, Float.floatToRawIntBits((float) (y + this.yOffset)));
+ this.byteBuffer.putInt(i + 8, Float.floatToRawIntBits((float) (z + this.zOffset)));
+ break;
+ case USHORT:
+ case SHORT:
+ this.byteBuffer.putShort(i, (short) ((int) (x + this.xOffset)));
+ this.byteBuffer.putShort(i + 2, (short) ((int) (y + this.yOffset)));
+ this.byteBuffer.putShort(i + 4, (short) ((int) (z + this.zOffset)));
+ break;
+ case UBYTE:
+ case BYTE:
+ this.byteBuffer.put(i, (byte) ((int) (x + this.xOffset)));
+ this.byteBuffer.put(i + 1, (byte) ((int) (y + this.yOffset)));
+ this.byteBuffer.put(i + 2, (byte) ((int) (z + this.zOffset)));
+ }
+
+ this.nextVertexFormatIndex();
+ return this;
+ }
+
+ public void putNormal(float x, float y, float z) {
+ int i = (byte) ((int) (x * 127.0F)) & 255;
+ int j = (byte) ((int) (y * 127.0F)) & 255;
+ int k = (byte) ((int) (z * 127.0F)) & 255;
+ int l = i | j << 8 | k << 16;
+ int i1 = this.vertexFormat.getNextOffset() >> 2;
+ int j1 = (this.vertexCount - 4) * i1 + this.vertexFormat.getNormalOffset() / 4;
+ this.rawIntBuffer.put(j1, l);
+ this.rawIntBuffer.put(j1 + i1, l);
+ this.rawIntBuffer.put(j1 + i1 * 2, l);
+ this.rawIntBuffer.put(j1 + i1 * 3, l);
+ }
+
+ private void nextVertexFormatIndex() {
+ ++this.vertexFormatIndex;
+ this.vertexFormatIndex %= this.vertexFormat.getElementCount();
+ this.vertexFormatElement = this.vertexFormat.getElement(this.vertexFormatIndex);
+
+ if (this.vertexFormatElement.getUsage() == VertexFormatElement.EnumUsage.PADDING) {
+ this.nextVertexFormatIndex();
+ }
+ }
+
+ public ReverseWorldRenderer normal(float p_181663_1_, float p_181663_2_, float p_181663_3_) {
+ int i = this.vertexCount * this.vertexFormat.getNextOffset() + this.vertexFormat.func_181720_d(this.vertexFormatIndex);
+
+ switch (this.vertexFormatElement.getType()) {
+ case FLOAT:
+ this.byteBuffer.putFloat(i, p_181663_1_);
+ this.byteBuffer.putFloat(i + 4, p_181663_2_);
+ this.byteBuffer.putFloat(i + 8, p_181663_3_);
+ break;
+ case UINT:
+ case INT:
+ this.byteBuffer.putInt(i, (int) p_181663_1_);
+ this.byteBuffer.putInt(i + 4, (int) p_181663_2_);
+ this.byteBuffer.putInt(i + 8, (int) p_181663_3_);
+ break;
+ case USHORT:
+ case SHORT:
+ this.byteBuffer.putShort(i, (short) ((int) (p_181663_1_ * 32767) & 65535));
+ this.byteBuffer.putShort(i + 2, (short) ((int) (p_181663_2_ * 32767) & 65535));
+ this.byteBuffer.putShort(i + 4, (short) ((int) (p_181663_3_ * 32767) & 65535));
+ break;
+ case UBYTE:
+ case BYTE:
+ this.byteBuffer.put(i, (byte) ((int) (p_181663_1_ * 127) & 255));
+ this.byteBuffer.put(i + 1, (byte) ((int) (p_181663_2_ * 127) & 255));
+ this.byteBuffer.put(i + 2, (byte) ((int) (p_181663_3_ * 127) & 255));
+ }
+
+ this.nextVertexFormatIndex();
+ return this;
+ }
+
+ public void setTranslation(double x, double y, double z) {
+ this.xOffset = x;
+ this.yOffset = y;
+ this.zOffset = z;
+ }
+
+ public void finishDrawing() {
+ if (!this.isDrawing) {
+ throw new IllegalStateException("Not building!");
+ } else {
+ this.isDrawing = false;
+ this.byteBuffer.position(0);
+ this.byteBuffer.limit(this.getBufferSize() * 4);
+ }
+ }
+
+ public ByteBuffer getByteBuffer() {
+ return this.byteBuffer;
+ }
+
+ public VertexFormat getVertexFormat() {
+ return this.vertexFormat;
+ }
+
+ public int getVertexCount() {
+ return this.vertexCount;
+ }
+
+ public int getDrawMode() {
+ return this.drawMode;
+ }
+
+ public void putColor4(int argb) {
+ for (int i = 0; i < 4; ++i) {
+ this.putColor(argb, i + 1);
+ }
+ }
+
+ public void putColorRGB_F4(float red, float green, float blue) {
+ for (int i = 0; i < 4; ++i) {
+ this.putColorRGB_F(red, green, blue, i + 1);
+ }
+ }
+
+ public void checkAndGrow() {
+ this.growBuffer(vertexFormat.getNextOffset()/* / 4 * 4 */);
+ }
+
+ public boolean isColorDisabled() {
+ /** None */
+ return noColor;
+ }
+
+ @SideOnly(Side.CLIENT)
+ public class State {
+ private final int[] stateRawBuffer;
+ private final VertexFormat stateVertexFormat;
+
+ public State(int[] buffer, VertexFormat format) {
+ this.stateRawBuffer = buffer;
+ this.stateVertexFormat = format;
+ }
+
+ public int[] getRawBuffer() {
+ return this.stateRawBuffer;
+ }
+
+ public int getVertexCount() {
+ return this.stateRawBuffer.length / this.stateVertexFormat.func_181719_f();
+ }
+
+ public VertexFormat getVertexFormat() {
+ return this.stateVertexFormat;
+ }
+ }
+} \ No newline at end of file
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/Utils.java b/src/main/java/io/github/moulberry/notenoughupdates/util/Utils.java
index f8621f2b..e40edd4f 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/util/Utils.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/util/Utils.java
@@ -518,11 +518,20 @@ public class Utils {
}
public static void renderShadowedString(String str, float x, float y, int maxLength) {
+ int strLen = Minecraft.getMinecraft().fontRendererObj.getStringWidth(str);
+ float factor;
+ if(maxLength < 0) {
+ factor = 1;
+ } else {
+ factor = maxLength/(float)strLen;
+ factor = Math.min(1, factor);
+ }
+
for(int xOff=-2; xOff<=2; xOff++) {
for(int yOff=-2; yOff<=2; yOff++) {
if(Math.abs(xOff) != Math.abs(yOff)) {
Utils.drawStringCenteredScaledMaxWidth(Utils.cleanColourNotModifiers(str), Minecraft.getMinecraft().fontRendererObj,
- x+xOff/2f, y+4+yOff/2f, false, maxLength,
+ x+xOff/2f*factor, y+4+yOff/2f*factor, false, maxLength,
new Color(0, 0, 0, 200/Math.max(Math.abs(xOff), Math.abs(yOff))).getRGB());
}
}
diff --git a/src/main/resources/assets/notenoughupdates/capes/furf.png b/src/main/resources/assets/notenoughupdates/capes/furf.png
index 70f8f98a..ce9f4c19 100644
--- a/src/main/resources/assets/notenoughupdates/capes/furf.png
+++ b/src/main/resources/assets/notenoughupdates/capes/furf.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/capes/furf_preview.png b/src/main/resources/assets/notenoughupdates/capes/furf_preview.png
new file mode 100644
index 00000000..a4ee6851
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/capes/furf_preview.png
Binary files differ