It is possible to check the absence of an item in an inventory, as can be seen in this question. However, it is more convenient probably to track the use of items. If you make a scoreboard that tracks stat.useItem.snowball
(I'm not sure if that's the exact name, but it looks like that) then you know exactly when somebody threw a snowball.
So instead of checking the amount of items in player's inventories, check how many items have been used.
EDIT:
In order to give a player a new snowball when the old snowball has vanished, you need to keep track of the owner of each snowball. In order to do that, you need two additional scoreboards: One for players IDs, called ID
, where each player has an entry with a unique number and one for all the snowballs in the field, called Snowballs
. On top of that, you need another scoreboard to do some maths in, called Math
.
In this answer, I assume that you know how to give each player a unique id in a scoreboard called ID
, since this is out of the scope of this question.
The most convenient way to achieve this is by using functions, because the function command in 1.12.2 allows you to specify a condition.
You need to execute a function at each player for whom there is no snowball in the field with a score that is equal to the id of that player.
The following commands initiate the snowballs and initiates your functions on all players that have thrown a snowball:
/execute @e[type=snowball,tag=!hasOwner] ~ ~ ~ scoreboard players operation @s Snowballs = @p ID
/scoreboard tag add @e[type=snowball,tag=!hasOwner] hasOwner
/execute @a[score_usedSB_min=1] ~ ~ ~ function findSnowball
This causes the entire function to be executed from the perspective of each player.
Next, you need to make a function called findSnowball
. This function contains the following commands:
# Set the score of each snowball in the math scoreboard to the difference between the score and the current player ID
execute @e[type=snowball] ~ ~ ~ scoreboard operation @s Math = @s Snowball
scoreboard operation @e[type=snowball] Math -= @s ID
# every snowball that has a score of 0 belongs to the current player
function giveSnowball unless @e[type=snowball,score_Math=0,score_Math_min=0]
The last function gives the correct players a new snowball and resets their scores on the scoreboard. It's called giveSnowball
:
give @s snowball
scoreboard players set @s usedSB 0
This method should work in your situation, given that I haven't accidentally made any mistakes. This method has a few drawbacks, which you should be aware of:
- This method only works if snowball entities are only created by players: If there are dispensers or snowgolems in the world, then those snowballs will cause trouble.
- The scoreboard
Snowballs
accumulates entries. snowballs that no longer exist still remain in this scoreboard and therefore it will start to clutter. I cannot think of a method to reliably clean this scoreboard without causing unexpected behaviour.
testfor
, but I think the point still needs to be made: don't usetestfor
! Any problem that can be solved withtestfor
can be solved in other ways, and usually those alternatives are better. It took a fair amount of experience to know when to usetestfor
and how to use it to the greatest utility. Not only that, buttestfor
was eliminated in 1.13, and for good reason. – MBraedley Jul 28 '18 at 20:10