Jump to content

Detecting slot change?


TLHPoE

Recommended Posts

I linked this up to my PlayerTickHandler to try to do this, but no results. :I

 

 

		for(int i = 0;i < this.lastSlots.length;i++)
		{

			try
			{

				if(this.lastSlots[i] != this.currentSlots[i])
				{

					if(this.lastSlots[i].getItem() != null && this.lastSlots[i].getItem() instanceof IAccessory)
					{

						IAccessory accessory = (IAccessory)this.lastSlots[i].getItem();

						accessory.unequipped(player);

					}

					if(this.currentSlots[i].getItem() != null && this.currentSlots[i].getItem() instanceof IAccessory)
					{

						IAccessory accessory = (IAccessory)this.currentSlots[i].getItem();

						accessory.equipped(player);

					}

				}

			}
			catch(Exception e)
			{

				e.printStackTrace();

			}

		}

 

Kain

Link to comment
Share on other sites

Hi

 

I think the basic concept should work fine.  Depending on how you are storing the slot contents, the problem might be here

if(this.lastSlots != this.currentSlots)

i.e. this statement compares two objects, so these might be different objects even if the contents are identical

 

alternatively, perhaps you are not updating lastSlots or currentSlots properly?  Have you tried inserting a breakpoint and inspecting them, or logging their contents to stdout?

 

-TGG

Link to comment
Share on other sites

Ok, I've switched to a much more efficient way. Instead of doing it every tick, I'm doing it every time a slot changes.

 

My only problem now, is that it detects if it's been equipped. But if I try to remove it, it does nothing.

It also only detects if it's equipped when it's the first thing I do in the inventory. I have to close and reopen for it to detect it.

 

My code:

 

public void onInventoryChanged()
{

	for(int i = 0;i < this.getSizeInventory();i++)
	{

		if(this.lastSlots[i] != this.slots[i])
		{

			if(this.slots[i] != null && this.slots[i].getItem() instanceof IAccessory)
			{

				IAccessory accessory = (IAccessory)this.slots[i].getItem();

				accessory.equipped(player);

			}

			if(this.lastSlots[i] != null && this.lastSlots[i].getItem() instanceof IAccessory)
			{

				IAccessory accessory = (IAccessory)this.lastSlots[i].getItem();

				accessory.unequipped(player);

			}

		}

	}

	this.saveInventoryToNBTTagCompound(player);

	this.lastSlots = this.slots;

}

 

Kain

Link to comment
Share on other sites

Hi

 

I've got a sneaking suspicion that onInventoryChanged is not called for all changes to the inventory.

To be honest, I wouldn't worry about your original idea being "inefficient", Java is pretty quick and comparing a few slots for changes takes basically no time at all.  I'd suggest you have another go with it because I reckon it should work fine.

 

-TGG

 

 

Link to comment
Share on other sites

Hi

 

I think this is probably the problem here:

this.lastSlots = this.currentSlots;

 

Although it looks like this copies currentSlots into lastSlots, it doesn't.  It makes lastSlots refer to the same array as currentSlots does, i.e. they are both the same object.  So your comparisons will always be true because you're comparing the same object against itself.

 

You need to copy the elements of the array, eg

for (int i = 0;i < 7;i++) {
  this.lastSlots[i] = this.currentSlots[i];
}
or
System.arraycopy(this.currentSlots, 0, this.lastSlots, 0, this.lastSlots.length);

 

-TGG

 

Link to comment
Share on other sites

Thanks for all the help, one last problem though.

 

I was testing and saw it earlier and knew the cause, but I had to go do something else. Now I can't figure out why it says that it's equipping and unequipping every tick.

 

 

package net.gloriarpg.handler;

import java.util.EnumSet;

import net.gloriarpg.GloriaRPG;
import net.gloriarpg.item.IAccessory;
import net.minecraft.client.Minecraft;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import cpw.mods.fml.common.ITickHandler;
import cpw.mods.fml.common.TickType;

public class PlayerTickHandler implements ITickHandler
{

private ItemStack[] currentSlots = new ItemStack[7];
private ItemStack[] lastSlots = new ItemStack[7];

private final EnumSet<TickType> ticksToGet;

public PlayerTickHandler(EnumSet<TickType> ticksToGet)
{

	this.ticksToGet = ticksToGet;

}

@Override
public void tickStart(EnumSet<TickType> type, Object... tickData)
{

	playerTick((EntityPlayer) tickData[0]);

}

@Override
public void tickEnd(EnumSet<TickType> type, Object... tickData)
{

}

@Override
public EnumSet<TickType> ticks()
{

	return ticksToGet;

}

@Override
public String getLabel()
{

	return "N/A";

}

public void playerTick(EntityPlayer player)
{

	NBTTagCompound playerNBT = player.getEntityData();

	if(Minecraft.getMinecraft().currentScreen != null)
	{

		AccessoriesKeyHandler.pressed = false;

	}

	if(AccessoriesKeyHandler.pressed)
	{

		player.openGui(GloriaRPG.instance, 2, player.worldObj, (int) player.posX, (int) player.posY, (int) player.posZ);

		AccessoriesKeyHandler.pressed = false;

	}

	if(playerNBT != null)
	{

		NBTTagList nbtTag = playerNBT.getTagList("Accessories");

		for(int i = 0;i < nbtTag.tagCount();i++)
		{

			NBTTagCompound nbt = (NBTTagCompound)nbtTag.tagAt(i);

			byte slot = nbt.getByte("Slot");

			if(slot >= 0 && slot < 7);
			{

				ItemStack itemStack = ItemStack.loadItemStackFromNBT(nbt);
				Item item = itemStack.getItem();

				this.currentSlots[i] = itemStack;

				if(item instanceof IAccessory)
				{

					IAccessory accessory = (IAccessory)item;

					accessory.tick(player);

				}

			}

		}

	}

	for(int i = 0;i < 7;i++)
	{

		if(this.lastSlots[i] != this.currentSlots[i])
		{

			if(this.currentSlots[i] != null && this.currentSlots[i].getItem() instanceof IAccessory)
			{

				IAccessory accessory = (IAccessory)this.currentSlots[i].getItem();

				accessory.equipped(player);

			}

			if(this.lastSlots[i] != null && this.lastSlots[i].getItem() instanceof IAccessory)
			{

				IAccessory accessory = (IAccessory)this.lastSlots[i].getItem();

				accessory.unequipped(player);

			}

		}

	}

	System.arraycopy(this.currentSlots, 0, this.lastSlots, 0, this.lastSlots.length);

}

}

 

Kain

Link to comment
Share on other sites

Hi

 

I think the problem is the same type as the one we just solved

if (this.lastSlots[i] != this.currentSlots[i])

i.e. this statement compares if the two references refer to the same objects, not if the contents of the objects are identical.  And since you are filling currentSlots with new ItemStacks every tick....

 

ItemStack itemStack = ItemStack.loadItemStackFromNBT(nbt);
this.currentSlots[i] = itemStack;

 

Two ItemStacks can be compared for equality using ItemStack.areItemStacksEqual (checks if itemID, stackSize, damage, and stackTagCompound are all equal).  Or you can just compare this.lastSlots.itemID.  Depends on what you mean by "unequip" - eg if your item gets damaged by using it, does this count as an unequip?

 

-TGG

 

 

Link to comment
Share on other sites

Agghhhhh.

 

Kind of the same problem, but I put it in, it detects equipped, I remove it, nothing. I close and re-open, and it detects nothing.

 

 

package net.gloriarpg.handler;

import java.util.EnumSet;

import net.gloriarpg.GloriaRPG;
import net.gloriarpg.item.IAccessory;
import net.minecraft.client.Minecraft;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import cpw.mods.fml.common.ITickHandler;
import cpw.mods.fml.common.TickType;

public class PlayerTickHandler implements ITickHandler
{

private ItemStack[] currentSlots = new ItemStack[7];
private ItemStack[] lastSlots = new ItemStack[7];

private final EnumSet<TickType> ticksToGet;

public PlayerTickHandler(EnumSet<TickType> ticksToGet)
{

	this.ticksToGet = ticksToGet;

}

@Override
public void tickStart(EnumSet<TickType> type, Object... tickData)
{

	playerTick((EntityPlayer) tickData[0]);

}

@Override
public void tickEnd(EnumSet<TickType> type, Object... tickData)
{

}

@Override
public EnumSet<TickType> ticks()
{

	return ticksToGet;

}

@Override
public String getLabel()
{

	return "N/A";

}

public void playerTick(EntityPlayer player)
{

	NBTTagCompound playerNBT = player.getEntityData();

	if(Minecraft.getMinecraft().currentScreen != null)
	{

		AccessoriesKeyHandler.pressed = false;

	}

	if(AccessoriesKeyHandler.pressed)
	{

		player.openGui(GloriaRPG.instance, 2, player.worldObj, (int) player.posX, (int) player.posY, (int) player.posZ);

		AccessoriesKeyHandler.pressed = false;

	}

	if(playerNBT != null)
	{

		NBTTagList nbtTag = playerNBT.getTagList("Accessories");

		for(int i = 0;i < nbtTag.tagCount();i++)
		{

			NBTTagCompound nbt = (NBTTagCompound)nbtTag.tagAt(i);

			byte slot = nbt.getByte("Slot");

			if(slot >= 0 && slot < 7);
			{

				ItemStack itemStack = ItemStack.loadItemStackFromNBT(nbt);
				Item item = itemStack.getItem();

				this.currentSlots[i] = itemStack;

				if(item instanceof IAccessory)
				{

					IAccessory accessory = (IAccessory)item;

					accessory.tick(player);

				}

			}

		}

	}

	for(int i = 0;i < 7;i++)
	{

		ItemStack itemStack1 = this.lastSlots[i];
		ItemStack itemStack2 = this.currentSlots[i];

		if(!ItemStack.areItemStacksEqual(itemStack1, itemStack2))
		{

			if(itemStack2 != null && itemStack2.getItem() instanceof IAccessory)
			{

				IAccessory accessory = (IAccessory)this.currentSlots[i].getItem();

				accessory.equipped(player);

			}

			if(itemStack1 != null && itemStack1.getItem() instanceof IAccessory)
			{

				IAccessory accessory = (IAccessory)this.lastSlots[i].getItem();

				accessory.unequipped(player);

			}

		}

	}

	System.arraycopy(this.currentSlots, 0, this.lastSlots, 0, this.lastSlots.length);

}

}

 

Kain

Link to comment
Share on other sites

Hi

 

Well I'm stumped now.  I can't see any problem in the code you've got here.

Perhaps if you add a few diagnostic statements it might become clearer, eg see below.  If you run it, equip and unequip, then paste the relevant bits of your console output to here, I'll have a look and see if there are any clues...

 

-TGG

 

		if(playerNBT != null)
	{
// etc
	}

System.out.print(  "lastSlots[0]:" + (this.lastSlots[0] == null) ? "null" : this.lastSlots[0].itemID
            +", currentSlots[0]:" + (this.currentSlots[0] == null) ? "null" : this.currentSlots[0]);

	for(int i = 0;i < 7;i++)
	{

		ItemStack itemStack1 = this.lastSlots[i];
		ItemStack itemStack2 = this.currentSlots[i];

		if(!ItemStack.areItemStacksEqual(itemStack1, itemStack2))
		{
if (i == 0) System.out.print("not equal ");
			if(itemStack2 != null && itemStack2.getItem() instanceof IAccessory)
			{
if (i == 0) System.out.print(" equip"); 

				IAccessory accessory = (IAccessory)this.currentSlots[i].getItem();

				accessory.equipped(player);

			}

			if(itemStack1 != null && itemStack1.getItem() instanceof IAccessory)
			{
if (i == 0) System.out.print(" unequip"); 

				IAccessory accessory = (IAccessory)this.lastSlots[i].getItem();

				accessory.unequipped(player);

			}

		}

	}
System.out.println(" copied");		
	System.arraycopy(this.currentSlots, 0, this.lastSlots, 0, this.lastSlots.length);

Link to comment
Share on other sites

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.