aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Update Notes/2.1.md1
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java18
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/NEUOverlay.java17
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/auction/APIManager.java1
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/commands/Commands.java11
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscgui/GuiItemRecipe.java4
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinEntity.java24
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinEntityAgeable.java21
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinEntityPlayer.java40
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/recipes/CraftingRecipe.java7
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/recipes/ForgeRecipe.java9
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/recipes/NeuRecipe.java17
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/recipes/VillagerTradeRecipe.java145
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/util/SBInfo.java110
-rw-r--r--src/main/resources/assets/notenoughupdates/dreamskin.pngbin0 -> 220 bytes
-rw-r--r--src/main/resources/assets/notenoughupdates/textures/gui/villager_recipe.pngbin0 -> 8633 bytes
-rw-r--r--src/main/resources/mixins.notenoughupdates.json73
17 files changed, 432 insertions, 66 deletions
diff --git a/Update Notes/2.1.md b/Update Notes/2.1.md
index ee124398..d6618bd3 100644
--- a/Update Notes/2.1.md
+++ b/Update Notes/2.1.md
@@ -15,6 +15,7 @@
- [Price graph for items on /ah and /bz](https://cdn.discordapp.com/attachments/896407218151366687/926968296929107999/unknown.png) - DeDiamondPro
### **Minor Changes:**
- Add built-in recipes for forge crafts - nea89
+- Add Stranded Villager Trades to the item list - nea89
- Make cata xp in /pv be calculated on how many runs you have and shows master mode xp rates
- Hide mine waypoints when at location setting - Lulonaut
- Added some info panels to some settings in /neu
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java b/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java
index 614884d9..bf3a0714 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java
@@ -3,7 +3,6 @@ package io.github.moulberry.notenoughupdates;
import com.google.gson.*;
import io.github.moulberry.notenoughupdates.auction.APIManager;
import io.github.moulberry.notenoughupdates.miscgui.GuiItemRecipe;
-import io.github.moulberry.notenoughupdates.options.NEUConfig;
import io.github.moulberry.notenoughupdates.recipes.CraftingOverlay;
import io.github.moulberry.notenoughupdates.recipes.CraftingRecipe;
import io.github.moulberry.notenoughupdates.recipes.Ingredient;
@@ -33,6 +32,7 @@ import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
+import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
@@ -418,10 +418,18 @@ public class NEUManager {
return recipesMap.getOrDefault(internalName, Collections.emptySet());
}
+ public List<NeuRecipe> getAvailableRecipesFor(String internalname) {
+ return getRecipesFor(internalname).stream().filter(NeuRecipe::isAvailable).collect(Collectors.toList());
+ }
+
public Set<NeuRecipe> getUsagesFor(String internalName) {
return usagesMap.getOrDefault(internalName, Collections.emptySet());
}
+ public List<NeuRecipe> getAvailableUsagesFor(String internalname) {
+ return getUsagesFor(internalname).stream().filter(NeuRecipe::isAvailable).collect(Collectors.toList());
+ }
+
/**
* Searches a string for a query. This method is used to mimic the behaviour of the more complex map-based search
* function. This method is used for the chest-item-search feature.
@@ -952,19 +960,19 @@ public class NEUManager {
public boolean displayGuiItemUsages(String internalName) {
if (!usagesMap.containsKey(internalName)) return false;
- Set<NeuRecipe> usages = usagesMap.get(internalName);
+ List<NeuRecipe> usages = getAvailableUsagesFor(internalName);
if (usages.isEmpty()) return false;
Minecraft.getMinecraft().displayGuiScreen(
- new GuiItemRecipe("Item Usages", new ArrayList<>(usages), this));
+ new GuiItemRecipe("Item Usages", usages, this));
return true;
}
public boolean displayGuiItemRecipe(String internalName, String text) {
if (!recipesMap.containsKey(internalName)) return false;
- Set<NeuRecipe> recipes = recipesMap.get(internalName);
+ List<NeuRecipe> recipes = getAvailableRecipesFor(internalName);
if (recipes.isEmpty()) return false;
Minecraft.getMinecraft().displayGuiScreen(
- new GuiItemRecipe(text != null ? text : "Item Recipe", new ArrayList<>(recipes), this));
+ new GuiItemRecipe(text != null ? text : "Item Recipe", recipes, this));
return true;
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NEUOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/NEUOverlay.java
index 1fbffd5f..04ed9964 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/NEUOverlay.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/NEUOverlay.java
@@ -62,9 +62,8 @@ import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL14;
import org.lwjgl.util.vector.Vector2f;
-import java.awt.*;
+import java.awt.Color;
import java.lang.reflect.InvocationTargetException;
-import java.util.List;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
@@ -2345,14 +2344,10 @@ public class NEUOverlay extends Gui {
ItemPriceInformation.addToTooltip(text, internalname, stack);
}
- boolean hasClick = false;
- boolean hasInfo = false;
- if (json.has("clickcommand") && !json.get("clickcommand").getAsString().isEmpty()) {
- hasClick = true;
- }
- if (json.has("info") && json.get("info").getAsJsonArray().size() > 0) {
- hasInfo = true;
- }
+ boolean hasClick =
+ (json.has("clickcommand") && !json.get("clickcommand").getAsString().isEmpty())
+ || !manager.getAvailableRecipesFor(internalname).isEmpty();
+ boolean hasInfo = json.has("info") && json.get("info").getAsJsonArray().size() > 0;
if (hasClick || hasInfo) text.add("");
if (hasClick)
@@ -2685,4 +2680,4 @@ public class NEUOverlay extends Gui {
public float getInfoPaneOffsetFactor() {
return infoPaneOffsetFactor.getValue() * getWidthMult();
}
-} \ No newline at end of file
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/auction/APIManager.java b/src/main/java/io/github/moulberry/notenoughupdates/auction/APIManager.java
index d0b4a7f5..9455eb64 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/auction/APIManager.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/auction/APIManager.java
@@ -799,6 +799,7 @@ public class APIManager {
if (recipes != null)
RECIPE_ITER:
for (NeuRecipe recipe : recipes) {
+ if (recipe.hasVariableCost() || !recipe.shouldUseForCraftCost()) continue;
float craftPrice = 0;
for (Ingredient i : recipe.getIngredients()) {
if (i.isCoins()) {
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/commands/Commands.java b/src/main/java/io/github/moulberry/notenoughupdates/commands/Commands.java
index d3fd7e0c..50662a80 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/commands/Commands.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/commands/Commands.java
@@ -14,13 +14,13 @@ import io.github.moulberry.notenoughupdates.cosmetics.GuiCosmetics;
import io.github.moulberry.notenoughupdates.dungeons.DungeonWin;
import io.github.moulberry.notenoughupdates.dungeons.GuiDungeonMapEditor;
import io.github.moulberry.notenoughupdates.gamemodes.GuiGamemodes;
-import io.github.moulberry.notenoughupdates.miscfeatures.customblockzones.CustomBiomes;
-import io.github.moulberry.notenoughupdates.miscfeatures.customblockzones.LocationChangeEvent;
-import io.github.moulberry.notenoughupdates.miscfeatures.customblockzones.SpecialBlockZone;
import io.github.moulberry.notenoughupdates.miscfeatures.FairySouls;
import io.github.moulberry.notenoughupdates.miscfeatures.FancyPortals;
import io.github.moulberry.notenoughupdates.miscfeatures.FishingHelper;
import io.github.moulberry.notenoughupdates.miscfeatures.NullzeeSphere;
+import io.github.moulberry.notenoughupdates.miscfeatures.customblockzones.CustomBiomes;
+import io.github.moulberry.notenoughupdates.miscfeatures.customblockzones.LocationChangeEvent;
+import io.github.moulberry.notenoughupdates.miscfeatures.customblockzones.SpecialBlockZone;
import io.github.moulberry.notenoughupdates.miscgui.*;
import io.github.moulberry.notenoughupdates.miscgui.tutorials.NeuTutorial;
import io.github.moulberry.notenoughupdates.options.NEUConfig;
@@ -745,6 +745,11 @@ public class Commands {
DupePOC.doDupe(args[0]);
return;
}*/
+ if (args.length >= 1 && args[0].equalsIgnoreCase("profileinfo")) {
+ String currentProfile = SBInfo.getInstance().currentProfile;
+ SBInfo.Gamemode gamemode = SBInfo.getInstance().getGamemodeForProfile(currentProfile);
+ sender.addChatMessage(new ChatComponentText(EnumChatFormatting.GOLD + "You are on Profile " + currentProfile + " with the mode " + gamemode));
+ }
if (args.length >= 1 && args[0].equalsIgnoreCase("pricetest")) {
if (args.length == 1) {
NotEnoughUpdates.INSTANCE.manager.auctionManager.updateBazaar();
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/GuiItemRecipe.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/GuiItemRecipe.java
index e820378b..6e4d13f6 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/GuiItemRecipe.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/GuiItemRecipe.java
@@ -90,7 +90,7 @@ public class GuiItemRecipe extends GuiScreen {
Minecraft.getMinecraft().getTextureManager().bindTexture(currentRecipe.getBackground());
this.drawTexturedModalRect(guiLeft, guiTop, 0, 0, this.xSize, this.ySize);
- currentRecipe.drawExtraBackground(this);
+ currentRecipe.drawExtraBackground(this, mouseX, mouseY);
List<RecipeSlot> slots = getAllRenderedSlots();
for (RecipeSlot slot : slots) {
@@ -101,7 +101,7 @@ public class GuiItemRecipe extends GuiScreen {
Utils.drawStringScaledMaxWidth(title, fontRendererObj, guiLeft + TITLE_X, guiTop + TITLE_Y, false, xSize - 38, 0x404040);
- currentRecipe.drawExtraInfo(this);
+ currentRecipe.drawExtraInfo(this, mouseX, mouseY);
for (RecipeSlot slot : slots) {
if (isWithinRect(mouseX, mouseY, slot.getX(this), slot.getY(this), SLOT_SIZE, SLOT_SIZE)) {
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinEntity.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinEntity.java
new file mode 100644
index 00000000..6e8f5cd2
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinEntity.java
@@ -0,0 +1,24 @@
+package io.github.moulberry.notenoughupdates.mixins;
+
+import net.minecraft.entity.Entity;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.injection.At;
+import org.spongepowered.asm.mixin.injection.Inject;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
+
+@Mixin(Entity.class)
+public class MixinEntity {
+ // Fix NPE in vanilla code, that we need to work for VillagerTradeRecipe
+ @Inject(method = "getBrightnessForRender", at = @At("HEAD"), cancellable = true)
+ public void onGetBrightnessForRender(float p_getBrightnessForRender_1_, CallbackInfoReturnable<Integer> cir) {
+ if (((Entity) (Object) this).worldObj == null)
+ cir.setReturnValue(-1);
+ }
+
+ // Fix NPE in vanilla code, that we need to work for VillagerTradeRecipe
+ @Inject(method = "getBrightness", at = @At("HEAD"), cancellable = true)
+ public void onGetBrightness(float p_getBrightness_1_, CallbackInfoReturnable<Float> cir) {
+ if (((Entity) (Object) this).worldObj == null)
+ cir.setReturnValue(1.0F);
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinEntityAgeable.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinEntityAgeable.java
new file mode 100644
index 00000000..a6f6c0c6
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinEntityAgeable.java
@@ -0,0 +1,21 @@
+package io.github.moulberry.notenoughupdates.mixins;
+
+import net.minecraft.entity.EntityAgeable;
+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.CallbackInfoReturnable;
+
+@Mixin(EntityAgeable.class)
+public class MixinEntityAgeable {
+ @Shadow
+ protected int growingAge;
+
+ // Fix NPE in vanilla code, that we need to work for VillagerTradeRecipe
+ @Inject(method = "getGrowingAge", cancellable = true, at = @At("HEAD"))
+ public void onGetGrowingAge(CallbackInfoReturnable<Integer> cir) {
+ if (((EntityAgeable) (Object) this).worldObj == null)
+ cir.setReturnValue(growingAge);
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinEntityPlayer.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinEntityPlayer.java
index 218e03eb..21063ea6 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinEntityPlayer.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinEntityPlayer.java
@@ -1,15 +1,26 @@
package io.github.moulberry.notenoughupdates.mixins;
import io.github.moulberry.notenoughupdates.cosmetics.CapeManager;
+import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EnumPlayerModelParts;
+import net.minecraft.scoreboard.ScorePlayerTeam;
+import net.minecraft.scoreboard.Scoreboard;
+import net.minecraft.util.BlockPos;
+import net.minecraft.world.World;
+import org.spongepowered.asm.lib.Opcodes;
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.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin({EntityPlayer.class})
public abstract class MixinEntityPlayer {
+ @Shadow
+ public abstract boolean interactWith(Entity par1);
+
@Inject(method = "isWearing", at = @At("HEAD"), cancellable = true)
public void isWearing(EnumPlayerModelParts part, CallbackInfoReturnable<Boolean> cir) {
if (part == EnumPlayerModelParts.CAPE) {
@@ -21,4 +32,33 @@ public abstract class MixinEntityPlayer {
}
}
}
+
+ @Redirect(method = "<init>", at = @At(value = "FIELD", target = "Lnet/minecraft/world/World;isRemote:Z", opcode = Opcodes.GETFIELD))
+ public boolean onIsRemote(World instance) {
+ if (instance == null) return true;
+ return instance.isRemote;
+ }
+
+ @Redirect(method = "<init>", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/World;getSpawnPoint()Lnet/minecraft/util/BlockPos;"))
+ public BlockPos onGetSpawnPoint(World instance) {
+ if (instance == null)
+ return new BlockPos(0, 0, 0);
+ return instance.getSpawnPoint();
+ }
+
+ @Inject(method = "getWorldScoreboard", at = @At("HEAD"), cancellable = true)
+ public void onGetWorldScoreboard(CallbackInfoReturnable<Scoreboard> cir) {
+ if (((EntityPlayer) (Object) this).worldObj == null) {
+ cir.setReturnValue(null);
+ }
+ }
+
+ @Redirect(method = "getTeam", at = @At(value = "INVOKE", target = "Lnet/minecraft/scoreboard/Scoreboard;getPlayersTeam(Ljava/lang/String;)Lnet/minecraft/scoreboard/ScorePlayerTeam;"))
+ public ScorePlayerTeam onGetTeam(Scoreboard instance, String p_getPlayersTeam_1_) {
+ if (instance == null) {
+ return null;
+ }
+ return instance.getPlayersTeam(p_getPlayersTeam_1_);
+ }
+
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/recipes/CraftingRecipe.java b/src/main/java/io/github/moulberry/notenoughupdates/recipes/CraftingRecipe.java
index 00e70462..082c1ad8 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/recipes/CraftingRecipe.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/recipes/CraftingRecipe.java
@@ -45,6 +45,11 @@ public class CraftingRecipe implements NeuRecipe {
}
@Override
+ public boolean hasVariableCost() {
+ return false;
+ }
+
+ @Override
public Set<Ingredient> getOutputs() {
return Collections.singleton(getOutput());
}
@@ -85,7 +90,7 @@ public class CraftingRecipe implements NeuRecipe {
}
@Override
- public void drawExtraInfo(GuiItemRecipe gui) {
+ public void drawExtraInfo(GuiItemRecipe gui, int mouseX, int mouseY) {
FontRenderer fontRenderer = Minecraft.getMinecraft().fontRendererObj;
String craftingText = getCraftText();
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/recipes/ForgeRecipe.java b/src/main/java/io/github/moulberry/notenoughupdates/recipes/ForgeRecipe.java
index 5cbb4afe..2870a54e 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/recipes/ForgeRecipe.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/recipes/ForgeRecipe.java
@@ -75,6 +75,11 @@ public class ForgeRecipe implements NeuRecipe {
}
@Override
+ public boolean hasVariableCost() {
+ return false;
+ }
+
+ @Override
public Set<Ingredient> getOutputs() {
return Collections.singleton(output);
}
@@ -95,7 +100,7 @@ public class ForgeRecipe implements NeuRecipe {
}
@Override
- public void drawExtraBackground(GuiItemRecipe gui) {
+ public void drawExtraBackground(GuiItemRecipe gui, int mouseX, int mouseY) {
Minecraft.getMinecraft().getTextureManager().bindTexture(BACKGROUND);
for (int i = 0; i < inputs.size(); i++) {
int[] slotCoordinates = getSlotCoordinates(i, inputs.size());
@@ -107,7 +112,7 @@ public class ForgeRecipe implements NeuRecipe {
}
@Override
- public void drawExtraInfo(GuiItemRecipe gui) {
+ public void drawExtraInfo(GuiItemRecipe gui, int mouseX, int mouseY) {
FontRenderer fontRenderer = Minecraft.getMinecraft().fontRendererObj;
if (timeInSeconds > 0)
Utils.drawStringCenteredScaledMaxWidth(formatDuration(timeInSeconds), fontRenderer, gui.guiLeft + EXTRA_INFO_X, gui.guiTop + EXTRA_INFO_Y, false, EXTRA_INFO_MAX_WIDTH, 0xff00ff);
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/recipes/NeuRecipe.java b/src/main/java/io/github/moulberry/notenoughupdates/recipes/NeuRecipe.java
index cfa091d5..99b05d28 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/recipes/NeuRecipe.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/recipes/NeuRecipe.java
@@ -15,14 +15,17 @@ public interface NeuRecipe {
List<RecipeSlot> getSlots();
- void drawExtraInfo(GuiItemRecipe gui);
+ default void drawExtraInfo(GuiItemRecipe gui, int mouseX, int mouseY) {
+ }
- default void drawExtraBackground(GuiItemRecipe gui) {
+ default void drawExtraBackground(GuiItemRecipe gui, int mouseX, int mouseY) {
}
default void drawHoverInformation(GuiItemRecipe gui, int mouseX, int mouseY) {
}
+ boolean hasVariableCost();
+
JsonObject serialize();
ResourceLocation getBackground();
@@ -32,8 +35,18 @@ public interface NeuRecipe {
switch (recipe.get("type").getAsString().intern()) {
case "forge":
return ForgeRecipe.parseForgeRecipe(manager, recipe, output);
+ case "trade":
+ return VillagerTradeRecipe.parseStaticRecipe(manager, recipe);
}
}
return CraftingRecipe.parseCraftingRecipe(manager, recipe, output);
}
+
+ default boolean shouldUseForCraftCost() {
+ return true;
+ }
+
+ default boolean isAvailable() {
+ return true;
+ }
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/recipes/VillagerTradeRecipe.java b/src/main/java/io/github/moulberry/notenoughupdates/recipes/VillagerTradeRecipe.java
new file mode 100644
index 00000000..530e8e32
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/recipes/VillagerTradeRecipe.java
@@ -0,0 +1,145 @@
+package io.github.moulberry.notenoughupdates.recipes;
+
+import com.google.common.collect.Sets;
+import com.google.gson.JsonObject;
+import com.mojang.authlib.GameProfile;
+import io.github.moulberry.notenoughupdates.NEUManager;
+import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
+import io.github.moulberry.notenoughupdates.miscgui.GuiItemRecipe;
+import io.github.moulberry.notenoughupdates.util.SBInfo;
+import io.github.moulberry.notenoughupdates.util.Utils;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.entity.AbstractClientPlayer;
+import net.minecraft.client.gui.FontRenderer;
+import net.minecraft.client.gui.inventory.GuiInventory;
+import net.minecraft.client.network.NetworkPlayerInfo;
+import net.minecraft.entity.EntityLivingBase;
+import net.minecraft.entity.passive.EntityVillager;
+import net.minecraft.util.ResourceLocation;
+
+import java.util.*;
+
+public class VillagerTradeRecipe implements NeuRecipe {
+
+ public static final int COST_SLOT_X = 51;
+ public static final int COST_SLOT_Y = 34;
+ public static final int RESULT_SLOT_Y = 35;
+ public static final int RESULT_SLOT_X = 124;
+
+ private static class Holder { // This holder object exists to defer initialization to first access
+ private static final GameProfile DREAM_PROFILE = new GameProfile(UUID.fromString("ec70bcaf-702f-4bb8-b48d-276fa52a780c"), "Dream");
+ private static final EntityLivingBase DEMO_DREAM = new AbstractClientPlayer(null, DREAM_PROFILE) {
+ @Override
+ protected NetworkPlayerInfo getPlayerInfo() {
+ return new NetworkPlayerInfo(DREAM_PROFILE) {
+ @Override
+ public ResourceLocation getLocationSkin() {
+ return new ResourceLocation("notenoughupdates", "dreamskin.png");
+ }
+ };
+ }
+ };
+ private static final EntityLivingBase DEMO_VILLAGER = new EntityVillager(null);
+
+ private static boolean isAprilFirst() {
+ Calendar cal = Calendar.getInstance();
+ return cal.get(Calendar.DAY_OF_MONTH) == 1 && cal.get(Calendar.MONTH) == Calendar.APRIL;
+ }
+
+ private static final EntityLivingBase DEMO_ENTITY = isAprilFirst() ? DEMO_DREAM : DEMO_VILLAGER;
+
+ }
+
+ private final static ResourceLocation BACKGROUND = new ResourceLocation("notenoughupdates", "textures/gui/villager_recipe.png");
+
+ private final Ingredient result;
+ private final Ingredient cost;
+ private final int minCost, maxCost;
+
+ public VillagerTradeRecipe(Ingredient result, Ingredient cost, int minCost, int maxCost) {
+ this.result = result;
+ this.cost = cost;
+ this.minCost = minCost;
+ this.maxCost = maxCost;
+ }
+
+ public VillagerTradeRecipe(Ingredient result, Ingredient cost) {
+ this(result, cost, -1, -1);
+ }
+
+ public boolean hasVariableCost() {
+ return minCost != -1 && maxCost != -1;
+ }
+
+ @Override
+ public Set<Ingredient> getIngredients() {
+ return Sets.newHashSet(cost);
+ }
+
+ @Override
+ public Set<Ingredient> getOutputs() {
+ return Sets.newHashSet(result);
+ }
+
+ @Override
+ public List<RecipeSlot> getSlots() {
+ return Arrays.asList(
+ new RecipeSlot(COST_SLOT_X, COST_SLOT_Y, cost.getItemStack()),
+ new RecipeSlot(RESULT_SLOT_X, RESULT_SLOT_Y, result.getItemStack())
+ );
+ }
+
+ @Override
+ public boolean shouldUseForCraftCost() {
+ return false;
+ }
+
+ @Override
+ public boolean isAvailable() {
+ return SBInfo.getInstance().getCurrentMode() == SBInfo.Gamemode.STRANDED || NotEnoughUpdates.INSTANCE.config.hidden.dev;
+ }
+
+ @Override
+ public void drawExtraInfo(GuiItemRecipe gui, int mouseX, int mouseY) {
+ if (hasVariableCost()) {
+ FontRenderer fontRenderer = Minecraft.getMinecraft().fontRendererObj;
+ Utils.drawStringCenteredScaledMaxWidth(
+ minCost + " - " + maxCost, fontRenderer,
+ gui.guiLeft + 50, gui.guiTop + 60, false, 75, 0xff00ff);
+
+ }
+ }
+
+ @Override
+ public void drawExtraBackground(GuiItemRecipe gui, int mouseX, int mouseY) {
+ GuiInventory.drawEntityOnScreen(gui.guiLeft + 90, gui.guiTop + 75, 30, gui.guiLeft - mouseX + 80, gui.guiTop + 60 - mouseY, Holder.DEMO_ENTITY);
+ }
+
+ @Override
+ public JsonObject serialize() {
+ JsonObject jsonObject = new JsonObject();
+ jsonObject.addProperty("type", "trade");
+ jsonObject.addProperty("result", result.serialize());
+ jsonObject.addProperty("cost", cost.getInternalItemId());
+ if (minCost > 0)
+ jsonObject.addProperty("min", minCost);
+ if (maxCost > 0)
+ jsonObject.addProperty("max", maxCost);
+ return jsonObject;
+ }
+
+ @Override
+ public ResourceLocation getBackground() {
+ return BACKGROUND;
+ }
+
+ public static VillagerTradeRecipe parseStaticRecipe(NEUManager manager, JsonObject recipe) {
+ return new VillagerTradeRecipe(
+ new Ingredient(manager, recipe.get("result").getAsString()),
+ new Ingredient(manager, recipe.get("cost").getAsString()),
+ recipe.has("min") ? recipe.get("min").getAsInt() : -1,
+ recipe.has("max") ? recipe.get("max").getAsInt() : -1
+ );
+ }
+
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/util/SBInfo.java b/src/main/java/io/github/moulberry/notenoughupdates/util/SBInfo.java
index 6dcd284e..7b5a29a9 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/util/SBInfo.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/util/SBInfo.java
@@ -1,13 +1,19 @@
package io.github.moulberry.notenoughupdates.util;
+import com.google.common.reflect.TypeToken;
import com.google.gson.JsonObject;
import io.github.moulberry.notenoughupdates.NotEnoughUpdates;
import io.github.moulberry.notenoughupdates.miscfeatures.customblockzones.LocationChangeEvent;
import io.github.moulberry.notenoughupdates.overlays.SlayerOverlay;
import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.gui.inventory.GuiChest;
import net.minecraft.client.network.NetworkPlayerInfo;
+import net.minecraft.init.Blocks;
import net.minecraft.inventory.ContainerChest;
+import net.minecraft.inventory.Slot;
+import net.minecraft.item.Item;
+import net.minecraft.item.ItemStack;
import net.minecraft.scoreboard.Score;
import net.minecraft.scoreboard.ScoreObjective;
import net.minecraft.scoreboard.ScorePlayerTeam;
@@ -19,13 +25,16 @@ import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.world.WorldEvent;
import net.minecraftforge.fml.common.eventhandler.EventPriority;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
+import net.minecraftforge.fml.common.gameevent.TickEvent;
+import java.io.File;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
import java.text.ParseException;
import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-import java.util.Objects;
+import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -61,6 +70,31 @@ public class SBInfo {
public boolean isInDungeon = false;
public boolean hasNewTab = false;
+
+ public enum Gamemode {
+ NORMAL("", ""), IRONMAN("Ironman", "♲"), STRANDED("Stranded", "☀");
+
+ private final String name;
+ private final String emoji;
+
+ Gamemode(String name, String emoji) {
+ this.name = name;
+ this.emoji = emoji;
+ }
+
+ public static Gamemode find(String type) {
+ for (Gamemode gamemode : values()) {
+ if (type.contains(gamemode.name))
+ return gamemode;
+ }
+ return null;
+ }
+ }
+
+
+ private Map<String, Gamemode> gamemodes = new HashMap<>();
+ private boolean areGamemodesLoaded = false;
+ private int tickCount = 0;
public String currentProfile = null;
@SubscribeEvent
@@ -77,6 +111,74 @@ public class SBInfo {
}
@SubscribeEvent
+ public void onGuiTick(TickEvent event) {
+ if (tickCount++ % 10 != 0) return;
+ GuiScreen currentScreen = Minecraft.getMinecraft().currentScreen;
+ if (currentScreen instanceof GuiChest) {
+ ContainerChest container = (ContainerChest) ((GuiChest) currentScreen).inventorySlots;
+ if ("Profile Management".equals(container.getLowerChestInventory().getDisplayName().getUnformattedText())) {
+ updateProfileInformation(container);
+ }
+ }
+ }
+
+ private static final Pattern PROFILE_PATTERN = Pattern.compile("(?<type>(♲ Ironman)|(☀ Stranded)|()) *Profile: (?<name>[^ ]+)");
+
+ private void updateProfileInformation(ContainerChest container) {
+ for (int i = 11; i < 16; i = -~i) {
+ Slot slot = container.getSlot(i);
+ if (slot == null || !slot.getHasStack()) continue;
+ ItemStack item = slot.getStack();
+ if (item == null || item.getItem() == Item.getItemFromBlock(Blocks.bedrock)) continue;
+ String displayName = Utils.cleanColour(item.getDisplayName());
+ Matcher matcher = PROFILE_PATTERN.matcher(displayName);
+ if (!matcher.matches()) continue;
+ String type = matcher.group("type");
+ String name = matcher.group("name");
+ Gamemode gamemode = Gamemode.find(type);
+ gamemodes.put(name, gamemode);
+ }
+ areGamemodesLoaded = true;
+ saveGameModes();
+ }
+
+ private Path getProfilesFile() {
+ return new File(NotEnoughUpdates.INSTANCE.manager.configLocation, "profiles.json").toPath();
+ }
+
+ public Map<String, Gamemode> getAllGamemodes() {
+ if (!areGamemodesLoaded)
+ loadGameModes();
+ return gamemodes;
+ }
+
+ public void saveGameModes() {
+ try {
+ Files.write(getProfilesFile(), NotEnoughUpdates.INSTANCE.manager.gson.toJson(gamemodes).getBytes(StandardCharsets.UTF_8));
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public Gamemode getGamemodeForProfile(String profiles) {
+ return getAllGamemodes().get(profiles);
+ }
+
+ public Gamemode getCurrentMode() {
+ return getGamemodeForProfile(currentProfile);
+ }
+
+ public void loadGameModes() {
+ try {
+ gamemodes = NotEnoughUpdates.INSTANCE.manager.gson.fromJson(Files.newBufferedReader(getProfilesFile()), new TypeToken<Map<String, Gamemode>>() {
+ }.getType());
+ areGamemodesLoaded = true;
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ @SubscribeEvent
public void onWorldLoad(WorldEvent.Load event) {
lastLocRaw = -1;
locraw = null;
diff --git a/src/main/resources/assets/notenoughupdates/dreamskin.png b/src/main/resources/assets/notenoughupdates/dreamskin.png
new file mode 100644
index 00000000..067d396e
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/dreamskin.png
Binary files differ
diff --git a/src/main/resources/assets/notenoughupdates/textures/gui/villager_recipe.png b/src/main/resources/assets/notenoughupdates/textures/gui/villager_recipe.png
new file mode 100644
index 00000000..42b6241c
--- /dev/null
+++ b/src/main/resources/assets/notenoughupdates/textures/gui/villager_recipe.png
Binary files differ
diff --git a/src/main/resources/mixins.notenoughupdates.json b/src/main/resources/mixins.notenoughupdates.json
index bec344ec..a566ee2e 100644
--- a/src/main/resources/mixins.notenoughupdates.json
+++ b/src/main/resources/mixins.notenoughupdates.json
@@ -3,40 +3,41 @@
"refmap": "mixins.notenoughupdates.refmap.json",
"compatibilityLevel": "JAVA_8",
"mixins": [
- "MixinMinecraft",
- "MixinAbstractClientPlayer",
- "MixinContainer",
- "MixinEffectRenderer",
- "MixinEntityPlayer",
- "MixinEntityPlayerSP",
- "MixinEntityRenderer",
- "MixinGuiChest",
- "MixinGuiContainer",
- "MixinGuiIngame",
- "MixinGuiInventory",
- "MixinGuiScreen",
- "MixinInventoryEffectRenderer",
- "MixinInventoryPlayer",
- "MixinItemCameraTransforms",
- "MixinItemRenderer",
- "MixinItemStack",
- "MixinLayerArmorBase",
- "MixinLayerCustomHead",
-
- "MixinMouseHelper",
- "MixinNetHandlerPlayClient",
- "MixinPlayerControllerMP",
- "MixinRender",
- "MixinRendererLivingEntity",
- "MixinRenderFish",
- "MixinRenderGlobal",
- "MixinRenderItem",
- "MixinRenderList",
- "MixinTextureManager",
- "MixinTileEntitySkullRenderer",
- "MixinTileEntitySpecialRenderer",
- "MixinVboRenderList",
- "MixinWorld",
- "MixinWorldClient"
+ "MixinAbstractClientPlayer",
+ "MixinContainer",
+ "MixinEffectRenderer",
+ "MixinEntity",
+ "MixinEntityAgeable",
+ "MixinEntityPlayer",
+ "MixinEntityPlayerSP",
+ "MixinEntityRenderer",
+ "MixinGuiChest",
+ "MixinGuiContainer",
+ "MixinGuiIngame",
+ "MixinGuiInventory",
+ "MixinGuiScreen",
+ "MixinInventoryEffectRenderer",
+ "MixinInventoryPlayer",
+ "MixinItemCameraTransforms",
+ "MixinItemRenderer",
+ "MixinItemStack",
+ "MixinLayerArmorBase",
+ "MixinLayerCustomHead",
+ "MixinMinecraft",
+ "MixinMouseHelper",
+ "MixinNetHandlerPlayClient",
+ "MixinPlayerControllerMP",
+ "MixinRender",
+ "MixinRendererLivingEntity",
+ "MixinRenderFish",
+ "MixinRenderGlobal",
+ "MixinRenderItem",
+ "MixinRenderList",
+ "MixinTextureManager",
+ "MixinTileEntitySkullRenderer",
+ "MixinTileEntitySpecialRenderer",
+ "MixinVboRenderList",
+ "MixinWorld",
+ "MixinWorldClient"
]
-} \ No newline at end of file
+}