Jump to content

Recommended Posts

Posted

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?

Posted

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.

Posted

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

Posted

A request/response system may work, I haven't really tried something like that myself.

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.

Posted

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?

Posted

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.

Posted

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.

Posted

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.

Posted

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

Posted

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.

Posted

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.

Posted

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.

Posted

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.

Posted

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

Posted

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.

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



  • Recently Browsing

    • No registered users viewing this page.
  • Posts

    • Looking to save big on your next Temu purchase? Our exclusive Temu coupon code 100€ off is here to help you unlock incredible discounts. By using the code acs670886, customers across European nations can enjoy maximum benefits on their orders. This code is tailored to provide significant savings for shoppers in countries like Germany, France, Italy, and Switzerland. Don't miss out on this opportunity to use our Temu coupon 100€ off and Temu 100 off coupon code for substantial savings on your favorite items. What Is The Coupon Code For Temu 100€ Off? Both new and existing customers can reap the rewards of our exclusive Temu coupon 100€ off. By applying this code to your orders on the Temu app and website, you can unlock a range of amazing benefits. acs670886: Enjoy a flat 100€ off your purchase.   acs670886: Receive a 100€ coupon pack for multiple uses.   acs670886: Get a 100€ flat discount for new customers.   acs670886: Unlock an extra 100€ promo code for existing customers.   acs670886: Enjoy a 100€ coupon for European users.   Temu Coupon Code 100€ Off For New Users In 2025 New users can experience the ultimate Temu shopping experience with our exclusive coupon code. By applying the acs670886 code on the Temu app, you can unlock a host of incredible benefits   acs670886: Get a flat 100€ discount as a new user.   acs670886: Receive a 100€ coupon bundle exclusively for new customers.   acs670886: Enjoy an up to 100€ coupon bundle for multiple uses.   acs670886: Benefit from free shipping all over European Nations, such as Germany, France, Italy, Switzerland, etc.   acs670886: Get an extra 30% off on any purchase during your first order.   How To Redeem The Temu Coupon 100€ Off For New Customers? To redeem your Temu 100€ coupon and Temu 100€ off coupon code for new users, follow these simple steps: Download the Temu app or visit the Temu website.   Create a new account.   Browse and add your desired items to your cart.   Proceed to the checkout page.   Locate the "Apply Coupon" or "Promo Code" field.   Enter the code acs670886 and click "Apply."   Verify that the discount has been applied to your total.   Complete your purchase and enjoy your savings. Temu Coupon 100€ Off For Existing Customers Existing Temu users can also enjoy fantastic savings with our exclusive coupon code. By applying the acs670886 code, you can unlock a range of exciting benefits: acs670886: Get 100€ extra discount for existing Temu users.   acs670886: Receive a 100€ coupon bundle for multiple purchases.   acs670886: Enjoy a free gift with express shipping all over Europe.   acs670886: Get up to 70% off on top of existing discount.   acs670886: Benefit from free shipping in the European Nations, such as Germany, France, Italy, Spain, Switzerland, etc. How To Use The Temu Coupon Code 100€ Off For Existing Customers? To use the Temu coupon code 100€ off and Temu coupon 100€ off code as an existing customer, follow these steps: Log in to your existing Temu account.   Browse through the available products and add your desired items to your cart.   Proceed to checkout.   Enter the acs670886 coupon code in the designated field.   Click "Apply" to see the discount reflected in your order total.   Complete your purchase and enjoy your savings Latest Temu Coupon 100€ Off First Order Customers can unlock the highest benefits when they use our coupon code during their first order. By applying the acs670886 code, you can enjoy: acs670886: Flat 100€ discount for the first order.   acs670886: 100€ Temu coupon code for the first order.   acs670886: Up to 100€ coupon for multiple uses.   acs670886: Free shipping to European countries.   acs670886: Extra 30% off on any purchase for first order in Germany, France, Italy, Switzerland, Spain, etc How To Find The Temu Coupon Code 100€ Off? Finding the latest and working Temu coupon 100€ off and Temu coupon 100€ off Reddit codes is easier than you might think. Sign up for the Temu newsletter: Stay updated on the latest promotions, exclusive offers, and coupon codes by subscribing to the Temu newsletter.   Visit Temu's social media pages: Follow Temu on social media platforms like Facebook, Instagram, and Twitter to stay informed about the latest deals and coupon codes.  
    • Looking to save big on your next Temu purchase? Our exclusive Temu coupon code $100 off is here to help you do just that. By using the code acs670886, shoppers in the USA, Canada, and Europe can unlock maximum benefits, including significant discounts and exclusive offers. This code is designed to provide unparalleled savings for both new and existing customers. Don't miss out on the opportunity to use our Temu coupon $100 off and Temu 100 off coupon code to enhance your shopping experience. Start saving today with these incredible deals. What Is The Coupon Code For Temu $100 Off? Both new and existing customers can enjoy amazing benefits by using our Temu coupon $100 off on the Temu app and website. This $100 off Temu coupon is your ticket to substantial savings. acs670886: Flat $100 off your purchase.   acs670886: $100 coupon pack for multiple uses.   acs670886: $100 flat discount for new customers.   acs670886: Extra $100 promo code for existing customers.   acs670886: $100 coupon for USA/Canada users.   Temu Coupon Code $100 Off For New Users In 2025 New users can reap the highest benefits by applying our Temu coupon $100 off on the Temu app. This Temu coupon code $100 off is tailored to provide maximum savings for first-time shoppers. acs670886: Flat $100 discount for new users.   acs670886: $100 coupon bundle for new customers.   acs670886: Up to $100 coupon bundle for multiple uses.   acs670886: Free shipping to 68 countries.   acs670886: Extra 30% off on any purchase for first-time users.   How To Redeem The Temu Coupon $100 Off For New Customers? To redeem the Temu $100 coupon and Temu $100 off coupon code for new users, follow these steps: Download the Temu app or visit the Temu website.   Sign up for a new account.   Browse and add items to your cart.   Proceed to checkout.   Enter the code acs670886 in the promo code field.   Enjoy your $100 discount and additional benefits.   Temu Coupon $100 Off For Existing Customers Existing users aren't left out! By using the Temu $100 coupon codes for existing users, you can continue to enjoy substantial savings. Plus, benefit from Temu coupon $100 off for existing customers free shipping. acs670886: $100 extra discount for existing Temu users.   acs670886: $100 coupon bundle for multiple purchases.   acs670886: Free gift with express shipping all over the USA/Canada.   acs670886: Extra 30% off on top of the existing discount.   acs670886: Free shipping to 68 countries.   How To Use The Temu Coupon Code $100 Off For Existing Customers? To utilize the Temu coupon code $100 off and Temu coupon $100 off code as an existing user: Log in to your Temu account on the app or website.   Add desired items to your cart.   Proceed to checkout.   Enter the code acs670886 in the promo code section.   Apply the code and enjoy your discounts and free shipping.   Latest Temu Coupon $100 Off First Order Make your first purchase memorable with our Temu coupon code $100 off first order. This Temu coupon code first order ensures that Temu coupon code $100 off first time user benefits are maximized. acs670886: Flat $100 discount for the first order.   acs670886: $100 Temu coupon code for the first order.   acs670886: Up to $100 coupon for multiple uses.   acs670886: Free shipping to 68 countries.   acs670886: Extra 30% off on any purchase for the first order.   How To Find The Temu Coupon Code $100 Off? Discovering the Temu coupon $100 off and Temu coupon $100 off Reddit is straightforward: Sign up for the Temu newsletter to receive verified and tested coupons.   Follow Temu’s social media pages for the latest coupons and promotions.   Visit trusted coupon sites to find the latest and working Temu coupon codes.   Is Temu $100 Off Coupon Legit? Absolutely! Our Temu $100 Off Coupon Legit and Temu 100 off coupon legit codes, including acs670886, are genuine. Customers can safely use our Temu coupon code to get $100 off on their first order and subsequent purchases. Our code is not only legit but also regularly tested and verified. Moreover, our Temu coupon code is valid worldwide and doesn't have any expiration date.  
    • Looking to save big on your next Temu purchase? Our exclusive Temu coupon code $100 off is here to help you maximize your savings. By using the code acs670886, customers in the USA, Canada, and Europe can unlock significant discounts and exclusive offers. This code is designed to provide maximum benefits for shoppers across these regions. Don't miss out on the incredible deals available with our Temu coupon $100 off and Temu 100 off coupon code. Start saving today! What Is The Coupon Code For Temu $100 Off? Both new and existing customers can enjoy amazing benefits by using our Temu coupon $100 off on the Temu app and website. This $100 off Temu coupon is your ticket to substantial savings. acs670886: Flat $100 off your total purchase.   acs670886: Access a $100 coupon pack for multiple uses.   acs670886: Enjoy $100 off as a new customer.   acs670886: Extra $100 promo code benefits for existing customers.   acs670886: Exclusive $100 coupon for users in the USA/Canada.   Temu Coupon Code $100 Off For New Users In 2025 New users can get unmatched savings with the Temu coupon $100 off and Temu coupon code $100 off. Use our exclusive code to unlock these amazing benefits: acs670886: Flat $100 discount for first-time shoppers.   acs670886: A $100 coupon bundle for new customers.   acs670886: Up to $100 off for multiple uses.   acs670886: Free shipping to 68 countries worldwide.   acs670886: An additional 30% off on your first purchase.   How To Redeem The Temu Coupon $100 Off For New Customers? To use the Temu $100 coupon and Temu $100 off coupon code for new users, follow these steps: Visit the Temu website or download the app.   Create a new account.   Browse and add items to your cart.   Proceed to checkout.   Enter the coupon code “acs670886” in the promo field.   Click “Apply” to see the discount.   Complete the payment and enjoy your savings.   Temu Coupon $100 Off For Existing Customers Existing users can also benefit from our Temu $100 coupon codes for existing users and Temu coupon $100 off for existing customers free shipping. Use “acs670886” to unlock these perks: acs670886: Extra $100 discount for loyal Temu users.   acs670886: A $100 coupon bundle for multiple purchases.   acs670886: Free gift with express shipping across the USA/Canada.   acs670886: Additional 30% off on top of existing discounts.   acs670886: Free shipping to 68 countries.   How To Use The Temu Coupon Code $100 Off For Existing Customers? To use the Temu coupon code $100 off and Temu coupon $100 off code, follow these steps: Log in to your Temu account.   Select items and add them to your cart.   Enter the coupon code “acs670886” at checkout.   Apply the code and confirm the discount.   Proceed with payment and enjoy exclusive offers.   Latest Temu Coupon $100 Off First Order First-time shoppers can enjoy maximum benefits with the Temu coupon code $100 off first order, Temu coupon code first order, and Temu coupon code $100 off first time user. Use the “acs670886” code to unlock these offers: acs670886: Flat $100 off on your first order.   acs670886: A $100 Temu coupon pack for first-time buyers.   acs670886: Up to $100 off for multiple uses.   acs670886: Free shipping to 68 countries.   acs670886: Additional 30% discount for first-time purchases.   How To Find The Temu Coupon Code $100 Off? Discover verified Temu coupon $100 off and Temu coupon $100 off Reddit deals by subscribing to the Temu newsletter. Check Temu’s social media pages for the latest promos or visit trusted coupon websites for regularly updated offers. Is Temu $100 Off Coupon Legit? Yes, the Temu $100 Off Coupon Legit and Temu 100 off coupon legit. Our code “acs670886” is tested, verified, and works globally. Use it confidently for discounts on both first and recurring orders. Our Temu coupon code is valid worldwide and doesn't have any expiration date. How Does Temu $100 Off Coupon Work? The Temu coupon code $100 off first-time user and Temu coupon codes 100 off apply a $100 discount at checkout. The discount is applied to the total price of your order before taxes and shipping costs
    • Looking for the best way to save big on your Temu purchases? Look no further than the Temu coupon code $100 off, which brings you massive savings with just a few clicks. One of the most powerful coupon codes right now is acs670886. This Temu coupon code will give maximum benefits for people residing in the USA, Canada, and European nations. With the Temu coupon $100 off and Temu 100 off coupon code, you can unlock exclusive deals and discounts that make shopping on Temu even more rewarding. What Is The Coupon Code For Temu $100 Off? Whether you're a new or returning customer, this exclusive code opens the door to amazing savings on the Temu app and website. Just apply the Temu coupon $100 off or $100 off Temu coupon and enjoy discounts you can't find anywhere else. acs670886 – Flat $100 off instantly on eligible purchases.   acs670886 – Enjoy a $100 coupon pack for multiple uses.   acs670886 – Get $100 flat discount as a welcome gift for new customers.   acs670886 – Extra $100 promo code tailored especially for existing customers.   acs670886 – $100 coupon specially designed for users in the USA and Canada.   Temu Coupon Code $100 Off For New Users In 2025 If you're signing up for the first time, you're in for the best deal Temu has to offer. New users can enjoy huge discounts simply by using our verified coupon. With the Temu coupon $100 off and Temu coupon code $100 off, your first-time shopping experience is guaranteed to be budget-friendly. acs670886 – Unlock a flat $100 discount for new users.   acs670886 – Get a $100 coupon bundle on your first order.   acs670886 – Use up to $100 in coupon benefits across multiple purchases.   acs670886 – Get free shipping to 68 countries including the USA and Canada.   acs670886 – First-time users also get an extra 30% off on any purchase.   How To Redeem The Temu Coupon $100 Off For New Customers? To redeem the Temu $100 coupon or the Temu $100 off coupon code for new users, simply follow these steps: Download the Temu app or visit the official website.   Sign up with a valid email address.   Add your favorite products to the cart.   Go to checkout and apply the coupon code acs670886.   See your total drop instantly as the coupon is applied.   Temu Coupon $100 Off For Existing Customers Already a Temu shopper? Don't worry – there’s still something special for you. By using our exclusive code, loyal users also get access to massive savings. With Temu $100 coupon codes for existing users and Temu coupon $100 off for existing customers free shipping, everyone gets a reason to smile while shopping. acs670886 – Get a $100 extra discount for existing Temu users.   acs670886 – Receive a $100 coupon bundle to use across multiple purchases.   acs670886 – Enjoy a free gift with express shipping throughout the USA and Canada.   acs670886 – Add an extra 30% discount on top of your current promotions.   acs670886 – Free shipping available to 68 countries worldwide.   How To Use The Temu Coupon Code $100 Off For Existing Customers? To redeem the Temu coupon code $100 off or Temu coupon $100 off code as an existing user, follow these easy steps: Open your Temu app or go to the official site.   Log in using your existing account credentials.   Shop as usual and add items to your cart.   Proceed to checkout and input acs670886 in the promo code section.   Enjoy the instant discount and perks that come with it.   Latest Temu Coupon $100 Off First Order If you're planning to place your first order on Temu, you're in luck. Use our code and unlock the biggest deal on your first-time purchase. With Temu coupon code $100 off first order, Temu coupon code first order, and Temu coupon code $100 off first time user, you're starting your shopping journey the right way. acs670886 – Get a flat $100 discount on your first order.   acs670886 – Apply the $100 Temu coupon code at checkout for instant savings.   acs670886 – Receive up to $100 in coupons usable over multiple orders.   acs670886 – Benefit from free shipping to over 68 countries.   acs670886 – Score an extra 30% discount on your entire first order.   How To Find The Temu Coupon Code $100 Off? Wondering how to discover verified deals? It's easier than you think. To find the best and latest Temu coupon $100 off or Temu coupon $100 off Reddit shared deals, follow these tips: Sign up for the Temu newsletter and get access to exclusive promo codes.   Follow Temu on social media platforms like Facebook, Instagram, and Twitter for real-time coupon announcements.   Visit reputable coupon-sharing websites (like ours!) to access the most up-to-date and verified codes like acs670886.   Is Temu $100 Off Coupon Legit? Yes, it absolutely is! If you're wondering whether the Temu $100 Off Coupon Legit or Temu 100 off coupon legit, we're here to clear the air. Our verified code acs670886 has been tested and confirmed to work by thousands of happy shoppers across the USA, Canada, and Europe. So, when you use this code, you're not just saving money—you're also using a 100% legit and verified deal that’s designed to help you shop smarter. Happy shopping and big savings await when you use acs670886!  
    • Maybe it refers to an issue with Java 8   Install this version: https://www.azul.com/downloads/?version=java-8-lts&os=windows&architecture=x86-64-bit&package=jre#zulu In your Launcher, change the Java Executable o the new java 8 installation at C:\Program Files\Zulu\zulu-8-jre\bin\javaw.exe
  • Topics

×
×
  • Create New...

Important Information

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