Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[1.10] GuiTabs for survival inventory, patch to solve inventory tab conflicts and reduce keybind usage. #3349

Closed
Next Next commit
Intended to solve conflicts between mods that add inventories for the…
… player and make a tab for them in the survival inventory. also allows for less key-bind usage.

added survival tabs that can be registered instantiating them.
registers their individual id depending on the container they have been attached too.
Only works for GuiContainers.

added SurvivalTablist class, an encasing class that handles all the drawing, button, and page logic to keep the code in GuiContainer minimal.

patched GuiInventory to call the super for actionPerformed, so it will pick up the button's from the survival tabs

patched guicontainer with a few simple lines that refer to the SurvivalTabsList class, a class that handles all logic and drawing for the survival tabs.

gitignore
AbsolemJackdaw committed Nov 2, 2016
commit 35352b8f2cca420042b31e043d0a435517fc6a4e
Original file line number Diff line number Diff line change
@@ -1,6 +1,45 @@
--- ../src-base/minecraft/net/minecraft/client/gui/inventory/GuiContainer.java
+++ ../src-work/minecraft/net/minecraft/client/gui/inventory/GuiContainer.java
@@ -176,8 +176,11 @@
@@ -53,11 +53,13 @@
private int field_146992_L;
private boolean field_146993_M;
private ItemStack field_146994_N;
-
+ private net.minecraft.client.player.inventory.tabs.SurvivalTabList survivalTabs;
+
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No whitespace changes.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, but my editor doesn't show any added whitespace, and genPatches results in no new patch, so I havent changed anything to it since I first edited it.

What do I do ?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Line 9 contains 4 spaces. Remove them, then lines 7 and 9 should go away.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll figure this out later .... i have no spaces in my editor whatsoever :s

public GuiContainer(Container p_i1072_1_)
{
this.field_147002_h = p_i1072_1_;
this.field_146995_H = true;
+ this.survivalTabs = new net.minecraft.client.player.inventory.tabs.SurvivalTabList(this);
}

public void func_73866_w_()
@@ -66,6 +68,7 @@
this.field_146297_k.field_71439_g.field_71070_bA = this.field_147002_h;
this.field_147003_i = (this.field_146294_l - this.field_146999_f) / 2;
this.field_147009_r = (this.field_146295_m - this.field_147000_g) / 2;
+ this.survivalTabs.addButtons(field_146292_n, field_147003_i, field_147009_r, field_146999_f, field_147000_g);
}

public void func_73863_a(int p_73863_1_, int p_73863_2_, float p_73863_3_)
@@ -73,12 +76,15 @@
this.func_146276_q_();
int i = this.field_147003_i;
int j = this.field_147009_r;
+ this.survivalTabs.drawTabs(false, p_73863_1_, p_73863_2_, p_73863_3_, field_147003_i, field_147009_r, field_146999_f, field_147000_g, field_146296_j, field_146289_q);
this.func_146976_a(p_73863_3_, p_73863_1_, p_73863_2_);
+ this.survivalTabs.drawTabs(true, p_73863_1_, p_73863_2_, p_73863_3_, field_147003_i, field_147009_r, field_146999_f, field_147000_g, field_146296_j, field_146289_q);
GlStateManager.func_179101_C();
RenderHelper.func_74518_a();
GlStateManager.func_179140_f();
GlStateManager.func_179097_i();
super.func_73863_a(p_73863_1_, p_73863_2_, p_73863_3_);
+ this.survivalTabs.drawTabHoveringText(this, p_73863_1_, p_73863_2_, field_147003_i, field_147009_r, field_146999_f, field_147000_g, field_146289_q);
RenderHelper.func_74520_c();
GlStateManager.func_179094_E();
GlStateManager.func_179109_b((float)i, (float)j, 0.0F);
@@ -176,8 +182,11 @@
GlStateManager.func_179109_b(0.0F, 0.0F, 32.0F);
this.field_73735_i = 200.0F;
this.field_146296_j.field_77023_b = 200.0F;
@@ -13,7 +52,7 @@
this.field_73735_i = 0.0F;
this.field_146296_j.field_77023_b = 0.0F;
}
@@ -240,13 +243,12 @@
@@ -240,13 +249,12 @@

if (itemstack == null && p_146977_1_.func_111238_b())
{
@@ -30,7 +69,7 @@
this.func_175175_a(i, j, textureatlassprite, 16, 16);
GlStateManager.func_179145_e();
flag1 = true;
@@ -316,7 +318,7 @@
@@ -316,7 +324,7 @@
protected void func_73864_a(int p_73864_1_, int p_73864_2_, int p_73864_3_) throws IOException
{
super.func_73864_a(p_73864_1_, p_73864_2_, p_73864_3_);
@@ -39,15 +78,15 @@
Slot slot = this.func_146975_c(p_73864_1_, p_73864_2_);
long i = Minecraft.func_71386_F();
this.field_146993_M = this.field_146998_K == slot && i - this.field_146997_J < 250L && this.field_146992_L == p_73864_3_;
@@ -327,6 +329,7 @@
@@ -327,6 +335,7 @@
int j = this.field_147003_i;
int k = this.field_147009_r;
boolean flag1 = p_73864_1_ < j || p_73864_2_ < k || p_73864_1_ >= j + this.field_146999_f || p_73864_2_ >= k + this.field_147000_g;
+ if (slot != null) flag1 = false; // Forge, prevent dropping of items through slots outside of GUI boundaries
int l = -1;

if (slot != null)
@@ -364,7 +367,7 @@
@@ -364,7 +373,7 @@
{
if (this.field_146297_k.field_71439_g.field_71071_by.func_70445_o() == null)
{
@@ -56,7 +95,7 @@
{
this.func_184098_a(slot, l, p_73864_3_, ClickType.CLONE);
}
@@ -402,7 +405,7 @@
@@ -402,7 +411,7 @@
{
this.field_146987_F = 1;
}
@@ -65,11 +104,12 @@
{
this.field_146987_F = 2;
}
@@ -464,10 +467,12 @@
@@ -464,10 +473,13 @@

protected void func_146286_b(int p_146286_1_, int p_146286_2_, int p_146286_3_)
{
+ super.func_146286_b(p_146286_1_, p_146286_2_, p_146286_3_); //Forge, Call parent to release buttons
+ this.survivalTabs.onMouseRelease(field_147003_i, field_147009_r, field_146999_f, field_147000_g, p_146286_3_, p_146286_1_, p_146286_2_);
Slot slot = this.func_146975_c(p_146286_1_, p_146286_2_);
int i = this.field_147003_i;
int j = this.field_147009_r;
@@ -78,7 +118,7 @@
int k = -1;

if (slot != null)
@@ -488,7 +493,7 @@
@@ -488,7 +500,7 @@
{
for (Slot slot2 : this.field_147002_h.field_75151_b)
{
@@ -87,7 +127,7 @@
{
this.func_184098_a(slot2, slot2.field_75222_d, p_146286_3_, ClickType.QUICK_MOVE);
}
@@ -575,7 +580,7 @@
@@ -575,7 +587,7 @@
}
else if (this.field_146297_k.field_71439_g.field_71071_by.func_70445_o() != null)
{
@@ -96,7 +136,7 @@
{
this.func_184098_a(slot, k, p_146286_3_, ClickType.CLONE);
}
@@ -627,7 +632,7 @@
@@ -627,7 +639,7 @@

protected void func_73869_a(char p_73869_1_, int p_73869_2_) throws IOException
{
@@ -105,7 +145,7 @@
{
this.field_146297_k.field_71439_g.func_71053_j();
}
@@ -636,11 +641,11 @@
@@ -636,11 +648,11 @@

if (this.field_147006_u != null && this.field_147006_u.func_75216_d())
{
@@ -119,7 +159,7 @@
{
this.func_184098_a(this.field_147006_u, this.field_147006_u.field_75222_d, func_146271_m() ? 1 : 0, ClickType.THROW);
}
@@ -653,7 +658,7 @@
@@ -653,7 +665,7 @@
{
for (int i = 0; i < 9; ++i)
{
@@ -128,10 +168,15 @@
{
this.func_184098_a(this.field_147006_u, this.field_147006_u.field_75222_d, i, ClickType.SWAP);
return true;
@@ -686,4 +691,16 @@
@@ -686,4 +698,21 @@
this.field_146297_k.field_71439_g.func_71053_j();
}
}
+
+ @Override
+ protected void func_146284_a(net.minecraft.client.gui.GuiButton button) throws IOException {
+ this.survivalTabs.actionPerformed(button);
+ }
+
+ /* ======================================== FORGE START =====================================*/
+
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
--- ../src-base/minecraft/net/minecraft/client/gui/inventory/GuiInventory.java
+++ ../src-work/minecraft/net/minecraft/client/gui/inventory/GuiInventory.java
@@ -123,5 +123,7 @@
{
this.field_146297_k.func_147108_a(new GuiStats(this, this.field_146297_k.field_71439_g.func_146107_m()));
}
+
+ else super.func_146284_a(p_146284_1_);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
package net.minecraftforge.client.player.inventory.tabs;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing license header.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Licence header added


import java.util.Arrays;
import java.util.List;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.inventory.GuiContainer;
import net.minecraft.client.gui.inventory.GuiInventory;
import net.minecraft.client.renderer.RenderItem;
import net.minecraft.client.resources.I18n;
import net.minecraft.util.ResourceLocation;

/**
* @author Subaraki
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't add author tags.

*
* Enclosing class to keep GuiContainer clean. This handles all the survival tab drawing, and the addition of two buttons.
*/
public class SurvivalTabList
{

private int page;
private int maxPages;
private GuiContainer container;
private List<SurvivalTabs> tabs;
private static final ResourceLocation SURVIVAL_INVENTORY_TABS = new ResourceLocation("textures/gui/container/creative_inventory/tabs.png");

public SurvivalTabList(GuiContainer container)
{
this.container = container;
tabs = SurvivalTabs.getTabsForContainer(container.getClass());
maxPages = ((tabs.size() - 12) / 12) + 1;

for (SurvivalTabs tab : tabs)//set the first page
if (container.getClass().equals(tab.getTabContainer()))
{
page = tab.getTabPage();
break;
}
}

/**
* draws all tabs that are not selected behind the texture
*/
public void drawTabs(boolean isFront, int mouseX, int mouseY, float partialTicks, int guiLeft, int guiTop, int xSize, int ySize, RenderItem itemRender,
FontRenderer fontRendererObj)
{

if (tabs.size() == 1 && container.getClass().equals(GuiInventory.class)) // don't draw the base tab if it's the only one
return;

int start = page * 12;
int end = Math.min(tabs.size(), (page + 1) * 12);

for (SurvivalTabs tab : tabs)
{
if (tab.getTabIndex() >= start && tab.getTabIndex() < end)
{

if (!tab.isActiveTab(container.getClass()) && !isFront)
{
Minecraft.getMinecraft().getTextureManager().bindTexture(SURVIVAL_INVENTORY_TABS);
tab.draw(container, isFront, guiLeft, guiTop, xSize, ySize, itemRender, fontRendererObj);
}

if (tab.isActiveTab(container.getClass()) && isFront)
{
Minecraft.getMinecraft().getTextureManager().bindTexture(SURVIVAL_INVENTORY_TABS);
tab.draw(container, isFront, guiLeft, guiTop, xSize, ySize, itemRender, fontRendererObj);
}
}
}
}

public void drawTabHoveringText(GuiContainer screen, int mouseX, int mouseY, int guiLeft, int guiTop, int xSize, int ySize, FontRenderer fontRendererObj)
{
if (tabs.size() == 1 && container.getClass().equals(GuiInventory.class)) // don't traw the base tab if it's the only one
return;
int start = page * 12;
int end = Math.min(tabs.size(), (page + 1) * 12);

for (SurvivalTabs tab : tabs)
{
if (tab.getTabIndex() >= start && tab.getTabIndex() < end)
{
if (tab != null && this.isMouseOverTab(tab, mouseX - guiLeft, mouseY - guiTop, xSize, ySize))
{
renderSurvivalInventoryHoveringText(tab, screen, mouseX, mouseY, fontRendererObj);
break;
}
}
}
}

private boolean renderSurvivalInventoryHoveringText(SurvivalTabs tab, GuiContainer screen, int mouseX, int mouseY, FontRenderer fontRendererObj)
{
net.minecraftforge.fml.client.config.GuiUtils.drawHoveringText(Arrays.<String> asList(new String[] { I18n.format(tab.getLocalizedName()) }), mouseX,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't a patch so you don't have to use fully-qualified names.

mouseY, screen.width, screen.height, -1, fontRendererObj);
return true;
}

private boolean isMouseOverTab(SurvivalTabs tab, int mouseX, int mouseY, int xSize, int ySize)
{
int column = tab.getColumn();
int xOffset = 28 * column;
int yOffset = 0;

if (column == 5)
xOffset = xSize - 28 + 2;
else if (column > 0)
xOffset += column;

if (tab.isTopRow())
yOffset = yOffset - 26;
else
yOffset = yOffset + ySize;

return mouseX >= xOffset && mouseX <= xOffset + 26 && mouseY >= yOffset && mouseY <= yOffset + 28;
}

public void onMouseRelease(int guiLeft, int guiTop, int xSize, int ySize, int state, int mouseX, int mouseY)
{
if (tabs.size() == 1 && container.getClass().equals(GuiInventory.class)) // don't traw the base tab if it's the only one
return;
if (state == 0)
{
int x = mouseX - guiLeft;
int y = mouseY - guiTop;

int start = page * 12;
int end = Math.min(tabs.size(), (page + 1) * 12);

for (SurvivalTabs tab : tabs)
{
int index = tab.getTabIndex();
if (index >= start && index < end)
{
if (tab != null && this.isMouseOverTab(tab, x, y, xSize, ySize))
{
tab.onTabClicked(Minecraft.getMinecraft().thePlayer);
return;
}
}
}
}
}

public void addButtons(List<GuiButton> buttonList, int guiLeft, int guiTop, int xSize, int ySize)
{
if (tabs.size() > 12)
{
buttonList.add(new GuiButton(101, guiLeft - 24, guiTop - 22, 20, 20, "<"));
buttonList.add(new GuiButton(102, guiLeft + xSize + 4, guiTop - 22, 20, 20, ">"));
}
}

public void actionPerformed(GuiButton button)
{
if (button.id == 101)
{
page = Math.max(page - 1, 0);
}
else if (button.id == 102)
{
page = Math.min(page + 1, maxPages);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,226 @@
package net.minecraftforge.client.player.inventory.tabs;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing license header

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Licence header added


import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ListMultimap;
import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.client.gui.FontRenderer;
import net.minecraft.client.gui.inventory.GuiContainer;
import net.minecraft.client.gui.inventory.GuiInventory;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.RenderHelper;
import net.minecraft.client.renderer.RenderItem;
import net.minecraft.init.Blocks;
import net.minecraft.item.ItemStack;
import net.minecraft.util.ResourceLocation;

/**
* @author Subaraki
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't add author tags.

*
* class named after CreativeTabs, but for Survival
*/
public abstract class SurvivalTabs
{

private static ListMultimap<Class<? extends GuiContainer>, SurvivalTabs> tabRegistry = ArrayListMultimap.create();
private static HashMap<Class<? extends GuiContainer>, Integer> tabIndexForContainer = new HashMap<Class<? extends GuiContainer>, Integer>();

private ItemStack iconStack = null;
private ResourceLocation iconResLoc = null;
private int tabIndex = 0;
private String name = null;

public static final SurvivalTabs VANILLA_INVENTORY_TAB = new SurvivalTabs("inventory", new ItemStack(Blocks.CHEST), GuiInventory.class) {
@Override
public void onTabClicked(EntityPlayerSP player)
{
Minecraft.getMinecraft().displayGuiScreen(new GuiInventory(player));
}

@Override
public Class<? extends GuiContainer> getTabContainer()
{
return GuiInventory.class;
}
};

public SurvivalTabs(String name, ItemStack icon, Class<? extends GuiContainer> parentContainer)
{

this.name = name;
this.tabIndex = getNextID(parentContainer);
this.iconStack = icon;
tabRegistry.put(parentContainer, this);
}

public SurvivalTabs(String name, ResourceLocation icon, Class<? extends GuiContainer> parentContainer)
{

this.name = name;
this.tabIndex = getNextID(parentContainer);
this.iconResLoc = icon;
tabRegistry.put(parentContainer, this);
}

public void draw(GuiContainer guiContainer, boolean isSelectedtab, int guiLeft, int guiTop, int xSize, int ySize, RenderItem itemRender,
FontRenderer fontRendererObj)
{

boolean isFirstRow = isTopRow();
int column = getColumn();
int texX = column * 28;
int texY = 0;
int x = guiLeft + 28 * column;
int y = guiTop;

if (isSelectedtab)
texY += 32;

if (column == 5) // set the last tab to the extreme right of the gui
x = guiLeft + xSize - 28;

else if (column > 0)
x += column;

if (isFirstRow)
y = y - 28;
else
{
texY += 64;
y = y + (ySize - 4);
}

RenderHelper.enableGUIStandardItemLighting();

GlStateManager.disableLighting();
GlStateManager.color(1F, 1F, 1F); // Forge: Reset color in case Items change it.
GlStateManager.enableBlend(); // Forge: Make sure blend is enabled else tabs show a white border.
guiContainer.drawTexturedModalRect(x, y, texX, texY, 28, 32);
itemRender.zLevel = 100.0F;
x = x + 6;
y = y + 8 + (isFirstRow ? 1 : -1);
GlStateManager.enableLighting();
GlStateManager.enableRescaleNormal();

if (getIconStack() != null)
{
ItemStack itemstack = getIconStack();
itemRender.renderItemAndEffectIntoGUI(itemstack, x, y);
itemRender.renderItemOverlays(fontRendererObj, itemstack, x, y);
}
else
{
Minecraft.getMinecraft().getTextureManager().bindTexture(getIconResLoc());
guiContainer.drawTexturedModalRect(x, y, 0, 0, 16, 16);
}

GlStateManager.disableLighting();
itemRender.zLevel = 0.0F;

}

private int getNextID(Class<? extends GuiContainer> guiContainer)
{
if (tabIndexForContainer.containsKey(guiContainer))
{
int newIndex = (tabIndexForContainer.get(guiContainer) + 1);
tabIndexForContainer.put(guiContainer, newIndex);
return newIndex;
}

tabIndexForContainer.put(guiContainer, 0);
return 0;
}

/** returns the index relative to the gui */
public int getTabIndex()
{
return tabIndex;
}

/** wether this tab is on the top row or not */
public boolean isTopRow()
{
return getTabIndex() > 11 ? ((getTabIndex() - 12) % 12) < 6 : getTabIndex() < 6;
}

/** returns index % 6 to determine column */
public int getColumn()
{
return getTabIndex() > 11 ? ((getTabIndex() - 12) % 12) % 6 : getTabIndex() % 6;
}

/**
* @return wether this tab's parent gui is the current gui
*/
public boolean isActiveTab(Class<? extends GuiContainer> guiContainer)
{
return guiContainer != null && guiContainer.equals(getTabContainer());
}

/**
* @return the tabindex / 12
*/
public int getTabPage()
{
return tabIndex / 12;
}

/**
* @return the localized name for this tab
*/
public String getLocalizedName()
{
return "guiGroup." + name;
}

public ResourceLocation getIconResLoc()
{
return iconResLoc;
}

public ItemStack getIconStack()
{
return iconStack;
}

/**
* @return a list of the appended tabs for the given guicontainer
*/
public static List<SurvivalTabs> getTabsForContainer(Class<? extends GuiContainer> guiContainer)
{
return tabRegistry.containsKey(guiContainer) ? tabRegistry.get(guiContainer) : new ArrayList<SurvivalTabs>();
}

/**
* Appends a list of tabs from a parent gui to another gui to create the illusion of continuity
*
* @param original
* : the tabs to copy from, if any registered
* @param guiContainer
* : the GuiContainer the list will be added too.
*/
public static void createContinuity(Class<? extends GuiContainer> original, Class<? extends GuiContainer> guiContainer)
{

if (tabRegistry.containsKey(original))
{
for (SurvivalTabs tab : tabRegistry.get(original))
tabRegistry.put(guiContainer, tab);
}
}

/**
* process interaction when the tab is clicked. should be used to send a packet to the server and open a gui
*/
public abstract void onTabClicked(EntityPlayerSP player);

/**
* returns the GuiContainer this tab should be linked too. not affiliated with opening the gui. can be null if no gui should lead to this tab. mostly used to know when a tab is
* on an affiliated gui, and draw the tab texture in of the others.
*/
public abstract Class<? extends GuiContainer> getTabContainer();
}