Jump to content

[1.10.2] Capabilities for ItemStacks


hugo_the_dwarf

Recommended Posts

Currently so far I've been dealing with Entities and I seem to have that handled fairly well.

 

I have an Attribute Capability that can be on Entities and items (I can easily modify the provider and constructors to take and save an ItemStack as well as an Entity, easy)

 

My question is will I have to create update packets for ItemStack Capabilities or will it be handled like NBT is (more or less synced automatically by MC all ready)

If I need to create these update events, when should I have them "query" the server for their information? Player Update event (check inventory, see if needs to be updated, ask server, get response)

 

Also the current way I'm using it:

@SubscribeEvent
    public void onAddCapabilities(AttachCapabilitiesEvent.Entity e) 
{
	if (canHaveAttributes(e.getEntity()))
	{
		EntityLivingBase ent = (EntityLivingBase)e.getEntity();

		if (ent instanceof EntityPlayer)
			e.addCapability(CapPlayerExtraProvider.KEY, new CapPlayerExtraProvider(ent));

		e.addCapability(CapAttributeProvider.KEY, new CapAttributeProvider(ent));
	}
    }

 

says the subEvent is deprecated, what is the new/upcoming correct way to use this?

Link to comment
Share on other sites

Syncing of item capabilities is tricky. Capability-only changes to an

ItemStack

in a server-side

Container

will cause an

SPacketSetSlot

to be sent for the slot, but this doesn't include the capability data so the client-side copy of the capability data will be reset to the default.

 

There are two open PRs with different fixes for this: #3099 and #3283. If either of these are merged, it should simplify the situation a bit.

 

One way to handle the syncing currently is to register an

IContainerListener

, as described in this thread.

 

The sub-events of

AttachCapabilitiesEvent

were deprecated in this commit with the addition of generic filtering of events. Instead of

AttachCapabilitiesEvent.Entity

, use

AttachCapabilitiesEvent<Entity>

.

Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.

Link to comment
Share on other sites

Hmm..

Ok so I updated the event to what you suggested, no issues, good.

 

I might have to stick with ye olde NBT read and write that I had before, However Once something for ItemStacks becomes a little easier I'll be converting ASAP. Going by the thread the asker had to do quite a bit of tinkering just to get the attach and removal of listeners.

 

Since the Cap is still server-side and most of my mechanics are server-side (events) would be fine, only issue is allowing the player to read what is added to the item (client-side) as their stats only take place once the player is holding (main or offhand) or wearing the piece. But would be nice to see if the stats are harmful before putting on/holding

 

The reads mainly happened every few seconds before or when hovering over an item "ItemTooltipEvent" which I guess if I really wanted to, I could just have it check during that event to update the cap if the default cap had a "boolean needsUpdate = true" to ask the server the stacks real cap.

 

Would that work? (Using a request/reponse packet system in the ItemTooltipEvent) As when wearing gear or holding something, it's the server that tallies up all the values, and just fires a packet off (if it needs to) to update the client for any GUIs I use

Link to comment
Share on other sites

Ah Crud, just remembered, When a mob is killed. I had random loot drop based on how tough it was, likewise the toughness of the mob determined the stats of the loot dropped (if valid equipment type)

 

Now the mob stats are easy to get (the loot table) it's having the Items get their stats rolled based on the dead mob's power. Does the "Attach Capability" event trigger as soon as "New ItemStack" is called?

 

Likewise I do this for crafting too (ItemCraftedEvent) so players have a chance to at least make some gear that has some ok stats so they can start the grind.

 

Q:

When does an ItemStack get it's Capability Attached? Right as it is created in code via New ItemStack?

Link to comment
Share on other sites

AttachCapabilitiesEvent.Item

is fired from

ItemStack#setItem

, which is called from the

ItemStack

constructor.

 

In general,

AttachCapabilitiesEvent

will be fired before you have access to any dynamic data.

AttachCapabilitiesEvent.Item

gives you the

ItemStack

and

Item

,

AttachCapabilitiesEvent<TileEntity>

and

AttachCapabilitiesEvent<Entity>

give you the

TileEntity

/

Entity

before it's been constructed and read from NBT,

AttachCapabilitiesEvent<World>

gives you the

World

when it's mostly initialised.

 

You'll need to generate the random stats for the item when it's crafted or dropped by a mob, not in

AttachCapabilitiesEvent

.

Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.

Link to comment
Share on other sites

So far is the "AttachCapabilitiesEvent<>" the only way to put capabilities on? Only wondering because I was thinking of adding "Unique" look items (weapons) that are not from the standard ItemTool/ItemSword era IE Baked_Potato. However I don't want to put the capability on ALL items just certain types.

 

And in this case a Bake_Potato does not fall into that list. Now this item will be created during a mobs death so created by me dynamically, is there anyway to attach a capability to an item even if it doesn't make it through the check for the event?

 

Item created

Event checks

Fails Item Instance pass

Is from unique item list

Attach Capability?

apply unique stats

apply custom name and enchantment (to give the shiny effect)

 

I'm trying to stay away from adding new blocks and items if I can, as I'd like my mod to be something like the Infernal Mobs mod where it doesn't add new content just new mechanics and can adapt to any other mod. And also reuse all Vanilla items/blocks if I can.

 

Idk the impact of adding a capability to ALL items. If there is no impact at all then I will go ahead and just slap it on, then check if it's the correct item type or a unique to roll stats

 

EDIT:

 

Ran into an issue with my idea for the request/response. The toolTipEvent doesn't supply a "Item current index" and I don't have any other ID's to use to try to toss to the server asking for "get Cap from ItemStack in player inventory at INDEX" then return it (with index) and update it on the client.

 

How would I go about getting what item the player is looking at/mouse is hovering over? Was thinking of using a loop to go through the players inventory and match the itemstack 1=1 but I think if I had say two Iron Swords and I was looking at the sword deeper in the inventory the one that was higher up on the list would be returned instead.

Link to comment
Share on other sites

AttachCapabilitiesEvent

is the only way to attach a capability to an external object, so you'll need to attach the capability to all potential

Item

s and then check if an

ItemStack

is allowed to have stats before you do anything stat-related with it.

 

There shouldn't be much impact of adding a capability to all

Item

s, as long as your

ICapabilityProvider

doesn't do anything expensive in

hasCapability

/

getCapability

it should just be one more iteration of the loops in

CapabilityDispatcher

's implementations of these methods.

 

ItemTooltipEvent

gives you the

ItemStack

, so you can search the player's inventory to find the slot containing the same

ItemStack

(i.e. use

==

instead of checking for equivalency).

Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.

Link to comment
Share on other sites

So ran into a different issue. For attaching capabilities I was using:

@SubscribeEvent

public void onAddCapabilitiesItemStack(AttachCapabilitiesEvent<ItemStack> e)

 

wondering why nothing was getting a capability looked at the documentation and i'm supposed to use <Item>

 

changed it, and some console.outs are telling me things are now being set. However I don't think my provider is working correctly. Anyone have an example of attaching Capabilities to Items? because I've noticed only ItemStack has getCapability()

 

[spoiler=Capability]

package htd.rot.capability.attribute;

import java.util.concurrent.Callable;

import net.minecraft.nbt.NBTBase;
import net.minecraft.util.EnumFacing;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.capabilities.CapabilityInject;
import net.minecraftforge.common.capabilities.CapabilityManager;

public class CapAttribute {
@CapabilityInject(CapAttributeData.class)
public static Capability<CapAttributeData> CAPABILITY = null;

public static void register()
{
	CapabilityManager.INSTANCE.register(CapAttributeData.class, new StorageHelper(), new DefaultInstanceFactory());
}

public static class StorageHelper implements Capability.IStorage<CapAttributeData> {

	@Override
	public NBTBase writeNBT(Capability<CapAttributeData> capability, CapAttributeData instance, EnumFacing side)
	{
		return instance.writeData();
	}

	@Override
	public void readNBT(Capability<CapAttributeData> capability, CapAttributeData instance, EnumFacing side,
			NBTBase nbt)
	{
		instance.readData(nbt);
	}
}

public static class DefaultInstanceFactory implements Callable<CapAttributeData> {
	@Override
	public CapAttributeData call() throws Exception
	{
		return new CapAttributeData();
	}
}
}

 

 

[spoiler=CapabilityData]

package htd.rot.capability.attribute;

import java.util.Random;

import htd.rot.capability.playerextra.CapPlayerExtra;
import htd.rot.capability.playerextra.CapPlayerExtraData;
import htd.rot.libs.HTDDataInfo;
import htd.rot.managers.PlayerCPTypeManager;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.item.Item;
import net.minecraft.nbt.NBTBase;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.math.BlockPos;

public class CapAttributeData {
private EntityLivingBase entity;
private Item item;

public int[] attributes = new int[HTDDataInfo.ATTRIBUTE_TAGS.length];

public float[] stats = new float[HTDDataInfo.STAT_TAGS.length];

public boolean isExhausted = false, needsUpdate = true;

public CapAttributeData()
{
	initData();
}

public EntityLivingBase getEntity()
{
	return entity;
}

public void setEntity(EntityLivingBase entity)
{
	this.entity = entity;
}

public Item getItem()
{
	return item;
}

public void setItem(Item item)
{
	this.item = item;
}

private void initData()
{
	for (int index = 0; index < attributes.length; index++)
	{
		attributes[index] = HTDDataInfo.attributes[index];
	}

	for (int index = 0; index < stats.length; index++)
	{
		stats[index] = HTDDataInfo.stats[index];
	}
}

// Stamina
public boolean needsStam()
{
	return stats[HTDDataInfo.STAM] < HTDDataInfo.MAX_STAM_MANA;
}

public boolean consumeStam(float cost)
{
	float adjustedCost = (cost * getAdjustedStamCostPercent(cost));
	if (stats[HTDDataInfo.STAM] - adjustedCost >= 0)
	{
		stats[HTDDataInfo.STAM] -= adjustedCost;
		return true;
	}
	return false;
}

public void regenStam()
{
	float amount = (stats[HTDDataInfo.VITALITY] * 0.0578f) + (stats[HTDDataInfo.BONUS_STAM_REGEN] * 0.20f);
	addStam(amount);
}

public void addStam(float amount)
{
	stats[HTDDataInfo.STAM] += (HTDDataInfo.MAX_STAM_MANA
			* (((getAdjustedMaxStam() + amount) / getAdjustedMaxStam()) - 1f));
	if (stats[HTDDataInfo.STAM] > HTDDataInfo.MAX_STAM_MANA)
		stats[HTDDataInfo.STAM] = HTDDataInfo.MAX_STAM_MANA;
}

public float getAdjustedMaxStam()
{
	CapPlayerExtraData playerExtra = entity.getCapability(CapPlayerExtra.CAPABILITY, null);
	float maxStam = HTDDataInfo.MAX_STAM_MANA;
	if (playerExtra != null && playerExtra.getCurrentClass() != -1)
		maxStam += (PlayerCPTypeManager.classes[playerExtra.getCurrentClass()].stamPerVitStat
				* attributes[HTDDataInfo.VITALITY])
				+ PlayerCPTypeManager.classes[playerExtra.getCurrentClass()].stats[HTDDataInfo.BONUS_STAM];
	else // Mobs
		maxStam += (5 * attributes[HTDDataInfo.VITALITY]);

	maxStam += stats[HTDDataInfo.BONUS_STAM];

	return maxStam;
}

public float getAdjustedCurrentStam()
{
	return getAdjustedMaxStam() * (stats[HTDDataInfo.STAM] / HTDDataInfo.MAX_STAM_MANA);
}

public float getAdjustedStamCostPercent(float cost)
{
	return 1f - ((getAdjustedMaxStam() - cost) / getAdjustedMaxStam());
}

// Mana
public boolean needsMana()
{
	return stats[HTDDataInfo.MANA] < HTDDataInfo.MAX_STAM_MANA;
}

public boolean consumeMana(float cost)
{
	float adjustedCost = (cost * getAdjustedManaCostPercent(cost));
	if (stats[HTDDataInfo.MANA] - adjustedCost >= 0)
	{
		stats[HTDDataInfo.MANA] -= adjustedCost;
		return true;
	}
	return false;
}

public void regenMana()
{
	float amount = (stats[HTDDataInfo.INTELLIGENCE] * 0.0578f) + (stats[HTDDataInfo.BONUS_MANA_REGEN] * 0.20f);
	addMana(amount);
}

public void addMana(float amount)
{
	stats[HTDDataInfo.MANA] += (HTDDataInfo.MAX_STAM_MANA
			* (((getAdjustedMaxMana() + amount) / getAdjustedMaxMana()) - 1f));
	if (stats[HTDDataInfo.MANA] > HTDDataInfo.MAX_STAM_MANA)
		stats[HTDDataInfo.MANA] = HTDDataInfo.MAX_STAM_MANA;
}

public float getAdjustedMaxMana()
{
	CapPlayerExtraData playerExtra = entity.getCapability(CapPlayerExtra.CAPABILITY, null);
	float maxMana = HTDDataInfo.MAX_STAM_MANA;
	if (playerExtra != null && playerExtra.getCurrentClass() != -1)
		maxMana += (PlayerCPTypeManager.classes[playerExtra.getCurrentClass()].manaPerIntStat
				* attributes[HTDDataInfo.INTELLIGENCE])
				+ PlayerCPTypeManager.classes[playerExtra.getCurrentClass()].stats[HTDDataInfo.BONUS_MANA];
	else // Mobs
		maxMana += (5 * attributes[HTDDataInfo.INTELLIGENCE]);

	maxMana += stats[HTDDataInfo.BONUS_MANA];

	return maxMana;
}

public float getAdjustedCurrentMana()
{
	return getAdjustedMaxMana() * (stats[HTDDataInfo.MANA] / HTDDataInfo.MAX_STAM_MANA);
}

public float getAdjustedManaCostPercent(float cost)
{
	return 1f - ((getAdjustedMaxMana() - cost) / getAdjustedMaxMana());
}

// Health
public float getAdjustedMaxHealth()
{
	CapPlayerExtraData playerExtra = entity.getCapability(CapPlayerExtra.CAPABILITY, null);
	float maxHP = entity.getMaxHealth() * HTDDataInfo.BASE_UPSCALE;

	if (playerExtra != null && playerExtra.getCurrentClass() != -1)
		maxHP += (PlayerCPTypeManager.classes[playerExtra.getCurrentClass()].hpPerVit
				* attributes[HTDDataInfo.VITALITY])
				+ PlayerCPTypeManager.classes[playerExtra.getCurrentClass()].stats[HTDDataInfo.BONUS_HP];
	else // Mobs
		maxHP += (5 * attributes[HTDDataInfo.VITALITY]);

	maxHP += stats[HTDDataInfo.BONUS_HP];

	return maxHP;
}

public float getAdjustedCurrentHealth()
{
	return getAdjustedMaxHealth() * (entity.getHealth() / entity.getMaxHealth());
}

public float getAdjustedDamagePercent(float damage)
{
	return 1f - ((getAdjustedMaxHealth() - damage) / getAdjustedMaxHealth());
}

public void rollStats()
{
	int[] attrs = new int[attributes.length];
	int lowerHeight = 62;
	int upperHeight = 100;

	int yHeight = (int) entity.posY;
	int heightBonus = 0;
	int sunlessDepth = 0;

	if (!entity.worldObj.canBlockSeeSky(new BlockPos(entity.posX, entity.posY, entity.posZ)))
	{
		for (int yOffset = 1; yOffset <= 50; yOffset++)
		{
			if (!entity.worldObj.canBlockSeeSky(new BlockPos(entity.posX, entity.posY + yOffset, entity.posZ)))
				sunlessDepth++;
			else
				break;
		}
	}

	if (yHeight < lowerHeight)
		heightBonus = (int) ((yHeight - lowerHeight) * 2.85f);
	else if (yHeight > upperHeight)
		heightBonus = yHeight - upperHeight;

	heightBonus = heightBonus < 0 ? heightBonus * -1 : heightBonus;

	int baseBonus = 5 + sunlessDepth;

	Random rand = new Random();
	for (int index = 0; index < attributes.length; index++)
	{
		attrs[index] = (baseBonus + (heightBonus <= 0 ? 0 : rand.nextInt(heightBonus))
				+ (sunlessDepth <= 0 ? 0 : rand.nextInt(sunlessDepth)));
	}
	attrs[HTDDataInfo.LIFE_STEAL] = 0;
	attrs[HTDDataInfo.MANA_STEAL] = 0;
	updateAttributes(attrs);
}

public void rollItemStats()
{
	int[] attrs = new int[attributes.length];
	int baseBonus = 5;

	Random rand = new Random();
	for (int index = 0; index < attributes.length; index++)
	{
		attrs[index] = (baseBonus + rand.nextInt(12));
	}
	attrs[HTDDataInfo.LIFE_STEAL] = 0;
	attrs[HTDDataInfo.MANA_STEAL] = 0;
	updateAttributes(attrs);
}

public NBTBase writeData()
{
	NBTTagCompound tag = new NBTTagCompound();
	for (int index = 0; index < attributes.length; index++)
	{
		tag.setInteger(HTDDataInfo.ATTRIBUTE_TAGS[index].trim().toLowerCase(), attributes[index]);
	}

	for (int index = 0; index < stats.length; index++)
	{
		tag.setFloat(HTDDataInfo.STAT_TAGS[index].trim().toLowerCase(), stats[index]);
	}

	return tag;
}

public void readData(NBTBase nbt)
{
	NBTTagCompound tag = (NBTTagCompound) nbt;
	for (int index = 0; index < attributes.length; index++)
	{
		attributes[index] = tag.getInteger(HTDDataInfo.ATTRIBUTE_TAGS[index].trim().toLowerCase());
	}

	for (int index = 0; index < stats.length; index++)
	{
		stats[index] = tag.getFloat(HTDDataInfo.STAT_TAGS[index].trim().toLowerCase());
	}
}

public Object[] compressData()
{
	Object[] data = new Object[attributes.length + stats.length];
	int dataIndex = 0;

	for (int index = 0; index < attributes.length; index++)
	{
		data[dataIndex++] = attributes[index];
	}

	for (int index = 0; index < stats.length; index++)
	{
		data[dataIndex++] = stats[index];
	}

	return data;
}

public void decompressData(Object[] data)
{
	int dataIndex = 0;

	for (int index = 0; index < attributes.length; index++)
	{
		attributes[index] = (int) data[dataIndex++];
	}

	for (int index = 0; index < stats.length; index++)
	{
		stats[index] = (float) data[dataIndex++];
	}

	updateAttributes(attributes);
}

public void updateAttributes(int[] attributes)
{
	int[] pulledAttributes = attributes;
	for (int index = 0; index < this.attributes.length; index++)
	{
		pulledAttributes[index] = pulledAttributes[index] > HTDDataInfo.ATTRIBUTE_MAX_LIMIT
				? HTDDataInfo.ATTRIBUTE_MAX_LIMIT : pulledAttributes[index];

		pulledAttributes[index] = pulledAttributes[index] < (HTDDataInfo.ATTRIBUTE_MAX_LIMIT * -1)
				? (HTDDataInfo.ATTRIBUTE_MAX_LIMIT * -1) : pulledAttributes[index];
	}
	pulledAttributes[HTDDataInfo.MAX_DAMAGE] = pulledAttributes[HTDDataInfo.MAX_DAMAGE] < pulledAttributes[HTDDataInfo.MIN_DAMAGE]
			? pulledAttributes[HTDDataInfo.MIN_DAMAGE] : pulledAttributes[HTDDataInfo.MAX_DAMAGE];
	this.attributes = pulledAttributes;
}
}

 

 

[spoiler=CapabilityProvider]

package htd.rot.capability.attribute;

import htd.rot.Rot;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.item.Item;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.capabilities.ICapabilityProvider;
import net.minecraftforge.common.capabilities.ICapabilitySerializable;

public class CapAttributeProvider implements ICapabilityProvider, ICapabilitySerializable<NBTTagCompound> {

public static final ResourceLocation KEY = new ResourceLocation(Rot.MODID, "htd_attributes");

private CapAttributeData INSTANCE = new CapAttributeData();

public CapAttributeProvider(EntityLivingBase entity)
{
	INSTANCE.setEntity(entity);
}

public CapAttributeProvider(Item item)
{
	INSTANCE.setItem(item);
}

@Override
public boolean hasCapability(Capability<?> capability, EnumFacing facing)
{
	return capability == CapAttribute.CAPABILITY;
}

@Override
public <T> T getCapability(Capability<T> capability, EnumFacing facing)
{
	if (capability == CapAttribute.CAPABILITY)
		return (T) INSTANCE;
	return null;
}

@Override
public NBTTagCompound serializeNBT()
{
	return (NBTTagCompound) CapAttribute.CAPABILITY.writeNBT(INSTANCE, null);
}

@Override
public void deserializeNBT(NBTTagCompound nbt)
{
	CapAttribute.CAPABILITY.readNBT(INSTANCE, null, nbt);
}

}

 

 

[spoiler=Event]

	@SubscribeEvent
public void onAddCapabilitiesItemStack(AttachCapabilitiesEvent<Item> e)
{
	if (canHaveAttributes(e.getObject()))
	{
		Console.out().println(e.getObject().getClass().getName());
		e.addCapability(CapAttributeProvider.KEY, new CapAttributeProvider(e.getObject()));
	}
}

public static boolean canHaveAttributes(Item item)
{
	if ((item instanceof ItemTool || item instanceof ItemSword || item instanceof ItemBow
			|| item instanceof ItemArmor || item instanceof ItemShield))
		return true;
	return false;
}

 

 

EDIT:

Updated my REPO found in my sig, incase I forgot a file that you'd want to look at

Link to comment
Share on other sites

ItemStack

is the class that implements

ICapabilityProvider

, so this is where you retrieve your capability instance from.

 

I can't see any obvious errors in your code.

 

I attach this provider for this capability to

Items.CLAY_BALL

here.

Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.

Link to comment
Share on other sites

Hmm... I made some tweaks and removed the "item" from the Capability as since the item is just the INSTANCE no point holding it as the ItemStack would hold more power..

 

The tweaks did nothing which isn't surpising. However this code doesn't seem to display what I intend, which is at the very bottom of this:

@SubscribeEvent
public void onItemToolTipUpdate(ItemTooltipEvent e)
{
	if (e.getItemStack().hasCapability(CapAttribute.CAPABILITY, null))
	{
		CapAttributeData cap = e.getItemStack().getCapability(CapAttribute.CAPABILITY, null);
		if (cap != null)
		{
			if (!cap.needsUpdate)
			{
				int ITEMS_PER_LINE = 2;
				int currentLineItems = 0;

				String lineItems = "";
				for (int index = 0; index < cap.attributes.length; index++)
				{
					if (currentLineItems < ITEMS_PER_LINE)
					{
						if (cap.attributes[index] != 0)
						{
							lineItems += HTDDataInfo.ATTRIBUTE_TAGS[index] + ": " + cap.attributes[index];
							currentLineItems++;
						}
					} else
					{
						e.getToolTip().add(lineItems);
						lineItems = "";
						currentLineItems = 0;
					}
				}
				if (currentLineItems > 0)
					e.getToolTip().add(lineItems);
				lineItems = "";
				currentLineItems = 0;
				for (int index = 0; index < cap.stats.length; index++)
				{
					if (currentLineItems < ITEMS_PER_LINE)
					{
						if (cap.stats[index] != 0)
						{
							lineItems += HTDDataInfo.STAT_TAGS[index] + ": " + cap.stats[index];
							currentLineItems++;
						}
					} else
					{
						e.getToolTip().add(lineItems);
						lineItems = "";
						currentLineItems = 0;
					}
				}
				if (currentLineItems > 0)
					e.getToolTip().add(lineItems);
			}
		} else
		{
			e.getToolTip().add("Unidentified...");
		}
	}

}

 

If there is a Capability on the ItemStack but since the capability on the client would be a fresh make of the Capability the Boolean needsUpdate will be true, triggering the code to say "This item is unidentified" to show in the toolTip at the bottom. This is also where I'd start putting the "search through inventories, find matching stack, return Inventory and Slot Id send to server. ask it for the updated capability, update client. And since this event runs "per tick" more or less once the data gets there it will be rendered in the toolTip.

 

So there is a great chance I have messed up somewhere.

Link to comment
Share on other sites

The

else

block that adds the

"Unidentified..."

tooltip is part of the

cap != null

if

statement instead of the

!cap.needsUpdate

if

statement, so it's only running when

cap == null

.

Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.

Link to comment
Share on other sites

Thank you very much, I must have just over complicated the whole darn thing. Thankfully I have a check to go through the equipped items and tally up the stats + class stats and send them off to the player. So even tho they all show up as "Unidentified" I can still see the stats in action via my GUI

 

Now it's getting this update request response system going.

Link to comment
Share on other sites

I've gotten it to the point where I'm happy, If the item is in another container. There is no way to to see what the items have "Unidentified..." but if you move them into your inventory and hover over they will update and show their colors. I'm wondering would it be possible to ask the forge team to let itemStacks hold a reference of their "current" inventory if not I think I'll look into some more events for when loot chests generate loot (so chests in dark places will have strong items) and maybe look into any container open events to try to get a packet sync system for external inventories

 

I've also updated my repo for anyone that wants to see how I did it.

 

htd.rot.managers.PacketManager

htd.rot.events.EventItemLogic

htd.rot.comms.packets.capabilities.CapAttributeItemRequestPacket

htd.rot.comms.packets.capabilities.CapAttributeItemResponsePacket

 

It's a bit messy for now since the player has like 3 inventories inside the InventoryPlayer (Main, Offhand, Armor)

Thanks for the help Choonster

Link to comment
Share on other sites

I'm glad you got it mostly working in the end.

 

I'd say it's unlikely that a PR to add an inventory reference to

ItemStack

will be accepted, since that would be a massive change to a lot of vanilla and mod code.

Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.

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.