Minecraft command to clear all but one item entity (tile) type

I've got a capture the flag arena. One issue we keep running into during play, is that of clutter.

We have /gamerule keepInventory false, so the pitch gets rather cluttered with armor, weapons and building materials, such that it becomes difficult to pick the flag up, due to full inventories.

I've discovered the following command to remove all drops from the arena:

/kill @e[type=Item]

However, this removes all the floating items from the ground. I'd like, if possible, to preserve the flag from being destroyed.

I have this command for detecting the flag:

/testfor @e[type=Item,x=40,y=1,z=40,dx=40,dy=27,dz=80] {Item:{id:"minecraft:banner",Damage:4s}}

But I'm not sure how to combine the two in a way that it will destroy everything except for the flag.

Any ideas?


Solution 1:

In 1.13 and above, this can be done with the following command:

/kill @e[type=item,nbt=!{Item:{id:"minecraft:blue_banner"}}]

The following solution is for version 1.8:

First, create a dummy scoreboard objective:

/scoreboard objectives add ItemToRemove dummy

Whenever you want to clean up the dropped items, run these commands in this order:

/scoreboard players set @e[type=Item] ItemToRemove 1
/scoreboard players set @e[type=Item,x=40,y=1,z=40,dx=40,dy=27,dz=80] ItemToRemove 0 {Item:{id:"minecraft:banner",Damage:4s}}
/kill @e[score_ItemToRemove_min=1]

What this does is set all item's ItemToRemove score to 1, sets the banner's ItemToRemove score back to 0, then kills everything with a minimum of 1 ItemToRemove score.

Solution 2:

Starting with Minecraft 1.9, you can use a scoreboard tag to mark the flag rather than a dummy objective as outlined in colorfusion's answer.

/scoreboard players tag @e[type=Item,tag=!isFlag] add isFlag {Item:{id:"minecraft:banner",Damage:4s}}
/kill @e[type=Item,tag=!isFlag]

This has three benefits:

  1. You don't need to set up an objective.
  2. Note how there is no command to tag every item. This is because tags are initialized as an empty list by default, meaning tag=!isFlag works on entities by default. This is unlike scoreboard objectives, which are initialized to Null/None, which fails all comparisons with numbers (for the purpose of target selector arguments), e.g. (Null>=0)==False, (Null<0)==False.
  3. As a result of 2, we can make it so every flag is only tagged once, rather than once per tick.