Files
Purpur/patches/server/0115-Configurable-chance-for-wolves-to-spawn-rabid.patch
2023-08-13 03:30:27 -07:00

245 lines
12 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Encode42 <me@encode42.dev>
Date: Tue, 8 Dec 2020 17:15:15 -0500
Subject: [PATCH] Configurable chance for wolves to spawn rabid
Configurable chance to spawn a wolf that is rabid.
Rabid wolves attack all players, mobs, and animals.
diff --git a/src/main/java/net/minecraft/world/entity/animal/Wolf.java b/src/main/java/net/minecraft/world/entity/animal/Wolf.java
index d8c73365915e67b38292c96a9601f983f121bdf9..f39b278bc520a4785e9fa472bccd836ad1daac85 100644
--- a/src/main/java/net/minecraft/world/entity/animal/Wolf.java
+++ b/src/main/java/net/minecraft/world/entity/animal/Wolf.java
@@ -10,6 +10,7 @@ import net.minecraft.network.syncher.EntityDataAccessor;
import net.minecraft.network.syncher.EntityDataSerializers;
import net.minecraft.network.syncher.SynchedEntityData;
import net.minecraft.server.level.ServerLevel;
+import net.minecraft.server.level.ServerPlayer;
import net.minecraft.sounds.SoundEvent;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.tags.BlockTags;
@@ -17,9 +18,12 @@ import net.minecraft.util.Mth;
import net.minecraft.util.RandomSource;
import net.minecraft.util.TimeUtil;
import net.minecraft.util.valueproviders.UniformInt;
+import net.minecraft.world.DifficultyInstance;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.damagesource.DamageSource;
+import net.minecraft.world.effect.MobEffectInstance;
+import net.minecraft.world.effect.MobEffects;
import net.minecraft.world.entity.AgeableMob;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityDimensions;
@@ -29,6 +33,7 @@ import net.minecraft.world.entity.Mob;
import net.minecraft.world.entity.MobSpawnType;
import net.minecraft.world.entity.NeutralMob;
import net.minecraft.world.entity.Pose;
+import net.minecraft.world.entity.SpawnGroupData;
import net.minecraft.world.entity.TamableAnimal;
import net.minecraft.world.entity.ai.attributes.AttributeSupplier;
import net.minecraft.world.entity.ai.attributes.Attributes;
@@ -37,6 +42,7 @@ import net.minecraft.world.entity.ai.goal.BegGoal;
import net.minecraft.world.entity.ai.goal.BreedGoal;
import net.minecraft.world.entity.ai.goal.FloatGoal;
import net.minecraft.world.entity.ai.goal.FollowOwnerGoal;
+import net.minecraft.world.entity.ai.goal.Goal;
import net.minecraft.world.entity.ai.goal.LeapAtTargetGoal;
import net.minecraft.world.entity.ai.goal.LookAtPlayerGoal;
import net.minecraft.world.entity.ai.goal.MeleeAttackGoal;
@@ -64,6 +70,7 @@ import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelAccessor;
+import net.minecraft.world.level.ServerLevelAccessor;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.gameevent.GameEvent;
import net.minecraft.world.level.pathfinder.BlockPathTypes;
@@ -84,6 +91,37 @@ public class Wolf extends TamableAnimal implements NeutralMob {
return entitytypes == EntityType.SHEEP || entitytypes == EntityType.RABBIT || entitytypes == EntityType.FOX;
};
+ // Purpur start - rabid wolf spawn chance
+ private boolean isRabid = false;
+ private static final Predicate<LivingEntity> RABID_PREDICATE = entity -> entity instanceof ServerPlayer || entity instanceof Mob;
+ private final Goal PATHFINDER_VANILLA = new NonTameRandomTargetGoal<>(this, Animal.class, false, PREY_SELECTOR);
+ private final Goal PATHFINDER_RABID = new NonTameRandomTargetGoal<>(this, LivingEntity.class, false, RABID_PREDICATE);
+ private static final class AvoidRabidWolfGoal extends AvoidEntityGoal<Wolf> {
+ private final Wolf wolf;
+
+ public AvoidRabidWolfGoal(Wolf wolf, float distance, double minSpeed, double maxSpeed) {
+ super(wolf, Wolf.class, distance, minSpeed, maxSpeed);
+ this.wolf = wolf;
+ }
+
+ @Override
+ public boolean canUse() {
+ return super.canUse() && !this.wolf.isRabid() && this.toAvoid != null && this.toAvoid.isRabid(); // wolves which are not rabid run away from rabid wolves
+ }
+
+ @Override
+ public void start() {
+ this.wolf.setTarget(null);
+ super.start();
+ }
+
+ @Override
+ public void tick() {
+ this.wolf.setTarget(null);
+ super.tick();
+ }
+ }
+ // Purpur end
private static final float START_HEALTH = 8.0F;
private static final float TAME_HEALTH = 20.0F;
private float interestedAngle;
@@ -135,6 +173,37 @@ public class Wolf extends TamableAnimal implements NeutralMob {
return this.level().purpurConfig.wolfBreedingTicks;
}
+ public boolean isRabid() {
+ return this.isRabid;
+ }
+
+ public void setRabid(boolean isRabid) {
+ this.isRabid = isRabid;
+ updatePathfinders(true);
+ }
+
+ public void updatePathfinders(boolean modifyEffects) {
+ this.targetSelector.removeGoal(PATHFINDER_VANILLA);
+ this.targetSelector.removeGoal(PATHFINDER_RABID);
+ if (this.isRabid) {
+ setTame(false);
+ setOwnerUUID(null);
+ this.targetSelector.addGoal(5, PATHFINDER_RABID);
+ if (modifyEffects) this.addEffect(new MobEffectInstance(MobEffects.CONFUSION, 1200));
+ } else {
+ this.targetSelector.addGoal(5, PATHFINDER_VANILLA);
+ this.stopBeingAngry();
+ if (modifyEffects) this.removeEffect(MobEffects.CONFUSION);
+ }
+ }
+
+ @Override
+ public SpawnGroupData finalizeSpawn(ServerLevelAccessor world, DifficultyInstance difficulty, MobSpawnType type, @Nullable SpawnGroupData data, @Nullable CompoundTag nbt) {
+ this.isRabid = world.getLevel().purpurConfig.wolfNaturalRabid > 0.0D && random.nextDouble() <= world.getLevel().purpurConfig.wolfNaturalRabid;
+ this.updatePathfinders(false);
+ return super.finalizeSpawn(world, difficulty, type, data, nbt);
+ }
+
@Override
protected void registerGoals() {
this.goalSelector.addGoal(1, new FloatGoal(this));
@@ -142,6 +211,7 @@ public class Wolf extends TamableAnimal implements NeutralMob {
this.goalSelector.addGoal(1, new Wolf.WolfPanicGoal(1.5D));
this.goalSelector.addGoal(2, new SitWhenOrderedToGoal(this));
this.goalSelector.addGoal(3, new Wolf.WolfAvoidEntityGoal<>(this, Llama.class, 24.0F, 1.5D, 1.5D));
+ this.goalSelector.addGoal(3, new AvoidRabidWolfGoal(this, 24.0F, 1.5D, 1.5D)); // Purpur
this.goalSelector.addGoal(4, new LeapAtTargetGoal(this, 0.4F));
this.goalSelector.addGoal(5, new MeleeAttackGoal(this, 1.0D, true));
this.goalSelector.addGoal(6, new FollowOwnerGoal(this, 1.0D, 10.0F, 2.0F, false));
@@ -155,7 +225,7 @@ public class Wolf extends TamableAnimal implements NeutralMob {
this.targetSelector.addGoal(2, new OwnerHurtTargetGoal(this));
this.targetSelector.addGoal(3, (new HurtByTargetGoal(this, new Class[0])).setAlertOthers());
this.targetSelector.addGoal(4, new NearestAttackableTargetGoal<>(this, Player.class, 10, true, false, this::isAngryAt));
- this.targetSelector.addGoal(5, new NonTameRandomTargetGoal<>(this, Animal.class, false, Wolf.PREY_SELECTOR));
+ // this.targetSelector.addGoal(5, new NonTameRandomTargetGoal<>(this, Animal.class, false, Wolf.PREY_SELECTOR)); // Purpur - moved to updatePathfinders()
this.targetSelector.addGoal(6, new NonTameRandomTargetGoal<>(this, Turtle.class, false, Turtle.BABY_ON_LAND_SELECTOR));
this.targetSelector.addGoal(7, new NearestAttackableTargetGoal<>(this, AbstractSkeleton.class, false));
this.targetSelector.addGoal(8, new ResetUniversalAngerTargetGoal<>(this, true));
@@ -182,6 +252,7 @@ public class Wolf extends TamableAnimal implements NeutralMob {
public void addAdditionalSaveData(CompoundTag nbt) {
super.addAdditionalSaveData(nbt);
nbt.putByte("CollarColor", (byte) this.getCollarColor().getId());
+ nbt.putBoolean("Purpur.IsRabid", this.isRabid); // Purpur
this.addPersistentAngerSaveData(nbt);
}
@@ -191,6 +262,10 @@ public class Wolf extends TamableAnimal implements NeutralMob {
if (nbt.contains("CollarColor", 99)) {
this.setCollarColor(DyeColor.byId(nbt.getInt("CollarColor")));
}
+ // Purpur start
+ this.isRabid = nbt.getBoolean("Purpur.IsRabid");
+ this.updatePathfinders(false);
+ // Purpur end
this.readPersistentAngerSaveData(this.level(), nbt);
}
@@ -235,6 +310,11 @@ public class Wolf extends TamableAnimal implements NeutralMob {
public void tick() {
super.tick();
if (this.isAlive()) {
+ // Purpur start
+ if (this.age % 300 == 0 && this.isRabid()) {
+ this.addEffect(new MobEffectInstance(MobEffects.CONFUSION, 400));
+ }
+ // Purpur end
this.interestedAngleO = this.interestedAngle;
if (this.isInterested()) {
this.interestedAngle += (1.0F - this.interestedAngle) * 0.4F;
@@ -450,6 +530,19 @@ public class Wolf extends TamableAnimal implements NeutralMob {
}
return InteractionResult.SUCCESS;
+ // Purpur start
+ } else if (this.level().purpurConfig.wolfMilkCuresRabies && itemstack.getItem() == Items.MILK_BUCKET && this.isRabid()) {
+ if (!player.isCreative()) {
+ player.setItemInHand(hand, new ItemStack(Items.BUCKET));
+ }
+ this.setRabid(false);
+ for (int i = 0; i < 10; ++i) {
+ ((ServerLevel) level()).sendParticles(((ServerLevel) level()).players(), null, ParticleTypes.HAPPY_VILLAGER,
+ getX() + random.nextFloat(), getY() + (random.nextFloat() * 1.5), getZ() + random.nextFloat(), 1,
+ random.nextGaussian() * 0.05D, random.nextGaussian() * 0.05D, random.nextGaussian() * 0.05D, 0, true);
+ }
+ return InteractionResult.SUCCESS;
+ // Purpur end
} else {
return super.mobInteract(player, hand);
}
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftWolf.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftWolf.java
index e43fd3e59fd8c74828ae65965fade27f56beef65..b2f133c8baabba1cffa6e92ea0f854532f4c181b 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftWolf.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftWolf.java
@@ -63,4 +63,16 @@ public class CraftWolf extends CraftTameableAnimal implements Wolf {
public void setInterested(boolean flag) {
this.getHandle().setIsInterested(flag);
}
+
+ // Purpur start
+ @Override
+ public boolean isRabid() {
+ return getHandle().isRabid();
+ }
+
+ @Override
+ public void setRabid(boolean isRabid) {
+ getHandle().setRabid(isRabid);
+ }
+ // Purpur end
}
diff --git a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
index dd3c9dd7bb6de648785a74fab7e011b6c472a0ed..0ccb2b3304482b6e8d92e3b9b4889e7b3823ed5b 100644
--- a/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
+++ b/src/main/java/org/purpurmc/purpur/PurpurWorldConfig.java
@@ -1943,6 +1943,8 @@ public class PurpurWorldConfig {
public boolean wolfRidableInWater = true;
public boolean wolfControllable = true;
public double wolfMaxHealth = 8.0D;
+ public boolean wolfMilkCuresRabies = true;
+ public double wolfNaturalRabid = 0.0D;
public int wolfBreedingTicks = 6000;
private void wolfSettings() {
wolfRidable = getBoolean("mobs.wolf.ridable", wolfRidable);
@@ -1954,6 +1956,8 @@ public class PurpurWorldConfig {
set("mobs.wolf.attributes.max_health", oldValue);
}
wolfMaxHealth = getDouble("mobs.wolf.attributes.max_health", wolfMaxHealth);
+ wolfMilkCuresRabies = getBoolean("mobs.wolf.milk-cures-rabid-wolves", wolfMilkCuresRabies);
+ wolfNaturalRabid = getDouble("mobs.wolf.spawn-rabid-chance", wolfNaturalRabid);
wolfBreedingTicks = getInt("mobs.wolf.breeding-delay-ticks", wolfBreedingTicks);
}