Something went wrong. Try again.
the game where you go into mines and start crafting! but for consoles (forked directly from smartcmd's github)
Something went wrong. Try again.
12 kB · 489 lines
C++
at master
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489#include "stdafx.h"
#include "com.mojang.nbt.h"#include "net.minecraft.world.level.tile.h"#include "net.minecraft.world.item.h"#include "net.minecraft.world.phys.h"#include "net.minecraft.world.level.h"#include "net.minecraft.world.level.storage.h"#include "net.minecraft.world.entity.player.h"#include "net.minecraft.world.entity.h"#include "net.minecraft.world.entity.projectile.h"#include "net.minecraft.world.damagesource.h"#include "net.minecraft.world.entity.monster.h"#include "net.minecraft.world.entity.ai.attributes.h"#include "Random.h"#include "Animal.h"
Animal::Animal(Level *level) : AgableMob( level ){// inLove = 0; // 4J removed - now synched data loveTime = 0; loveCause = shared_ptr<Player>();
setDespawnProtected();}
void Animal::defineSynchedData(){ AgableMob::defineSynchedData();
entityData->define(DATA_IN_LOVE, (int)0); // 4J added}
void Animal::serverAiMobStep(){ if (getAge() != 0) setInLoveValue(0); AgableMob::serverAiMobStep();}
void Animal::aiStep(){ AgableMob::aiStep();
if (getAge() != 0) setInLoveValue(0);
if (getInLoveValue() > 0) { setInLoveValue(getInLoveValue()-1); if (getInLoveValue() % 10 == 0) { double xa = random->nextGaussian() * 0.02; double ya = random->nextGaussian() * 0.02; double za = random->nextGaussian() * 0.02; level->addParticle(eParticleType_heart, x + random->nextFloat() * bbWidth * 2 - bbWidth, y + .5f + random->nextFloat() * bbHeight, z + random->nextFloat() * bbWidth * 2 - bbWidth, xa, ya, za); } } else { loveTime = 0; }
updateDespawnProtectedState(); // 4J added}
void Animal::checkHurtTarget(shared_ptr<Entity> target, float d){ // 4J-JEV: Changed from dynamic cast to use eINSTANCEOF if ( target->instanceof(eTYPE_PLAYER) ) { if (d < 3) { double xd = target->x - x; double zd = target->z - z; yRot = (float) (atan2(zd, xd) * 180 / PI) - 90;
holdGround = true; }
shared_ptr<Player> p = dynamic_pointer_cast<Player>(target); if (p->getSelectedItem() == NULL || !isFood(p->getSelectedItem())) { attackTarget = nullptr; }
} // 4J-JEV: Changed from dynamic cast to use eINSTANCEOF else if ( target->instanceof(eTYPE_ANIMAL) ) { shared_ptr<Animal> a = dynamic_pointer_cast<Animal>(target); if (getAge() > 0 && a->getAge() < 0) { if (d < 2.5) { holdGround = true; } } else if (getInLoveValue() > 0 && a->getInLoveValue() > 0) { if (a->attackTarget == NULL) a->attackTarget = shared_from_this();
if (a->attackTarget == shared_from_this() && d < 3.5) { a->setInLoveValue(a->getInLoveValue()+1); setInLoveValue(getInLoveValue()+1); loveTime++; if (loveTime % 4 == 0) { level->addParticle(eParticleType_heart, x + random->nextFloat() * bbWidth * 2 - bbWidth, y + .5f + random->nextFloat() * bbHeight, z + random->nextFloat() * bbWidth * 2 - bbWidth, 0, 0, 0); }
if (loveTime == 20 * 3) breedWith(a); } else loveTime = 0; } else { loveTime = 0; attackTarget = nullptr; }
}}
void Animal::breedWith(shared_ptr<Animal> target){ shared_ptr<AgableMob> offspring = getBreedOffspring(target);
setInLoveValue(0); loveTime = 0; attackTarget = nullptr; target->attackTarget = nullptr; target->loveTime = 0; target->setInLoveValue(0);
// 4J - we have offspring of NULL returned when we have hit our limits of spawning any particular type of animal. In these cases try and do everything we can apart from actually // spawning the entity. if (offspring != NULL) { // Only want to set the age to this +ve value if something is actually spawned, as during this period the animal will attempt to follow offspring and ignore players. setAge(5 * 60 * 20); target->setAge(5 * 60 * 20);
offspring->setAge(-20 * 60 * 20); offspring->moveTo(x, y, z, yRot, xRot); offspring->setDespawnProtected(); for (int i = 0; i < 7; i++) { double xa = random->nextGaussian() * 0.02; double ya = random->nextGaussian() * 0.02; double za = random->nextGaussian() * 0.02; level->addParticle(eParticleType_heart, x + random->nextFloat() * bbWidth * 2 - bbWidth, y + .5f + random->nextFloat() * bbHeight, z + random->nextFloat() * bbWidth * 2 - bbWidth, xa, ya, za); } level->addEntity(offspring);
level->addEntity( shared_ptr<ExperienceOrb>( new ExperienceOrb(level, x, y, z, random->nextInt(4) + 1) ) ); }
setDespawnProtected();}
float Animal::getWalkTargetValue(int x, int y, int z){ if (level->getTile(x, y - 1, z) == Tile::grass_Id) return 10; return level->getBrightness(x, y, z) - 0.5f;}
bool Animal::hurt(DamageSource *dmgSource, float dmg){ if (isInvulnerable()) return false; if (dynamic_cast<EntityDamageSource *>(dmgSource) != NULL) { shared_ptr<Entity> source = dmgSource->getDirectEntity();
// 4J-JEV: Changed from dynamic cast to use eINSTANCEOF if ( source->instanceof(eTYPE_PLAYER) && !dynamic_pointer_cast<Player>(source)->isAllowedToAttackAnimals() ) { return false; }
if ( (source != NULL) && source->instanceof(eTYPE_ARROW) ) { shared_ptr<Arrow> arrow = dynamic_pointer_cast<Arrow>(source);
// 4J: Check that the arrow's owner can attack animals (dispenser arrows are not owned) if (arrow->owner != NULL && arrow->owner->instanceof(eTYPE_PLAYER) && !dynamic_pointer_cast<Player>(arrow->owner)->isAllowedToAttackAnimals() ) { return false; } } }
fleeTime = 20 * 3;
if (!useNewAi()) { AttributeInstance *speed = getAttribute(SharedMonsterAttributes::MOVEMENT_SPEED); if (speed->getModifier(eModifierId_MOB_FLEEING) == NULL) { speed->addModifier(new AttributeModifier(*Animal::SPEED_MODIFIER_FLEEING)); } }
attackTarget = nullptr; setInLoveValue(0);
return AgableMob::hurt(dmgSource, dmg);}
void Animal::addAdditonalSaveData(CompoundTag *tag){ AgableMob::addAdditonalSaveData(tag); tag->putInt(L"InLove", getInLoveValue());}
void Animal::readAdditionalSaveData(CompoundTag *tag){ AgableMob::readAdditionalSaveData(tag); setInLoveValue(tag->getInt(L"InLove")); setDespawnProtected();}
shared_ptr<Entity> Animal::findAttackTarget(){ if (fleeTime > 0) return nullptr;
float r = 8; if (getInLoveValue() > 0) { vector<shared_ptr<Entity> > *others = level->getEntitiesOfClass(typeid(*this), bb->grow(r, r, r)); //for (int i = 0; i < others->size(); i++) for(AUTO_VAR(it, others->begin()); it != others->end(); ++it) { shared_ptr<Animal> p = dynamic_pointer_cast<Animal>(*it); if (p != shared_from_this() && p->getInLoveValue() > 0) { delete others; return p; } } delete others; } else { if (getAge() == 0) { vector<shared_ptr<Entity> > *players = level->getEntitiesOfClass(typeid(Player), bb->grow(r, r, r)); //for (int i = 0; i < players.size(); i++) for(AUTO_VAR(it, players->begin()); it != players->end(); ++it) { setDespawnProtected();
shared_ptr<Player> p = dynamic_pointer_cast<Player>(*it); if (p->getSelectedItem() != NULL && this->isFood(p->getSelectedItem())) { delete players; return p; } } delete players; } else if (getAge() > 0) { vector<shared_ptr<Entity> > *others = level->getEntitiesOfClass(typeid(*this), bb->grow(r, r, r)); //for (int i = 0; i < others.size(); i++) for(AUTO_VAR(it, others->begin()); it != others->end(); ++it) { shared_ptr<Animal> p = dynamic_pointer_cast<Animal>(*it); if (p != shared_from_this() && p->getAge() < 0) { delete others; return p; } } delete others; } } return nullptr;}
bool Animal::canSpawn(){ int xt = Mth::floor(x); int yt = Mth::floor(bb->y0); int zt = Mth::floor(z); return level->getTile(xt, yt - 1, zt) == Tile::grass_Id && level->getDaytimeRawBrightness(xt, yt, zt) > 8 && AgableMob::canSpawn();}
int Animal::getAmbientSoundInterval(){ return 20 * 6;}
bool Animal::removeWhenFarAway(){ return !isDespawnProtected(); // 4J changed - was false}
int Animal::getExperienceReward(shared_ptr<Player> killedBy){ return 1 + level->random->nextInt(3);}
bool Animal::isFood(shared_ptr<ItemInstance> itemInstance){ return itemInstance->id == Item::wheat_Id;}
bool Animal::mobInteract(shared_ptr<Player> player){ shared_ptr<ItemInstance> item = player->inventory->getSelected(); if (item != NULL && isFood(item) && getAge() == 0 && getInLoveValue() <= 0) { if (!player->abilities.instabuild) { item->count--; if (item->count <= 0) { player->inventory->setItem(player->inventory->selected, nullptr); } }
// 4J-PB - If we can't produce another animal through breeding because of the spawn limits, display a message here if(!level->isClientSide) { switch(GetType()) { case eTYPE_CHICKEN: if( !level->canCreateMore(eTYPE_CHICKEN, Level::eSpawnType_Breed) ) { player->displayClientMessage(IDS_MAX_CHICKENS_BRED ); return false; } break; case eTYPE_WOLF: if( !level->canCreateMore(eTYPE_WOLF, Level::eSpawnType_Breed) ) { player->displayClientMessage(IDS_MAX_WOLVES_BRED ); return false; } break; case eTYPE_MUSHROOMCOW: if( !level->canCreateMore(eTYPE_MUSHROOMCOW, Level::eSpawnType_Breed) ) { player->displayClientMessage(IDS_MAX_MUSHROOMCOWS_BRED ); return false; } break; default: if((GetType() & eTYPE_ANIMALS_SPAWN_LIMIT_CHECK) == eTYPE_ANIMALS_SPAWN_LIMIT_CHECK) { if( !level->canCreateMore(GetType(), Level::eSpawnType_Breed) ) { player->displayClientMessage(IDS_MAX_PIGS_SHEEP_COWS_CATS_BRED );
return false; } } else if( instanceof(eTYPE_MONSTER) ) {
} break; } setInLove(player); } setInLove();
return true; } return AgableMob::mobInteract(player);}
// 4J addedint Animal::getInLoveValue(){ return entityData->getInteger(DATA_IN_LOVE);}
void Animal::setInLoveValue(int value){ entityData->set(DATA_IN_LOVE, value);}
// 4J addedvoid Animal::setInLove(shared_ptr<Player> player){ loveCause = player; setInLoveValue(20*30);}
shared_ptr<Player> Animal::getLoveCause(){ return loveCause.lock();}
void Animal::setInLove(){ entityData->set(DATA_IN_LOVE, 20 * 30);
attackTarget = nullptr; level->broadcastEntityEvent(shared_from_this(), EntityEvent::IN_LOVE_HEARTS);}
bool Animal::isInLove(){ return entityData->getInteger(DATA_IN_LOVE) > 0;}
void Animal::resetLove() { entityData->set(DATA_IN_LOVE, 0);}
bool Animal::canMate(shared_ptr<Animal> partner){ if (partner == shared_from_this()) return false; if (typeid(*partner) != typeid(*this)) return false; return isInLove() && partner->isInLove();}
void Animal::handleEntityEvent(byte id){ if (id == EntityEvent::IN_LOVE_HEARTS) { for (int i = 0; i < 7; i++) { double xa = random->nextGaussian() * 0.02; double ya = random->nextGaussian() * 0.02; double za = random->nextGaussian() * 0.02; level->addParticle(eParticleType_heart, x + random->nextFloat() * bbWidth * 2 - bbWidth, y + .5f + random->nextFloat() * bbHeight, z + random->nextFloat() * bbWidth * 2 - bbWidth, xa, ya, za); } } else { AgableMob::handleEntityEvent(id); }}
void Animal::updateDespawnProtectedState(){ if( level->isClientSide ) return;
if( m_isDespawnProtected ) { int xt = Mth::floor(x); int zt = Mth::floor(z);
if ( xt > m_maxWanderX ) m_maxWanderX = xt; if ( xt < m_minWanderX ) m_minWanderX = xt; if ( zt > m_maxWanderZ ) m_maxWanderZ = zt; if ( zt < m_minWanderZ ) m_minWanderZ = zt;
if( ( ( m_maxWanderX - m_minWanderX ) > MAX_WANDER_DISTANCE ) || ( ( m_maxWanderZ - m_minWanderZ ) > MAX_WANDER_DISTANCE ) ) {// printf("Unprotecting : %d to %d, %d to %d\n", m_minWanderX, m_maxWanderX, m_minWanderZ, m_maxWanderZ ); m_isDespawnProtected = false; }
/* if( isExtraWanderingEnabled() ) { printf("%d: %d %d, %d\n",entityId,m_maxWanderX - m_minWanderX, m_maxWanderZ - m_minWanderZ, getWanderingQuadrant()); } */ }}
bool Animal::isDespawnProtected(){ return m_isDespawnProtected;}
void Animal::setDespawnProtected(){ if( level && level->isClientSide ) return;
int xt = Mth::floor(x); int zt = Mth::floor(z);
m_minWanderX = xt; m_maxWanderX = xt; m_minWanderZ = zt; m_maxWanderZ = zt;
m_isDespawnProtected = true;}