Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement aging + breeding #2696

Merged
merged 1 commit into from
Nov 30, 2015
Merged

Implement aging + breeding #2696

merged 1 commit into from
Nov 30, 2015

Conversation

Gargaj
Copy link
Contributor

@Gargaj Gargaj commented Nov 29, 2015

Notes:

  • Tested and works with pigs, sheep, cows/mooshrooms, rabbits and chicken
  • Works with ocelots although taming for ocelots isn't implemented yet.
  • Doesn't work yet with wolves: they are not a passive but a neutral mob. This was an oversight in my part, but I didn't want to move the behaviour into cMonster just yet because it would introduce a whole new set of problems.
  • Horses need taming first and that behaviour seems dodgy / broken, so I didn't yet try that.

Another important note: There's a change in the 1.8 protocol implementation when it comes to communicating age: @rom1504 and I did a bit of snooping in the less-documented parts of the protocol (http://wiki.vg/Entities#Ageable) and found out that the only way to make the love-mode hearts disappear is to set the Age to x>0. This introduces 3 distinct states for Age: x<0 when baby, x==0 when adult and ready for mating, x>0 when exhausted from mating.

@Gargaj
Copy link
Contributor Author

Gargaj commented Nov 29, 2015

/cc @SafwatHalaby

@SafwatHalaby
Copy link
Member

Minor remark: At https://github.com/Gargaj/cuberite/blob/breeding/src/World.cpp#L3485
It's probably best to have it that way:

if (a_Baby)
{
    Monster->SetAge(-1);
}
else
{
   mob->StopAgingTimer();
}

@Gargaj
Copy link
Contributor Author

Gargaj commented Nov 29, 2015

Probably true, although in the grand scheme of things it doesn't change much if it spawns as an adult, it just counts the aging timer down and then doesn't do anything.

@SafwatHalaby
Copy link
Member

True as of now. But the value may be used in the future in ways we can't anticipate. Suppose some Lua API wants to query how long it'd take for a mob to grow up. Currently it would return a false answer for adult mobs.

@Gargaj
Copy link
Contributor Author

Gargaj commented Nov 29, 2015

It's a bit of a mess because "age" seems to have two uses: http://minecraft.gamepedia.com/Chunk_format/Breedable

GetFollowedItems(FollowedItems);
if (FollowedItems.Size() > 0)
{
cPlayer * a_Closest_Player = m_World->FindClosestPlayer(GetPosition(), static_cast<float>(m_SightDistance));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code means that the player holding the bait must be the nearest player, is this the case in Vanilla? This is a minor issue though, and can be resolved after this merge.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's not my code, I just worked around it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about a DoWithClosestPlayers(Position, Callback)?
It would sort the players based on how far they are away from the position. The closest player first, and the furthest as last. When the callback returns true it stops.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't there be an equiavilant with a max-distance cap? You don't want to sort all the players in the world every tick for every mob.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code is just ripe for a rewrite. We don't want to be finding the closes player all the time, instead, we should store the followed player and only update it from time to time. The variable name is super-confusing, too, since we use a_ prefix for function args. And of course we want to react to non-closest players, too, if applicable.

@SafwatHalaby
Copy link
Member

  • Does the love cooldown reset on a failed attempt? The only call to ResetLoveMode is when breeding succeeds. Shouldn't it be called also when m_LoveTimerm_LoveCooldown reaches zero?
  • I am pretty ignorant with regards to the chunk saving aspect of Cuberite. Are the timers saved properly on chunk loads / unloads? @worktycho @madmaxoft @tigerw

@Gargaj
Copy link
Contributor Author

Gargaj commented Nov 29, 2015

  1. From what I can tell trying it in vanilla, no, you can re-feed the animals once the initial burst of love expires.
  2. I didn't update the NBT writer yet.

@rom1504
Copy link

rom1504 commented Nov 29, 2015

You need to send the entity status "love mode" every n ms (got to figure out n) to near players if you want them to see the hearts for 30s. Only the client of the player that give the wheat predicts the "love mode" itself. Not sure if you already do that ? (trying these stuff with 2 clients is generally useful to make sure it's not just the client predicting stuff)

Edit: actually, I tried it with the vanilla server and it doesn't do that (the 2nd vanilla client can only see the first heart (for 1 sec))
No idea if this is a vanilla bug or the expected behavior, so currently you indeed do stuff like vanilla.

@SafwatHalaby
Copy link
Member

@Gargaj You are correct about point 1.

@SafwatHalaby
Copy link
Member

Shouldn't the partner be nullified when m_LoveTimer hits zero to avoid chasing the partner after the hearts go away?

@Gargaj
Copy link
Contributor Author

Gargaj commented Nov 29, 2015

There's no such state. If the mob has a partner, m_LoveTimer doesn't matter anymore.

@SafwatHalaby
Copy link
Member

Consider a case where you isolate the two partners just after they lock in to each other. Shouldn't they give up at some point?

@Gargaj
Copy link
Contributor Author

Gargaj commented Nov 29, 2015

Right now it doesn't actually matter that they can't reach each other. :)
I don't know how vanilla deals with that, if at all.

@SafwatHalaby
Copy link
Member

I just tested this, two chickens had bred through a 2-block thick wall. Once they lock in, their physical position doesn't matter any more, a baby will be born. I never knew that.

@SafwatHalaby
Copy link
Member

-Tested with Vanilla-

@Gargaj
Copy link
Contributor Author

Gargaj commented Nov 29, 2015

There are so many jokes to be made about that.

@SafwatHalaby
Copy link
Member

Lol.
The code looks great to me. Thanks for this PR.
Is it ok for me to merge?

SafwatHalaby added a commit that referenced this pull request Nov 30, 2015
Implement aging + breeding
@SafwatHalaby SafwatHalaby merged commit 1a9c023 into cuberite:master Nov 30, 2015
@SafwatHalaby
Copy link
Member

Vanilla does care about mob reaching each other. Apparently ~2 blocks is the maximum distance in which the mobs can still breed. Seperating them with a 3-block wall prevents breeding and makes them give up after a while.

cPassiveMonster * m_LovePartner;
int m_LoveTimer;
int m_LoveCooldown;
int m_MatingTimer;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These should have been documented - what they do, how they interact with each other etc.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Gargaj Gargaj deleted the breeding branch November 30, 2015 12:07
@Gargaj
Copy link
Contributor Author

Gargaj commented Dec 1, 2015

Question: If you said above 2 blocks distance they dont breed, do they go into post-breed cooldown or can you re-feed them?

@SafwatHalaby
Copy link
Member

I will test that as soon as I can. But I think this is the least urgent of the AI issues.

@Gargaj
Copy link
Contributor Author

Gargaj commented Dec 6, 2015

Sure, but also reasonably easy to fix :)

@jammet
Copy link
Contributor

jammet commented Dec 7, 2015

I think they should be in love mode for a few more seconds, -- right now it's rather short, but I'm so glad this is being tackled!

Maybe it was just by chance but I noticed that sheep do not inherit their fur/wool color yet, and that we don't get domesticated cats when ocelots breed.

Thanks for all of this!! :)

@Outfenneced
Copy link

Looks like there's currently no way to pass down information from parents. Might even just be a good idea to pass the parents to the baby's constructor and have each baby mob do their own thing with the information. For instance, a baby sheep will find the wool color of the parents and use that to determine their wool color.

@jammet
Copy link
Contributor

jammet commented Dec 12, 2015

On a technical side, I don't know how this works at all. But I'm glad you're figuring it out. Thank you very much :).

@Gargaj
Copy link
Contributor Author

Gargaj commented Dec 12, 2015

The only reason I haven't added the wool color cos I haven't figured out how the colors blend when they're different color. Otherwise it's just some additional conditions right after the baby spawn.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

7 participants