Jump to content

HDainester

Members
  • Posts

    4
  • Joined

  • Last visited

HDainester's Achievements

Tree Puncher

Tree Puncher (2/8)

0

Reputation

  1. So, I seem to have found a fix/workaround for this bug. Simply override Item#onDroppedByPlayer (requires forge) to prevent the original drop action, and instead remove and drop the item from there. Here an example: @Override public boolean onDroppedByPlayer(ItemStack stack, Player player) { player.getInventory().removeItem(stack); player.drop(stack, true); return false; // prevents original drop action } I am still not really sure why this is necessary (I have my assumptions) or if I am updating my item tags wrong but for now I am happy that I got it to work. Still, I wouldn't mind of somebody with more insight would shed some light into the situation.
  2. So I have experimented around with the example project and could reproduce this bug with following alternatives: Changing the tag in an override of onUseTick() ExampleItem#onUseTick @Override public void onUseTick(Level level, LivingEntity living, ItemStack stack, int count) { if(!level.isClientSide) { stack.getOrCreateTag().putInt("test", (int)(1000*Math.random())); } } Changing the tag of only the main- or offhand item in an tick event handler for the LivingEntity holding the stack ExampleItem#update public static void update(LivingEntity entity) { var stack = entity.getMainHandItem(); var item = ExampleMod.EXAMPLE_ITEM.get(); if(!stack.is(item)) { stack = entity.getOffhandItem(); } if(stack.is(item)) { var tag = stack.getOrCreateTag(); tag.putInt("test", (int)(1000*Math.random())); } } ExampleMod // ... (static fields) public ExampleMod() { IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus(); ITEMS.register(modEventBus); modEventBus.addListener(this::commonSetup); } public void commonSetup(FMLCommonSetupEvent evt) { IEventBus bus = MinecraftForge.EVENT_BUS; bus.addListener((LivingEvent.LivingTickEvent e) -> ExampleItem.update(e.getEntity())); } I was also able to reproduce the bug while updating the tag only every 5 ticks, e.g. ExampleItem#update public static void update(LivingEntity entity) { if(entity.tickCount % 5 == 0) { // ... } } I could lower the update rate even more but I feel like that this would not be a real soution to the problem but rather making the bug less likely to occour (apart from beeing a little bit inconvenient). At this point I am really not sure anymore where and how to update tag values properly. It feels like I am missing something crucial. But looking at the source code of other mods (e.g. Botania or MiningGadgets) I cannot seem to figure out what they are doing different.
  3. Hi warjort, thanks for the answer. I have set up a repository with a minimal example illustrating the issue. You can find it here: https://gitlab.com/hd-mc-mods/examples/item-tick-bug . There is also a gif that shows how to reproduce the bug. For now I will look into how Botania did it (though maybe the bug went unnoticed on their side?! I will have to check I guess). Thanks for pointing that out! I indeed get the hunch that this might be the case considering I had no issues replicating the bug with a minimal example.
  4. What is my goal: Create an item with forge energy support. It is supposed to switch between an active and inactive state. It should drain energy while active and inside the inventory of an entity. What I am currently doing to archieve this: I have an override of inventoryTick() in my item class which currently looks like this: @Override public void inventoryTick(ItemStack stack, Level level, Entity entity, int i, boolean bl) { if(!level.isClientSide) { if(updateActive(stack, level, entity)) { // checks state of the 'active' boolean tag for(var stackInHand : entity.getHandSlots()) { if(stackInHand == stack) { updateLight(level, entity); // might cause some lag (places light blocks) break; } } // extractEnergy(stack, 1); stack.getOrCreateTag().putInt("energy", 1000 + (int)(1000*Math.random())); // for testing } } } Apart from that I have defined an ICapabilityProvider which provides an instance of my custom IEnergyStorage implementation (stores current energy of an ItemStack in the 'energy' tag). As can be seen in the snippet above I have disabled the the extractEnergy() call and modified the energy tag directly to ensure nothing is wrong with my IEnergyStorage implementation. What's the issue: It appears that sometimes when I drop an 'active' item into the world the entity is dropped but a ghost item stays in the slot of the player inventory. I could confirm with debug outputs that inventoryTick() is only called on the client side from that point on (checking the inventory slot with the data command also reports that no item exist in that slot). As soon as I open the inventory the ghost item becomes an actual item (i.e. it is beeing updated on the server side again) effectively duping the item. I have observed this behaviour only when dropping the item while the game is lagging (sometimes). Though even a minor lag spike could be enough I guess. In my case this can be caused by the updateLight() call (depending on the mod settings and the spec of the machine) since it places light blocks in the world causing some light updates. I use this call with high settings (i.e. placing many light blocks) to forcefully cause some lag to be able to somewhat consistently replicate this issue. I guess the information that the item was dropped does not reach the client. This is somewhat surprising to me since from my understanding this could happen to any item?! Though I have never observed this kind of bug with any other modded (or vanilla) item from what I can recall. Whats interesting is that if I remove the randomness from the tag value (e.g. stack.getOrCreateTag().putInt("energy", 1000)) the issue seems to be gone. Hence I came to the conclusion this might be tied to the tag values getting out of sync between the server and client. But I have no idea what to do about this. Minimal example: I have set up a project with a minimal example showcasing the bug. The repository can be found here: https://gitlab.com/hd-mc-mods/examples/item-tick-bug So this makes me wonder: Am I not supposed to change tag values in inventoryTick()? Is there a way to check on the client side if an item stack does not exist anymore on the server side (i.e. remove ghost items)? Is it wrong to put to much load on the server inside inventoryTick() (e.g. updateLight())? What would be alternatives? Am I doing something obviously wrong that is out of my grasp? I hope somebody with a little more insight can help me with this or point me to good examples matching my usecase.
×
×
  • Create New...

Important Information

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