Jump to content

Recommended Posts

Posted (edited)

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.

Edited by HDainester
Removed irrelevant information and added link to example project.
Posted (edited)

If you want help with your code, put a reproducable example of your problem on github.

Not random and incomplete code snippets out of context in this forum.

We need to see how the code fits together and maybe try it for ourselves if the problem is not obvious

 

I am not very familiar with inventoryTick and what rules apply to it. It is mostly used by Mojang to do animation related stuff on the client,

But one place they do use it on the server is to update MapItem information. This does not modify the actual item, instead it updates information stored elsewhere.

 

It would not suprise to learn that modifying an ItemStack while the game is iterating over the inventory causes it to become very confused.

The tags on an ItemStack form part of its "identity".

But I don't know that for sure.

Edited by warjort

Boilerplate:

If you don't post your logs/debug.log we can't help you. For curseforge you need to enable the forge debug.log in its minecraft settings. You should also post your crash report if you have one.

If there is no error in the log file and you don't have a crash report then post the launcher_log.txt from the minecraft folder. Again for curseforge this will be in your curseforge/minecraft/Install

Large files should be posted to a file sharing site like https://gist.github.com  You should also read the support forum sticky post.

Posted

A quick search finds this example in the Botania mod updating tags during inventoryTick, so my concern about that is probably not correct?

https://github.com/VazkiiMods/Botania/blob/0568ec726bd42c506cdfa00705159dbe9b897b46/Xplat/src/main/java/vazkii/botania/common/item/equipment/tool/VitreousPickaxeItem.java#L90

Boilerplate:

If you don't post your logs/debug.log we can't help you. For curseforge you need to enable the forge debug.log in its minecraft settings. You should also post your crash report if you have one.

If there is no error in the log file and you don't have a crash report then post the launcher_log.txt from the minecraft folder. Again for curseforge this will be in your curseforge/minecraft/Install

Large files should be posted to a file sharing site like https://gist.github.com  You should also read the support forum sticky post.

Posted (edited)

By the way, if you are concerned about lag, you can always throttle your tick handling.

Something like:

if (entity.tickCount % 20 == 0) {
   // do processing once per second
}

 

Edited by warjort

Boilerplate:

If you don't post your logs/debug.log we can't help you. For curseforge you need to enable the forge debug.log in its minecraft settings. You should also post your crash report if you have one.

If there is no error in the log file and you don't have a crash report then post the launcher_log.txt from the minecraft folder. Again for curseforge this will be in your curseforge/minecraft/Install

Large files should be posted to a file sharing site like https://gist.github.com  You should also read the support forum sticky post.

Posted (edited)

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!

  On 1/6/2024 at 10:05 PM, warjort said:

It would not suprise to learn that modifying an ItemStack while the game is iterating over the inventory causes it to become very confused.

Expand  

I indeed get the hunch that this might be the case considering I had no issues replicating the bug with a minimal example.

Edited by HDainester
Fixed link to repo
Posted

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.

Posted (edited)

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.

Edited by HDainester

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

    • Ignore shrimple, it doesn't work with Oculus. Also, enableShaders was alr true when it said that towards the end of the log. If you could also figure out why my tags are messed up that'd be cool too, but that's a later issue. https://drive.google.com/drive/folders/1ovEKDZECUCl7zZxGfpyQcS4s5PZPQyfa?usp=drive_link
    • accidental duplicate mesage cuz lag
    • https://gnomebot.dev/paste/231527759279685634/1372324909073563730/1372324908629102716 https://gnomebot.dev/paste/231527759279685634/1372320454861262908/1372320454299090996 seems like theres a registry sync error, not sure what that means though, however in an old pack i played on, i actually had a registry sync error happen whenever the world tried too save and it would suddenly stop loading chunks, is there a mod fix for this or some way too bypass registry syncing? is this a server problem? i have no issues with the pack on pc, only on my server.
    • i think the problem is the player animator library but i need it for one of my main mods is there any way i can fix this? The game crashed: rendering overlay Error: java.lang.IllegalArgumentException: Failed to create player model for default heres the crash report: https://pastebin.com/U5Wp8ysb
    • I have been an enthusiastic investor in crypt0currencies for several years, and my digital assets have been integral to my financial strategy. A few months ago, I encountered a distressing predicament when I lost access to my primary cryptocurrency walleet after clicking on an airdrop link that inadvertently connected to my walleet. The dread of potentially losing all my hard-earned funds was overwhelming, leaving me uncertain about where to seek assistance. In my pursuit of solutions, I stumbled upon ChainDigger Retrievers. From our initial consultation to the triumphant recovery of my assets, the team exhibited exceptional expertise. They provided comprehensive explanations of the recovery process, ensuring I was informed at every stage and offering reassurance during this tumultuous time. Their approach was not only meticulous but also compassionate, which significantly alleviated my anxiety. ChainDigger Retrievers unwavering commitment to resolving my issue was evident throughout the process. Leveraging their profound understanding of crypt0currency technology and digital forensics, they initiated an exhaustive investigation to trace the transactions linked to my compromised wallet. Their meticulous analysis and relentless determination were apparent as they left no stone unturned in their quest to recover my funds. After several days of diligent investigation, the team successfully recovered everything I had lost. They uncovered that the link I had clicked contained malware, which scammeers had used to infiltrate my walleet. This revelation was both alarming and enlightening, underscoring the inherent risks associated with crypt0currency transactions when proper precautions are not taken.Thanks to ChainDigger Retrievers, I not only regained everything but also acquired invaluable knowledge about safeguarding my investments. Their expertise and steadfast support transformed a daunting situation into a manageable one, and I am profoundly grateful for their assistance. I can now continue my investment journey with renewed confidence, knowing that I have a trustworthy ally in ChainDigger Retrievers. Their client satisfaction is truly commendable, and I wholeheartedly recommend their services to anyone facing similar challenges in the crypt0currency realm. With their help, I was able to turn a distressing time into a positive outcome, and I will forever be grateful for their support.  
  • Topics

  • Who's Online (See full list)

×
×
  • Create New...

Important Information

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