diff options
| author | Loki Rautio <lokirautio@gmail.com> | 2026-03-04 03:56:03 -0600 |
|---|---|---|
| committer | Loki Rautio <lokirautio@gmail.com> | 2026-03-04 03:56:03 -0600 |
| commit | 42aec6dac53dffa6afe072560a7e1d4986112538 (patch) | |
| tree | 0836426857391df1b6a83f6368a183f83ec9b104 /Minecraft.World/Wolf.cpp | |
| parent | c9d58eeac7c72f0b3038e084667b4d89a6249fce (diff) | |
| parent | ef9b6fd500dfabd9463267b0dd9e29577eea8a2b (diff) | |
Merge branch 'main' into pr/win64-world-saves
# Conflicts:
# Minecraft.Client/MinecraftServer.cpp
# README.md
Diffstat (limited to 'Minecraft.World/Wolf.cpp')
| -rw-r--r-- | Minecraft.World/Wolf.cpp | 183 |
1 files changed, 116 insertions, 67 deletions
diff --git a/Minecraft.World/Wolf.cpp b/Minecraft.World/Wolf.cpp index 8ffc45c6..1988382e 100644 --- a/Minecraft.World/Wolf.cpp +++ b/Minecraft.World/Wolf.cpp @@ -5,9 +5,12 @@ #include "net.minecraft.world.level.h" #include "net.minecraft.world.item.h" #include "net.minecraft.world.entity.h" +#include "net.minecraft.world.entity.animal.h" +#include "net.minecraft.world.entity.ai.attributes.h" #include "net.minecraft.world.entity.ai.goal.h" #include "net.minecraft.world.entity.ai.goal.target.h" #include "net.minecraft.world.entity.ai.navigation.h" +#include "net.minecraft.world.entity.monster.h" #include "net.minecraft.world.entity.player.h" #include "net.minecraft.world.entity.projectile.h" #include "net.minecraft.world.level.pathfinder.h" @@ -25,26 +28,23 @@ Wolf::Wolf(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(); + registerAttributes(); + setHealth(getMaxHealth()); interestedAngle = interestedAngleO = 0.0f; m_isWet = isShaking = false; shakeAnim = shakeAnimO = 0.0f; - this->textureIdx = TN_MOB_WOLF; // 4J - was L"/mob/wolf.png"; this->setSize(0.60f, 0.8f); - runSpeed = 0.3f; getNavigation()->setAvoidWater(true); goalSelector.addGoal(1, new FloatGoal(this)); goalSelector.addGoal(2, sitGoal, false); - goalSelector.addGoal(3, new LeapAtTargetGoal(this, 0.4f)); - goalSelector.addGoal(4, new MeleeAttackGoal(this, runSpeed, true)); - goalSelector.addGoal(5, new FollowOwnerGoal(this, runSpeed, 10, 2)); - goalSelector.addGoal(6, new BreedGoal(this, runSpeed)); - goalSelector.addGoal(7, new RandomStrollGoal(this, runSpeed)); + goalSelector.addGoal(3, new LeapAtTargetGoal(this, 0.4)); + goalSelector.addGoal(4, new MeleeAttackGoal(this, 1.0, true)); + goalSelector.addGoal(5, new FollowOwnerGoal(this, 1.0, 10, 2)); + goalSelector.addGoal(6, new BreedGoal(this, 1.0)); + goalSelector.addGoal(7, new RandomStrollGoal(this, 1.0)); goalSelector.addGoal(8, new BegGoal(this, 8)); goalSelector.addGoal(9, new LookAtPlayerGoal(this, typeid(Player), 8)); goalSelector.addGoal(9, new RandomLookAroundGoal(this)); @@ -52,7 +52,25 @@ Wolf::Wolf(Level *level) : TamableAnimal( level ) targetSelector.addGoal(1, new OwnerHurtByTargetGoal(this)); targetSelector.addGoal(2, new OwnerHurtTargetGoal(this)); targetSelector.addGoal(3, new HurtByTargetGoal(this, true)); - targetSelector.addGoal(4, new NonTameRandomTargetGoal(this, typeid(Sheep), 16, 200, false)); + targetSelector.addGoal(4, new NonTameRandomTargetGoal(this, typeid(Sheep), 200, false)); + + setTame(false); // Initialize health +} + +void Wolf::registerAttributes() +{ + TamableAnimal::registerAttributes(); + + getAttribute(SharedMonsterAttributes::MOVEMENT_SPEED)->setBaseValue(0.3f); + + if (isTame()) + { + getAttribute(SharedMonsterAttributes::MAX_HEALTH)->setBaseValue(TAME_HEALTH); + } + else + { + getAttribute(SharedMonsterAttributes::MAX_HEALTH)->setBaseValue(START_HEALTH); + } } bool Wolf::useNewAi() @@ -60,10 +78,10 @@ bool Wolf::useNewAi() return true; } -void Wolf::setTarget(shared_ptr<Mob> target) +void Wolf::setTarget(shared_ptr<LivingEntity> target) { TamableAnimal::setTarget(target); - if ( dynamic_pointer_cast<Player>(target) == NULL ) + if ( target == NULL ) { setAngry(false); } @@ -78,39 +96,17 @@ void Wolf::serverAiMobStep() entityData->set(DATA_HEALTH_ID, getHealth()); } -int Wolf::getMaxHealth() -{ - if (isTame()) - { - return TAME_HEALTH; - } - return START_HEALTH; -} - void Wolf::defineSynchedData() { TamableAnimal::defineSynchedData(); entityData->define(DATA_HEALTH_ID, getHealth()); entityData->define(DATA_INTERESTED_ID, (byte)0); - entityData->define(DATA_COLLAR_COLOR, (byte) ClothTile::getTileDataForItemAuxValue(DyePowderItem::RED)); + entityData->define(DATA_COLLAR_COLOR, (byte) ColoredTile::getTileDataForItemAuxValue(DyePowderItem::RED)); } -bool Wolf::makeStepSound() +void Wolf::playStepSound(int xt, int yt, int zt, int t) { - return false; -} - -int Wolf::getTexture() -{ - if (isTame()) - { - return TN_MOB_WOLF_TAME; // 4J was L"/mob/wolf_tame.png"; - } - if (isAngry()) - { - return TN_MOB_WOLF_ANGRY; // 4J was L"/mob/wolf_angry.png"; - } - return TamableAnimal::getTexture(); + playSound(eSoundType_MOB_WOLF_STEP, 0.15f, 1); } void Wolf::addAdditonalSaveData(CompoundTag *tag) @@ -129,11 +125,6 @@ void Wolf::readAdditionalSaveData(CompoundTag *tag) if (tag->contains(L"CollarColor")) setCollarColor(tag->getByte(L"CollarColor")); } -bool Wolf::removeWhenFarAway() -{ - return !isTame(); -} - int Wolf::getAmbientSound() { if (isAngry()) @@ -142,7 +133,7 @@ int Wolf::getAmbientSound() } if (random->nextInt(3) == 0) { - if (isTame() && entityData->getInteger(DATA_HEALTH_ID) < 10) + if (isTame() && entityData->getFloat(DATA_HEALTH_ID) < 10) { return eSoundType_MOB_WOLF_WHINE; } @@ -217,7 +208,7 @@ void Wolf::tick() if (shakeAnim == 0) { - level->playSound(shared_from_this(), eSoundType_MOB_WOLF_SHAKE, getSoundVolume(), (random->nextFloat() - random->nextFloat()) * 0.2f + 1.0f); + playSound(eSoundType_MOB_WOLF_SHAKE, getSoundVolume(), (random->nextFloat() - random->nextFloat()) * 0.2f + 1.0f); } shakeAnimO = shakeAnim; @@ -289,14 +280,25 @@ int Wolf::getMaxHeadXRot() return TamableAnimal::getMaxHeadXRot(); } -bool Wolf::hurt(DamageSource *source, int dmg) +bool Wolf::hurt(DamageSource *source, float dmg) { + // 4J: Protect owned wolves from untrusted players + if (isTame()) + { + shared_ptr<Entity> entity = source->getDirectEntity(); + if (entity != NULL && entity->instanceof(eTYPE_PLAYER)) + { + shared_ptr<Player> attacker = dynamic_pointer_cast<Player>(entity); + attacker->canHarmPlayer(getOwnerUUID()); + } + } + if (isInvulnerable()) return false; shared_ptr<Entity> sourceEntity = source->getEntity(); sitGoal->wantToSit(false); - if (sourceEntity != NULL && !(dynamic_pointer_cast<Player>(sourceEntity) != NULL || dynamic_pointer_cast<Arrow>(sourceEntity) != NULL)) + if (sourceEntity != NULL && !(sourceEntity->instanceof(eTYPE_PLAYER) || sourceEntity->instanceof(eTYPE_ARROW))) { - // take half damage from non-players and arrows + // Take half damage from non-players and arrows dmg = (dmg + 1) / 2; } return TamableAnimal::hurt(source, dmg); @@ -308,6 +310,20 @@ bool Wolf::doHurtTarget(shared_ptr<Entity> target) return target->hurt(DamageSource::mobAttack(dynamic_pointer_cast<Mob>(shared_from_this())), damage); } +void Wolf::setTame(bool value) +{ + TamableAnimal::setTame(value); + + if (value) + { + getAttribute(SharedMonsterAttributes::MAX_HEALTH)->setBaseValue(TAME_HEALTH); + } + else + { + getAttribute(SharedMonsterAttributes::MAX_HEALTH)->setBaseValue(START_HEALTH); + } +} + void Wolf::tame(const wstring &wsOwnerUUID, bool bDisplayTamingParticles, bool bSetSitting) { setTame(true); @@ -322,7 +338,7 @@ void Wolf::tame(const wstring &wsOwnerUUID, bool bDisplayTamingParticles, bool b spawnTamingParticles(bDisplayTamingParticles); } -bool Wolf::interact(shared_ptr<Player> player) +bool Wolf::mobInteract(shared_ptr<Player> player) { shared_ptr<ItemInstance> item = player->inventory->getSelected(); @@ -334,28 +350,24 @@ bool Wolf::interact(shared_ptr<Player> player) { FoodItem *food = dynamic_cast<FoodItem *>( Item::items[item->id] ); - if (food->isMeat()) + if (food->isMeat() && entityData->getFloat(DATA_HEALTH_ID) < MAX_HEALTH) { - if(entityData->getInteger(DATA_HEALTH_ID) < MAX_HEALTH) + heal(food->getNutrition()); + // 4J-PB - don't lose the bone in creative mode + if (player->abilities.instabuild==false) { - heal(food->getNutrition()); - // 4J-PB - don't lose the bone in creative mode - if (player->abilities.instabuild==false) + item->count--; + if (item->count <= 0) { - item->count--; - if (item->count <= 0) - { - player->inventory->setItem(player->inventory->selected, nullptr); - } + player->inventory->setItem(player->inventory->selected, nullptr); } - return true; } - else return TamableAnimal::interact(player); + return true; } } else if (item->id == Item::dye_powder_Id) { - int color = ClothTile::getTileDataForItemAuxValue(item->getAuxValue()); + int color = ColoredTile::getTileDataForItemAuxValue(item->getAuxValue()); if (color != getCollarColor()) { setCollarColor(color); @@ -376,6 +388,8 @@ bool Wolf::interact(shared_ptr<Player> player) sitGoal->wantToSit(!isSitting()); jumping = false; setPath(NULL); + setAttackTarget(nullptr); + setTarget(nullptr); } } } @@ -403,7 +417,7 @@ bool Wolf::interact(shared_ptr<Player> player) // 4J Changed to this tame(player->getUUID(),true,true); - level->broadcastEntityEvent(shared_from_this(), EntityEvent::TAMING_SUCCEEDED); + level->broadcastEntityEvent(shared_from_this(), EntityEvent::TAMING_SUCCEEDED); } else { @@ -421,7 +435,7 @@ bool Wolf::interact(shared_ptr<Player> player) return false; } } - return TamableAnimal::interact(player); + return TamableAnimal::mobInteract(player); } void Wolf::handleEntityEvent(byte id) @@ -446,7 +460,7 @@ float Wolf::getTailAngle() } else if (isTame()) { - return (0.55f - (MAX_HEALTH - entityData->getInteger(DATA_HEALTH_ID)) * 0.02f) * PI; + return (0.55f - (MAX_HEALTH - entityData->getFloat(DATA_HEALTH_ID)) * 0.02f) * PI; } return 0.20f * PI; } @@ -520,8 +534,6 @@ shared_ptr<AgableMob> Wolf::getBreedOffspring(shared_ptr<AgableMob> target) void Wolf::setIsInterested(bool value) { - //byte current = entityData->getByte(DATA_INTERESTED_ID); - if (value) { entityData->set(DATA_INTERESTED_ID, (byte) 1); @@ -536,7 +548,10 @@ bool Wolf::canMate(shared_ptr<Animal> animal) { if (animal == shared_from_this()) return false; if (!isTame()) return false; + + if (!animal->instanceof(eTYPE_WOLF)) return false; shared_ptr<Wolf> partner = dynamic_pointer_cast<Wolf>(animal); + if (partner == NULL) return false; if (!partner->isTame()) return false; if (partner->isSitting()) return false; @@ -548,3 +563,37 @@ bool Wolf::isInterested() { return entityData->getByte(DATA_INTERESTED_ID) == 1; } + +bool Wolf::removeWhenFarAway() +{ + return !isTame() && tickCount > SharedConstants::TICKS_PER_SECOND * 60 * 2; +} + +bool Wolf::wantsToAttack(shared_ptr<LivingEntity> target, shared_ptr<LivingEntity> owner) +{ + // filter un-attackable mobs + if (target->GetType() == eTYPE_CREEPER || target->GetType() == eTYPE_GHAST) + { + return false; + } + // never target wolves that has this player as owner + if (target->GetType() == eTYPE_WOLF) + { + shared_ptr<Wolf> wolfTarget = dynamic_pointer_cast<Wolf>(target); + if (wolfTarget->isTame() && wolfTarget->getOwner() == owner) + { + return false; + } + } + if ( target->instanceof(eTYPE_PLAYER) && owner->instanceof(eTYPE_PLAYER) && !dynamic_pointer_cast<Player>(owner)->canHarmPlayer(dynamic_pointer_cast<Player>(target) )) + { + // pvp is off + return false; + } + // don't attack tame horses + if ((target->GetType() == eTYPE_HORSE) && dynamic_pointer_cast<EntityHorse>(target)->isTamed()) + { + return false; + } + return true; +}
\ No newline at end of file |
