5

I'm trying to find out, in a command block, if a targeted mob (cow, sheep, chicken, etc.) is a baby or an adult. I know that's determined by the Age data tag: if Age<0, it's a baby, otherwise it's an adult. The problem is, as far as I know, there's no way to check if a data tag is <0, you can only test for exact values.

I'm able to detect the moment when a baby grows up, since the Age passes through -1 in that case (not checking 0 to avoid detection of newly spawned adults). But how can I tell whether a passive mob is a baby or an adult before that moment triggers (especially since adults won't have that moment at all)?

1
  • I don't say this often, but I'm not sure it's possible to do what you want to do. I thought it would be possible to do this using the scoreboar (probably with a little help from the stats command), but I'm not seeing anything useful that also doesn't include a massive number of command blocks.
    – MBraedley
    Oct 23, 2015 at 21:58

3 Answers 3

2

When a mob is a baby, InLove will be constantly set to 0. If it's an adult, it'll slowly decrease to 0. So, you should be able to run these, in this exact order:

scoreboard players set @e[score_checkAge_min=1] isBaby 0
scoreboard players set @e[score_checkAge_min=1] isBaby 1 {InLove:0}
entitydata @e[score_checkAge_min=1] {InLove:0}
scoreboard players set @e checkAge 0
scoreboard players set @e checkAge 1 {InLove:0}
entitydata @e[score_checkAge_min=1] {InLove:30000}

InLove only exists on animals, so you don't have to worry about it setting the score for players or other non-animals.

This method should work for 1.8 and horses.

Breakdown

scoreboard players set @e checkAge 0
scoreboard players set @e checkAge 1 {InLove:0}

This sets a checkAge dummy score to 1 for all not-currently-breeding passive mobs, adult and child.

 entitydata @e[score_checkAge_min=1] {InLove:30000}

Changes the InLove tag of previously selected entities to 30000.

Then, in the next tick:

scoreboard players set @e[score_checkAge_min=1] isBaby 0
scoreboard players set @e[score_checkAge_min=1] isBaby 1 {InLove:0}

Sets isBaby to 1 if InLove has instantly returned to 0, or 0 otherwise.

entitydata @e[score_checkAge_min=1] {InLove:0}

Sets InLove back to 0 for all checked entities.


You should be able to select adults like this:

@e[score_isBaby=0]

Or babies like this:

@e[score_isBaby_min=1]
7
  • I prefer this answer to @MBraedly's, simply because it'll immediately detect all applicable mobs regardless of their initial InLove value. Thanks! Oct 24, 2015 at 4:59
  • Wait...in trying to implement this, it doesn't work as well as I'd hoped. It seems to also detect animals that have bred in the last tick. I don't really understand why; the logic behind your idea seems solid. I manually set InLove to 30000 and checked the entitydata, and it properly stays high and decrements by 1 each tick; yet somehow, when the animals breed, they get marked as babies anyway. Any idea why that might happen? Oct 24, 2015 at 5:29
  • @IceMetalPunk Hmm, I thought it would have at worst just waited a second before tagging mobs that had just bred; I'll do some more testing with mobs that have just bred and try to figure that out.
    – SirBenet
    Oct 24, 2015 at 10:00
  • @IceMetalPunk My method will immediately detect almost all applicable mobs, because the InLove timer is only 10 seconds and the breeding timer is 5 minutes. All you need to do to make this work 100% of the time is idle for 5 minutes before activating the command blocks.
    – MBraedley
    Oct 24, 2015 at 11:23
  • @MBraedley Right, but for my particular use case, it needs to be running on a 20 tps clock, so I can't wait 5 minutes before running it. Thanks anyway. Oct 24, 2015 at 18:12
2

MBraedley's answer doesn't work at all in its current state. GIF demonstration:

demonstration

colorfusion's answer somewhat works, but messes up with breeding as you appear to have noticed.

The following method is a bit of a hybrid between the two that I believe works 100% of the time.


Add these objectives:

/scoreboard objectives add CheckAge dummy
/scoreboard objectives add GrowthLevel dummy

On your clock:

/scoreboard players set @e CheckAge 1 {InLove:0}
/scoreboard players add @e[score_CheckAge_min=1] GrowthLevel 0
/scoreboard players set @e[score_CheckAge_min=1] GrowthLevel 1 {Age:0}

Then use @e[score_GrowthLevel_min=1] to select adults, or @e[score_GrowthLevel=0] for babies.

10
  • I can't test this until later tonight, but how does that handle adults that spawned before the clock started (i.e. were already in the world before I turned the system on)? Their age would be >0 at all times, so wouldn't they be mistagged as babies? Oct 24, 2015 at 21:32
  • I guess @colorfusion was at least partially right in one of his comments on my answer. I've fixed the problem.
    – MBraedley
    Oct 24, 2015 at 22:00
  • 1
    @IceMetalPunk Should work fine. Adults usually have age 0, not >0.
    – user114151
    Oct 24, 2015 at 22:08
  • @MBraedley Their comment wasn't "at least partially right", it was fully right. Not being able to specify multiple selector arguments is a fairly basic thing, and I'm not sure how you tested your method to work correctly.
    – user114151
    Oct 24, 2015 at 22:08
  • I swear I ran a command that worked as expected using two two tags in the selector. Now perhaps it worked because of an edge case in my test, or I just didn't notice that it wasn't working right, but what's important is I've fixed the issue, and have fully tested it.
    – MBraedley
    Oct 24, 2015 at 22:13
1

So my comment above was wrong, this is doable, albeit with a caveat. The important thing to realize is what the Age tag actually represents:

Age: Represents the age of the mob in ticks; when negative, the mob is a baby. When 0 or above, the mob is an adult. When above 0, represents the number of ticks before this mob can breed again.

So, all friendly mobs will have an Age of 0 unless they're either a baby or were recently bred. This means we can easily tag them with a scoreboard value. Now we won't get newly minted parents, but if we use version 1.9 (or, at this point, the snapshots for 1.9), we don't have to worry about that, since we're going to tag all adults ready to breed. Even after you breed them, they'll still keep their tag; adults can't turn back into babies, so there's no reason to remove the tag.

So, it's fairly simple: just tag all entities with an Age of 0 as an adult.

/scoreboard players tag @e add Adult {Age:0}

Run that in a repeating command block, and all friendly mobs that are adults will have the tag unless they recently bred.

Now, to get all the babies is a little more complicated. The naive approach below isn't very desirable:

/scoreboard players tag @e remove Baby
/scoreboard players tag @e[tag=!Adult] add Baby

That will tag every single entity, including players, as a baby if they aren't already tagged as an adult. Not great. What we need to do is be able to distinguish friendly mobs from every other entity. Luckily, there is a way to do this:

/scoreboard players tag @e add FriendlyMob {InLove:0}

So, your commands, in order, should be:

/scoreboard players tag @e add FriendlyMob {InLove:0}
/scoreboard players tag @e add Adult {Age:0}
/scoreboard players tag @e[tag=!Adult] add Baby
/scoreboard players tag @e[tag=!FriendlyMob] remove Baby
/scoreboard players tag @e[tag=Adult] remove Baby

The only friendly mobs this won't work correctly with are mobs that are about to breed, or have just bred, and still, once those two timers reach 0 again, they'll be properly tagged. This won't take long either. The timer for InLove is only 10 seconds, and the timer for Age is 5 minutes. In most cases, you won't have to wait at all.

Hopefully it's self evident, but in order to select the adults, just use @e[tag=Adult], and similarly for the babies, use @e[tag=Baby].


SirBenet's answer made me realize I could simplify things a little (well, a lot): I don't need to actually tag friendly mobs, I can just do a data tag check instead:

/scoreboard players tag @e add Adult {Age:0}
/scoreboard players tag @e[tag=!Adult] add Baby {InLove:0}
/scoreboard players tag @e[tag=Adult] remove Baby

As before, if the Age or InLove timers are counting down, it won't tag the mob properly, but unless you're willing to go mess with those, there isn't really a way around it.

5
  • Why they couldn't just use IsBaby like for Zombies is beyond me.
    – MBraedley
    Oct 23, 2015 at 23:20
  • "@e[tag=!Adult,tag=FriendlyMob]" - Have you tested this? Didn't think you could select multiple tags. Easy enough to change it to scoreboard though, and should be more compact than my suggested method.
    – SirBenet
    Oct 24, 2015 at 1:26
  • It's basically the same as scores. Pretty sure you can select multiple scores.
    – MBraedley
    Oct 24, 2015 at 1:35
  • And just to be sure, I just tested it. Works as expected.
    – MBraedley
    Oct 24, 2015 at 1:38
  • I guess I wasn't doing a valid test last night. A little rearrangement and an additional command sorted everything out.
    – MBraedley
    Oct 24, 2015 at 22:08

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .