Jump to content

Recommended Posts

Posted

I have a problem connected with custom item NBT updates and block breaking that I am trying to resolve. The custom item mentioned is a torch with it's own custom class and NBT values that are regularly updated twice every 20 ticks. The problem occurs when I try to break blocks with the torch selected. The moment the item runs an NBT update the break progress is stopped with an Action.ABORT_DESTROY_BLOCK action.

 

My plan to solve this is to create a static map which would contain ItemStack references and boolean flags that would return true while the block is being mined with the belonging item, try to catch the block breaking event and raise these flags, and finally either stop updating until the flags are false or update to a local container somewhere and copy to NBT later. I've tracked down the cause of the problem (check down for more info), however I would like to know if there is a more elegant solution then the one I have in mind. The mentioned solution requires a lot of work around and I would rather avoid it if possible.

 

Here's an open issue on GitHub with additional information:

https://github.com/yooksi/FierySouls/issues/5

 

Thank you in advance!

I still haven't published a mod because I can never get that in-dev version just right to warrant a public release. And yes, after two years of mod development I am still learning to speak Java.

 

Follow me on GitHub: https://github.com/yooksi

Contact me on Twitter: https://twitter.com/yooksi

Read my Minecraft blog: https://yooksidoesminecraft.blogspot.de/

Posted

You need to overrode the

shouldRefresh()

method (or similar, I don't know it's exact name).

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

Posted

You need to overrode the

shouldRefresh()

method (or similar, I don't know it's exact name).

Unfortunately, that method is not used in this context.

 

@OP I think your plan is probably fine. Part of the issue is that the check is happening client side, so you may be fine simply listening for the use-item key / mouse click, checking if it's your item, and adding that player's entityID to a Set. Then in your item's update code, check if the player's entity ID is in that set and if so, don't update the NBT.

 

A Map could work, too, with playerID -> ItemStack and then you could update NBT using the map reference (make a copy of the ItemStack). One thing to watch out for with that, though, is when you copy the data back, if something else happened to change the real ItemStack's NBT in the meantime, those changes might be lost. I would recommend only copying the specific variables that you are tracking instead of replacing the whole NBT tag or ItemStack.

Posted
You need to overrode the shouldRefresh() method (or similar, I don't know it's exact name).

I was unable to find that method in Item, could you give me more information about it?

 

@OP I think your plan is probably fine. Part of the issue is that the check is happening client side, so you may be fine simply listening for the use-item key / mouse click, checking if it's your item, and adding that player's entityID to a Set. Then in your item's update code, check if the player's entity ID is in that set and if so, don't update the NBT.

 

A Map could work, too, with playerID -> ItemStack and then you could update NBT using the map reference (make a copy of the ItemStack). One thing to watch out for with that, though, is when you copy the data back, if something else happened to change the real ItemStack's NBT in the meantime, those changes might be lost. I would recommend only copying the specific variables that you are tracking instead of replacing the whole NBT tag or ItemStack.

 

After closely examining my plan I realized I have no clue how to figure out when the player has stopped breaking the block. Some ideas I had were reading the block destruction progress and overriding the PlayerControllerMP class. For the first one I need access to RenderGlobal.damagedBlocks which is private, for the second idea I don't have enough knowledge on how does the controller interact with the world. A perfect solution would be to listen for a forge event that fires when a player stops breaking a block.

 

Any ideas where to go from this point?

Thanks for trying to help.

I still haven't published a mod because I can never get that in-dev version just right to warrant a public release. And yes, after two years of mod development I am still learning to speak Java.

 

Follow me on GitHub: https://github.com/yooksi

Contact me on Twitter: https://twitter.com/yooksi

Read my Minecraft blog: https://yooksidoesminecraft.blogspot.de/

Posted

You need to overrode the shouldRefresh() method (or similar, I don't know it's exact name).

I was unable to find that method in Item, could you give me more information about it?

 

Per coolAlias, it probably won't help you anyway.

 

Problem is I forget the exact name, its like

shouldItemStackRefresh

or something along those lines.  Search the Item class for "refresh" and you'll find it.  Its used to make the game realize that minor changes to an equipped item should or should not be treated as switching inventory slots (the animation and stuff).

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

Posted

/**
* Determine if the player switching between these two item stacks    
* @param oldStack The old stack that was equipped
* @param newStack The new stack
* @param slotChanged If the current equipped slot was changed,
*                    Vanilla does not play the animation if you switch between two
*                    slots that hold the exact same item.
* @return True to play the item change animation
*/
public boolean shouldCauseReequipAnimation(ItemStack oldStack, ItemStack newStack, boolean slotChanged)
{
    return !ItemStack.areItemStacksEqual(oldStack, newStack);
}

Are you talking about this method? This only affects the "bobbing" animation.

The cause of the problem is in PlayerControllerMP.

I still haven't published a mod because I can never get that in-dev version just right to warrant a public release. And yes, after two years of mod development I am still learning to speak Java.

 

Follow me on GitHub: https://github.com/yooksi

Contact me on Twitter: https://twitter.com/yooksi

Read my Minecraft blog: https://yooksidoesminecraft.blogspot.de/

Posted

ClientTickEvent / KeyInputEvent - check if keyboard.isKeyDown for the attack keybinding (I said the itemUse key before, but that's not the one for breaking blocks). Also be sure to check the mouse using MouseEvent:

if (event.button - 100 == mc.gameSettings.keyBindAttack.getKeyCode()) {
  // mouse button is the attack key, do something
}

Once you know that the attack key was pressed AND that they are holding your item, you may want to check if they are hitting a block (use Minecraft.getMinecraft().objectMouseOver to easily check).

 

Now that you have a boolean flag for that player, you are still checking each tick if they are holding the attack key down - as soon as it is released, unset the flag / remove the player.

 

It would be much easier using the PlayerInteractEvent via the LEFT_CLICK_BLOCK action, but that, unfortunately, is only fired on the server side.

Posted

Okay that sounds like a good plan, I will try it out as as soon as possible and let you know how it worked.

 

Thank you again for helping out.

I still haven't published a mod because I can never get that in-dev version just right to warrant a public release. And yes, after two years of mod development I am still learning to speak Java.

 

Follow me on GitHub: https://github.com/yooksi

Contact me on Twitter: https://twitter.com/yooksi

Read my Minecraft blog: https://yooksidoesminecraft.blogspot.de/

Posted

I've managed to resolve my issue and everything works fine now.

This is the method I created to find out if the player is currently breaking a block:

 

/**
*  Checks if the player is in the process of hitting a block. <br>
*  <i>If the game is played in multiplayer, this should be validated only on client.</i>
*  
*  @return True if the player is holding mouse left-click and is mousing over a block.
*/
public static boolean isPlayerBreakingBlock()
{
    // TODO: Find a better place for this method, it belongs to more of a general purpose category.
    	
    final Minecraft minecraft = Minecraft.getMinecraft();
    final net.minecraft.util.MovingObjectPosition mouseOver = minecraft.objectMouseOver;
    	
    boolean isAttackKeyDown = minecraft.gameSettings.keyBindAttack.isKeyDown();
    boolean isMouseOverBlock = mouseOver != null && mouseOver.typeOfHit == net.minecraft.util.MovingObjectPosition.MovingObjectType.BLOCK;
    	
    return isAttackKeyDown && isMouseOverBlock;
}

I still haven't published a mod because I can never get that in-dev version just right to warrant a public release. And yes, after two years of mod development I am still learning to speak Java.

 

Follow me on GitHub: https://github.com/yooksi

Contact me on Twitter: https://twitter.com/yooksi

Read my Minecraft blog: https://yooksidoesminecraft.blogspot.de/

Guest
This topic is now closed to further replies.
×
×
  • Create New...

Important Information

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