Jump to content

[1.9.4] Strange issue with capabilities


Recommended Posts

I have a very strange issue with capabilities losing their state on client side when connected to dedicated server. They basically default to the default value that's set when they are initialized for the given ItemStack. However what's even more strange is the fact that if I put breakpoint in to check for the default value and it stops there when I try to retrieve the capabilities again (ItemStack.capabilities) they have the correct state (not the default one that it just evaluated to in breakpoint)


I was trying to debug the issue and stopped when I was in EntityPlayer onUpdate (looking at itemstack.capabilities):

if (!ItemStack.areItemStacksEqual(this.itemStackMainHand, itemstack))
            if (!ItemStack.areItemsEqualIgnoreDurability(this.itemStackMainHand, itemstack))

            this.itemStackMainHand = itemstack == null ? null : itemstack.copy();


It's always the same - breakpoint set to stop on default value which it does and even if I have watches set to show me the capabilities value they would show the default, but the moment I start editing them and just hit enter they would show the correct state.


It almost seems as if there was some async call happening which wouldn't be done when the caps are queried by breakpoint, but is done immediately after. But I don't believe there is anything like that in there.


Any thoughts on what could be causing this?


The primary issue that I have with this is that I use the caps to store charge of staff of flight (Rending Gale) and thus it needs to understand client side if there is a charge and player can still fly. However as it stands it breaks mid air quite a bit.

The same code doesn't seem to have any issues in 1.9 so I suspect some 1.9.4 change.

Link to comment
Share on other sites

So I have figured out what's going on here.


Basically it relates to packets and a recent forge change. When I start using the flight stuff capabilities get modified and because there was a change to forge which made capabilities part of ItemStack.areItemStackTagsEqual comparison it figures out that stacks are different. https://github.com/MinecraftForge/MinecraftForge/commit/9df1e4b11e0d2d0fbf938cedae2da130d40cca89


Which then triggers SPacketSetSlot to be sent to client, which would be ok if this actually included capabilities. However that is not the case and it only syncs stackTagCompound. Which means that deserialized itemstack on client gets capabilities set to default value.


I have my own packet that syncs the capability I need, however packets based on what I have seen seem to be treated async, which means that I am not guaranteed that the capability value gets synced before client starts using it. Thus client a lot of the times suddenly sees 0 in the Staff's charge and stops flying.


Now the question is what should be the solution here.

Should forge make a change and sync capabilities in SetStackInSlot given that it uses capability value to see if the packet needs to be sent?

Or should it start ignoring capability comparison in this case again to avoid sending slots that delete capability data on client?


Or is the solution really for my case to save capability data on player to avoid this issue? That would seem like an awkward one to me, but at the moment seems like the only solution on the mod side apart from reverting to looking at just charge at the start minus ItemUseDuration and approximating how much charge is still remaining.

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.

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.


  • Recently Browsing

    • No registered users viewing this page.
  • Posts

    • I want to download Forge 1.20.6, but when I press download, it redirects me to Adfocus and does not provide any download. I have never encountered such a problem when I downloaded Forge 1.18.2 at least 12 months ago.
    • did you find any solutions? i have the same problem and also that mahito doesnt transform
    • Here's a simple example to solve this particular issue: public class ModArmorMaterials { public static final DeferredRegister<ArmorMaterial> ARMORS = DeferredRegister.create(Registries.ARMOR_MATERIAL, MyModName.MOD_ID); public static final RegistryObject<ArmorMaterial> COPPER = registerArmor("copper", Util.make(new EnumMap<>(ArmorItem.Type.class), enumMap -> { enumMap.put(ArmorItem.Type.BOOTS, 1); enumMap.put(ArmorItem.Type.LEGGINGS, 4); enumMap.put(ArmorItem.Type.CHESTPLATE, 5); enumMap.put(ArmorItem.Type.HELMET, 2); enumMap.put(ArmorItem.Type.BODY, 4); }), 12, SoundEvents.ARMOR_EQUIP_IRON, 0.0F, 0.0F, () -> Ingredient.of(Items.COPPER_INGOT)); private static RegistryObject<ArmorMaterial> registerArmor(String pGroup, EnumMap<ArmorItem.Type, Integer> pEnumMap, int pEnchantmentValue, Holder<SoundEvent> pEquipSound, float pToughness, float pKnockbackResistance, Supplier<Ingredient> pRepairIngredient) { List<ArmorMaterial.Layer> pLayerList = List.of(new ArmorMaterial.Layer(new ResourceLocation(pGroup))); return registerArmor(pGroup, pEnumMap, pEnchantmentValue, pEquipSound, pToughness, pKnockbackResistance, pRepairIngredient, pLayerList); } private static RegistryObject<ArmorMaterial> registerArmor( String pGroup, EnumMap<ArmorItem.Type, Integer> pEnumMap, int pEnchantmentValue, Holder<SoundEvent> pEquipSound, float pToughness, float pKnockbackResistance, Supplier<Ingredient> pRepairIngredient, List<ArmorMaterial.Layer> pLayerList) { return ARMORS.register(pGroup, () -> new ArmorMaterial(pEnumMap, pEnchantmentValue, pEquipSound, pRepairIngredient, pLayerList, pToughness, pKnockbackResistance)); } public static void register(IEventBus eventBus) { ARMORS.register(eventBus); } } Essentially, the TierSortingRegistry has been removed and so you now need to set up your own DeferredRegister. Please see the minecraftforge GitHub for more information; I found this solution through their issues (https://github.com/MinecraftForge/MinecraftForge/issues/9961)
    • How did I even leave that in there? I’ll try it in a bit, that very well could be it.
  • Topics

  • Create New...

Important Information

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