Jump to content

[Solved] [1.7.10] Making a container have 0 slots sometimes, 5 other times


Recommended Posts

Posted

I'm a long-time programmer, but very new to Forge (and somewhat new to Java). I'm working on a small mod to get myself into the language and API, and it's all going well, except I've hit a roadblock.

 

The mod is supposed to add "Ender hoppers" with a slightly different functionality from the regular ones, which it does. These hoppers store the UUID of the players who place them in an ownerUUID member variable, then are able to pull/push to and from their owner's Ender Chest inventory. This is all working just fine.

 

However, I'm trying to make it so that if a player opens the hopper's inventory, if they're not the owner, they won't be able to use any of the hopper's slots--it'll be "locked", effectively. I figured this would be easy enough by making a separate Container class and GUI class for a "locked" Ender hopper and displaying that one if the activating player isn't a match. If they're both passed a 0-slot inventory (i.e. a new class that simply implements IInventory but doesn't ever set any slots), it *should* display an unusable inventory, right?

 

At least, that was what I thought. Instead, if a non-owner player right-clicks on the Ender hopper, no GUI shows up. Even worse, their player inventory gets all screwed up, with items moving around to seemingly random slots, including armor, inventory, and hotbar slots. I can't seem to figure out what I'm doing wrong here.

 

Here's the relevant code (imports excluded for brevity):

 

EnderHoppers.java (main mod class) GUI registration:

 

NetworkRegistry.INSTANCE.registerGuiHandler(this, new EnderHopperGui());

 

 

EnderHopperGui.java:

 

public class EnderHopperGui implements IGuiHandler {

@Override
public Object getServerGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z) {
	// TODO Auto-generated method stub
        TileEntity tileEntity = world.getTileEntity(x, y, z);
        if(tileEntity instanceof TileEntityEnderHopper){
        	if (ID==0) {
        		return new ContainerHopper(player.inventory, (TileEntityEnderHopper) tileEntity);
        	}
        	else {
        		return new ContainerLockedEnderHopper(player.inventory, new EmptyInventory());
        	}
        }
        return null;
}

@Override
public Object getClientGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z) {
        TileEntity tileEntity = world.getTileEntity(x, y, z);
        
        if(tileEntity instanceof TileEntityEnderHopper){
        	if (ID==0) {
                return new GuiHopper(player.inventory, (TileEntityEnderHopper) tileEntity);
        	}
        	else {
        		return new GuiLockedEnderHopper(player.inventory, (TileEntityEnderHopper) tileEntity);
        	}
        }
        return null;
}

}

 

 

(EmptyInventory is just a class which implements IInventory and returns 0, null, or false appropriately for all methods.)

 

BlockEnderHopper.java onBlockActivated method:

 

    public boolean onBlockActivated(World p_149727_1_, int p_149727_2_, int p_149727_3_, int p_149727_4_, EntityPlayer p_149727_5_, int p_149727_6_, float p_149727_7_, float p_149727_8_, float p_149727_9_)
    {
        if (p_149727_1_.isRemote)
        {
            return true;
        }
        else
        {
            TileEntityEnderHopper tileentityhopper = func_149920_e(p_149727_1_, p_149727_2_, p_149727_3_, p_149727_4_);

            if (tileentityhopper != null)
            {
            	if (p_149727_5_.getGameProfile().getId().equals(tileentityhopper.getOwner())) {
            		p_149727_5_.openGui(EnderHoppers.instance, 0, p_149727_1_, p_149727_2_, p_149727_3_, p_149727_4_);
            	}
            	else {
            		p_149727_5_.openGui(EnderHoppers.instance, 1, p_149727_1_, p_149727_2_, p_149727_3_, p_149727_4_);
            	}
            }
            return true;
        }
    }

 

 

(getOwner() returns the tile entity's ownerUUID, which I've verified is correct. GUI 0 is a normal, unlocked Ender hopper, which works; GUI 1 is a locked Ender hopper, which does not work.)

 

GUILockedEnderHopper.java:

 

@SideOnly(Side.CLIENT)
public class GuiLockedEnderHopper extends GuiContainer
{
    private static final ResourceLocation field_147085_u = new ResourceLocation("enderhoppers:textures/gui/container/locked_ender_hopper.png");
    private IInventory field_147084_v;
    private IInventory field_147083_w;
    private TileEntityEnderHopper hopper;
    private static final String __OBFID = "CL_00000759";

    public GuiLockedEnderHopper(InventoryPlayer p_i1092_1_, TileEntityEnderHopper hop)
    {
        super(new ContainerLockedEnderHopper(p_i1092_1_, hop));
        this.field_147084_v = p_i1092_1_;
        this.field_147083_w = hop;
        this.allowUserInput = false;
        this.ySize = 133;
    }

    /**
     * Draw the foreground layer for the GuiContainer (everything in front of the items)
     */
    protected void drawGuiContainerForegroundLayer(int p_146979_1_, int p_146979_2_)
    {
    	String name=((TileEntityEnderHopper)(field_147083_w)).getOwnerName();
        this.fontRendererObj.drawString("Bound to "+name, 8, 6, 4210752);
        this.fontRendererObj.drawString("Bound to "+name, 8, this.ySize - 96 + 2, 4210752);
    }

    protected void drawGuiContainerBackgroundLayer(float p_146976_1_, int p_146976_2_, int p_146976_3_)
    {
        GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
        this.mc.getTextureManager().bindTexture(field_147085_u);
        int k = (this.width - this.xSize) / 2;
        int l = (this.height - this.ySize) / 2;
        this.drawTexturedModalRect(k, l, 0, 0, this.xSize, this.ySize);
    }
}

 

 

(The getOwnerName() method returns the string name of the owner of the hopper. I'm 100% sure the texture is loading properly as it worked before I tried making it 0-slots.)

 

ContainerLockedEnderHopper.java:

 

public class ContainerLockedEnderHopper extends Container
{
    private final IInventory field_94538_a;
    private static final String __OBFID = "CL_00001750";

    public ContainerLockedEnderHopper(InventoryPlayer p_i1814_1_, IInventory p_i1814_2_)
    {
        this.field_94538_a = p_i1814_2_;
        p_i1814_2_.openInventory();
        byte b0 = 51;
        int i;

        // Hopper slots
        for (i = 0; i < p_i1814_2_.getSizeInventory(); ++i)
        {
            this.addSlotToContainer(new Slot(p_i1814_2_, i, 44 + i * 18, 20));
        }

        // 3x9 inventory slots
        for (i = 0; i < 3; ++i)
        {
            for (int j = 0; j < 9; ++j)
            {
                this.addSlotToContainer(new Slot(p_i1814_1_, j + i * 9 + 9, 8 + j * 18, i * 18 + b0));
            }
        }

        // Hotbar slots
        for (i = 0; i < 9; ++i)
        {
            this.addSlotToContainer(new Slot(p_i1814_1_, i, 8 + i * 18, 58 + b0));
        }
    }

    public boolean canInteractWith(EntityPlayer p_75145_1_)
    {
    	return false;
        //return this.field_94538_a.isUseableByPlayer(p_75145_1_);
    }

    /**
     * Called when a player shift-clicks on a slot. You must override this or you will crash when someone does that.
     */
    public ItemStack transferStackInSlot(EntityPlayer p_82846_1_, int p_82846_2_)
    {
        ItemStack itemstack = null;
        Slot slot = (Slot)this.inventorySlots.get(p_82846_2_);

        if (slot != null && slot.getHasStack())
        {
            ItemStack itemstack1 = slot.getStack();
            itemstack = itemstack1.copy();

            if (p_82846_2_ < this.field_94538_a.getSizeInventory())
            {
                if (!this.mergeItemStack(itemstack1, this.field_94538_a.getSizeInventory(), this.inventorySlots.size(), true))
                {
                    return null;
                }
            }
            else if (!this.mergeItemStack(itemstack1, 0, this.field_94538_a.getSizeInventory(), false))
            {
                return null;
            }

            if (itemstack1.stackSize == 0)
            {
                slot.putStack((ItemStack)null);
            }
            else
            {
                slot.onSlotChanged();
            }
        }

        return itemstack;
    }

    /**
     * Called when the container is closed.
     */
    public void onContainerClosed(EntityPlayer p_75134_1_)
    {
        super.onContainerClosed(p_75134_1_);
        this.field_94538_a.closeInventory();
    }
}

 

 

I tried setting canInteractWith() to always return false, thinking that would do my job without needing the EmptyInventory class, but it didn't seem to do anything at all no matter what it returned, so I moved on to trying the EmptyInventory method.

 

Can anyone see where I've gone wrong, or maybe a better/easier way to get this functionality working?

Whatever Minecraft needs, it is most likely not yet another tool tier.

Posted

Perhaps instead make a custom 'lockable slot' overriding the method:

    public boolean canTakeStack(EntityPlayer player){}

 

And possibly "graying out" the slot, so they can see

 

I think its my java of the variables.

Posted

*EDIT* Oops! I figured out the problem...I had canInteractWith returning false constantly, which stops the container from showing up >_< . Fixed it all now! Thanks for your help; the LockedSlot class idea is definitely more elegant than my EmptyInventory technique :)

 

*Original post below saved for the archives...*

 

Ah! That sounds like a good idea. And yet, it still doesn't work :( It doesn't mess up the player's inventory anymore, but it still doesn't show the GUI. Here's the code I've updated from the original above, plus I've deleted the EmptyInventory class:

 

EnderHopperGui.java:

 

	@Override
public Object getServerGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z) {
	// TODO Auto-generated method stub
        TileEntity tileEntity = world.getTileEntity(x, y, z);
        if(tileEntity instanceof TileEntityEnderHopper){
        	if (ID==0) {
        		return new ContainerHopper(player.inventory, (TileEntityEnderHopper) tileEntity);
        	}
        	else {
        		return new ContainerLockedEnderHopper(player.inventory,  (TileEntityEnderHopper) tileEntity);
        	}
        }
        return null;
}

 

 

ContainerLockedHopper.java:

 

public ContainerLockedEnderHopper(InventoryPlayer p_i1814_1_, IInventory p_i1814_2_)
    {
        this.field_94538_a = p_i1814_2_;
        p_i1814_2_.openInventory();
        byte b0 = 51;
        int i;

        // Hopper slots
        for (i = 0; i < p_i1814_2_.getSizeInventory(); ++i)
        {
            this.addSlotToContainer(new LockedSlot(p_i1814_2_, i, 44 + i * 18, 20));
        }

        // 3x9 inventory slots
        for (i = 0; i < 3; ++i)
        {
            for (int j = 0; j < 9; ++j)
            {
                this.addSlotToContainer(new Slot(p_i1814_1_, j + i * 9 + 9, 8 + j * 18, i * 18 + b0));
            }
        }

        // Hotbar slots
        for (i = 0; i < 9; ++i)
        {
            this.addSlotToContainer(new Slot(p_i1814_1_, i, 8 + i * 18, 58 + b0));
        }
    }

 

 

LockedSlot.java:

 

package enderhoppers;

import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.IInventory;
import net.minecraft.inventory.Slot;

public class LockedSlot extends Slot {

public LockedSlot(IInventory p_i1824_1_, int p_i1824_2_, int p_i1824_3_, int p_i1824_4_) {
	super(p_i1824_1_, p_i1824_2_, p_i1824_3_, p_i1824_4_);
}

@Override
public boolean canTakeStack(EntityPlayer player) {
	return false;
}

}

 

 

Not sure why the UI isn't even showing up at all...

Whatever Minecraft needs, it is most likely not yet another tool tier.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Announcements



×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.