Java tutorial
/******************************************************************************* * The MIT License (MIT) * * Copyright (C) 2014-2018 Sam Bassett (aka Lothrazar) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. ******************************************************************************/ package com.lothrazar.cyclicmagic.item.merchant; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Map; import org.lwjgl.opengl.GL11; import com.lothrazar.cyclicmagic.ModCyclic; import com.lothrazar.cyclicmagic.data.ITooltipButton; import com.lothrazar.cyclicmagic.gui.container.GuiBaseContainer; import com.lothrazar.cyclicmagic.util.Const; import com.lothrazar.cyclicmagic.util.Const.ScreenSize; import com.lothrazar.cyclicmagic.util.UtilChat; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Gui; import net.minecraft.client.gui.GuiButton; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.renderer.RenderHelper; import net.minecraft.enchantment.Enchantment; import net.minecraft.enchantment.EnchantmentHelper; import net.minecraft.entity.passive.EntityVillager; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.InventoryPlayer; import net.minecraft.util.ResourceLocation; import net.minecraft.village.MerchantRecipe; import net.minecraft.village.MerchantRecipeList; import net.minecraft.world.World; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; @SideOnly(Side.CLIENT) public class GuiMerchantBetter extends GuiBaseContainer { public static final ResourceLocation TRADE_REDX = new ResourceLocation(Const.MODID, Const.Res.folder + "tradex.png"); private int btnColCount = 4; private int yBtnStart; private int lastUnusedButtonId; private int xBtnStart; EntityPlayer player; private int selectedMerchantRecipe; private List<GuiButtonPurchase> merchButtons = new ArrayList<GuiButtonPurchase>(); public GuiMerchantBetter(InventoryPlayer ip, EntityVillager merch, InventoryMerchantBetter im, World worldIn) { super(new ContainerMerchantBetter(ip, merch, im, worldIn)); player = ip.player; this.setScreenSize(ScreenSize.LARGEWIDE); this.xSize = getScreenSize().width(); this.ySize = getScreenSize().height(); } public ContainerMerchantBetter getContainer() { return (ContainerMerchantBetter) this.inventorySlots; } @Override public void initGui() { super.initGui(); //setup for the validate btns this.xBtnStart = this.guiLeft; this.yBtnStart = getMiddleY(); this.lastUnusedButtonId = 1; } private void validateMerchantButtons() { MerchantRecipeList merchantrecipelist = getContainer().getTrades(); int s = merchantrecipelist.size(); int btnH = 20, btnW = 56; int x = this.xBtnStart; int y = this.yBtnStart; int currRow; int currCol; for (int i = 0; i < s; i++) { if (i >= merchButtons.size()) { currRow = i / btnColCount; currCol = i % btnColCount; x = this.xBtnStart + currCol * btnW; y = this.yBtnStart + currRow * btnH; GuiButtonPurchase slotBtn = this .addButton(new GuiButtonPurchase(lastUnusedButtonId, x, y, btnW, btnH, i, this)); merchButtons.add(slotBtn); lastUnusedButtonId++; } } } @Override protected void drawGuiContainerForegroundLayer(int mouseX, int mouseY) { } @Override public void updateScreen() { super.updateScreen(); getContainer().setCurrentRecipeIndex(this.selectedMerchantRecipe);//try to sync between both containers this.validateMerchantButtons(); } @Override protected void actionPerformed(GuiButton button) throws IOException { if (button instanceof GuiButtonPurchase) { setAndTryPurchase(((GuiButtonPurchase) button)); } } private void setAndTryPurchase(GuiButtonPurchase button) { this.selectedMerchantRecipe = button.getRecipeIndex(); getContainer().setCurrentRecipeIndex(this.selectedMerchantRecipe); ModCyclic.network.sendToServer(new PacketVillagerTrade(this.selectedMerchantRecipe)); } @Override protected void drawGuiContainerBackgroundLayer(float partialTicks, int mouseX, int mouseY) { GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); this.mc.getTextureManager().bindTexture(getScreenSize().texture()); int thisX = this.getMiddleX(); int thisY = this.getMiddleY(); int u = 0, v = 0; Gui.drawModalRectWithCustomSizedTexture(thisX, thisY, u, v, getScreenSize().width(), getScreenSize().height(), getScreenSize().width(), getScreenSize().height()); } /** * this HAS to be a nested class, because the Gui itemRender is not public */ @SideOnly(Side.CLIENT) static class GuiButtonPurchase extends GuiButton implements ITooltipButton { final static int rowCount = 4; final static int spacing = 18; private int recipeIndex; private GuiMerchantBetter parent; public GuiButtonPurchase(int buttonId, int x, int y, int widthIn, int heightIn, int r, GuiMerchantBetter p) { super(buttonId, x, y, widthIn, heightIn, ""); recipeIndex = r; this.parent = p; } public int getRecipeIndex() { return recipeIndex; } @Override public void drawButton(Minecraft mc, int mouseX, int mouseY, float p) { super.drawButton(mc, mouseX, mouseY, p); if (this.visible) { MerchantRecipeList merchantrecipelist = parent.getContainer().getTrades(); if (merchantrecipelist == null) { return; } if (recipeIndex >= merchantrecipelist.size()) { //in 1.11.2 the draw cycles happen before the recipe list is finished syncing from server, so we get index OOB errors //just keep it hidden if we have and index for a recipe that is valid but not in the current list. // see https://github.com/PrinceOfAmber/Cyclic/issues/324 this.visible = false; return;//wait until its done loading until next draw } this.visible = true; MerchantRecipe r = merchantrecipelist.get(recipeIndex); if (r == null) { return; } int x = this.x + 2; int y = this.y + 1; GlStateManager.pushMatrix(); ModCyclic.proxy.renderItemOnGui(r.getItemToBuy(), parent.itemRender, parent.fontRenderer, x, y); x += spacing; ModCyclic.proxy.renderItemOnGui(r.getSecondItemToBuy(), parent.itemRender, parent.fontRenderer, x, y); x += spacing; ModCyclic.proxy.renderItemOnGui(r.getItemToSell(), parent.itemRender, parent.fontRenderer, x, y); GlStateManager.popMatrix(); RenderHelper.enableGUIStandardItemLighting();//IMPORTANT: without this, any button with transparent item (glass) well have messed up shading if (r.isRecipeDisabled()) { parent.mc.getTextureManager().bindTexture(TRADE_REDX); GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); GlStateManager.disableLighting(); int sizeOfX = 30 / 2;//real physical texture is 30x30 pixels, and we just reduce it a touch Gui.drawModalRectWithCustomSizedTexture(x - 18, y + 1, 0, 0, sizeOfX, sizeOfX, sizeOfX, sizeOfX); } } } @Override public List<String> getTooltips() { List<String> tt = new ArrayList<String>(); MerchantRecipeList merchantrecipelist = parent.getContainer().getTrades(); if (merchantrecipelist == null) { return tt; } MerchantRecipe r = merchantrecipelist.get(recipeIndex); if (r == null) { return tt; } if (r.isRecipeDisabled()) { tt.add(UtilChat.lang("merchant.deprecated")); } else { tt.add(UtilChat.lang("tile.tool_trade.button.tooltip")); } if (r.getItemToSell() != null) {// && r.getItemToSell().getItem() == Items.ENCHANTED_BOOK Map<Enchantment, Integer> map = EnchantmentHelper.getEnchantments(r.getItemToSell()); if (map != null) { for (Map.Entry<Enchantment, Integer> entry : map.entrySet()) { tt.add(entry.getKey().getTranslatedName(entry.getValue())); } } } return tt; } } }