Anyway to have testfor a count of 0? 1.12.2 [duplicate]

Is there anyway to do something like:

testfor @p[score_snowball=0] {Inventory:[{id:"minecraft:snowball",Count:0b}]}"

That works besides inverting:

testfor @p[score_snowball=0] {Inventory:[{id:"minecraft:snowball",Count:1b}]} ?

I wanna give player a snowball when they accidentally thrown one into a wall. Because when they throw it into a wall when they are too close to it, it doesn't get found by:

testfor @e[type=snowball]

and therefore doesn't give a snowball when it breaks.

I also want the player to only have 1 snowball, everytime the snowball objective = 0.

Setup:

  1. Repeating + Always active cmd block with: testfor @p[score_snowball=0] and comp going to: give @p minecraft:snowball

  2. Another Repeating + Always active cmd block with: testfor @e[type=snowball] and two comps, one going to: scoreboard players add @p snowball 1 and another going to cmd block that's inverted: scoreboard players set @p snowball 0


Solution 1:

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.