From b691c43c44ff180d10e7d4a9afc83b98551ff586 Mon Sep 17 00:00:00 2001 From: daoge_cmd <3523206925@qq.com> Date: Sun, 1 Mar 2026 12:16:08 +0800 Subject: Initial commit --- Minecraft.World/Ozelot.cpp | 333 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 333 insertions(+) create mode 100644 Minecraft.World/Ozelot.cpp (limited to 'Minecraft.World/Ozelot.cpp') diff --git a/Minecraft.World/Ozelot.cpp b/Minecraft.World/Ozelot.cpp new file mode 100644 index 00000000..3c05f357 --- /dev/null +++ b/Minecraft.World/Ozelot.cpp @@ -0,0 +1,333 @@ +#include "stdafx.h" +#include "net.minecraft.world.entity.ai.control.h" +#include "net.minecraft.world.entity.ai.goal.target.h" +#include "net.minecraft.world.entity.ai.goal.h" +#include "net.minecraft.world.entity.ai.navigation.h" +#include "net.minecraft.world.entity.animal.h" +#include "net.minecraft.world.entity.player.h" +#include "net.minecraft.world.entity.h" +#include "net.minecraft.world.damagesource.h" +#include "net.minecraft.world.level.h" +#include "net.minecraft.world.item.h" +#include "net.minecraft.world.phys.h" +#include "SynchedEntityData.h" +#include "StringHelpers.h" +#include "..\Minecraft.Client\Textures.h" +#include "GenericStats.h" +#include "Ozelot.h" + +const float Ozelot::SNEAK_SPEED = 0.18f; +const float Ozelot::WALK_SPEED = 0.23f; +const float Ozelot::FOLLOW_SPEED = 0.3f; +const float Ozelot::SPRINT_SPEED = 0.4f; + +const int Ozelot::DATA_TYPE_ID = 18; + +const int Ozelot::TYPE_OZELOT = 0; +const int Ozelot::TYPE_BLACK = 1; +const int Ozelot::TYPE_RED = 2; +const int Ozelot::TYPE_SIAMESE = 3; + +Ozelot::Ozelot(Level *level) : TamableAnimal(level) +{ + // 4J Stu - This function call had to be moved here from the Entity ctor to ensure that + // the derived version of the function is called + this->defineSynchedData(); + + // 4J Stu - This function call had to be moved here from the Entity ctor to ensure that the derived version of the function is called + health = getMaxHealth(); + + this->textureIdx = TN_MOB_OZELOT; // "/mob/ozelot.png"; + this->setSize(0.6f, 0.8f); + + getNavigation()->setAvoidWater(true); + goalSelector.addGoal(1, new FloatGoal(this)); + goalSelector.addGoal(2, sitGoal, false); + goalSelector.addGoal(3, temptGoal = new TemptGoal(this, SNEAK_SPEED, Item::fish_raw_Id, true), false); + goalSelector.addGoal(4, new AvoidPlayerGoal(this, typeid(Player), 16, WALK_SPEED, SPRINT_SPEED)); + goalSelector.addGoal(5, new FollowOwnerGoal(this, FOLLOW_SPEED, 10, 5)); + goalSelector.addGoal(6, new OcelotSitOnTileGoal(this, SPRINT_SPEED)); + goalSelector.addGoal(7, new LeapAtTargetGoal(this, 0.3f)); + goalSelector.addGoal(8, new OzelotAttackGoal(this)); + goalSelector.addGoal(9, new BreedGoal(this, WALK_SPEED)); + goalSelector.addGoal(10, new RandomStrollGoal(this, WALK_SPEED)); + goalSelector.addGoal(11, new LookAtPlayerGoal(this, typeid(Player), 10)); + + targetSelector.addGoal(1, new NonTameRandomTargetGoal(this, typeid(Chicken), 14, 750, false)); +} + +void Ozelot::defineSynchedData() +{ + TamableAnimal::defineSynchedData(); + + entityData->define(DATA_TYPE_ID, (byte) TYPE_OZELOT); +} + +void Ozelot::serverAiMobStep() +{ + if (getMoveControl()->hasWanted()) + { + float speed = getMoveControl()->getSpeed(); + if (speed == SNEAK_SPEED) + { + setSneaking(true); + setSprinting(false); + } + else if (speed == SPRINT_SPEED) + { + setSneaking(false); + setSprinting(true); + } + else + { + setSneaking(false); + setSprinting(false); + } + } + else + { + setSneaking(false); + setSprinting(false); + } +} + +bool Ozelot::removeWhenFarAway() +{ + return Animal::removeWhenFarAway() && !isTame(); +} + +int Ozelot::getTexture() +{ + switch (getCatType()) + { + case TYPE_OZELOT: + return TN_MOB_OZELOT; //"/mob/ozelot.png"; + case TYPE_BLACK: + return TN_MOB_CAT_BLACK; //"/mob/cat_black.png"; + case TYPE_RED: + return TN_MOB_CAT_RED; //"/mob/cat_red.png"; + case TYPE_SIAMESE: + return TN_MOB_CAT_SIAMESE; //"/mob/cat_siamese.png"; + } + return TamableAnimal::getTexture(); +} + +bool Ozelot::useNewAi() +{ + return true; +} + +int Ozelot::getMaxHealth() +{ + return 10; +} + +void Ozelot::causeFallDamage(float distance) +{ + // do nothing +} + +void Ozelot::addAdditonalSaveData(CompoundTag *tag) +{ + TamableAnimal::addAdditonalSaveData(tag); + tag->putInt(L"CatType", getCatType()); +} + +void Ozelot::readAdditionalSaveData(CompoundTag *tag) +{ + TamableAnimal::readAdditionalSaveData(tag); + if(isTame()) + { + setCatType(tag->getInt(L"CatType")); + } + else + { + setCatType(TYPE_OZELOT); + } +} + +int Ozelot::getAmbientSound() +{ + if (isTame()) + { + if (isInLove()) + { + return eSoundType_MOB_CAT_PURR; + } + if (random->nextInt(4) == 0) + { + return eSoundType_MOB_CAT_PURREOW; + } + return eSoundType_MOB_CAT_MEOW; + } + + return -1; +} + +int Ozelot::getHurtSound() +{ + return eSoundType_MOB_CAT_HITT; +} + +int Ozelot::getDeathSound() +{ + return eSoundType_MOB_CAT_HITT; +} + +float Ozelot::getSoundVolume() +{ + return 0.4f; +} + +int Ozelot::getDeathLoot() +{ + return Item::leather_Id; +} + +bool Ozelot::doHurtTarget(shared_ptr target) +{ + return target->hurt(DamageSource::mobAttack(dynamic_pointer_cast(shared_from_this())), 3); +} + +bool Ozelot::hurt(DamageSource *source, int dmg) +{ + sitGoal->wantToSit(false); + return TamableAnimal::hurt(source, dmg); +} + +void Ozelot::dropDeathLoot(bool wasKilledByPlayer, int playerBonusLevel) +{ +} + +bool Ozelot::interact(shared_ptr player) +{ + shared_ptr item = player->inventory->getSelected(); + if (isTame()) + { + if (equalsIgnoreCase(player->getUUID(), getOwnerUUID())) + { + if (!level->isClientSide && !isFood(item)) + { + sitGoal->wantToSit(!isSitting()); + } + } + } + else + { + if (temptGoal->isRunning() && item != NULL && item->id == Item::fish_raw_Id && player->distanceToSqr(shared_from_this()) < 3 * 3) + { + // 4J-PB - don't lose the fish in creative mode + if (!player->abilities.instabuild) item->count--; + if (item->count <= 0) + { + player->inventory->setItem(player->inventory->selected, nullptr); + } + + if (!level->isClientSide) + { + if (random->nextInt(3) == 0) + { + setTame(true); + + // 4J-JEV, hook for durango event. + player->awardStat(GenericStats::tamedEntity(eTYPE_OZELOT),GenericStats::param_tamedEntity(eTYPE_OZELOT)); + + setCatType(1 + level->random->nextInt(3)); + setOwnerUUID(player->getUUID()); + spawnTamingParticles(true); + sitGoal->wantToSit(true); + level->broadcastEntityEvent(shared_from_this(), EntityEvent::TAMING_SUCCEEDED); + } + else + { + spawnTamingParticles(false); + level->broadcastEntityEvent(shared_from_this(), EntityEvent::TAMING_FAILED); + } + } + return true; + } + } + return TamableAnimal::interact(player); +} + +shared_ptr Ozelot::getBreedOffspring(shared_ptr target) +{ + // 4J - added limit to number of animals that can be bred + if( level->canCreateMore( GetType(), Level::eSpawnType_Breed) ) + { + shared_ptr offspring = shared_ptr( new Ozelot(level) ); + if (isTame()) + { + offspring->setOwnerUUID(getOwnerUUID()); + offspring->setTame(true); + offspring->setCatType(getCatType()); + } + return offspring; + } + else + { + return nullptr; + } +} + +bool Ozelot::isFood(shared_ptr itemInstance) +{ + return itemInstance != NULL && itemInstance->id == Item::fish_raw_Id; +} + +bool Ozelot::canMate(shared_ptr animal) +{ + if (animal == shared_from_this()) return false; + if (!isTame()) return false; + + shared_ptr partner = dynamic_pointer_cast(animal); + if (partner == NULL) return false; + if (!partner->isTame()) return false; + + return isInLove() && partner->isInLove(); +} + +int Ozelot::getCatType() +{ + return entityData->getByte(DATA_TYPE_ID); +} + +void Ozelot::setCatType(int type) +{ + entityData->set(DATA_TYPE_ID, (byte) type); +} + +bool Ozelot::canSpawn() +{ + // artificially make ozelots more rare + if (level->random->nextInt(3) == 0) + { + return false; + } + if (level->isUnobstructed(bb) && level->getCubes(shared_from_this(), bb)->empty() && !level->containsAnyLiquid(bb)) + { + int xt = Mth::floor(x); + int yt = Mth::floor(bb->y0); + int zt = Mth::floor(z); + if (yt < level->seaLevel) + { + return false; + } + + int tile = level->getTile(xt, yt - 1, zt); + if (tile == Tile::grass_Id || tile == Tile::leaves_Id) + { + return true; + } + } + return false; +} + +wstring Ozelot::getAName() +{ + if (isTame()) + { + return L"entity.Cat.name"; + } + return TamableAnimal::getAName(); +} -- cgit v1.2.3