diff options
author | nea <romangraef@gmail.com> | 2022-02-10 03:06:33 +0100 |
---|---|---|
committer | nea <romangraef@gmail.com> | 2022-02-10 03:06:33 +0100 |
commit | 3b844cb2c8bcf191a4249114383ea7cc88c8849c (patch) | |
tree | 91312d2ee7d92c8503b41f7b5d4a4ced3fa36bb5 | |
parent | 076733d8ad73a2cfccb910e0bb1dc71c00d8ded1 (diff) | |
download | NotEnoughUpdates-3b844cb2c8bcf191a4249114383ea7cc88c8849c.tar.gz NotEnoughUpdates-3b844cb2c8bcf191a4249114383ea7cc88c8849c.tar.bz2 NotEnoughUpdates-3b844cb2c8bcf191a4249114383ea7cc88c8849c.zip |
villager trades
12 files changed, 287 insertions, 43 deletions
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/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..f0363bc8 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,14 @@ 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; + } } 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..bd3f5be8 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/recipes/VillagerTradeRecipe.java @@ -0,0 +1,138 @@ +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.miscgui.GuiItemRecipe; +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 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/resources/assets/notenoughupdates/dreamskin.png b/src/main/resources/assets/notenoughupdates/dreamskin.png Binary files differnew file mode 100644 index 00000000..067d396e --- /dev/null +++ b/src/main/resources/assets/notenoughupdates/dreamskin.png diff --git a/src/main/resources/assets/notenoughupdates/textures/gui/villager_recipe.png b/src/main/resources/assets/notenoughupdates/textures/gui/villager_recipe.png Binary files differnew file mode 100644 index 00000000..42b6241c --- /dev/null +++ b/src/main/resources/assets/notenoughupdates/textures/gui/villager_recipe.png 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 +} |