From b3feddfef372618c8a9d7a0abcaf18cfad866c18 Mon Sep 17 00:00:00 2001 From: daoge <3523206925@qq.com> Date: Tue, 3 Mar 2026 03:04:10 +0800 Subject: feat: TU19 (Dec 2014) Features & Content (#155) * try to resolve merge conflict * feat: TU19 (Dec 2014) Features & Content (#32) * December 2014 files * Working release build * Fix compilation issues * Add sound to Windows64Media * Add DLC content and force Tutorial DLC * Revert "Add DLC content and force Tutorial DLC" This reverts commit 97a43994725008e35fceb984d5549df9c8cea470. * Disable broken light packing * Disable breakpoint during DLC texture map load Allows DLC loading but the DLC textures are still broken * Fix post build not working * ... * fix vs2022 build * fix cmake build --------- Co-authored-by: Loki --- Minecraft.World/Wolf.cpp | 183 ++++++++++++++++++++++++++++++----------------- 1 file changed, 116 insertions(+), 67 deletions(-) (limited to 'Minecraft.World/Wolf.cpp') 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 target) +void Wolf::setTarget(shared_ptr target) { TamableAnimal::setTarget(target); - if ( dynamic_pointer_cast(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 = source->getDirectEntity(); + if (entity != NULL && entity->instanceof(eTYPE_PLAYER)) + { + shared_ptr attacker = dynamic_pointer_cast(entity); + attacker->canHarmPlayer(getOwnerUUID()); + } + } + if (isInvulnerable()) return false; shared_ptr sourceEntity = source->getEntity(); sitGoal->wantToSit(false); - if (sourceEntity != NULL && !(dynamic_pointer_cast(sourceEntity) != NULL || dynamic_pointer_cast(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 target) return target->hurt(DamageSource::mobAttack(dynamic_pointer_cast(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) +bool Wolf::mobInteract(shared_ptr player) { shared_ptr item = player->inventory->getSelected(); @@ -334,28 +350,24 @@ bool Wolf::interact(shared_ptr player) { FoodItem *food = dynamic_cast( 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) sitGoal->wantToSit(!isSitting()); jumping = false; setPath(NULL); + setAttackTarget(nullptr); + setTarget(nullptr); } } } @@ -403,7 +417,7 @@ bool Wolf::interact(shared_ptr 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) 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 Wolf::getBreedOffspring(shared_ptr 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) { if (animal == shared_from_this()) return false; if (!isTame()) return false; + + if (!animal->instanceof(eTYPE_WOLF)) return false; shared_ptr partner = dynamic_pointer_cast(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 target, shared_ptr 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 wolfTarget = dynamic_pointer_cast(target); + if (wolfTarget->isTame() && wolfTarget->getOwner() == owner) + { + return false; + } + } + if ( target->instanceof(eTYPE_PLAYER) && owner->instanceof(eTYPE_PLAYER) && !dynamic_pointer_cast(owner)->canHarmPlayer(dynamic_pointer_cast(target) )) + { + // pvp is off + return false; + } + // don't attack tame horses + if ((target->GetType() == eTYPE_HORSE) && dynamic_pointer_cast(target)->isTamed()) + { + return false; + } + return true; +} \ No newline at end of file -- cgit v1.2.3