My custom AI checks if the player has a particular item in his hand, and attacks the player if he does. I do it with this method. However, when shouldExecute gets called it gets the wrong result from my shouldAttackPlayer method (the print always says "Should the AI attack the player: false" even if I am holding the correct item). Did I do something wrong?
As you can probably tell the entire project is on github if you need it. Note that the AI is an anonymous class in EntityLivingShadow.
EDIT: I fixed it. I'm not entirely sure, but I think I did it by making sure that the predicate I made in shouldExecute used the parameter instead of player type I made. A diff can be found here.
You are checking the item by creating a new itemstack. The comparison using == checks that the stacks are the same instance, which they never will be. You should be using stack.isItemEqual(new stack).
Or even easier, just check that stack.getItem() == YOUR_ITEM
Btw, you've annotated the player parameter as nullable, but the aren't handling a case of a null player...
And why don't you move that shouldAttackPlayer method into the AI class if that's the only place you're using it?
Otherwise, try adding a break point and stepping through the code and see what it's doing.
I based my code of the EntityEnderman code, which has shouldAttackPlayer in the main class. I also had it in my class because I didn't want to create an AI at first, but eventually felt it was necessary and didn't bother moving that method since it shouldn't matter anyway. Adding a breakpoint just confirms what Alpvax said, the debugger doesn't tell me what Item the player is holding.
You are checking the item by creating a new itemstack. The comparison using == checks that the stacks are the same instance, which they never will be. You should be using stack.isItemEqual(new stack).
Or even easier, just check that stack.getItem() == YOUR_ITEM
I've tried this and multiple other solutions, I just happened to upload an itemstack version to github. This is the version I'm most confused about not working: http://pastebin.com/T0gvr17R
EDIT: Adding a breakpoint to the if statement in the pastebined version tells me that it 100% should return true (both player.getHeldItemMainhand().getItem() and the variable I created is the same as ModItems.swordBrighstone).
When you say they are the same, what does the debugger show the values as? If it is a different instance (i.e. a different address in memory) it will not match. You could try using #equals() instead.
When you say they are the same, what does the debugger show the values as? If it is a different instance (i.e. a different address in memory) it will not match. You could try using #equals() instead.
I mean they are the same. If one is ModItems.swordBrighstone@123456 the other one is ModItems.swordBrightstone@123456.
EDIT: Using equals() doesn't work either BTW.
EDIT 2: Actually, using equals() makes the print return true, but the mob still doesn't attack me.
According to your github you are always returning false from shouldExecute. You are retrieving the player (target) using the predicate, then returning false.
According to your github you are always returning false from shouldExecute. You are retrieving the player (target) using the predicate, then returning false.
I feel so stupid because of that. However, even though I updated it to this, the mob still doesn't attack me. What's up with that? I think I'm going to try to rebuild the class from scratch and see if I did some other slipup that I never noticed.
Rollback Post to RevisionRollBack
Teleporting XP, for when you want to improve performance with XP farms
That isn't quite the same. Now you are finding the nearest player, then only attacking based on the item, instead of finding the nearest player matching the condition and attacking that.
Go back to the previous code and just return player != null
That isn't quite the same. Now you are finding the nearest player, then only attacking based on the item, instead of finding the nearest player matching the condition and attacking that.
Go back to the previous code and just return player != null
I'm not sure I understand the difference. In game it seems they work like I want them to though (if I hold a brighstone sword they run to attack me). They do seem a bit dumb though, getting stuck on steep cliffs and having trouble swimming. I doubt that has to do with my AI though.
Rollback Post to RevisionRollBack
Teleporting XP, for when you want to improve performance with XP farms
I'm not sure I understand the difference. In game it seems they work like I want them to though (if I hold a brighstone sword they run to attack me).
When there is only 1 player, they are effectively the same. When there are multiple players in range the new method will choose the nearest, but then if it doesn't have the sword active, it just won't attack it, even if the further player does have the sword out.
When there is only 1 player, they are effectively the same. When there are multiple players in range the new method will choose the nearest, but then if it doesn't have the sword active, it just won't attack it, even if the further player does have the sword out.
Ahh, thank you for clearing that up. Fixed it now.
Rollback Post to RevisionRollBack
Teleporting XP, for when you want to improve performance with XP farms
My custom AI checks if the player has a particular item in his hand, and attacks the player if he does. I do it with this method. However, when shouldExecute gets called it gets the wrong result from my shouldAttackPlayer method (the print always says "Should the AI attack the player: false" even if I am holding the correct item). Did I do something wrong?
As you can probably tell the entire project is on github if you need it. Note that the AI is an anonymous class in EntityLivingShadow.
EDIT: I fixed it. I'm not entirely sure, but I think I did it by making sure that the predicate I made in shouldExecute used the parameter instead of player type I made. A diff can be found here.
Teleporting XP, for when you want to improve performance with XP farms
Btw, you've annotated the player parameter as nullable, but the aren't handling a case of a null player...
And why don't you move that shouldAttackPlayer method into the AI class if that's the only place you're using it?
Otherwise, try adding a break point and stepping through the code and see what it's doing.
You are checking the item by creating a new itemstack. The comparison using == checks that the stacks are the same instance, which they never will be. You should be using stack.isItemEqual(new stack).
Or even easier, just check that stack.getItem() == YOUR_ITEM
If I helped you, please click the green up arrow.
I based my code of the EntityEnderman code, which has shouldAttackPlayer in the main class. I also had it in my class because I didn't want to create an AI at first, but eventually felt it was necessary and didn't bother moving that method since it shouldn't matter anyway. Adding a breakpoint just confirms what Alpvax said, the debugger doesn't tell me what Item the player is holding.
I've tried this and multiple other solutions, I just happened to upload an itemstack version to github. This is the version I'm most confused about not working: http://pastebin.com/T0gvr17R
EDIT: Adding a breakpoint to the if statement in the pastebined version tells me that it 100% should return true (both player.getHeldItemMainhand().getItem() and the variable I created is the same as ModItems.swordBrighstone).
Teleporting XP, for when you want to improve performance with XP farms
When you say they are the same, what does the debugger show the values as? If it is a different instance (i.e. a different address in memory) it will not match. You could try using #equals() instead.
If I helped you, please click the green up arrow.
I mean they are the same. If one is ModItems.swordBrighstone@123456 the other one is ModItems.swordBrightstone@123456.
EDIT: Using equals() doesn't work either BTW.
EDIT 2: Actually, using equals() makes the print return true, but the mob still doesn't attack me.
Teleporting XP, for when you want to improve performance with XP farms
According to your github you are always returning false from shouldExecute. You are retrieving the player (target) using the predicate, then returning false.
If I helped you, please click the green up arrow.
I feel so stupid because of that. However, even though I updated it to this, the mob still doesn't attack me. What's up with that? I think I'm going to try to rebuild the class from scratch and see if I did some other slipup that I never noticed.
Teleporting XP, for when you want to improve performance with XP farms
That isn't quite the same. Now you are finding the nearest player, then only attacking based on the item, instead of finding the nearest player matching the condition and attacking that.
Go back to the previous code and just return player != null
If I helped you, please click the green up arrow.
I'm not sure I understand the difference. In game it seems they work like I want them to though (if I hold a brighstone sword they run to attack me). They do seem a bit dumb though, getting stuck on steep cliffs and having trouble swimming. I doubt that has to do with my AI though.
Teleporting XP, for when you want to improve performance with XP farms
When there is only 1 player, they are effectively the same. When there are multiple players in range the new method will choose the nearest, but then if it doesn't have the sword active, it just won't attack it, even if the further player does have the sword out.
If I helped you, please click the green up arrow.
Ahh, thank you for clearing that up. Fixed it now.
Teleporting XP, for when you want to improve performance with XP farms
You're welcome. Did you solve the problem?
If I helped you, please click the green up arrow.
Yes, thank you for the help.
Teleporting XP, for when you want to improve performance with XP farms
Glad I could help.
If I helped you, please click the green up arrow.