diff options
author | MiniDigger | Martin <[email protected]> | 2024-01-14 11:04:49 +0100 |
---|---|---|
committer | MiniDigger | Martin <[email protected]> | 2024-01-14 11:04:49 +0100 |
commit | bee74680e607c2e29b038329f62181238911cd83 (patch) | |
tree | 708fd1a4a0227d9071243adf2a42d5e9e96cde4a /patch-remap/mache-vineflower/net/minecraft/world/entity/monster | |
parent | 0a44692ef6ff6e255d48eb3ba1bb114166eafda9 (diff) | |
download | Paper-softspoon.tar.gz Paper-softspoon.zip |
add remapped patches as a testsoftspoon
Diffstat (limited to 'patch-remap/mache-vineflower/net/minecraft/world/entity/monster')
30 files changed, 12063 insertions, 0 deletions
diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/AbstractSkeleton.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/AbstractSkeleton.java.patch new file mode 100644 index 0000000000..c20b81663c --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/AbstractSkeleton.java.patch @@ -0,0 +1,238 @@ +--- a/net/minecraft/world/entity/monster/AbstractSkeleton.java ++++ b/net/minecraft/world/entity/monster/AbstractSkeleton.java +@@ -12,14 +12,14 @@ + import net.minecraft.world.DifficultyInstance; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.EnumMonsterType; + import net.minecraft.world.entity.EquipmentSlot; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.LivingEntity; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.MobType; + import net.minecraft.world.entity.PathfinderMob; +-import net.minecraft.world.entity.Pose; +-import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; + import net.minecraft.world.entity.ai.attributes.Attributes; + import net.minecraft.world.entity.ai.goal.AvoidEntityGoal; +@@ -44,11 +44,12 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.ServerLevelAccessor; + import net.minecraft.world.level.block.Blocks; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + + public abstract class AbstractSkeleton extends Monster implements RangedAttackMob { +- private final RangedBowAttackGoal<AbstractSkeleton> bowGoal = new RangedBowAttackGoal<>(this, 1.0, 20, 15.0F); +- private final MeleeAttackGoal meleeGoal = new MeleeAttackGoal(this, 1.2, false) { ++ ++ private final RangedBowAttackGoal<AbstractSkeleton> bowGoal = new RangedBowAttackGoal<>(this, 1.0D, 20, 15.0F); ++ private final MeleeAttackGoal meleeGoal = new MeleeAttackGoal(this, 1.2D, false) { + @Override + public void stop() { + super.stop(); +@@ -70,51 +71,53 @@ + @Override + protected void registerGoals() { + this.goalSelector.addGoal(2, new RestrictSunGoal(this)); +- this.goalSelector.addGoal(3, new FleeSunGoal(this, 1.0)); +- this.goalSelector.addGoal(3, new AvoidEntityGoal<>(this, Wolf.class, 6.0F, 1.0, 1.2)); +- this.goalSelector.addGoal(5, new WaterAvoidingRandomStrollGoal(this, 1.0)); ++ this.goalSelector.addGoal(3, new FleeSunGoal(this, 1.0D)); ++ this.goalSelector.addGoal(3, new AvoidEntityGoal<>(this, Wolf.class, 6.0F, 1.0D, 1.2D)); ++ this.goalSelector.addGoal(5, new WaterAvoidingRandomStrollGoal(this, 1.0D)); + this.goalSelector.addGoal(6, new LookAtPlayerGoal(this, Player.class, 8.0F)); + this.goalSelector.addGoal(6, new RandomLookAroundGoal(this)); +- this.targetSelector.addGoal(1, new HurtByTargetGoal(this)); ++ this.targetSelector.addGoal(1, new HurtByTargetGoal(this, new Class[0])); + this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, true)); + this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, IronGolem.class, true)); + this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, Turtle.class, 10, true, false, Turtle.BABY_ON_LAND_SELECTOR)); + } + + public static AttributeSupplier.Builder createAttributes() { +- return Monster.createMonsterAttributes().add(Attributes.MOVEMENT_SPEED, 0.25); ++ return Monster.createMonsterAttributes().add(Attributes.MOVEMENT_SPEED, 0.25D); + } + + @Override +- protected void playStepSound(BlockPos pos, BlockState block) { ++ protected void playStepSound(BlockPos pos, IBlockData block) { + this.playSound(this.getStepSound(), 0.15F, 1.0F); + } + + abstract SoundEvent getStepSound(); + + @Override +- public MobType getMobType() { +- return MobType.UNDEAD; ++ public EnumMonsterType getMobType() { ++ return EnumMonsterType.UNDEAD; + } + + @Override + public void aiStep() { +- boolean isSunBurnTick = this.isSunBurnTick(); +- if (isSunBurnTick) { +- ItemStack itemBySlot = this.getItemBySlot(EquipmentSlot.HEAD); +- if (!itemBySlot.isEmpty()) { +- if (itemBySlot.isDamageableItem()) { +- itemBySlot.setDamageValue(itemBySlot.getDamageValue() + this.random.nextInt(2)); +- if (itemBySlot.getDamageValue() >= itemBySlot.getMaxDamage()) { ++ boolean flag = this.isSunBurnTick(); ++ ++ if (flag) { ++ ItemStack itemstack = this.getItemBySlot(EquipmentSlot.HEAD); ++ ++ if (!itemstack.isEmpty()) { ++ if (itemstack.isDamageableItem()) { ++ itemstack.setDamageValue(itemstack.getDamageValue() + this.random.nextInt(2)); ++ if (itemstack.getDamageValue() >= itemstack.getMaxDamage()) { + this.broadcastBreakEvent(EquipmentSlot.HEAD); + this.setItemSlot(EquipmentSlot.HEAD, ItemStack.EMPTY); + } + } + +- isSunBurnTick = false; ++ flag = false; + } + +- if (isSunBurnTick) { ++ if (flag) { + this.setSecondsOnFire(8); + } + } +@@ -125,9 +128,14 @@ + @Override + public void rideTick() { + super.rideTick(); +- if (this.getControlledVehicle() instanceof PathfinderMob pathfinderMob) { +- this.yBodyRot = pathfinderMob.yBodyRot; ++ Entity entity = this.getControlledVehicle(); ++ ++ if (entity instanceof PathfinderMob) { ++ PathfinderMob entitycreature = (PathfinderMob) entity; ++ ++ this.yBodyRot = entitycreature.yBodyRot; + } ++ + } + + @Override +@@ -138,58 +146,73 @@ + + @Nullable + @Override +- public SpawnGroupData finalizeSpawn( +- ServerLevelAccessor level, DifficultyInstance difficulty, MobSpawnType reason, @Nullable SpawnGroupData spawnData, @Nullable CompoundTag dataTag +- ) { +- SpawnGroupData var10 = super.finalizeSpawn(level, difficulty, reason, spawnData, dataTag); +- RandomSource random = level.getRandom(); +- this.populateDefaultEquipmentSlots(random, difficulty); +- this.populateDefaultEquipmentEnchantments(random, difficulty); ++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) { ++ spawnData = super.finalizeSpawn(level, difficulty, reason, spawnData, dataTag); ++ RandomSource randomsource = level.getRandom(); ++ ++ this.populateDefaultEquipmentSlots(randomsource, difficulty); ++ this.populateDefaultEquipmentEnchantments(randomsource, difficulty); + this.reassessWeaponGoal(); +- this.setCanPickUpLoot(random.nextFloat() < 0.55F * difficulty.getSpecialMultiplier()); ++ this.setCanPickUpLoot(randomsource.nextFloat() < 0.55F * difficulty.getSpecialMultiplier()); + if (this.getItemBySlot(EquipmentSlot.HEAD).isEmpty()) { +- LocalDate localDate = LocalDate.now(); +- int i = localDate.get(ChronoField.DAY_OF_MONTH); +- int i1 = localDate.get(ChronoField.MONTH_OF_YEAR); +- if (i1 == 10 && i == 31 && random.nextFloat() < 0.25F) { +- this.setItemSlot(EquipmentSlot.HEAD, new ItemStack(random.nextFloat() < 0.1F ? Blocks.JACK_O_LANTERN : Blocks.CARVED_PUMPKIN)); ++ LocalDate localdate = LocalDate.now(); ++ int i = localdate.get(ChronoField.DAY_OF_MONTH); ++ int j = localdate.get(ChronoField.MONTH_OF_YEAR); ++ ++ if (j == 10 && i == 31 && randomsource.nextFloat() < 0.25F) { ++ this.setItemSlot(EquipmentSlot.HEAD, new ItemStack(randomsource.nextFloat() < 0.1F ? Blocks.JACK_O_LANTERN : Blocks.CARVED_PUMPKIN)); + this.armorDropChances[EquipmentSlot.HEAD.getIndex()] = 0.0F; + } + } + +- return var10; ++ return spawnData; + } + + public void reassessWeaponGoal() { + if (this.level() != null && !this.level().isClientSide) { + this.goalSelector.removeGoal(this.meleeGoal); + this.goalSelector.removeGoal(this.bowGoal); +- ItemStack itemInHand = this.getItemInHand(ProjectileUtil.getWeaponHoldingHand(this, Items.BOW)); +- if (itemInHand.is(Items.BOW)) { +- int i = 20; ++ ItemStack itemstack = this.getItemInHand(ProjectileUtil.getWeaponHoldingHand(this, Items.BOW)); ++ ++ if (itemstack.is(Items.BOW)) { ++ byte b0 = 20; ++ + if (this.level().getDifficulty() != Difficulty.HARD) { +- i = 40; ++ b0 = 40; + } + +- this.bowGoal.setMinAttackInterval(i); ++ this.bowGoal.setMinAttackInterval(b0); + this.goalSelector.addGoal(4, this.bowGoal); + } else { + this.goalSelector.addGoal(4, this.meleeGoal); + } ++ + } + } + + @Override + public void performRangedAttack(LivingEntity target, float distanceFactor) { +- ItemStack projectile = this.getProjectile(this.getItemInHand(ProjectileUtil.getWeaponHoldingHand(this, Items.BOW))); +- AbstractArrow arrow = this.getArrow(projectile, distanceFactor); +- double d = target.getX() - this.getX(); +- double d1 = target.getY(0.3333333333333333) - arrow.getY(); ++ ItemStack itemstack = this.getProjectile(this.getItemInHand(ProjectileUtil.getWeaponHoldingHand(this, Items.BOW))); ++ AbstractArrow entityarrow = this.getArrow(itemstack, distanceFactor); ++ double d0 = target.getX() - this.getX(); ++ double d1 = target.getY(0.3333333333333333D) - entityarrow.getY(); + double d2 = target.getZ() - this.getZ(); +- double squareRoot = Math.sqrt(d * d + d2 * d2); +- arrow.shoot(d, d1 + squareRoot * 0.2F, d2, 1.6F, (float)(14 - this.level().getDifficulty().getId() * 4)); ++ double d3 = Math.sqrt(d0 * d0 + d2 * d2); ++ ++ entityarrow.shoot(d0, d1 + d3 * 0.20000000298023224D, d2, 1.6F, (float) (14 - this.level().getDifficulty().getId() * 4)); ++ // CraftBukkit start ++ org.bukkit.event.entity.EntityShootBowEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityShootBowEvent(this, this.getMainHandItem(), null, entityarrow, net.minecraft.world.EnumHand.MAIN_HAND, 0.8F, true); ++ if (event.isCancelled()) { ++ event.getProjectile().remove(); ++ return; ++ } ++ ++ if (event.getProjectile() == entityarrow.getBukkitEntity()) { ++ this.level().addFreshEntity(entityarrow); ++ } ++ // CraftBukkit end + this.playSound(SoundEvents.SKELETON_SHOOT, 1.0F, 1.0F / (this.getRandom().nextFloat() * 0.4F + 0.8F)); +- this.level().addFreshEntity(arrow); ++ // this.level().addFreshEntity(entityarrow); // CraftBukkit - moved up + } + + protected AbstractArrow getArrow(ItemStack arrowStack, float velocity) { +@@ -213,10 +236,11 @@ + if (!this.level().isClientSide) { + this.reassessWeaponGoal(); + } ++ + } + + @Override +- protected float getStandingEyeHeight(Pose pose, EntityDimensions size) { ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions size) { + return 1.74F; + } + diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/CaveSpider.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/CaveSpider.java.patch new file mode 100644 index 0000000000..0bb3955f74 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/CaveSpider.java.patch @@ -0,0 +1,78 @@ +--- a/net/minecraft/world/entity/monster/CaveSpider.java ++++ b/net/minecraft/world/entity/monster/CaveSpider.java +@@ -8,11 +8,11 @@ + import net.minecraft.world.effect.MobEffects; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.LivingEntity; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.Pose; +-import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; + import net.minecraft.world.entity.ai.attributes.Attributes; + import net.minecraft.world.level.Level; +@@ -20,27 +20,29 @@ + import org.joml.Vector3f; + + public class CaveSpider extends Spider { ++ + public CaveSpider(EntityType<? extends CaveSpider> entityType, Level level) { + super(entityType, level); + } + + public static AttributeSupplier.Builder createCaveSpider() { +- return Spider.createAttributes().add(Attributes.MAX_HEALTH, 12.0); ++ return Spider.createAttributes().add(Attributes.MAX_HEALTH, 12.0D); + } + + @Override + public boolean doHurtTarget(Entity entity) { + if (super.doHurtTarget(entity)) { + if (entity instanceof LivingEntity) { +- int i = 0; ++ byte b0 = 0; ++ + if (this.level().getDifficulty() == Difficulty.NORMAL) { +- i = 7; ++ b0 = 7; + } else if (this.level().getDifficulty() == Difficulty.HARD) { +- i = 15; ++ b0 = 15; + } + +- if (i > 0) { +- ((LivingEntity)entity).addEffect(new MobEffectInstance(MobEffects.POISON, i * 20, 0), this); ++ if (b0 > 0) { ++ ((LivingEntity) entity).addEffect(new MobEffectInstance(MobEffects.POISON, b0 * 20, 0), this, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit + } + } + +@@ -52,20 +54,18 @@ + + @Nullable + @Override +- public SpawnGroupData finalizeSpawn( +- ServerLevelAccessor level, DifficultyInstance difficulty, MobSpawnType reason, @Nullable SpawnGroupData spawnData, @Nullable CompoundTag dataTag +- ) { ++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) { + return spawnData; + } + + @Override +- protected float getStandingEyeHeight(Pose pose, EntityDimensions size) { ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions size) { + return 0.45F; + } + + @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entityDimensions, float f) { +- return new Vector3f(0.0F, entityDimensions.height, 0.0F); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ return new Vector3f(0.0F, entitysize.height, 0.0F); + } + + @Override diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Creeper.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Creeper.java.patch new file mode 100644 index 0000000000..4a441084d9 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Creeper.java.patch @@ -0,0 +1,319 @@ +--- a/net/minecraft/world/entity/monster/Creeper.java ++++ b/net/minecraft/world/entity/monster/Creeper.java +@@ -1,6 +1,7 @@ + package net.minecraft.world.entity.monster; + + import java.util.Collection; ++import java.util.Iterator; + import javax.annotation.Nullable; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.network.syncher.EntityDataAccessor; +@@ -11,7 +12,7 @@ + import net.minecraft.sounds.SoundEvents; + import net.minecraft.tags.ItemTags; + import net.minecraft.util.Mth; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.effect.MobEffectInstance; +@@ -38,17 +39,25 @@ + import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.Items; ++import net.minecraft.world.level.IMaterial; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.gameevent.GameEvent; + ++// CraftBukkit start; ++import org.bukkit.event.entity.CreatureSpawnEvent; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.ExplosionPrimeEvent; ++// CraftBukkit end ++ + public class Creeper extends Monster implements PowerableMob { ++ + private static final EntityDataAccessor<Integer> DATA_SWELL_DIR = SynchedEntityData.defineId(Creeper.class, EntityDataSerializers.INT); + private static final EntityDataAccessor<Boolean> DATA_IS_POWERED = SynchedEntityData.defineId(Creeper.class, EntityDataSerializers.BOOLEAN); + private static final EntityDataAccessor<Boolean> DATA_IS_IGNITED = SynchedEntityData.defineId(Creeper.class, EntityDataSerializers.BOOLEAN); + private int oldSwell; +- private int swell; +- private int maxSwell = 30; +- private int explosionRadius = 3; ++ public int swell; ++ public int maxSwell = 30; ++ public int explosionRadius = 3; + private int droppedSkulls; + + public Creeper(EntityType<? extends Creeper> entityType, Level level) { +@@ -59,29 +68,30 @@ + protected void registerGoals() { + this.goalSelector.addGoal(1, new FloatGoal(this)); + this.goalSelector.addGoal(2, new SwellGoal(this)); +- this.goalSelector.addGoal(3, new AvoidEntityGoal<>(this, Ocelot.class, 6.0F, 1.0, 1.2)); +- this.goalSelector.addGoal(3, new AvoidEntityGoal<>(this, Cat.class, 6.0F, 1.0, 1.2)); +- this.goalSelector.addGoal(4, new MeleeAttackGoal(this, 1.0, false)); +- this.goalSelector.addGoal(5, new WaterAvoidingRandomStrollGoal(this, 0.8)); ++ this.goalSelector.addGoal(3, new AvoidEntityGoal<>(this, Ocelot.class, 6.0F, 1.0D, 1.2D)); ++ this.goalSelector.addGoal(3, new AvoidEntityGoal<>(this, Cat.class, 6.0F, 1.0D, 1.2D)); ++ this.goalSelector.addGoal(4, new MeleeAttackGoal(this, 1.0D, false)); ++ this.goalSelector.addGoal(5, new WaterAvoidingRandomStrollGoal(this, 0.8D)); + this.goalSelector.addGoal(6, new LookAtPlayerGoal(this, Player.class, 8.0F)); + this.goalSelector.addGoal(6, new RandomLookAroundGoal(this)); + this.targetSelector.addGoal(1, new NearestAttackableTargetGoal<>(this, Player.class, true)); +- this.targetSelector.addGoal(2, new HurtByTargetGoal(this)); ++ this.targetSelector.addGoal(2, new HurtByTargetGoal(this, new Class[0])); + } + + public static AttributeSupplier.Builder createAttributes() { +- return Monster.createMonsterAttributes().add(Attributes.MOVEMENT_SPEED, 0.25); ++ return Monster.createMonsterAttributes().add(Attributes.MOVEMENT_SPEED, 0.25D); + } + + @Override + public int getMaxFallDistance() { +- return this.getTarget() == null ? 3 : 3 + (int)(this.getHealth() - 1.0F); ++ return this.getTarget() == null ? 3 : 3 + (int) (this.getHealth() - 1.0F); + } + + @Override + public boolean causeFallDamage(float fallDistance, float multiplier, DamageSource source) { + boolean flag = super.causeFallDamage(fallDistance, multiplier, source); +- this.swell += (int)(fallDistance * 1.5F); ++ ++ this.swell += (int) (fallDistance * 1.5F); + if (this.swell > this.maxSwell - 5) { + this.swell = this.maxSwell - 5; + } +@@ -92,27 +102,27 @@ + @Override + protected void defineSynchedData() { + super.defineSynchedData(); +- this.entityData.define(DATA_SWELL_DIR, -1); +- this.entityData.define(DATA_IS_POWERED, false); +- this.entityData.define(DATA_IS_IGNITED, false); ++ this.entityData.define(Creeper.DATA_SWELL_DIR, -1); ++ this.entityData.define(Creeper.DATA_IS_POWERED, false); ++ this.entityData.define(Creeper.DATA_IS_IGNITED, false); + } + + @Override + public void addAdditionalSaveData(CompoundTag compound) { + super.addAdditionalSaveData(compound); +- if (this.entityData.get(DATA_IS_POWERED)) { ++ if ((Boolean) this.entityData.get(Creeper.DATA_IS_POWERED)) { + compound.putBoolean("powered", true); + } + +- compound.putShort("Fuse", (short)this.maxSwell); +- compound.putByte("ExplosionRadius", (byte)this.explosionRadius); ++ compound.putShort("Fuse", (short) this.maxSwell); ++ compound.putByte("ExplosionRadius", (byte) this.explosionRadius); + compound.putBoolean("ignited", this.isIgnited()); + } + + @Override + public void readAdditionalSaveData(CompoundTag compound) { + super.readAdditionalSaveData(compound); +- this.entityData.set(DATA_IS_POWERED, compound.getBoolean("powered")); ++ this.entityData.set(Creeper.DATA_IS_POWERED, compound.getBoolean("powered")); + if (compound.contains("Fuse", 99)) { + this.maxSwell = compound.getShort("Fuse"); + } +@@ -124,6 +134,7 @@ + if (compound.getBoolean("ignited")) { + this.ignite(); + } ++ + } + + @Override +@@ -134,13 +145,14 @@ + this.setSwellDir(1); + } + +- int swellDir = this.getSwellDir(); +- if (swellDir > 0 && this.swell == 0) { ++ int i = this.getSwellDir(); ++ ++ if (i > 0 && this.swell == 0) { + this.playSound(SoundEvents.CREEPER_PRIMED, 1.0F, 0.5F); + this.gameEvent(GameEvent.PRIME_FUSE); + } + +- this.swell += swellDir; ++ this.swell += i; + if (this.swell < 0) { + this.swell = 0; + } +@@ -175,10 +187,16 @@ + protected void dropCustomDeathLoot(DamageSource source, int looting, boolean recentlyHit) { + super.dropCustomDeathLoot(source, looting, recentlyHit); + Entity entity = source.getEntity(); +- if (entity != this && entity instanceof Creeper creeper && creeper.canDropMobsSkull()) { +- creeper.increaseDroppedSkulls(); +- this.spawnAtLocation(Items.CREEPER_HEAD); ++ ++ if (entity != this && entity instanceof Creeper) { ++ Creeper entitycreeper = (Creeper) entity; ++ ++ if (entitycreeper.canDropMobsSkull()) { ++ entitycreeper.increaseDroppedSkulls(); ++ this.spawnAtLocation((IMaterial) Items.CREEPER_HEAD); ++ } + } ++ + } + + @Override +@@ -188,40 +206,54 @@ + + @Override + public boolean isPowered() { +- return this.entityData.get(DATA_IS_POWERED); ++ return (Boolean) this.entityData.get(Creeper.DATA_IS_POWERED); + } + + public float getSwelling(float partialTicks) { +- return Mth.lerp(partialTicks, (float)this.oldSwell, (float)this.swell) / (float)(this.maxSwell - 2); ++ return Mth.lerp(partialTicks, (float) this.oldSwell, (float) this.swell) / (float) (this.maxSwell - 2); + } + + public int getSwellDir() { +- return this.entityData.get(DATA_SWELL_DIR); ++ return (Integer) this.entityData.get(Creeper.DATA_SWELL_DIR); + } + + public void setSwellDir(int state) { +- this.entityData.set(DATA_SWELL_DIR, state); ++ this.entityData.set(Creeper.DATA_SWELL_DIR, state); + } + + @Override + public void thunderHit(ServerLevel level, LightningBolt lightning) { + super.thunderHit(level, lightning); +- this.entityData.set(DATA_IS_POWERED, true); ++ // CraftBukkit start ++ if (CraftEventFactory.callCreeperPowerEvent(this, lightning, org.bukkit.event.entity.CreeperPowerEvent.PowerCause.LIGHTNING).isCancelled()) { ++ return; ++ } ++ // CraftBukkit end ++ this.entityData.set(Creeper.DATA_IS_POWERED, true); + } + ++ // CraftBukkit start ++ public void setPowered(boolean powered) { ++ this.entityData.set(Creeper.DATA_IS_POWERED, powered); ++ } ++ // CraftBukkit end ++ + @Override +- protected InteractionResult mobInteract(Player player, InteractionHand hand) { +- ItemStack itemInHand = player.getItemInHand(hand); +- if (itemInHand.is(ItemTags.CREEPER_IGNITERS)) { +- SoundEvent soundEvent = itemInHand.is(Items.FIRE_CHARGE) ? SoundEvents.FIRECHARGE_USE : SoundEvents.FLINTANDSTEEL_USE; +- this.level() +- .playSound(player, this.getX(), this.getY(), this.getZ(), soundEvent, this.getSoundSource(), 1.0F, this.random.nextFloat() * 0.4F + 0.8F); ++ protected InteractionResult mobInteract(Player player, EnumHand hand) { ++ ItemStack itemstack = player.getItemInHand(hand); ++ ++ if (itemstack.is(ItemTags.CREEPER_IGNITERS)) { ++ SoundEvent soundeffect = itemstack.is(Items.FIRE_CHARGE) ? SoundEvents.FIRECHARGE_USE : SoundEvents.FLINTANDSTEEL_USE; ++ ++ this.level().playSound(player, this.getX(), this.getY(), this.getZ(), soundeffect, this.getSoundSource(), 1.0F, this.random.nextFloat() * 0.4F + 0.8F); + if (!this.level().isClientSide) { + this.ignite(); +- if (!itemInHand.isDamageableItem()) { +- itemInHand.shrink(1); ++ if (itemstack.getItem().getMaxDamage() == 0) { // CraftBukkit - fix MC-264285: unbreakable flint and steels are completely consumed when igniting a creeper ++ itemstack.shrink(1); + } else { +- itemInHand.hurtAndBreak(1, player, entity -> entity.broadcastBreakEvent(hand)); ++ itemstack.hurtAndBreak(1, player, (entityhuman1) -> { ++ entityhuman1.broadcastBreakEvent(hand); ++ }); + } + } + +@@ -231,40 +263,58 @@ + } + } + +- private void explodeCreeper() { ++ public void explodeCreeper() { + if (!this.level().isClientSide) { + float f = this.isPowered() ? 2.0F : 1.0F; ++ ++ // CraftBukkit start ++ ExplosionPrimeEvent event = CraftEventFactory.callExplosionPrimeEvent(this, this.explosionRadius * f, false); ++ if (!event.isCancelled()) { ++ // CraftBukkit end + this.dead = true; +- this.level().explode(this, this.getX(), this.getY(), this.getZ(), (float)this.explosionRadius * f, Level.ExplosionInteraction.MOB); ++ this.level().explode(this, this.getX(), this.getY(), this.getZ(), event.getRadius(), event.getFire(), Level.a.MOB); // CraftBukkit + this.discard(); + this.spawnLingeringCloud(); ++ // CraftBukkit start ++ } else { ++ swell = 0; ++ } ++ // CraftBukkit end + } ++ + } + + private void spawnLingeringCloud() { +- Collection<MobEffectInstance> activeEffects = this.getActiveEffects(); +- if (!activeEffects.isEmpty()) { +- AreaEffectCloud areaEffectCloud = new AreaEffectCloud(this.level(), this.getX(), this.getY(), this.getZ()); +- areaEffectCloud.setRadius(2.5F); +- areaEffectCloud.setRadiusOnUse(-0.5F); +- areaEffectCloud.setWaitTime(10); +- areaEffectCloud.setDuration(areaEffectCloud.getDuration() / 2); +- areaEffectCloud.setRadiusPerTick(-areaEffectCloud.getRadius() / (float)areaEffectCloud.getDuration()); ++ Collection<MobEffectInstance> collection = this.getActiveEffects(); + +- for (MobEffectInstance mobEffectInstance : activeEffects) { +- areaEffectCloud.addEffect(new MobEffectInstance(mobEffectInstance)); ++ if (!collection.isEmpty()) { ++ AreaEffectCloud entityareaeffectcloud = new AreaEffectCloud(this.level(), this.getX(), this.getY(), this.getZ()); ++ ++ entityareaeffectcloud.setOwner(this); // CraftBukkit ++ entityareaeffectcloud.setRadius(2.5F); ++ entityareaeffectcloud.setRadiusOnUse(-0.5F); ++ entityareaeffectcloud.setWaitTime(10); ++ entityareaeffectcloud.setDuration(entityareaeffectcloud.getDuration() / 2); ++ entityareaeffectcloud.setRadiusPerTick(-entityareaeffectcloud.getRadius() / (float) entityareaeffectcloud.getDuration()); ++ Iterator iterator = collection.iterator(); ++ ++ while (iterator.hasNext()) { ++ MobEffectInstance mobeffect = (MobEffectInstance) iterator.next(); ++ ++ entityareaeffectcloud.addEffect(new MobEffectInstance(mobeffect)); + } + +- this.level().addFreshEntity(areaEffectCloud); ++ this.level().addFreshEntity(entityareaeffectcloud, CreatureSpawnEvent.SpawnReason.EXPLOSION); // CraftBukkit + } ++ + } + + public boolean isIgnited() { +- return this.entityData.get(DATA_IS_IGNITED); ++ return (Boolean) this.entityData.get(Creeper.DATA_IS_IGNITED); + } + + public void ignite() { +- this.entityData.set(DATA_IS_IGNITED, true); ++ this.entityData.set(Creeper.DATA_IS_IGNITED, true); + } + + public boolean canDropMobsSkull() { +@@ -272,6 +322,6 @@ + } + + public void increaseDroppedSkulls() { +- this.droppedSkulls++; ++ ++this.droppedSkulls; + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Drowned.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Drowned.java.patch new file mode 100644 index 0000000000..e6905ed1f3 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Drowned.java.patch @@ -0,0 +1,580 @@ +--- a/net/minecraft/world/entity/monster/Drowned.java ++++ b/net/minecraft/world/entity/monster/Drowned.java +@@ -13,15 +13,15 @@ + import net.minecraft.util.RandomSource; + import net.minecraft.world.Difficulty; + import net.minecraft.world.DifficultyInstance; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.EnumMoveType; + import net.minecraft.world.entity.EquipmentSlot; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.LivingEntity; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.MoverType; + import net.minecraft.world.entity.PathfinderMob; +-import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.ai.attributes.Attributes; + import net.minecraft.world.entity.ai.control.MoveControl; + import net.minecraft.world.entity.ai.goal.Goal; +@@ -53,10 +53,11 @@ + import net.minecraft.world.phys.Vec3; + + public class Drowned extends Zombie implements RangedAttackMob { ++ + public static final float NAUTILUS_SHELL_CHANCE = 0.03F; + boolean searchingForLand; +- protected final WaterBoundPathNavigation waterNavigation; +- protected final GroundPathNavigation groundNavigation; ++ public final WaterBoundPathNavigation waterNavigation; ++ public final GroundPathNavigation groundNavigation; + + public Drowned(EntityType<? extends Drowned> entityType, Level level) { + super(entityType, level); +@@ -69,13 +70,13 @@ + + @Override + protected void addBehaviourGoals() { +- this.goalSelector.addGoal(1, new Drowned.DrownedGoToWaterGoal(this, 1.0)); +- this.goalSelector.addGoal(2, new Drowned.DrownedTridentAttackGoal(this, 1.0, 40, 10.0F)); +- this.goalSelector.addGoal(2, new Drowned.DrownedAttackGoal(this, 1.0, false)); +- this.goalSelector.addGoal(5, new Drowned.DrownedGoToBeachGoal(this, 1.0)); +- this.goalSelector.addGoal(6, new Drowned.DrownedSwimUpGoal(this, 1.0, this.level().getSeaLevel())); +- this.goalSelector.addGoal(7, new RandomStrollGoal(this, 1.0)); +- this.targetSelector.addGoal(1, new HurtByTargetGoal(this, Drowned.class).setAlertOthers(ZombifiedPiglin.class)); ++ this.goalSelector.addGoal(1, new Drowned.DrownedGoToWaterGoal(this, 1.0D)); ++ this.goalSelector.addGoal(2, new Drowned.DrownedTridentAttackGoal(this, 1.0D, 40, 10.0F)); ++ this.goalSelector.addGoal(2, new Drowned.DrownedAttackGoal(this, 1.0D, false)); ++ this.goalSelector.addGoal(5, new Drowned.DrownedGoToBeachGoal(this, 1.0D)); ++ this.goalSelector.addGoal(6, new Drowned.DrownedSwimUpGoal(this, 1.0D, this.level().getSeaLevel())); ++ this.goalSelector.addGoal(7, new RandomStrollGoal(this, 1.0D)); ++ this.targetSelector.addGoal(1, (new HurtByTargetGoal(this, new Class[]{Drowned.class})).setAlertOthers(ZombifiedPiglin.class)); + this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, 10, true, false, this::okTarget)); + this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, AbstractVillager.class, false)); + this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, IronGolem.class, true)); +@@ -84,35 +85,24 @@ + } + + @Override +- public SpawnGroupData finalizeSpawn( +- ServerLevelAccessor level, DifficultyInstance difficulty, MobSpawnType reason, @Nullable SpawnGroupData spawnData, @Nullable CompoundTag dataTag +- ) { +- SpawnGroupData var6 = super.finalizeSpawn(level, difficulty, reason, spawnData, dataTag); ++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) { ++ spawnData = super.finalizeSpawn(level, difficulty, reason, spawnData, dataTag); + if (this.getItemBySlot(EquipmentSlot.OFFHAND).isEmpty() && level.getRandom().nextFloat() < 0.03F) { + this.setItemSlot(EquipmentSlot.OFFHAND, new ItemStack(Items.NAUTILUS_SHELL)); + this.setGuaranteedDrop(EquipmentSlot.OFFHAND); + } + +- return var6; ++ return spawnData; + } + +- public static boolean checkDrownedSpawnRules( +- EntityType<Drowned> drowned, ServerLevelAccessor serverLevel, MobSpawnType mobSpawnType, BlockPos pos, RandomSource random +- ) { +- if (!serverLevel.getFluidState(pos.below()).is(FluidTags.WATER) && !MobSpawnType.isSpawner(mobSpawnType)) { ++ public static boolean checkDrownedSpawnRules(EntityType<Drowned> drowned, ServerLevelAccessor serverLevel, EnumMobSpawn mobSpawnType, BlockPos pos, RandomSource random) { ++ if (!serverLevel.getFluidState(pos.below()).is(FluidTags.WATER) && !EnumMobSpawn.isSpawner(mobSpawnType)) { + return false; + } else { +- Holder<Biome> biome = serverLevel.getBiome(pos); +- boolean flag = serverLevel.getDifficulty() != Difficulty.PEACEFUL +- && (MobSpawnType.ignoresLightRequirements(mobSpawnType) || isDarkEnoughToSpawn(serverLevel, pos, random)) +- && (MobSpawnType.isSpawner(mobSpawnType) || serverLevel.getFluidState(pos).is(FluidTags.WATER)); +- if (flag && MobSpawnType.isSpawner(mobSpawnType)) { +- return true; +- } else { +- return biome.is(BiomeTags.MORE_FREQUENT_DROWNED_SPAWNS) +- ? random.nextInt(15) == 0 && flag +- : random.nextInt(40) == 0 && isDeepEnoughToSpawn(serverLevel, pos) && flag; +- } ++ Holder<Biome> holder = serverLevel.getBiome(pos); ++ boolean flag = serverLevel.getDifficulty() != Difficulty.PEACEFUL && (EnumMobSpawn.ignoresLightRequirements(mobSpawnType) || isDarkEnoughToSpawn(serverLevel, pos, random)) && (EnumMobSpawn.isSpawner(mobSpawnType) || serverLevel.getFluidState(pos).is(FluidTags.WATER)); ++ ++ return flag && EnumMobSpawn.isSpawner(mobSpawnType) ? true : (holder.is(BiomeTags.MORE_FREQUENT_DROWNED_SPAWNS) ? random.nextInt(15) == 0 && flag : random.nextInt(40) == 0 && isDeepEnoughToSpawn(serverLevel, pos) && flag); + } + } + +@@ -157,25 +147,21 @@ + + @Override + protected void populateDefaultEquipmentSlots(RandomSource random, DifficultyInstance difficulty) { +- if ((double)random.nextFloat() > 0.9) { +- int randomInt = random.nextInt(16); +- if (randomInt < 10) { ++ if ((double) random.nextFloat() > 0.9D) { ++ int i = random.nextInt(16); ++ ++ if (i < 10) { + this.setItemSlot(EquipmentSlot.MAINHAND, new ItemStack(Items.TRIDENT)); + } else { + this.setItemSlot(EquipmentSlot.MAINHAND, new ItemStack(Items.FISHING_ROD)); + } + } ++ + } + + @Override + protected boolean canReplaceCurrentItem(ItemStack candidate, ItemStack existing) { +- if (existing.is(Items.NAUTILUS_SHELL)) { +- return false; +- } else { +- return existing.is(Items.TRIDENT) +- ? candidate.is(Items.TRIDENT) && candidate.getDamageValue() < existing.getDamageValue() +- : candidate.is(Items.TRIDENT) || super.canReplaceCurrentItem(candidate, existing); +- } ++ return existing.is(Items.NAUTILUS_SHELL) ? false : (existing.is(Items.TRIDENT) ? (candidate.is(Items.TRIDENT) ? candidate.getDamageValue() < existing.getDamageValue() : false) : (candidate.is(Items.TRIDENT) ? true : super.canReplaceCurrentItem(candidate, existing))); + } + + @Override +@@ -189,7 +175,7 @@ + } + + public boolean okTarget(@Nullable LivingEntity target) { +- return target != null && (!this.level().isDay() || target.isInWater()); ++ return target != null ? !this.level().isDay() || target.isInWater() : false; + } + + @Override +@@ -201,8 +187,9 @@ + if (this.searchingForLand) { + return true; + } else { +- LivingEntity target = this.getTarget(); +- return target != null && target.isInWater(); ++ LivingEntity entityliving = this.getTarget(); ++ ++ return entityliving != null && entityliving.isInWater(); + } + } + +@@ -210,11 +197,12 @@ + public void travel(Vec3 travelVector) { + if (this.isControlledByLocalInstance() && this.isInWater() && this.wantsToSwim()) { + this.moveRelative(0.01F, travelVector); +- this.move(MoverType.SELF, this.getDeltaMovement()); +- this.setDeltaMovement(this.getDeltaMovement().scale(0.9)); ++ this.move(EnumMoveType.SELF, this.getDeltaMovement()); ++ this.setDeltaMovement(this.getDeltaMovement().scale(0.9D)); + } else { + super.travel(travelVector); + } ++ + } + + @Override +@@ -228,6 +216,7 @@ + this.setSwimming(false); + } + } ++ + } + + @Override +@@ -236,12 +225,15 @@ + } + + protected boolean closeToNextPos() { +- Path path = this.getNavigation().getPath(); +- if (path != null) { +- BlockPos target = path.getTarget(); +- if (target != null) { +- double d = this.distanceToSqr((double)target.getX(), (double)target.getY(), (double)target.getZ()); +- if (d < 4.0) { ++ Path pathentity = this.getNavigation().getPath(); ++ ++ if (pathentity != null) { ++ BlockPos blockposition = pathentity.getTarget(); ++ ++ if (blockposition != null) { ++ double d0 = this.distanceToSqr((double) blockposition.getX(), (double) blockposition.getY(), (double) blockposition.getZ()); ++ ++ if (d0 < 4.0D) { + return true; + } + } +@@ -252,80 +244,72 @@ + + @Override + public void performRangedAttack(LivingEntity target, float distanceFactor) { +- ThrownTrident thrownTrident = new ThrownTrident(this.level(), this, new ItemStack(Items.TRIDENT)); +- double d = target.getX() - this.getX(); +- double d1 = target.getY(0.3333333333333333) - thrownTrident.getY(); ++ ThrownTrident entitythrowntrident = new ThrownTrident(this.level(), this, this.getItemInHand(net.minecraft.world.entity.projectile.ProjectileUtil.getWeaponHoldingHand(this, Items.TRIDENT))); // CraftBukkit - Use Trident in hand like skeletons (SPIGOT-7025) ++ double d0 = target.getX() - this.getX(); ++ double d1 = target.getY(0.3333333333333333D) - entitythrowntrident.getY(); + double d2 = target.getZ() - this.getZ(); +- double squareRoot = Math.sqrt(d * d + d2 * d2); +- thrownTrident.shoot(d, d1 + squareRoot * 0.2F, d2, 1.6F, (float)(14 - this.level().getDifficulty().getId() * 4)); ++ double d3 = Math.sqrt(d0 * d0 + d2 * d2); ++ ++ entitythrowntrident.shoot(d0, d1 + d3 * 0.20000000298023224D, d2, 1.6F, (float) (14 - this.level().getDifficulty().getId() * 4)); + this.playSound(SoundEvents.DROWNED_SHOOT, 1.0F, 1.0F / (this.getRandom().nextFloat() * 0.4F + 0.8F)); +- this.level().addFreshEntity(thrownTrident); ++ this.level().addFreshEntity(entitythrowntrident); + } + + public void setSearchingForLand(boolean searchingForLand) { + this.searchingForLand = searchingForLand; + } + +- static class DrownedAttackGoal extends ZombieAttackGoal { ++ private static class DrownedMoveControl extends MoveControl { ++ + private final Drowned drowned; + +- public DrownedAttackGoal(Drowned drowned, double speedModifier, boolean followingTargetEvenIfNotSeen) { +- super(drowned, speedModifier, followingTargetEvenIfNotSeen); ++ public DrownedMoveControl(Drowned drowned) { ++ super(drowned); + this.drowned = drowned; + } + + @Override +- public boolean canUse() { +- return super.canUse() && this.drowned.okTarget(this.drowned.getTarget()); +- } ++ public void tick() { ++ LivingEntity entityliving = this.drowned.getTarget(); + +- @Override +- public boolean canContinueToUse() { +- return super.canContinueToUse() && this.drowned.okTarget(this.drowned.getTarget()); +- } +- } ++ if (this.drowned.wantsToSwim() && this.drowned.isInWater()) { ++ if (entityliving != null && entityliving.getY() > this.drowned.getY() || this.drowned.searchingForLand) { ++ this.drowned.setDeltaMovement(this.drowned.getDeltaMovement().add(0.0D, 0.002D, 0.0D)); ++ } + +- static class DrownedGoToBeachGoal extends MoveToBlockGoal { +- private final Drowned drowned; ++ if (this.operation != MoveControl.Operation.MOVE_TO || this.drowned.getNavigation().isDone()) { ++ this.drowned.setSpeed(0.0F); ++ return; ++ } + +- public DrownedGoToBeachGoal(Drowned drowned, double speedModifier) { +- super(drowned, speedModifier, 8, 2); +- this.drowned = drowned; +- } ++ double d0 = this.wantedX - this.drowned.getX(); ++ double d1 = this.wantedY - this.drowned.getY(); ++ double d2 = this.wantedZ - this.drowned.getZ(); ++ double d3 = Math.sqrt(d0 * d0 + d1 * d1 + d2 * d2); + +- @Override +- public boolean canUse() { +- return super.canUse() +- && !this.drowned.level().isDay() +- && this.drowned.isInWater() +- && this.drowned.getY() >= (double)(this.drowned.level().getSeaLevel() - 3); +- } ++ d1 /= d3; ++ float f = (float) (Mth.atan2(d2, d0) * 57.2957763671875D) - 90.0F; + +- @Override +- public boolean canContinueToUse() { +- return super.canContinueToUse(); +- } ++ this.drowned.setYRot(this.rotlerp(this.drowned.getYRot(), f, 90.0F)); ++ this.drowned.yBodyRot = this.drowned.getYRot(); ++ float f1 = (float) (this.speedModifier * this.drowned.getAttributeValue(Attributes.MOVEMENT_SPEED)); ++ float f2 = Mth.lerp(0.125F, this.drowned.getSpeed(), f1); + +- @Override +- protected boolean isValidTarget(LevelReader level, BlockPos pos) { +- BlockPos blockPos = pos.above(); +- return level.isEmptyBlock(blockPos) && level.isEmptyBlock(blockPos.above()) && level.getBlockState(pos).entityCanStandOn(level, pos, this.drowned); +- } ++ this.drowned.setSpeed(f2); ++ this.drowned.setDeltaMovement(this.drowned.getDeltaMovement().add((double) f2 * d0 * 0.005D, (double) f2 * d1 * 0.1D, (double) f2 * d2 * 0.005D)); ++ } else { ++ if (!this.drowned.onGround()) { ++ this.drowned.setDeltaMovement(this.drowned.getDeltaMovement().add(0.0D, -0.008D, 0.0D)); ++ } + +- @Override +- public void start() { +- this.drowned.setSearchingForLand(false); +- this.drowned.navigation = this.drowned.groundNavigation; +- super.start(); +- } ++ super.tick(); ++ } + +- @Override +- public void stop() { +- super.stop(); + } + } + +- static class DrownedGoToWaterGoal extends Goal { ++ private static class DrownedGoToWaterGoal extends Goal { ++ + private final PathfinderMob mob; + private double wantedX; + private double wantedY; +@@ -337,7 +321,7 @@ + this.mob = mob; + this.speedModifier = speedModifier; + this.level = mob.level(); +- this.setFlags(EnumSet.of(Goal.Flag.MOVE)); ++ this.setFlags(EnumSet.of(Goal.Type.MOVE)); + } + + @Override +@@ -347,13 +331,14 @@ + } else if (this.mob.isInWater()) { + return false; + } else { +- Vec3 waterPos = this.getWaterPos(); +- if (waterPos == null) { ++ Vec3 vec3d = this.getWaterPos(); ++ ++ if (vec3d == null) { + return false; + } else { +- this.wantedX = waterPos.x; +- this.wantedY = waterPos.y; +- this.wantedZ = waterPos.z; ++ this.wantedX = vec3d.x; ++ this.wantedY = vec3d.y; ++ this.wantedZ = vec3d.z; + return true; + } + } +@@ -371,13 +356,14 @@ + + @Nullable + private Vec3 getWaterPos() { +- RandomSource random = this.mob.getRandom(); +- BlockPos blockPos = this.mob.blockPosition(); ++ RandomSource randomsource = this.mob.getRandom(); ++ BlockPos blockposition = this.mob.blockPosition(); + +- for (int i = 0; i < 10; i++) { +- BlockPos blockPos1 = blockPos.offset(random.nextInt(20) - 10, 2 - random.nextInt(8), random.nextInt(20) - 10); +- if (this.level.getBlockState(blockPos1).is(Blocks.WATER)) { +- return Vec3.atBottomCenterOf(blockPos1); ++ for (int i = 0; i < 10; ++i) { ++ BlockPos blockposition1 = blockposition.offset(randomsource.nextInt(20) - 10, 2 - randomsource.nextInt(8), randomsource.nextInt(20) - 10); ++ ++ if (this.level.getBlockState(blockposition1).is(Blocks.WATER)) { ++ return Vec3.atBottomCenterOf(blockposition1); + } + } + +@@ -385,123 +371,141 @@ + } + } + +- static class DrownedMoveControl extends MoveControl { ++ private static class DrownedTridentAttackGoal extends RangedAttackGoal { ++ + private final Drowned drowned; + +- public DrownedMoveControl(Drowned mob) { +- super(mob); +- this.drowned = mob; ++ public DrownedTridentAttackGoal(RangedAttackMob rangedAttackMob, double speedModifier, int i, float attackInterval) { ++ super(rangedAttackMob, speedModifier, i, attackInterval); ++ this.drowned = (Drowned) rangedAttackMob; + } + + @Override +- public void tick() { +- LivingEntity target = this.drowned.getTarget(); +- if (this.drowned.wantsToSwim() && this.drowned.isInWater()) { +- if (target != null && target.getY() > this.drowned.getY() || this.drowned.searchingForLand) { +- this.drowned.setDeltaMovement(this.drowned.getDeltaMovement().add(0.0, 0.002, 0.0)); +- } ++ public boolean canUse() { ++ return super.canUse() && this.drowned.getMainHandItem().is(Items.TRIDENT); ++ } + +- if (this.operation != MoveControl.Operation.MOVE_TO || this.drowned.getNavigation().isDone()) { +- this.drowned.setSpeed(0.0F); +- return; +- } ++ @Override ++ public void start() { ++ super.start(); ++ this.drowned.setAggressive(true); ++ this.drowned.startUsingItem(EnumHand.MAIN_HAND); ++ } + +- double d = this.wantedX - this.drowned.getX(); +- double d1 = this.wantedY - this.drowned.getY(); +- double d2 = this.wantedZ - this.drowned.getZ(); +- double squareRoot = Math.sqrt(d * d + d1 * d1 + d2 * d2); +- d1 /= squareRoot; +- float f = (float)(Mth.atan2(d2, d) * 180.0F / (float)Math.PI) - 90.0F; +- this.drowned.setYRot(this.rotlerp(this.drowned.getYRot(), f, 90.0F)); +- this.drowned.yBodyRot = this.drowned.getYRot(); +- float f1 = (float)(this.speedModifier * this.drowned.getAttributeValue(Attributes.MOVEMENT_SPEED)); +- float f2 = Mth.lerp(0.125F, this.drowned.getSpeed(), f1); +- this.drowned.setSpeed(f2); +- this.drowned.setDeltaMovement(this.drowned.getDeltaMovement().add((double)f2 * d * 0.005, (double)f2 * d1 * 0.1, (double)f2 * d2 * 0.005)); +- } else { +- if (!this.drowned.onGround()) { +- this.drowned.setDeltaMovement(this.drowned.getDeltaMovement().add(0.0, -0.008, 0.0)); +- } ++ @Override ++ public void stop() { ++ super.stop(); ++ this.drowned.stopUsingItem(); ++ this.drowned.setAggressive(false); ++ } ++ } + +- super.tick(); +- } ++ private static class DrownedAttackGoal extends ZombieAttackGoal { ++ ++ private final Drowned drowned; ++ ++ public DrownedAttackGoal(Drowned drowned, double speedModifier, boolean flag) { ++ super((Zombie) drowned, speedModifier, flag); ++ this.drowned = drowned; + } ++ ++ @Override ++ public boolean canUse() { ++ return super.canUse() && this.drowned.okTarget(this.drowned.getTarget()); ++ } ++ ++ @Override ++ public boolean canContinueToUse() { ++ return super.canContinueToUse() && this.drowned.okTarget(this.drowned.getTarget()); ++ } + } + +- static class DrownedSwimUpGoal extends Goal { ++ private static class DrownedGoToBeachGoal extends MoveToBlockGoal { ++ + private final Drowned drowned; +- private final double speedModifier; +- private final int seaLevel; +- private boolean stuck; + +- public DrownedSwimUpGoal(Drowned drowned, double speedModifier, int seaLevel) { ++ public DrownedGoToBeachGoal(Drowned drowned, double speedModifier) { ++ super(drowned, speedModifier, 8, 2); + this.drowned = drowned; +- this.speedModifier = speedModifier; +- this.seaLevel = seaLevel; + } + + @Override + public boolean canUse() { +- return !this.drowned.level().isDay() && this.drowned.isInWater() && this.drowned.getY() < (double)(this.seaLevel - 2); ++ return super.canUse() && !this.drowned.level().isDay() && this.drowned.isInWater() && this.drowned.getY() >= (double) (this.drowned.level().getSeaLevel() - 3); + } + + @Override + public boolean canContinueToUse() { +- return this.canUse() && !this.stuck; ++ return super.canContinueToUse(); + } + + @Override +- public void tick() { +- if (this.drowned.getY() < (double)(this.seaLevel - 1) && (this.drowned.getNavigation().isDone() || this.drowned.closeToNextPos())) { +- Vec3 posTowards = DefaultRandomPos.getPosTowards( +- this.drowned, 4, 8, new Vec3(this.drowned.getX(), (double)(this.seaLevel - 1), this.drowned.getZ()), (float) (Math.PI / 2) +- ); +- if (posTowards == null) { +- this.stuck = true; +- return; +- } ++ protected boolean isValidTarget(LevelReader level, BlockPos pos) { ++ BlockPos blockposition1 = pos.above(); + +- this.drowned.getNavigation().moveTo(posTowards.x, posTowards.y, posTowards.z, this.speedModifier); +- } ++ return level.isEmptyBlock(blockposition1) && level.isEmptyBlock(blockposition1.above()) ? level.getBlockState(pos).entityCanStandOn(level, pos, this.drowned) : false; + } + + @Override + public void start() { +- this.drowned.setSearchingForLand(true); +- this.stuck = false; ++ this.drowned.setSearchingForLand(false); ++ this.drowned.navigation = this.drowned.groundNavigation; ++ super.start(); + } + + @Override + public void stop() { +- this.drowned.setSearchingForLand(false); ++ super.stop(); + } + } + +- static class DrownedTridentAttackGoal extends RangedAttackGoal { ++ private static class DrownedSwimUpGoal extends Goal { ++ + private final Drowned drowned; ++ private final double speedModifier; ++ private final int seaLevel; ++ private boolean stuck; + +- public DrownedTridentAttackGoal(RangedAttackMob rangedAttackMob, double speedModifier, int attackInterval, float attackRadius) { +- super(rangedAttackMob, speedModifier, attackInterval, attackRadius); +- this.drowned = (Drowned)rangedAttackMob; ++ public DrownedSwimUpGoal(Drowned drowned, double speedModifier, int i) { ++ this.drowned = drowned; ++ this.speedModifier = speedModifier; ++ this.seaLevel = i; + } + + @Override + public boolean canUse() { +- return super.canUse() && this.drowned.getMainHandItem().is(Items.TRIDENT); ++ return !this.drowned.level().isDay() && this.drowned.isInWater() && this.drowned.getY() < (double) (this.seaLevel - 2); + } + + @Override ++ public boolean canContinueToUse() { ++ return this.canUse() && !this.stuck; ++ } ++ ++ @Override ++ public void tick() { ++ if (this.drowned.getY() < (double) (this.seaLevel - 1) && (this.drowned.getNavigation().isDone() || this.drowned.closeToNextPos())) { ++ Vec3 vec3d = DefaultRandomPos.getPosTowards(this.drowned, 4, 8, new Vec3(this.drowned.getX(), (double) (this.seaLevel - 1), this.drowned.getZ()), 1.5707963705062866D); ++ ++ if (vec3d == null) { ++ this.stuck = true; ++ return; ++ } ++ ++ this.drowned.getNavigation().moveTo(vec3d.x, vec3d.y, vec3d.z, this.speedModifier); ++ } ++ ++ } ++ ++ @Override + public void start() { +- super.start(); +- this.drowned.setAggressive(true); +- this.drowned.startUsingItem(InteractionHand.MAIN_HAND); ++ this.drowned.setSearchingForLand(true); ++ this.stuck = false; + } + + @Override + public void stop() { +- super.stop(); +- this.drowned.stopUsingItem(); +- this.drowned.setAggressive(false); ++ this.drowned.setSearchingForLand(false); + } + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/ElderGuardian.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/ElderGuardian.java.patch new file mode 100644 index 0000000000..52bedd93b6 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/ElderGuardian.java.patch @@ -0,0 +1,54 @@ +--- a/net/minecraft/world/entity/monster/ElderGuardian.java ++++ b/net/minecraft/world/entity/monster/ElderGuardian.java +@@ -19,6 +19,7 @@ + import org.joml.Vector3f; + + public class ElderGuardian extends Guardian { ++ + public static final float ELDER_SIZE_SCALE = EntityType.ELDER_GUARDIAN.getWidth() / EntityType.GUARDIAN.getWidth(); + private static final int EFFECT_INTERVAL = 1200; + private static final int EFFECT_RADIUS = 50; +@@ -32,10 +33,11 @@ + if (this.randomStrollGoal != null) { + this.randomStrollGoal.setInterval(400); + } ++ + } + + public static AttributeSupplier.Builder createAttributes() { +- return Guardian.createAttributes().add(Attributes.MOVEMENT_SPEED, 0.3F).add(Attributes.ATTACK_DAMAGE, 8.0).add(Attributes.MAX_HEALTH, 80.0); ++ return Guardian.createAttributes().add(Attributes.MOVEMENT_SPEED, 0.30000001192092896D).add(Attributes.ATTACK_DAMAGE, 8.0D).add(Attributes.MAX_HEALTH, 80.0D); + } + + @Override +@@ -67,21 +69,22 @@ + protected void customServerAiStep() { + super.customServerAiStep(); + if ((this.tickCount + this.getId()) % 1200 == 0) { +- MobEffectInstance mobEffectInstance = new MobEffectInstance(MobEffects.DIG_SLOWDOWN, 6000, 2); +- List<ServerPlayer> list = MobEffectUtil.addEffectToPlayersAround((ServerLevel)this.level(), this, this.position(), 50.0, mobEffectInstance, 1200); +- list.forEach( +- serverPlayer -> serverPlayer.connection +- .send(new ClientboundGameEventPacket(ClientboundGameEventPacket.GUARDIAN_ELDER_EFFECT, this.isSilent() ? 0.0F : 1.0F)) +- ); ++ MobEffectInstance mobeffect = new MobEffectInstance(MobEffects.DIG_SLOWDOWN, 6000, 2); ++ List<ServerPlayer> list = MobEffectUtil.addEffectToPlayersAround((ServerLevel) this.level(), this, this.position(), 50.0D, mobeffect, 1200, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit ++ ++ list.forEach((entityplayer) -> { ++ entityplayer.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.GUARDIAN_ELDER_EFFECT, this.isSilent() ? 0.0F : 1.0F)); ++ }); + } + + if (!this.hasRestriction()) { + this.restrictTo(this.blockPosition(), 16); + } ++ + } + + @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entityDimensions, float f) { +- return new Vector3f(0.0F, entityDimensions.height + 0.353125F * f, 0.0F); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ return new Vector3f(0.0F, entitysize.height + 0.353125F * f, 0.0F); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/EnderMan.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/EnderMan.java.patch new file mode 100644 index 0000000000..56412da320 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/EnderMan.java.patch @@ -0,0 +1,692 @@ +--- a/net/minecraft/world/entity/monster/EnderMan.java ++++ b/net/minecraft/world/entity/monster/EnderMan.java +@@ -1,6 +1,7 @@ + package net.minecraft.world.entity.monster; + + import java.util.EnumSet; ++import java.util.Iterator; + import java.util.List; + import java.util.Optional; + import java.util.UUID; +@@ -29,10 +30,10 @@ + import net.minecraft.world.effect.MobEffectInstance; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.NeutralMob; +-import net.minecraft.world.entity.Pose; + import net.minecraft.world.entity.ai.attributes.AttributeInstance; + import net.minecraft.world.entity.ai.attributes.AttributeModifier; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; +@@ -60,7 +61,7 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.Blocks; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.level.pathfinder.BlockPathTypes; + import net.minecraft.world.level.storage.loot.LootParams; +@@ -70,16 +71,18 @@ + import net.minecraft.world.phys.Vec3; + import org.joml.Vector3f; + ++// CraftBukkit start; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityTargetEvent; ++// CraftBukkit end ++ + public class EnderMan extends Monster implements NeutralMob { ++ + private static final UUID SPEED_MODIFIER_ATTACKING_UUID = UUID.fromString("020E0DFB-87AE-4653-9556-831010E291A0"); +- private static final AttributeModifier SPEED_MODIFIER_ATTACKING = new AttributeModifier( +- SPEED_MODIFIER_ATTACKING_UUID, "Attacking speed boost", 0.15F, AttributeModifier.Operation.ADDITION +- ); ++ private static final AttributeModifier SPEED_MODIFIER_ATTACKING = new AttributeModifier(EnderMan.SPEED_MODIFIER_ATTACKING_UUID, "Attacking speed boost", 0.15000000596046448D, AttributeModifier.Operation.ADDITION); + private static final int DELAY_BETWEEN_CREEPY_STARE_SOUND = 400; + private static final int MIN_DEAGGRESSION_TIME = 600; +- private static final EntityDataAccessor<Optional<BlockState>> DATA_CARRY_STATE = SynchedEntityData.defineId( +- EnderMan.class, EntityDataSerializers.OPTIONAL_BLOCK_STATE +- ); ++ private static final EntityDataAccessor<Optional<IBlockData>> DATA_CARRY_STATE = SynchedEntityData.defineId(EnderMan.class, EntityDataSerializers.OPTIONAL_BLOCK_STATE); + private static final EntityDataAccessor<Boolean> DATA_CREEPY = SynchedEntityData.defineId(EnderMan.class, EntityDataSerializers.BOOLEAN); + private static final EntityDataAccessor<Boolean> DATA_STARED_AT = SynchedEntityData.defineId(EnderMan.class, EntityDataSerializers.BOOLEAN); + private int lastStareSound = Integer.MIN_VALUE; +@@ -99,55 +102,64 @@ + protected void registerGoals() { + this.goalSelector.addGoal(0, new FloatGoal(this)); + this.goalSelector.addGoal(1, new EnderMan.EndermanFreezeWhenLookedAt(this)); +- this.goalSelector.addGoal(2, new MeleeAttackGoal(this, 1.0, false)); +- this.goalSelector.addGoal(7, new WaterAvoidingRandomStrollGoal(this, 1.0, 0.0F)); ++ this.goalSelector.addGoal(2, new MeleeAttackGoal(this, 1.0D, false)); ++ this.goalSelector.addGoal(7, new WaterAvoidingRandomStrollGoal(this, 1.0D, 0.0F)); + this.goalSelector.addGoal(8, new LookAtPlayerGoal(this, Player.class, 8.0F)); + this.goalSelector.addGoal(8, new RandomLookAroundGoal(this)); + this.goalSelector.addGoal(10, new EnderMan.EndermanLeaveBlockGoal(this)); + this.goalSelector.addGoal(11, new EnderMan.EndermanTakeBlockGoal(this)); + this.targetSelector.addGoal(1, new EnderMan.EndermanLookForPlayerGoal(this, this::isAngryAt)); +- this.targetSelector.addGoal(2, new HurtByTargetGoal(this)); ++ this.targetSelector.addGoal(2, new HurtByTargetGoal(this, new Class[0])); + this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, Endermite.class, true, false)); + this.targetSelector.addGoal(4, new ResetUniversalAngerTargetGoal<>(this, false)); + } + + public static AttributeSupplier.Builder createAttributes() { +- return Monster.createMonsterAttributes() +- .add(Attributes.MAX_HEALTH, 40.0) +- .add(Attributes.MOVEMENT_SPEED, 0.3F) +- .add(Attributes.ATTACK_DAMAGE, 7.0) +- .add(Attributes.FOLLOW_RANGE, 64.0); ++ return Monster.createMonsterAttributes().add(Attributes.MAX_HEALTH, 40.0D).add(Attributes.MOVEMENT_SPEED, 0.30000001192092896D).add(Attributes.ATTACK_DAMAGE, 7.0D).add(Attributes.FOLLOW_RANGE, 64.0D); + } + + @Override + public void setTarget(@Nullable LivingEntity livingEntity) { +- super.setTarget(livingEntity); +- AttributeInstance attribute = this.getAttribute(Attributes.MOVEMENT_SPEED); +- if (livingEntity == null) { ++ // CraftBukkit start - fire event ++ setTarget(livingEntity, EntityTargetEvent.TargetReason.UNKNOWN, true); ++ } ++ ++ @Override ++ public boolean setTarget(LivingEntity entityliving, EntityTargetEvent.TargetReason reason, boolean fireEvent) { ++ if (!super.setTarget(entityliving, reason, fireEvent)) { ++ return false; ++ } ++ entityliving = getTarget(); ++ // CraftBukkit end ++ AttributeInstance attributemodifiable = this.getAttribute(Attributes.MOVEMENT_SPEED); ++ ++ if (entityliving == null) { + this.targetChangeTime = 0; +- this.entityData.set(DATA_CREEPY, false); +- this.entityData.set(DATA_STARED_AT, false); +- attribute.removeModifier(SPEED_MODIFIER_ATTACKING.getId()); ++ this.entityData.set(EnderMan.DATA_CREEPY, false); ++ this.entityData.set(EnderMan.DATA_STARED_AT, false); ++ attributemodifiable.removeModifier(EnderMan.SPEED_MODIFIER_ATTACKING.getId()); + } else { + this.targetChangeTime = this.tickCount; +- this.entityData.set(DATA_CREEPY, true); +- if (!attribute.hasModifier(SPEED_MODIFIER_ATTACKING)) { +- attribute.addTransientModifier(SPEED_MODIFIER_ATTACKING); ++ this.entityData.set(EnderMan.DATA_CREEPY, true); ++ if (!attributemodifiable.hasModifier(EnderMan.SPEED_MODIFIER_ATTACKING)) { ++ attributemodifiable.addTransientModifier(EnderMan.SPEED_MODIFIER_ATTACKING); + } + } ++ return true; ++ + } + + @Override + protected void defineSynchedData() { + super.defineSynchedData(); +- this.entityData.define(DATA_CARRY_STATE, Optional.empty()); +- this.entityData.define(DATA_CREEPY, false); +- this.entityData.define(DATA_STARED_AT, false); ++ this.entityData.define(EnderMan.DATA_CARRY_STATE, Optional.empty()); ++ this.entityData.define(EnderMan.DATA_CREEPY, false); ++ this.entityData.define(EnderMan.DATA_STARED_AT, false); + } + + @Override + public void startPersistentAngerTimer() { +- this.setRemainingPersistentAngerTime(PERSISTENT_ANGER_TIME.sample(this.random)); ++ this.setRemainingPersistentAngerTime(EnderMan.PERSISTENT_ANGER_TIME.sample(this.random)); + } + + @Override +@@ -178,11 +190,12 @@ + this.level().playLocalSound(this.getX(), this.getEyeY(), this.getZ(), SoundEvents.ENDERMAN_STARE, this.getSoundSource(), 2.5F, 1.0F, false); + } + } ++ + } + + @Override + public void onSyncedDataUpdated(EntityDataAccessor<?> key) { +- if (DATA_CREEPY.equals(key) && this.hasBeenStaredAt() && this.level().isClientSide) { ++ if (EnderMan.DATA_CREEPY.equals(key) && this.hasBeenStaredAt() && this.level().isClientSide) { + this.playStareSound(); + } + +@@ -192,9 +205,10 @@ + @Override + public void addAdditionalSaveData(CompoundTag compound) { + super.addAdditionalSaveData(compound); +- BlockState carriedBlock = this.getCarriedBlock(); +- if (carriedBlock != null) { +- compound.put("carriedBlockState", NbtUtils.writeBlockState(carriedBlock)); ++ IBlockData iblockdata = this.getCarriedBlock(); ++ ++ if (iblockdata != null) { ++ compound.put("carriedBlockState", NbtUtils.writeBlockState(iblockdata)); + } + + this.addPersistentAngerSaveData(compound); +@@ -203,62 +217,57 @@ + @Override + public void readAdditionalSaveData(CompoundTag compound) { + super.readAdditionalSaveData(compound); +- BlockState blockState = null; ++ IBlockData iblockdata = null; ++ + if (compound.contains("carriedBlockState", 10)) { +- blockState = NbtUtils.readBlockState(this.level().holderLookup(Registries.BLOCK), compound.getCompound("carriedBlockState")); +- if (blockState.isAir()) { +- blockState = null; ++ iblockdata = NbtUtils.readBlockState(this.level().holderLookup(Registries.BLOCK), compound.getCompound("carriedBlockState")); ++ if (iblockdata.isAir()) { ++ iblockdata = null; + } + } + +- this.setCarriedBlock(blockState); ++ this.setCarriedBlock(iblockdata); + this.readPersistentAngerSaveData(this.level(), compound); + } + + boolean isLookingAtMe(Player player) { +- ItemStack itemStack = player.getInventory().armor.get(3); +- if (itemStack.is(Blocks.CARVED_PUMPKIN.asItem())) { ++ ItemStack itemstack = (ItemStack) player.getInventory().armor.get(3); ++ ++ if (itemstack.is(Blocks.CARVED_PUMPKIN.asItem())) { + return false; + } else { +- Vec3 vec3 = player.getViewVector(1.0F).normalize(); +- Vec3 vec31 = new Vec3(this.getX() - player.getX(), this.getEyeY() - player.getEyeY(), this.getZ() - player.getZ()); +- double len = vec31.length(); +- vec31 = vec31.normalize(); +- double d = vec3.dot(vec31); +- return d > 1.0 - 0.025 / len && player.hasLineOfSight(this); ++ Vec3 vec3d = player.getViewVector(1.0F).normalize(); ++ Vec3 vec3d1 = new Vec3(this.getX() - player.getX(), this.getEyeY() - player.getEyeY(), this.getZ() - player.getZ()); ++ double d0 = vec3d1.length(); ++ ++ vec3d1 = vec3d1.normalize(); ++ double d1 = vec3d.dot(vec3d1); ++ ++ return d1 > 1.0D - 0.025D / d0 ? player.hasLineOfSight(this) : false; + } + } + + @Override +- protected float getStandingEyeHeight(Pose pose, EntityDimensions size) { ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions size) { + return 2.55F; + } + + @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entityDimensions, float f) { +- return new Vector3f(0.0F, entityDimensions.height - 0.09375F * f, 0.0F); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ return new Vector3f(0.0F, entitysize.height - 0.09375F * f, 0.0F); + } + + @Override + public void aiStep() { + if (this.level().isClientSide) { +- for (int i = 0; i < 2; i++) { +- this.level() +- .addParticle( +- ParticleTypes.PORTAL, +- this.getRandomX(0.5), +- this.getRandomY() - 0.25, +- this.getRandomZ(0.5), +- (this.random.nextDouble() - 0.5) * 2.0, +- -this.random.nextDouble(), +- (this.random.nextDouble() - 0.5) * 2.0 +- ); ++ for (int i = 0; i < 2; ++i) { ++ this.level().addParticle(ParticleTypes.PORTAL, this.getRandomX(0.5D), this.getRandomY() - 0.25D, this.getRandomZ(0.5D), (this.random.nextDouble() - 0.5D) * 2.0D, -this.random.nextDouble(), (this.random.nextDouble() - 0.5D) * 2.0D); + } + } + + this.jumping = false; + if (!this.level().isClientSide) { +- this.updatePersistentAnger((ServerLevel)this.level(), true); ++ this.updatePersistentAnger((ServerLevel) this.level(), true); + } + + super.aiStep(); +@@ -272,11 +281,10 @@ + @Override + protected void customServerAiStep() { + if (this.level().isDay() && this.tickCount >= this.targetChangeTime + 600) { +- float lightLevelDependentMagicValue = this.getLightLevelDependentMagicValue(); +- if (lightLevelDependentMagicValue > 0.5F +- && this.level().canSeeSky(this.blockPosition()) +- && this.random.nextFloat() * 30.0F < (lightLevelDependentMagicValue - 0.4F) * 2.0F) { +- this.setTarget(null); ++ float f = this.getLightLevelDependentMagicValue(); ++ ++ if (f > 0.5F && this.level().canSeeSky(this.blockPosition()) && this.random.nextFloat() * 30.0F < (f - 0.4F) * 2.0F) { ++ this.setTarget((LivingEntity) null); + this.teleport(); + } + } +@@ -284,49 +292,54 @@ + super.customServerAiStep(); + } + +- protected boolean teleport() { ++ public boolean teleport() { + if (!this.level().isClientSide() && this.isAlive()) { +- double d = this.getX() + (this.random.nextDouble() - 0.5) * 64.0; +- double d1 = this.getY() + (double)(this.random.nextInt(64) - 32); +- double d2 = this.getZ() + (this.random.nextDouble() - 0.5) * 64.0; +- return this.teleport(d, d1, d2); ++ double d0 = this.getX() + (this.random.nextDouble() - 0.5D) * 64.0D; ++ double d1 = this.getY() + (double) (this.random.nextInt(64) - 32); ++ double d2 = this.getZ() + (this.random.nextDouble() - 0.5D) * 64.0D; ++ ++ return this.teleport(d0, d1, d2); + } else { + return false; + } + } + +- boolean teleportTowards(Entity target) { +- Vec3 vec3 = new Vec3(this.getX() - target.getX(), this.getY(0.5) - target.getEyeY(), this.getZ() - target.getZ()); +- vec3 = vec3.normalize(); +- double d = 16.0; +- double d1 = this.getX() + (this.random.nextDouble() - 0.5) * 8.0 - vec3.x * 16.0; +- double d2 = this.getY() + (double)(this.random.nextInt(16) - 8) - vec3.y * 16.0; +- double d3 = this.getZ() + (this.random.nextDouble() - 0.5) * 8.0 - vec3.z * 16.0; ++ public boolean teleportTowards(Entity target) { ++ Vec3 vec3d = new Vec3(this.getX() - target.getX(), this.getY(0.5D) - target.getEyeY(), this.getZ() - target.getZ()); ++ ++ vec3d = vec3d.normalize(); ++ double d0 = 16.0D; ++ double d1 = this.getX() + (this.random.nextDouble() - 0.5D) * 8.0D - vec3d.x * 16.0D; ++ double d2 = this.getY() + (double) (this.random.nextInt(16) - 8) - vec3d.y * 16.0D; ++ double d3 = this.getZ() + (this.random.nextDouble() - 0.5D) * 8.0D - vec3d.z * 16.0D; ++ + return this.teleport(d1, d2, d3); + } + +- private boolean teleport(double x, double y, double z) { +- BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos(x, y, z); ++ private boolean teleport(double x, double d1, double y) { ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(x, d1, y); + +- while (mutableBlockPos.getY() > this.level().getMinBuildHeight() && !this.level().getBlockState(mutableBlockPos).blocksMotion()) { +- mutableBlockPos.move(Direction.DOWN); ++ while (blockposition_mutableblockposition.getY() > this.level().getMinBuildHeight() && !this.level().getBlockState(blockposition_mutableblockposition).blocksMotion()) { ++ blockposition_mutableblockposition.move(Direction.DOWN); + } + +- BlockState blockState = this.level().getBlockState(mutableBlockPos); +- boolean flag = blockState.blocksMotion(); +- boolean isWater = blockState.getFluidState().is(FluidTags.WATER); +- if (flag && !isWater) { +- Vec3 vec3 = this.position(); +- boolean flag1 = this.randomTeleport(x, y, z, true); +- if (flag1) { +- this.level().gameEvent(GameEvent.TELEPORT, vec3, GameEvent.Context.of(this)); ++ IBlockData iblockdata = this.level().getBlockState(blockposition_mutableblockposition); ++ boolean flag = iblockdata.blocksMotion(); ++ boolean flag1 = iblockdata.getFluidState().is(FluidTags.WATER); ++ ++ if (flag && !flag1) { ++ Vec3 vec3d = this.position(); ++ boolean flag2 = this.randomTeleport(x, d1, y, true); ++ ++ if (flag2) { ++ this.level().gameEvent(GameEvent.TELEPORT, vec3d, GameEvent.Context.of((Entity) this)); + if (!this.isSilent()) { +- this.level().playSound(null, this.xo, this.yo, this.zo, SoundEvents.ENDERMAN_TELEPORT, this.getSoundSource(), 1.0F, 1.0F); ++ this.level().playSound((Player) null, this.xo, this.yo, this.zo, SoundEvents.ENDERMAN_TELEPORT, this.getSoundSource(), 1.0F, 1.0F); + this.playSound(SoundEvents.ENDERMAN_TELEPORT, 1.0F, 1.0F); + } + } + +- return flag1; ++ return flag2; + } else { + return false; + } +@@ -350,28 +363,32 @@ + @Override + protected void dropCustomDeathLoot(DamageSource source, int looting, boolean recentlyHit) { + super.dropCustomDeathLoot(source, looting, recentlyHit); +- BlockState carriedBlock = this.getCarriedBlock(); +- if (carriedBlock != null) { +- ItemStack itemStack = new ItemStack(Items.DIAMOND_AXE); +- itemStack.enchant(Enchantments.SILK_TOUCH, 1); +- LootParams.Builder builder = new LootParams.Builder((ServerLevel)this.level()) +- .withParameter(LootContextParams.ORIGIN, this.position()) +- .withParameter(LootContextParams.TOOL, itemStack) +- .withOptionalParameter(LootContextParams.THIS_ENTITY, this); ++ IBlockData iblockdata = this.getCarriedBlock(); + +- for (ItemStack itemStack1 : carriedBlock.getDrops(builder)) { +- this.spawnAtLocation(itemStack1); ++ if (iblockdata != null) { ++ ItemStack itemstack = new ItemStack(Items.DIAMOND_AXE); ++ ++ itemstack.enchant(Enchantments.SILK_TOUCH, 1); ++ LootParams.Builder lootparams_a = (new LootParams.Builder((ServerLevel) this.level())).withParameter(LootContextParams.ORIGIN, this.position()).withParameter(LootContextParams.TOOL, itemstack).withOptionalParameter(LootContextParams.THIS_ENTITY, this); ++ List<ItemStack> list = iblockdata.getDrops(lootparams_a); ++ Iterator iterator = list.iterator(); ++ ++ while (iterator.hasNext()) { ++ ItemStack itemstack1 = (ItemStack) iterator.next(); ++ ++ this.spawnAtLocation(itemstack1); + } + } ++ + } + +- public void setCarriedBlock(@Nullable BlockState state) { +- this.entityData.set(DATA_CARRY_STATE, Optional.ofNullable(state)); ++ public void setCarriedBlock(@Nullable IBlockData state) { ++ this.entityData.set(EnderMan.DATA_CARRY_STATE, Optional.ofNullable(state)); + } + + @Nullable +- public BlockState getCarriedBlock() { +- return this.entityData.get(DATA_CARRY_STATE).orElse(null); ++ public IBlockData getCarriedBlock() { ++ return (IBlockData) ((Optional) this.entityData.get(EnderMan.DATA_CARRY_STATE)).orElse((Object) null); + } + + @Override +@@ -380,17 +397,19 @@ + return false; + } else { + boolean flag = source.getDirectEntity() instanceof ThrownPotion; ++ boolean flag1; ++ + if (!source.is(DamageTypeTags.IS_PROJECTILE) && !flag) { +- boolean flag1 = super.hurt(source, amount); ++ flag1 = super.hurt(source, amount); + if (!this.level().isClientSide() && !(source.getEntity() instanceof LivingEntity) && this.random.nextInt(10) != 0) { + this.teleport(); + } + + return flag1; + } else { +- boolean flag1 = flag && this.hurtWithCleanWater(source, (ThrownPotion)source.getDirectEntity(), amount); ++ flag1 = flag && this.hurtWithCleanWater(source, (ThrownPotion) source.getDirectEntity(), amount); + +- for (int i = 0; i < 64; i++) { ++ for (int i = 0; i < 64; ++i) { + if (this.teleport()) { + return true; + } +@@ -402,23 +421,24 @@ + } + + private boolean hurtWithCleanWater(DamageSource source, ThrownPotion potion, float amount) { +- ItemStack item = potion.getItem(); +- Potion potion1 = PotionUtils.getPotion(item); +- List<MobEffectInstance> mobEffects = PotionUtils.getMobEffects(item); +- boolean flag = potion1 == Potions.WATER && mobEffects.isEmpty(); +- return flag && super.hurt(source, amount); ++ ItemStack itemstack = potion.getItem(); ++ Potion potionregistry = PotionUtils.getPotion(itemstack); ++ List<MobEffectInstance> list = PotionUtils.getMobEffects(itemstack); ++ boolean flag = potionregistry == Potions.WATER && list.isEmpty(); ++ ++ return flag ? super.hurt(source, amount) : false; + } + + public boolean isCreepy() { +- return this.entityData.get(DATA_CREEPY); ++ return (Boolean) this.entityData.get(EnderMan.DATA_CREEPY); + } + + public boolean hasBeenStaredAt() { +- return this.entityData.get(DATA_STARED_AT); ++ return (Boolean) this.entityData.get(EnderMan.DATA_STARED_AT); + } + + public void setBeingStaredAt() { +- this.entityData.set(DATA_STARED_AT, true); ++ this.entityData.set(EnderMan.DATA_STARED_AT, true); + } + + @Override +@@ -426,14 +446,15 @@ + return super.requiresCustomPersistence() || this.getCarriedBlock() != null; + } + +- static class EndermanFreezeWhenLookedAt extends Goal { ++ private static class EndermanFreezeWhenLookedAt extends Goal { ++ + private final EnderMan enderman; + @Nullable + private LivingEntity target; + + public EndermanFreezeWhenLookedAt(EnderMan enderman) { + this.enderman = enderman; +- this.setFlags(EnumSet.of(Goal.Flag.JUMP, Goal.Flag.MOVE)); ++ this.setFlags(EnumSet.of(Goal.Type.JUMP, Goal.Type.MOVE)); + } + + @Override +@@ -442,8 +463,9 @@ + if (!(this.target instanceof Player)) { + return false; + } else { +- double d = this.target.distanceToSqr(this.enderman); +- return !(d > 256.0) && this.enderman.isLookingAtMe((Player)this.target); ++ double d0 = this.target.distanceToSqr((Entity) this.enderman); ++ ++ return d0 > 256.0D ? false : this.enderman.isLookingAtMe((Player) this.target); + } + } + +@@ -458,7 +480,8 @@ + } + } + +- static class EndermanLeaveBlockGoal extends Goal { ++ private static class EndermanLeaveBlockGoal extends Goal { ++ + private final EnderMan enderman; + + public EndermanLeaveBlockGoal(EnderMan enderman) { +@@ -467,52 +490,81 @@ + + @Override + public boolean canUse() { +- return this.enderman.getCarriedBlock() != null +- && this.enderman.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) +- && this.enderman.getRandom().nextInt(reducedTickDelay(2000)) == 0; ++ return this.enderman.getCarriedBlock() == null ? false : (!this.enderman.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) ? false : this.enderman.getRandom().nextInt(reducedTickDelay(2000)) == 0); + } + + @Override + public void tick() { +- RandomSource random = this.enderman.getRandom(); +- Level level = this.enderman.level(); +- int floor = Mth.floor(this.enderman.getX() - 1.0 + random.nextDouble() * 2.0); +- int floor1 = Mth.floor(this.enderman.getY() + random.nextDouble() * 2.0); +- int floor2 = Mth.floor(this.enderman.getZ() - 1.0 + random.nextDouble() * 2.0); +- BlockPos blockPos = new BlockPos(floor, floor1, floor2); +- BlockState blockState = level.getBlockState(blockPos); +- BlockPos blockPos1 = blockPos.below(); +- BlockState blockState1 = level.getBlockState(blockPos1); +- BlockState carriedBlock = this.enderman.getCarriedBlock(); +- if (carriedBlock != null) { +- BlockState var11 = Block.updateFromNeighbourShapes(carriedBlock, this.enderman.level(), blockPos); +- if (this.canPlaceBlock(level, blockPos, var11, blockState, blockState1, blockPos1)) { +- level.setBlock(blockPos, var11, 3); +- level.gameEvent(GameEvent.BLOCK_PLACE, blockPos, GameEvent.Context.of(this.enderman, var11)); +- this.enderman.setCarriedBlock(null); ++ RandomSource randomsource = this.enderman.getRandom(); ++ Level world = this.enderman.level(); ++ int i = Mth.floor(this.enderman.getX() - 1.0D + randomsource.nextDouble() * 2.0D); ++ int j = Mth.floor(this.enderman.getY() + randomsource.nextDouble() * 2.0D); ++ int k = Mth.floor(this.enderman.getZ() - 1.0D + randomsource.nextDouble() * 2.0D); ++ BlockPos blockposition = new BlockPos(i, j, k); ++ IBlockData iblockdata = world.getBlockState(blockposition); ++ BlockPos blockposition1 = blockposition.below(); ++ IBlockData iblockdata1 = world.getBlockState(blockposition1); ++ IBlockData iblockdata2 = this.enderman.getCarriedBlock(); ++ ++ if (iblockdata2 != null) { ++ iblockdata2 = Block.updateFromNeighbourShapes(iblockdata2, this.enderman.level(), blockposition); ++ if (this.canPlaceBlock(world, blockposition, iblockdata2, iblockdata, iblockdata1, blockposition1)) { ++ if (CraftEventFactory.callEntityChangeBlockEvent(this.enderman, blockposition, iblockdata2)) { // CraftBukkit - Place event ++ world.setBlock(blockposition, iblockdata2, 3); ++ world.gameEvent(GameEvent.BLOCK_PLACE, blockposition, GameEvent.Context.of(this.enderman, iblockdata2)); ++ this.enderman.setCarriedBlock((IBlockData) null); ++ } // CraftBukkit + } ++ + } + } + +- private boolean canPlaceBlock( +- Level level, +- BlockPos destinationPos, +- BlockState carriedState, +- BlockState destinationState, +- BlockState belowDestinationState, +- BlockPos belowDestinationPos +- ) { +- return destinationState.isAir() +- && !belowDestinationState.isAir() +- && !belowDestinationState.is(Blocks.BEDROCK) +- && belowDestinationState.isCollisionShapeFullBlock(level, belowDestinationPos) +- && carriedState.canSurvive(level, destinationPos) +- && level.getEntities(this.enderman, AABB.unitCubeFromLowerCorner(Vec3.atLowerCornerOf(destinationPos))).isEmpty(); ++ private boolean canPlaceBlock(Level level, BlockPos destinationPos, IBlockData carriedState, IBlockData destinationState, IBlockData belowDestinationState, BlockPos belowDestinationPos) { ++ return destinationState.isAir() && !belowDestinationState.isAir() && !belowDestinationState.is(Blocks.BEDROCK) && belowDestinationState.isCollisionShapeFullBlock(level, belowDestinationPos) && carriedState.canSurvive(level, destinationPos) && level.getEntities(this.enderman, AABB.unitCubeFromLowerCorner(Vec3.atLowerCornerOf(destinationPos))).isEmpty(); + } + } + +- static class EndermanLookForPlayerGoal extends NearestAttackableTargetGoal<Player> { ++ private static class EndermanTakeBlockGoal extends Goal { ++ + private final EnderMan enderman; ++ ++ public EndermanTakeBlockGoal(EnderMan enderman) { ++ this.enderman = enderman; ++ } ++ ++ @Override ++ public boolean canUse() { ++ return this.enderman.getCarriedBlock() != null ? false : (!this.enderman.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) ? false : this.enderman.getRandom().nextInt(reducedTickDelay(20)) == 0); ++ } ++ ++ @Override ++ public void tick() { ++ RandomSource randomsource = this.enderman.getRandom(); ++ Level world = this.enderman.level(); ++ int i = Mth.floor(this.enderman.getX() - 2.0D + randomsource.nextDouble() * 4.0D); ++ int j = Mth.floor(this.enderman.getY() + randomsource.nextDouble() * 3.0D); ++ int k = Mth.floor(this.enderman.getZ() - 2.0D + randomsource.nextDouble() * 4.0D); ++ BlockPos blockposition = new BlockPos(i, j, k); ++ IBlockData iblockdata = world.getBlockState(blockposition); ++ Vec3 vec3d = new Vec3((double) this.enderman.getBlockX() + 0.5D, (double) j + 0.5D, (double) this.enderman.getBlockZ() + 0.5D); ++ Vec3 vec3d1 = new Vec3((double) i + 0.5D, (double) j + 0.5D, (double) k + 0.5D); ++ BlockHitResult movingobjectpositionblock = world.clip(new ClipContext(vec3d, vec3d1, ClipContext.Block.OUTLINE, ClipContext.Fluid.NONE, this.enderman)); ++ boolean flag = movingobjectpositionblock.getBlockPos().equals(blockposition); ++ ++ if (iblockdata.is(BlockTags.ENDERMAN_HOLDABLE) && flag) { ++ if (CraftEventFactory.callEntityChangeBlockEvent(this.enderman, blockposition, Blocks.AIR.defaultBlockState())) { // CraftBukkit - Place event ++ world.removeBlock(blockposition, false); ++ world.gameEvent(GameEvent.BLOCK_DESTROY, blockposition, GameEvent.Context.of(this.enderman, iblockdata)); ++ this.enderman.setCarriedBlock(iblockdata.getBlock().defaultBlockState()); ++ } // CraftBukkit ++ } ++ ++ } ++ } ++ ++ private static class EndermanLookForPlayerGoal extends NearestAttackableTargetGoal<Player> { ++ ++ private final EnderMan enderman; + @Nullable + private Player pendingTarget; + private int aggroTime; +@@ -524,7 +576,9 @@ + public EndermanLookForPlayerGoal(EnderMan enderman, @Nullable Predicate<LivingEntity> selectionPredicate) { + super(enderman, Player.class, 10, false, false, selectionPredicate); + this.enderman = enderman; +- this.isAngerInducing = entity -> (enderman.isLookingAtMe((Player)entity) || enderman.isAngryAt(entity)) && !enderman.hasIndirectPassenger(entity); ++ this.isAngerInducing = (entityliving) -> { ++ return (enderman.isLookingAtMe((Player) entityliving) || enderman.isAngryAt(entityliving)) && !enderman.hasIndirectPassenger(entityliving); ++ }; + this.startAggroTargetConditions = TargetingConditions.forCombat().range(this.getFollowDistance()).selector(this.isAngerInducing); + } + +@@ -574,7 +628,7 @@ + @Override + public void tick() { + if (this.enderman.getTarget() == null) { +- super.setTarget(null); ++ super.setTarget((LivingEntity) null); + } + + if (this.pendingTarget != null) { +@@ -585,56 +639,20 @@ + } + } else { + if (this.target != null && !this.enderman.isPassenger()) { +- if (this.enderman.isLookingAtMe((Player)this.target)) { +- if (this.target.distanceToSqr(this.enderman) < 16.0) { ++ if (this.enderman.isLookingAtMe((Player) this.target)) { ++ if (this.target.distanceToSqr((Entity) this.enderman) < 16.0D) { + this.enderman.teleport(); + } + + this.teleportTime = 0; +- } else if (this.target.distanceToSqr(this.enderman) > 256.0 +- && this.teleportTime++ >= this.adjustedTickDelay(30) +- && this.enderman.teleportTowards(this.target)) { ++ } else if (this.target.distanceToSqr((Entity) this.enderman) > 256.0D && this.teleportTime++ >= this.adjustedTickDelay(30) && this.enderman.teleportTowards(this.target)) { + this.teleportTime = 0; + } + } + + super.tick(); + } +- } +- } + +- static class EndermanTakeBlockGoal extends Goal { +- private final EnderMan enderman; +- +- public EndermanTakeBlockGoal(EnderMan enderman) { +- this.enderman = enderman; + } +- +- @Override +- public boolean canUse() { +- return this.enderman.getCarriedBlock() == null +- && this.enderman.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) +- && this.enderman.getRandom().nextInt(reducedTickDelay(20)) == 0; +- } +- +- @Override +- public void tick() { +- RandomSource random = this.enderman.getRandom(); +- Level level = this.enderman.level(); +- int floor = Mth.floor(this.enderman.getX() - 2.0 + random.nextDouble() * 4.0); +- int floor1 = Mth.floor(this.enderman.getY() + random.nextDouble() * 3.0); +- int floor2 = Mth.floor(this.enderman.getZ() - 2.0 + random.nextDouble() * 4.0); +- BlockPos blockPos = new BlockPos(floor, floor1, floor2); +- BlockState blockState = level.getBlockState(blockPos); +- Vec3 vec3 = new Vec3((double)this.enderman.getBlockX() + 0.5, (double)floor1 + 0.5, (double)this.enderman.getBlockZ() + 0.5); +- Vec3 vec31 = new Vec3((double)floor + 0.5, (double)floor1 + 0.5, (double)floor2 + 0.5); +- BlockHitResult blockHitResult = level.clip(new ClipContext(vec3, vec31, ClipContext.Block.OUTLINE, ClipContext.Fluid.NONE, this.enderman)); +- boolean flag = blockHitResult.getBlockPos().equals(blockPos); +- if (blockState.is(BlockTags.ENDERMAN_HOLDABLE) && flag) { +- level.removeBlock(blockPos, false); +- level.gameEvent(GameEvent.BLOCK_DESTROY, blockPos, GameEvent.Context.of(this.enderman, blockState)); +- this.enderman.setCarriedBlock(blockState.getBlock().defaultBlockState()); +- } +- } + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Evoker.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Evoker.java.patch new file mode 100644 index 0000000000..fd571c6fc7 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Evoker.java.patch @@ -0,0 +1,410 @@ +--- a/net/minecraft/world/entity/monster/Evoker.java ++++ b/net/minecraft/world/entity/monster/Evoker.java +@@ -12,10 +12,11 @@ + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.EnumMonsterType; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.MobType; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; + import net.minecraft.world.entity.ai.attributes.Attributes; + import net.minecraft.world.entity.ai.goal.AvoidEntityGoal; +@@ -34,13 +35,14 @@ + import net.minecraft.world.item.DyeColor; + import net.minecraft.world.level.GameRules; + import net.minecraft.world.level.Level; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.Vec3; + import net.minecraft.world.phys.shapes.VoxelShape; + import net.minecraft.world.scores.PlayerTeam; + + public class Evoker extends SpellcasterIllager { ++ + @Nullable + private Sheep wololoTarget; + +@@ -54,21 +56,21 @@ + super.registerGoals(); + this.goalSelector.addGoal(0, new FloatGoal(this)); + this.goalSelector.addGoal(1, new Evoker.EvokerCastingSpellGoal()); +- this.goalSelector.addGoal(2, new AvoidEntityGoal<>(this, Player.class, 8.0F, 0.6, 1.0)); ++ this.goalSelector.addGoal(2, new AvoidEntityGoal<>(this, Player.class, 8.0F, 0.6D, 1.0D)); + this.goalSelector.addGoal(4, new Evoker.EvokerSummonSpellGoal()); + this.goalSelector.addGoal(5, new Evoker.EvokerAttackSpellGoal()); + this.goalSelector.addGoal(6, new Evoker.EvokerWololoSpellGoal()); +- this.goalSelector.addGoal(8, new RandomStrollGoal(this, 0.6)); ++ this.goalSelector.addGoal(8, new RandomStrollGoal(this, 0.6D)); + this.goalSelector.addGoal(9, new LookAtPlayerGoal(this, Player.class, 3.0F, 1.0F)); + this.goalSelector.addGoal(10, new LookAtPlayerGoal(this, Mob.class, 8.0F)); +- this.targetSelector.addGoal(1, new HurtByTargetGoal(this, Raider.class).setAlertOthers()); +- this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, true).setUnseenMemoryTicks(300)); +- this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, AbstractVillager.class, false).setUnseenMemoryTicks(300)); ++ this.targetSelector.addGoal(1, (new HurtByTargetGoal(this, new Class[]{Raider.class})).setAlertOthers()); ++ this.targetSelector.addGoal(2, (new NearestAttackableTargetGoal<>(this, Player.class, true)).setUnseenMemoryTicks(300)); ++ this.targetSelector.addGoal(3, (new NearestAttackableTargetGoal<>(this, AbstractVillager.class, false)).setUnseenMemoryTicks(300)); + this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, IronGolem.class, false)); + } + + public static AttributeSupplier.Builder createAttributes() { +- return Monster.createMonsterAttributes().add(Attributes.MOVEMENT_SPEED, 0.5).add(Attributes.FOLLOW_RANGE, 12.0).add(Attributes.MAX_HEALTH, 24.0); ++ return Monster.createMonsterAttributes().add(Attributes.MOVEMENT_SPEED, 0.5D).add(Attributes.FOLLOW_RANGE, 12.0D).add(Attributes.MAX_HEALTH, 24.0D); + } + + @Override +@@ -98,20 +100,7 @@ + + @Override + public boolean isAlliedTo(Entity entity) { +- if (entity == null) { +- return false; +- } else if (entity == this) { +- return true; +- } else if (super.isAlliedTo(entity)) { +- return true; +- } else { +- return entity instanceof Vex +- ? this.isAlliedTo(((Vex)entity).getOwner()) +- : entity instanceof LivingEntity +- && ((LivingEntity)entity).getMobType() == MobType.ILLAGER +- && this.getTeam() == null +- && entity.getTeam() == null; +- } ++ return entity == null ? false : (entity == this ? true : (super.isAlliedTo(entity) ? true : (entity instanceof Vex ? this.isAlliedTo((Entity) ((Vex) entity).getOwner()) : (entity instanceof LivingEntity && ((LivingEntity) entity).getMobType() == EnumMonsterType.ILLAGER ? this.getTeam() == null && entity.getTeam() == null : false)))); + } + + @Override +@@ -144,162 +133,192 @@ + } + + @Override +- public void applyRaidBuffs(int wave, boolean unusedFalse) { ++ public void applyRaidBuffs(int wave, boolean unusedFalse) {} ++ ++ private class EvokerCastingSpellGoal extends SpellcasterIllager.SpellcasterCastingSpellGoal { ++ ++ EvokerCastingSpellGoal() { ++ super(); ++ } ++ ++ @Override ++ public void tick() { ++ if (Evoker.this.getTarget() != null) { ++ Evoker.this.getLookControl().setLookAt(Evoker.this.getTarget(), (float) Evoker.this.getMaxHeadYRot(), (float) Evoker.this.getMaxHeadXRot()); ++ } else if (Evoker.this.getWololoTarget() != null) { ++ Evoker.this.getLookControl().setLookAt(Evoker.this.getWololoTarget(), (float) Evoker.this.getMaxHeadYRot(), (float) Evoker.this.getMaxHeadXRot()); ++ } ++ ++ } + } + +- class EvokerAttackSpellGoal extends SpellcasterIllager.SpellcasterUseSpellGoal { ++ private class EvokerSummonSpellGoal extends SpellcasterIllager.SpellcasterUseSpellGoal { ++ ++ private final TargetingConditions vexCountTargeting = TargetingConditions.forNonCombat().range(16.0D).ignoreLineOfSight().ignoreInvisibilityTesting(); ++ ++ EvokerSummonSpellGoal() { ++ super(); ++ } ++ + @Override ++ public boolean canUse() { ++ if (!super.canUse()) { ++ return false; ++ } else { ++ int i = Evoker.this.level().getNearbyEntities(Vex.class, this.vexCountTargeting, Evoker.this, Evoker.this.getBoundingBox().inflate(16.0D)).size(); ++ ++ return Evoker.this.random.nextInt(8) + 1 > i; ++ } ++ } ++ ++ @Override + protected int getCastingTime() { +- return 40; ++ return 100; + } + + @Override + protected int getCastingInterval() { +- return 100; ++ return 340; + } + + @Override + protected void performSpellCasting() { +- LivingEntity target = Evoker.this.getTarget(); +- double min = Math.min(target.getY(), Evoker.this.getY()); +- double d = Math.max(target.getY(), Evoker.this.getY()) + 1.0; +- float f = (float)Mth.atan2(target.getZ() - Evoker.this.getZ(), target.getX() - Evoker.this.getX()); +- if (Evoker.this.distanceToSqr(target) < 9.0) { +- for (int i = 0; i < 5; i++) { +- float f1 = f + (float)i * (float) Math.PI * 0.4F; +- this.createSpellEntity(Evoker.this.getX() + (double)Mth.cos(f1) * 1.5, Evoker.this.getZ() + (double)Mth.sin(f1) * 1.5, min, d, f1, 0); +- } ++ ServerLevel worldserver = (ServerLevel) Evoker.this.level(); ++ PlayerTeam scoreboardteam = Evoker.this.getTeam(); + +- for (int i = 0; i < 8; i++) { +- float f1 = f + (float)i * (float) Math.PI * 2.0F / 8.0F + (float) (Math.PI * 2.0 / 5.0); +- this.createSpellEntity(Evoker.this.getX() + (double)Mth.cos(f1) * 2.5, Evoker.this.getZ() + (double)Mth.sin(f1) * 2.5, min, d, f1, 3); +- } +- } else { +- for (int i = 0; i < 16; i++) { +- double d1 = 1.25 * (double)(i + 1); +- int i1 = 1 * i; +- this.createSpellEntity(Evoker.this.getX() + (double)Mth.cos(f) * d1, Evoker.this.getZ() + (double)Mth.sin(f) * d1, min, d, f, i1); +- } +- } +- } ++ for (int i = 0; i < 3; ++i) { ++ BlockPos blockposition = Evoker.this.blockPosition().offset(-2 + Evoker.this.random.nextInt(5), 1, -2 + Evoker.this.random.nextInt(5)); ++ Vex entityvex = (Vex) EntityType.VEX.create(Evoker.this.level()); + +- private void createSpellEntity(double x, double z, double minY, double maxY, float yRot, int warmupDelay) { +- BlockPos blockPos = BlockPos.containing(x, maxY, z); +- boolean flag = false; +- double d = 0.0; +- +- do { +- BlockPos blockPos1 = blockPos.below(); +- BlockState blockState = Evoker.this.level().getBlockState(blockPos1); +- if (blockState.isFaceSturdy(Evoker.this.level(), blockPos1, Direction.UP)) { +- if (!Evoker.this.level().isEmptyBlock(blockPos)) { +- BlockState blockState1 = Evoker.this.level().getBlockState(blockPos); +- VoxelShape collisionShape = blockState1.getCollisionShape(Evoker.this.level(), blockPos); +- if (!collisionShape.isEmpty()) { +- d = collisionShape.max(Direction.Axis.Y); +- } ++ if (entityvex != null) { ++ entityvex.moveTo(blockposition, 0.0F, 0.0F); ++ entityvex.finalizeSpawn(worldserver, Evoker.this.level().getCurrentDifficultyAt(blockposition), EnumMobSpawn.MOB_SUMMONED, (GroupDataEntity) null, (CompoundTag) null); ++ entityvex.setOwner(Evoker.this); ++ entityvex.setBoundOrigin(blockposition); ++ entityvex.setLimitedLife(20 * (30 + Evoker.this.random.nextInt(90))); ++ if (scoreboardteam != null) { ++ worldserver.getScoreboard().addPlayerToTeam(entityvex.getScoreboardName(), scoreboardteam); + } + +- flag = true; +- break; ++ worldserver.addFreshEntityWithPassengers(entityvex, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPELL); // CraftBukkit - Add SpawnReason ++ worldserver.gameEvent(GameEvent.ENTITY_PLACE, blockposition, GameEvent.Context.of((Entity) Evoker.this)); + } +- +- blockPos = blockPos.below(); +- } while (blockPos.getY() >= Mth.floor(minY) - 1); +- +- if (flag) { +- Evoker.this.level().addFreshEntity(new EvokerFangs(Evoker.this.level(), x, (double)blockPos.getY() + d, z, yRot, warmupDelay, Evoker.this)); +- Evoker.this.level().gameEvent(GameEvent.ENTITY_PLACE, new Vec3(x, (double)blockPos.getY() + d, z), GameEvent.Context.of(Evoker.this)); + } ++ + } + + @Override + protected SoundEvent getSpellPrepareSound() { +- return SoundEvents.EVOKER_PREPARE_ATTACK; ++ return SoundEvents.EVOKER_PREPARE_SUMMON; + } + + @Override + protected SpellcasterIllager.IllagerSpell getSpell() { +- return SpellcasterIllager.IllagerSpell.FANGS; ++ return SpellcasterIllager.IllagerSpell.SUMMON_VEX; + } + } + +- class EvokerCastingSpellGoal extends SpellcasterIllager.SpellcasterCastingSpellGoal { +- @Override +- public void tick() { +- if (Evoker.this.getTarget() != null) { +- Evoker.this.getLookControl().setLookAt(Evoker.this.getTarget(), (float)Evoker.this.getMaxHeadYRot(), (float)Evoker.this.getMaxHeadXRot()); +- } else if (Evoker.this.getWololoTarget() != null) { +- Evoker.this.getLookControl().setLookAt(Evoker.this.getWololoTarget(), (float)Evoker.this.getMaxHeadYRot(), (float)Evoker.this.getMaxHeadXRot()); +- } +- } +- } ++ private class EvokerAttackSpellGoal extends SpellcasterIllager.SpellcasterUseSpellGoal { + +- class EvokerSummonSpellGoal extends SpellcasterIllager.SpellcasterUseSpellGoal { +- private final TargetingConditions vexCountTargeting = TargetingConditions.forNonCombat().range(16.0).ignoreLineOfSight().ignoreInvisibilityTesting(); +- +- @Override +- public boolean canUse() { +- if (!super.canUse()) { +- return false; +- } else { +- int size = Evoker.this.level() +- .getNearbyEntities(Vex.class, this.vexCountTargeting, Evoker.this, Evoker.this.getBoundingBox().inflate(16.0)) +- .size(); +- return Evoker.this.random.nextInt(8) + 1 > size; +- } ++ EvokerAttackSpellGoal() { ++ super(); + } + + @Override + protected int getCastingTime() { +- return 100; ++ return 40; + } + + @Override + protected int getCastingInterval() { +- return 340; ++ return 100; + } + + @Override + protected void performSpellCasting() { +- ServerLevel serverLevel = (ServerLevel)Evoker.this.level(); +- PlayerTeam team = Evoker.this.getTeam(); ++ LivingEntity entityliving = Evoker.this.getTarget(); ++ double d0 = Math.min(entityliving.getY(), Evoker.this.getY()); ++ double d1 = Math.max(entityliving.getY(), Evoker.this.getY()) + 1.0D; ++ float f = (float) Mth.atan2(entityliving.getZ() - Evoker.this.getZ(), entityliving.getX() - Evoker.this.getX()); ++ int i; + +- for (int i = 0; i < 3; i++) { +- BlockPos blockPos = Evoker.this.blockPosition().offset(-2 + Evoker.this.random.nextInt(5), 1, -2 + Evoker.this.random.nextInt(5)); +- Vex vex = EntityType.VEX.create(Evoker.this.level()); +- if (vex != null) { +- vex.moveTo(blockPos, 0.0F, 0.0F); +- vex.finalizeSpawn(serverLevel, Evoker.this.level().getCurrentDifficultyAt(blockPos), MobSpawnType.MOB_SUMMONED, null, null); +- vex.setOwner(Evoker.this); +- vex.setBoundOrigin(blockPos); +- vex.setLimitedLife(20 * (30 + Evoker.this.random.nextInt(90))); +- if (team != null) { +- serverLevel.getScoreboard().addPlayerToTeam(vex.getScoreboardName(), team); ++ if (Evoker.this.distanceToSqr((Entity) entityliving) < 9.0D) { ++ float f1; ++ ++ for (i = 0; i < 5; ++i) { ++ f1 = f + (float) i * 3.1415927F * 0.4F; ++ this.createSpellEntity(Evoker.this.getX() + (double) Mth.cos(f1) * 1.5D, Evoker.this.getZ() + (double) Mth.sin(f1) * 1.5D, d0, d1, f1, 0); ++ } ++ ++ for (i = 0; i < 8; ++i) { ++ f1 = f + (float) i * 3.1415927F * 2.0F / 8.0F + 1.2566371F; ++ this.createSpellEntity(Evoker.this.getX() + (double) Mth.cos(f1) * 2.5D, Evoker.this.getZ() + (double) Mth.sin(f1) * 2.5D, d0, d1, f1, 3); ++ } ++ } else { ++ for (i = 0; i < 16; ++i) { ++ double d2 = 1.25D * (double) (i + 1); ++ int j = 1 * i; ++ ++ this.createSpellEntity(Evoker.this.getX() + (double) Mth.cos(f) * d2, Evoker.this.getZ() + (double) Mth.sin(f) * d2, d0, d1, f, j); ++ } ++ } ++ ++ } ++ ++ private void createSpellEntity(double x, double d1, double z, double d3, float minY, int i) { ++ BlockPos blockposition = BlockPos.containing(x, d3, d1); ++ boolean flag = false; ++ double d4 = 0.0D; ++ ++ do { ++ BlockPos blockposition1 = blockposition.below(); ++ IBlockData iblockdata = Evoker.this.level().getBlockState(blockposition1); ++ ++ if (iblockdata.isFaceSturdy(Evoker.this.level(), blockposition1, Direction.UP)) { ++ if (!Evoker.this.level().isEmptyBlock(blockposition)) { ++ IBlockData iblockdata1 = Evoker.this.level().getBlockState(blockposition); ++ VoxelShape voxelshape = iblockdata1.getCollisionShape(Evoker.this.level(), blockposition); ++ ++ if (!voxelshape.isEmpty()) { ++ d4 = voxelshape.max(Direction.Axis.Y); ++ } + } + +- serverLevel.addFreshEntityWithPassengers(vex); +- serverLevel.gameEvent(GameEvent.ENTITY_PLACE, blockPos, GameEvent.Context.of(Evoker.this)); ++ flag = true; ++ break; + } ++ ++ blockposition = blockposition.below(); ++ } while (blockposition.getY() >= Mth.floor(z) - 1); ++ ++ if (flag) { ++ Evoker.this.level().addFreshEntity(new EvokerFangs(Evoker.this.level(), x, (double) blockposition.getY() + d4, d1, minY, i, Evoker.this)); ++ Evoker.this.level().gameEvent(GameEvent.ENTITY_PLACE, new Vec3(x, (double) blockposition.getY() + d4, d1), GameEvent.Context.of((Entity) Evoker.this)); + } ++ + } + + @Override + protected SoundEvent getSpellPrepareSound() { +- return SoundEvents.EVOKER_PREPARE_SUMMON; ++ return SoundEvents.EVOKER_PREPARE_ATTACK; + } + + @Override + protected SpellcasterIllager.IllagerSpell getSpell() { +- return SpellcasterIllager.IllagerSpell.SUMMON_VEX; ++ return SpellcasterIllager.IllagerSpell.FANGS; + } + } + + public class EvokerWololoSpellGoal extends SpellcasterIllager.SpellcasterUseSpellGoal { +- private final TargetingConditions wololoTargeting = TargetingConditions.forNonCombat() +- .range(16.0) +- .selector(entity -> ((Sheep)entity).getColor() == DyeColor.BLUE); + ++ private final TargetingConditions wololoTargeting = TargetingConditions.forNonCombat().range(16.0D).selector((entityliving) -> { ++ return ((Sheep) entityliving).getColor() == DyeColor.BLUE; ++ }); ++ ++ public EvokerWololoSpellGoal() { ++ super(); ++ } ++ + @Override + public boolean canUse() { + if (Evoker.this.getTarget() != null) { +@@ -311,12 +330,12 @@ + } else if (!Evoker.this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { + return false; + } else { +- List<Sheep> nearbyEntities = Evoker.this.level() +- .getNearbyEntities(Sheep.class, this.wololoTargeting, Evoker.this, Evoker.this.getBoundingBox().inflate(16.0, 4.0, 16.0)); +- if (nearbyEntities.isEmpty()) { ++ List<Sheep> list = Evoker.this.level().getNearbyEntities(Sheep.class, this.wololoTargeting, Evoker.this, Evoker.this.getBoundingBox().inflate(16.0D, 4.0D, 16.0D)); ++ ++ if (list.isEmpty()) { + return false; + } else { +- Evoker.this.setWololoTarget(nearbyEntities.get(Evoker.this.random.nextInt(nearbyEntities.size()))); ++ Evoker.this.setWololoTarget((Sheep) list.get(Evoker.this.random.nextInt(list.size()))); + return true; + } + } +@@ -330,15 +349,17 @@ + @Override + public void stop() { + super.stop(); +- Evoker.this.setWololoTarget(null); ++ Evoker.this.setWololoTarget((Sheep) null); + } + + @Override + protected void performSpellCasting() { +- Sheep wololoTarget = Evoker.this.getWololoTarget(); +- if (wololoTarget != null && wololoTarget.isAlive()) { +- wololoTarget.setColor(DyeColor.RED); ++ Sheep entitysheep = Evoker.this.getWololoTarget(); ++ ++ if (entitysheep != null && entitysheep.isAlive()) { ++ entitysheep.setColor(DyeColor.RED); + } ++ + } + + @Override diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Ghast.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Ghast.java.patch new file mode 100644 index 0000000000..883eb23c05 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Ghast.java.patch @@ -0,0 +1,392 @@ +--- a/net/minecraft/world/entity/monster/Ghast.java ++++ b/net/minecraft/world/entity/monster/Ghast.java +@@ -15,12 +15,12 @@ + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; + import net.minecraft.world.entity.FlyingMob; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.Pose; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; + import net.minecraft.world.entity.ai.attributes.Attributes; + import net.minecraft.world.entity.ai.control.MoveControl; +@@ -34,7 +34,8 @@ + import net.minecraft.world.phys.Vec3; + import org.joml.Vector3f; + +-public class Ghast extends FlyingMob implements Enemy { ++public class Ghast extends FlyingMob implements IMonster { ++ + private static final EntityDataAccessor<Boolean> DATA_IS_CHARGING = SynchedEntityData.defineId(Ghast.class, EntityDataSerializers.BOOLEAN); + private int explosionPower = 1; + +@@ -49,18 +50,17 @@ + this.goalSelector.addGoal(5, new Ghast.RandomFloatAroundGoal(this)); + this.goalSelector.addGoal(7, new Ghast.GhastLookGoal(this)); + this.goalSelector.addGoal(7, new Ghast.GhastShootFireballGoal(this)); +- this.targetSelector +- .addGoal( +- 1, new NearestAttackableTargetGoal<>(this, Player.class, 10, true, false, livingEntity -> Math.abs(livingEntity.getY() - this.getY()) <= 4.0) +- ); ++ this.targetSelector.addGoal(1, new NearestAttackableTargetGoal<>(this, Player.class, 10, true, false, (entityliving) -> { ++ return Math.abs(entityliving.getY() - this.getY()) <= 4.0D; ++ })); + } + + public boolean isCharging() { +- return this.entityData.get(DATA_IS_CHARGING); ++ return (Boolean) this.entityData.get(Ghast.DATA_IS_CHARGING); + } + + public void setCharging(boolean charging) { +- this.entityData.set(DATA_IS_CHARGING, charging); ++ this.entityData.set(Ghast.DATA_IS_CHARGING, charging); + } + + public int getExplosionPower() { +@@ -87,18 +87,18 @@ + super.hurt(source, 1000.0F); + return true; + } else { +- return !this.isInvulnerableTo(source) && super.hurt(source, amount); ++ return this.isInvulnerableTo(source) ? false : super.hurt(source, amount); + } + } + + @Override + protected void defineSynchedData() { + super.defineSynchedData(); +- this.entityData.define(DATA_IS_CHARGING, false); ++ this.entityData.define(Ghast.DATA_IS_CHARGING, false); + } + + public static AttributeSupplier.Builder createAttributes() { +- return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 10.0).add(Attributes.FOLLOW_RANGE, 100.0); ++ return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 10.0D).add(Attributes.FOLLOW_RANGE, 100.0D); + } + + @Override +@@ -126,7 +126,7 @@ + return 5.0F; + } + +- public static boolean checkGhastSpawnRules(EntityType<Ghast> ghast, LevelAccessor level, MobSpawnType spawnType, BlockPos pos, RandomSource random) { ++ public static boolean checkGhastSpawnRules(EntityType<Ghast> ghast, LevelAccessor level, EnumMobSpawn spawnType, BlockPos pos, RandomSource random) { + return level.getDifficulty() != Difficulty.PEACEFUL && random.nextInt(20) == 0 && checkMobSpawnRules(ghast, level, spawnType, pos, random); + } + +@@ -136,8 +136,8 @@ + } + + @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entityDimensions, float f) { +- return new Vector3f(0.0F, entityDimensions.height + 0.0625F * f, 0.0F); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ return new Vector3f(0.0F, entitysize.height + 0.0625F * f, 0.0F); + } + + @Override +@@ -148,7 +148,7 @@ + @Override + public void addAdditionalSaveData(CompoundTag compound) { + super.addAdditionalSaveData(compound); +- compound.putByte("ExplosionPower", (byte)this.explosionPower); ++ compound.putByte("ExplosionPower", (byte) this.explosionPower); + } + + @Override +@@ -157,91 +157,142 @@ + if (compound.contains("ExplosionPower", 99)) { + this.explosionPower = compound.getByte("ExplosionPower"); + } ++ + } + + @Override +- protected float getStandingEyeHeight(Pose pose, EntityDimensions size) { ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions size) { + return 2.6F; + } + +- static class GhastLookGoal extends Goal { ++ private static class GhastMoveControl extends MoveControl { ++ + private final Ghast ghast; ++ private int floatDuration; + +- public GhastLookGoal(Ghast ghast) { ++ public GhastMoveControl(Ghast ghast) { ++ super(ghast); + this.ghast = ghast; +- this.setFlags(EnumSet.of(Goal.Flag.LOOK)); + } + + @Override +- public boolean canUse() { +- return true; ++ public void tick() { ++ if (this.operation == MoveControl.Operation.MOVE_TO) { ++ if (this.floatDuration-- <= 0) { ++ this.floatDuration += this.ghast.getRandom().nextInt(5) + 2; ++ Vec3 vec3d = new Vec3(this.wantedX - this.ghast.getX(), this.wantedY - this.ghast.getY(), this.wantedZ - this.ghast.getZ()); ++ double d0 = vec3d.length(); ++ ++ vec3d = vec3d.normalize(); ++ if (this.canReach(vec3d, Mth.ceil(d0))) { ++ this.ghast.setDeltaMovement(this.ghast.getDeltaMovement().add(vec3d.scale(0.1D))); ++ } else { ++ this.operation = MoveControl.Operation.WAIT; ++ } ++ } ++ ++ } + } + +- @Override +- public boolean requiresUpdateEveryTick() { ++ private boolean canReach(Vec3 pos, int length) { ++ AABB axisalignedbb = this.ghast.getBoundingBox(); ++ ++ for (int j = 1; j < length; ++j) { ++ axisalignedbb = axisalignedbb.move(pos); ++ if (!this.ghast.level().noCollision(this.ghast, axisalignedbb)) { ++ return false; ++ } ++ } ++ + return true; + } ++ } + ++ private static class RandomFloatAroundGoal extends Goal { ++ ++ private final Ghast ghast; ++ ++ public RandomFloatAroundGoal(Ghast ghast) { ++ this.ghast = ghast; ++ this.setFlags(EnumSet.of(Goal.Type.MOVE)); ++ } ++ + @Override +- public void tick() { +- if (this.ghast.getTarget() == null) { +- Vec3 deltaMovement = this.ghast.getDeltaMovement(); +- this.ghast.setYRot(-((float)Mth.atan2(deltaMovement.x, deltaMovement.z)) * (180.0F / (float)Math.PI)); +- this.ghast.yBodyRot = this.ghast.getYRot(); ++ public boolean canUse() { ++ MoveControl controllermove = this.ghast.getMoveControl(); ++ ++ if (!controllermove.hasWanted()) { ++ return true; + } else { +- LivingEntity target = this.ghast.getTarget(); +- double d = 64.0; +- if (target.distanceToSqr(this.ghast) < 4096.0) { +- double d1 = target.getX() - this.ghast.getX(); +- double d2 = target.getZ() - this.ghast.getZ(); +- this.ghast.setYRot(-((float)Mth.atan2(d1, d2)) * (180.0F / (float)Math.PI)); +- this.ghast.yBodyRot = this.ghast.getYRot(); +- } ++ double d0 = controllermove.getWantedX() - this.ghast.getX(); ++ double d1 = controllermove.getWantedY() - this.ghast.getY(); ++ double d2 = controllermove.getWantedZ() - this.ghast.getZ(); ++ double d3 = d0 * d0 + d1 * d1 + d2 * d2; ++ ++ return d3 < 1.0D || d3 > 3600.0D; + } + } ++ ++ @Override ++ public boolean canContinueToUse() { ++ return false; ++ } ++ ++ @Override ++ public void start() { ++ RandomSource randomsource = this.ghast.getRandom(); ++ double d0 = this.ghast.getX() + (double) ((randomsource.nextFloat() * 2.0F - 1.0F) * 16.0F); ++ double d1 = this.ghast.getY() + (double) ((randomsource.nextFloat() * 2.0F - 1.0F) * 16.0F); ++ double d2 = this.ghast.getZ() + (double) ((randomsource.nextFloat() * 2.0F - 1.0F) * 16.0F); ++ ++ this.ghast.getMoveControl().setWantedPosition(d0, d1, d2, 1.0D); ++ } + } + +- static class GhastMoveControl extends MoveControl { ++ private static class GhastLookGoal extends Goal { ++ + private final Ghast ghast; +- private int floatDuration; + +- public GhastMoveControl(Ghast mob) { +- super(mob); +- this.ghast = mob; ++ public GhastLookGoal(Ghast ghast) { ++ this.ghast = ghast; ++ this.setFlags(EnumSet.of(Goal.Type.LOOK)); + } + + @Override +- public void tick() { +- if (this.operation == MoveControl.Operation.MOVE_TO) { +- if (this.floatDuration-- <= 0) { +- this.floatDuration = this.floatDuration + this.ghast.getRandom().nextInt(5) + 2; +- Vec3 vec3 = new Vec3(this.wantedX - this.ghast.getX(), this.wantedY - this.ghast.getY(), this.wantedZ - this.ghast.getZ()); +- double len = vec3.length(); +- Vec3 var4 = vec3.normalize(); +- if (this.canReach(var4, Mth.ceil(len))) { +- this.ghast.setDeltaMovement(this.ghast.getDeltaMovement().add(var4.scale(0.1))); +- } else { +- this.operation = MoveControl.Operation.WAIT; +- } +- } +- } ++ public boolean canUse() { ++ return true; + } + +- private boolean canReach(Vec3 pos, int length) { +- AABB boundingBox = this.ghast.getBoundingBox(); ++ @Override ++ public boolean requiresUpdateEveryTick() { ++ return true; ++ } + +- for (int i = 1; i < length; i++) { +- boundingBox = boundingBox.move(pos); +- if (!this.ghast.level().noCollision(this.ghast, boundingBox)) { +- return false; ++ @Override ++ public void tick() { ++ if (this.ghast.getTarget() == null) { ++ Vec3 vec3d = this.ghast.getDeltaMovement(); ++ ++ this.ghast.setYRot(-((float) Mth.atan2(vec3d.x, vec3d.z)) * 57.295776F); ++ this.ghast.yBodyRot = this.ghast.getYRot(); ++ } else { ++ LivingEntity entityliving = this.ghast.getTarget(); ++ double d0 = 64.0D; ++ ++ if (entityliving.distanceToSqr((Entity) this.ghast) < 4096.0D) { ++ double d1 = entityliving.getX() - this.ghast.getX(); ++ double d2 = entityliving.getZ() - this.ghast.getZ(); ++ ++ this.ghast.setYRot(-((float) Mth.atan2(d1, d2)) * 57.295776F); ++ this.ghast.yBodyRot = this.ghast.getYRot(); + } + } + +- return true; + } + } + +- static class GhastShootFireballGoal extends Goal { ++ private static class GhastShootFireballGoal extends Goal { ++ + private final Ghast ghast; + public int chargeTime; + +@@ -271,74 +322,44 @@ + + @Override + public void tick() { +- LivingEntity target = this.ghast.getTarget(); +- if (target != null) { +- double d = 64.0; +- if (target.distanceToSqr(this.ghast) < 4096.0 && this.ghast.hasLineOfSight(target)) { +- Level level = this.ghast.level(); +- this.chargeTime++; ++ LivingEntity entityliving = this.ghast.getTarget(); ++ ++ if (entityliving != null) { ++ double d0 = 64.0D; ++ ++ if (entityliving.distanceToSqr((Entity) this.ghast) < 4096.0D && this.ghast.hasLineOfSight(entityliving)) { ++ Level world = this.ghast.level(); ++ ++ ++this.chargeTime; + if (this.chargeTime == 10 && !this.ghast.isSilent()) { +- level.levelEvent(null, 1015, this.ghast.blockPosition(), 0); ++ world.levelEvent((Player) null, 1015, this.ghast.blockPosition(), 0); + } + + if (this.chargeTime == 20) { +- double d1 = 4.0; +- Vec3 viewVector = this.ghast.getViewVector(1.0F); +- double d2 = target.getX() - (this.ghast.getX() + viewVector.x * 4.0); +- double d3 = target.getY(0.5) - (0.5 + this.ghast.getY(0.5)); +- double d4 = target.getZ() - (this.ghast.getZ() + viewVector.z * 4.0); ++ double d1 = 4.0D; ++ Vec3 vec3d = this.ghast.getViewVector(1.0F); ++ double d2 = entityliving.getX() - (this.ghast.getX() + vec3d.x * 4.0D); ++ double d3 = entityliving.getY(0.5D) - (0.5D + this.ghast.getY(0.5D)); ++ double d4 = entityliving.getZ() - (this.ghast.getZ() + vec3d.z * 4.0D); ++ + if (!this.ghast.isSilent()) { +- level.levelEvent(null, 1016, this.ghast.blockPosition(), 0); ++ world.levelEvent((Player) null, 1016, this.ghast.blockPosition(), 0); + } + +- LargeFireball largeFireball = new LargeFireball(level, this.ghast, d2, d3, d4, this.ghast.getExplosionPower()); +- largeFireball.setPos(this.ghast.getX() + viewVector.x * 4.0, this.ghast.getY(0.5) + 0.5, largeFireball.getZ() + viewVector.z * 4.0); +- level.addFreshEntity(largeFireball); ++ LargeFireball entitylargefireball = new LargeFireball(world, this.ghast, d2, d3, d4, this.ghast.getExplosionPower()); ++ ++ // CraftBukkit - set bukkitYield when setting explosionpower ++ entitylargefireball.bukkitYield = entitylargefireball.explosionPower = this.ghast.getExplosionPower(); ++ entitylargefireball.setPos(this.ghast.getX() + vec3d.x * 4.0D, this.ghast.getY(0.5D) + 0.5D, entitylargefireball.getZ() + vec3d.z * 4.0D); ++ world.addFreshEntity(entitylargefireball); + this.chargeTime = -40; + } + } else if (this.chargeTime > 0) { +- this.chargeTime--; ++ --this.chargeTime; + } + + this.ghast.setCharging(this.chargeTime > 10); + } + } + } +- +- static class RandomFloatAroundGoal extends Goal { +- private final Ghast ghast; +- +- public RandomFloatAroundGoal(Ghast ghast) { +- this.ghast = ghast; +- this.setFlags(EnumSet.of(Goal.Flag.MOVE)); +- } +- +- @Override +- public boolean canUse() { +- MoveControl moveControl = this.ghast.getMoveControl(); +- if (!moveControl.hasWanted()) { +- return true; +- } else { +- double d = moveControl.getWantedX() - this.ghast.getX(); +- double d1 = moveControl.getWantedY() - this.ghast.getY(); +- double d2 = moveControl.getWantedZ() - this.ghast.getZ(); +- double d3 = d * d + d1 * d1 + d2 * d2; +- return d3 < 1.0 || d3 > 3600.0; +- } +- } +- +- @Override +- public boolean canContinueToUse() { +- return false; +- } +- +- @Override +- public void start() { +- RandomSource random = this.ghast.getRandom(); +- double d = this.ghast.getX() + (double)((random.nextFloat() * 2.0F - 1.0F) * 16.0F); +- double d1 = this.ghast.getY() + (double)((random.nextFloat() * 2.0F - 1.0F) * 16.0F); +- double d2 = this.ghast.getZ() + (double)((random.nextFloat() * 2.0F - 1.0F) * 16.0F); +- this.ghast.getMoveControl().setWantedPosition(d, d1, d2, 1.0); +- } +- } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Guardian.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Guardian.java.patch new file mode 100644 index 0000000000..b2e7e561b7 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Guardian.java.patch @@ -0,0 +1,574 @@ +--- a/net/minecraft/world/entity/monster/Guardian.java ++++ b/net/minecraft/world/entity/monster/Guardian.java +@@ -19,12 +19,12 @@ + import net.minecraft.world.damagesource.DamageTypes; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.EnumMonsterType; ++import net.minecraft.world.entity.EnumMoveType; + import net.minecraft.world.entity.LivingEntity; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.MobType; +-import net.minecraft.world.entity.MoverType; +-import net.minecraft.world.entity.Pose; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; + import net.minecraft.world.entity.ai.attributes.Attributes; + import net.minecraft.world.entity.ai.control.LookControl; +@@ -48,6 +48,7 @@ + import org.joml.Vector3f; + + public class Guardian extends Monster { ++ + protected static final int ATTACK_TIME = 80; + private static final EntityDataAccessor<Boolean> DATA_ID_MOVING = SynchedEntityData.defineId(Guardian.class, EntityDataSerializers.BOOLEAN); + private static final EntityDataAccessor<Integer> DATA_ID_ATTACK_TARGET = SynchedEntityData.defineId(Guardian.class, EntityDataSerializers.INT); +@@ -61,7 +62,8 @@ + private int clientSideAttackTime; + private boolean clientSideTouchedGround; + @Nullable +- protected RandomStrollGoal randomStrollGoal; ++ public RandomStrollGoal randomStrollGoal; ++ public Guardian.GuardianAttackGoal guardianAttackGoal; // CraftBukkit - add field + + public Guardian(EntityType<? extends Guardian> entityType, Level level) { + super(entityType, level); +@@ -74,25 +76,22 @@ + + @Override + protected void registerGoals() { +- MoveTowardsRestrictionGoal moveTowardsRestrictionGoal = new MoveTowardsRestrictionGoal(this, 1.0); +- this.randomStrollGoal = new RandomStrollGoal(this, 1.0, 80); +- this.goalSelector.addGoal(4, new Guardian.GuardianAttackGoal(this)); +- this.goalSelector.addGoal(5, moveTowardsRestrictionGoal); ++ MoveTowardsRestrictionGoal pathfindergoalmovetowardsrestriction = new MoveTowardsRestrictionGoal(this, 1.0D); ++ ++ this.randomStrollGoal = new RandomStrollGoal(this, 1.0D, 80); ++ this.goalSelector.addGoal(4, guardianAttackGoal = new Guardian.GuardianAttackGoal(this)); // CraftBukkit - assign field ++ this.goalSelector.addGoal(5, pathfindergoalmovetowardsrestriction); + this.goalSelector.addGoal(7, this.randomStrollGoal); + this.goalSelector.addGoal(8, new LookAtPlayerGoal(this, Player.class, 8.0F)); + this.goalSelector.addGoal(8, new LookAtPlayerGoal(this, Guardian.class, 12.0F, 0.01F)); + this.goalSelector.addGoal(9, new RandomLookAroundGoal(this)); +- this.randomStrollGoal.setFlags(EnumSet.of(Goal.Flag.MOVE, Goal.Flag.LOOK)); +- moveTowardsRestrictionGoal.setFlags(EnumSet.of(Goal.Flag.MOVE, Goal.Flag.LOOK)); ++ this.randomStrollGoal.setFlags(EnumSet.of(Goal.Type.MOVE, Goal.Type.LOOK)); ++ pathfindergoalmovetowardsrestriction.setFlags(EnumSet.of(Goal.Type.MOVE, Goal.Type.LOOK)); + this.targetSelector.addGoal(1, new NearestAttackableTargetGoal<>(this, LivingEntity.class, 10, true, false, new Guardian.GuardianAttackSelector(this))); + } + + public static AttributeSupplier.Builder createAttributes() { +- return Monster.createMonsterAttributes() +- .add(Attributes.ATTACK_DAMAGE, 6.0) +- .add(Attributes.MOVEMENT_SPEED, 0.5) +- .add(Attributes.FOLLOW_RANGE, 16.0) +- .add(Attributes.MAX_HEALTH, 30.0); ++ return Monster.createMonsterAttributes().add(Attributes.ATTACK_DAMAGE, 6.0D).add(Attributes.MOVEMENT_SPEED, 0.5D).add(Attributes.FOLLOW_RANGE, 16.0D).add(Attributes.MAX_HEALTH, 30.0D); + } + + @Override +@@ -103,33 +102,33 @@ + @Override + protected void defineSynchedData() { + super.defineSynchedData(); +- this.entityData.define(DATA_ID_MOVING, false); +- this.entityData.define(DATA_ID_ATTACK_TARGET, 0); ++ this.entityData.define(Guardian.DATA_ID_MOVING, false); ++ this.entityData.define(Guardian.DATA_ID_ATTACK_TARGET, 0); + } + + @Override +- public MobType getMobType() { +- return MobType.WATER; ++ public EnumMonsterType getMobType() { ++ return EnumMonsterType.WATER; + } + + public boolean isMoving() { +- return this.entityData.get(DATA_ID_MOVING); ++ return (Boolean) this.entityData.get(Guardian.DATA_ID_MOVING); + } + + void setMoving(boolean moving) { +- this.entityData.set(DATA_ID_MOVING, moving); ++ this.entityData.set(Guardian.DATA_ID_MOVING, moving); + } + + public int getAttackDuration() { + return 80; + } + +- void setActiveAttackTarget(int activeAttackTargetId) { +- this.entityData.set(DATA_ID_ATTACK_TARGET, activeAttackTargetId); ++ public void setActiveAttackTarget(int activeAttackTargetId) { ++ this.entityData.set(Guardian.DATA_ID_ATTACK_TARGET, activeAttackTargetId); + } + + public boolean hasActiveAttackTarget() { +- return this.entityData.get(DATA_ID_ATTACK_TARGET) != 0; ++ return (Integer) this.entityData.get(Guardian.DATA_ID_ATTACK_TARGET) != 0; + } + + @Nullable +@@ -140,9 +139,10 @@ + if (this.clientSideCachedAttackTarget != null) { + return this.clientSideCachedAttackTarget; + } else { +- Entity entity = this.level().getEntity(this.entityData.get(DATA_ID_ATTACK_TARGET)); ++ Entity entity = this.level().getEntity((Integer) this.entityData.get(Guardian.DATA_ID_ATTACK_TARGET)); ++ + if (entity instanceof LivingEntity) { +- this.clientSideCachedAttackTarget = (LivingEntity)entity; ++ this.clientSideCachedAttackTarget = (LivingEntity) entity; + return this.clientSideCachedAttackTarget; + } else { + return null; +@@ -156,10 +156,11 @@ + @Override + public void onSyncedDataUpdated(EntityDataAccessor<?> key) { + super.onSyncedDataUpdated(key); +- if (DATA_ID_ATTACK_TARGET.equals(key)) { ++ if (Guardian.DATA_ID_ATTACK_TARGET.equals(key)) { + this.clientSideAttackTime = 0; + this.clientSideCachedAttackTarget = null; + } ++ + } + + @Override +@@ -188,7 +189,7 @@ + } + + @Override +- protected float getStandingEyeHeight(Pose pose, EntityDimensions size) { ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions size) { + return size.height * 0.5F; + } + +@@ -202,82 +203,68 @@ + if (this.isAlive()) { + if (this.level().isClientSide) { + this.clientSideTailAnimationO = this.clientSideTailAnimation; ++ Vec3 vec3d; ++ + if (!this.isInWater()) { + this.clientSideTailAnimationSpeed = 2.0F; +- Vec3 deltaMovement = this.getDeltaMovement(); +- if (deltaMovement.y > 0.0 && this.clientSideTouchedGround && !this.isSilent()) { ++ vec3d = this.getDeltaMovement(); ++ if (vec3d.y > 0.0D && this.clientSideTouchedGround && !this.isSilent()) { + this.level().playLocalSound(this.getX(), this.getY(), this.getZ(), this.getFlopSound(), this.getSoundSource(), 1.0F, 1.0F, false); + } + +- this.clientSideTouchedGround = deltaMovement.y < 0.0 && this.level().loadedAndEntityCanStandOn(this.blockPosition().below(), this); ++ this.clientSideTouchedGround = vec3d.y < 0.0D && this.level().loadedAndEntityCanStandOn(this.blockPosition().below(), this); + } else if (this.isMoving()) { + if (this.clientSideTailAnimationSpeed < 0.5F) { + this.clientSideTailAnimationSpeed = 4.0F; + } else { +- this.clientSideTailAnimationSpeed = this.clientSideTailAnimationSpeed + (0.5F - this.clientSideTailAnimationSpeed) * 0.1F; ++ this.clientSideTailAnimationSpeed += (0.5F - this.clientSideTailAnimationSpeed) * 0.1F; + } + } else { +- this.clientSideTailAnimationSpeed = this.clientSideTailAnimationSpeed + (0.125F - this.clientSideTailAnimationSpeed) * 0.2F; ++ this.clientSideTailAnimationSpeed += (0.125F - this.clientSideTailAnimationSpeed) * 0.2F; + } + +- this.clientSideTailAnimation = this.clientSideTailAnimation + this.clientSideTailAnimationSpeed; ++ this.clientSideTailAnimation += this.clientSideTailAnimationSpeed; + this.clientSideSpikesAnimationO = this.clientSideSpikesAnimation; + if (!this.isInWaterOrBubble()) { + this.clientSideSpikesAnimation = this.random.nextFloat(); + } else if (this.isMoving()) { +- this.clientSideSpikesAnimation = this.clientSideSpikesAnimation + (0.0F - this.clientSideSpikesAnimation) * 0.25F; ++ this.clientSideSpikesAnimation += (0.0F - this.clientSideSpikesAnimation) * 0.25F; + } else { +- this.clientSideSpikesAnimation = this.clientSideSpikesAnimation + (1.0F - this.clientSideSpikesAnimation) * 0.06F; ++ this.clientSideSpikesAnimation += (1.0F - this.clientSideSpikesAnimation) * 0.06F; + } + + if (this.isMoving() && this.isInWater()) { +- Vec3 deltaMovement = this.getViewVector(0.0F); ++ vec3d = this.getViewVector(0.0F); + +- for (int i = 0; i < 2; i++) { +- this.level() +- .addParticle( +- ParticleTypes.BUBBLE, +- this.getRandomX(0.5) - deltaMovement.x * 1.5, +- this.getRandomY() - deltaMovement.y * 1.5, +- this.getRandomZ(0.5) - deltaMovement.z * 1.5, +- 0.0, +- 0.0, +- 0.0 +- ); ++ for (int i = 0; i < 2; ++i) { ++ this.level().addParticle(ParticleTypes.BUBBLE, this.getRandomX(0.5D) - vec3d.x * 1.5D, this.getRandomY() - vec3d.y * 1.5D, this.getRandomZ(0.5D) - vec3d.z * 1.5D, 0.0D, 0.0D, 0.0D); + } + } + + if (this.hasActiveAttackTarget()) { + if (this.clientSideAttackTime < this.getAttackDuration()) { +- this.clientSideAttackTime++; ++ ++this.clientSideAttackTime; + } + +- LivingEntity activeAttackTarget = this.getActiveAttackTarget(); +- if (activeAttackTarget != null) { +- this.getLookControl().setLookAt(activeAttackTarget, 90.0F, 90.0F); ++ LivingEntity entityliving = this.getActiveAttackTarget(); ++ ++ if (entityliving != null) { ++ this.getLookControl().setLookAt(entityliving, 90.0F, 90.0F); + this.getLookControl().tick(); +- double d = (double)this.getAttackAnimationScale(0.0F); +- double d1 = activeAttackTarget.getX() - this.getX(); +- double d2 = activeAttackTarget.getY(0.5) - this.getEyeY(); +- double d3 = activeAttackTarget.getZ() - this.getZ(); +- double squareRoot = Math.sqrt(d1 * d1 + d2 * d2 + d3 * d3); +- double var17 = d1 / squareRoot; +- double var18 = d2 / squareRoot; +- double var19 = d3 / squareRoot; +- double randomDouble = this.random.nextDouble(); ++ double d0 = (double) this.getAttackAnimationScale(0.0F); ++ double d1 = entityliving.getX() - this.getX(); ++ double d2 = entityliving.getY(0.5D) - this.getEyeY(); ++ double d3 = entityliving.getZ() - this.getZ(); ++ double d4 = Math.sqrt(d1 * d1 + d2 * d2 + d3 * d3); + +- while (randomDouble < squareRoot) { +- randomDouble += 1.8 - d + this.random.nextDouble() * (1.7 - d); +- this.level() +- .addParticle( +- ParticleTypes.BUBBLE, +- this.getX() + var17 * randomDouble, +- this.getEyeY() + var18 * randomDouble, +- this.getZ() + var19 * randomDouble, +- 0.0, +- 0.0, +- 0.0 +- ); ++ d1 /= d4; ++ d2 /= d4; ++ d3 /= d4; ++ double d5 = this.random.nextDouble(); ++ ++ while (d5 < d4) { ++ d5 += 1.8D - d0 + this.random.nextDouble() * (1.7D - d0); ++ this.level().addParticle(ParticleTypes.BUBBLE, this.getX() + d1 * d5, this.getEyeY() + d2 * d5, this.getZ() + d3 * d5, 0.0D, 0.0D, 0.0D); + } + } + } +@@ -286,10 +273,7 @@ + if (this.isInWaterOrBubble()) { + this.setAirSupply(300); + } else if (this.onGround()) { +- this.setDeltaMovement( +- this.getDeltaMovement() +- .add((double)((this.random.nextFloat() * 2.0F - 1.0F) * 0.4F), 0.5, (double)((this.random.nextFloat() * 2.0F - 1.0F) * 0.4F)) +- ); ++ this.setDeltaMovement(this.getDeltaMovement().add((double) ((this.random.nextFloat() * 2.0F - 1.0F) * 0.4F), 0.5D, (double) ((this.random.nextFloat() * 2.0F - 1.0F) * 0.4F))); + this.setYRot(this.random.nextFloat() * 360.0F); + this.setOnGround(false); + this.hasImpulse = true; +@@ -316,11 +300,11 @@ + } + + public float getAttackAnimationScale(float partialTick) { +- return ((float)this.clientSideAttackTime + partialTick) / (float)this.getAttackDuration(); ++ return ((float) this.clientSideAttackTime + partialTick) / (float) this.getAttackDuration(); + } + + public float getClientSideAttackTime() { +- return (float)this.clientSideAttackTime; ++ return (float) this.clientSideAttackTime; + } + + @Override +@@ -328,13 +312,8 @@ + return level.isUnobstructed(this); + } + +- public static boolean checkGuardianSpawnRules( +- EntityType<? extends Guardian> guardian, LevelAccessor level, MobSpawnType spawnType, BlockPos pos, RandomSource random +- ) { +- return (random.nextInt(20) == 0 || !level.canSeeSkyFromBelowWater(pos)) +- && level.getDifficulty() != Difficulty.PEACEFUL +- && (MobSpawnType.isSpawner(spawnType) || level.getFluidState(pos).is(FluidTags.WATER)) +- && level.getFluidState(pos.below()).is(FluidTags.WATER); ++ public static boolean checkGuardianSpawnRules(EntityType<? extends Guardian> guardian, LevelAccessor level, EnumMobSpawn spawnType, BlockPos pos, RandomSource random) { ++ return (random.nextInt(20) == 0 || !level.canSeeSkyFromBelowWater(pos)) && level.getDifficulty() != Difficulty.PEACEFUL && (EnumMobSpawn.isSpawner(spawnType) || level.getFluidState(pos).is(FluidTags.WATER)) && level.getFluidState(pos.below()).is(FluidTags.WATER); + } + + @Override +@@ -342,11 +321,14 @@ + if (this.level().isClientSide) { + return false; + } else { +- if (!this.isMoving() +- && !source.is(DamageTypeTags.AVOIDS_GUARDIAN_THORNS) +- && !source.is(DamageTypes.THORNS) +- && source.getDirectEntity() instanceof LivingEntity livingEntity) { +- livingEntity.hurt(this.damageSources().thorns(this), 2.0F); ++ if (!this.isMoving() && !source.is(DamageTypeTags.AVOIDS_GUARDIAN_THORNS) && !source.is(DamageTypes.THORNS)) { ++ Entity entity = source.getDirectEntity(); ++ ++ if (entity instanceof LivingEntity) { ++ LivingEntity entityliving = (LivingEntity) entity; ++ ++ entityliving.hurt(this.damageSources().thorns(this), 2.0F); ++ } + } + + if (this.randomStrollGoal != null) { +@@ -366,51 +348,108 @@ + public void travel(Vec3 travelVector) { + if (this.isControlledByLocalInstance() && this.isInWater()) { + this.moveRelative(0.1F, travelVector); +- this.move(MoverType.SELF, this.getDeltaMovement()); +- this.setDeltaMovement(this.getDeltaMovement().scale(0.9)); ++ this.move(EnumMoveType.SELF, this.getDeltaMovement()); ++ this.setDeltaMovement(this.getDeltaMovement().scale(0.9D)); + if (!this.isMoving() && this.getTarget() == null) { +- this.setDeltaMovement(this.getDeltaMovement().add(0.0, -0.005, 0.0)); ++ this.setDeltaMovement(this.getDeltaMovement().add(0.0D, -0.005D, 0.0D)); + } + } else { + super.travel(travelVector); + } ++ + } + + @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entityDimensions, float f) { +- return new Vector3f(0.0F, entityDimensions.height + 0.125F * f, 0.0F); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ return new Vector3f(0.0F, entitysize.height + 0.125F * f, 0.0F); + } + +- static class GuardianAttackGoal extends Goal { ++ private static class GuardianMoveControl extends MoveControl { ++ + private final Guardian guardian; +- private int attackTime; ++ ++ public GuardianMoveControl(Guardian guardian) { ++ super(guardian); ++ this.guardian = guardian; ++ } ++ ++ @Override ++ public void tick() { ++ if (this.operation == MoveControl.Operation.MOVE_TO && !this.guardian.getNavigation().isDone()) { ++ Vec3 vec3d = new Vec3(this.wantedX - this.guardian.getX(), this.wantedY - this.guardian.getY(), this.wantedZ - this.guardian.getZ()); ++ double d0 = vec3d.length(); ++ double d1 = vec3d.x / d0; ++ double d2 = vec3d.y / d0; ++ double d3 = vec3d.z / d0; ++ float f = (float) (Mth.atan2(vec3d.z, vec3d.x) * 57.2957763671875D) - 90.0F; ++ ++ this.guardian.setYRot(this.rotlerp(this.guardian.getYRot(), f, 90.0F)); ++ this.guardian.yBodyRot = this.guardian.getYRot(); ++ float f1 = (float) (this.speedModifier * this.guardian.getAttributeValue(Attributes.MOVEMENT_SPEED)); ++ float f2 = Mth.lerp(0.125F, this.guardian.getSpeed(), f1); ++ ++ this.guardian.setSpeed(f2); ++ double d4 = Math.sin((double) (this.guardian.tickCount + this.guardian.getId()) * 0.5D) * 0.05D; ++ double d5 = Math.cos((double) (this.guardian.getYRot() * 0.017453292F)); ++ double d6 = Math.sin((double) (this.guardian.getYRot() * 0.017453292F)); ++ double d7 = Math.sin((double) (this.guardian.tickCount + this.guardian.getId()) * 0.75D) * 0.05D; ++ ++ this.guardian.setDeltaMovement(this.guardian.getDeltaMovement().add(d4 * d5, d7 * (d6 + d5) * 0.25D + (double) f2 * d2 * 0.1D, d4 * d6)); ++ LookControl controllerlook = this.guardian.getLookControl(); ++ double d8 = this.guardian.getX() + d1 * 2.0D; ++ double d9 = this.guardian.getEyeY() + d2 / d0; ++ double d10 = this.guardian.getZ() + d3 * 2.0D; ++ double d11 = controllerlook.getWantedX(); ++ double d12 = controllerlook.getWantedY(); ++ double d13 = controllerlook.getWantedZ(); ++ ++ if (!controllerlook.isLookingAtTarget()) { ++ d11 = d8; ++ d12 = d9; ++ d13 = d10; ++ } ++ ++ this.guardian.getLookControl().setLookAt(Mth.lerp(0.125D, d11, d8), Mth.lerp(0.125D, d12, d9), Mth.lerp(0.125D, d13, d10), 10.0F, 40.0F); ++ this.guardian.setMoving(true); ++ } else { ++ this.guardian.setSpeed(0.0F); ++ this.guardian.setMoving(false); ++ } ++ } ++ } ++ ++ public static class GuardianAttackGoal extends Goal { ++ ++ private final Guardian guardian; ++ public int attackTime; + private final boolean elder; + + public GuardianAttackGoal(Guardian guardian) { + this.guardian = guardian; + this.elder = guardian instanceof ElderGuardian; +- this.setFlags(EnumSet.of(Goal.Flag.MOVE, Goal.Flag.LOOK)); ++ this.setFlags(EnumSet.of(Goal.Type.MOVE, Goal.Type.LOOK)); + } + + @Override + public boolean canUse() { +- LivingEntity target = this.guardian.getTarget(); +- return target != null && target.isAlive(); ++ LivingEntity entityliving = this.guardian.getTarget(); ++ ++ return entityliving != null && entityliving.isAlive(); + } + + @Override + public boolean canContinueToUse() { +- return super.canContinueToUse() +- && (this.elder || this.guardian.getTarget() != null && this.guardian.distanceToSqr(this.guardian.getTarget()) > 9.0); ++ return super.canContinueToUse() && (this.elder || this.guardian.getTarget() != null && this.guardian.distanceToSqr((Entity) this.guardian.getTarget()) > 9.0D); + } + + @Override + public void start() { + this.attackTime = -10; + this.guardian.getNavigation().stop(); +- LivingEntity target = this.guardian.getTarget(); +- if (target != null) { +- this.guardian.getLookControl().setLookAt(target, 90.0F, 90.0F); ++ LivingEntity entityliving = this.guardian.getTarget(); ++ ++ if (entityliving != null) { ++ this.guardian.getLookControl().setLookAt(entityliving, 90.0F, 90.0F); + } + + this.guardian.hasImpulse = true; +@@ -419,7 +458,7 @@ + @Override + public void stop() { + this.guardian.setActiveAttackTarget(0); +- this.guardian.setTarget(null); ++ this.guardian.setTarget((LivingEntity) null); + this.guardian.randomStrollGoal.trigger(); + } + +@@ -430,21 +469,23 @@ + + @Override + public void tick() { +- LivingEntity target = this.guardian.getTarget(); +- if (target != null) { ++ LivingEntity entityliving = this.guardian.getTarget(); ++ ++ if (entityliving != null) { + this.guardian.getNavigation().stop(); +- this.guardian.getLookControl().setLookAt(target, 90.0F, 90.0F); +- if (!this.guardian.hasLineOfSight(target)) { +- this.guardian.setTarget(null); ++ this.guardian.getLookControl().setLookAt(entityliving, 90.0F, 90.0F); ++ if (!this.guardian.hasLineOfSight(entityliving)) { ++ this.guardian.setTarget((LivingEntity) null); + } else { +- this.attackTime++; ++ ++this.attackTime; + if (this.attackTime == 0) { +- this.guardian.setActiveAttackTarget(target.getId()); ++ this.guardian.setActiveAttackTarget(entityliving.getId()); + if (!this.guardian.isSilent()) { +- this.guardian.level().broadcastEntityEvent(this.guardian, (byte)21); ++ this.guardian.level().broadcastEntityEvent(this.guardian, (byte) 21); + } + } else if (this.attackTime >= this.guardian.getAttackDuration()) { + float f = 1.0F; ++ + if (this.guardian.level().getDifficulty() == Difficulty.HARD) { + f += 2.0F; + } +@@ -453,9 +494,9 @@ + f += 2.0F; + } + +- target.hurt(this.guardian.damageSources().indirectMagic(this.guardian, this.guardian), f); +- target.hurt(this.guardian.damageSources().mobAttack(this.guardian), (float)this.guardian.getAttributeValue(Attributes.ATTACK_DAMAGE)); +- this.guardian.setTarget(null); ++ entityliving.hurt(this.guardian.damageSources().indirectMagic(this.guardian, this.guardian), f); ++ entityliving.hurt(this.guardian.damageSources().mobAttack(this.guardian), (float) this.guardian.getAttributeValue(Attributes.ATTACK_DAMAGE)); ++ this.guardian.setTarget((LivingEntity) null); + } + + super.tick(); +@@ -464,67 +505,16 @@ + } + } + +- static class GuardianAttackSelector implements Predicate<LivingEntity> { ++ private static class GuardianAttackSelector implements Predicate<LivingEntity> { ++ + private final Guardian guardian; + + public GuardianAttackSelector(Guardian guardian) { + this.guardian = guardian; + } + +- @Override + public boolean test(@Nullable LivingEntity entity) { +- return (entity instanceof Player || entity instanceof Squid || entity instanceof Axolotl) && entity.distanceToSqr(this.guardian) > 9.0; ++ return (entity instanceof Player || entity instanceof Squid || entity instanceof Axolotl) && entity.distanceToSqr((Entity) this.guardian) > 9.0D; + } + } +- +- static class GuardianMoveControl extends MoveControl { +- private final Guardian guardian; +- +- public GuardianMoveControl(Guardian mob) { +- super(mob); +- this.guardian = mob; +- } +- +- @Override +- public void tick() { +- if (this.operation == MoveControl.Operation.MOVE_TO && !this.guardian.getNavigation().isDone()) { +- Vec3 vec3 = new Vec3(this.wantedX - this.guardian.getX(), this.wantedY - this.guardian.getY(), this.wantedZ - this.guardian.getZ()); +- double len = vec3.length(); +- double d = vec3.x / len; +- double d1 = vec3.y / len; +- double d2 = vec3.z / len; +- float f = (float)(Mth.atan2(vec3.z, vec3.x) * 180.0F / (float)Math.PI) - 90.0F; +- this.guardian.setYRot(this.rotlerp(this.guardian.getYRot(), f, 90.0F)); +- this.guardian.yBodyRot = this.guardian.getYRot(); +- float f1 = (float)(this.speedModifier * this.guardian.getAttributeValue(Attributes.MOVEMENT_SPEED)); +- float f2 = Mth.lerp(0.125F, this.guardian.getSpeed(), f1); +- this.guardian.setSpeed(f2); +- double d3 = Math.sin((double)(this.guardian.tickCount + this.guardian.getId()) * 0.5) * 0.05; +- double cos = Math.cos((double)(this.guardian.getYRot() * (float) (Math.PI / 180.0))); +- double sin = Math.sin((double)(this.guardian.getYRot() * (float) (Math.PI / 180.0))); +- double d4 = Math.sin((double)(this.guardian.tickCount + this.guardian.getId()) * 0.75) * 0.05; +- this.guardian.setDeltaMovement(this.guardian.getDeltaMovement().add(d3 * cos, d4 * (sin + cos) * 0.25 + (double)f2 * d1 * 0.1, d3 * sin)); +- LookControl lookControl = this.guardian.getLookControl(); +- double d5 = this.guardian.getX() + d * 2.0; +- double d6 = this.guardian.getEyeY() + d1 / len; +- double d7 = this.guardian.getZ() + d2 * 2.0; +- double wantedX = lookControl.getWantedX(); +- double wantedY = lookControl.getWantedY(); +- double wantedZ = lookControl.getWantedZ(); +- if (!lookControl.isLookingAtTarget()) { +- wantedX = d5; +- wantedY = d6; +- wantedZ = d7; +- } +- +- this.guardian +- .getLookControl() +- .setLookAt(Mth.lerp(0.125, wantedX, d5), Mth.lerp(0.125, wantedY, d6), Mth.lerp(0.125, wantedZ, d7), 10.0F, 40.0F); +- this.guardian.setMoving(true); +- } else { +- this.guardian.setSpeed(0.0F); +- this.guardian.setMoving(false); +- } +- } +- } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Husk.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Husk.java.patch new file mode 100644 index 0000000000..d48c4adfd2 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Husk.java.patch @@ -0,0 +1,63 @@ +--- a/net/minecraft/world/entity/monster/Husk.java ++++ b/net/minecraft/world/entity/monster/Husk.java +@@ -10,20 +10,22 @@ + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; + import net.minecraft.world.entity.LivingEntity; +-import net.minecraft.world.entity.MobSpawnType; ++import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.ServerLevelAccessor; + import org.joml.Vector3f; + + public class Husk extends Zombie { ++ + public Husk(EntityType<? extends Husk> entityType, Level level) { + super(entityType, level); + } + +- public static boolean checkHuskSpawnRules(EntityType<Husk> husk, ServerLevelAccessor level, MobSpawnType spawnType, BlockPos pos, RandomSource random) { +- return checkMonsterSpawnRules(husk, level, spawnType, pos, random) && (MobSpawnType.isSpawner(spawnType) || level.canSeeSky(pos)); ++ public static boolean checkHuskSpawnRules(EntityType<Husk> husk, ServerLevelAccessor level, EnumMobSpawn spawnType, BlockPos pos, RandomSource random) { ++ return checkMonsterSpawnRules(husk, level, spawnType, pos, random) && (EnumMobSpawn.isSpawner(spawnType) || level.canSeeSky(pos)); + } + + @Override +@@ -54,9 +56,11 @@ + @Override + public boolean doHurtTarget(Entity entity) { + boolean flag = super.doHurtTarget(entity); ++ + if (flag && this.getMainHandItem().isEmpty() && entity instanceof LivingEntity) { +- float effectiveDifficulty = this.level().getCurrentDifficultyAt(this.blockPosition()).getEffectiveDifficulty(); +- ((LivingEntity)entity).addEffect(new MobEffectInstance(MobEffects.HUNGER, 140 * (int)effectiveDifficulty), this); ++ float f = this.level().getCurrentDifficultyAt(this.blockPosition()).getEffectiveDifficulty(); ++ ++ ((LivingEntity) entity).addEffect(new MobEffectInstance(MobEffects.HUNGER, 140 * (int) f), this, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit + } + + return flag; +@@ -71,8 +75,9 @@ + protected void doUnderWaterConversion() { + this.convertToZombieType(EntityType.ZOMBIE); + if (!this.isSilent()) { +- this.level().levelEvent(null, 1041, this.blockPosition(), 0); ++ this.level().levelEvent((Player) null, 1041, this.blockPosition(), 0); + } ++ + } + + @Override +@@ -81,7 +86,7 @@ + } + + @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entityDimensions, float f) { +- return new Vector3f(0.0F, entityDimensions.height + 0.125F * f, 0.0F); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ return new Vector3f(0.0F, entitysize.height + 0.125F * f, 0.0F); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Illusioner.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Illusioner.java.patch new file mode 100644 index 0000000000..2c34f0888c --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Illusioner.java.patch @@ -0,0 +1,324 @@ +--- a/net/minecraft/world/entity/monster/Illusioner.java ++++ b/net/minecraft/world/entity/monster/Illusioner.java +@@ -12,12 +12,12 @@ + import net.minecraft.world.effect.MobEffects; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.EnumMonsterType; + import net.minecraft.world.entity.EquipmentSlot; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.MobType; +-import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; + import net.minecraft.world.entity.ai.attributes.Attributes; + import net.minecraft.world.entity.ai.goal.FloatGoal; +@@ -40,6 +40,7 @@ + import net.minecraft.world.phys.Vec3; + + public class Illusioner extends SpellcasterIllager implements RangedAttackMob { ++ + private static final int NUM_ILLUSIONS = 4; + private static final int ILLUSION_TRANSITION_TICKS = 3; + private static final int ILLUSION_SPREAD = 3; +@@ -51,10 +52,11 @@ + this.xpReward = 5; + this.clientSideIllusionOffsets = new Vec3[2][4]; + +- for (int i = 0; i < 4; i++) { ++ for (int i = 0; i < 4; ++i) { + this.clientSideIllusionOffsets[0][i] = Vec3.ZERO; + this.clientSideIllusionOffsets[1][i] = Vec3.ZERO; + } ++ + } + + @Override +@@ -64,24 +66,22 @@ + this.goalSelector.addGoal(1, new SpellcasterIllager.SpellcasterCastingSpellGoal()); + this.goalSelector.addGoal(4, new Illusioner.IllusionerMirrorSpellGoal()); + this.goalSelector.addGoal(5, new Illusioner.IllusionerBlindnessSpellGoal()); +- this.goalSelector.addGoal(6, new RangedBowAttackGoal<>(this, 0.5, 20, 15.0F)); +- this.goalSelector.addGoal(8, new RandomStrollGoal(this, 0.6)); ++ this.goalSelector.addGoal(6, new RangedBowAttackGoal<>(this, 0.5D, 20, 15.0F)); ++ this.goalSelector.addGoal(8, new RandomStrollGoal(this, 0.6D)); + this.goalSelector.addGoal(9, new LookAtPlayerGoal(this, Player.class, 3.0F, 1.0F)); + this.goalSelector.addGoal(10, new LookAtPlayerGoal(this, Mob.class, 8.0F)); +- this.targetSelector.addGoal(1, new HurtByTargetGoal(this, Raider.class).setAlertOthers()); +- this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, true).setUnseenMemoryTicks(300)); +- this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, AbstractVillager.class, false).setUnseenMemoryTicks(300)); +- this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, IronGolem.class, false).setUnseenMemoryTicks(300)); ++ this.targetSelector.addGoal(1, (new HurtByTargetGoal(this, new Class[]{Raider.class})).setAlertOthers()); ++ this.targetSelector.addGoal(2, (new NearestAttackableTargetGoal<>(this, Player.class, true)).setUnseenMemoryTicks(300)); ++ this.targetSelector.addGoal(3, (new NearestAttackableTargetGoal<>(this, AbstractVillager.class, false)).setUnseenMemoryTicks(300)); ++ this.targetSelector.addGoal(3, (new NearestAttackableTargetGoal<>(this, IronGolem.class, false)).setUnseenMemoryTicks(300)); + } + + public static AttributeSupplier.Builder createAttributes() { +- return Monster.createMonsterAttributes().add(Attributes.MOVEMENT_SPEED, 0.5).add(Attributes.FOLLOW_RANGE, 18.0).add(Attributes.MAX_HEALTH, 32.0); ++ return Monster.createMonsterAttributes().add(Attributes.MOVEMENT_SPEED, 0.5D).add(Attributes.FOLLOW_RANGE, 18.0D).add(Attributes.MAX_HEALTH, 32.0D); + } + + @Override +- public SpawnGroupData finalizeSpawn( +- ServerLevelAccessor level, DifficultyInstance difficulty, MobSpawnType reason, @Nullable SpawnGroupData spawnData, @Nullable CompoundTag dataTag +- ) { ++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) { + this.setItemSlot(EquipmentSlot.MAINHAND, new ItemStack(Items.BOW)); + return super.finalizeSpawn(level, difficulty, reason, spawnData, dataTag); + } +@@ -93,47 +93,47 @@ + + @Override + public AABB getBoundingBoxForCulling() { +- return this.getBoundingBox().inflate(3.0, 0.0, 3.0); ++ return this.getBoundingBox().inflate(3.0D, 0.0D, 3.0D); + } + + @Override + public void aiStep() { + super.aiStep(); + if (this.level().isClientSide && this.isInvisible()) { +- this.clientSideIllusionTicks--; ++ --this.clientSideIllusionTicks; + if (this.clientSideIllusionTicks < 0) { + this.clientSideIllusionTicks = 0; + } + +- if (this.hurtTime == 1 || this.tickCount % 1200 == 0) { ++ if (this.hurtTime != 1 && this.tickCount % 1200 != 0) { ++ if (this.hurtTime == this.hurtDuration - 1) { ++ this.clientSideIllusionTicks = 3; ++ ++ for (int i = 0; i < 4; ++i) { ++ this.clientSideIllusionOffsets[0][i] = this.clientSideIllusionOffsets[1][i]; ++ this.clientSideIllusionOffsets[1][i] = new Vec3(0.0D, 0.0D, 0.0D); ++ } ++ } ++ } else { + this.clientSideIllusionTicks = 3; + float f = -6.0F; +- int i = 13; ++ boolean flag = true; + +- for (int i1 = 0; i1 < 4; i1++) { +- this.clientSideIllusionOffsets[0][i1] = this.clientSideIllusionOffsets[1][i1]; +- this.clientSideIllusionOffsets[1][i1] = new Vec3( +- (double)(-6.0F + (float)this.random.nextInt(13)) * 0.5, +- (double)Math.max(0, this.random.nextInt(6) - 4), +- (double)(-6.0F + (float)this.random.nextInt(13)) * 0.5 +- ); +- } ++ int j; + +- for (int i1 = 0; i1 < 16; i1++) { +- this.level().addParticle(ParticleTypes.CLOUD, this.getRandomX(0.5), this.getRandomY(), this.getZ(0.5), 0.0, 0.0, 0.0); ++ for (j = 0; j < 4; ++j) { ++ this.clientSideIllusionOffsets[0][j] = this.clientSideIllusionOffsets[1][j]; ++ this.clientSideIllusionOffsets[1][j] = new Vec3((double) (-6.0F + (float) this.random.nextInt(13)) * 0.5D, (double) Math.max(0, this.random.nextInt(6) - 4), (double) (-6.0F + (float) this.random.nextInt(13)) * 0.5D); + } + +- this.level() +- .playLocalSound(this.getX(), this.getY(), this.getZ(), SoundEvents.ILLUSIONER_MIRROR_MOVE, this.getSoundSource(), 1.0F, 1.0F, false); +- } else if (this.hurtTime == this.hurtDuration - 1) { +- this.clientSideIllusionTicks = 3; +- +- for (int i2 = 0; i2 < 4; i2++) { +- this.clientSideIllusionOffsets[0][i2] = this.clientSideIllusionOffsets[1][i2]; +- this.clientSideIllusionOffsets[1][i2] = new Vec3(0.0, 0.0, 0.0); ++ for (j = 0; j < 16; ++j) { ++ this.level().addParticle(ParticleTypes.CLOUD, this.getRandomX(0.5D), this.getRandomY(), this.getZ(0.5D), 0.0D, 0.0D, 0.0D); + } ++ ++ this.level().playLocalSound(this.getX(), this.getY(), this.getZ(), SoundEvents.ILLUSIONER_MIRROR_MOVE, this.getSoundSource(), 1.0F, 1.0F, false); + } + } ++ + } + + @Override +@@ -145,22 +145,22 @@ + if (this.clientSideIllusionTicks <= 0) { + return this.clientSideIllusionOffsets[1]; + } else { +- double d = (double)(((float)this.clientSideIllusionTicks - partialTick) / 3.0F); +- double var6 = Math.pow(d, 0.25); +- Vec3[] vec3s = new Vec3[4]; ++ double d0 = (double) (((float) this.clientSideIllusionTicks - partialTick) / 3.0F); + +- for (int i = 0; i < 4; i++) { +- vec3s[i] = this.clientSideIllusionOffsets[1][i].scale(1.0 - var6).add(this.clientSideIllusionOffsets[0][i].scale(var6)); ++ d0 = Math.pow(d0, 0.25D); ++ Vec3[] avec3d = new Vec3[4]; ++ ++ for (int i = 0; i < 4; ++i) { ++ avec3d[i] = this.clientSideIllusionOffsets[1][i].scale(1.0D - d0).add(this.clientSideIllusionOffsets[0][i].scale(d0)); + } + +- return vec3s; ++ return avec3d; + } + } + + @Override + public boolean isAlliedTo(Entity entity) { +- return super.isAlliedTo(entity) +- || entity instanceof LivingEntity && ((LivingEntity)entity).getMobType() == MobType.ILLAGER && this.getTeam() == null && entity.getTeam() == null; ++ return super.isAlliedTo(entity) ? true : (entity instanceof LivingEntity && ((LivingEntity) entity).getMobType() == EnumMonsterType.ILLAGER ? this.getTeam() == null && entity.getTeam() == null : false); + } + + @Override +@@ -184,49 +184,36 @@ + } + + @Override +- public void applyRaidBuffs(int wave, boolean unusedFalse) { +- } ++ public void applyRaidBuffs(int wave, boolean unusedFalse) {} + + @Override + public void performRangedAttack(LivingEntity target, float distanceFactor) { +- ItemStack projectile = this.getProjectile(this.getItemInHand(ProjectileUtil.getWeaponHoldingHand(this, Items.BOW))); +- AbstractArrow mobArrow = ProjectileUtil.getMobArrow(this, projectile, distanceFactor); +- double d = target.getX() - this.getX(); +- double d1 = target.getY(0.3333333333333333) - mobArrow.getY(); ++ ItemStack itemstack = this.getProjectile(this.getItemInHand(ProjectileUtil.getWeaponHoldingHand(this, Items.BOW))); ++ AbstractArrow entityarrow = ProjectileUtil.getMobArrow(this, itemstack, distanceFactor); ++ double d0 = target.getX() - this.getX(); ++ double d1 = target.getY(0.3333333333333333D) - entityarrow.getY(); + double d2 = target.getZ() - this.getZ(); +- double squareRoot = Math.sqrt(d * d + d2 * d2); +- mobArrow.shoot(d, d1 + squareRoot * 0.2F, d2, 1.6F, (float)(14 - this.level().getDifficulty().getId() * 4)); ++ double d3 = Math.sqrt(d0 * d0 + d2 * d2); ++ ++ entityarrow.shoot(d0, d1 + d3 * 0.20000000298023224D, d2, 1.6F, (float) (14 - this.level().getDifficulty().getId() * 4)); + this.playSound(SoundEvents.SKELETON_SHOOT, 1.0F, 1.0F / (this.getRandom().nextFloat() * 0.4F + 0.8F)); +- this.level().addFreshEntity(mobArrow); ++ this.level().addFreshEntity(entityarrow); + } + + @Override +- public AbstractIllager.IllagerArmPose getArmPose() { +- if (this.isCastingSpell()) { +- return AbstractIllager.IllagerArmPose.SPELLCASTING; +- } else { +- return this.isAggressive() ? AbstractIllager.IllagerArmPose.BOW_AND_ARROW : AbstractIllager.IllagerArmPose.CROSSED; +- } ++ public AbstractIllager.a getArmPose() { ++ return this.isCastingSpell() ? AbstractIllager.a.SPELLCASTING : (this.isAggressive() ? AbstractIllager.a.BOW_AND_ARROW : AbstractIllager.a.CROSSED); + } + +- class IllusionerBlindnessSpellGoal extends SpellcasterIllager.SpellcasterUseSpellGoal { +- private int lastTargetId; ++ private class IllusionerMirrorSpellGoal extends SpellcasterIllager.SpellcasterUseSpellGoal { + +- @Override +- public boolean canUse() { +- return super.canUse() +- && Illusioner.this.getTarget() != null +- && Illusioner.this.getTarget().getId() != this.lastTargetId +- && Illusioner.this.level().getCurrentDifficultyAt(Illusioner.this.blockPosition()).isHarderThan((float)Difficulty.NORMAL.ordinal()); ++ IllusionerMirrorSpellGoal() { ++ super(); + } + + @Override +- public void start() { +- super.start(); +- LivingEntity target = Illusioner.this.getTarget(); +- if (target != null) { +- this.lastTargetId = target.getId(); +- } ++ public boolean canUse() { ++ return !super.canUse() ? false : !Illusioner.this.hasEffect(MobEffects.INVISIBILITY); + } + + @Override +@@ -236,55 +223,73 @@ + + @Override + protected int getCastingInterval() { +- return 180; ++ return 340; + } + + @Override + protected void performSpellCasting() { +- Illusioner.this.getTarget().addEffect(new MobEffectInstance(MobEffects.BLINDNESS, 400), Illusioner.this); ++ Illusioner.this.addEffect(new MobEffectInstance(MobEffects.INVISIBILITY, 1200), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ILLUSION); // CraftBukkit + } + ++ @Nullable + @Override + protected SoundEvent getSpellPrepareSound() { +- return SoundEvents.ILLUSIONER_PREPARE_BLINDNESS; ++ return SoundEvents.ILLUSIONER_PREPARE_MIRROR; + } + + @Override + protected SpellcasterIllager.IllagerSpell getSpell() { +- return SpellcasterIllager.IllagerSpell.BLINDNESS; ++ return SpellcasterIllager.IllagerSpell.DISAPPEAR; + } + } + +- class IllusionerMirrorSpellGoal extends SpellcasterIllager.SpellcasterUseSpellGoal { ++ private class IllusionerBlindnessSpellGoal extends SpellcasterIllager.SpellcasterUseSpellGoal { ++ ++ private int lastTargetId; ++ ++ IllusionerBlindnessSpellGoal() { ++ super(); ++ } ++ + @Override + public boolean canUse() { +- return super.canUse() && !Illusioner.this.hasEffect(MobEffects.INVISIBILITY); ++ return !super.canUse() ? false : (Illusioner.this.getTarget() == null ? false : (Illusioner.this.getTarget().getId() == this.lastTargetId ? false : Illusioner.this.level().getCurrentDifficultyAt(Illusioner.this.blockPosition()).isHarderThan((float) Difficulty.NORMAL.ordinal()))); + } + + @Override ++ public void start() { ++ super.start(); ++ LivingEntity entityliving = Illusioner.this.getTarget(); ++ ++ if (entityliving != null) { ++ this.lastTargetId = entityliving.getId(); ++ } ++ ++ } ++ ++ @Override + protected int getCastingTime() { + return 20; + } + + @Override + protected int getCastingInterval() { +- return 340; ++ return 180; + } + + @Override + protected void performSpellCasting() { +- Illusioner.this.addEffect(new MobEffectInstance(MobEffects.INVISIBILITY, 1200)); ++ Illusioner.this.getTarget().addEffect(new MobEffectInstance(MobEffects.BLINDNESS, 400), Illusioner.this, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit + } + +- @Nullable + @Override + protected SoundEvent getSpellPrepareSound() { +- return SoundEvents.ILLUSIONER_PREPARE_MIRROR; ++ return SoundEvents.ILLUSIONER_PREPARE_BLINDNESS; + } + + @Override + protected SpellcasterIllager.IllagerSpell getSpell() { +- return SpellcasterIllager.IllagerSpell.DISAPPEAR; ++ return SpellcasterIllager.IllagerSpell.BLINDNESS; + } + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Phantom.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Phantom.java.patch new file mode 100644 index 0000000000..cf3ac8546b --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Phantom.java.patch @@ -0,0 +1,668 @@ +--- a/net/minecraft/world/entity/monster/Phantom.java ++++ b/net/minecraft/world/entity/monster/Phantom.java +@@ -2,6 +2,7 @@ + + import java.util.Comparator; + import java.util.EnumSet; ++import java.util.Iterator; + import java.util.List; + import javax.annotation.Nullable; + import net.minecraft.core.BlockPos; +@@ -18,15 +19,15 @@ + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntitySelector; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.EnumMonsterType; + import net.minecraft.world.entity.FlyingMob; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.MobType; +-import net.minecraft.world.entity.Pose; +-import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.ai.attributes.Attributes; + import net.minecraft.world.entity.ai.control.BodyRotationControl; + import net.minecraft.world.entity.ai.control.LookControl; +@@ -41,16 +42,20 @@ + import net.minecraft.world.phys.Vec3; + import org.joml.Vector3f; + +-public class Phantom extends FlyingMob implements Enemy { ++public class Phantom extends FlyingMob implements IMonster { ++ + public static final float FLAP_DEGREES_PER_TICK = 7.448451F; + public static final int TICKS_PER_FLAP = Mth.ceil(24.166098F); + private static final EntityDataAccessor<Integer> ID_SIZE = SynchedEntityData.defineId(Phantom.class, EntityDataSerializers.INT); +- Vec3 moveTargetPoint = Vec3.ZERO; +- BlockPos anchorPoint = BlockPos.ZERO; +- Phantom.AttackPhase attackPhase = Phantom.AttackPhase.CIRCLE; ++ Vec3 moveTargetPoint; ++ BlockPos anchorPoint; ++ Phantom.AttackPhase attackPhase; + + public Phantom(EntityType<? extends Phantom> entityType, Level level) { + super(entityType, level); ++ this.moveTargetPoint = Vec3.ZERO; ++ this.anchorPoint = BlockPos.ZERO; ++ this.attackPhase = Phantom.AttackPhase.CIRCLE; + this.xpReward = 5; + this.moveControl = new Phantom.PhantomMoveControl(this); + this.lookControl = new Phantom.PhantomLookControl(this); +@@ -58,7 +63,7 @@ + + @Override + public boolean isFlapping() { +- return (this.getUniqueFlapTickOffset() + this.tickCount) % TICKS_PER_FLAP == 0; ++ return (this.getUniqueFlapTickOffset() + this.tickCount) % Phantom.TICKS_PER_FLAP == 0; + } + + @Override +@@ -77,30 +82,30 @@ + @Override + protected void defineSynchedData() { + super.defineSynchedData(); +- this.entityData.define(ID_SIZE, 0); ++ this.entityData.define(Phantom.ID_SIZE, 0); + } + + public void setPhantomSize(int phantomSize) { +- this.entityData.set(ID_SIZE, Mth.clamp(phantomSize, 0, 64)); ++ this.entityData.set(Phantom.ID_SIZE, Mth.clamp(phantomSize, 0, 64)); + } + + private void updatePhantomSizeInfo() { + this.refreshDimensions(); +- this.getAttribute(Attributes.ATTACK_DAMAGE).setBaseValue((double)(6 + this.getPhantomSize())); ++ this.getAttribute(Attributes.ATTACK_DAMAGE).setBaseValue((double) (6 + this.getPhantomSize())); + } + + public int getPhantomSize() { +- return this.entityData.get(ID_SIZE); ++ return (Integer) this.entityData.get(Phantom.ID_SIZE); + } + + @Override +- protected float getStandingEyeHeight(Pose pose, EntityDimensions size) { ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions size) { + return size.height * 0.35F; + } + + @Override + public void onSyncedDataUpdated(EntityDataAccessor<?> key) { +- if (ID_SIZE.equals(key)) { ++ if (Phantom.ID_SIZE.equals(key)) { + this.updatePhantomSizeInfo(); + } + +@@ -120,29 +125,22 @@ + public void tick() { + super.tick(); + if (this.level().isClientSide) { +- float cos = Mth.cos((float)(this.getUniqueFlapTickOffset() + this.tickCount) * 7.448451F * (float) (Math.PI / 180.0) + (float) Math.PI); +- float cos1 = Mth.cos((float)(this.getUniqueFlapTickOffset() + this.tickCount + 1) * 7.448451F * (float) (Math.PI / 180.0) + (float) Math.PI); +- if (cos > 0.0F && cos1 <= 0.0F) { +- this.level() +- .playLocalSound( +- this.getX(), +- this.getY(), +- this.getZ(), +- SoundEvents.PHANTOM_FLAP, +- this.getSoundSource(), +- 0.95F + this.random.nextFloat() * 0.05F, +- 0.95F + this.random.nextFloat() * 0.05F, +- false +- ); ++ float f = Mth.cos((float) (this.getUniqueFlapTickOffset() + this.tickCount) * 7.448451F * 0.017453292F + 3.1415927F); ++ float f1 = Mth.cos((float) (this.getUniqueFlapTickOffset() + this.tickCount + 1) * 7.448451F * 0.017453292F + 3.1415927F); ++ ++ if (f > 0.0F && f1 <= 0.0F) { ++ this.level().playLocalSound(this.getX(), this.getY(), this.getZ(), SoundEvents.PHANTOM_FLAP, this.getSoundSource(), 0.95F + this.random.nextFloat() * 0.05F, 0.95F + this.random.nextFloat() * 0.05F, false); + } + +- int phantomSize = this.getPhantomSize(); +- float f = Mth.cos(this.getYRot() * (float) (Math.PI / 180.0)) * (1.3F + 0.21F * (float)phantomSize); +- float f1 = Mth.sin(this.getYRot() * (float) (Math.PI / 180.0)) * (1.3F + 0.21F * (float)phantomSize); +- float f2 = (0.3F + cos * 0.45F) * ((float)phantomSize * 0.2F + 1.0F); +- this.level().addParticle(ParticleTypes.MYCELIUM, this.getX() + (double)f, this.getY() + (double)f2, this.getZ() + (double)f1, 0.0, 0.0, 0.0); +- this.level().addParticle(ParticleTypes.MYCELIUM, this.getX() - (double)f, this.getY() + (double)f2, this.getZ() - (double)f1, 0.0, 0.0, 0.0); ++ int i = this.getPhantomSize(); ++ float f2 = Mth.cos(this.getYRot() * 0.017453292F) * (1.3F + 0.21F * (float) i); ++ float f3 = Mth.sin(this.getYRot() * 0.017453292F) * (1.3F + 0.21F * (float) i); ++ float f4 = (0.3F + f * 0.45F) * ((float) i * 0.2F + 1.0F); ++ ++ this.level().addParticle(ParticleTypes.MYCELIUM, this.getX() + (double) f2, this.getY() + (double) f4, this.getZ() + (double) f3, 0.0D, 0.0D, 0.0D); ++ this.level().addParticle(ParticleTypes.MYCELIUM, this.getX() - (double) f2, this.getY() + (double) f4, this.getZ() - (double) f3, 0.0D, 0.0D, 0.0D); + } ++ + } + + @Override +@@ -160,9 +158,7 @@ + } + + @Override +- public SpawnGroupData finalizeSpawn( +- ServerLevelAccessor level, DifficultyInstance difficulty, MobSpawnType reason, @Nullable SpawnGroupData spawnData, @Nullable CompoundTag dataTag +- ) { ++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) { + this.anchorPoint = this.blockPosition().above(5); + this.setPhantomSize(0); + return super.finalizeSpawn(level, difficulty, reason, spawnData, dataTag); +@@ -213,8 +209,8 @@ + } + + @Override +- public MobType getMobType() { +- return MobType.UNDEAD; ++ public EnumMonsterType getMobType() { ++ return EnumMonsterType.UNDEAD; + } + + @Override +@@ -228,15 +224,16 @@ + } + + @Override +- public EntityDimensions getDimensions(Pose pose) { +- int phantomSize = this.getPhantomSize(); +- EntityDimensions entityDimensions = super.getDimensions(pose); +- return entityDimensions.scale(1.0F + 0.15F * (float)phantomSize); ++ public EntityDimensions getDimensions(EntityPose pose) { ++ int i = this.getPhantomSize(); ++ EntityDimensions entitysize = super.getDimensions(pose); ++ ++ return entitysize.scale(1.0F + 0.15F * (float) i); + } + + @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entityDimensions, float f) { +- return new Vector3f(0.0F, entityDimensions.height * 0.675F, 0.0F); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ return new Vector3f(0.0F, entitysize.height * 0.675F, 0.0F); + } + + @Override +@@ -244,53 +241,102 @@ + return -0.125F; + } + +- static enum AttackPhase { +- CIRCLE, +- SWOOP; ++ private static enum AttackPhase { ++ ++ CIRCLE, SWOOP; ++ ++ private AttackPhase() {} + } + +- class PhantomAttackPlayerTargetGoal extends Goal { +- private final TargetingConditions attackTargeting = TargetingConditions.forCombat().range(64.0); +- private int nextScanTick = reducedTickDelay(20); ++ private class PhantomMoveControl extends MoveControl { + ++ private float speed = 0.1F; ++ ++ public PhantomMoveControl(Mob mob) { ++ super(mob); ++ } ++ + @Override +- public boolean canUse() { +- if (this.nextScanTick > 0) { +- this.nextScanTick--; +- return false; +- } else { +- this.nextScanTick = reducedTickDelay(60); +- List<Player> nearbyPlayers = Phantom.this.level() +- .getNearbyPlayers(this.attackTargeting, Phantom.this, Phantom.this.getBoundingBox().inflate(16.0, 64.0, 16.0)); +- if (!nearbyPlayers.isEmpty()) { +- nearbyPlayers.sort(Comparator.<Player, Double>comparing(Entity::getY).reversed()); ++ public void tick() { ++ if (Phantom.this.horizontalCollision) { ++ Phantom.this.setYRot(Phantom.this.getYRot() + 180.0F); ++ this.speed = 0.1F; ++ } + +- for (Player player : nearbyPlayers) { +- if (Phantom.this.canAttack(player, TargetingConditions.DEFAULT)) { +- Phantom.this.setTarget(player); +- return true; +- } +- } ++ double d0 = Phantom.this.moveTargetPoint.x - Phantom.this.getX(); ++ double d1 = Phantom.this.moveTargetPoint.y - Phantom.this.getY(); ++ double d2 = Phantom.this.moveTargetPoint.z - Phantom.this.getZ(); ++ double d3 = Math.sqrt(d0 * d0 + d2 * d2); ++ ++ if (Math.abs(d3) > 9.999999747378752E-6D) { ++ double d4 = 1.0D - Math.abs(d1 * 0.699999988079071D) / d3; ++ ++ d0 *= d4; ++ d2 *= d4; ++ d3 = Math.sqrt(d0 * d0 + d2 * d2); ++ double d5 = Math.sqrt(d0 * d0 + d2 * d2 + d1 * d1); ++ float f = Phantom.this.getYRot(); ++ float f1 = (float) Mth.atan2(d2, d0); ++ float f2 = Mth.wrapDegrees(Phantom.this.getYRot() + 90.0F); ++ float f3 = Mth.wrapDegrees(f1 * 57.295776F); ++ ++ Phantom.this.setYRot(Mth.approachDegrees(f2, f3, 4.0F) - 90.0F); ++ Phantom.this.yBodyRot = Phantom.this.getYRot(); ++ if (Mth.degreesDifferenceAbs(f, Phantom.this.getYRot()) < 3.0F) { ++ this.speed = Mth.approach(this.speed, 1.8F, 0.005F * (1.8F / this.speed)); ++ } else { ++ this.speed = Mth.approach(this.speed, 0.2F, 0.025F); + } + +- return false; ++ float f4 = (float) (-(Mth.atan2(-d1, d3) * 57.2957763671875D)); ++ ++ Phantom.this.setXRot(f4); ++ float f5 = Phantom.this.getYRot() + 90.0F; ++ double d6 = (double) (this.speed * Mth.cos(f5 * 0.017453292F)) * Math.abs(d0 / d5); ++ double d7 = (double) (this.speed * Mth.sin(f5 * 0.017453292F)) * Math.abs(d2 / d5); ++ double d8 = (double) (this.speed * Mth.sin(f4 * 0.017453292F)) * Math.abs(d1 / d5); ++ Vec3 vec3d = Phantom.this.getDeltaMovement(); ++ ++ Phantom.this.setDeltaMovement(vec3d.add((new Vec3(d6, d8, d7)).subtract(vec3d).scale(0.2D))); + } ++ + } ++ } + ++ private class PhantomLookControl extends LookControl { ++ ++ public PhantomLookControl(Mob mob) { ++ super(mob); ++ } ++ + @Override +- public boolean canContinueToUse() { +- LivingEntity target = Phantom.this.getTarget(); +- return target != null && Phantom.this.canAttack(target, TargetingConditions.DEFAULT); ++ public void tick() {} ++ } ++ ++ private class PhantomBodyRotationControl extends BodyRotationControl { ++ ++ public PhantomBodyRotationControl(Mob mob) { ++ super(mob); + } ++ ++ @Override ++ public void clientTick() { ++ Phantom.this.yHeadRot = Phantom.this.yBodyRot; ++ Phantom.this.yBodyRot = Phantom.this.getYRot(); ++ } + } + +- class PhantomAttackStrategyGoal extends Goal { ++ private class PhantomAttackStrategyGoal extends Goal { ++ + private int nextSweepTick; + ++ PhantomAttackStrategyGoal() {} ++ + @Override + public boolean canUse() { +- LivingEntity target = Phantom.this.getTarget(); +- return target != null && Phantom.this.canAttack(target, TargetingConditions.DEFAULT); ++ LivingEntity entityliving = Phantom.this.getTarget(); ++ ++ return entityliving != null ? Phantom.this.canAttack(entityliving, TargetingConditions.DEFAULT) : false; + } + + @Override +@@ -302,15 +348,13 @@ + + @Override + public void stop() { +- Phantom.this.anchorPoint = Phantom.this.level() +- .getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, Phantom.this.anchorPoint) +- .above(10 + Phantom.this.random.nextInt(20)); ++ Phantom.this.anchorPoint = Phantom.this.level().getHeightmapPos(Heightmap.Types.MOTION_BLOCKING, Phantom.this.anchorPoint).above(10 + Phantom.this.random.nextInt(20)); + } + + @Override + public void tick() { + if (Phantom.this.attackPhase == Phantom.AttackPhase.CIRCLE) { +- this.nextSweepTick--; ++ --this.nextSweepTick; + if (this.nextSweepTick <= 0) { + Phantom.this.attackPhase = Phantom.AttackPhase.SWOOP; + this.setAnchorAboveTarget(); +@@ -318,36 +362,112 @@ + Phantom.this.playSound(SoundEvents.PHANTOM_SWOOP, 10.0F, 0.95F + Phantom.this.random.nextFloat() * 0.1F); + } + } ++ + } + + private void setAnchorAboveTarget() { + Phantom.this.anchorPoint = Phantom.this.getTarget().blockPosition().above(20 + Phantom.this.random.nextInt(20)); + if (Phantom.this.anchorPoint.getY() < Phantom.this.level().getSeaLevel()) { +- Phantom.this.anchorPoint = new BlockPos( +- Phantom.this.anchorPoint.getX(), Phantom.this.level().getSeaLevel() + 1, Phantom.this.anchorPoint.getZ() +- ); ++ Phantom.this.anchorPoint = new BlockPos(Phantom.this.anchorPoint.getX(), Phantom.this.level().getSeaLevel() + 1, Phantom.this.anchorPoint.getZ()); + } ++ + } + } + +- class PhantomBodyRotationControl extends BodyRotationControl { +- public PhantomBodyRotationControl(Mob mob) { +- super(mob); ++ private class PhantomSweepAttackGoal extends Phantom.h { ++ ++ private static final int CAT_SEARCH_TICK_DELAY = 20; ++ private boolean isScaredOfCat; ++ private int catSearchTick; ++ ++ PhantomSweepAttackGoal() { ++ super(); + } + + @Override +- public void clientTick() { +- Phantom.this.yHeadRot = Phantom.this.yBodyRot; +- Phantom.this.yBodyRot = Phantom.this.getYRot(); ++ public boolean canUse() { ++ return Phantom.this.getTarget() != null && Phantom.this.attackPhase == Phantom.AttackPhase.SWOOP; + } ++ ++ @Override ++ public boolean canContinueToUse() { ++ LivingEntity entityliving = Phantom.this.getTarget(); ++ ++ if (entityliving == null) { ++ return false; ++ } else if (!entityliving.isAlive()) { ++ return false; ++ } else { ++ if (entityliving instanceof Player) { ++ Player entityhuman = (Player) entityliving; ++ ++ if (entityliving.isSpectator() || entityhuman.isCreative()) { ++ return false; ++ } ++ } ++ ++ if (!this.canUse()) { ++ return false; ++ } else { ++ if (Phantom.this.tickCount > this.catSearchTick) { ++ this.catSearchTick = Phantom.this.tickCount + 20; ++ List<Cat> list = Phantom.this.level().getEntitiesOfClass(Cat.class, Phantom.this.getBoundingBox().inflate(16.0D), EntitySelector.ENTITY_STILL_ALIVE); ++ Iterator iterator = list.iterator(); ++ ++ while (iterator.hasNext()) { ++ Cat entitycat = (Cat) iterator.next(); ++ ++ entitycat.hiss(); ++ } ++ ++ this.isScaredOfCat = !list.isEmpty(); ++ } ++ ++ return !this.isScaredOfCat; ++ } ++ } ++ } ++ ++ @Override ++ public void start() {} ++ ++ @Override ++ public void stop() { ++ Phantom.this.setTarget((LivingEntity) null); ++ Phantom.this.attackPhase = Phantom.AttackPhase.CIRCLE; ++ } ++ ++ @Override ++ public void tick() { ++ LivingEntity entityliving = Phantom.this.getTarget(); ++ ++ if (entityliving != null) { ++ Phantom.this.moveTargetPoint = new Vec3(entityliving.getX(), entityliving.getY(0.5D), entityliving.getZ()); ++ if (Phantom.this.getBoundingBox().inflate(0.20000000298023224D).intersects(entityliving.getBoundingBox())) { ++ Phantom.this.doHurtTarget(entityliving); ++ Phantom.this.attackPhase = Phantom.AttackPhase.CIRCLE; ++ if (!Phantom.this.isSilent()) { ++ Phantom.this.level().levelEvent(1039, Phantom.this.blockPosition(), 0); ++ } ++ } else if (Phantom.this.horizontalCollision || Phantom.this.hurtTime > 0) { ++ Phantom.this.attackPhase = Phantom.AttackPhase.CIRCLE; ++ } ++ ++ } ++ } + } + +- class PhantomCircleAroundAnchorGoal extends Phantom.PhantomMoveTargetGoal { ++ private class PhantomCircleAroundAnchorGoal extends Phantom.h { ++ + private float angle; + private float distance; + private float height; + private float clockwise; + ++ PhantomCircleAroundAnchorGoal() { ++ super(); ++ } ++ + @Override + public boolean canUse() { + return Phantom.this.getTarget() == null || Phantom.this.attackPhase == Phantom.AttackPhase.CIRCLE; +@@ -368,7 +488,7 @@ + } + + if (Phantom.this.random.nextInt(this.adjustedTickDelay(250)) == 0) { +- this.distance++; ++ ++this.distance; + if (this.distance > 15.0F) { + this.distance = 5.0F; + this.clockwise = -this.clockwise; +@@ -376,7 +496,7 @@ + } + + if (Phantom.this.random.nextInt(this.adjustedTickDelay(450)) == 0) { +- this.angle = Phantom.this.random.nextFloat() * 2.0F * (float) Math.PI; ++ this.angle = Phantom.this.random.nextFloat() * 2.0F * 3.1415927F; + this.selectNext(); + } + +@@ -393,6 +513,7 @@ + this.height = Math.min(-1.0F, this.height); + this.selectNext(); + } ++ + } + + private void selectNext() { +@@ -400,147 +521,61 @@ + Phantom.this.anchorPoint = Phantom.this.blockPosition(); + } + +- this.angle = this.angle + this.clockwise * 15.0F * (float) (Math.PI / 180.0); +- Phantom.this.moveTargetPoint = Vec3.atLowerCornerOf(Phantom.this.anchorPoint) +- .add((double)(this.distance * Mth.cos(this.angle)), (double)(-4.0F + this.height), (double)(this.distance * Mth.sin(this.angle))); ++ this.angle += this.clockwise * 15.0F * 0.017453292F; ++ Phantom.this.moveTargetPoint = Vec3.atLowerCornerOf(Phantom.this.anchorPoint).add((double) (this.distance * Mth.cos(this.angle)), (double) (-4.0F + this.height), (double) (this.distance * Mth.sin(this.angle))); + } + } + +- class PhantomLookControl extends LookControl { +- public PhantomLookControl(Mob mob) { +- super(mob); +- } ++ private class PhantomAttackPlayerTargetGoal extends Goal { + +- @Override +- public void tick() { +- } +- } ++ private final TargetingConditions attackTargeting = TargetingConditions.forCombat().range(64.0D); ++ private int nextScanTick = reducedTickDelay(20); + +- class PhantomMoveControl extends MoveControl { +- private float speed = 0.1F; ++ PhantomAttackPlayerTargetGoal() {} + +- public PhantomMoveControl(Mob mob) { +- super(mob); +- } +- + @Override +- public void tick() { +- if (Phantom.this.horizontalCollision) { +- Phantom.this.setYRot(Phantom.this.getYRot() + 180.0F); +- this.speed = 0.1F; +- } +- +- double d = Phantom.this.moveTargetPoint.x - Phantom.this.getX(); +- double d1 = Phantom.this.moveTargetPoint.y - Phantom.this.getY(); +- double d2 = Phantom.this.moveTargetPoint.z - Phantom.this.getZ(); +- double squareRoot = Math.sqrt(d * d + d2 * d2); +- if (Math.abs(squareRoot) > 1.0E-5F) { +- double d3 = 1.0 - Math.abs(d1 * 0.7F) / squareRoot; +- double var26 = d * d3; +- double var27 = d2 * d3; +- squareRoot = Math.sqrt(var26 * var26 + var27 * var27); +- double squareRoot1 = Math.sqrt(var26 * var26 + var27 * var27 + d1 * d1); +- float yRot = Phantom.this.getYRot(); +- float f = (float)Mth.atan2(var27, var26); +- float f1 = Mth.wrapDegrees(Phantom.this.getYRot() + 90.0F); +- float f2 = Mth.wrapDegrees(f * (180.0F / (float)Math.PI)); +- Phantom.this.setYRot(Mth.approachDegrees(f1, f2, 4.0F) - 90.0F); +- Phantom.this.yBodyRot = Phantom.this.getYRot(); +- if (Mth.degreesDifferenceAbs(yRot, Phantom.this.getYRot()) < 3.0F) { +- this.speed = Mth.approach(this.speed, 1.8F, 0.005F * (1.8F / this.speed)); +- } else { +- this.speed = Mth.approach(this.speed, 0.2F, 0.025F); +- } +- +- float f3 = (float)(-(Mth.atan2(-d1, squareRoot) * 180.0F / (float)Math.PI)); +- Phantom.this.setXRot(f3); +- float f4 = Phantom.this.getYRot() + 90.0F; +- double d4 = (double)(this.speed * Mth.cos(f4 * (float) (Math.PI / 180.0))) * Math.abs(var26 / squareRoot1); +- double d5 = (double)(this.speed * Mth.sin(f4 * (float) (Math.PI / 180.0))) * Math.abs(var27 / squareRoot1); +- double d6 = (double)(this.speed * Mth.sin(f3 * (float) (Math.PI / 180.0))) * Math.abs(d1 / squareRoot1); +- Vec3 deltaMovement = Phantom.this.getDeltaMovement(); +- Phantom.this.setDeltaMovement(deltaMovement.add(new Vec3(d4, d6, d5).subtract(deltaMovement).scale(0.2))); +- } +- } +- } +- +- abstract class PhantomMoveTargetGoal extends Goal { +- public PhantomMoveTargetGoal() { +- this.setFlags(EnumSet.of(Goal.Flag.MOVE)); +- } +- +- protected boolean touchingTarget() { +- return Phantom.this.moveTargetPoint.distanceToSqr(Phantom.this.getX(), Phantom.this.getY(), Phantom.this.getZ()) < 4.0; +- } +- } +- +- class PhantomSweepAttackGoal extends Phantom.PhantomMoveTargetGoal { +- private static final int CAT_SEARCH_TICK_DELAY = 20; +- private boolean isScaredOfCat; +- private int catSearchTick; +- +- @Override + public boolean canUse() { +- return Phantom.this.getTarget() != null && Phantom.this.attackPhase == Phantom.AttackPhase.SWOOP; +- } +- +- @Override +- public boolean canContinueToUse() { +- LivingEntity target = Phantom.this.getTarget(); +- if (target == null) { ++ if (this.nextScanTick > 0) { ++ --this.nextScanTick; + return false; +- } else if (!target.isAlive()) { +- return false; + } else { +- if (target instanceof Player player && (target.isSpectator() || player.isCreative())) { +- return false; +- } ++ this.nextScanTick = reducedTickDelay(60); ++ List<Player> list = Phantom.this.level().getNearbyPlayers(this.attackTargeting, Phantom.this, Phantom.this.getBoundingBox().inflate(16.0D, 64.0D, 16.0D)); + +- if (!this.canUse()) { +- return false; +- } else { +- if (Phantom.this.tickCount > this.catSearchTick) { +- this.catSearchTick = Phantom.this.tickCount + 20; +- List<Cat> entitiesOfClass = Phantom.this.level() +- .getEntitiesOfClass(Cat.class, Phantom.this.getBoundingBox().inflate(16.0), EntitySelector.ENTITY_STILL_ALIVE); ++ if (!list.isEmpty()) { ++ list.sort(Comparator.comparing((Entity e) -> { return e.getY(); }).reversed()); // CraftBukkit - decompile error ++ Iterator iterator = list.iterator(); + +- for (Cat cat : entitiesOfClass) { +- cat.hiss(); +- } ++ while (iterator.hasNext()) { ++ Player entityhuman = (Player) iterator.next(); + +- this.isScaredOfCat = !entitiesOfClass.isEmpty(); ++ if (Phantom.this.canAttack(entityhuman, TargetingConditions.DEFAULT)) { ++ Phantom.this.setTarget(entityhuman, org.bukkit.event.entity.EntityTargetEvent.TargetReason.CLOSEST_PLAYER, true); // CraftBukkit - reason ++ return true; ++ } + } +- +- return !this.isScaredOfCat; + } ++ ++ return false; + } + } + + @Override +- public void start() { ++ public boolean canContinueToUse() { ++ LivingEntity entityliving = Phantom.this.getTarget(); ++ ++ return entityliving != null ? Phantom.this.canAttack(entityliving, TargetingConditions.DEFAULT) : false; + } ++ } + +- @Override +- public void stop() { +- Phantom.this.setTarget(null); +- Phantom.this.attackPhase = Phantom.AttackPhase.CIRCLE; ++ private abstract class h extends Goal { ++ ++ public h() { ++ this.setFlags(EnumSet.of(Goal.Type.MOVE)); + } + +- @Override +- public void tick() { +- LivingEntity target = Phantom.this.getTarget(); +- if (target != null) { +- Phantom.this.moveTargetPoint = new Vec3(target.getX(), target.getY(0.5), target.getZ()); +- if (Phantom.this.getBoundingBox().inflate(0.2F).intersects(target.getBoundingBox())) { +- Phantom.this.doHurtTarget(target); +- Phantom.this.attackPhase = Phantom.AttackPhase.CIRCLE; +- if (!Phantom.this.isSilent()) { +- Phantom.this.level().levelEvent(1039, Phantom.this.blockPosition(), 0); +- } +- } else if (Phantom.this.horizontalCollision || Phantom.this.hurtTime > 0) { +- Phantom.this.attackPhase = Phantom.AttackPhase.CIRCLE; +- } +- } ++ protected boolean touchingTarget() { ++ return Phantom.this.moveTargetPoint.distanceToSqr(Phantom.this.getX(), Phantom.this.getY(), Phantom.this.getZ()) < 4.0D; + } + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Ravager.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Ravager.java.patch new file mode 100644 index 0000000000..2819d9219e --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Ravager.java.patch @@ -0,0 +1,313 @@ +--- a/net/minecraft/world/entity/monster/Ravager.java ++++ b/net/minecraft/world/entity/monster/Ravager.java +@@ -1,5 +1,7 @@ + package net.minecraft.world.entity.monster; + ++import java.util.Iterator; ++import java.util.List; + import java.util.function.Predicate; + import javax.annotation.Nullable; + import net.minecraft.core.BlockPos; +@@ -34,21 +36,28 @@ + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.LeavesBlock; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.level.pathfinder.BlockPathTypes; + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.Vec3; + import org.joml.Vector3f; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end ++ + public class Ravager extends Raider { +- private static final Predicate<Entity> NO_RAVAGER_AND_ALIVE = entity -> entity.isAlive() && !(entity instanceof Ravager); +- private static final double BASE_MOVEMENT_SPEED = 0.3; +- private static final double ATTACK_MOVEMENT_SPEED = 0.35; ++ ++ private static final Predicate<Entity> NO_RAVAGER_AND_ALIVE = (entity) -> { ++ return entity.isAlive() && !(entity instanceof Ravager); ++ }; ++ private static final double BASE_MOVEMENT_SPEED = 0.3D; ++ private static final double ATTACK_MOVEMENT_SPEED = 0.35D; + private static final int STUNNED_COLOR = 8356754; +- private static final double STUNNED_COLOR_BLUE = 0.5725490196078431; +- private static final double STUNNED_COLOR_GREEN = 0.5137254901960784; +- private static final double STUNNED_COLOR_RED = 0.4980392156862745; ++ private static final double STUNNED_COLOR_BLUE = 0.5725490196078431D; ++ private static final double STUNNED_COLOR_GREEN = 0.5137254901960784D; ++ private static final double STUNNED_COLOR_RED = 0.4980392156862745D; + private static final int ATTACK_DURATION = 10; + public static final int STUN_DURATION = 40; + private int attackTick; +@@ -66,13 +75,15 @@ + protected void registerGoals() { + super.registerGoals(); + this.goalSelector.addGoal(0, new FloatGoal(this)); +- this.goalSelector.addGoal(4, new MeleeAttackGoal(this, 1.0, true)); +- this.goalSelector.addGoal(5, new WaterAvoidingRandomStrollGoal(this, 0.4)); ++ this.goalSelector.addGoal(4, new MeleeAttackGoal(this, 1.0D, true)); ++ this.goalSelector.addGoal(5, new WaterAvoidingRandomStrollGoal(this, 0.4D)); + this.goalSelector.addGoal(6, new LookAtPlayerGoal(this, Player.class, 6.0F)); + this.goalSelector.addGoal(10, new LookAtPlayerGoal(this, Mob.class, 8.0F)); +- this.targetSelector.addGoal(2, new HurtByTargetGoal(this, Raider.class).setAlertOthers()); ++ this.targetSelector.addGoal(2, (new HurtByTargetGoal(this, new Class[]{Raider.class})).setAlertOthers()); + this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, Player.class, true)); +- this.targetSelector.addGoal(4, new NearestAttackableTargetGoal<>(this, AbstractVillager.class, true, entity -> !entity.isBaby())); ++ this.targetSelector.addGoal(4, new NearestAttackableTargetGoal<>(this, AbstractVillager.class, true, (entityliving) -> { ++ return !entityliving.isBaby(); ++ })); + this.targetSelector.addGoal(4, new NearestAttackableTargetGoal<>(this, IronGolem.class, true)); + } + +@@ -80,20 +91,15 @@ + protected void updateControlFlags() { + boolean flag = !(this.getControllingPassenger() instanceof Mob) || this.getControllingPassenger().getType().is(EntityTypeTags.RAIDERS); + boolean flag1 = !(this.getVehicle() instanceof Boat); +- this.goalSelector.setControlFlag(Goal.Flag.MOVE, flag); +- this.goalSelector.setControlFlag(Goal.Flag.JUMP, flag && flag1); +- this.goalSelector.setControlFlag(Goal.Flag.LOOK, flag); +- this.goalSelector.setControlFlag(Goal.Flag.TARGET, flag); ++ ++ this.goalSelector.setControlFlag(Goal.Type.MOVE, flag); ++ this.goalSelector.setControlFlag(Goal.Type.JUMP, flag && flag1); ++ this.goalSelector.setControlFlag(Goal.Type.LOOK, flag); ++ this.goalSelector.setControlFlag(Goal.Type.TARGET, flag); + } + + public static AttributeSupplier.Builder createAttributes() { +- return Monster.createMonsterAttributes() +- .add(Attributes.MAX_HEALTH, 100.0) +- .add(Attributes.MOVEMENT_SPEED, 0.3) +- .add(Attributes.KNOCKBACK_RESISTANCE, 0.75) +- .add(Attributes.ATTACK_DAMAGE, 12.0) +- .add(Attributes.ATTACK_KNOCKBACK, 1.5) +- .add(Attributes.FOLLOW_RANGE, 32.0); ++ return Monster.createMonsterAttributes().add(Attributes.MAX_HEALTH, 100.0D).add(Attributes.MOVEMENT_SPEED, 0.3D).add(Attributes.KNOCKBACK_RESISTANCE, 0.75D).add(Attributes.ATTACK_DAMAGE, 12.0D).add(Attributes.ATTACK_KNOCKBACK, 1.5D).add(Attributes.FOLLOW_RANGE, 32.0D); + } + + @Override +@@ -123,8 +129,8 @@ + } + + @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entityDimensions, float f) { +- return new Vector3f(0.0F, entityDimensions.height + 0.0625F * f, -0.0625F * f); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ return new Vector3f(0.0F, entitysize.height + 0.0625F * f, -0.0625F * f); + } + + @Override +@@ -132,24 +138,31 @@ + super.aiStep(); + if (this.isAlive()) { + if (this.isImmobile()) { +- this.getAttribute(Attributes.MOVEMENT_SPEED).setBaseValue(0.0); ++ this.getAttribute(Attributes.MOVEMENT_SPEED).setBaseValue(0.0D); + } else { +- double d = this.getTarget() != null ? 0.35 : 0.3; +- double baseValue = this.getAttribute(Attributes.MOVEMENT_SPEED).getBaseValue(); +- this.getAttribute(Attributes.MOVEMENT_SPEED).setBaseValue(Mth.lerp(0.1, baseValue, d)); ++ double d0 = this.getTarget() != null ? 0.35D : 0.3D; ++ double d1 = this.getAttribute(Attributes.MOVEMENT_SPEED).getBaseValue(); ++ ++ this.getAttribute(Attributes.MOVEMENT_SPEED).setBaseValue(Mth.lerp(0.1D, d1, d0)); + } + + if (this.horizontalCollision && this.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { + boolean flag = false; +- AABB aABB = this.getBoundingBox().inflate(0.2); ++ AABB axisalignedbb = this.getBoundingBox().inflate(0.2D); ++ Iterator iterator = BlockPos.betweenClosed(Mth.floor(axisalignedbb.minX), Mth.floor(axisalignedbb.minY), Mth.floor(axisalignedbb.minZ), Mth.floor(axisalignedbb.maxX), Mth.floor(axisalignedbb.maxY), Mth.floor(axisalignedbb.maxZ)).iterator(); + +- for (BlockPos blockPos : BlockPos.betweenClosed( +- Mth.floor(aABB.minX), Mth.floor(aABB.minY), Mth.floor(aABB.minZ), Mth.floor(aABB.maxX), Mth.floor(aABB.maxY), Mth.floor(aABB.maxZ) +- )) { +- BlockState blockState = this.level().getBlockState(blockPos); +- Block block = blockState.getBlock(); ++ while (iterator.hasNext()) { ++ BlockPos blockposition = (BlockPos) iterator.next(); ++ IBlockData iblockdata = this.level().getBlockState(blockposition); ++ Block block = iblockdata.getBlock(); ++ + if (block instanceof LeavesBlock) { +- flag = this.level().destroyBlock(blockPos, true, this) || flag; ++ // CraftBukkit start ++ if (!CraftEventFactory.callEntityChangeBlockEvent(this, blockposition, net.minecraft.world.level.block.Blocks.AIR.defaultBlockState())) { ++ continue; ++ } ++ // CraftBukkit end ++ flag = this.level().destroyBlock(blockposition, true, this) || flag; + } + } + +@@ -159,38 +172,37 @@ + } + + if (this.roarTick > 0) { +- this.roarTick--; ++ --this.roarTick; + if (this.roarTick == 10) { + this.roar(); + } + } + + if (this.attackTick > 0) { +- this.attackTick--; ++ --this.attackTick; + } + + if (this.stunnedTick > 0) { +- this.stunnedTick--; ++ --this.stunnedTick; + this.stunEffect(); + if (this.stunnedTick == 0) { + this.playSound(SoundEvents.RAVAGER_ROAR, 1.0F, 1.0F); + this.roarTick = 20; + } + } ++ + } + } + + private void stunEffect() { + if (this.random.nextInt(6) == 0) { +- double d = this.getX() +- - (double)this.getBbWidth() * Math.sin((double)(this.yBodyRot * (float) (Math.PI / 180.0))) +- + (this.random.nextDouble() * 0.6 - 0.3); +- double d1 = this.getY() + (double)this.getBbHeight() - 0.3; +- double d2 = this.getZ() +- + (double)this.getBbWidth() * Math.cos((double)(this.yBodyRot * (float) (Math.PI / 180.0))) +- + (this.random.nextDouble() * 0.6 - 0.3); +- this.level().addParticle(ParticleTypes.ENTITY_EFFECT, d, d1, d2, 0.4980392156862745, 0.5137254901960784, 0.5725490196078431); ++ double d0 = this.getX() - (double) this.getBbWidth() * Math.sin((double) (this.yBodyRot * 0.017453292F)) + (this.random.nextDouble() * 0.6D - 0.3D); ++ double d1 = this.getY() + (double) this.getBbHeight() - 0.3D; ++ double d2 = this.getZ() + (double) this.getBbWidth() * Math.cos((double) (this.yBodyRot * 0.017453292F)) + (this.random.nextDouble() * 0.6D - 0.3D); ++ ++ this.level().addParticle(ParticleTypes.ENTITY_EFFECT, d0, d1, d2, 0.4980392156862745D, 0.5137254901960784D, 0.5725490196078431D); + } ++ + } + + @Override +@@ -200,16 +212,16 @@ + + @Override + public boolean hasLineOfSight(Entity entity) { +- return this.stunnedTick <= 0 && this.roarTick <= 0 && super.hasLineOfSight(entity); ++ return this.stunnedTick <= 0 && this.roarTick <= 0 ? super.hasLineOfSight(entity) : false; + } + + @Override + protected void blockedByShield(LivingEntity entity) { + if (this.roarTick == 0) { +- if (this.random.nextDouble() < 0.5) { ++ if (this.random.nextDouble() < 0.5D) { + this.stunnedTick = 40; + this.playSound(SoundEvents.RAVAGER_STUNNED, 1.0F, 1.0F); +- this.level().broadcastEntityEvent(this, (byte)39); ++ this.level().broadcastEntityEvent(this, (byte) 39); + entity.push(this); + } else { + this.strongKnockback(entity); +@@ -217,36 +229,43 @@ + + entity.hurtMarked = true; + } ++ + } + + private void roar() { + if (this.isAlive()) { +- for (LivingEntity livingEntity : this.level().getEntitiesOfClass(LivingEntity.class, this.getBoundingBox().inflate(4.0), NO_RAVAGER_AND_ALIVE)) { +- if (!(livingEntity instanceof AbstractIllager)) { +- livingEntity.hurt(this.damageSources().mobAttack(this), 6.0F); +- } ++ List<? extends LivingEntity> list = this.level().getEntitiesOfClass(LivingEntity.class, this.getBoundingBox().inflate(4.0D), Ravager.NO_RAVAGER_AND_ALIVE); + +- this.strongKnockback(livingEntity); ++ LivingEntity entityliving; ++ ++ for (Iterator iterator = list.iterator(); iterator.hasNext(); this.strongKnockback(entityliving)) { ++ entityliving = (LivingEntity) iterator.next(); ++ if (!(entityliving instanceof AbstractIllager)) { ++ entityliving.hurt(this.damageSources().mobAttack(this), 6.0F); ++ } + } + +- Vec3 center = this.getBoundingBox().getCenter(); ++ Vec3 vec3d = this.getBoundingBox().getCenter(); + +- for (int i = 0; i < 40; i++) { +- double d = this.random.nextGaussian() * 0.2; +- double d1 = this.random.nextGaussian() * 0.2; +- double d2 = this.random.nextGaussian() * 0.2; +- this.level().addParticle(ParticleTypes.POOF, center.x, center.y, center.z, d, d1, d2); ++ for (int i = 0; i < 40; ++i) { ++ double d0 = this.random.nextGaussian() * 0.2D; ++ double d1 = this.random.nextGaussian() * 0.2D; ++ double d2 = this.random.nextGaussian() * 0.2D; ++ ++ this.level().addParticle(ParticleTypes.POOF, vec3d.x, vec3d.y, vec3d.z, d0, d1, d2); + } + + this.gameEvent(GameEvent.ENTITY_ACTION); + } ++ + } + + private void strongKnockback(Entity entity) { +- double d = entity.getX() - this.getX(); ++ double d0 = entity.getX() - this.getX(); + double d1 = entity.getZ() - this.getZ(); +- double max = Math.max(d * d + d1 * d1, 0.001); +- entity.push(d / max * 4.0, 0.2, d1 / max * 4.0); ++ double d2 = Math.max(d0 * d0 + d1 * d1, 0.001D); ++ ++ entity.push(d0 / d2 * 4.0D, 0.2D, d1 / d2 * 4.0D); + } + + @Override +@@ -276,7 +295,7 @@ + @Override + public boolean doHurtTarget(Entity entity) { + this.attackTick = 10; +- this.level().broadcastEntityEvent(this, (byte)4); ++ this.level().broadcastEntityEvent(this, (byte) 4); + this.playSound(SoundEvents.RAVAGER_ATTACK, 1.0F, 1.0F); + return super.doHurtTarget(entity); + } +@@ -298,7 +317,7 @@ + } + + @Override +- protected void playStepSound(BlockPos pos, BlockState block) { ++ protected void playStepSound(BlockPos pos, IBlockData block) { + this.playSound(SoundEvents.RAVAGER_STEP, 0.15F, 1.0F); + } + +@@ -308,8 +327,7 @@ + } + + @Override +- public void applyRaidBuffs(int wave, boolean unusedFalse) { +- } ++ public void applyRaidBuffs(int wave, boolean unusedFalse) {} + + @Override + public boolean canBeLeader() { +@@ -318,7 +336,8 @@ + + @Override + protected AABB getAttackBoundingBox() { +- AABB aABB = super.getAttackBoundingBox(); +- return aABB.deflate(0.05, 0.0, 0.05); ++ AABB axisalignedbb = super.getAttackBoundingBox(); ++ ++ return axisalignedbb.deflate(0.05D, 0.0D, 0.05D); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Shulker.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Shulker.java.patch new file mode 100644 index 0000000000..109f273887 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Shulker.java.patch @@ -0,0 +1,853 @@ +--- a/net/minecraft/world/entity/monster/Shulker.java ++++ b/net/minecraft/world/entity/monster/Shulker.java +@@ -1,6 +1,8 @@ + package net.minecraft.world.entity.monster; + + import java.util.EnumSet; ++import java.util.Iterator; ++import java.util.List; + import java.util.Optional; + import java.util.UUID; + import javax.annotation.Nullable; +@@ -23,14 +25,14 @@ + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntitySelector; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.EnumMoveType; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.MoverType; +-import net.minecraft.world.entity.Pose; +-import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.VariantHolder; + import net.minecraft.world.entity.ai.attributes.AttributeModifier; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; +@@ -50,20 +52,26 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.ServerLevelAccessor; + import net.minecraft.world.level.block.Blocks; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; ++import net.minecraft.world.level.entity.EntityTypeTest; + import net.minecraft.world.level.gameevent.GameEvent; + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.Vec3; + import org.joml.Vector3f; + +-public class Shulker extends AbstractGolem implements VariantHolder<Optional<DyeColor>>, Enemy { ++// CraftBukkit start ++import org.bukkit.craftbukkit.util.CraftLocation; ++import org.bukkit.event.entity.EntityTeleportEvent; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end ++ ++public class Shulker extends AbstractGolem implements VariantHolder<Optional<DyeColor>>, IMonster { ++ + private static final UUID COVERED_ARMOR_MODIFIER_UUID = UUID.fromString("7E0292F2-9434-48D5-A29F-9583AF7DF27F"); +- private static final AttributeModifier COVERED_ARMOR_MODIFIER = new AttributeModifier( +- COVERED_ARMOR_MODIFIER_UUID, "Covered armor bonus", 20.0, AttributeModifier.Operation.ADDITION +- ); ++ private static final AttributeModifier COVERED_ARMOR_MODIFIER = new AttributeModifier(Shulker.COVERED_ARMOR_MODIFIER_UUID, "Covered armor bonus", 20.0D, AttributeModifier.Operation.ADDITION); + protected static final EntityDataAccessor<Direction> DATA_ATTACH_FACE_ID = SynchedEntityData.defineId(Shulker.class, EntityDataSerializers.DIRECTION); + protected static final EntityDataAccessor<Byte> DATA_PEEK_ID = SynchedEntityData.defineId(Shulker.class, EntityDataSerializers.BYTE); +- protected static final EntityDataAccessor<Byte> DATA_COLOR_ID = SynchedEntityData.defineId(Shulker.class, EntityDataSerializers.BYTE); ++ public static final EntityDataAccessor<Byte> DATA_COLOR_ID = SynchedEntityData.defineId(Shulker.class, EntityDataSerializers.BYTE); + private static final int TELEPORT_STEPS = 6; + private static final byte NO_COLOR = 16; + private static final byte DEFAULT_COLOR = 16; +@@ -71,9 +79,10 @@ + private static final int OTHER_SHULKER_SCAN_RADIUS = 8; + private static final int OTHER_SHULKER_LIMIT = 5; + private static final float PEEK_PER_TICK = 0.05F; +- static final Vector3f FORWARD = Util.make(() -> { +- Vec3i normal = Direction.SOUTH.getNormal(); +- return new Vector3f((float)normal.getX(), (float)normal.getY(), (float)normal.getZ()); ++ static final Vector3f FORWARD = (Vector3f) Util.make(() -> { ++ Vec3i baseblockposition = Direction.SOUTH.getNormal(); ++ ++ return new Vector3f((float) baseblockposition.getX(), (float) baseblockposition.getY(), (float) baseblockposition.getZ()); + }); + private float currentPeekAmountO; + private float currentPeekAmount; +@@ -94,7 +103,7 @@ + this.goalSelector.addGoal(4, new Shulker.ShulkerAttackGoal()); + this.goalSelector.addGoal(7, new Shulker.ShulkerPeekGoal()); + this.goalSelector.addGoal(8, new RandomLookAroundGoal(this)); +- this.targetSelector.addGoal(1, new HurtByTargetGoal(this, this.getClass()).setAlertOthers()); ++ this.targetSelector.addGoal(1, (new HurtByTargetGoal(this, new Class[]{this.getClass()})).setAlertOthers()); + this.targetSelector.addGoal(2, new Shulker.ShulkerNearestAttackGoal(this)); + this.targetSelector.addGoal(3, new Shulker.ShulkerDefenseAttackGoal(this)); + } +@@ -119,6 +128,7 @@ + if (!this.isClosed()) { + super.playAmbientSound(); + } ++ + } + + @Override +@@ -134,13 +144,13 @@ + @Override + protected void defineSynchedData() { + super.defineSynchedData(); +- this.entityData.define(DATA_ATTACH_FACE_ID, Direction.DOWN); +- this.entityData.define(DATA_PEEK_ID, (byte)0); +- this.entityData.define(DATA_COLOR_ID, (byte)16); ++ this.entityData.define(Shulker.DATA_ATTACH_FACE_ID, Direction.DOWN); ++ this.entityData.define(Shulker.DATA_PEEK_ID, (byte) 0); ++ this.entityData.define(Shulker.DATA_COLOR_ID, (byte) 16); + } + + public static AttributeSupplier.Builder createAttributes() { +- return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 30.0); ++ return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 30.0D); + } + + @Override +@@ -152,18 +162,19 @@ + public void readAdditionalSaveData(CompoundTag compound) { + super.readAdditionalSaveData(compound); + this.setAttachFace(Direction.from3DDataValue(compound.getByte("AttachFace"))); +- this.entityData.set(DATA_PEEK_ID, compound.getByte("Peek")); ++ this.entityData.set(Shulker.DATA_PEEK_ID, compound.getByte("Peek")); + if (compound.contains("Color", 99)) { +- this.entityData.set(DATA_COLOR_ID, compound.getByte("Color")); ++ this.entityData.set(Shulker.DATA_COLOR_ID, compound.getByte("Color")); + } ++ + } + + @Override + public void addAdditionalSaveData(CompoundTag compound) { + super.addAdditionalSaveData(compound); +- compound.putByte("AttachFace", (byte)this.getAttachFace().get3DDataValue()); +- compound.putByte("Peek", this.entityData.get(DATA_PEEK_ID)); +- compound.putByte("Color", this.entityData.get(DATA_COLOR_ID)); ++ compound.putByte("AttachFace", (byte) this.getAttachFace().get3DDataValue()); ++ compound.putByte("Peek", (Byte) this.entityData.get(Shulker.DATA_PEEK_ID)); ++ compound.putByte("Color", (Byte) this.entityData.get(Shulker.DATA_COLOR_ID)); + } + + @Override +@@ -179,37 +190,42 @@ + + if (this.level().isClientSide) { + if (this.clientSideTeleportInterpolation > 0) { +- this.clientSideTeleportInterpolation--; ++ --this.clientSideTeleportInterpolation; + } else { + this.clientOldAttachPosition = null; + } + } ++ + } + + private void findNewAttachment() { +- Direction direction = this.findAttachableSurface(this.blockPosition()); +- if (direction != null) { +- this.setAttachFace(direction); ++ Direction enumdirection = this.findAttachableSurface(this.blockPosition()); ++ ++ if (enumdirection != null) { ++ this.setAttachFace(enumdirection); + } else { + this.teleportSomewhere(); + } ++ + } + + @Override + protected AABB makeBoundingBox() { +- float physicalPeek = getPhysicalPeek(this.currentPeekAmount); +- Direction opposite = this.getAttachFace().getOpposite(); +- float f = this.getType().getWidth() / 2.0F; +- return getProgressAabb(opposite, physicalPeek).move(this.getX() - (double)f, this.getY(), this.getZ() - (double)f); ++ float f = getPhysicalPeek(this.currentPeekAmount); ++ Direction enumdirection = this.getAttachFace().getOpposite(); ++ float f1 = this.getType().getWidth() / 2.0F; ++ ++ return getProgressAabb(enumdirection, f).move(this.getX() - (double) f1, this.getY(), this.getZ() - (double) f1); + } + + private static float getPhysicalPeek(float peek) { +- return 0.5F - Mth.sin((0.5F + peek) * (float) Math.PI) * 0.5F; ++ return 0.5F - Mth.sin((0.5F + peek) * 3.1415927F) * 0.5F; + } + + private boolean updatePeekAmount() { + this.currentPeekAmountO = this.currentPeekAmount; +- float f = (float)this.getRawPeekAmount() * 0.01F; ++ float f = (float) this.getRawPeekAmount() * 0.01F; ++ + if (this.currentPeekAmount == f) { + return false; + } else { +@@ -225,24 +241,25 @@ + + private void onPeekAmountChange() { + this.reapplyPosition(); +- float physicalPeek = getPhysicalPeek(this.currentPeekAmount); +- float physicalPeek1 = getPhysicalPeek(this.currentPeekAmountO); +- Direction opposite = this.getAttachFace().getOpposite(); +- float f = physicalPeek - physicalPeek1; +- if (!(f <= 0.0F)) { +- for (Entity entity : this.level() +- .getEntities( +- this, +- getProgressDeltaAabb(opposite, physicalPeek1, physicalPeek).move(this.getX() - 0.5, this.getY(), this.getZ() - 0.5), +- EntitySelector.NO_SPECTATORS.and(entity1 -> !entity1.isPassengerOfSameVehicle(this)) +- )) { ++ float f = getPhysicalPeek(this.currentPeekAmount); ++ float f1 = getPhysicalPeek(this.currentPeekAmountO); ++ Direction enumdirection = this.getAttachFace().getOpposite(); ++ float f2 = f - f1; ++ ++ if (f2 > 0.0F) { ++ List<Entity> list = this.level().getEntities((Entity) this, getProgressDeltaAabb(enumdirection, f1, f).move(this.getX() - 0.5D, this.getY(), this.getZ() - 0.5D), EntitySelector.NO_SPECTATORS.and((entity) -> { ++ return !entity.isPassengerOfSameVehicle(this); ++ })); ++ Iterator iterator = list.iterator(); ++ ++ while (iterator.hasNext()) { ++ Entity entity = (Entity) iterator.next(); ++ + if (!(entity instanceof Shulker) && !entity.noPhysics) { +- entity.move( +- MoverType.SHULKER, +- new Vec3((double)(f * (float)opposite.getStepX()), (double)(f * (float)opposite.getStepY()), (double)(f * (float)opposite.getStepZ())) +- ); ++ entity.move(EnumMoveType.SHULKER, new Vec3((double) (f2 * (float) enumdirection.getStepX()), (double) (f2 * (float) enumdirection.getStepY()), (double) (f2 * (float) enumdirection.getStepZ()))); + } + } ++ + } + } + +@@ -251,11 +268,10 @@ + } + + public static AABB getProgressDeltaAabb(Direction direction, float delta, float deltaO) { +- double d = (double)Math.max(delta, deltaO); +- double d1 = (double)Math.min(delta, deltaO); +- return new AABB(BlockPos.ZERO) +- .expandTowards((double)direction.getStepX() * d, (double)direction.getStepY() * d, (double)direction.getStepZ() * d) +- .contract((double)(-direction.getStepX()) * (1.0 + d1), (double)(-direction.getStepY()) * (1.0 + d1), (double)(-direction.getStepZ()) * (1.0 + d1)); ++ double d0 = (double) Math.max(delta, deltaO); ++ double d1 = (double) Math.min(delta, deltaO); ++ ++ return (new AABB(BlockPos.ZERO)).expandTowards((double) direction.getStepX() * d0, (double) direction.getStepY() * d0, (double) direction.getStepZ() * d0).contract((double) (-direction.getStepX()) * (1.0D + d1), (double) (-direction.getStepY()) * (1.0D + d1), (double) (-direction.getStepZ()) * (1.0D + d1)); + } + + @Override +@@ -282,9 +298,7 @@ + + @Nullable + @Override +- public SpawnGroupData finalizeSpawn( +- ServerLevelAccessor level, DifficultyInstance difficulty, MobSpawnType reason, @Nullable SpawnGroupData spawnData, @Nullable CompoundTag dataTag +- ) { ++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) { + this.setYRot(0.0F); + this.yHeadRot = this.getYRot(); + this.setOldPosAndRot(); +@@ -292,12 +306,13 @@ + } + + @Override +- public void move(MoverType type, Vec3 pos) { +- if (type == MoverType.SHULKER_BOX) { ++ public void move(EnumMoveType type, Vec3 pos) { ++ if (type == EnumMoveType.SHULKER_BOX) { + this.teleportSomewhere(); + } else { + super.move(type, pos); + } ++ + } + + @Override +@@ -306,39 +321,46 @@ + } + + @Override +- public void setDeltaMovement(Vec3 deltaMovement) { +- } ++ public void setDeltaMovement(Vec3 deltaMovement) {} + + @Override +- public void setPos(double x, double y, double z) { +- BlockPos blockPos = this.blockPosition(); ++ public void setPos(double x, double d1, double y) { ++ BlockPos blockposition = this.blockPosition(); ++ + if (this.isPassenger()) { +- super.setPos(x, y, z); ++ super.setPos(x, d1, y); + } else { +- super.setPos((double)Mth.floor(x) + 0.5, (double)Mth.floor(y + 0.5), (double)Mth.floor(z) + 0.5); ++ super.setPos((double) Mth.floor(x) + 0.5D, (double) Mth.floor(d1 + 0.5D), (double) Mth.floor(y) + 0.5D); + } + + if (this.tickCount != 0) { +- BlockPos blockPos1 = this.blockPosition(); +- if (!blockPos1.equals(blockPos)) { +- this.entityData.set(DATA_PEEK_ID, (byte)0); ++ BlockPos blockposition1 = this.blockPosition(); ++ ++ if (!blockposition1.equals(blockposition)) { ++ this.entityData.set(Shulker.DATA_PEEK_ID, (byte) 0); + this.hasImpulse = true; +- if (this.level().isClientSide && !this.isPassenger() && !blockPos1.equals(this.clientOldAttachPosition)) { +- this.clientOldAttachPosition = blockPos; ++ if (this.level().isClientSide && !this.isPassenger() && !blockposition1.equals(this.clientOldAttachPosition)) { ++ this.clientOldAttachPosition = blockposition; + this.clientSideTeleportInterpolation = 6; + this.xOld = this.getX(); + this.yOld = this.getY(); + this.zOld = this.getZ(); + } + } ++ + } + } + + @Nullable + protected Direction findAttachableSurface(BlockPos pos) { +- for (Direction direction : Direction.values()) { +- if (this.canStayAt(pos, direction)) { +- return direction; ++ Direction[] aenumdirection = Direction.values(); ++ int i = aenumdirection.length; ++ ++ for (int j = 0; j < i; ++j) { ++ Direction enumdirection = aenumdirection[j]; ++ ++ if (this.canStayAt(pos, enumdirection)) { ++ return enumdirection; + } + } + +@@ -349,49 +371,56 @@ + if (this.isPositionBlocked(pos)) { + return false; + } else { +- Direction opposite = facing.getOpposite(); +- if (!this.level().loadedAndEntityCanStandOnFace(pos.relative(facing), this, opposite)) { ++ Direction enumdirection1 = facing.getOpposite(); ++ ++ if (!this.level().loadedAndEntityCanStandOnFace(pos.relative(facing), this, enumdirection1)) { + return false; + } else { +- AABB aABB = getProgressAabb(opposite, 1.0F).move(pos).deflate(1.0E-6); +- return this.level().noCollision(this, aABB); ++ AABB axisalignedbb = getProgressAabb(enumdirection1, 1.0F).move(pos).deflate(1.0E-6D); ++ ++ return this.level().noCollision(this, axisalignedbb); + } + } + } + + private boolean isPositionBlocked(BlockPos pos) { +- BlockState blockState = this.level().getBlockState(pos); +- if (blockState.isAir()) { ++ IBlockData iblockdata = this.level().getBlockState(pos); ++ ++ if (iblockdata.isAir()) { + return false; + } else { +- boolean flag = blockState.is(Blocks.MOVING_PISTON) && pos.equals(this.blockPosition()); ++ boolean flag = iblockdata.is(Blocks.MOVING_PISTON) && pos.equals(this.blockPosition()); ++ + return !flag; + } + } + + protected boolean teleportSomewhere() { + if (!this.isNoAi() && this.isAlive()) { +- BlockPos blockPos = this.blockPosition(); ++ BlockPos blockposition = this.blockPosition(); + +- for (int i = 0; i < 5; i++) { +- BlockPos blockPos1 = blockPos.offset( +- Mth.randomBetweenInclusive(this.random, -8, 8), +- Mth.randomBetweenInclusive(this.random, -8, 8), +- Mth.randomBetweenInclusive(this.random, -8, 8) +- ); +- if (blockPos1.getY() > this.level().getMinBuildHeight() +- && this.level().isEmptyBlock(blockPos1) +- && this.level().getWorldBorder().isWithinBounds(blockPos1) +- && this.level().noCollision(this, new AABB(blockPos1).deflate(1.0E-6))) { +- Direction direction = this.findAttachableSurface(blockPos1); +- if (direction != null) { ++ for (int i = 0; i < 5; ++i) { ++ BlockPos blockposition1 = blockposition.offset(Mth.randomBetweenInclusive(this.random, -8, 8), Mth.randomBetweenInclusive(this.random, -8, 8), Mth.randomBetweenInclusive(this.random, -8, 8)); ++ ++ if (blockposition1.getY() > this.level().getMinBuildHeight() && this.level().isEmptyBlock(blockposition1) && this.level().getWorldBorder().isWithinBounds(blockposition1) && this.level().noCollision(this, (new AABB(blockposition1)).deflate(1.0E-6D))) { ++ Direction enumdirection = this.findAttachableSurface(blockposition1); ++ ++ if (enumdirection != null) { ++ // CraftBukkit start ++ EntityTeleportEvent teleportEvent = CraftEventFactory.callEntityTeleportEvent(this, blockposition1.getX(), blockposition1.getY(), blockposition1.getZ()); ++ if (teleportEvent.isCancelled()) { ++ return false; ++ } else { ++ blockposition1 = CraftLocation.toBlockPosition(teleportEvent.getTo()); ++ } ++ // CraftBukkit end + this.unRide(); +- this.setAttachFace(direction); ++ this.setAttachFace(enumdirection); + this.playSound(SoundEvents.SHULKER_TELEPORT, 1.0F, 1.0F); +- this.setPos((double)blockPos1.getX() + 0.5, (double)blockPos1.getY(), (double)blockPos1.getZ() + 0.5); +- this.level().gameEvent(GameEvent.TELEPORT, blockPos, GameEvent.Context.of(this)); +- this.entityData.set(DATA_PEEK_ID, (byte)0); +- this.setTarget(null); ++ this.setPos((double) blockposition1.getX() + 0.5D, (double) blockposition1.getY(), (double) blockposition1.getZ() + 0.5D); ++ this.level().gameEvent(GameEvent.TELEPORT, blockposition, GameEvent.Context.of((Entity) this)); ++ this.entityData.set(Shulker.DATA_PEEK_ID, (byte) 0); ++ this.setTarget((LivingEntity) null); + return true; + } + } +@@ -404,17 +433,19 @@ + } + + @Override +- public void lerpTo(double d, double d1, double d2, float f, float f1, int i) { ++ public void lerpTo(double d0, double d1, double d2, float f, float f1, int i) { + this.lerpSteps = 0; +- this.setPos(d, d1, d2); ++ this.setPos(d0, d1, d2); + this.setRot(f, f1); + } + + @Override + public boolean hurt(DamageSource source, float amount) { ++ Entity entity; ++ + if (this.isClosed()) { +- Entity directEntity = source.getDirectEntity(); +- if (directEntity instanceof AbstractArrow) { ++ entity = source.getDirectEntity(); ++ if (entity instanceof AbstractArrow) { + return false; + } + } +@@ -422,11 +453,11 @@ + if (!super.hurt(source, amount)) { + return false; + } else { +- if ((double)this.getHealth() < (double)this.getMaxHealth() * 0.5 && this.random.nextInt(4) == 0) { ++ if ((double) this.getHealth() < (double) this.getMaxHealth() * 0.5D && this.random.nextInt(4) == 0) { + this.teleportSomewhere(); + } else if (source.is(DamageTypeTags.IS_PROJECTILE)) { +- Entity directEntity = source.getDirectEntity(); +- if (directEntity != null && directEntity.getType() == EntityType.SHULKER_BULLET) { ++ entity = source.getDirectEntity(); ++ if (entity != null && entity.getType() == EntityType.SHULKER_BULLET) { + this.hitByShulkerBullet(); + } + } +@@ -440,18 +471,22 @@ + } + + private void hitByShulkerBullet() { +- Vec3 vec3 = this.position(); +- AABB boundingBox = this.getBoundingBox(); ++ Vec3 vec3d = this.position(); ++ AABB axisalignedbb = this.getBoundingBox(); ++ + if (!this.isClosed() && this.teleportSomewhere()) { +- int size = this.level().getEntities(EntityType.SHULKER, boundingBox.inflate(8.0), Entity::isAlive).size(); +- float f = (float)(size - 1) / 5.0F; +- if (!(this.level().random.nextFloat() < f)) { +- Shulker shulker = EntityType.SHULKER.create(this.level()); +- if (shulker != null) { +- shulker.setVariant(this.getVariant()); +- shulker.moveTo(vec3); +- this.level().addFreshEntity(shulker); ++ int i = this.level().getEntities((EntityTypeTest) EntityType.SHULKER, axisalignedbb.inflate(8.0D), Entity::isAlive).size(); ++ float f = (float) (i - 1) / 5.0F; ++ ++ if (this.level().random.nextFloat() >= f) { ++ Shulker entityshulker = (Shulker) EntityType.SHULKER.create(this.level()); ++ ++ if (entityshulker != null) { ++ entityshulker.setVariant(this.getVariant()); ++ entityshulker.moveTo(vec3d); ++ this.level().addFreshEntity(entityshulker, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.BREEDING); // CraftBukkit - the mysteries of life + } ++ + } + } + } +@@ -462,31 +497,31 @@ + } + + public Direction getAttachFace() { +- return this.entityData.get(DATA_ATTACH_FACE_ID); ++ return (Direction) this.entityData.get(Shulker.DATA_ATTACH_FACE_ID); + } + +- private void setAttachFace(Direction attachFace) { +- this.entityData.set(DATA_ATTACH_FACE_ID, attachFace); ++ public void setAttachFace(Direction attachFace) { ++ this.entityData.set(Shulker.DATA_ATTACH_FACE_ID, attachFace); + } + + @Override + public void onSyncedDataUpdated(EntityDataAccessor<?> key) { +- if (DATA_ATTACH_FACE_ID.equals(key)) { ++ if (Shulker.DATA_ATTACH_FACE_ID.equals(key)) { + this.setBoundingBox(this.makeBoundingBox()); + } + + super.onSyncedDataUpdated(key); + } + +- private int getRawPeekAmount() { +- return this.entityData.get(DATA_PEEK_ID); ++ public int getRawPeekAmount() { ++ return (Byte) this.entityData.get(Shulker.DATA_PEEK_ID); + } + +- void setRawPeekAmount(int peekAmount) { ++ public void setRawPeekAmount(int peekAmount) { + if (!this.level().isClientSide) { +- this.getAttribute(Attributes.ARMOR).removeModifier(COVERED_ARMOR_MODIFIER.getId()); ++ this.getAttribute(Attributes.ARMOR).removeModifier(Shulker.COVERED_ARMOR_MODIFIER.getId()); + if (peekAmount == 0) { +- this.getAttribute(Attributes.ARMOR).addPermanentModifier(COVERED_ARMOR_MODIFIER); ++ this.getAttribute(Attributes.ARMOR).addPermanentModifier(Shulker.COVERED_ARMOR_MODIFIER); + this.playSound(SoundEvents.SHULKER_CLOSE, 1.0F, 1.0F); + this.gameEvent(GameEvent.CONTAINER_CLOSE); + } else { +@@ -495,7 +530,7 @@ + } + } + +- this.entityData.set(DATA_PEEK_ID, (byte)peekAmount); ++ this.entityData.set(Shulker.DATA_PEEK_ID, (byte) peekAmount); + } + + public float getClientPeekAmount(float partialTick) { +@@ -503,7 +538,7 @@ + } + + @Override +- protected float getStandingEyeHeight(Pose pose, EntityDimensions size) { ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions size) { + return 0.5F; + } + +@@ -525,26 +560,28 @@ + } + + @Override +- public void push(Entity entity) { +- } ++ public void push(Entity entity) {} + + public Optional<Vec3> getRenderPosition(float partial) { + if (this.clientOldAttachPosition != null && this.clientSideTeleportInterpolation > 0) { +- double d = (double)((float)this.clientSideTeleportInterpolation - partial) / 6.0; +- d *= d; +- BlockPos blockPos = this.blockPosition(); +- double d1 = (double)(blockPos.getX() - this.clientOldAttachPosition.getX()) * d; +- double d2 = (double)(blockPos.getY() - this.clientOldAttachPosition.getY()) * d; +- double d3 = (double)(blockPos.getZ() - this.clientOldAttachPosition.getZ()) * d; ++ double d0 = (double) ((float) this.clientSideTeleportInterpolation - partial) / 6.0D; ++ ++ d0 *= d0; ++ BlockPos blockposition = this.blockPosition(); ++ double d1 = (double) (blockposition.getX() - this.clientOldAttachPosition.getX()) * d0; ++ double d2 = (double) (blockposition.getY() - this.clientOldAttachPosition.getY()) * d0; ++ double d3 = (double) (blockposition.getZ() - this.clientOldAttachPosition.getZ()) * d0; ++ + return Optional.of(new Vec3(-d1, -d2, -d3)); + } else { + return Optional.empty(); + } + } + +- @Override + public void setVariant(Optional<DyeColor> variant) { +- this.entityData.set(DATA_COLOR_ID, variant.<Byte>map(color -> (byte)color.getId()).orElse((byte)16)); ++ this.entityData.set(Shulker.DATA_COLOR_ID, (Byte) variant.map((enumcolor) -> { ++ return (byte) enumcolor.getId(); ++ }).orElse((byte) 16)); + } + + @Override +@@ -554,21 +591,57 @@ + + @Nullable + public DyeColor getColor() { +- byte b = this.entityData.get(DATA_COLOR_ID); +- return b != 16 && b <= 15 ? DyeColor.byId(b) : null; ++ byte b0 = (Byte) this.entityData.get(Shulker.DATA_COLOR_ID); ++ ++ return b0 != 16 && b0 <= 15 ? DyeColor.byId(b0) : null; + } + +- class ShulkerAttackGoal extends Goal { ++ private class ShulkerLookControl extends LookControl { ++ ++ public ShulkerLookControl(Mob mob) { ++ super(mob); ++ } ++ ++ @Override ++ protected void clampHeadRotationToBody() {} ++ ++ @Override ++ protected Optional<Float> getYRotD() { ++ Direction enumdirection = Shulker.this.getAttachFace().getOpposite(); ++ Vector3f vector3f = enumdirection.getRotation().transform(new Vector3f(Shulker.FORWARD)); ++ Vec3i baseblockposition = enumdirection.getNormal(); ++ Vector3f vector3f1 = new Vector3f((float) baseblockposition.getX(), (float) baseblockposition.getY(), (float) baseblockposition.getZ()); ++ ++ vector3f1.cross(vector3f); ++ double d0 = this.wantedX - this.mob.getX(); ++ double d1 = this.wantedY - this.mob.getEyeY(); ++ double d2 = this.wantedZ - this.mob.getZ(); ++ Vector3f vector3f2 = new Vector3f((float) d0, (float) d1, (float) d2); ++ float f = vector3f1.dot(vector3f2); ++ float f1 = vector3f.dot(vector3f2); ++ ++ return Math.abs(f) <= 1.0E-5F && Math.abs(f1) <= 1.0E-5F ? Optional.empty() : Optional.of((float) (Mth.atan2((double) (-f), (double) f1) * 57.2957763671875D)); ++ } ++ ++ @Override ++ protected Optional<Float> getXRotD() { ++ return Optional.of(0.0F); ++ } ++ } ++ ++ private class ShulkerAttackGoal extends Goal { ++ + private int attackTime; + + public ShulkerAttackGoal() { +- this.setFlags(EnumSet.of(Goal.Flag.MOVE, Goal.Flag.LOOK)); ++ this.setFlags(EnumSet.of(Goal.Type.MOVE, Goal.Type.LOOK)); + } + + @Override + public boolean canUse() { +- LivingEntity target = Shulker.this.getTarget(); +- return target != null && target.isAlive() && Shulker.this.level().getDifficulty() != Difficulty.PEACEFUL; ++ LivingEntity entityliving = Shulker.this.getTarget(); ++ ++ return entityliving != null && entityliving.isAlive() ? Shulker.this.level().getDifficulty() != Difficulty.PEACEFUL : false; + } + + @Override +@@ -590,22 +663,21 @@ + @Override + public void tick() { + if (Shulker.this.level().getDifficulty() != Difficulty.PEACEFUL) { +- this.attackTime--; +- LivingEntity target = Shulker.this.getTarget(); +- if (target != null) { +- Shulker.this.getLookControl().setLookAt(target, 180.0F, 180.0F); +- double d = Shulker.this.distanceToSqr(target); +- if (d < 400.0) { ++ --this.attackTime; ++ LivingEntity entityliving = Shulker.this.getTarget(); ++ ++ if (entityliving != null) { ++ Shulker.this.getLookControl().setLookAt(entityliving, 180.0F, 180.0F); ++ double d0 = Shulker.this.distanceToSqr((Entity) entityliving); ++ ++ if (d0 < 400.0D) { + if (this.attackTime <= 0) { + this.attackTime = 20 + Shulker.this.random.nextInt(10) * 20 / 2; +- Shulker.this.level() +- .addFreshEntity(new ShulkerBullet(Shulker.this.level(), Shulker.this, target, Shulker.this.getAttachFace().getAxis())); +- Shulker.this.playSound( +- SoundEvents.SHULKER_SHOOT, 2.0F, (Shulker.this.random.nextFloat() - Shulker.this.random.nextFloat()) * 0.2F + 1.0F +- ); ++ Shulker.this.level().addFreshEntity(new ShulkerBullet(Shulker.this.level(), Shulker.this, entityliving, Shulker.this.getAttachFace().getAxis())); ++ Shulker.this.playSound(SoundEvents.SHULKER_SHOOT, 2.0F, (Shulker.this.random.nextFloat() - Shulker.this.random.nextFloat()) * 0.2F + 1.0F); + } + } else { +- Shulker.this.setTarget(null); ++ Shulker.this.setTarget((LivingEntity) null); + } + + super.tick(); +@@ -614,126 +686,89 @@ + } + } + +- static class ShulkerBodyRotationControl extends BodyRotationControl { +- public ShulkerBodyRotationControl(Mob mob) { +- super(mob); +- } ++ private class ShulkerPeekGoal extends Goal { + +- @Override +- public void clientTick() { +- } +- } ++ private int peekTime; + +- static class ShulkerDefenseAttackGoal extends NearestAttackableTargetGoal<LivingEntity> { +- public ShulkerDefenseAttackGoal(Shulker shulker) { +- super(shulker, LivingEntity.class, 10, true, false, entity -> entity instanceof Enemy); +- } ++ ShulkerPeekGoal() {} + + @Override + public boolean canUse() { +- return this.mob.getTeam() != null && super.canUse(); ++ return Shulker.this.getTarget() == null && Shulker.this.random.nextInt(reducedTickDelay(40)) == 0 && Shulker.this.canStayAt(Shulker.this.blockPosition(), Shulker.this.getAttachFace()); + } + + @Override +- protected AABB getTargetSearchArea(double targetDistance) { +- Direction attachFace = ((Shulker)this.mob).getAttachFace(); +- if (attachFace.getAxis() == Direction.Axis.X) { +- return this.mob.getBoundingBox().inflate(4.0, targetDistance, targetDistance); +- } else { +- return attachFace.getAxis() == Direction.Axis.Z +- ? this.mob.getBoundingBox().inflate(targetDistance, targetDistance, 4.0) +- : this.mob.getBoundingBox().inflate(targetDistance, 4.0, targetDistance); +- } ++ public boolean canContinueToUse() { ++ return Shulker.this.getTarget() == null && this.peekTime > 0; + } +- } + +- class ShulkerLookControl extends LookControl { +- public ShulkerLookControl(Mob mob) { +- super(mob); +- } +- + @Override +- protected void clampHeadRotationToBody() { ++ public void start() { ++ this.peekTime = this.adjustedTickDelay(20 * (1 + Shulker.this.random.nextInt(3))); ++ Shulker.this.setRawPeekAmount(30); + } + + @Override +- protected Optional<Float> getYRotD() { +- Direction opposite = Shulker.this.getAttachFace().getOpposite(); +- Vector3f vector3f = opposite.getRotation().transform(new Vector3f(Shulker.FORWARD)); +- Vec3i normal = opposite.getNormal(); +- Vector3f vector3f1 = new Vector3f((float)normal.getX(), (float)normal.getY(), (float)normal.getZ()); +- vector3f1.cross(vector3f); +- double d = this.wantedX - this.mob.getX(); +- double d1 = this.wantedY - this.mob.getEyeY(); +- double d2 = this.wantedZ - this.mob.getZ(); +- Vector3f vector3f2 = new Vector3f((float)d, (float)d1, (float)d2); +- float f = vector3f1.dot(vector3f2); +- float f1 = vector3f.dot(vector3f2); +- return !(Math.abs(f) > 1.0E-5F) && !(Math.abs(f1) > 1.0E-5F) +- ? Optional.empty() +- : Optional.of((float)(Mth.atan2((double)(-f), (double)f1) * 180.0F / (float)Math.PI)); ++ public void stop() { ++ if (Shulker.this.getTarget() == null) { ++ Shulker.this.setRawPeekAmount(0); ++ } ++ + } + + @Override +- protected Optional<Float> getXRotD() { +- return Optional.of(0.0F); ++ public void tick() { ++ --this.peekTime; + } + } + +- class ShulkerNearestAttackGoal extends NearestAttackableTargetGoal<Player> { +- public ShulkerNearestAttackGoal(Shulker shulker) { +- super(shulker, Player.class, true); ++ private class ShulkerNearestAttackGoal extends NearestAttackableTargetGoal<Player> { ++ ++ public ShulkerNearestAttackGoal(Shulker entityshulker) { ++ super(entityshulker, Player.class, true); + } + + @Override + public boolean canUse() { +- return Shulker.this.level().getDifficulty() != Difficulty.PEACEFUL && super.canUse(); ++ return Shulker.this.level().getDifficulty() == Difficulty.PEACEFUL ? false : super.canUse(); + } + + @Override + protected AABB getTargetSearchArea(double targetDistance) { +- Direction attachFace = ((Shulker)this.mob).getAttachFace(); +- if (attachFace.getAxis() == Direction.Axis.X) { +- return this.mob.getBoundingBox().inflate(4.0, targetDistance, targetDistance); +- } else { +- return attachFace.getAxis() == Direction.Axis.Z +- ? this.mob.getBoundingBox().inflate(targetDistance, targetDistance, 4.0) +- : this.mob.getBoundingBox().inflate(targetDistance, 4.0, targetDistance); +- } ++ Direction enumdirection = ((Shulker) this.mob).getAttachFace(); ++ ++ return enumdirection.getAxis() == Direction.Axis.X ? this.mob.getBoundingBox().inflate(4.0D, targetDistance, targetDistance) : (enumdirection.getAxis() == Direction.Axis.Z ? this.mob.getBoundingBox().inflate(targetDistance, targetDistance, 4.0D) : this.mob.getBoundingBox().inflate(targetDistance, 4.0D, targetDistance)); + } + } + +- class ShulkerPeekGoal extends Goal { +- private int peekTime; ++ private static class ShulkerDefenseAttackGoal extends NearestAttackableTargetGoal<LivingEntity> { + +- @Override +- public boolean canUse() { +- return Shulker.this.getTarget() == null +- && Shulker.this.random.nextInt(reducedTickDelay(40)) == 0 +- && Shulker.this.canStayAt(Shulker.this.blockPosition(), Shulker.this.getAttachFace()); ++ public ShulkerDefenseAttackGoal(Shulker shulker) { ++ super(shulker, LivingEntity.class, 10, true, false, (entityliving) -> { ++ return entityliving instanceof IMonster; ++ }); + } + + @Override +- public boolean canContinueToUse() { +- return Shulker.this.getTarget() == null && this.peekTime > 0; ++ public boolean canUse() { ++ return this.mob.getTeam() == null ? false : super.canUse(); + } + + @Override +- public void start() { +- this.peekTime = this.adjustedTickDelay(20 * (1 + Shulker.this.random.nextInt(3))); +- Shulker.this.setRawPeekAmount(30); ++ protected AABB getTargetSearchArea(double targetDistance) { ++ Direction enumdirection = ((Shulker) this.mob).getAttachFace(); ++ ++ return enumdirection.getAxis() == Direction.Axis.X ? this.mob.getBoundingBox().inflate(4.0D, targetDistance, targetDistance) : (enumdirection.getAxis() == Direction.Axis.Z ? this.mob.getBoundingBox().inflate(targetDistance, targetDistance, 4.0D) : this.mob.getBoundingBox().inflate(targetDistance, 4.0D, targetDistance)); + } ++ } + +- @Override +- public void stop() { +- if (Shulker.this.getTarget() == null) { +- Shulker.this.setRawPeekAmount(0); +- } ++ private static class ShulkerBodyRotationControl extends BodyRotationControl { ++ ++ public ShulkerBodyRotationControl(Mob mob) { ++ super(mob); + } + + @Override +- public void tick() { +- this.peekTime--; +- } ++ public void clientTick() {} + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Silverfish.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Silverfish.java.patch new file mode 100644 index 0000000000..1e5713e0bb --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Silverfish.java.patch @@ -0,0 +1,282 @@ +--- a/net/minecraft/world/entity/monster/Silverfish.java ++++ b/net/minecraft/world/entity/monster/Silverfish.java +@@ -11,10 +11,10 @@ + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.MobType; +-import net.minecraft.world.entity.Pose; ++import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.EnumMonsterType; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; + import net.minecraft.world.entity.ai.attributes.Attributes; + import net.minecraft.world.entity.ai.goal.ClimbOnTopOfPowderSnowGoal; +@@ -31,10 +31,15 @@ + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.block.Block; + import net.minecraft.world.level.block.InfestedBlock; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import org.joml.Vector3f; + ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end ++ + public class Silverfish extends Monster { ++ + @Nullable + private Silverfish.SilverfishWakeUpFriendsGoal friendsGoal; + +@@ -48,19 +53,19 @@ + this.goalSelector.addGoal(1, new FloatGoal(this)); + this.goalSelector.addGoal(1, new ClimbOnTopOfPowderSnowGoal(this, this.level())); + this.goalSelector.addGoal(3, this.friendsGoal); +- this.goalSelector.addGoal(4, new MeleeAttackGoal(this, 1.0, false)); ++ this.goalSelector.addGoal(4, new MeleeAttackGoal(this, 1.0D, false)); + this.goalSelector.addGoal(5, new Silverfish.SilverfishMergeWithStoneGoal(this)); +- this.targetSelector.addGoal(1, new HurtByTargetGoal(this).setAlertOthers()); ++ this.targetSelector.addGoal(1, (new HurtByTargetGoal(this, new Class[0])).setAlertOthers()); + this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, true)); + } + + @Override +- protected float getStandingEyeHeight(Pose pose, EntityDimensions size) { ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions size) { + return 0.13F; + } + + public static AttributeSupplier.Builder createAttributes() { +- return Monster.createMonsterAttributes().add(Attributes.MAX_HEALTH, 8.0).add(Attributes.MOVEMENT_SPEED, 0.25).add(Attributes.ATTACK_DAMAGE, 1.0); ++ return Monster.createMonsterAttributes().add(Attributes.MAX_HEALTH, 8.0D).add(Attributes.MOVEMENT_SPEED, 0.25D).add(Attributes.ATTACK_DAMAGE, 1.0D); + } + + @Override +@@ -84,7 +89,7 @@ + } + + @Override +- protected void playStepSound(BlockPos pos, BlockState block) { ++ protected void playStepSound(BlockPos pos, IBlockData block) { + this.playSound(SoundEvents.SILVERFISH_STEP, 0.15F, 1.0F); + } + +@@ -118,35 +123,95 @@ + return InfestedBlock.isCompatibleHostBlock(level.getBlockState(pos.below())) ? 10.0F : super.getWalkTargetValue(pos, level); + } + +- public static boolean checkSilverfishSpawnRules( +- EntityType<Silverfish> silverfish, LevelAccessor level, MobSpawnType spawnType, BlockPos pos, RandomSource random +- ) { ++ public static boolean checkSilverfishSpawnRules(EntityType<Silverfish> silverfish, LevelAccessor level, EnumMobSpawn spawnType, BlockPos pos, RandomSource random) { + if (checkAnyLightMonsterSpawnRules(silverfish, level, spawnType, pos, random)) { +- Player nearestPlayer = level.getNearestPlayer((double)pos.getX() + 0.5, (double)pos.getY() + 0.5, (double)pos.getZ() + 0.5, 5.0, true); +- return nearestPlayer == null; ++ Player entityhuman = level.getNearestPlayer((double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D, 5.0D, true); ++ ++ return entityhuman == null; + } else { + return false; + } + } + + @Override +- public MobType getMobType() { +- return MobType.ARTHROPOD; ++ public EnumMonsterType getMobType() { ++ return EnumMonsterType.ARTHROPOD; + } + + @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entityDimensions, float f) { +- return new Vector3f(0.0F, entityDimensions.height - 0.0625F * f, 0.0F); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ return new Vector3f(0.0F, entitysize.height - 0.0625F * f, 0.0F); + } + +- static class SilverfishMergeWithStoneGoal extends RandomStrollGoal { ++ private static class SilverfishWakeUpFriendsGoal extends Goal { ++ ++ private final Silverfish silverfish; ++ private int lookForFriends; ++ ++ public SilverfishWakeUpFriendsGoal(Silverfish silverfish) { ++ this.silverfish = silverfish; ++ } ++ ++ public void notifyHurt() { ++ if (this.lookForFriends == 0) { ++ this.lookForFriends = this.adjustedTickDelay(20); ++ } ++ ++ } ++ ++ @Override ++ public boolean canUse() { ++ return this.lookForFriends > 0; ++ } ++ ++ @Override ++ public void tick() { ++ --this.lookForFriends; ++ if (this.lookForFriends <= 0) { ++ Level world = this.silverfish.level(); ++ RandomSource randomsource = this.silverfish.getRandom(); ++ BlockPos blockposition = this.silverfish.blockPosition(); ++ ++ for (int i = 0; i <= 5 && i >= -5; i = (i <= 0 ? 1 : 0) - i) { ++ for (int j = 0; j <= 10 && j >= -10; j = (j <= 0 ? 1 : 0) - j) { ++ for (int k = 0; k <= 10 && k >= -10; k = (k <= 0 ? 1 : 0) - k) { ++ BlockPos blockposition1 = blockposition.offset(j, i, k); ++ IBlockData iblockdata = world.getBlockState(blockposition1); ++ Block block = iblockdata.getBlock(); ++ ++ if (block instanceof InfestedBlock) { ++ // CraftBukkit start ++ if (!CraftEventFactory.callEntityChangeBlockEvent(this.silverfish, blockposition1, net.minecraft.world.level.block.Blocks.AIR.defaultBlockState())) { ++ continue; ++ } ++ // CraftBukkit end ++ if (world.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { ++ world.destroyBlock(blockposition1, true, this.silverfish); ++ } else { ++ world.setBlock(blockposition1, ((InfestedBlock) block).hostStateByInfested(world.getBlockState(blockposition1)), 3); ++ } ++ ++ if (randomsource.nextBoolean()) { ++ return; ++ } ++ } ++ } ++ } ++ } ++ } ++ ++ } ++ } ++ ++ private static class SilverfishMergeWithStoneGoal extends RandomStrollGoal { ++ + @Nullable + private Direction selectedDirection; + private boolean doMerge; + + public SilverfishMergeWithStoneGoal(Silverfish silverfish) { +- super(silverfish, 1.0, 10); +- this.setFlags(EnumSet.of(Goal.Flag.MOVE)); ++ super(silverfish, 1.0D, 10); ++ this.setFlags(EnumSet.of(Goal.Type.MOVE)); + } + + @Override +@@ -156,12 +221,14 @@ + } else if (!this.mob.getNavigation().isDone()) { + return false; + } else { +- RandomSource random = this.mob.getRandom(); +- if (this.mob.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) && random.nextInt(reducedTickDelay(10)) == 0) { +- this.selectedDirection = Direction.getRandom(random); +- BlockPos blockPos = BlockPos.containing(this.mob.getX(), this.mob.getY() + 0.5, this.mob.getZ()).relative(this.selectedDirection); +- BlockState blockState = this.mob.level().getBlockState(blockPos); +- if (InfestedBlock.isCompatibleHostBlock(blockState)) { ++ RandomSource randomsource = this.mob.getRandom(); ++ ++ if (this.mob.level().getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) && randomsource.nextInt(reducedTickDelay(10)) == 0) { ++ this.selectedDirection = Direction.getRandom(randomsource); ++ BlockPos blockposition = BlockPos.containing(this.mob.getX(), this.mob.getY() + 0.5D, this.mob.getZ()).relative(this.selectedDirection); ++ IBlockData iblockdata = this.mob.level().getBlockState(blockposition); ++ ++ if (InfestedBlock.isCompatibleHostBlock(iblockdata)) { + this.doMerge = true; + return true; + } +@@ -174,7 +241,7 @@ + + @Override + public boolean canContinueToUse() { +- return !this.doMerge && super.canContinueToUse(); ++ return this.doMerge ? false : super.canContinueToUse(); + } + + @Override +@@ -182,66 +249,22 @@ + if (!this.doMerge) { + super.start(); + } else { +- LevelAccessor levelAccessor = this.mob.level(); +- BlockPos blockPos = BlockPos.containing(this.mob.getX(), this.mob.getY() + 0.5, this.mob.getZ()).relative(this.selectedDirection); +- BlockState blockState = levelAccessor.getBlockState(blockPos); +- if (InfestedBlock.isCompatibleHostBlock(blockState)) { +- levelAccessor.setBlock(blockPos, InfestedBlock.infestedStateByHost(blockState), 3); ++ Level world = this.mob.level(); ++ BlockPos blockposition = BlockPos.containing(this.mob.getX(), this.mob.getY() + 0.5D, this.mob.getZ()).relative(this.selectedDirection); ++ IBlockData iblockdata = world.getBlockState(blockposition); ++ ++ if (InfestedBlock.isCompatibleHostBlock(iblockdata)) { ++ // CraftBukkit start ++ if (!CraftEventFactory.callEntityChangeBlockEvent(this.mob, blockposition, InfestedBlock.infestedStateByHost(iblockdata))) { ++ return; ++ } ++ // CraftBukkit end ++ world.setBlock(blockposition, InfestedBlock.infestedStateByHost(iblockdata), 3); + this.mob.spawnAnim(); + this.mob.discard(); + } +- } +- } +- } + +- static class SilverfishWakeUpFriendsGoal extends Goal { +- private final Silverfish silverfish; +- private int lookForFriends; +- +- public SilverfishWakeUpFriendsGoal(Silverfish silverfish) { +- this.silverfish = silverfish; +- } +- +- public void notifyHurt() { +- if (this.lookForFriends == 0) { +- this.lookForFriends = this.adjustedTickDelay(20); + } + } +- +- @Override +- public boolean canUse() { +- return this.lookForFriends > 0; +- } +- +- @Override +- public void tick() { +- this.lookForFriends--; +- if (this.lookForFriends <= 0) { +- Level level = this.silverfish.level(); +- RandomSource random = this.silverfish.getRandom(); +- BlockPos blockPos = this.silverfish.blockPosition(); +- +- for (int i = 0; i <= 5 && i >= -5; i = (i <= 0 ? 1 : 0) - i) { +- for (int i1 = 0; i1 <= 10 && i1 >= -10; i1 = (i1 <= 0 ? 1 : 0) - i1) { +- for (int i2 = 0; i2 <= 10 && i2 >= -10; i2 = (i2 <= 0 ? 1 : 0) - i2) { +- BlockPos blockPos1 = blockPos.offset(i1, i, i2); +- BlockState blockState = level.getBlockState(blockPos1); +- Block block = blockState.getBlock(); +- if (block instanceof InfestedBlock) { +- if (level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) { +- level.destroyBlock(blockPos1, true, this.silverfish); +- } else { +- level.setBlock(blockPos1, ((InfestedBlock)block).hostStateByInfested(level.getBlockState(blockPos1)), 3); +- } +- +- if (random.nextBoolean()) { +- return; +- } +- } +- } +- } +- } +- } +- } + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Skeleton.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Skeleton.java.patch new file mode 100644 index 0000000000..ede8670387 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Skeleton.java.patch @@ -0,0 +1,103 @@ +--- a/net/minecraft/world/entity/monster/Skeleton.java ++++ b/net/minecraft/world/entity/monster/Skeleton.java +@@ -7,16 +7,20 @@ + import net.minecraft.sounds.SoundEvent; + import net.minecraft.sounds.SoundEvents; + import net.minecraft.world.damagesource.DamageSource; ++import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.player.Player; + import net.minecraft.world.item.Items; ++import net.minecraft.world.level.IMaterial; + import net.minecraft.world.level.Level; + + public class Skeleton extends AbstractSkeleton { ++ + private static final int TOTAL_CONVERSION_TIME = 300; +- private static final EntityDataAccessor<Boolean> DATA_STRAY_CONVERSION_ID = SynchedEntityData.defineId(Skeleton.class, EntityDataSerializers.BOOLEAN); ++ public static final EntityDataAccessor<Boolean> DATA_STRAY_CONVERSION_ID = SynchedEntityData.defineId(Skeleton.class, EntityDataSerializers.BOOLEAN); + public static final String CONVERSION_TAG = "StrayConversionTime"; + private int inPowderSnowTime; +- private int conversionTime; ++ public int conversionTime; + + public Skeleton(EntityType<? extends Skeleton> entityType, Level level) { + super(entityType, level); +@@ -25,15 +29,15 @@ + @Override + protected void defineSynchedData() { + super.defineSynchedData(); +- this.getEntityData().define(DATA_STRAY_CONVERSION_ID, false); ++ this.getEntityData().define(Skeleton.DATA_STRAY_CONVERSION_ID, false); + } + + public boolean isFreezeConverting() { +- return this.getEntityData().get(DATA_STRAY_CONVERSION_ID); ++ return (Boolean) this.getEntityData().get(Skeleton.DATA_STRAY_CONVERSION_ID); + } + + public void setFreezeConverting(boolean isFrozen) { +- this.entityData.set(DATA_STRAY_CONVERSION_ID, isFrozen); ++ this.entityData.set(Skeleton.DATA_STRAY_CONVERSION_ID, isFrozen); + } + + @Override +@@ -46,12 +50,12 @@ + if (!this.level().isClientSide && this.isAlive() && !this.isNoAi()) { + if (this.isInPowderSnow) { + if (this.isFreezeConverting()) { +- this.conversionTime--; ++ --this.conversionTime; + if (this.conversionTime < 0) { + this.doFreezeConversion(); + } + } else { +- this.inPowderSnowTime++; ++ ++this.inPowderSnowTime; + if (this.inPowderSnowTime >= 140) { + this.startFreezeConversion(300); + } +@@ -77,18 +81,20 @@ + if (compound.contains("StrayConversionTime", 99) && compound.getInt("StrayConversionTime") > -1) { + this.startFreezeConversion(compound.getInt("StrayConversionTime")); + } ++ + } + +- private void startFreezeConversion(int conversionTime) { ++ public void startFreezeConversion(int conversionTime) { + this.conversionTime = conversionTime; + this.setFreezeConverting(true); + } + + protected void doFreezeConversion() { +- this.convertTo(EntityType.STRAY, true); ++ this.convertTo(EntityType.STRAY, true, org.bukkit.event.entity.EntityTransformEvent.TransformReason.FROZEN, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.FROZEN); // CraftBukkit - add spawn and transform reasons + if (!this.isSilent()) { +- this.level().levelEvent(null, 1048, this.blockPosition(), 0); ++ this.level().levelEvent((Player) null, 1048, this.blockPosition(), 0); + } ++ + } + + @Override +@@ -119,9 +125,16 @@ + @Override + protected void dropCustomDeathLoot(DamageSource source, int looting, boolean recentlyHit) { + super.dropCustomDeathLoot(source, looting, recentlyHit); +- if (source.getEntity() instanceof Creeper creeper && creeper.canDropMobsSkull()) { +- creeper.increaseDroppedSkulls(); +- this.spawnAtLocation(Items.SKELETON_SKULL); ++ Entity entity = source.getEntity(); ++ ++ if (entity instanceof Creeper) { ++ Creeper entitycreeper = (Creeper) entity; ++ ++ if (entitycreeper.canDropMobsSkull()) { ++ entitycreeper.increaseDroppedSkulls(); ++ this.spawnAtLocation((IMaterial) Items.SKELETON_SKULL); ++ } + } ++ + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Slime.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Slime.java.patch new file mode 100644 index 0000000000..7808f88a35 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Slime.java.patch @@ -0,0 +1,665 @@ +--- a/net/minecraft/world/entity/monster/Slime.java ++++ b/net/minecraft/world/entity/monster/Slime.java +@@ -23,12 +23,12 @@ + import net.minecraft.world.effect.MobEffects; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.Pose; +-import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.ai.attributes.Attributes; + import net.minecraft.world.entity.ai.control.MoveControl; + import net.minecraft.world.entity.ai.goal.Goal; +@@ -44,7 +44,16 @@ + import net.minecraft.world.phys.Vec3; + import org.joml.Vector3f; + +-public class Slime extends Mob implements Enemy { ++// CraftBukkit start ++import java.util.ArrayList; ++import java.util.List; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.event.entity.EntityTransformEvent; ++import org.bukkit.event.entity.SlimeSplitEvent; ++// CraftBukkit end ++ ++public class Slime extends Mob implements IMonster { ++ + private static final EntityDataAccessor<Integer> ID_SIZE = SynchedEntityData.defineId(Slime.class, EntityDataSerializers.INT); + public static final int MIN_SIZE = 1; + public static final int MAX_SIZE = 127; +@@ -65,10 +74,9 @@ + this.goalSelector.addGoal(2, new Slime.SlimeAttackGoal(this)); + this.goalSelector.addGoal(3, new Slime.SlimeRandomDirectionGoal(this)); + this.goalSelector.addGoal(5, new Slime.SlimeKeepOnJumpingGoal(this)); +- this.targetSelector +- .addGoal( +- 1, new NearestAttackableTargetGoal<>(this, Player.class, 10, true, false, livingEntity -> Math.abs(livingEntity.getY() - this.getY()) <= 4.0) +- ); ++ this.targetSelector.addGoal(1, new NearestAttackableTargetGoal<>(this, Player.class, 10, true, false, (entityliving) -> { ++ return Math.abs(entityliving.getY() - this.getY()) <= 4.0D; ++ })); + this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, IronGolem.class, true)); + } + +@@ -80,27 +88,28 @@ + @Override + protected void defineSynchedData() { + super.defineSynchedData(); +- this.entityData.define(ID_SIZE, 1); ++ this.entityData.define(Slime.ID_SIZE, 1); + } + + @VisibleForTesting + public void setSize(int size, boolean resetHealth) { +- int i = Mth.clamp(size, 1, 127); +- this.entityData.set(ID_SIZE, i); ++ int j = Mth.clamp(size, 1, 127); ++ ++ this.entityData.set(Slime.ID_SIZE, j); + this.reapplyPosition(); + this.refreshDimensions(); +- this.getAttribute(Attributes.MAX_HEALTH).setBaseValue((double)(i * i)); +- this.getAttribute(Attributes.MOVEMENT_SPEED).setBaseValue((double)(0.2F + 0.1F * (float)i)); +- this.getAttribute(Attributes.ATTACK_DAMAGE).setBaseValue((double)i); ++ this.getAttribute(Attributes.MAX_HEALTH).setBaseValue((double) (j * j)); ++ this.getAttribute(Attributes.MOVEMENT_SPEED).setBaseValue((double) (0.2F + 0.1F * (float) j)); ++ this.getAttribute(Attributes.ATTACK_DAMAGE).setBaseValue((double) j); + if (resetHealth) { + this.setHealth(this.getMaxHealth()); + } + +- this.xpReward = i; ++ this.xpReward = j; + } + + public int getSize() { +- return this.entityData.get(ID_SIZE); ++ return (Integer) this.entityData.get(Slime.ID_SIZE); + } + + @Override +@@ -132,18 +141,19 @@ + + @Override + public void tick() { +- this.squish = this.squish + (this.targetSquish - this.squish) * 0.5F; ++ this.squish += (this.targetSquish - this.squish) * 0.5F; + this.oSquish = this.squish; + super.tick(); + if (this.onGround() && !this.wasOnGround) { +- int size = this.getSize(); ++ int i = this.getSize(); + +- for (int i = 0; i < size * 8; i++) { +- float f = this.random.nextFloat() * (float) (Math.PI * 2); ++ for (int j = 0; j < i * 8; ++j) { ++ float f = this.random.nextFloat() * 6.2831855F; + float f1 = this.random.nextFloat() * 0.5F + 0.5F; +- float f2 = Mth.sin(f) * (float)size * 0.5F * f1; +- float f3 = Mth.cos(f) * (float)size * 0.5F * f1; +- this.level().addParticle(this.getParticleType(), this.getX() + (double)f2, this.getY(), this.getZ() + (double)f3, 0.0, 0.0, 0.0); ++ float f2 = Mth.sin(f) * (float) i * 0.5F * f1; ++ float f3 = Mth.cos(f) * (float) i * 0.5F * f1; ++ ++ this.level().addParticle(this.getParticleType(), this.getX() + (double) f2, this.getY(), this.getZ() + (double) f3, 0.0D, 0.0D, 0.0D); + } + + this.playSound(this.getSquishSound(), this.getSoundVolume(), ((this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 1.0F) / 0.8F); +@@ -166,16 +176,17 @@ + + @Override + public void refreshDimensions() { +- double x = this.getX(); +- double y = this.getY(); +- double z = this.getZ(); ++ double d0 = this.getX(); ++ double d1 = this.getY(); ++ double d2 = this.getZ(); ++ + super.refreshDimensions(); +- this.setPos(x, y, z); ++ this.setPos(d0, d1, d2); + } + + @Override + public void onSyncedDataUpdated(EntityDataAccessor<?> key) { +- if (ID_SIZE.equals(key)) { ++ if (Slime.ID_SIZE.equals(key)) { + this.refreshDimensions(); + this.setYRot(this.yHeadRot); + this.yBodyRot = this.yHeadRot; +@@ -189,36 +200,60 @@ + + @Override + public EntityType<? extends Slime> getType() { +- return (EntityType<? extends Slime>)super.getType(); ++ return (EntityType<? extends Slime>) super.getType(); // CraftBukkit - decompile error + } + + @Override + public void remove(Entity.RemovalReason reason) { +- int size = this.getSize(); +- if (!this.level().isClientSide && size > 1 && this.isDeadOrDying()) { +- Component customName = this.getCustomName(); +- boolean isNoAi = this.isNoAi(); +- float f = (float)size / 4.0F; +- int i = size / 2; +- int i1 = 2 + this.random.nextInt(3); ++ int i = this.getSize(); + +- for (int i2 = 0; i2 < i1; i2++) { +- float f1 = ((float)(i2 % 2) - 0.5F) * f; +- float f2 = ((float)(i2 / 2) - 0.5F) * f; +- Slime slime = this.getType().create(this.level()); +- if (slime != null) { ++ if (!this.level().isClientSide && i > 1 && this.isDeadOrDying()) { ++ Component ichatbasecomponent = this.getCustomName(); ++ boolean flag = this.isNoAi(); ++ float f = (float) i / 4.0F; ++ int j = i / 2; ++ int k = 2 + this.random.nextInt(3); ++ ++ // CraftBukkit start ++ SlimeSplitEvent event = new SlimeSplitEvent((org.bukkit.entity.Slime) this.getBukkitEntity(), k); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (!event.isCancelled() && event.getCount() > 0) { ++ k = event.getCount(); ++ } else { ++ super.remove(reason); ++ return; ++ } ++ List<LivingEntity> slimes = new ArrayList<>(j); ++ // CraftBukkit end ++ ++ for (int l = 0; l < k; ++l) { ++ float f1 = ((float) (l % 2) - 0.5F) * f; ++ float f2 = ((float) (l / 2) - 0.5F) * f; ++ Slime entityslime = (Slime) this.getType().create(this.level()); ++ ++ if (entityslime != null) { + if (this.isPersistenceRequired()) { +- slime.setPersistenceRequired(); ++ entityslime.setPersistenceRequired(); + } + +- slime.setCustomName(customName); +- slime.setNoAi(isNoAi); +- slime.setInvulnerable(this.isInvulnerable()); +- slime.setSize(i, true); +- slime.moveTo(this.getX() + (double)f1, this.getY() + 0.5, this.getZ() + (double)f2, this.random.nextFloat() * 360.0F, 0.0F); +- this.level().addFreshEntity(slime); ++ entityslime.setCustomName(ichatbasecomponent); ++ entityslime.setNoAi(flag); ++ entityslime.setInvulnerable(this.isInvulnerable()); ++ entityslime.setSize(j, true); ++ entityslime.moveTo(this.getX() + (double) f1, this.getY() + 0.5D, this.getZ() + (double) f2, this.random.nextFloat() * 360.0F, 0.0F); ++ slimes.add(entityslime); // CraftBukkit + } + } ++ // CraftBukkit start ++ if (CraftEventFactory.callEntityTransformEvent(this, slimes, EntityTransformEvent.TransformReason.SPLIT).isCancelled()) { ++ super.remove(reason); ++ return; ++ } ++ for (LivingEntity living : slimes) { ++ this.level().addFreshEntity(living, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SLIME_SPLIT); // CraftBukkit - SpawnReason ++ } ++ // CraftBukkit end + } + + super.remove(reason); +@@ -228,8 +263,9 @@ + public void push(Entity entity) { + super.push(entity); + if (entity instanceof IronGolem && this.isDealsDamage()) { +- this.dealDamage((LivingEntity)entity); ++ this.dealDamage((LivingEntity) entity); + } ++ + } + + @Override +@@ -237,28 +273,29 @@ + if (this.isDealsDamage()) { + this.dealDamage(entity); + } ++ + } + + protected void dealDamage(LivingEntity livingEntity) { + if (this.isAlive()) { +- int size = this.getSize(); +- if (this.distanceToSqr(livingEntity) < 0.6 * (double)size * 0.6 * (double)size +- && this.hasLineOfSight(livingEntity) +- && livingEntity.hurt(this.damageSources().mobAttack(this), this.getAttackDamage())) { ++ int i = this.getSize(); ++ ++ if (this.distanceToSqr((Entity) livingEntity) < 0.6D * (double) i * 0.6D * (double) i && this.hasLineOfSight(livingEntity) && livingEntity.hurt(this.damageSources().mobAttack(this), this.getAttackDamage())) { + this.playSound(SoundEvents.SLIME_ATTACK, 1.0F, (this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 1.0F); + this.doEnchantDamageEffects(this, livingEntity); + } + } ++ + } + + @Override +- protected float getStandingEyeHeight(Pose pose, EntityDimensions size) { ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions size) { + return 0.625F * size.height; + } + + @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entityDimensions, float f) { +- return new Vector3f(0.0F, entityDimensions.height - 0.015625F * (float)this.getSize() * f, 0.0F); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ return new Vector3f(0.0F, entitysize.height - 0.015625F * (float) this.getSize() * f, 0.0F); + } + + protected boolean isDealsDamage() { +@@ -266,7 +303,7 @@ + } + + protected float getAttackDamage() { +- return (float)this.getAttributeValue(Attributes.ATTACK_DAMAGE); ++ return (float) this.getAttributeValue(Attributes.ATTACK_DAMAGE); + } + + @Override +@@ -283,21 +320,16 @@ + return this.isTiny() ? SoundEvents.SLIME_SQUISH_SMALL : SoundEvents.SLIME_SQUISH; + } + +- public static boolean checkSlimeSpawnRules(EntityType<Slime> slime, LevelAccessor level, MobSpawnType spawnType, BlockPos pos, RandomSource random) { +- if (MobSpawnType.isSpawner(spawnType)) { ++ public static boolean checkSlimeSpawnRules(EntityType<Slime> slime, LevelAccessor level, EnumMobSpawn spawnType, BlockPos pos, RandomSource random) { ++ if (EnumMobSpawn.isSpawner(spawnType)) { + return checkMobSpawnRules(slime, level, spawnType, pos, random); + } else { + if (level.getDifficulty() != Difficulty.PEACEFUL) { +- if (spawnType == MobSpawnType.SPAWNER) { ++ if (spawnType == EnumMobSpawn.SPAWNER) { + return checkMobSpawnRules(slime, level, spawnType, pos, random); + } + +- if (level.getBiome(pos).is(BiomeTags.ALLOWS_SURFACE_SLIME_SPAWNS) +- && pos.getY() > 50 +- && pos.getY() < 70 +- && random.nextFloat() < 0.5F +- && random.nextFloat() < level.getMoonBrightness() +- && level.getMaxLocalRawBrightness(pos) <= random.nextInt(8)) { ++ if (level.getBiome(pos).is(BiomeTags.ALLOWS_SURFACE_SLIME_SPAWNS) && pos.getY() > 50 && pos.getY() < 70 && random.nextFloat() < 0.5F && random.nextFloat() < level.getMoonBrightness() && level.getMaxLocalRawBrightness(pos) <= random.nextInt(8)) { + return checkMobSpawnRules(slime, level, spawnType, pos, random); + } + +@@ -305,8 +337,9 @@ + return false; + } + +- ChunkPos chunkPos = new ChunkPos(pos); +- boolean flag = WorldgenRandom.seedSlimeChunk(chunkPos.x, chunkPos.z, ((WorldGenLevel)level).getSeed(), 987234911L).nextInt(10) == 0; ++ ChunkPos chunkcoordintpair = new ChunkPos(pos); ++ boolean flag = WorldgenRandom.seedSlimeChunk(chunkcoordintpair.x, chunkcoordintpair.z, ((WorldGenLevel) level).getSeed(), 987234911L).nextInt(10) == 0; ++ + if (random.nextInt(10) == 0 && flag && pos.getY() < 40) { + return checkMobSpawnRules(slime, level, spawnType, pos, random); + } +@@ -318,7 +351,7 @@ + + @Override + protected float getSoundVolume() { +- return 0.4F * (float)this.getSize(); ++ return 0.4F * (float) this.getSize(); + } + + @Override +@@ -332,29 +365,31 @@ + + @Override + protected void jumpFromGround() { +- Vec3 deltaMovement = this.getDeltaMovement(); +- this.setDeltaMovement(deltaMovement.x, (double)this.getJumpPower(), deltaMovement.z); ++ Vec3 vec3d = this.getDeltaMovement(); ++ ++ this.setDeltaMovement(vec3d.x, (double) this.getJumpPower(), vec3d.z); + this.hasImpulse = true; + } + + @Nullable + @Override +- public SpawnGroupData finalizeSpawn( +- ServerLevelAccessor level, DifficultyInstance difficulty, MobSpawnType reason, @Nullable SpawnGroupData spawnData, @Nullable CompoundTag dataTag +- ) { +- RandomSource random = level.getRandom(); +- int randomInt = random.nextInt(3); +- if (randomInt < 2 && random.nextFloat() < 0.5F * difficulty.getSpecialMultiplier()) { +- randomInt++; ++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) { ++ RandomSource randomsource = level.getRandom(); ++ int i = randomsource.nextInt(3); ++ ++ if (i < 2 && randomsource.nextFloat() < 0.5F * difficulty.getSpecialMultiplier()) { ++ ++i; + } + +- int i = 1 << randomInt; +- this.setSize(i, true); ++ int j = 1 << i; ++ ++ this.setSize(j, true); + return super.finalizeSpawn(level, difficulty, reason, spawnData, dataTag); + } + + float getSoundPitch() { + float f = this.isTiny() ? 1.4F : 0.8F; ++ + return ((this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 1.0F) * f; + } + +@@ -363,61 +398,74 @@ + } + + @Override +- public EntityDimensions getDimensions(Pose pose) { +- return super.getDimensions(pose).scale(0.255F * (float)this.getSize()); ++ public EntityDimensions getDimensions(EntityPose pose) { ++ return super.getDimensions(pose).scale(0.255F * (float) this.getSize()); + } + +- static class SlimeAttackGoal extends Goal { ++ private static class SlimeMoveControl extends MoveControl { ++ ++ private float yRot; ++ private int jumpDelay; + private final Slime slime; +- private int growTiredTimer; ++ private boolean isAggressive; + +- public SlimeAttackGoal(Slime slime) { ++ public SlimeMoveControl(Slime slime) { ++ super(slime); + this.slime = slime; +- this.setFlags(EnumSet.of(Goal.Flag.LOOK)); ++ this.yRot = 180.0F * slime.getYRot() / 3.1415927F; + } + +- @Override +- public boolean canUse() { +- LivingEntity target = this.slime.getTarget(); +- return target != null && this.slime.canAttack(target) && this.slime.getMoveControl() instanceof Slime.SlimeMoveControl; ++ public void setDirection(float yRot, boolean aggressive) { ++ this.yRot = yRot; ++ this.isAggressive = aggressive; + } + +- @Override +- public void start() { +- this.growTiredTimer = reducedTickDelay(300); +- super.start(); ++ public void setWantedMovement(double speed) { ++ this.speedModifier = speed; ++ this.operation = MoveControl.Operation.MOVE_TO; + } + + @Override +- public boolean canContinueToUse() { +- LivingEntity target = this.slime.getTarget(); +- return target != null && this.slime.canAttack(target) && --this.growTiredTimer > 0; +- } ++ public void tick() { ++ this.mob.setYRot(this.rotlerp(this.mob.getYRot(), this.yRot, 90.0F)); ++ this.mob.yHeadRot = this.mob.getYRot(); ++ this.mob.yBodyRot = this.mob.getYRot(); ++ if (this.operation != MoveControl.Operation.MOVE_TO) { ++ this.mob.setZza(0.0F); ++ } else { ++ this.operation = MoveControl.Operation.WAIT; ++ if (this.mob.onGround()) { ++ this.mob.setSpeed((float) (this.speedModifier * this.mob.getAttributeValue(Attributes.MOVEMENT_SPEED))); ++ if (this.jumpDelay-- <= 0) { ++ this.jumpDelay = this.slime.getJumpDelay(); ++ if (this.isAggressive) { ++ this.jumpDelay /= 3; ++ } + +- @Override +- public boolean requiresUpdateEveryTick() { +- return true; +- } ++ this.slime.getJumpControl().jump(); ++ if (this.slime.doPlayJumpSound()) { ++ this.slime.playSound(this.slime.getJumpSound(), this.slime.getSoundVolume(), this.slime.getSoundPitch()); ++ } ++ } else { ++ this.slime.xxa = 0.0F; ++ this.slime.zza = 0.0F; ++ this.mob.setSpeed(0.0F); ++ } ++ } else { ++ this.mob.setSpeed((float) (this.speedModifier * this.mob.getAttributeValue(Attributes.MOVEMENT_SPEED))); ++ } + +- @Override +- public void tick() { +- LivingEntity target = this.slime.getTarget(); +- if (target != null) { +- this.slime.lookAt(target, 10.0F, 10.0F); + } +- +- if (this.slime.getMoveControl() instanceof Slime.SlimeMoveControl slimeMoveControl) { +- slimeMoveControl.setDirection(this.slime.getYRot(), this.slime.isDealsDamage()); +- } + } + } + +- static class SlimeFloatGoal extends Goal { ++ private static class SlimeFloatGoal extends Goal { ++ + private final Slime slime; + + public SlimeFloatGoal(Slime slime) { + this.slime = slime; +- this.setFlags(EnumSet.of(Goal.Flag.JUMP, Goal.Flag.MOVE)); ++ this.setFlags(EnumSet.of(Goal.Type.JUMP, Goal.Type.MOVE)); + slime.getNavigation().setCanFloat(true); + } + +@@ -437,115 +485,129 @@ + this.slime.getJumpControl().jump(); + } + +- if (this.slime.getMoveControl() instanceof Slime.SlimeMoveControl slimeMoveControl) { +- slimeMoveControl.setWantedMovement(1.2); ++ MoveControl controllermove = this.slime.getMoveControl(); ++ ++ if (controllermove instanceof Slime.SlimeMoveControl) { ++ Slime.SlimeMoveControl entityslime_controllermoveslime = (Slime.SlimeMoveControl) controllermove; ++ ++ entityslime_controllermoveslime.setWantedMovement(1.2D); + } ++ + } + } + +- static class SlimeKeepOnJumpingGoal extends Goal { ++ private static class SlimeAttackGoal extends Goal { ++ + private final Slime slime; ++ private int growTiredTimer; + +- public SlimeKeepOnJumpingGoal(Slime slime) { ++ public SlimeAttackGoal(Slime slime) { + this.slime = slime; +- this.setFlags(EnumSet.of(Goal.Flag.JUMP, Goal.Flag.MOVE)); ++ this.setFlags(EnumSet.of(Goal.Type.LOOK)); + } + + @Override + public boolean canUse() { +- return !this.slime.isPassenger(); ++ LivingEntity entityliving = this.slime.getTarget(); ++ ++ return entityliving == null ? false : (!this.slime.canAttack(entityliving) ? false : this.slime.getMoveControl() instanceof Slime.SlimeMoveControl); + } + + @Override +- public void tick() { +- if (this.slime.getMoveControl() instanceof Slime.SlimeMoveControl slimeMoveControl) { +- slimeMoveControl.setWantedMovement(1.0); +- } ++ public void start() { ++ this.growTiredTimer = reducedTickDelay(300); ++ super.start(); + } +- } + +- static class SlimeMoveControl extends MoveControl { +- private float yRot; +- private int jumpDelay; +- private final Slime slime; +- private boolean isAggressive; ++ @Override ++ public boolean canContinueToUse() { ++ LivingEntity entityliving = this.slime.getTarget(); + +- public SlimeMoveControl(Slime mob) { +- super(mob); +- this.slime = mob; +- this.yRot = 180.0F * mob.getYRot() / (float) Math.PI; ++ return entityliving == null ? false : (!this.slime.canAttack(entityliving) ? false : --this.growTiredTimer > 0); + } + +- public void setDirection(float yRot, boolean aggressive) { +- this.yRot = yRot; +- this.isAggressive = aggressive; ++ @Override ++ public boolean requiresUpdateEveryTick() { ++ return true; + } + +- public void setWantedMovement(double speed) { +- this.speedModifier = speed; +- this.operation = MoveControl.Operation.MOVE_TO; +- } +- + @Override + public void tick() { +- this.mob.setYRot(this.rotlerp(this.mob.getYRot(), this.yRot, 90.0F)); +- this.mob.yHeadRot = this.mob.getYRot(); +- this.mob.yBodyRot = this.mob.getYRot(); +- if (this.operation != MoveControl.Operation.MOVE_TO) { +- this.mob.setZza(0.0F); +- } else { +- this.operation = MoveControl.Operation.WAIT; +- if (this.mob.onGround()) { +- this.mob.setSpeed((float)(this.speedModifier * this.mob.getAttributeValue(Attributes.MOVEMENT_SPEED))); +- if (this.jumpDelay-- <= 0) { +- this.jumpDelay = this.slime.getJumpDelay(); +- if (this.isAggressive) { +- this.jumpDelay /= 3; +- } ++ LivingEntity entityliving = this.slime.getTarget(); + +- this.slime.getJumpControl().jump(); +- if (this.slime.doPlayJumpSound()) { +- this.slime.playSound(this.slime.getJumpSound(), this.slime.getSoundVolume(), this.slime.getSoundPitch()); +- } +- } else { +- this.slime.xxa = 0.0F; +- this.slime.zza = 0.0F; +- this.mob.setSpeed(0.0F); +- } +- } else { +- this.mob.setSpeed((float)(this.speedModifier * this.mob.getAttributeValue(Attributes.MOVEMENT_SPEED))); +- } ++ if (entityliving != null) { ++ this.slime.lookAt(entityliving, 10.0F, 10.0F); + } ++ ++ MoveControl controllermove = this.slime.getMoveControl(); ++ ++ if (controllermove instanceof Slime.SlimeMoveControl) { ++ Slime.SlimeMoveControl entityslime_controllermoveslime = (Slime.SlimeMoveControl) controllermove; ++ ++ entityslime_controllermoveslime.setDirection(this.slime.getYRot(), this.slime.isDealsDamage()); ++ } ++ + } + } + +- static class SlimeRandomDirectionGoal extends Goal { ++ private static class SlimeRandomDirectionGoal extends Goal { ++ + private final Slime slime; + private float chosenDegrees; + private int nextRandomizeTime; + + public SlimeRandomDirectionGoal(Slime slime) { + this.slime = slime; +- this.setFlags(EnumSet.of(Goal.Flag.LOOK)); ++ this.setFlags(EnumSet.of(Goal.Type.LOOK)); + } + + @Override + public boolean canUse() { +- return this.slime.getTarget() == null +- && (this.slime.onGround() || this.slime.isInWater() || this.slime.isInLava() || this.slime.hasEffect(MobEffects.LEVITATION)) +- && this.slime.getMoveControl() instanceof Slime.SlimeMoveControl; ++ return this.slime.getTarget() == null && (this.slime.onGround() || this.slime.isInWater() || this.slime.isInLava() || this.slime.hasEffect(MobEffects.LEVITATION)) && this.slime.getMoveControl() instanceof Slime.SlimeMoveControl; + } + + @Override + public void tick() { + if (--this.nextRandomizeTime <= 0) { + this.nextRandomizeTime = this.adjustedTickDelay(40 + this.slime.getRandom().nextInt(60)); +- this.chosenDegrees = (float)this.slime.getRandom().nextInt(360); ++ this.chosenDegrees = (float) this.slime.getRandom().nextInt(360); + } + +- if (this.slime.getMoveControl() instanceof Slime.SlimeMoveControl slimeMoveControl) { +- slimeMoveControl.setDirection(this.chosenDegrees, false); ++ MoveControl controllermove = this.slime.getMoveControl(); ++ ++ if (controllermove instanceof Slime.SlimeMoveControl) { ++ Slime.SlimeMoveControl entityslime_controllermoveslime = (Slime.SlimeMoveControl) controllermove; ++ ++ entityslime_controllermoveslime.setDirection(this.chosenDegrees, false); + } ++ + } + } ++ ++ private static class SlimeKeepOnJumpingGoal extends Goal { ++ ++ private final Slime slime; ++ ++ public SlimeKeepOnJumpingGoal(Slime slime) { ++ this.slime = slime; ++ this.setFlags(EnumSet.of(Goal.Type.JUMP, Goal.Type.MOVE)); ++ } ++ ++ @Override ++ public boolean canUse() { ++ return !this.slime.isPassenger(); ++ } ++ ++ @Override ++ public void tick() { ++ MoveControl controllermove = this.slime.getMoveControl(); ++ ++ if (controllermove instanceof Slime.SlimeMoveControl) { ++ Slime.SlimeMoveControl entityslime_controllermoveslime = (Slime.SlimeMoveControl) controllermove; ++ ++ entityslime_controllermoveslime.setWantedMovement(1.0D); ++ } ++ ++ } ++ } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/SpellcasterIllager.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/SpellcasterIllager.java.patch new file mode 100644 index 0000000000..c726efdf25 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/SpellcasterIllager.java.patch @@ -0,0 +1,271 @@ +--- a/net/minecraft/world/entity/monster/SpellcasterIllager.java ++++ b/net/minecraft/world/entity/monster/SpellcasterIllager.java +@@ -15,20 +15,25 @@ + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.ai.goal.Goal; + import net.minecraft.world.level.Level; ++// CraftBukkit start ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++// CraftBukkit end + + public abstract class SpellcasterIllager extends AbstractIllager { ++ + private static final EntityDataAccessor<Byte> DATA_SPELL_CASTING_ID = SynchedEntityData.defineId(SpellcasterIllager.class, EntityDataSerializers.BYTE); + protected int spellCastingTickCount; +- private SpellcasterIllager.IllagerSpell currentSpell = SpellcasterIllager.IllagerSpell.NONE; ++ private SpellcasterIllager.IllagerSpell currentSpell; + + protected SpellcasterIllager(EntityType<? extends SpellcasterIllager> entityType, Level level) { + super(entityType, level); ++ this.currentSpell = SpellcasterIllager.IllagerSpell.NONE; + } + + @Override + protected void defineSynchedData() { + super.defineSynchedData(); +- this.entityData.define(DATA_SPELL_CASTING_ID, (byte)0); ++ this.entityData.define(SpellcasterIllager.DATA_SPELL_CASTING_ID, (byte) 0); + } + + @Override +@@ -44,51 +49,48 @@ + } + + @Override +- public AbstractIllager.IllagerArmPose getArmPose() { +- if (this.isCastingSpell()) { +- return AbstractIllager.IllagerArmPose.SPELLCASTING; +- } else { +- return this.isCelebrating() ? AbstractIllager.IllagerArmPose.CELEBRATING : AbstractIllager.IllagerArmPose.CROSSED; +- } ++ public AbstractIllager.a getArmPose() { ++ return this.isCastingSpell() ? AbstractIllager.a.SPELLCASTING : (this.isCelebrating() ? AbstractIllager.a.CELEBRATING : AbstractIllager.a.CROSSED); + } + + public boolean isCastingSpell() { +- return this.level().isClientSide ? this.entityData.get(DATA_SPELL_CASTING_ID) > 0 : this.spellCastingTickCount > 0; ++ return this.level().isClientSide ? (Byte) this.entityData.get(SpellcasterIllager.DATA_SPELL_CASTING_ID) > 0 : this.spellCastingTickCount > 0; + } + + public void setIsCastingSpell(SpellcasterIllager.IllagerSpell currentSpell) { + this.currentSpell = currentSpell; +- this.entityData.set(DATA_SPELL_CASTING_ID, (byte)currentSpell.id); ++ this.entityData.set(SpellcasterIllager.DATA_SPELL_CASTING_ID, (byte) currentSpell.id); + } + +- protected SpellcasterIllager.IllagerSpell getCurrentSpell() { +- return !this.level().isClientSide ? this.currentSpell : SpellcasterIllager.IllagerSpell.byId(this.entityData.get(DATA_SPELL_CASTING_ID)); ++ public SpellcasterIllager.IllagerSpell getCurrentSpell() { ++ return !this.level().isClientSide ? this.currentSpell : SpellcasterIllager.IllagerSpell.byId((Byte) this.entityData.get(SpellcasterIllager.DATA_SPELL_CASTING_ID)); + } + + @Override + protected void customServerAiStep() { + super.customServerAiStep(); + if (this.spellCastingTickCount > 0) { +- this.spellCastingTickCount--; ++ --this.spellCastingTickCount; + } ++ + } + + @Override + public void tick() { + super.tick(); + if (this.level().isClientSide && this.isCastingSpell()) { +- SpellcasterIllager.IllagerSpell currentSpell = this.getCurrentSpell(); +- double d = currentSpell.spellColor[0]; +- double d1 = currentSpell.spellColor[1]; +- double d2 = currentSpell.spellColor[2]; +- float f = this.yBodyRot * (float) (Math.PI / 180.0) + Mth.cos((float)this.tickCount * 0.6662F) * 0.25F; +- float cos = Mth.cos(f); +- float sin = Mth.sin(f); +- this.level() +- .addParticle(ParticleTypes.ENTITY_EFFECT, this.getX() + (double)cos * 0.6, this.getY() + 1.8, this.getZ() + (double)sin * 0.6, d, d1, d2); +- this.level() +- .addParticle(ParticleTypes.ENTITY_EFFECT, this.getX() - (double)cos * 0.6, this.getY() + 1.8, this.getZ() - (double)sin * 0.6, d, d1, d2); ++ SpellcasterIllager.IllagerSpell entityillagerwizard_spell = this.getCurrentSpell(); ++ double d0 = entityillagerwizard_spell.spellColor[0]; ++ double d1 = entityillagerwizard_spell.spellColor[1]; ++ double d2 = entityillagerwizard_spell.spellColor[2]; ++ float f = this.yBodyRot * 0.017453292F + Mth.cos((float) this.tickCount * 0.6662F) * 0.25F; ++ float f1 = Mth.cos(f); ++ float f2 = Mth.sin(f); ++ ++ this.level().addParticle(ParticleTypes.ENTITY_EFFECT, this.getX() + (double) f1 * 0.6D, this.getY() + 1.8D, this.getZ() + (double) f2 * 0.6D, d0, d1, d2); ++ this.level().addParticle(ParticleTypes.ENTITY_EFFECT, this.getX() - (double) f1 * 0.6D, this.getY() + 1.8D, this.getZ() - (double) f2 * 0.6D, d0, d1, d2); + } ++ + } + + protected int getSpellCastingTime() { +@@ -97,80 +99,45 @@ + + protected abstract SoundEvent getCastingSoundEvent(); + +- protected static enum IllagerSpell { +- NONE(0, 0.0, 0.0, 0.0), +- SUMMON_VEX(1, 0.7, 0.7, 0.8), +- FANGS(2, 0.4, 0.3, 0.35), +- WOLOLO(3, 0.7, 0.5, 0.2), +- DISAPPEAR(4, 0.3, 0.3, 0.8), +- BLINDNESS(5, 0.1, 0.1, 0.2); ++ public static enum IllagerSpell { + +- private static final IntFunction<SpellcasterIllager.IllagerSpell> BY_ID = ByIdMap.continuous( +- illagerSpell -> illagerSpell.id, values(), ByIdMap.OutOfBoundsStrategy.ZERO +- ); ++ NONE(0, 0.0D, 0.0D, 0.0D), SUMMON_VEX(1, 0.7D, 0.7D, 0.8D), FANGS(2, 0.4D, 0.3D, 0.35D), WOLOLO(3, 0.7D, 0.5D, 0.2D), DISAPPEAR(4, 0.3D, 0.3D, 0.8D), BLINDNESS(5, 0.1D, 0.1D, 0.2D); ++ ++ private static final IntFunction<SpellcasterIllager.IllagerSpell> BY_ID = ByIdMap.continuous((entityillagerwizard_spell) -> { ++ return entityillagerwizard_spell.id; ++ }, values(), ByIdMap.a.ZERO); + final int id; + final double[] spellColor; + +- private IllagerSpell(int id, double red, double green, double blue) { +- this.id = id; +- this.spellColor = new double[]{red, green, blue}; ++ private IllagerSpell(int i, double d0, double d1, double d2) { ++ this.id = i; ++ this.spellColor = new double[]{d0, d1, d2}; + } + + public static SpellcasterIllager.IllagerSpell byId(int id) { +- return BY_ID.apply(id); ++ return (SpellcasterIllager.IllagerSpell) SpellcasterIllager.IllagerSpell.BY_ID.apply(id); + } + } + +- protected class SpellcasterCastingSpellGoal extends Goal { +- public SpellcasterCastingSpellGoal() { +- this.setFlags(EnumSet.of(Goal.Flag.MOVE, Goal.Flag.LOOK)); +- } +- +- @Override +- public boolean canUse() { +- return SpellcasterIllager.this.getSpellCastingTime() > 0; +- } +- +- @Override +- public void start() { +- super.start(); +- SpellcasterIllager.this.navigation.stop(); +- } +- +- @Override +- public void stop() { +- super.stop(); +- SpellcasterIllager.this.setIsCastingSpell(SpellcasterIllager.IllagerSpell.NONE); +- } +- +- @Override +- public void tick() { +- if (SpellcasterIllager.this.getTarget() != null) { +- SpellcasterIllager.this.getLookControl() +- .setLookAt( +- SpellcasterIllager.this.getTarget(), (float)SpellcasterIllager.this.getMaxHeadYRot(), (float)SpellcasterIllager.this.getMaxHeadXRot() +- ); +- } +- } +- } +- + protected abstract class SpellcasterUseSpellGoal extends Goal { ++ + protected int attackWarmupDelay; + protected int nextAttackTickCount; + ++ protected SpellcasterUseSpellGoal() {} ++ + @Override + public boolean canUse() { +- LivingEntity target = SpellcasterIllager.this.getTarget(); +- return target != null +- && target.isAlive() +- && !SpellcasterIllager.this.isCastingSpell() +- && SpellcasterIllager.this.tickCount >= this.nextAttackTickCount; ++ LivingEntity entityliving = SpellcasterIllager.this.getTarget(); ++ ++ return entityliving != null && entityliving.isAlive() ? (SpellcasterIllager.this.isCastingSpell() ? false : SpellcasterIllager.this.tickCount >= this.nextAttackTickCount) : false; + } + + @Override + public boolean canContinueToUse() { +- LivingEntity target = SpellcasterIllager.this.getTarget(); +- return target != null && target.isAlive() && this.attackWarmupDelay > 0; ++ LivingEntity entityliving = SpellcasterIllager.this.getTarget(); ++ ++ return entityliving != null && entityliving.isAlive() && this.attackWarmupDelay > 0; + } + + @Override +@@ -178,9 +145,10 @@ + this.attackWarmupDelay = this.adjustedTickDelay(this.getCastWarmupTime()); + SpellcasterIllager.this.spellCastingTickCount = this.getCastingTime(); + this.nextAttackTickCount = SpellcasterIllager.this.tickCount + this.getCastingInterval(); +- SoundEvent spellPrepareSound = this.getSpellPrepareSound(); +- if (spellPrepareSound != null) { +- SpellcasterIllager.this.playSound(spellPrepareSound, 1.0F, 1.0F); ++ SoundEvent soundeffect = this.getSpellPrepareSound(); ++ ++ if (soundeffect != null) { ++ SpellcasterIllager.this.playSound(soundeffect, 1.0F, 1.0F); + } + + SpellcasterIllager.this.setIsCastingSpell(this.getSpell()); +@@ -188,11 +156,17 @@ + + @Override + public void tick() { +- this.attackWarmupDelay--; ++ --this.attackWarmupDelay; + if (this.attackWarmupDelay == 0) { ++ // CraftBukkit start ++ if (!CraftEventFactory.handleEntitySpellCastEvent(SpellcasterIllager.this, this.getSpell())) { ++ return; ++ } ++ // CraftBukkit end + this.performSpellCasting(); + SpellcasterIllager.this.playSound(SpellcasterIllager.this.getCastingSoundEvent(), 1.0F, 1.0F); + } ++ + } + + protected abstract void performSpellCasting(); +@@ -210,4 +184,36 @@ + + protected abstract SpellcasterIllager.IllagerSpell getSpell(); + } ++ ++ protected class SpellcasterCastingSpellGoal extends Goal { ++ ++ public SpellcasterCastingSpellGoal() { ++ this.setFlags(EnumSet.of(Goal.Type.MOVE, Goal.Type.LOOK)); ++ } ++ ++ @Override ++ public boolean canUse() { ++ return SpellcasterIllager.this.getSpellCastingTime() > 0; ++ } ++ ++ @Override ++ public void start() { ++ super.start(); ++ SpellcasterIllager.this.navigation.stop(); ++ } ++ ++ @Override ++ public void stop() { ++ super.stop(); ++ SpellcasterIllager.this.setIsCastingSpell(SpellcasterIllager.IllagerSpell.NONE); ++ } ++ ++ @Override ++ public void tick() { ++ if (SpellcasterIllager.this.getTarget() != null) { ++ SpellcasterIllager.this.getLookControl().setLookAt(SpellcasterIllager.this.getTarget(), (float) SpellcasterIllager.this.getMaxHeadYRot(), (float) SpellcasterIllager.this.getMaxHeadXRot()); ++ } ++ ++ } ++ } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Spider.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Spider.java.patch new file mode 100644 index 0000000000..8019035f12 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Spider.java.patch @@ -0,0 +1,278 @@ +--- a/net/minecraft/world/entity/monster/Spider.java ++++ b/net/minecraft/world/entity/monster/Spider.java +@@ -17,12 +17,12 @@ + import net.minecraft.world.effect.MobEffects; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.EnumMonsterType; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.LivingEntity; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.MobType; +-import net.minecraft.world.entity.Pose; +-import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; + import net.minecraft.world.entity.ai.attributes.Attributes; + import net.minecraft.world.entity.ai.goal.FloatGoal; +@@ -40,11 +40,12 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.ServerLevelAccessor; + import net.minecraft.world.level.block.Blocks; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.phys.Vec3; + import org.joml.Vector3f; + + public class Spider extends Monster { ++ + private static final EntityDataAccessor<Byte> DATA_FLAGS_ID = SynchedEntityData.defineId(Spider.class, EntityDataSerializers.BYTE); + private static final float SPIDER_SPECIAL_EFFECT_CHANCE = 0.1F; + +@@ -57,17 +58,17 @@ + this.goalSelector.addGoal(1, new FloatGoal(this)); + this.goalSelector.addGoal(3, new LeapAtTargetGoal(this, 0.4F)); + this.goalSelector.addGoal(4, new Spider.SpiderAttackGoal(this)); +- this.goalSelector.addGoal(5, new WaterAvoidingRandomStrollGoal(this, 0.8)); ++ this.goalSelector.addGoal(5, new WaterAvoidingRandomStrollGoal(this, 0.8D)); + this.goalSelector.addGoal(6, new LookAtPlayerGoal(this, Player.class, 8.0F)); + this.goalSelector.addGoal(6, new RandomLookAroundGoal(this)); +- this.targetSelector.addGoal(1, new HurtByTargetGoal(this)); ++ this.targetSelector.addGoal(1, new HurtByTargetGoal(this, new Class[0])); + this.targetSelector.addGoal(2, new Spider.SpiderTargetGoal<>(this, Player.class)); + this.targetSelector.addGoal(3, new Spider.SpiderTargetGoal<>(this, IronGolem.class)); + } + + @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entityDimensions, float f) { +- return new Vector3f(0.0F, entityDimensions.height * 0.85F, 0.0F); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ return new Vector3f(0.0F, entitysize.height * 0.85F, 0.0F); + } + + @Override +@@ -78,7 +79,7 @@ + @Override + protected void defineSynchedData() { + super.defineSynchedData(); +- this.entityData.define(DATA_FLAGS_ID, (byte)0); ++ this.entityData.define(Spider.DATA_FLAGS_ID, (byte) 0); + } + + @Override +@@ -87,10 +88,11 @@ + if (!this.level().isClientSide) { + this.setClimbing(this.horizontalCollision); + } ++ + } + + public static AttributeSupplier.Builder createAttributes() { +- return Monster.createMonsterAttributes().add(Attributes.MAX_HEALTH, 16.0).add(Attributes.MOVEMENT_SPEED, 0.3F); ++ return Monster.createMonsterAttributes().add(Attributes.MAX_HEALTH, 16.0D).add(Attributes.MOVEMENT_SPEED, 0.30000001192092896D); + } + + @Override +@@ -109,7 +111,7 @@ + } + + @Override +- protected void playStepSound(BlockPos pos, BlockState block) { ++ protected void playStepSound(BlockPos pos, IBlockData block) { + this.playSound(SoundEvents.SPIDER_STEP, 0.15F, 1.0F); + } + +@@ -119,72 +121,76 @@ + } + + @Override +- public void makeStuckInBlock(BlockState state, Vec3 motionMultiplier) { ++ public void makeStuckInBlock(IBlockData state, Vec3 motionMultiplier) { + if (!state.is(Blocks.COBWEB)) { + super.makeStuckInBlock(state, motionMultiplier); + } ++ + } + + @Override +- public MobType getMobType() { +- return MobType.ARTHROPOD; ++ public EnumMonsterType getMobType() { ++ return EnumMonsterType.ARTHROPOD; + } + + @Override + public boolean canBeAffected(MobEffectInstance potioneffect) { +- return potioneffect.getEffect() != MobEffects.POISON && super.canBeAffected(potioneffect); ++ return potioneffect.getEffect() == MobEffects.POISON ? false : super.canBeAffected(potioneffect); + } + + public boolean isClimbing() { +- return (this.entityData.get(DATA_FLAGS_ID) & 1) != 0; ++ return ((Byte) this.entityData.get(Spider.DATA_FLAGS_ID) & 1) != 0; + } + + public void setClimbing(boolean climbing) { +- byte b = this.entityData.get(DATA_FLAGS_ID); ++ byte b0 = (Byte) this.entityData.get(Spider.DATA_FLAGS_ID); ++ + if (climbing) { +- b = (byte)(b | 1); ++ b0 = (byte) (b0 | 1); + } else { +- b = (byte)(b & -2); ++ b0 &= -2; + } + +- this.entityData.set(DATA_FLAGS_ID, b); ++ this.entityData.set(Spider.DATA_FLAGS_ID, b0); + } + + @Nullable + @Override +- public SpawnGroupData finalizeSpawn( +- ServerLevelAccessor level, DifficultyInstance difficulty, MobSpawnType reason, @Nullable SpawnGroupData spawnData, @Nullable CompoundTag dataTag +- ) { +- SpawnGroupData var9 = super.finalizeSpawn(level, difficulty, reason, spawnData, dataTag); +- RandomSource random = level.getRandom(); +- if (random.nextInt(100) == 0) { +- Skeleton skeleton = EntityType.SKELETON.create(this.level()); +- if (skeleton != null) { +- skeleton.moveTo(this.getX(), this.getY(), this.getZ(), this.getYRot(), 0.0F); +- skeleton.finalizeSpawn(level, difficulty, reason, null, null); +- skeleton.startRiding(this); ++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) { ++ Object object = super.finalizeSpawn(level, difficulty, reason, spawnData, dataTag); ++ RandomSource randomsource = level.getRandom(); ++ ++ if (randomsource.nextInt(100) == 0) { ++ Skeleton entityskeleton = (Skeleton) EntityType.SKELETON.create(this.level()); ++ ++ if (entityskeleton != null) { ++ entityskeleton.moveTo(this.getX(), this.getY(), this.getZ(), this.getYRot(), 0.0F); ++ entityskeleton.finalizeSpawn(level, difficulty, reason, (GroupDataEntity) null, (CompoundTag) null); ++ entityskeleton.startRiding(this); + } + } + +- if (var9 == null) { +- var9 = new Spider.SpiderEffectsGroupData(); +- if (level.getDifficulty() == Difficulty.HARD && random.nextFloat() < 0.1F * difficulty.getSpecialMultiplier()) { +- ((Spider.SpiderEffectsGroupData)var9).setRandomEffect(random); ++ if (object == null) { ++ object = new Spider.SpiderEffectsGroupData(); ++ if (level.getDifficulty() == Difficulty.HARD && randomsource.nextFloat() < 0.1F * difficulty.getSpecialMultiplier()) { ++ ((Spider.SpiderEffectsGroupData) object).setRandomEffect(randomsource); + } + } + +- if (var9 instanceof Spider.SpiderEffectsGroupData spiderEffectsGroupData) { +- MobEffect mobEffect = spiderEffectsGroupData.effect; +- if (mobEffect != null) { +- this.addEffect(new MobEffectInstance(mobEffect, -1)); ++ if (object instanceof Spider.SpiderEffectsGroupData) { ++ Spider.SpiderEffectsGroupData entityspider_groupdataspider = (Spider.SpiderEffectsGroupData) object; ++ MobEffect mobeffectlist = entityspider_groupdataspider.effect; ++ ++ if (mobeffectlist != null) { ++ this.addEffect(new MobEffectInstance(mobeffectlist, -1), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.SPIDER_SPAWN); // CraftBukkit + } + } + +- return (SpawnGroupData)var9; ++ return (GroupDataEntity) object; + } + + @Override +- protected float getStandingEyeHeight(Pose pose, EntityDimensions size) { ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions size) { + return 0.65F; + } + +@@ -193,9 +199,10 @@ + return entity.getBbWidth() <= this.getBbWidth() ? -0.3125F : 0.0F; + } + +- static class SpiderAttackGoal extends MeleeAttackGoal { ++ private static class SpiderAttackGoal extends MeleeAttackGoal { ++ + public SpiderAttackGoal(Spider spider) { +- super(spider, 1.0, true); ++ super(spider, 1.0D, true); + } + + @Override +@@ -205,9 +212,10 @@ + + @Override + public boolean canContinueToUse() { +- float lightLevelDependentMagicValue = this.mob.getLightLevelDependentMagicValue(); +- if (lightLevelDependentMagicValue >= 0.5F && this.mob.getRandom().nextInt(100) == 0) { +- this.mob.setTarget(null); ++ float f = this.mob.getLightLevelDependentMagicValue(); ++ ++ if (f >= 0.5F && this.mob.getRandom().nextInt(100) == 0) { ++ this.mob.setTarget((LivingEntity) null); + return false; + } else { + return super.canContinueToUse(); +@@ -215,33 +223,40 @@ + } + } + +- public static class SpiderEffectsGroupData implements SpawnGroupData { ++ private static class SpiderTargetGoal<T extends LivingEntity> extends NearestAttackableTargetGoal<T> { ++ ++ public SpiderTargetGoal(Spider spider, Class<T> entityTypeToTarget) { ++ super(spider, entityTypeToTarget, true); ++ } ++ ++ @Override ++ public boolean canUse() { ++ float f = this.mob.getLightLevelDependentMagicValue(); ++ ++ return f >= 0.5F ? false : super.canUse(); ++ } ++ } ++ ++ public static class SpiderEffectsGroupData implements GroupDataEntity { ++ + @Nullable + public MobEffect effect; + ++ public SpiderEffectsGroupData() {} ++ + public void setRandomEffect(RandomSource random) { +- int randomInt = random.nextInt(5); +- if (randomInt <= 1) { ++ int i = random.nextInt(5); ++ ++ if (i <= 1) { + this.effect = MobEffects.MOVEMENT_SPEED; +- } else if (randomInt <= 2) { ++ } else if (i <= 2) { + this.effect = MobEffects.DAMAGE_BOOST; +- } else if (randomInt <= 3) { ++ } else if (i <= 3) { + this.effect = MobEffects.REGENERATION; +- } else if (randomInt <= 4) { ++ } else if (i <= 4) { + this.effect = MobEffects.INVISIBILITY; + } +- } +- } + +- static class SpiderTargetGoal<T extends LivingEntity> extends NearestAttackableTargetGoal<T> { +- public SpiderTargetGoal(Spider spider, Class<T> entityTypeToTarget) { +- super(spider, entityTypeToTarget, true); + } +- +- @Override +- public boolean canUse() { +- float lightLevelDependentMagicValue = this.mob.getLightLevelDependentMagicValue(); +- return !(lightLevelDependentMagicValue >= 0.5F) && super.canUse(); +- } + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Strider.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Strider.java.patch new file mode 100644 index 0000000000..23517c9040 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Strider.java.patch @@ -0,0 +1,583 @@ +--- a/net/minecraft/world/entity/monster/Strider.java ++++ b/net/minecraft/world/entity/monster/Strider.java +@@ -1,6 +1,8 @@ + package net.minecraft.world.entity.monster; + + import com.google.common.collect.Sets; ++import com.google.common.collect.UnmodifiableIterator; ++import java.util.Iterator; + import java.util.Set; + import java.util.UUID; + import javax.annotation.Nullable; +@@ -19,22 +21,22 @@ + import net.minecraft.util.Mth; + import net.minecraft.util.RandomSource; + import net.minecraft.world.DifficultyInstance; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.AgeableMob; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; + import net.minecraft.world.entity.EquipmentSlot; ++import net.minecraft.world.entity.GroupDataEntity; ++import net.minecraft.world.entity.ISteerable; + import net.minecraft.world.entity.ItemBasedSteering; +-import net.minecraft.world.entity.ItemSteerable; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.Pose; + import net.minecraft.world.entity.Saddleable; +-import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.ai.attributes.AttributeInstance; + import net.minecraft.world.entity.ai.attributes.AttributeModifier; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; +@@ -55,28 +57,28 @@ + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.Items; + import net.minecraft.world.item.crafting.Ingredient; ++import net.minecraft.world.level.IMaterial; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.ServerLevelAccessor; + import net.minecraft.world.level.block.Blocks; + import net.minecraft.world.level.block.LiquidBlock; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.material.FluidState; + import net.minecraft.world.level.pathfinder.BlockPathTypes; +-import net.minecraft.world.level.pathfinder.PathComputationType; + import net.minecraft.world.level.pathfinder.PathFinder; ++import net.minecraft.world.level.pathfinder.PathMode; + import net.minecraft.world.level.pathfinder.WalkNodeEvaluator; + import net.minecraft.world.phys.AABB; + import net.minecraft.world.phys.Vec3; + import net.minecraft.world.phys.shapes.CollisionContext; + import org.joml.Vector3f; + +-public class Strider extends Animal implements ItemSteerable, Saddleable { ++public class Strider extends Animal implements ISteerable, Saddleable { ++ + private static final UUID SUFFOCATING_MODIFIER_UUID = UUID.fromString("9e362924-01de-4ddd-a2b2-d0f7a405a174"); +- private static final AttributeModifier SUFFOCATING_MODIFIER = new AttributeModifier( +- SUFFOCATING_MODIFIER_UUID, "Strider suffocating modifier", -0.34F, AttributeModifier.Operation.MULTIPLY_BASE +- ); ++ private static final AttributeModifier SUFFOCATING_MODIFIER = new AttributeModifier(Strider.SUFFOCATING_MODIFIER_UUID, "Strider suffocating modifier", -0.3400000035762787D, AttributeModifier.Operation.MULTIPLY_BASE); + private static final float SUFFOCATE_STEERING_MODIFIER = 0.35F; + private static final float STEERING_MODIFIER = 0.55F; + private static final Ingredient FOOD_ITEMS = Ingredient.of(Items.WARPED_FUNGUS); +@@ -84,12 +86,13 @@ + private static final EntityDataAccessor<Integer> DATA_BOOST_TIME = SynchedEntityData.defineId(Strider.class, EntityDataSerializers.INT); + private static final EntityDataAccessor<Boolean> DATA_SUFFOCATING = SynchedEntityData.defineId(Strider.class, EntityDataSerializers.BOOLEAN); + private static final EntityDataAccessor<Boolean> DATA_SADDLE_ID = SynchedEntityData.defineId(Strider.class, EntityDataSerializers.BOOLEAN); +- private final ItemBasedSteering steering = new ItemBasedSteering(this.entityData, DATA_BOOST_TIME, DATA_SADDLE_ID); ++ public final ItemBasedSteering steering; + @Nullable + private TemptGoal temptGoal; + + public Strider(EntityType<? extends Strider> entityType, Level level) { + super(entityType, level); ++ this.steering = new ItemBasedSteering(this.entityData, Strider.DATA_BOOST_TIME, Strider.DATA_SADDLE_ID); + this.blocksBuilding = true; + this.setPathfindingMalus(BlockPathTypes.WATER, -1.0F); + this.setPathfindingMalus(BlockPathTypes.LAVA, 0.0F); +@@ -97,19 +100,19 @@ + this.setPathfindingMalus(BlockPathTypes.DAMAGE_FIRE, 0.0F); + } + +- public static boolean checkStriderSpawnRules(EntityType<Strider> strider, LevelAccessor level, MobSpawnType spawnType, BlockPos pos, RandomSource random) { +- BlockPos.MutableBlockPos mutableBlockPos = pos.mutable(); ++ public static boolean checkStriderSpawnRules(EntityType<Strider> strider, LevelAccessor level, EnumMobSpawn spawnType, BlockPos pos, RandomSource random) { ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = pos.mutable(); + + do { +- mutableBlockPos.move(Direction.UP); +- } while (level.getFluidState(mutableBlockPos).is(FluidTags.LAVA)); ++ blockposition_mutableblockposition.move(Direction.UP); ++ } while (level.getFluidState(blockposition_mutableblockposition).is(FluidTags.LAVA)); + +- return level.getBlockState(mutableBlockPos).isAir(); ++ return level.getBlockState(blockposition_mutableblockposition).isAir(); + } + + @Override + public void onSyncedDataUpdated(EntityDataAccessor<?> key) { +- if (DATA_BOOST_TIME.equals(key) && this.level().isClientSide) { ++ if (Strider.DATA_BOOST_TIME.equals(key) && this.level().isClientSide) { + this.steering.onSynced(); + } + +@@ -119,9 +122,9 @@ + @Override + protected void defineSynchedData() { + super.defineSynchedData(); +- this.entityData.define(DATA_BOOST_TIME, 0); +- this.entityData.define(DATA_SUFFOCATING, false); +- this.entityData.define(DATA_SADDLE_ID, false); ++ this.entityData.define(Strider.DATA_BOOST_TIME, 0); ++ this.entityData.define(Strider.DATA_SUFFOCATING, false); ++ this.entityData.define(Strider.DATA_SADDLE_ID, false); + } + + @Override +@@ -150,37 +153,40 @@ + public void equipSaddle(@Nullable SoundSource source) { + this.steering.setSaddle(true); + if (source != null) { +- this.level().playSound(null, this, SoundEvents.STRIDER_SADDLE, source, 0.5F, 1.0F); ++ this.level().playSound((Player) null, (Entity) this, SoundEvents.STRIDER_SADDLE, source, 0.5F, 1.0F); + } ++ + } + + @Override + protected void registerGoals() { +- this.goalSelector.addGoal(1, new PanicGoal(this, 1.65)); +- this.goalSelector.addGoal(2, new BreedGoal(this, 1.0)); +- this.temptGoal = new TemptGoal(this, 1.4, TEMPT_ITEMS, false); ++ this.goalSelector.addGoal(1, new PanicGoal(this, 1.65D)); ++ this.goalSelector.addGoal(2, new BreedGoal(this, 1.0D)); ++ this.temptGoal = new TemptGoal(this, 1.4D, Strider.TEMPT_ITEMS, false); + this.goalSelector.addGoal(3, this.temptGoal); +- this.goalSelector.addGoal(4, new Strider.StriderGoToLavaGoal(this, 1.0)); +- this.goalSelector.addGoal(5, new FollowParentGoal(this, 1.0)); +- this.goalSelector.addGoal(7, new RandomStrollGoal(this, 1.0, 60)); ++ this.goalSelector.addGoal(4, new Strider.StriderGoToLavaGoal(this, 1.0D)); ++ this.goalSelector.addGoal(5, new FollowParentGoal(this, 1.0D)); ++ this.goalSelector.addGoal(7, new RandomStrollGoal(this, 1.0D, 60)); + this.goalSelector.addGoal(8, new LookAtPlayerGoal(this, Player.class, 8.0F)); + this.goalSelector.addGoal(8, new RandomLookAroundGoal(this)); + this.goalSelector.addGoal(9, new LookAtPlayerGoal(this, Strider.class, 8.0F)); + } + + public void setSuffocating(boolean suffocating) { +- this.entityData.set(DATA_SUFFOCATING, suffocating); +- AttributeInstance attribute = this.getAttribute(Attributes.MOVEMENT_SPEED); +- if (attribute != null) { +- attribute.removeModifier(SUFFOCATING_MODIFIER_UUID); ++ this.entityData.set(Strider.DATA_SUFFOCATING, suffocating); ++ AttributeInstance attributemodifiable = this.getAttribute(Attributes.MOVEMENT_SPEED); ++ ++ if (attributemodifiable != null) { ++ attributemodifiable.removeModifier(Strider.SUFFOCATING_MODIFIER_UUID); + if (suffocating) { +- attribute.addTransientModifier(SUFFOCATING_MODIFIER); ++ attributemodifiable.addTransientModifier(Strider.SUFFOCATING_MODIFIER); + } + } ++ + } + + public boolean isSuffocating() { +- return this.entityData.get(DATA_SUFFOCATING); ++ return (Boolean) this.entityData.get(Strider.DATA_SUFFOCATING); + } + + @Override +@@ -189,11 +195,12 @@ + } + + @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entityDimensions, float f) { +- float min = Math.min(0.25F, this.walkAnimation.speed()); +- float f1 = this.walkAnimation.position(); +- float f2 = 0.12F * Mth.cos(f1 * 1.5F) * 2.0F * min; +- return new Vector3f(0.0F, entityDimensions.height + f2 * f, 0.0F); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ float f1 = Math.min(0.25F, this.walkAnimation.speed()); ++ float f2 = this.walkAnimation.position(); ++ float f3 = 0.12F * Mth.cos(f2 * 1.5F) * 2.0F * f1; ++ ++ return new Vector3f(0.0F, entitysize.height + f3 * f, 0.0F); + } + + @Override +@@ -204,45 +211,61 @@ + @Nullable + @Override + public LivingEntity getControllingPassenger() { +- return (LivingEntity)(this.isSaddled() && this.getFirstPassenger() instanceof Player player && player.isHolding(Items.WARPED_FUNGUS_ON_A_STICK) +- ? player +- : super.getControllingPassenger()); ++ if (this.isSaddled()) { ++ Entity entity = this.getFirstPassenger(); ++ ++ if (entity instanceof Player) { ++ Player entityhuman = (Player) entity; ++ ++ if (entityhuman.isHolding(Items.WARPED_FUNGUS_ON_A_STICK)) { ++ return entityhuman; ++ } ++ } ++ } ++ ++ return super.getControllingPassenger(); + } + + @Override + public Vec3 getDismountLocationForPassenger(LivingEntity livingEntity) { +- Vec3[] vec3s = new Vec3[]{ +- getCollisionHorizontalEscapeVector((double)this.getBbWidth(), (double)livingEntity.getBbWidth(), livingEntity.getYRot()), +- getCollisionHorizontalEscapeVector((double)this.getBbWidth(), (double)livingEntity.getBbWidth(), livingEntity.getYRot() - 22.5F), +- getCollisionHorizontalEscapeVector((double)this.getBbWidth(), (double)livingEntity.getBbWidth(), livingEntity.getYRot() + 22.5F), +- getCollisionHorizontalEscapeVector((double)this.getBbWidth(), (double)livingEntity.getBbWidth(), livingEntity.getYRot() - 45.0F), +- getCollisionHorizontalEscapeVector((double)this.getBbWidth(), (double)livingEntity.getBbWidth(), livingEntity.getYRot() + 45.0F) +- }; ++ Vec3[] avec3d = new Vec3[]{getCollisionHorizontalEscapeVector((double) this.getBbWidth(), (double) livingEntity.getBbWidth(), livingEntity.getYRot()), getCollisionHorizontalEscapeVector((double) this.getBbWidth(), (double) livingEntity.getBbWidth(), livingEntity.getYRot() - 22.5F), getCollisionHorizontalEscapeVector((double) this.getBbWidth(), (double) livingEntity.getBbWidth(), livingEntity.getYRot() + 22.5F), getCollisionHorizontalEscapeVector((double) this.getBbWidth(), (double) livingEntity.getBbWidth(), livingEntity.getYRot() - 45.0F), getCollisionHorizontalEscapeVector((double) this.getBbWidth(), (double) livingEntity.getBbWidth(), livingEntity.getYRot() + 45.0F)}; + Set<BlockPos> set = Sets.newLinkedHashSet(); +- double d = this.getBoundingBox().maxY; +- double d1 = this.getBoundingBox().minY - 0.5; +- BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos(); ++ double d0 = this.getBoundingBox().maxY; ++ double d1 = this.getBoundingBox().minY - 0.5D; ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); ++ Vec3[] avec3d1 = avec3d; ++ int i = avec3d.length; + +- for (Vec3 vec3 : vec3s) { +- mutableBlockPos.set(this.getX() + vec3.x, d, this.getZ() + vec3.z); ++ for (int j = 0; j < i; ++j) { ++ Vec3 vec3d = avec3d1[j]; + +- for (double d2 = d; d2 > d1; d2--) { +- set.add(mutableBlockPos.immutable()); +- mutableBlockPos.move(Direction.DOWN); ++ blockposition_mutableblockposition.set(this.getX() + vec3d.x, d0, this.getZ() + vec3d.z); ++ ++ for (double d2 = d0; d2 > d1; --d2) { ++ set.add(blockposition_mutableblockposition.immutable()); ++ blockposition_mutableblockposition.move(Direction.DOWN); + } + } + +- for (BlockPos blockPos : set) { +- if (!this.level().getFluidState(blockPos).is(FluidTags.LAVA)) { +- double blockFloorHeight = this.level().getBlockFloorHeight(blockPos); +- if (DismountHelper.isBlockFloorValid(blockFloorHeight)) { +- Vec3 vec31 = Vec3.upFromBottomCenterOf(blockPos, blockFloorHeight); ++ Iterator iterator = set.iterator(); + +- for (Pose pose : livingEntity.getDismountPoses()) { +- AABB localBoundsForPose = livingEntity.getLocalBoundsForPose(pose); +- if (DismountHelper.canDismountTo(this.level(), livingEntity, localBoundsForPose.move(vec31))) { +- livingEntity.setPose(pose); +- return vec31; ++ while (iterator.hasNext()) { ++ BlockPos blockposition = (BlockPos) iterator.next(); ++ ++ if (!this.level().getFluidState(blockposition).is(FluidTags.LAVA)) { ++ double d3 = this.level().getBlockFloorHeight(blockposition); ++ ++ if (DismountHelper.isBlockFloorValid(d3)) { ++ Vec3 vec3d1 = Vec3.upFromBottomCenterOf(blockposition, d3); ++ UnmodifiableIterator unmodifiableiterator = livingEntity.getDismountPoses().iterator(); ++ ++ while (unmodifiableiterator.hasNext()) { ++ EntityPose entitypose = (EntityPose) unmodifiableiterator.next(); ++ AABB axisalignedbb = livingEntity.getLocalBoundsForPose(entitypose); ++ ++ if (DismountHelper.canDismountTo(this.level(), livingEntity, axisalignedbb.move(vec3d1))) { ++ livingEntity.setPose(entitypose); ++ return vec3d1; + } + } + } +@@ -262,12 +285,12 @@ + + @Override + protected Vec3 getRiddenInput(Player player, Vec3 travelVector) { +- return new Vec3(0.0, 0.0, 1.0); ++ return new Vec3(0.0D, 0.0D, 1.0D); + } + + @Override + protected float getRiddenSpeed(Player player) { +- return (float)(this.getAttributeValue(Attributes.MOVEMENT_SPEED) * (double)(this.isSuffocating() ? 0.35F : 0.55F) * (double)this.steering.boostFactor()); ++ return (float) (this.getAttributeValue(Attributes.MOVEMENT_SPEED) * (double) (this.isSuffocating() ? 0.35F : 0.55F) * (double) this.steering.boostFactor()); + } + + @Override +@@ -276,7 +299,7 @@ + } + + @Override +- protected void playStepSound(BlockPos pos, BlockState block) { ++ protected void playStepSound(BlockPos pos, IBlockData block) { + this.playSound(this.isInLava() ? SoundEvents.STRIDER_STEP_LAVA : SoundEvents.STRIDER_STEP, 1.0F, 1.0F); + } + +@@ -286,12 +309,12 @@ + } + + @Override +- protected void checkFallDamage(double y, boolean onGround, BlockState state, BlockPos pos) { ++ protected void checkFallDamage(double y, boolean flag, IBlockData onGround, BlockPos state) { + this.checkInsideBlocks(); + if (this.isInLava()) { + this.resetFallDistance(); + } else { +- super.checkFallDamage(y, onGround, state, pos); ++ super.checkFallDamage(y, flag, onGround, state); + } + } + +@@ -305,23 +328,37 @@ + + if (!this.isNoAi()) { + boolean flag; +- boolean var10000; +- label36: { +- BlockState blockState = this.level().getBlockState(this.blockPosition()); +- BlockState blockStateOnLegacy = this.getBlockStateOnLegacy(); +- flag = blockState.is(BlockTags.STRIDER_WARM_BLOCKS) +- || blockStateOnLegacy.is(BlockTags.STRIDER_WARM_BLOCKS) +- || this.getFluidHeight(FluidTags.LAVA) > 0.0; +- if (this.getVehicle() instanceof Strider strider && strider.isSuffocating()) { +- var10000 = true; +- break label36; ++ boolean flag1; ++ label36: ++ { ++ IBlockData iblockdata = this.level().getBlockState(this.blockPosition()); ++ IBlockData iblockdata1 = this.getBlockStateOnLegacy(); ++ ++ flag = iblockdata.is(BlockTags.STRIDER_WARM_BLOCKS) || iblockdata1.is(BlockTags.STRIDER_WARM_BLOCKS) || this.getFluidHeight(FluidTags.LAVA) > 0.0D; ++ Entity entity = this.getVehicle(); ++ ++ if (entity instanceof Strider) { ++ Strider entitystrider = (Strider) entity; ++ ++ if (entitystrider.isSuffocating()) { ++ flag1 = true; ++ break label36; ++ } + } + +- var10000 = false; ++ flag1 = false; + } + +- boolean flag1 = var10000; +- this.setSuffocating(!flag || flag1); ++ boolean flag2 = flag1; ++ ++ // CraftBukkit start ++ boolean suffocating = !flag || flag2; ++ if (suffocating ^ this.isSuffocating()) { ++ if (org.bukkit.craftbukkit.event.CraftEventFactory.callStriderTemperatureChangeEvent(this, suffocating)) { ++ this.setSuffocating(suffocating); ++ } ++ } ++ // CraftBukkit end + } + + super.tick(); +@@ -340,18 +377,19 @@ + + private void floatStrider() { + if (this.isInLava()) { +- CollisionContext collisionContext = CollisionContext.of(this); +- if (collisionContext.isAbove(LiquidBlock.STABLE_SHAPE, this.blockPosition(), true) +- && !this.level().getFluidState(this.blockPosition().above()).is(FluidTags.LAVA)) { ++ CollisionContext voxelshapecollision = CollisionContext.of(this); ++ ++ if (voxelshapecollision.isAbove(LiquidBlock.STABLE_SHAPE, this.blockPosition(), true) && !this.level().getFluidState(this.blockPosition().above()).is(FluidTags.LAVA)) { + this.setOnGround(true); + } else { +- this.setDeltaMovement(this.getDeltaMovement().scale(0.5).add(0.0, 0.05, 0.0)); ++ this.setDeltaMovement(this.getDeltaMovement().scale(0.5D).add(0.0D, 0.05D, 0.0D)); + } + } ++ + } + + public static AttributeSupplier.Builder createAttributes() { +- return Mob.createMobAttributes().add(Attributes.MOVEMENT_SPEED, 0.175F).add(Attributes.FOLLOW_RANGE, 16.0); ++ return Mob.createMobAttributes().add(Attributes.MOVEMENT_SPEED, 0.17499999701976776D).add(Attributes.FOLLOW_RANGE, 16.0D); + } + + @Override +@@ -391,109 +429,101 @@ + + @Override + public float getWalkTargetValue(BlockPos pos, LevelReader level) { +- if (level.getBlockState(pos).getFluidState().is(FluidTags.LAVA)) { +- return 10.0F; +- } else { +- return this.isInLava() ? Float.NEGATIVE_INFINITY : 0.0F; +- } ++ return level.getBlockState(pos).getFluidState().is(FluidTags.LAVA) ? 10.0F : (this.isInLava() ? Float.NEGATIVE_INFINITY : 0.0F); + } + + @Nullable + @Override + public Strider getBreedOffspring(ServerLevel level, AgeableMob otherParent) { +- return EntityType.STRIDER.create(level); ++ return (Strider) EntityType.STRIDER.create(level); + } + + @Override + public boolean isFood(ItemStack stack) { +- return FOOD_ITEMS.test(stack); ++ return Strider.FOOD_ITEMS.test(stack); + } + + @Override + protected void dropEquipment() { + super.dropEquipment(); + if (this.isSaddled()) { +- this.spawnAtLocation(Items.SADDLE); ++ this.spawnAtLocation((IMaterial) Items.SADDLE); + } ++ + } + + @Override +- public InteractionResult mobInteract(Player player, InteractionHand hand) { +- boolean isFood = this.isFood(player.getItemInHand(hand)); +- if (!isFood && this.isSaddled() && !this.isVehicle() && !player.isSecondaryUseActive()) { ++ public InteractionResult mobInteract(Player player, EnumHand hand) { ++ boolean flag = this.isFood(player.getItemInHand(hand)); ++ ++ if (!flag && this.isSaddled() && !this.isVehicle() && !player.isSecondaryUseActive()) { + if (!this.level().isClientSide) { + player.startRiding(this); + } + + return InteractionResult.sidedSuccess(this.level().isClientSide); + } else { +- InteractionResult interactionResult = super.mobInteract(player, hand); +- if (!interactionResult.consumesAction()) { +- ItemStack itemInHand = player.getItemInHand(hand); +- return itemInHand.is(Items.SADDLE) ? itemInHand.interactLivingEntity(player, this, hand) : InteractionResult.PASS; ++ InteractionResult enuminteractionresult = super.mobInteract(player, hand); ++ ++ if (!enuminteractionresult.consumesAction()) { ++ ItemStack itemstack = player.getItemInHand(hand); ++ ++ return itemstack.is(Items.SADDLE) ? itemstack.interactLivingEntity(player, this, hand) : InteractionResult.PASS; + } else { +- if (isFood && !this.isSilent()) { +- this.level() +- .playSound( +- null, +- this.getX(), +- this.getY(), +- this.getZ(), +- SoundEvents.STRIDER_EAT, +- this.getSoundSource(), +- 1.0F, +- 1.0F + (this.random.nextFloat() - this.random.nextFloat()) * 0.2F +- ); ++ if (flag && !this.isSilent()) { ++ this.level().playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.STRIDER_EAT, this.getSoundSource(), 1.0F, 1.0F + (this.random.nextFloat() - this.random.nextFloat()) * 0.2F); + } + +- return interactionResult; ++ return enuminteractionresult; + } + } + } + + @Override + public Vec3 getLeashOffset() { +- return new Vec3(0.0, (double)(0.6F * this.getEyeHeight()), (double)(this.getBbWidth() * 0.4F)); ++ return new Vec3(0.0D, (double) (0.6F * this.getEyeHeight()), (double) (this.getBbWidth() * 0.4F)); + } + + @Nullable + @Override +- public SpawnGroupData finalizeSpawn( +- ServerLevelAccessor level, DifficultyInstance difficulty, MobSpawnType reason, @Nullable SpawnGroupData spawnData, @Nullable CompoundTag dataTag +- ) { ++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) { + if (this.isBaby()) { +- return super.finalizeSpawn(level, difficulty, reason, spawnData, dataTag); ++ return super.finalizeSpawn(level, difficulty, reason, (GroupDataEntity) spawnData, dataTag); + } else { +- RandomSource random = level.getRandom(); +- if (random.nextInt(30) == 0) { +- Mob mob = EntityType.ZOMBIFIED_PIGLIN.create(level.getLevel()); +- if (mob != null) { +- spawnData = this.spawnJockey(level, difficulty, mob, new Zombie.ZombieGroupData(Zombie.getSpawnAsBabyOdds(random), false)); +- mob.setItemSlot(EquipmentSlot.MAINHAND, new ItemStack(Items.WARPED_FUNGUS_ON_A_STICK)); +- this.equipSaddle(null); ++ RandomSource randomsource = level.getRandom(); ++ ++ if (randomsource.nextInt(30) == 0) { ++ Mob entityinsentient = (Mob) EntityType.ZOMBIFIED_PIGLIN.create(level.getLevel()); ++ ++ if (entityinsentient != null) { ++ spawnData = this.spawnJockey(level, difficulty, entityinsentient, new Zombie.ZombieGroupData(Zombie.getSpawnAsBabyOdds(randomsource), false)); ++ entityinsentient.setItemSlot(EquipmentSlot.MAINHAND, new ItemStack(Items.WARPED_FUNGUS_ON_A_STICK)); ++ this.equipSaddle((SoundSource) null); + } +- } else if (random.nextInt(10) == 0) { +- AgeableMob ageableMob = EntityType.STRIDER.create(level.getLevel()); +- if (ageableMob != null) { +- ageableMob.setAge(-24000); +- spawnData = this.spawnJockey(level, difficulty, ageableMob, null); ++ } else if (randomsource.nextInt(10) == 0) { ++ AgeableMob entityageable = (AgeableMob) EntityType.STRIDER.create(level.getLevel()); ++ ++ if (entityageable != null) { ++ entityageable.setAge(-24000); ++ spawnData = this.spawnJockey(level, difficulty, entityageable, (GroupDataEntity) null); + } + } else { + spawnData = new AgeableMob.AgeableMobGroupData(0.5F); + } + +- return super.finalizeSpawn(level, difficulty, reason, spawnData, dataTag); ++ return super.finalizeSpawn(level, difficulty, reason, (GroupDataEntity) spawnData, dataTag); + } + } + +- private SpawnGroupData spawnJockey(ServerLevelAccessor serverLevel, DifficultyInstance difficulty, Mob jockey, @Nullable SpawnGroupData spawnData) { ++ private GroupDataEntity spawnJockey(ServerLevelAccessor serverLevel, DifficultyInstance difficulty, Mob jockey, @Nullable GroupDataEntity spawnData) { + jockey.moveTo(this.getX(), this.getY(), this.getZ(), this.getYRot(), 0.0F); +- jockey.finalizeSpawn(serverLevel, difficulty, MobSpawnType.JOCKEY, spawnData, null); ++ jockey.finalizeSpawn(serverLevel, difficulty, EnumMobSpawn.JOCKEY, spawnData, (CompoundTag) null); + jockey.startRiding(this, true); + return new AgeableMob.AgeableMobGroupData(0.0F); + } + +- static class StriderGoToLavaGoal extends MoveToBlockGoal { ++ private static class StriderGoToLavaGoal extends MoveToBlockGoal { ++ + private final Strider strider; + + StriderGoToLavaGoal(Strider strider, double speedModifier) { +@@ -523,11 +553,12 @@ + + @Override + protected boolean isValidTarget(LevelReader level, BlockPos pos) { +- return level.getBlockState(pos).is(Blocks.LAVA) && level.getBlockState(pos.above()).isPathfindable(level, pos, PathComputationType.LAND); ++ return level.getBlockState(pos).is(Blocks.LAVA) && level.getBlockState(pos.above()).isPathfindable(level, pos, PathMode.LAND); + } + } + +- static class StriderPathNavigation extends GroundPathNavigation { ++ private static class StriderPathNavigation extends GroundPathNavigation { ++ + StriderPathNavigation(Strider strider, Level level) { + super(strider, level); + } +@@ -541,10 +572,7 @@ + + @Override + protected boolean hasValidPathType(BlockPathTypes pathType) { +- return pathType == BlockPathTypes.LAVA +- || pathType == BlockPathTypes.DAMAGE_FIRE +- || pathType == BlockPathTypes.DANGER_FIRE +- || super.hasValidPathType(pathType); ++ return pathType != BlockPathTypes.LAVA && pathType != BlockPathTypes.DAMAGE_FIRE && pathType != BlockPathTypes.DANGER_FIRE ? super.hasValidPathType(pathType) : true; + } + + @Override diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Vex.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Vex.java.patch new file mode 100644 index 0000000000..07677de98b --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Vex.java.patch @@ -0,0 +1,402 @@ +--- a/net/minecraft/world/entity/monster/Vex.java ++++ b/net/minecraft/world/entity/monster/Vex.java +@@ -15,15 +15,15 @@ + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.EnumMoveType; + import net.minecraft.world.entity.EquipmentSlot; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.MoverType; + import net.minecraft.world.entity.PathfinderMob; +-import net.minecraft.world.entity.Pose; +-import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.TraceableEntity; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; + import net.minecraft.world.entity.ai.attributes.Attributes; +@@ -45,16 +45,17 @@ + import org.joml.Vector3f; + + public class Vex extends Monster implements TraceableEntity { ++ + public static final float FLAP_DEGREES_PER_TICK = 45.836624F; +- public static final int TICKS_PER_FLAP = Mth.ceil((float) (Math.PI * 5.0 / 4.0)); ++ public static final int TICKS_PER_FLAP = Mth.ceil(3.9269907F); + protected static final EntityDataAccessor<Byte> DATA_FLAGS_ID = SynchedEntityData.defineId(Vex.class, EntityDataSerializers.BYTE); + private static final int FLAG_IS_CHARGING = 1; + @Nullable + Mob owner; + @Nullable + private BlockPos boundOrigin; +- private boolean hasLimitedLife; +- private int limitedLifeTicks; ++ public boolean hasLimitedLife; ++ public int limitedLifeTicks; + + public Vex(EntityType<? extends Vex> entityType, Level level) { + super(entityType, level); +@@ -63,17 +64,17 @@ + } + + @Override +- protected float getStandingEyeHeight(Pose pose, EntityDimensions dimensions) { ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions dimensions) { + return dimensions.height - 0.28125F; + } + + @Override + public boolean isFlapping() { +- return this.tickCount % TICKS_PER_FLAP == 0; ++ return this.tickCount % Vex.TICKS_PER_FLAP == 0; + } + + @Override +- public void move(MoverType type, Vec3 pos) { ++ public void move(EnumMoveType type, Vec3 pos) { + super.move(type, pos); + this.checkInsideBlocks(); + } +@@ -88,6 +89,7 @@ + this.limitedLifeTicks = 20; + this.hurt(this.damageSources().starve(), 1.0F); + } ++ + } + + @Override +@@ -98,19 +100,19 @@ + this.goalSelector.addGoal(8, new Vex.VexRandomMoveGoal()); + this.goalSelector.addGoal(9, new LookAtPlayerGoal(this, Player.class, 3.0F, 1.0F)); + this.goalSelector.addGoal(10, new LookAtPlayerGoal(this, Mob.class, 8.0F)); +- this.targetSelector.addGoal(1, new HurtByTargetGoal(this, Raider.class).setAlertOthers()); ++ this.targetSelector.addGoal(1, (new HurtByTargetGoal(this, new Class[]{Raider.class})).setAlertOthers()); + this.targetSelector.addGoal(2, new Vex.VexCopyOwnerTargetGoal(this)); + this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, Player.class, true)); + } + + public static AttributeSupplier.Builder createAttributes() { +- return Monster.createMonsterAttributes().add(Attributes.MAX_HEALTH, 14.0).add(Attributes.ATTACK_DAMAGE, 4.0); ++ return Monster.createMonsterAttributes().add(Attributes.MAX_HEALTH, 14.0D).add(Attributes.ATTACK_DAMAGE, 4.0D); + } + + @Override + protected void defineSynchedData() { + super.defineSynchedData(); +- this.entityData.define(DATA_FLAGS_ID, (byte)0); ++ this.entityData.define(Vex.DATA_FLAGS_ID, (byte) 0); + } + + @Override +@@ -123,14 +125,18 @@ + if (compound.contains("LifeTicks")) { + this.setLimitedLife(compound.getInt("LifeTicks")); + } ++ + } + + @Override + public void restoreFrom(Entity entity) { + super.restoreFrom(entity); +- if (entity instanceof Vex vex) { +- this.owner = vex.getOwner(); ++ if (entity instanceof Vex) { ++ Vex entityvex = (Vex) entity; ++ ++ this.owner = entityvex.getOwner(); + } ++ + } + + @Override +@@ -145,6 +151,7 @@ + if (this.hasLimitedLife) { + compound.putInt("LifeTicks", this.limitedLifeTicks); + } ++ + } + + @Nullable +@@ -163,19 +170,22 @@ + } + + private boolean getVexFlag(int mask) { +- int i = this.entityData.get(DATA_FLAGS_ID); +- return (i & mask) != 0; ++ byte b0 = (Byte) this.entityData.get(Vex.DATA_FLAGS_ID); ++ ++ return (b0 & mask) != 0; + } + + private void setVexFlag(int mask, boolean value) { +- int i = this.entityData.get(DATA_FLAGS_ID); ++ byte b0 = (Byte) this.entityData.get(Vex.DATA_FLAGS_ID); ++ int j; ++ + if (value) { +- i |= mask; ++ j = b0 | mask; + } else { +- i &= ~mask; ++ j = b0 & ~mask; + } + +- this.entityData.set(DATA_FLAGS_ID, (byte)(i & 0xFF)); ++ this.entityData.set(Vex.DATA_FLAGS_ID, (byte) (j & 255)); + } + + public boolean isCharging() { +@@ -217,12 +227,11 @@ + + @Nullable + @Override +- public SpawnGroupData finalizeSpawn( +- ServerLevelAccessor level, DifficultyInstance difficulty, MobSpawnType reason, @Nullable SpawnGroupData spawnData, @Nullable CompoundTag dataTag +- ) { +- RandomSource random = level.getRandom(); +- this.populateDefaultEquipmentSlots(random, difficulty); +- this.populateDefaultEquipmentEnchantments(random, difficulty); ++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) { ++ RandomSource randomsource = level.getRandom(); ++ ++ this.populateDefaultEquipmentSlots(randomsource, difficulty); ++ this.populateDefaultEquipmentEnchantments(randomsource, difficulty); + return super.finalizeSpawn(level, difficulty, reason, spawnData, dataTag); + } + +@@ -238,23 +247,56 @@ + } + + @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entityDimensions, float f) { +- return new Vector3f(0.0F, entityDimensions.height - 0.0625F * f, 0.0F); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ return new Vector3f(0.0F, entitysize.height - 0.0625F * f, 0.0F); + } + +- class VexChargeAttackGoal extends Goal { ++ private class VexMoveControl extends MoveControl { ++ ++ public VexMoveControl(Vex entityvex) { ++ super(entityvex); ++ } ++ ++ @Override ++ public void tick() { ++ if (this.operation == MoveControl.Operation.MOVE_TO) { ++ Vec3 vec3d = new Vec3(this.wantedX - Vex.this.getX(), this.wantedY - Vex.this.getY(), this.wantedZ - Vex.this.getZ()); ++ double d0 = vec3d.length(); ++ ++ if (d0 < Vex.this.getBoundingBox().getSize()) { ++ this.operation = MoveControl.Operation.WAIT; ++ Vex.this.setDeltaMovement(Vex.this.getDeltaMovement().scale(0.5D)); ++ } else { ++ Vex.this.setDeltaMovement(Vex.this.getDeltaMovement().add(vec3d.scale(this.speedModifier * 0.05D / d0))); ++ if (Vex.this.getTarget() == null) { ++ Vec3 vec3d1 = Vex.this.getDeltaMovement(); ++ ++ Vex.this.setYRot(-((float) Mth.atan2(vec3d1.x, vec3d1.z)) * 57.295776F); ++ Vex.this.yBodyRot = Vex.this.getYRot(); ++ } else { ++ double d1 = Vex.this.getTarget().getX() - Vex.this.getX(); ++ double d2 = Vex.this.getTarget().getZ() - Vex.this.getZ(); ++ ++ Vex.this.setYRot(-((float) Mth.atan2(d1, d2)) * 57.295776F); ++ Vex.this.yBodyRot = Vex.this.getYRot(); ++ } ++ } ++ ++ } ++ } ++ } ++ ++ private class VexChargeAttackGoal extends Goal { ++ + public VexChargeAttackGoal() { +- this.setFlags(EnumSet.of(Goal.Flag.MOVE)); ++ this.setFlags(EnumSet.of(Goal.Type.MOVE)); + } + + @Override + public boolean canUse() { +- LivingEntity target = Vex.this.getTarget(); +- return target != null +- && target.isAlive() +- && !Vex.this.getMoveControl().hasWanted() +- && Vex.this.random.nextInt(reducedTickDelay(7)) == 0 +- && Vex.this.distanceToSqr(target) > 4.0; ++ LivingEntity entityliving = Vex.this.getTarget(); ++ ++ return entityliving != null && entityliving.isAlive() && !Vex.this.getMoveControl().hasWanted() && Vex.this.random.nextInt(reducedTickDelay(7)) == 0 ? Vex.this.distanceToSqr((Entity) entityliving) > 4.0D : false; + } + + @Override +@@ -264,10 +306,12 @@ + + @Override + public void start() { +- LivingEntity target = Vex.this.getTarget(); +- if (target != null) { +- Vec3 eyePosition = target.getEyePosition(); +- Vex.this.moveControl.setWantedPosition(eyePosition.x, eyePosition.y, eyePosition.z, 1.0); ++ LivingEntity entityliving = Vex.this.getTarget(); ++ ++ if (entityliving != null) { ++ Vec3 vec3d = entityliving.getEyePosition(); ++ ++ Vex.this.moveControl.setWantedPosition(vec3d.x, vec3d.y, vec3d.z, 1.0D); + } + + Vex.this.setIsCharging(true); +@@ -286,104 +330,82 @@ + + @Override + public void tick() { +- LivingEntity target = Vex.this.getTarget(); +- if (target != null) { +- if (Vex.this.getBoundingBox().intersects(target.getBoundingBox())) { +- Vex.this.doHurtTarget(target); ++ LivingEntity entityliving = Vex.this.getTarget(); ++ ++ if (entityliving != null) { ++ if (Vex.this.getBoundingBox().intersects(entityliving.getBoundingBox())) { ++ Vex.this.doHurtTarget(entityliving); + Vex.this.setIsCharging(false); + } else { +- double d = Vex.this.distanceToSqr(target); +- if (d < 9.0) { +- Vec3 eyePosition = target.getEyePosition(); +- Vex.this.moveControl.setWantedPosition(eyePosition.x, eyePosition.y, eyePosition.z, 1.0); ++ double d0 = Vex.this.distanceToSqr((Entity) entityliving); ++ ++ if (d0 < 9.0D) { ++ Vec3 vec3d = entityliving.getEyePosition(); ++ ++ Vex.this.moveControl.setWantedPosition(vec3d.x, vec3d.y, vec3d.z, 1.0D); + } + } ++ + } + } + } + +- class VexCopyOwnerTargetGoal extends TargetGoal { +- private final TargetingConditions copyOwnerTargeting = TargetingConditions.forNonCombat().ignoreLineOfSight().ignoreInvisibilityTesting(); ++ private class VexRandomMoveGoal extends Goal { + +- public VexCopyOwnerTargetGoal(PathfinderMob mob) { +- super(mob, false); ++ public VexRandomMoveGoal() { ++ this.setFlags(EnumSet.of(Goal.Type.MOVE)); + } + + @Override + public boolean canUse() { +- return Vex.this.owner != null && Vex.this.owner.getTarget() != null && this.canAttack(Vex.this.owner.getTarget(), this.copyOwnerTargeting); ++ return !Vex.this.getMoveControl().hasWanted() && Vex.this.random.nextInt(reducedTickDelay(7)) == 0; + } + + @Override +- public void start() { +- Vex.this.setTarget(Vex.this.owner.getTarget()); +- super.start(); ++ public boolean canContinueToUse() { ++ return false; + } +- } + +- class VexMoveControl extends MoveControl { +- public VexMoveControl(Vex mob) { +- super(mob); +- } +- + @Override + public void tick() { +- if (this.operation == MoveControl.Operation.MOVE_TO) { +- Vec3 vec3 = new Vec3(this.wantedX - Vex.this.getX(), this.wantedY - Vex.this.getY(), this.wantedZ - Vex.this.getZ()); +- double len = vec3.length(); +- if (len < Vex.this.getBoundingBox().getSize()) { +- this.operation = MoveControl.Operation.WAIT; +- Vex.this.setDeltaMovement(Vex.this.getDeltaMovement().scale(0.5)); +- } else { +- Vex.this.setDeltaMovement(Vex.this.getDeltaMovement().add(vec3.scale(this.speedModifier * 0.05 / len))); ++ BlockPos blockposition = Vex.this.getBoundOrigin(); ++ ++ if (blockposition == null) { ++ blockposition = Vex.this.blockPosition(); ++ } ++ ++ for (int i = 0; i < 3; ++i) { ++ BlockPos blockposition1 = blockposition.offset(Vex.this.random.nextInt(15) - 7, Vex.this.random.nextInt(11) - 5, Vex.this.random.nextInt(15) - 7); ++ ++ if (Vex.this.level().isEmptyBlock(blockposition1)) { ++ Vex.this.moveControl.setWantedPosition((double) blockposition1.getX() + 0.5D, (double) blockposition1.getY() + 0.5D, (double) blockposition1.getZ() + 0.5D, 0.25D); + if (Vex.this.getTarget() == null) { +- Vec3 deltaMovement = Vex.this.getDeltaMovement(); +- Vex.this.setYRot(-((float)Mth.atan2(deltaMovement.x, deltaMovement.z)) * (180.0F / (float)Math.PI)); +- Vex.this.yBodyRot = Vex.this.getYRot(); +- } else { +- double d = Vex.this.getTarget().getX() - Vex.this.getX(); +- double d1 = Vex.this.getTarget().getZ() - Vex.this.getZ(); +- Vex.this.setYRot(-((float)Mth.atan2(d, d1)) * (180.0F / (float)Math.PI)); +- Vex.this.yBodyRot = Vex.this.getYRot(); ++ Vex.this.getLookControl().setLookAt((double) blockposition1.getX() + 0.5D, (double) blockposition1.getY() + 0.5D, (double) blockposition1.getZ() + 0.5D, 180.0F, 20.0F); + } ++ break; + } + } ++ + } + } + +- class VexRandomMoveGoal extends Goal { +- public VexRandomMoveGoal() { +- this.setFlags(EnumSet.of(Goal.Flag.MOVE)); ++ private class VexCopyOwnerTargetGoal extends TargetGoal { ++ ++ private final TargetingConditions copyOwnerTargeting = TargetingConditions.forNonCombat().ignoreLineOfSight().ignoreInvisibilityTesting(); ++ ++ public VexCopyOwnerTargetGoal(PathfinderMob entitycreature) { ++ super(entitycreature, false); + } + + @Override + public boolean canUse() { +- return !Vex.this.getMoveControl().hasWanted() && Vex.this.random.nextInt(reducedTickDelay(7)) == 0; ++ return Vex.this.owner != null && Vex.this.owner.getTarget() != null && this.canAttack(Vex.this.owner.getTarget(), this.copyOwnerTargeting); + } + + @Override +- public boolean canContinueToUse() { +- return false; ++ public void start() { ++ Vex.this.setTarget(Vex.this.owner.getTarget(), org.bukkit.event.entity.EntityTargetEvent.TargetReason.OWNER_ATTACKED_TARGET, true); // CraftBukkit ++ super.start(); + } +- +- @Override +- public void tick() { +- BlockPos boundOrigin = Vex.this.getBoundOrigin(); +- if (boundOrigin == null) { +- boundOrigin = Vex.this.blockPosition(); +- } +- +- for (int i = 0; i < 3; i++) { +- BlockPos blockPos = boundOrigin.offset(Vex.this.random.nextInt(15) - 7, Vex.this.random.nextInt(11) - 5, Vex.this.random.nextInt(15) - 7); +- if (Vex.this.level().isEmptyBlock(blockPos)) { +- Vex.this.moveControl.setWantedPosition((double)blockPos.getX() + 0.5, (double)blockPos.getY() + 0.5, (double)blockPos.getZ() + 0.5, 0.25); +- if (Vex.this.getTarget() == null) { +- Vex.this.getLookControl() +- .setLookAt((double)blockPos.getX() + 0.5, (double)blockPos.getY() + 0.5, (double)blockPos.getZ() + 0.5, 180.0F, 20.0F); +- } +- break; +- } +- } +- } + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Witch.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Witch.java.patch new file mode 100644 index 0000000000..64cc833019 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Witch.java.patch @@ -0,0 +1,313 @@ +--- a/net/minecraft/world/entity/monster/Witch.java ++++ b/net/minecraft/world/entity/monster/Witch.java +@@ -1,7 +1,9 @@ + package net.minecraft.world.entity.monster; + ++import java.util.Iterator; + import java.util.List; + import java.util.UUID; ++import java.util.function.Predicate; + import net.minecraft.core.particles.ParticleTypes; + import net.minecraft.network.syncher.EntityDataAccessor; + import net.minecraft.network.syncher.EntityDataSerializers; +@@ -15,10 +17,10 @@ + import net.minecraft.world.effect.MobEffects; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; + import net.minecraft.world.entity.EquipmentSlot; + import net.minecraft.world.entity.LivingEntity; +-import net.minecraft.world.entity.Pose; + import net.minecraft.world.entity.ai.attributes.AttributeInstance; + import net.minecraft.world.entity.ai.attributes.AttributeModifier; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; +@@ -45,10 +47,9 @@ + import org.joml.Vector3f; + + public class Witch extends Raider implements RangedAttackMob { ++ + private static final UUID SPEED_MODIFIER_DRINKING_UUID = UUID.fromString("5CD17E52-A79A-43D3-A529-90FDE04B181E"); +- private static final AttributeModifier SPEED_MODIFIER_DRINKING = new AttributeModifier( +- SPEED_MODIFIER_DRINKING_UUID, "Drinking speed penalty", -0.25, AttributeModifier.Operation.ADDITION +- ); ++ private static final AttributeModifier SPEED_MODIFIER_DRINKING = new AttributeModifier(Witch.SPEED_MODIFIER_DRINKING_UUID, "Drinking speed penalty", -0.25D, AttributeModifier.Operation.ADDITION); + private static final EntityDataAccessor<Boolean> DATA_USING_ITEM = SynchedEntityData.defineId(Witch.class, EntityDataSerializers.BOOLEAN); + private int usingTime; + private NearestHealableRaiderTargetGoal<Raider> healRaidersGoal; +@@ -61,16 +62,16 @@ + @Override + protected void registerGoals() { + super.registerGoals(); +- this.healRaidersGoal = new NearestHealableRaiderTargetGoal<>( +- this, Raider.class, true, livingEntity -> livingEntity != null && this.hasActiveRaid() && livingEntity.getType() != EntityType.WITCH +- ); +- this.attackPlayersGoal = new NearestAttackableWitchTargetGoal<>(this, Player.class, 10, true, false, null); ++ this.healRaidersGoal = new NearestHealableRaiderTargetGoal<>(this, Raider.class, true, (entityliving) -> { ++ return entityliving != null && this.hasActiveRaid() && entityliving.getType() != EntityType.WITCH; ++ }); ++ this.attackPlayersGoal = new NearestAttackableWitchTargetGoal<>(this, Player.class, 10, true, false, (Predicate) null); + this.goalSelector.addGoal(1, new FloatGoal(this)); +- this.goalSelector.addGoal(2, new RangedAttackGoal(this, 1.0, 60, 10.0F)); +- this.goalSelector.addGoal(2, new WaterAvoidingRandomStrollGoal(this, 1.0)); ++ this.goalSelector.addGoal(2, new RangedAttackGoal(this, 1.0D, 60, 10.0F)); ++ this.goalSelector.addGoal(2, new WaterAvoidingRandomStrollGoal(this, 1.0D)); + this.goalSelector.addGoal(3, new LookAtPlayerGoal(this, Player.class, 8.0F)); + this.goalSelector.addGoal(3, new RandomLookAroundGoal(this)); +- this.targetSelector.addGoal(1, new HurtByTargetGoal(this, Raider.class)); ++ this.targetSelector.addGoal(1, new HurtByTargetGoal(this, new Class[]{Raider.class})); + this.targetSelector.addGoal(2, this.healRaidersGoal); + this.targetSelector.addGoal(3, this.attackPlayersGoal); + } +@@ -78,7 +79,7 @@ + @Override + protected void defineSynchedData() { + super.defineSynchedData(); +- this.getEntityData().define(DATA_USING_ITEM, false); ++ this.getEntityData().define(Witch.DATA_USING_ITEM, false); + } + + @Override +@@ -97,15 +98,15 @@ + } + + public void setUsingItem(boolean usingItem) { +- this.getEntityData().set(DATA_USING_ITEM, usingItem); ++ this.getEntityData().set(Witch.DATA_USING_ITEM, usingItem); + } + + public boolean isDrinkingPotion() { +- return this.getEntityData().get(DATA_USING_ITEM); ++ return (Boolean) this.getEntityData().get(Witch.DATA_USING_ITEM); + } + + public static AttributeSupplier.Builder createAttributes() { +- return Monster.createMonsterAttributes().add(Attributes.MAX_HEALTH, 26.0).add(Attributes.MOVEMENT_SPEED, 0.25); ++ return Monster.createMonsterAttributes().add(Attributes.MAX_HEALTH, 26.0D).add(Attributes.MOVEMENT_SPEED, 0.25D); + } + + @Override +@@ -121,63 +122,56 @@ + if (this.isDrinkingPotion()) { + if (this.usingTime-- <= 0) { + this.setUsingItem(false); +- ItemStack mainHandItem = this.getMainHandItem(); ++ ItemStack itemstack = this.getMainHandItem(); ++ + this.setItemSlot(EquipmentSlot.MAINHAND, ItemStack.EMPTY); +- if (mainHandItem.is(Items.POTION)) { +- List<MobEffectInstance> mobEffects = PotionUtils.getMobEffects(mainHandItem); +- if (mobEffects != null) { +- for (MobEffectInstance mobEffectInstance : mobEffects) { +- this.addEffect(new MobEffectInstance(mobEffectInstance)); ++ if (itemstack.is(Items.POTION)) { ++ List<MobEffectInstance> list = PotionUtils.getMobEffects(itemstack); ++ ++ if (list != null) { ++ Iterator iterator = list.iterator(); ++ ++ while (iterator.hasNext()) { ++ MobEffectInstance mobeffect = (MobEffectInstance) iterator.next(); ++ ++ this.addEffect(new MobEffectInstance(mobeffect), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit + } + } + } + + this.gameEvent(GameEvent.DRINK); +- this.getAttribute(Attributes.MOVEMENT_SPEED).removeModifier(SPEED_MODIFIER_DRINKING.getId()); ++ this.getAttribute(Attributes.MOVEMENT_SPEED).removeModifier(Witch.SPEED_MODIFIER_DRINKING.getId()); + } + } else { +- Potion potion = null; ++ Potion potionregistry = null; ++ + if (this.random.nextFloat() < 0.15F && this.isEyeInFluid(FluidTags.WATER) && !this.hasEffect(MobEffects.WATER_BREATHING)) { +- potion = Potions.WATER_BREATHING; +- } else if (this.random.nextFloat() < 0.15F +- && (this.isOnFire() || this.getLastDamageSource() != null && this.getLastDamageSource().is(DamageTypeTags.IS_FIRE)) +- && !this.hasEffect(MobEffects.FIRE_RESISTANCE)) { +- potion = Potions.FIRE_RESISTANCE; ++ potionregistry = Potions.WATER_BREATHING; ++ } else if (this.random.nextFloat() < 0.15F && (this.isOnFire() || this.getLastDamageSource() != null && this.getLastDamageSource().is(DamageTypeTags.IS_FIRE)) && !this.hasEffect(MobEffects.FIRE_RESISTANCE)) { ++ potionregistry = Potions.FIRE_RESISTANCE; + } else if (this.random.nextFloat() < 0.05F && this.getHealth() < this.getMaxHealth()) { +- potion = Potions.HEALING; +- } else if (this.random.nextFloat() < 0.5F +- && this.getTarget() != null +- && !this.hasEffect(MobEffects.MOVEMENT_SPEED) +- && this.getTarget().distanceToSqr(this) > 121.0) { +- potion = Potions.SWIFTNESS; ++ potionregistry = Potions.HEALING; ++ } else if (this.random.nextFloat() < 0.5F && this.getTarget() != null && !this.hasEffect(MobEffects.MOVEMENT_SPEED) && this.getTarget().distanceToSqr((Entity) this) > 121.0D) { ++ potionregistry = Potions.SWIFTNESS; + } + +- if (potion != null) { +- this.setItemSlot(EquipmentSlot.MAINHAND, PotionUtils.setPotion(new ItemStack(Items.POTION), potion)); ++ if (potionregistry != null) { ++ this.setItemSlot(EquipmentSlot.MAINHAND, PotionUtils.setPotion(new ItemStack(Items.POTION), potionregistry)); + this.usingTime = this.getMainHandItem().getUseDuration(); + this.setUsingItem(true); + if (!this.isSilent()) { +- this.level() +- .playSound( +- null, +- this.getX(), +- this.getY(), +- this.getZ(), +- SoundEvents.WITCH_DRINK, +- this.getSoundSource(), +- 1.0F, +- 0.8F + this.random.nextFloat() * 0.4F +- ); ++ this.level().playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.WITCH_DRINK, this.getSoundSource(), 1.0F, 0.8F + this.random.nextFloat() * 0.4F); + } + +- AttributeInstance attribute = this.getAttribute(Attributes.MOVEMENT_SPEED); +- attribute.removeModifier(SPEED_MODIFIER_DRINKING.getId()); +- attribute.addTransientModifier(SPEED_MODIFIER_DRINKING); ++ AttributeInstance attributemodifiable = this.getAttribute(Attributes.MOVEMENT_SPEED); ++ ++ attributemodifiable.removeModifier(Witch.SPEED_MODIFIER_DRINKING.getId()); ++ attributemodifiable.addTransientModifier(Witch.SPEED_MODIFIER_DRINKING); + } + } + + if (this.random.nextFloat() < 7.5E-4F) { +- this.level().broadcastEntityEvent(this, (byte)15); ++ this.level().broadcastEntityEvent(this, (byte) 15); + } + } + +@@ -192,97 +186,80 @@ + @Override + public void handleEntityEvent(byte id) { + if (id == 15) { +- for (int i = 0; i < this.random.nextInt(35) + 10; i++) { +- this.level() +- .addParticle( +- ParticleTypes.WITCH, +- this.getX() + this.random.nextGaussian() * 0.13F, +- this.getBoundingBox().maxY + 0.5 + this.random.nextGaussian() * 0.13F, +- this.getZ() + this.random.nextGaussian() * 0.13F, +- 0.0, +- 0.0, +- 0.0 +- ); ++ for (int i = 0; i < this.random.nextInt(35) + 10; ++i) { ++ this.level().addParticle(ParticleTypes.WITCH, this.getX() + this.random.nextGaussian() * 0.12999999523162842D, this.getBoundingBox().maxY + 0.5D + this.random.nextGaussian() * 0.12999999523162842D, this.getZ() + this.random.nextGaussian() * 0.12999999523162842D, 0.0D, 0.0D, 0.0D); + } + } else { + super.handleEntityEvent(id); + } ++ + } + + @Override + protected float getDamageAfterMagicAbsorb(DamageSource source, float damage) { +- float var3 = super.getDamageAfterMagicAbsorb(source, damage); ++ damage = super.getDamageAfterMagicAbsorb(source, damage); + if (source.getEntity() == this) { +- var3 = 0.0F; ++ damage = 0.0F; + } + + if (source.is(DamageTypeTags.WITCH_RESISTANT_TO)) { +- var3 *= 0.15F; ++ damage *= 0.15F; + } + +- return var3; ++ return damage; + } + + @Override + public void performRangedAttack(LivingEntity target, float distanceFactor) { + if (!this.isDrinkingPotion()) { +- Vec3 deltaMovement = target.getDeltaMovement(); +- double d = target.getX() + deltaMovement.x - this.getX(); +- double d1 = target.getEyeY() - 1.1F - this.getY(); +- double d2 = target.getZ() + deltaMovement.z - this.getZ(); +- double squareRoot = Math.sqrt(d * d + d2 * d2); +- Potion potion = Potions.HARMING; ++ Vec3 vec3d = target.getDeltaMovement(); ++ double d0 = target.getX() + vec3d.x - this.getX(); ++ double d1 = target.getEyeY() - 1.100000023841858D - this.getY(); ++ double d2 = target.getZ() + vec3d.z - this.getZ(); ++ double d3 = Math.sqrt(d0 * d0 + d2 * d2); ++ Potion potionregistry = Potions.HARMING; ++ + if (target instanceof Raider) { + if (target.getHealth() <= 4.0F) { +- potion = Potions.HEALING; ++ potionregistry = Potions.HEALING; + } else { +- potion = Potions.REGENERATION; ++ potionregistry = Potions.REGENERATION; + } + +- this.setTarget(null); +- } else if (squareRoot >= 8.0 && !target.hasEffect(MobEffects.MOVEMENT_SLOWDOWN)) { +- potion = Potions.SLOWNESS; ++ this.setTarget((LivingEntity) null); ++ } else if (d3 >= 8.0D && !target.hasEffect(MobEffects.MOVEMENT_SLOWDOWN)) { ++ potionregistry = Potions.SLOWNESS; + } else if (target.getHealth() >= 8.0F && !target.hasEffect(MobEffects.POISON)) { +- potion = Potions.POISON; +- } else if (squareRoot <= 3.0 && !target.hasEffect(MobEffects.WEAKNESS) && this.random.nextFloat() < 0.25F) { +- potion = Potions.WEAKNESS; ++ potionregistry = Potions.POISON; ++ } else if (d3 <= 3.0D && !target.hasEffect(MobEffects.WEAKNESS) && this.random.nextFloat() < 0.25F) { ++ potionregistry = Potions.WEAKNESS; + } + +- ThrownPotion thrownPotion = new ThrownPotion(this.level(), this); +- thrownPotion.setItem(PotionUtils.setPotion(new ItemStack(Items.SPLASH_POTION), potion)); +- thrownPotion.setXRot(thrownPotion.getXRot() - -20.0F); +- thrownPotion.shoot(d, d1 + squareRoot * 0.2, d2, 0.75F, 8.0F); ++ ThrownPotion entitypotion = new ThrownPotion(this.level(), this); ++ ++ entitypotion.setItem(PotionUtils.setPotion(new ItemStack(Items.SPLASH_POTION), potionregistry)); ++ entitypotion.setXRot(entitypotion.getXRot() - -20.0F); ++ entitypotion.shoot(d0, d1 + d3 * 0.2D, d2, 0.75F, 8.0F); + if (!this.isSilent()) { +- this.level() +- .playSound( +- null, +- this.getX(), +- this.getY(), +- this.getZ(), +- SoundEvents.WITCH_THROW, +- this.getSoundSource(), +- 1.0F, +- 0.8F + this.random.nextFloat() * 0.4F +- ); ++ this.level().playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.WITCH_THROW, this.getSoundSource(), 1.0F, 0.8F + this.random.nextFloat() * 0.4F); + } + +- this.level().addFreshEntity(thrownPotion); ++ this.level().addFreshEntity(entitypotion); + } + } + + @Override +- protected float getStandingEyeHeight(Pose pose, EntityDimensions size) { ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions size) { + return 1.62F; + } + + @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entityDimensions, float f) { +- return new Vector3f(0.0F, entityDimensions.height + 0.3125F * f, 0.0F); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ return new Vector3f(0.0F, entitysize.height + 0.3125F * f, 0.0F); + } + + @Override +- public void applyRaidBuffs(int wave, boolean unusedFalse) { +- } ++ public void applyRaidBuffs(int wave, boolean unusedFalse) {} + + @Override + public boolean canBeLeader() { diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/WitherSkeleton.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/WitherSkeleton.java.patch new file mode 100644 index 0000000000..7ece9183c9 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/WitherSkeleton.java.patch @@ -0,0 +1,110 @@ +--- a/net/minecraft/world/entity/monster/WitherSkeleton.java ++++ b/net/minecraft/world/entity/monster/WitherSkeleton.java +@@ -11,23 +11,25 @@ + import net.minecraft.world.effect.MobEffects; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; + import net.minecraft.world.entity.EquipmentSlot; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.LivingEntity; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.Pose; +-import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.ai.attributes.Attributes; + import net.minecraft.world.entity.ai.goal.target.NearestAttackableTargetGoal; + import net.minecraft.world.entity.monster.piglin.AbstractPiglin; + import net.minecraft.world.entity.projectile.AbstractArrow; + import net.minecraft.world.item.ItemStack; + import net.minecraft.world.item.Items; ++import net.minecraft.world.level.IMaterial; + import net.minecraft.world.level.Level; + import net.minecraft.world.level.ServerLevelAccessor; + import net.minecraft.world.level.pathfinder.BlockPathTypes; + + public class WitherSkeleton extends AbstractSkeleton { ++ + public WitherSkeleton(EntityType<? extends WitherSkeleton> entityType, Level level) { + super(entityType, level); + this.setPathfindingMalus(BlockPathTypes.LAVA, 8.0F); +@@ -62,10 +64,17 @@ + @Override + protected void dropCustomDeathLoot(DamageSource source, int looting, boolean recentlyHit) { + super.dropCustomDeathLoot(source, looting, recentlyHit); +- if (source.getEntity() instanceof Creeper creeper && creeper.canDropMobsSkull()) { +- creeper.increaseDroppedSkulls(); +- this.spawnAtLocation(Items.WITHER_SKELETON_SKULL); ++ Entity entity = source.getEntity(); ++ ++ if (entity instanceof Creeper) { ++ Creeper entitycreeper = (Creeper) entity; ++ ++ if (entitycreeper.canDropMobsSkull()) { ++ entitycreeper.increaseDroppedSkulls(); ++ this.spawnAtLocation((IMaterial) Items.WITHER_SKELETON_SKULL); ++ } + } ++ + } + + @Override +@@ -74,22 +83,20 @@ + } + + @Override +- protected void populateDefaultEquipmentEnchantments(RandomSource random, DifficultyInstance difficulty) { +- } ++ protected void populateDefaultEquipmentEnchantments(RandomSource random, DifficultyInstance difficulty) {} + + @Nullable + @Override +- public SpawnGroupData finalizeSpawn( +- ServerLevelAccessor level, DifficultyInstance difficulty, MobSpawnType reason, @Nullable SpawnGroupData spawnData, @Nullable CompoundTag dataTag +- ) { +- SpawnGroupData spawnGroupData = super.finalizeSpawn(level, difficulty, reason, spawnData, dataTag); +- this.getAttribute(Attributes.ATTACK_DAMAGE).setBaseValue(4.0); ++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) { ++ GroupDataEntity groupdataentity1 = super.finalizeSpawn(level, difficulty, reason, spawnData, dataTag); ++ ++ this.getAttribute(Attributes.ATTACK_DAMAGE).setBaseValue(4.0D); + this.reassessWeaponGoal(); +- return spawnGroupData; ++ return groupdataentity1; + } + + @Override +- protected float getStandingEyeHeight(Pose pose, EntityDimensions size) { ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions size) { + return 2.1F; + } + +@@ -104,7 +111,7 @@ + return false; + } else { + if (entity instanceof LivingEntity) { +- ((LivingEntity)entity).addEffect(new MobEffectInstance(MobEffects.WITHER, 200), this); ++ ((LivingEntity) entity).addEffect(new MobEffectInstance(MobEffects.WITHER, 200), this, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.ATTACK); // CraftBukkit + } + + return true; +@@ -113,13 +120,14 @@ + + @Override + protected AbstractArrow getArrow(ItemStack arrowStack, float distanceFactor) { +- AbstractArrow abstractArrow = super.getArrow(arrowStack, distanceFactor); +- abstractArrow.setSecondsOnFire(100); +- return abstractArrow; ++ AbstractArrow entityarrow = super.getArrow(arrowStack, distanceFactor); ++ ++ entityarrow.setSecondsOnFire(100); ++ return entityarrow; + } + + @Override + public boolean canBeAffected(MobEffectInstance potioneffect) { +- return potioneffect.getEffect() != MobEffects.WITHER && super.canBeAffected(potioneffect); ++ return potioneffect.getEffect() == MobEffects.WITHER ? false : super.canBeAffected(potioneffect); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Zombie.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Zombie.java.patch new file mode 100644 index 0000000000..d2568e3ef0 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/Zombie.java.patch @@ -0,0 +1,718 @@ +--- a/net/minecraft/world/entity/monster/Zombie.java ++++ b/net/minecraft/world/entity/monster/Zombie.java +@@ -6,17 +6,6 @@ + import java.util.UUID; + import java.util.function.Predicate; + import javax.annotation.Nullable; +-import net.minecraft.core.BlockPos; +-import net.minecraft.nbt.CompoundTag; +-import net.minecraft.nbt.NbtOps; +-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.sounds.SoundEvent; +-import net.minecraft.sounds.SoundEvents; +-import net.minecraft.sounds.SoundSource; +-import net.minecraft.tags.FluidTags; + import net.minecraft.util.Mth; + import net.minecraft.util.RandomSource; + import net.minecraft.world.Difficulty; +@@ -24,15 +13,15 @@ + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntitySelector; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.EnumMonsterType; + import net.minecraft.world.entity.EquipmentSlot; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.LivingEntity; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.MobType; + import net.minecraft.world.entity.PathfinderMob; +-import net.minecraft.world.entity.Pose; +-import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.SpawnPlacements; + import net.minecraft.world.entity.ai.attributes.AttributeInstance; + import net.minecraft.world.entity.ai.attributes.AttributeModifier; +@@ -63,31 +52,53 @@ + import net.minecraft.world.level.NaturalSpawner; + import net.minecraft.world.level.ServerLevelAccessor; + import net.minecraft.world.level.block.Blocks; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import org.joml.Vector3f; ++import net.minecraft.core.BlockPos; ++import net.minecraft.nbt.CompoundTag; ++import net.minecraft.nbt.NbtOps; ++import net.minecraft.nbt.Tag; ++import net.minecraft.network.syncher.EntityDataAccessor; ++import net.minecraft.network.syncher.EntityDataSerializers; ++import net.minecraft.network.syncher.SynchedEntityData; ++// CraftBukkit start ++import net.minecraft.server.MinecraftServer; ++import net.minecraft.server.level.ServerLevel; ++import net.minecraft.sounds.SoundEvent; ++import net.minecraft.sounds.SoundEvents; ++import net.minecraft.sounds.SoundSource; ++import net.minecraft.tags.FluidTags; ++import org.bukkit.event.entity.CreatureSpawnEvent; ++import org.bukkit.event.entity.EntityCombustByEntityEvent; ++import org.bukkit.event.entity.EntityTargetEvent; ++import org.bukkit.event.entity.EntityTransformEvent; ++// CraftBukkit end + + public class Zombie extends Monster { ++ + private static final UUID SPEED_MODIFIER_BABY_UUID = UUID.fromString("B9766B59-9566-4402-BC1F-2EE2A276D836"); +- private static final AttributeModifier SPEED_MODIFIER_BABY = new AttributeModifier( +- SPEED_MODIFIER_BABY_UUID, "Baby speed boost", 0.5, AttributeModifier.Operation.MULTIPLY_BASE +- ); ++ private static final AttributeModifier SPEED_MODIFIER_BABY = new AttributeModifier(Zombie.SPEED_MODIFIER_BABY_UUID, "Baby speed boost", 0.5D, AttributeModifier.Operation.MULTIPLY_BASE); + private static final EntityDataAccessor<Boolean> DATA_BABY_ID = SynchedEntityData.defineId(Zombie.class, EntityDataSerializers.BOOLEAN); + private static final EntityDataAccessor<Integer> DATA_SPECIAL_TYPE_ID = SynchedEntityData.defineId(Zombie.class, EntityDataSerializers.INT); +- private static final EntityDataAccessor<Boolean> DATA_DROWNED_CONVERSION_ID = SynchedEntityData.defineId(Zombie.class, EntityDataSerializers.BOOLEAN); ++ public static final EntityDataAccessor<Boolean> DATA_DROWNED_CONVERSION_ID = SynchedEntityData.defineId(Zombie.class, EntityDataSerializers.BOOLEAN); + public static final float ZOMBIE_LEADER_CHANCE = 0.05F; + public static final int REINFORCEMENT_ATTEMPTS = 50; + public static final int REINFORCEMENT_RANGE_MAX = 40; + public static final int REINFORCEMENT_RANGE_MIN = 7; + protected static final float BABY_EYE_HEIGHT_ADJUSTMENT = 0.81F; + private static final float BREAK_DOOR_CHANCE = 0.1F; +- private static final Predicate<Difficulty> DOOR_BREAKING_PREDICATE = difficulty -> difficulty == Difficulty.HARD; +- private final BreakDoorGoal breakDoorGoal = new BreakDoorGoal(this, DOOR_BREAKING_PREDICATE); ++ private static final Predicate<Difficulty> DOOR_BREAKING_PREDICATE = (enumdifficulty) -> { ++ return enumdifficulty == Difficulty.HARD; ++ }; ++ private final BreakDoorGoal breakDoorGoal; + private boolean canBreakDoors; + private int inWaterTime; +- private int conversionTime; ++ public int conversionTime; ++ private int lastTick = MinecraftServer.currentTick; // CraftBukkit - add field + + public Zombie(EntityType<? extends Zombie> entityType, Level level) { + super(entityType, level); ++ this.breakDoorGoal = new BreakDoorGoal(this, Zombie.DOOR_BREAKING_PREDICATE); + } + + public Zombie(Level level) { +@@ -96,17 +107,17 @@ + + @Override + protected void registerGoals() { +- this.goalSelector.addGoal(4, new Zombie.ZombieAttackTurtleEggGoal(this, 1.0, 3)); ++ this.goalSelector.addGoal(4, new Zombie.ZombieAttackTurtleEggGoal(this, 1.0D, 3)); + this.goalSelector.addGoal(8, new LookAtPlayerGoal(this, Player.class, 8.0F)); + this.goalSelector.addGoal(8, new RandomLookAroundGoal(this)); + this.addBehaviourGoals(); + } + + protected void addBehaviourGoals() { +- this.goalSelector.addGoal(2, new ZombieAttackGoal(this, 1.0, false)); +- this.goalSelector.addGoal(6, new MoveThroughVillageGoal(this, 1.0, true, 4, this::canBreakDoors)); +- this.goalSelector.addGoal(7, new WaterAvoidingRandomStrollGoal(this, 1.0)); +- this.targetSelector.addGoal(1, new HurtByTargetGoal(this).setAlertOthers(ZombifiedPiglin.class)); ++ this.goalSelector.addGoal(2, new ZombieAttackGoal(this, 1.0D, false)); ++ this.goalSelector.addGoal(6, new MoveThroughVillageGoal(this, 1.0D, true, 4, this::canBreakDoors)); ++ this.goalSelector.addGoal(7, new WaterAvoidingRandomStrollGoal(this, 1.0D)); ++ this.targetSelector.addGoal(1, (new HurtByTargetGoal(this, new Class[0])).setAlertOthers(ZombifiedPiglin.class)); + this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, true)); + this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, AbstractVillager.class, false)); + this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, IronGolem.class, true)); +@@ -114,24 +125,19 @@ + } + + public static AttributeSupplier.Builder createAttributes() { +- return Monster.createMonsterAttributes() +- .add(Attributes.FOLLOW_RANGE, 35.0) +- .add(Attributes.MOVEMENT_SPEED, 0.23F) +- .add(Attributes.ATTACK_DAMAGE, 3.0) +- .add(Attributes.ARMOR, 2.0) +- .add(Attributes.SPAWN_REINFORCEMENTS_CHANCE); ++ return Monster.createMonsterAttributes().add(Attributes.FOLLOW_RANGE, 35.0D).add(Attributes.MOVEMENT_SPEED, 0.23000000417232513D).add(Attributes.ATTACK_DAMAGE, 3.0D).add(Attributes.ARMOR, 2.0D).add(Attributes.SPAWN_REINFORCEMENTS_CHANCE); + } + + @Override + protected void defineSynchedData() { + super.defineSynchedData(); +- this.getEntityData().define(DATA_BABY_ID, false); +- this.getEntityData().define(DATA_SPECIAL_TYPE_ID, 0); +- this.getEntityData().define(DATA_DROWNED_CONVERSION_ID, false); ++ this.getEntityData().define(Zombie.DATA_BABY_ID, false); ++ this.getEntityData().define(Zombie.DATA_SPECIAL_TYPE_ID, 0); ++ this.getEntityData().define(Zombie.DATA_DROWNED_CONVERSION_ID, false); + } + + public boolean isUnderWaterConverting() { +- return this.getEntityData().get(DATA_DROWNED_CONVERSION_ID); ++ return (Boolean) this.getEntityData().get(Zombie.DATA_DROWNED_CONVERSION_ID); + } + + public boolean canBreakDoors() { +@@ -142,7 +148,7 @@ + if (this.supportsBreakDoorGoal() && GoalUtils.hasGroundPathNavigation(this)) { + if (this.canBreakDoors != canBreakDoors) { + this.canBreakDoors = canBreakDoors; +- ((GroundPathNavigation)this.getNavigation()).setCanOpenDoors(canBreakDoors); ++ ((GroundPathNavigation) this.getNavigation()).setCanOpenDoors(canBreakDoors); + if (canBreakDoors) { + this.goalSelector.addGoal(1, this.breakDoorGoal); + } else { +@@ -153,6 +159,7 @@ + this.goalSelector.removeGoal(this.breakDoorGoal); + this.canBreakDoors = false; + } ++ + } + + protected boolean supportsBreakDoorGoal() { +@@ -161,13 +168,13 @@ + + @Override + public boolean isBaby() { +- return this.getEntityData().get(DATA_BABY_ID); ++ return (Boolean) this.getEntityData().get(Zombie.DATA_BABY_ID); + } + + @Override + public int getExperienceReward() { + if (this.isBaby()) { +- this.xpReward = (int)((double)this.xpReward * 2.5); ++ this.xpReward = (int) ((double) this.xpReward * 2.5D); + } + + return super.getExperienceReward(); +@@ -175,19 +182,21 @@ + + @Override + public void setBaby(boolean childZombie) { +- this.getEntityData().set(DATA_BABY_ID, childZombie); ++ this.getEntityData().set(Zombie.DATA_BABY_ID, childZombie); + if (this.level() != null && !this.level().isClientSide) { +- AttributeInstance attribute = this.getAttribute(Attributes.MOVEMENT_SPEED); +- attribute.removeModifier(SPEED_MODIFIER_BABY.getId()); ++ AttributeInstance attributemodifiable = this.getAttribute(Attributes.MOVEMENT_SPEED); ++ ++ attributemodifiable.removeModifier(Zombie.SPEED_MODIFIER_BABY.getId()); + if (childZombie) { +- attribute.addTransientModifier(SPEED_MODIFIER_BABY); ++ attributemodifiable.addTransientModifier(Zombie.SPEED_MODIFIER_BABY); + } + } ++ + } + + @Override + public void onSyncedDataUpdated(EntityDataAccessor<?> key) { +- if (DATA_BABY_ID.equals(key)) { ++ if (Zombie.DATA_BABY_ID.equals(key)) { + this.refreshDimensions(); + } + +@@ -202,13 +211,16 @@ + public void tick() { + if (!this.level().isClientSide && this.isAlive() && !this.isNoAi()) { + if (this.isUnderWaterConverting()) { +- this.conversionTime--; ++ // CraftBukkit start - Use wall time instead of ticks for conversion ++ int elapsedTicks = MinecraftServer.currentTick - this.lastTick; ++ this.conversionTime -= elapsedTicks; ++ // CraftBukkit end + if (this.conversionTime < 0) { + this.doUnderWaterConversion(); + } + } else if (this.convertsInWater()) { + if (this.isEyeInFluid(FluidTags.WATER)) { +- this.inWaterTime++; ++ ++this.inWaterTime; + if (this.inWaterTime >= 600) { + this.startUnderWaterConversion(300); + } +@@ -219,18 +231,21 @@ + } + + super.tick(); ++ this.lastTick = MinecraftServer.currentTick; // CraftBukkit + } + + @Override + public void aiStep() { + if (this.isAlive()) { + boolean flag = this.isSunSensitive() && this.isSunBurnTick(); ++ + if (flag) { +- ItemStack itemBySlot = this.getItemBySlot(EquipmentSlot.HEAD); +- if (!itemBySlot.isEmpty()) { +- if (itemBySlot.isDamageableItem()) { +- itemBySlot.setDamageValue(itemBySlot.getDamageValue() + this.random.nextInt(2)); +- if (itemBySlot.getDamageValue() >= itemBySlot.getMaxDamage()) { ++ ItemStack itemstack = this.getItemBySlot(EquipmentSlot.HEAD); ++ ++ if (!itemstack.isEmpty()) { ++ if (itemstack.isDamageableItem()) { ++ itemstack.setDamageValue(itemstack.getDamageValue() + this.random.nextInt(2)); ++ if (itemstack.getDamageValue() >= itemstack.getMaxDamage()) { + this.broadcastBreakEvent(EquipmentSlot.HEAD); + this.setItemSlot(EquipmentSlot.HEAD, ItemStack.EMPTY); + } +@@ -248,24 +263,32 @@ + super.aiStep(); + } + +- private void startUnderWaterConversion(int conversionTime) { ++ public void startUnderWaterConversion(int conversionTime) { ++ this.lastTick = MinecraftServer.currentTick; // CraftBukkit + this.conversionTime = conversionTime; +- this.getEntityData().set(DATA_DROWNED_CONVERSION_ID, true); ++ this.getEntityData().set(Zombie.DATA_DROWNED_CONVERSION_ID, true); + } + + protected void doUnderWaterConversion() { + this.convertToZombieType(EntityType.DROWNED); + if (!this.isSilent()) { +- this.level().levelEvent(null, 1040, this.blockPosition(), 0); ++ this.level().levelEvent((Player) null, 1040, this.blockPosition(), 0); + } ++ + } + + protected void convertToZombieType(EntityType<? extends Zombie> entityType) { +- Zombie zombie = this.convertTo(entityType, true); +- if (zombie != null) { +- zombie.handleAttributes(zombie.level().getCurrentDifficultyAt(zombie.blockPosition()).getSpecialMultiplier()); +- zombie.setCanBreakDoors(zombie.supportsBreakDoorGoal() && this.canBreakDoors()); ++ Zombie entityzombie = (Zombie) this.convertTo(entityType, true, EntityTransformEvent.TransformReason.DROWNED, CreatureSpawnEvent.SpawnReason.DROWNED); ++ ++ if (entityzombie != null) { ++ entityzombie.handleAttributes(entityzombie.level().getCurrentDifficultyAt(entityzombie.blockPosition()).getSpecialMultiplier()); ++ entityzombie.setCanBreakDoors(entityzombie.supportsBreakDoorGoal() && this.canBreakDoors()); ++ // CraftBukkit start - SPIGOT-5208: End conversion to stop event spam ++ } else { ++ ((org.bukkit.entity.Zombie) getBukkitEntity()).setConversionTime(-1); ++ // CraftBukkit end + } ++ + } + + protected boolean isSunSensitive() { +@@ -279,44 +302,35 @@ + } else if (!(this.level() instanceof ServerLevel)) { + return false; + } else { +- ServerLevel serverLevel = (ServerLevel)this.level(); +- LivingEntity target = this.getTarget(); +- if (target == null && source.getEntity() instanceof LivingEntity) { +- target = (LivingEntity)source.getEntity(); ++ ServerLevel worldserver = (ServerLevel) this.level(); ++ LivingEntity entityliving = this.getTarget(); ++ ++ if (entityliving == null && source.getEntity() instanceof LivingEntity) { ++ entityliving = (LivingEntity) source.getEntity(); + } + +- if (target != null +- && this.level().getDifficulty() == Difficulty.HARD +- && (double)this.random.nextFloat() < this.getAttributeValue(Attributes.SPAWN_REINFORCEMENTS_CHANCE) +- && this.level().getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING)) { +- int floor = Mth.floor(this.getX()); +- int floor1 = Mth.floor(this.getY()); +- int floor2 = Mth.floor(this.getZ()); +- Zombie zombie = new Zombie(this.level()); ++ if (entityliving != null && this.level().getDifficulty() == Difficulty.HARD && (double) this.random.nextFloat() < this.getAttributeValue(Attributes.SPAWN_REINFORCEMENTS_CHANCE) && this.level().getGameRules().getBoolean(GameRules.RULE_DOMOBSPAWNING)) { ++ int i = Mth.floor(this.getX()); ++ int j = Mth.floor(this.getY()); ++ int k = Mth.floor(this.getZ()); ++ Zombie entityzombie = new Zombie(this.level()); + +- for (int i = 0; i < 50; i++) { +- int i1 = floor + Mth.nextInt(this.random, 7, 40) * Mth.nextInt(this.random, -1, 1); +- int i2 = floor1 + Mth.nextInt(this.random, 7, 40) * Mth.nextInt(this.random, -1, 1); +- int i3 = floor2 + Mth.nextInt(this.random, 7, 40) * Mth.nextInt(this.random, -1, 1); +- BlockPos blockPos = new BlockPos(i1, i2, i3); +- EntityType<?> type = zombie.getType(); +- SpawnPlacements.Type placementType = SpawnPlacements.getPlacementType(type); +- if (NaturalSpawner.isSpawnPositionOk(placementType, this.level(), blockPos, type) +- && SpawnPlacements.checkSpawnRules(type, serverLevel, MobSpawnType.REINFORCEMENT, blockPos, this.level().random)) { +- zombie.setPos((double)i1, (double)i2, (double)i3); +- if (!this.level().hasNearbyAlivePlayer((double)i1, (double)i2, (double)i3, 7.0) +- && this.level().isUnobstructed(zombie) +- && this.level().noCollision(zombie) +- && !this.level().containsAnyLiquid(zombie.getBoundingBox())) { +- zombie.setTarget(target); +- zombie.finalizeSpawn( +- serverLevel, this.level().getCurrentDifficultyAt(zombie.blockPosition()), MobSpawnType.REINFORCEMENT, null, null +- ); +- serverLevel.addFreshEntityWithPassengers(zombie); +- this.getAttribute(Attributes.SPAWN_REINFORCEMENTS_CHANCE) +- .addPermanentModifier(new AttributeModifier("Zombie reinforcement caller charge", -0.05F, AttributeModifier.Operation.ADDITION)); +- zombie.getAttribute(Attributes.SPAWN_REINFORCEMENTS_CHANCE) +- .addPermanentModifier(new AttributeModifier("Zombie reinforcement callee charge", -0.05F, AttributeModifier.Operation.ADDITION)); ++ for (int l = 0; l < 50; ++l) { ++ int i1 = i + Mth.nextInt(this.random, 7, 40) * Mth.nextInt(this.random, -1, 1); ++ int j1 = j + Mth.nextInt(this.random, 7, 40) * Mth.nextInt(this.random, -1, 1); ++ int k1 = k + Mth.nextInt(this.random, 7, 40) * Mth.nextInt(this.random, -1, 1); ++ BlockPos blockposition = new BlockPos(i1, j1, k1); ++ EntityType<?> entitytypes = entityzombie.getType(); ++ SpawnPlacements.Surface entitypositiontypes_surface = SpawnPlacements.getPlacementType(entitytypes); ++ ++ if (NaturalSpawner.isSpawnPositionOk(entitypositiontypes_surface, this.level(), blockposition, entitytypes) && SpawnPlacements.checkSpawnRules(entitytypes, worldserver, EnumMobSpawn.REINFORCEMENT, blockposition, this.level().random)) { ++ entityzombie.setPos((double) i1, (double) j1, (double) k1); ++ if (!this.level().hasNearbyAlivePlayer((double) i1, (double) j1, (double) k1, 7.0D) && this.level().isUnobstructed(entityzombie) && this.level().noCollision((Entity) entityzombie) && !this.level().containsAnyLiquid(entityzombie.getBoundingBox())) { ++ entityzombie.setTarget(entityliving, EntityTargetEvent.TargetReason.REINFORCEMENT_TARGET, true); // CraftBukkit ++ entityzombie.finalizeSpawn(worldserver, this.level().getCurrentDifficultyAt(entityzombie.blockPosition()), EnumMobSpawn.REINFORCEMENT, (GroupDataEntity) null, (CompoundTag) null); ++ worldserver.addFreshEntityWithPassengers(entityzombie, CreatureSpawnEvent.SpawnReason.REINFORCEMENTS); // CraftBukkit ++ this.getAttribute(Attributes.SPAWN_REINFORCEMENTS_CHANCE).addPermanentModifier(new AttributeModifier("Zombie reinforcement caller charge", -0.05000000074505806D, AttributeModifier.Operation.ADDITION)); ++ entityzombie.getAttribute(Attributes.SPAWN_REINFORCEMENTS_CHANCE).addPermanentModifier(new AttributeModifier("Zombie reinforcement callee charge", -0.05000000074505806D, AttributeModifier.Operation.ADDITION)); + break; + } + } +@@ -330,10 +344,19 @@ + @Override + public boolean doHurtTarget(Entity entity) { + boolean flag = super.doHurtTarget(entity); ++ + if (flag) { +- float effectiveDifficulty = this.level().getCurrentDifficultyAt(this.blockPosition()).getEffectiveDifficulty(); +- if (this.getMainHandItem().isEmpty() && this.isOnFire() && this.random.nextFloat() < effectiveDifficulty * 0.3F) { +- entity.setSecondsOnFire(2 * (int)effectiveDifficulty); ++ float f = this.level().getCurrentDifficultyAt(this.blockPosition()).getEffectiveDifficulty(); ++ ++ if (this.getMainHandItem().isEmpty() && this.isOnFire() && this.random.nextFloat() < f * 0.3F) { ++ // CraftBukkit start ++ EntityCombustByEntityEvent event = new EntityCombustByEntityEvent(this.getBukkitEntity(), entity.getBukkitEntity(), 2 * (int) f); // PAIL: fixme ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ ++ if (!event.isCancelled()) { ++ entity.setSecondsOnFire(event.getDuration(), false); ++ } ++ // CraftBukkit end + } + } + +@@ -360,26 +383,28 @@ + } + + @Override +- protected void playStepSound(BlockPos pos, BlockState block) { ++ protected void playStepSound(BlockPos pos, IBlockData block) { + this.playSound(this.getStepSound(), 0.15F, 1.0F); + } + + @Override +- public MobType getMobType() { +- return MobType.UNDEAD; ++ public EnumMonsterType getMobType() { ++ return EnumMonsterType.UNDEAD; + } + + @Override + protected void populateDefaultEquipmentSlots(RandomSource random, DifficultyInstance difficulty) { + super.populateDefaultEquipmentSlots(random, difficulty); + if (random.nextFloat() < (this.level().getDifficulty() == Difficulty.HARD ? 0.05F : 0.01F)) { +- int randomInt = random.nextInt(3); +- if (randomInt == 0) { ++ int i = random.nextInt(3); ++ ++ if (i == 0) { + this.setItemSlot(EquipmentSlot.MAINHAND, new ItemStack(Items.IRON_SWORD)); + } else { + this.setItemSlot(EquipmentSlot.MAINHAND, new ItemStack(Items.IRON_SHOVEL)); + } + } ++ + } + + @Override +@@ -400,107 +425,124 @@ + if (compound.contains("DrownedConversionTime", 99) && compound.getInt("DrownedConversionTime") > -1) { + this.startUnderWaterConversion(compound.getInt("DrownedConversionTime")); + } ++ + } + + @Override + public boolean killedEntity(ServerLevel level, LivingEntity entity) { + boolean flag = super.killedEntity(level, entity); +- if ((level.getDifficulty() == Difficulty.NORMAL || level.getDifficulty() == Difficulty.HARD) && entity instanceof Villager villager) { ++ ++ if ((level.getDifficulty() == Difficulty.NORMAL || level.getDifficulty() == Difficulty.HARD) && entity instanceof Villager) { ++ Villager entityvillager = (Villager) entity; ++ + if (level.getDifficulty() != Difficulty.HARD && this.random.nextBoolean()) { + return flag; + } ++ // CraftBukkit start ++ flag = zombifyVillager(level, entityvillager, this.blockPosition(), this.isSilent(), CreatureSpawnEvent.SpawnReason.INFECTION) == null; ++ } + +- ZombieVillager zombieVillager = villager.convertTo(EntityType.ZOMBIE_VILLAGER, false); +- if (zombieVillager != null) { +- zombieVillager.finalizeSpawn( +- level, level.getCurrentDifficultyAt(zombieVillager.blockPosition()), MobSpawnType.CONVERSION, new Zombie.ZombieGroupData(false, true), null +- ); +- zombieVillager.setVillagerData(villager.getVillagerData()); +- zombieVillager.setGossips(villager.getGossips().store(NbtOps.INSTANCE)); +- zombieVillager.setTradeOffers(villager.getOffers().createTag()); +- zombieVillager.setVillagerXp(villager.getVillagerXp()); +- if (!this.isSilent()) { +- level.levelEvent(null, 1026, this.blockPosition(), 0); ++ return flag; ++ } ++ ++ public static ZombieVillager zombifyVillager(ServerLevel worldserver, Villager entityvillager, net.minecraft.core.BlockPos blockPosition, boolean silent, CreatureSpawnEvent.SpawnReason spawnReason) { ++ { ++ ZombieVillager entityzombievillager = (ZombieVillager) entityvillager.convertTo(EntityType.ZOMBIE_VILLAGER, false, EntityTransformEvent.TransformReason.INFECTION, spawnReason); ++ // CraftBukkit end ++ ++ if (entityzombievillager != null) { ++ entityzombievillager.finalizeSpawn(worldserver, worldserver.getCurrentDifficultyAt(entityzombievillager.blockPosition()), EnumMobSpawn.CONVERSION, new Zombie.ZombieGroupData(false, true), (CompoundTag) null); ++ entityzombievillager.setVillagerData(entityvillager.getVillagerData()); ++ entityzombievillager.setGossips((Tag) entityvillager.getGossips().store(NbtOps.INSTANCE)); ++ entityzombievillager.setTradeOffers(entityvillager.getOffers().createTag()); ++ entityzombievillager.setVillagerXp(entityvillager.getVillagerXp()); ++ // CraftBukkit start ++ if (!silent) { ++ worldserver.levelEvent((Player) null, 1026, blockPosition, 0); + } + +- flag = false; ++ // flag = false; + } +- } + +- return flag; ++ return entityzombievillager; ++ } ++ // CraftBukkit end + } + + @Override +- protected float getStandingEyeHeight(Pose pose, EntityDimensions size) { ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions size) { + return this.isBaby() ? 0.93F : 1.74F; + } + + @Override + public boolean canHoldItem(ItemStack stack) { +- return (!stack.is(Items.EGG) || !this.isBaby() || !this.isPassenger()) && super.canHoldItem(stack); ++ return stack.is(Items.EGG) && this.isBaby() && this.isPassenger() ? false : super.canHoldItem(stack); + } + + @Override + public boolean wantsToPickUp(ItemStack stack) { +- return !stack.is(Items.GLOW_INK_SAC) && super.wantsToPickUp(stack); ++ return stack.is(Items.GLOW_INK_SAC) ? false : super.wantsToPickUp(stack); + } + + @Nullable + @Override +- public SpawnGroupData finalizeSpawn( +- ServerLevelAccessor level, DifficultyInstance difficulty, MobSpawnType reason, @Nullable SpawnGroupData spawnData, @Nullable CompoundTag dataTag +- ) { +- RandomSource random = level.getRandom(); +- SpawnGroupData var11 = super.finalizeSpawn(level, difficulty, reason, spawnData, dataTag); +- float specialMultiplier = difficulty.getSpecialMultiplier(); +- this.setCanPickUpLoot(random.nextFloat() < 0.55F * specialMultiplier); +- if (var11 == null) { +- var11 = new Zombie.ZombieGroupData(getSpawnAsBabyOdds(random), true); ++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) { ++ RandomSource randomsource = level.getRandom(); ++ Object object = super.finalizeSpawn(level, difficulty, reason, spawnData, dataTag); ++ float f = difficulty.getSpecialMultiplier(); ++ ++ this.setCanPickUpLoot(randomsource.nextFloat() < 0.55F * f); ++ if (object == null) { ++ object = new Zombie.ZombieGroupData(getSpawnAsBabyOdds(randomsource), true); + } + +- if (var11 instanceof Zombie.ZombieGroupData zombieGroupData) { +- if (zombieGroupData.isBaby) { ++ if (object instanceof Zombie.ZombieGroupData) { ++ Zombie.ZombieGroupData entityzombie_groupdatazombie = (Zombie.ZombieGroupData) object; ++ ++ if (entityzombie_groupdatazombie.isBaby) { + this.setBaby(true); +- if (zombieGroupData.canSpawnJockey) { +- if ((double)random.nextFloat() < 0.05) { +- List<Chicken> entitiesOfClass = level.getEntitiesOfClass( +- Chicken.class, this.getBoundingBox().inflate(5.0, 3.0, 5.0), EntitySelector.ENTITY_NOT_BEING_RIDDEN +- ); +- if (!entitiesOfClass.isEmpty()) { +- Chicken chicken = entitiesOfClass.get(0); +- chicken.setChickenJockey(true); +- this.startRiding(chicken); ++ if (entityzombie_groupdatazombie.canSpawnJockey) { ++ if ((double) randomsource.nextFloat() < 0.05D) { ++ List<Chicken> list = level.getEntitiesOfClass(Chicken.class, this.getBoundingBox().inflate(5.0D, 3.0D, 5.0D), EntitySelector.ENTITY_NOT_BEING_RIDDEN); ++ ++ if (!list.isEmpty()) { ++ Chicken entitychicken = (Chicken) list.get(0); ++ ++ entitychicken.setChickenJockey(true); ++ this.startRiding(entitychicken); + } +- } else if ((double)random.nextFloat() < 0.05) { +- Chicken chicken1 = EntityType.CHICKEN.create(this.level()); +- if (chicken1 != null) { +- chicken1.moveTo(this.getX(), this.getY(), this.getZ(), this.getYRot(), 0.0F); +- chicken1.finalizeSpawn(level, difficulty, MobSpawnType.JOCKEY, null, null); +- chicken1.setChickenJockey(true); +- this.startRiding(chicken1); +- level.addFreshEntity(chicken1); ++ } else if ((double) randomsource.nextFloat() < 0.05D) { ++ Chicken entitychicken1 = (Chicken) EntityType.CHICKEN.create(this.level()); ++ ++ if (entitychicken1 != null) { ++ entitychicken1.moveTo(this.getX(), this.getY(), this.getZ(), this.getYRot(), 0.0F); ++ entitychicken1.finalizeSpawn(level, difficulty, EnumMobSpawn.JOCKEY, (GroupDataEntity) null, (CompoundTag) null); ++ entitychicken1.setChickenJockey(true); ++ this.startRiding(entitychicken1); ++ level.addFreshEntity(entitychicken1, CreatureSpawnEvent.SpawnReason.MOUNT); // CraftBukkit + } + } + } + } + +- this.setCanBreakDoors(this.supportsBreakDoorGoal() && random.nextFloat() < specialMultiplier * 0.1F); +- this.populateDefaultEquipmentSlots(random, difficulty); +- this.populateDefaultEquipmentEnchantments(random, difficulty); ++ this.setCanBreakDoors(this.supportsBreakDoorGoal() && randomsource.nextFloat() < f * 0.1F); ++ this.populateDefaultEquipmentSlots(randomsource, difficulty); ++ this.populateDefaultEquipmentEnchantments(randomsource, difficulty); + } + + if (this.getItemBySlot(EquipmentSlot.HEAD).isEmpty()) { +- LocalDate localDate = LocalDate.now(); +- int i = localDate.get(ChronoField.DAY_OF_MONTH); +- int i1 = localDate.get(ChronoField.MONTH_OF_YEAR); +- if (i1 == 10 && i == 31 && random.nextFloat() < 0.25F) { +- this.setItemSlot(EquipmentSlot.HEAD, new ItemStack(random.nextFloat() < 0.1F ? Blocks.JACK_O_LANTERN : Blocks.CARVED_PUMPKIN)); ++ LocalDate localdate = LocalDate.now(); ++ int i = localdate.get(ChronoField.DAY_OF_MONTH); ++ int j = localdate.get(ChronoField.MONTH_OF_YEAR); ++ ++ if (j == 10 && i == 31 && randomsource.nextFloat() < 0.25F) { ++ this.setItemSlot(EquipmentSlot.HEAD, new ItemStack(randomsource.nextFloat() < 0.1F ? Blocks.JACK_O_LANTERN : Blocks.CARVED_PUMPKIN)); + this.armorDropChances[EquipmentSlot.HEAD.getIndex()] = 0.0F; + } + } + +- this.handleAttributes(specialMultiplier); +- return (SpawnGroupData)var11; ++ this.handleAttributes(f); ++ return (GroupDataEntity) object; + } + + public static boolean getSpawnAsBabyOdds(RandomSource random) { +@@ -509,32 +551,28 @@ + + protected void handleAttributes(float difficulty) { + this.randomizeReinforcementsChance(); +- this.getAttribute(Attributes.KNOCKBACK_RESISTANCE) +- .addPermanentModifier(new AttributeModifier("Random spawn bonus", this.random.nextDouble() * 0.05F, AttributeModifier.Operation.ADDITION)); +- double d = this.random.nextDouble() * 1.5 * (double)difficulty; +- if (d > 1.0) { +- this.getAttribute(Attributes.FOLLOW_RANGE) +- .addPermanentModifier(new AttributeModifier("Random zombie-spawn bonus", d, AttributeModifier.Operation.MULTIPLY_TOTAL)); ++ this.getAttribute(Attributes.KNOCKBACK_RESISTANCE).addPermanentModifier(new AttributeModifier("Random spawn bonus", this.random.nextDouble() * 0.05000000074505806D, AttributeModifier.Operation.ADDITION)); ++ double d0 = this.random.nextDouble() * 1.5D * (double) difficulty; ++ ++ if (d0 > 1.0D) { ++ this.getAttribute(Attributes.FOLLOW_RANGE).addPermanentModifier(new AttributeModifier("Random zombie-spawn bonus", d0, AttributeModifier.Operation.MULTIPLY_TOTAL)); + } + + if (this.random.nextFloat() < difficulty * 0.05F) { +- this.getAttribute(Attributes.SPAWN_REINFORCEMENTS_CHANCE) +- .addPermanentModifier(new AttributeModifier("Leader zombie bonus", this.random.nextDouble() * 0.25 + 0.5, AttributeModifier.Operation.ADDITION)); +- this.getAttribute(Attributes.MAX_HEALTH) +- .addPermanentModifier( +- new AttributeModifier("Leader zombie bonus", this.random.nextDouble() * 3.0 + 1.0, AttributeModifier.Operation.MULTIPLY_TOTAL) +- ); ++ this.getAttribute(Attributes.SPAWN_REINFORCEMENTS_CHANCE).addPermanentModifier(new AttributeModifier("Leader zombie bonus", this.random.nextDouble() * 0.25D + 0.5D, AttributeModifier.Operation.ADDITION)); ++ this.getAttribute(Attributes.MAX_HEALTH).addPermanentModifier(new AttributeModifier("Leader zombie bonus", this.random.nextDouble() * 3.0D + 1.0D, AttributeModifier.Operation.MULTIPLY_TOTAL)); + this.setCanBreakDoors(this.supportsBreakDoorGoal()); + } ++ + } + + protected void randomizeReinforcementsChance() { +- this.getAttribute(Attributes.SPAWN_REINFORCEMENTS_CHANCE).setBaseValue(this.random.nextDouble() * 0.1F); ++ this.getAttribute(Attributes.SPAWN_REINFORCEMENTS_CHANCE).setBaseValue(this.random.nextDouble() * 0.10000000149011612D); + } + + @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entityDimensions, float f) { +- return new Vector3f(0.0F, entityDimensions.height + 0.0625F * f, 0.0F); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ return new Vector3f(0.0F, entitysize.height + 0.0625F * f, 0.0F); + } + + @Override +@@ -545,41 +583,51 @@ + @Override + protected void dropCustomDeathLoot(DamageSource source, int looting, boolean recentlyHit) { + super.dropCustomDeathLoot(source, looting, recentlyHit); +- if (source.getEntity() instanceof Creeper creeper && creeper.canDropMobsSkull()) { +- ItemStack skull = this.getSkull(); +- if (!skull.isEmpty()) { +- creeper.increaseDroppedSkulls(); +- this.spawnAtLocation(skull); ++ Entity entity = source.getEntity(); ++ ++ if (entity instanceof Creeper) { ++ Creeper entitycreeper = (Creeper) entity; ++ ++ if (entitycreeper.canDropMobsSkull()) { ++ ItemStack itemstack = this.getSkull(); ++ ++ if (!itemstack.isEmpty()) { ++ entitycreeper.increaseDroppedSkulls(); ++ this.spawnAtLocation(itemstack); ++ } + } + } ++ + } + + protected ItemStack getSkull() { + return new ItemStack(Items.ZOMBIE_HEAD); + } + +- class ZombieAttackTurtleEggGoal extends RemoveBlockGoal { +- ZombieAttackTurtleEggGoal(PathfinderMob mob, double speedModifier, int verticalSearchRange) { +- super(Blocks.TURTLE_EGG, mob, speedModifier, verticalSearchRange); ++ private class ZombieAttackTurtleEggGoal extends RemoveBlockGoal { ++ ++ ZombieAttackTurtleEggGoal(PathfinderMob mob, double speedModifier, int i) { ++ super(Blocks.TURTLE_EGG, mob, speedModifier, i); + } + + @Override + public void playDestroyProgressSound(LevelAccessor level, BlockPos pos) { +- level.playSound(null, pos, SoundEvents.ZOMBIE_DESTROY_EGG, SoundSource.HOSTILE, 0.5F, 0.9F + Zombie.this.random.nextFloat() * 0.2F); ++ level.playSound((Player) null, pos, SoundEvents.ZOMBIE_DESTROY_EGG, SoundSource.HOSTILE, 0.5F, 0.9F + Zombie.this.random.nextFloat() * 0.2F); + } + + @Override + public void playBreakSound(Level level, BlockPos pos) { +- level.playSound(null, pos, SoundEvents.TURTLE_EGG_BREAK, SoundSource.BLOCKS, 0.7F, 0.9F + level.random.nextFloat() * 0.2F); ++ level.playSound((Player) null, pos, SoundEvents.TURTLE_EGG_BREAK, SoundSource.BLOCKS, 0.7F, 0.9F + level.random.nextFloat() * 0.2F); + } + + @Override + public double acceptedDistance() { +- return 1.14; ++ return 1.14D; + } + } + +- public static class ZombieGroupData implements SpawnGroupData { ++ public static class ZombieGroupData implements GroupDataEntity { ++ + public final boolean isBaby; + public final boolean canSpawnJockey; + diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/ZombieVillager.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/ZombieVillager.java.patch new file mode 100644 index 0000000000..e2bfe9f30e --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/ZombieVillager.java.patch @@ -0,0 +1,389 @@ +--- a/net/minecraft/world/entity/monster/ZombieVillager.java ++++ b/net/minecraft/world/entity/monster/ZombieVillager.java +@@ -3,11 +3,11 @@ + import com.mojang.logging.LogUtils; + import com.mojang.serialization.DataResult; + import com.mojang.serialization.Dynamic; ++import java.util.Objects; + import java.util.UUID; + import javax.annotation.Nullable; + import net.minecraft.advancements.CriteriaTriggers; + import net.minecraft.core.BlockPos; +-import net.minecraft.core.Holder; + import net.minecraft.core.registries.BuiltInRegistries; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.nbt.NbtOps; +@@ -15,12 +15,8 @@ + 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.world.DifficultyInstance; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.effect.MobEffectInstance; +@@ -28,9 +24,9 @@ + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; + import net.minecraft.world.entity.EquipmentSlot; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.SpawnGroupData; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.ai.village.ReputationEventType; + import net.minecraft.world.entity.npc.Villager; + import net.minecraft.world.entity.npc.VillagerData; +@@ -46,50 +42,63 @@ + import net.minecraft.world.level.ServerLevelAccessor; + import net.minecraft.world.level.block.BedBlock; + import net.minecraft.world.level.block.Blocks; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + import org.joml.Vector3f; + import org.slf4j.Logger; + ++// CraftBukkit start ++import net.minecraft.server.MinecraftServer; ++import net.minecraft.server.level.ServerLevel; ++import net.minecraft.server.level.ServerPlayer; ++import net.minecraft.sounds.SoundEvent; ++import net.minecraft.sounds.SoundEvents; ++import org.bukkit.event.entity.CreatureSpawnEvent; ++import org.bukkit.event.entity.EntityTransformEvent; ++// CraftBukkit end ++ + public class ZombieVillager extends Zombie implements VillagerDataHolder { ++ + private static final Logger LOGGER = LogUtils.getLogger(); +- private static final EntityDataAccessor<Boolean> DATA_CONVERTING_ID = SynchedEntityData.defineId(ZombieVillager.class, EntityDataSerializers.BOOLEAN); +- private static final EntityDataAccessor<VillagerData> DATA_VILLAGER_DATA = SynchedEntityData.defineId( +- ZombieVillager.class, EntityDataSerializers.VILLAGER_DATA +- ); ++ public static final EntityDataAccessor<Boolean> DATA_CONVERTING_ID = SynchedEntityData.defineId(ZombieVillager.class, EntityDataSerializers.BOOLEAN); ++ private static final EntityDataAccessor<VillagerData> DATA_VILLAGER_DATA = SynchedEntityData.defineId(ZombieVillager.class, EntityDataSerializers.VILLAGER_DATA); + private static final int VILLAGER_CONVERSION_WAIT_MIN = 3600; + private static final int VILLAGER_CONVERSION_WAIT_MAX = 6000; + private static final int MAX_SPECIAL_BLOCKS_COUNT = 14; + private static final int SPECIAL_BLOCK_RADIUS = 4; +- private int villagerConversionTime; ++ public int villagerConversionTime; + @Nullable +- private UUID conversionStarter; ++ public UUID conversionStarter; + @Nullable + private Tag gossips; + @Nullable + private CompoundTag tradeOffers; + private int villagerXp; ++ private int lastTick = MinecraftServer.currentTick; // CraftBukkit - add field + + public ZombieVillager(EntityType<? extends ZombieVillager> entityType, Level level) { + super(entityType, level); +- BuiltInRegistries.VILLAGER_PROFESSION +- .getRandom(this.random) +- .ifPresent(profession -> this.setVillagerData(this.getVillagerData().setProfession(profession.value()))); ++ BuiltInRegistries.VILLAGER_PROFESSION.getRandom(this.random).ifPresent((holder_c) -> { ++ this.setVillagerData(this.getVillagerData().setProfession((VillagerProfession) holder_c.value())); ++ }); + } + + @Override + protected void defineSynchedData() { + super.defineSynchedData(); +- this.entityData.define(DATA_CONVERTING_ID, false); +- this.entityData.define(DATA_VILLAGER_DATA, new VillagerData(VillagerType.PLAINS, VillagerProfession.NONE, 1)); ++ this.entityData.define(ZombieVillager.DATA_CONVERTING_ID, false); ++ this.entityData.define(ZombieVillager.DATA_VILLAGER_DATA, new VillagerData(VillagerType.PLAINS, VillagerProfession.NONE, 1)); + } + + @Override + public void addAdditionalSaveData(CompoundTag compound) { + super.addAdditionalSaveData(compound); +- VillagerData.CODEC +- .encodeStart(NbtOps.INSTANCE, this.getVillagerData()) +- .resultOrPartial(LOGGER::error) +- .ifPresent(tag -> compound.put("VillagerData", tag)); ++ DataResult<Tag> dataresult = VillagerData.CODEC.encodeStart(NbtOps.INSTANCE, this.getVillagerData()); // CraftBukkit - decompile error ++ Logger logger = ZombieVillager.LOGGER; ++ ++ Objects.requireNonNull(logger); ++ dataresult.resultOrPartial(logger::error).ifPresent((nbtbase) -> { ++ compound.put("VillagerData", nbtbase); ++ }); + if (this.tradeOffers != null) { + compound.put("Offers", this.tradeOffers); + } +@@ -110,8 +119,11 @@ + public void readAdditionalSaveData(CompoundTag compound) { + super.readAdditionalSaveData(compound); + if (compound.contains("VillagerData", 10)) { +- DataResult<VillagerData> dataResult = VillagerData.CODEC.parse(new Dynamic<>(NbtOps.INSTANCE, compound.get("VillagerData"))); +- dataResult.resultOrPartial(LOGGER::error).ifPresent(this::setVillagerData); ++ DataResult<VillagerData> dataresult = VillagerData.CODEC.parse(new Dynamic(NbtOps.INSTANCE, compound.get("VillagerData"))); ++ Logger logger = ZombieVillager.LOGGER; ++ ++ Objects.requireNonNull(logger); ++ dataresult.resultOrPartial(logger::error).ifPresent(this::setVillagerData); + } + + if (compound.contains("Offers", 10)) { +@@ -129,28 +141,36 @@ + if (compound.contains("Xp", 3)) { + this.villagerXp = compound.getInt("Xp"); + } ++ + } + + @Override + public void tick() { + if (!this.level().isClientSide && this.isAlive() && this.isConverting()) { +- int conversionProgress = this.getConversionProgress(); +- this.villagerConversionTime -= conversionProgress; ++ int i = this.getConversionProgress(); ++ // CraftBukkit start - Use wall time instead of ticks for villager conversion ++ int elapsedTicks = MinecraftServer.currentTick - this.lastTick; ++ i *= elapsedTicks; ++ // CraftBukkit end ++ ++ this.villagerConversionTime -= i; + if (this.villagerConversionTime <= 0) { +- this.finishConversion((ServerLevel)this.level()); ++ this.finishConversion((ServerLevel) this.level()); + } + } + + super.tick(); ++ this.lastTick = MinecraftServer.currentTick; // CraftBukkit + } + + @Override +- public InteractionResult mobInteract(Player player, InteractionHand hand) { +- ItemStack itemInHand = player.getItemInHand(hand); +- if (itemInHand.is(Items.GOLDEN_APPLE)) { ++ public InteractionResult mobInteract(Player player, EnumHand hand) { ++ ItemStack itemstack = player.getItemInHand(hand); ++ ++ if (itemstack.is(Items.GOLDEN_APPLE)) { + if (this.hasEffect(MobEffects.WEAKNESS)) { + if (!player.getAbilities().instabuild) { +- itemInHand.shrink(1); ++ itemstack.shrink(1); + } + + if (!this.level().isClientSide) { +@@ -177,98 +197,108 @@ + } + + public boolean isConverting() { +- return this.getEntityData().get(DATA_CONVERTING_ID); ++ return (Boolean) this.getEntityData().get(ZombieVillager.DATA_CONVERTING_ID); + } + +- private void startConverting(@Nullable UUID conversionStarter, int villagerConversionTime) { ++ public void startConverting(@Nullable UUID conversionStarter, int villagerConversionTime) { + this.conversionStarter = conversionStarter; + this.villagerConversionTime = villagerConversionTime; +- this.getEntityData().set(DATA_CONVERTING_ID, true); +- this.removeEffect(MobEffects.WEAKNESS); +- this.addEffect(new MobEffectInstance(MobEffects.DAMAGE_BOOST, villagerConversionTime, Math.min(this.level().getDifficulty().getId() - 1, 0))); +- this.level().broadcastEntityEvent(this, (byte)16); ++ this.getEntityData().set(ZombieVillager.DATA_CONVERTING_ID, true); ++ // CraftBukkit start ++ this.removeEffect(MobEffects.WEAKNESS, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.CONVERSION); ++ this.addEffect(new MobEffectInstance(MobEffects.DAMAGE_BOOST, villagerConversionTime, Math.min(this.level().getDifficulty().getId() - 1, 0)), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.CONVERSION); ++ // CraftBukkit end ++ this.level().broadcastEntityEvent(this, (byte) 16); + } + + @Override + public void handleEntityEvent(byte id) { + if (id == 16) { + if (!this.isSilent()) { +- this.level() +- .playLocalSound( +- this.getX(), +- this.getEyeY(), +- this.getZ(), +- SoundEvents.ZOMBIE_VILLAGER_CURE, +- this.getSoundSource(), +- 1.0F + this.random.nextFloat(), +- this.random.nextFloat() * 0.7F + 0.3F, +- false +- ); ++ this.level().playLocalSound(this.getX(), this.getEyeY(), this.getZ(), SoundEvents.ZOMBIE_VILLAGER_CURE, this.getSoundSource(), 1.0F + this.random.nextFloat(), this.random.nextFloat() * 0.7F + 0.3F, false); + } ++ + } else { + super.handleEntityEvent(id); + } + } + + private void finishConversion(ServerLevel serverLevel) { +- Villager villager = this.convertTo(EntityType.VILLAGER, false); ++ // CraftBukkit start ++ Villager entityvillager = (Villager) this.convertTo(EntityType.VILLAGER, false, EntityTransformEvent.TransformReason.CURED, CreatureSpawnEvent.SpawnReason.CURED); ++ if (entityvillager == null) { ++ ((org.bukkit.entity.ZombieVillager) getBukkitEntity()).setConversionTime(-1); // SPIGOT-5208: End conversion to stop event spam ++ return; ++ } ++ // CraftBukkit end ++ EquipmentSlot[] aenumitemslot = EquipmentSlot.values(); ++ int i = aenumitemslot.length; + +- for (EquipmentSlot equipmentSlot : EquipmentSlot.values()) { +- ItemStack itemBySlot = this.getItemBySlot(equipmentSlot); +- if (!itemBySlot.isEmpty()) { +- if (EnchantmentHelper.hasBindingCurse(itemBySlot)) { +- villager.getSlot(equipmentSlot.getIndex() + 300).set(itemBySlot); ++ for (int j = 0; j < i; ++j) { ++ EquipmentSlot enumitemslot = aenumitemslot[j]; ++ ItemStack itemstack = this.getItemBySlot(enumitemslot); ++ ++ if (!itemstack.isEmpty()) { ++ if (EnchantmentHelper.hasBindingCurse(itemstack)) { ++ entityvillager.getSlot(enumitemslot.getIndex() + 300).set(itemstack); + } else { +- double d = (double)this.getEquipmentDropChance(equipmentSlot); +- if (d > 1.0) { +- this.spawnAtLocation(itemBySlot); ++ double d0 = (double) this.getEquipmentDropChance(enumitemslot); ++ ++ if (d0 > 1.0D) { ++ this.forceDrops = true; // CraftBukkit ++ this.spawnAtLocation(itemstack); ++ this.forceDrops = false; // CraftBukkit + } + } + } + } + +- villager.setVillagerData(this.getVillagerData()); ++ entityvillager.setVillagerData(this.getVillagerData()); + if (this.gossips != null) { +- villager.setGossips(this.gossips); ++ entityvillager.setGossips(this.gossips); + } + + if (this.tradeOffers != null) { +- villager.setOffers(new MerchantOffers(this.tradeOffers)); ++ entityvillager.setOffers(new MerchantOffers(this.tradeOffers)); + } + +- villager.setVillagerXp(this.villagerXp); +- villager.finalizeSpawn(serverLevel, serverLevel.getCurrentDifficultyAt(villager.blockPosition()), MobSpawnType.CONVERSION, null, null); +- villager.refreshBrain(serverLevel); ++ entityvillager.setVillagerXp(this.villagerXp); ++ entityvillager.finalizeSpawn(serverLevel, serverLevel.getCurrentDifficultyAt(entityvillager.blockPosition()), EnumMobSpawn.CONVERSION, (GroupDataEntity) null, (CompoundTag) null); ++ entityvillager.refreshBrain(serverLevel); + if (this.conversionStarter != null) { +- Player playerByUUID = serverLevel.getPlayerByUUID(this.conversionStarter); +- if (playerByUUID instanceof ServerPlayer) { +- CriteriaTriggers.CURED_ZOMBIE_VILLAGER.trigger((ServerPlayer)playerByUUID, this, villager); +- serverLevel.onReputationEvent(ReputationEventType.ZOMBIE_VILLAGER_CURED, playerByUUID, villager); ++ Player entityhuman = serverLevel.getPlayerByUUID(this.conversionStarter); ++ ++ if (entityhuman instanceof ServerPlayer) { ++ CriteriaTriggers.CURED_ZOMBIE_VILLAGER.trigger((ServerPlayer) entityhuman, this, entityvillager); ++ serverLevel.onReputationEvent(ReputationEventType.ZOMBIE_VILLAGER_CURED, entityhuman, entityvillager); + } + } + +- villager.addEffect(new MobEffectInstance(MobEffects.CONFUSION, 200, 0)); ++ entityvillager.addEffect(new MobEffectInstance(MobEffects.CONFUSION, 200, 0), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.CONVERSION); // CraftBukkit + if (!this.isSilent()) { +- serverLevel.levelEvent(null, 1027, this.blockPosition(), 0); ++ serverLevel.levelEvent((Player) null, 1027, this.blockPosition(), 0); + } ++ + } + + private int getConversionProgress() { + int i = 1; ++ + if (this.random.nextFloat() < 0.01F) { +- int i1 = 0; +- BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos(); ++ int j = 0; ++ BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos(); + +- for (int i2 = (int)this.getX() - 4; i2 < (int)this.getX() + 4 && i1 < 14; i2++) { +- for (int i3 = (int)this.getY() - 4; i3 < (int)this.getY() + 4 && i1 < 14; i3++) { +- for (int i4 = (int)this.getZ() - 4; i4 < (int)this.getZ() + 4 && i1 < 14; i4++) { +- BlockState blockState = this.level().getBlockState(mutableBlockPos.set(i2, i3, i4)); +- if (blockState.is(Blocks.IRON_BARS) || blockState.getBlock() instanceof BedBlock) { ++ for (int k = (int) this.getX() - 4; k < (int) this.getX() + 4 && j < 14; ++k) { ++ for (int l = (int) this.getY() - 4; l < (int) this.getY() + 4 && j < 14; ++l) { ++ for (int i1 = (int) this.getZ() - 4; i1 < (int) this.getZ() + 4 && j < 14; ++i1) { ++ IBlockData iblockdata = this.level().getBlockState(blockposition_mutableblockposition.set(k, l, i1)); ++ ++ if (iblockdata.is(Blocks.IRON_BARS) || iblockdata.getBlock() instanceof BedBlock) { + if (this.random.nextFloat() < 0.3F) { +- i++; ++ ++i; + } + +- i1++; ++ ++j; + } + } + } +@@ -280,9 +310,7 @@ + + @Override + public float getVoicePitch() { +- return this.isBaby() +- ? (this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 2.0F +- : (this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 1.0F; ++ return this.isBaby() ? (this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 2.0F : (this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 1.0F; + } + + @Override +@@ -320,26 +348,25 @@ + + @Nullable + @Override +- public SpawnGroupData finalizeSpawn( +- ServerLevelAccessor level, DifficultyInstance difficulty, MobSpawnType reason, @Nullable SpawnGroupData spawnData, @Nullable CompoundTag dataTag +- ) { ++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) { + this.setVillagerData(this.getVillagerData().setType(VillagerType.byBiome(level.getBiome(this.blockPosition())))); + return super.finalizeSpawn(level, difficulty, reason, spawnData, dataTag); + } + + @Override + public void setVillagerData(VillagerData data) { +- VillagerData villagerData = this.getVillagerData(); +- if (villagerData.getProfession() != data.getProfession()) { ++ VillagerData villagerdata1 = this.getVillagerData(); ++ ++ if (villagerdata1.getProfession() != data.getProfession()) { + this.tradeOffers = null; + } + +- this.entityData.set(DATA_VILLAGER_DATA, data); ++ this.entityData.set(ZombieVillager.DATA_VILLAGER_DATA, data); + } + + @Override + public VillagerData getVillagerData() { +- return this.entityData.get(DATA_VILLAGER_DATA); ++ return (VillagerData) this.entityData.get(ZombieVillager.DATA_VILLAGER_DATA); + } + + public int getVillagerXp() { +@@ -351,7 +378,7 @@ + } + + @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entityDimensions, float f) { +- return new Vector3f(0.0F, entityDimensions.height + 0.175F * f, 0.0F); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ return new Vector3f(0.0F, entitysize.height + 0.175F * f, 0.0F); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/ZombifiedPiglin.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/ZombifiedPiglin.java.patch new file mode 100644 index 0000000000..e8ce6c3e73 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/ZombifiedPiglin.java.patch @@ -0,0 +1,202 @@ +--- a/net/minecraft/world/entity/monster/ZombifiedPiglin.java ++++ b/net/minecraft/world/entity/monster/ZombifiedPiglin.java +@@ -15,13 +15,13 @@ + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntitySelector; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; + import net.minecraft.world.entity.EquipmentSlot; + import net.minecraft.world.entity.LivingEntity; +-import net.minecraft.world.entity.MobSpawnType; + import net.minecraft.world.entity.NeutralMob; +-import net.minecraft.world.entity.Pose; + import net.minecraft.world.entity.ai.attributes.AttributeInstance; + import net.minecraft.world.entity.ai.attributes.AttributeModifier; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; +@@ -43,10 +43,9 @@ + import org.joml.Vector3f; + + public class ZombifiedPiglin extends Zombie implements NeutralMob { ++ + private static final UUID SPEED_MODIFIER_ATTACKING_UUID = UUID.fromString("49455A49-7EC5-45BA-B886-3B90B23A1718"); +- private static final AttributeModifier SPEED_MODIFIER_ATTACKING = new AttributeModifier( +- SPEED_MODIFIER_ATTACKING_UUID, "Attacking speed boost", 0.05, AttributeModifier.Operation.ADDITION +- ); ++ private static final AttributeModifier SPEED_MODIFIER_ATTACKING = new AttributeModifier(ZombifiedPiglin.SPEED_MODIFIER_ATTACKING_UUID, "Attacking speed boost", 0.05D, AttributeModifier.Operation.ADDITION); + private static final UniformInt FIRST_ANGER_SOUND_DELAY = TimeUtil.rangeOfSeconds(0, 1); + private int playFirstAngerSoundIn; + private static final UniformInt PERSISTENT_ANGER_TIME = TimeUtil.rangeOfSeconds(20, 39); +@@ -71,22 +70,19 @@ + + @Override + protected void addBehaviourGoals() { +- this.goalSelector.addGoal(2, new ZombieAttackGoal(this, 1.0, false)); +- this.goalSelector.addGoal(7, new WaterAvoidingRandomStrollGoal(this, 1.0)); +- this.targetSelector.addGoal(1, new HurtByTargetGoal(this).setAlertOthers()); ++ this.goalSelector.addGoal(2, new ZombieAttackGoal(this, 1.0D, false)); ++ this.goalSelector.addGoal(7, new WaterAvoidingRandomStrollGoal(this, 1.0D)); ++ this.targetSelector.addGoal(1, (new HurtByTargetGoal(this, new Class[0])).setAlertOthers()); + this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, 10, true, false, this::isAngryAt)); + this.targetSelector.addGoal(3, new ResetUniversalAngerTargetGoal<>(this, true)); + } + + public static AttributeSupplier.Builder createAttributes() { +- return Zombie.createAttributes() +- .add(Attributes.SPAWN_REINFORCEMENTS_CHANCE, 0.0) +- .add(Attributes.MOVEMENT_SPEED, 0.23F) +- .add(Attributes.ATTACK_DAMAGE, 5.0); ++ return Zombie.createAttributes().add(Attributes.SPAWN_REINFORCEMENTS_CHANCE, 0.0D).add(Attributes.MOVEMENT_SPEED, 0.23000000417232513D).add(Attributes.ATTACK_DAMAGE, 5.0D); + } + + @Override +- protected float getStandingEyeHeight(Pose pose, EntityDimensions size) { ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions size) { + return this.isBaby() ? 0.96999997F : 1.79F; + } + +@@ -97,18 +93,19 @@ + + @Override + protected void customServerAiStep() { +- AttributeInstance attribute = this.getAttribute(Attributes.MOVEMENT_SPEED); ++ AttributeInstance attributemodifiable = this.getAttribute(Attributes.MOVEMENT_SPEED); ++ + if (this.isAngry()) { +- if (!this.isBaby() && !attribute.hasModifier(SPEED_MODIFIER_ATTACKING)) { +- attribute.addTransientModifier(SPEED_MODIFIER_ATTACKING); ++ if (!this.isBaby() && !attributemodifiable.hasModifier(ZombifiedPiglin.SPEED_MODIFIER_ATTACKING)) { ++ attributemodifiable.addTransientModifier(ZombifiedPiglin.SPEED_MODIFIER_ATTACKING); + } + + this.maybePlayFirstAngerSound(); +- } else if (attribute.hasModifier(SPEED_MODIFIER_ATTACKING)) { +- attribute.removeModifier(SPEED_MODIFIER_ATTACKING.getId()); ++ } else if (attributemodifiable.hasModifier(ZombifiedPiglin.SPEED_MODIFIER_ATTACKING)) { ++ attributemodifiable.removeModifier(ZombifiedPiglin.SPEED_MODIFIER_ATTACKING.getId()); + } + +- this.updatePersistentAnger((ServerLevel)this.level(), true); ++ this.updatePersistentAnger((ServerLevel) this.level(), true); + if (this.getTarget() != null) { + this.maybeAlertOthers(); + } +@@ -122,35 +119,39 @@ + + private void maybePlayFirstAngerSound() { + if (this.playFirstAngerSoundIn > 0) { +- this.playFirstAngerSoundIn--; ++ --this.playFirstAngerSoundIn; + if (this.playFirstAngerSoundIn == 0) { + this.playAngerSound(); + } + } ++ + } + + private void maybeAlertOthers() { + if (this.ticksUntilNextAlert > 0) { +- this.ticksUntilNextAlert--; ++ --this.ticksUntilNextAlert; + } else { + if (this.getSensing().hasLineOfSight(this.getTarget())) { + this.alertOthers(); + } + +- this.ticksUntilNextAlert = ALERT_INTERVAL.sample(this.random); ++ this.ticksUntilNextAlert = ZombifiedPiglin.ALERT_INTERVAL.sample(this.random); + } + } + + private void alertOthers() { +- double attributeValue = this.getAttributeValue(Attributes.FOLLOW_RANGE); +- AABB aABB = AABB.unitCubeFromLowerCorner(this.position()).inflate(attributeValue, 10.0, attributeValue); +- this.level() +- .getEntitiesOfClass(ZombifiedPiglin.class, aABB, EntitySelector.NO_SPECTATORS) +- .stream() +- .filter(zombifiedPiglin -> zombifiedPiglin != this) +- .filter(zombifiedPiglin -> zombifiedPiglin.getTarget() == null) +- .filter(zombifiedPiglin -> !zombifiedPiglin.isAlliedTo(this.getTarget())) +- .forEach(zombifiedPiglin -> zombifiedPiglin.setTarget(this.getTarget())); ++ double d0 = this.getAttributeValue(Attributes.FOLLOW_RANGE); ++ AABB axisalignedbb = AABB.unitCubeFromLowerCorner(this.position()).inflate(d0, 10.0D, d0); ++ ++ this.level().getEntitiesOfClass(ZombifiedPiglin.class, axisalignedbb, EntitySelector.NO_SPECTATORS).stream().filter((entitypigzombie) -> { ++ return entitypigzombie != this; ++ }).filter((entitypigzombie) -> { ++ return entitypigzombie.getTarget() == null; ++ }).filter((entitypigzombie) -> { ++ return !entitypigzombie.isAlliedTo((Entity) this.getTarget()); ++ }).forEach((entitypigzombie) -> { ++ entitypigzombie.setTarget(this.getTarget(), org.bukkit.event.entity.EntityTargetEvent.TargetReason.TARGET_ATTACKED_NEARBY_ENTITY, true); // CraftBukkit ++ }); + } + + private void playAngerSound() { +@@ -158,27 +159,34 @@ + } + + @Override +- public void setTarget(@Nullable LivingEntity livingEntity) { +- if (this.getTarget() == null && livingEntity != null) { +- this.playFirstAngerSoundIn = FIRST_ANGER_SOUND_DELAY.sample(this.random); +- this.ticksUntilNextAlert = ALERT_INTERVAL.sample(this.random); ++ public boolean setTarget(@Nullable LivingEntity entityliving, org.bukkit.event.entity.EntityTargetEvent.TargetReason reason, boolean fireEvent) { // CraftBukkit - signature ++ if (this.getTarget() == null && entityliving != null) { ++ this.playFirstAngerSoundIn = ZombifiedPiglin.FIRST_ANGER_SOUND_DELAY.sample(this.random); ++ this.ticksUntilNextAlert = ZombifiedPiglin.ALERT_INTERVAL.sample(this.random); + } + +- if (livingEntity instanceof Player) { +- this.setLastHurtByPlayer((Player)livingEntity); ++ if (entityliving instanceof Player) { ++ this.setLastHurtByPlayer((Player) entityliving); + } + +- super.setTarget(livingEntity); ++ return super.setTarget(entityliving, reason, fireEvent); // CraftBukkit + } + + @Override + public void startPersistentAngerTimer() { +- this.setRemainingPersistentAngerTime(PERSISTENT_ANGER_TIME.sample(this.random)); ++ // CraftBukkit start ++ Entity entity = ((ServerLevel) this.level()).getEntity(getPersistentAngerTarget()); ++ org.bukkit.event.entity.PigZombieAngerEvent event = new org.bukkit.event.entity.PigZombieAngerEvent((org.bukkit.entity.PigZombie) this.getBukkitEntity(), (entity == null) ? null : entity.getBukkitEntity(), ZombifiedPiglin.PERSISTENT_ANGER_TIME.sample(this.random)); ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ this.setPersistentAngerTarget(null); ++ return; ++ } ++ this.setRemainingPersistentAngerTime(event.getNewAnger()); ++ // CraftBukkit end + } + +- public static boolean checkZombifiedPiglinSpawnRules( +- EntityType<ZombifiedPiglin> zombifiedPiglin, LevelAccessor level, MobSpawnType spawnType, BlockPos pos, RandomSource random +- ) { ++ public static boolean checkZombifiedPiglinSpawnRules(EntityType<ZombifiedPiglin> zombifiedPiglin, LevelAccessor level, EnumMobSpawn spawnType, BlockPos pos, RandomSource random) { + return level.getDifficulty() != Difficulty.PEACEFUL && !level.getBlockState(pos.below()).is(Blocks.NETHER_WART_BLOCK); + } + +@@ -236,7 +244,7 @@ + + @Override + protected void randomizeReinforcementsChance() { +- this.getAttribute(Attributes.SPAWN_REINFORCEMENTS_CHANCE).setBaseValue(0.0); ++ this.getAttribute(Attributes.SPAWN_REINFORCEMENTS_CHANCE).setBaseValue(0.0D); + } + + @Nullable +@@ -256,7 +264,7 @@ + } + + @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entityDimensions, float f) { +- return new Vector3f(0.0F, entityDimensions.height + 0.05F * f, 0.0F); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ return new Vector3f(0.0F, entitysize.height + 0.05F * f, 0.0F); + } + } diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/piglin/AbstractPiglin.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/piglin/AbstractPiglin.java.patch new file mode 100644 index 0000000000..4b8d2d70f8 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/piglin/AbstractPiglin.java.patch @@ -0,0 +1,133 @@ +--- a/net/minecraft/world/entity/monster/piglin/AbstractPiglin.java ++++ b/net/minecraft/world/entity/monster/piglin/AbstractPiglin.java +@@ -11,9 +11,9 @@ + import net.minecraft.world.effect.MobEffects; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; + import net.minecraft.world.entity.LivingEntity; +-import net.minecraft.world.entity.Pose; + import net.minecraft.world.entity.ai.memory.MemoryModuleType; + import net.minecraft.world.entity.ai.navigation.GroundPathNavigation; + import net.minecraft.world.entity.ai.util.GoalUtils; +@@ -25,12 +25,11 @@ + import org.joml.Vector3f; + + public abstract class AbstractPiglin extends Monster { +- protected static final EntityDataAccessor<Boolean> DATA_IMMUNE_TO_ZOMBIFICATION = SynchedEntityData.defineId( +- AbstractPiglin.class, EntityDataSerializers.BOOLEAN +- ); ++ ++ protected static final EntityDataAccessor<Boolean> DATA_IMMUNE_TO_ZOMBIFICATION = SynchedEntityData.defineId(AbstractPiglin.class, EntityDataSerializers.BOOLEAN); + protected static final int CONVERSION_TIME = 300; + protected static final float PIGLIN_EYE_HEIGHT = 1.79F; +- protected int timeInOverworld; ++ public int timeInOverworld; + + public AbstractPiglin(EntityType<? extends AbstractPiglin> entityType, Level level) { + super(entityType, level); +@@ -42,12 +41,13 @@ + + private void applyOpenDoorsAbility() { + if (GoalUtils.hasGroundPathNavigation(this)) { +- ((GroundPathNavigation)this.getNavigation()).setCanOpenDoors(true); ++ ((GroundPathNavigation) this.getNavigation()).setCanOpenDoors(true); + } ++ + } + + @Override +- protected float getStandingEyeHeight(Pose pose, EntityDimensions dimensions) { ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions dimensions) { + return 1.79F; + } + +@@ -57,24 +57,24 @@ + } + + @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entityDimensions, float f) { +- return new Vector3f(0.0F, entityDimensions.height + 0.0625F * f, 0.0F); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ return new Vector3f(0.0F, entitysize.height + 0.0625F * f, 0.0F); + } + + protected abstract boolean canHunt(); + + public void setImmuneToZombification(boolean immuneToZombification) { +- this.getEntityData().set(DATA_IMMUNE_TO_ZOMBIFICATION, immuneToZombification); ++ this.getEntityData().set(AbstractPiglin.DATA_IMMUNE_TO_ZOMBIFICATION, immuneToZombification); + } + +- protected boolean isImmuneToZombification() { +- return this.getEntityData().get(DATA_IMMUNE_TO_ZOMBIFICATION); ++ public boolean isImmuneToZombification() { ++ return (Boolean) this.getEntityData().get(AbstractPiglin.DATA_IMMUNE_TO_ZOMBIFICATION); + } + + @Override + protected void defineSynchedData() { + super.defineSynchedData(); +- this.entityData.define(DATA_IMMUNE_TO_ZOMBIFICATION, false); ++ this.entityData.define(AbstractPiglin.DATA_IMMUNE_TO_ZOMBIFICATION, false); + } + + @Override +@@ -98,15 +98,16 @@ + protected void customServerAiStep() { + super.customServerAiStep(); + if (this.isConverting()) { +- this.timeInOverworld++; ++ ++this.timeInOverworld; + } else { + this.timeInOverworld = 0; + } + + if (this.timeInOverworld > 300) { + this.playConvertedSound(); +- this.finishConversion((ServerLevel)this.level()); ++ this.finishConversion((ServerLevel) this.level()); + } ++ + } + + public boolean isConverting() { +@@ -114,22 +115,24 @@ + } + + protected void finishConversion(ServerLevel serverLevel) { +- ZombifiedPiglin zombifiedPiglin = this.convertTo(EntityType.ZOMBIFIED_PIGLIN, true); +- if (zombifiedPiglin != null) { +- zombifiedPiglin.addEffect(new MobEffectInstance(MobEffects.CONFUSION, 200, 0)); ++ ZombifiedPiglin entitypigzombie = (ZombifiedPiglin) this.convertTo(EntityType.ZOMBIFIED_PIGLIN, true, org.bukkit.event.entity.EntityTransformEvent.TransformReason.PIGLIN_ZOMBIFIED, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.PIGLIN_ZOMBIFIED); // CraftBukkit - add spawn and transform reasons ++ ++ if (entitypigzombie != null) { ++ entitypigzombie.addEffect(new MobEffectInstance(MobEffects.CONFUSION, 200, 0)); + } ++ + } + + public boolean isAdult() { + return !this.isBaby(); + } + +- public abstract PiglinArmPose getArmPose(); ++ public abstract EntityPiglinArmPose getArmPose(); + + @Nullable + @Override + public LivingEntity getTarget() { +- return this.brain.getMemory(MemoryModuleType.ATTACK_TARGET).orElse(null); ++ return (LivingEntity) this.brain.getMemory(MemoryModuleType.ATTACK_TARGET).orElse(null); // CraftBukkit - decompile error + } + + protected boolean isHoldingMeleeWeapon() { +@@ -141,6 +144,7 @@ + if (PiglinAi.isIdle(this)) { + super.playAmbientSound(); + } ++ + } + + @Override diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/piglin/Piglin.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/piglin/Piglin.java.patch new file mode 100644 index 0000000000..7bda1083f5 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/piglin/Piglin.java.patch @@ -0,0 +1,474 @@ +--- a/net/minecraft/world/entity/monster/piglin/Piglin.java ++++ b/net/minecraft/world/entity/monster/piglin/Piglin.java +@@ -5,30 +5,22 @@ + import java.util.List; + import java.util.UUID; + import javax.annotation.Nullable; +-import net.minecraft.core.BlockPos; +-import net.minecraft.nbt.CompoundTag; +-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.sounds.SoundEvent; +-import net.minecraft.sounds.SoundEvents; + import net.minecraft.util.RandomSource; + import net.minecraft.util.VisibleForDebug; + import net.minecraft.world.DifficultyInstance; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.SimpleContainer; + import net.minecraft.world.damagesource.DamageSource; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; + import net.minecraft.world.entity.EquipmentSlot; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.LivingEntity; + import net.minecraft.world.entity.Mob; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.Pose; +-import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.ai.Brain; + import net.minecraft.world.entity.ai.attributes.AttributeInstance; + import net.minecraft.world.entity.ai.attributes.AttributeModifier; +@@ -53,16 +45,35 @@ + import net.minecraft.world.level.LevelAccessor; + import net.minecraft.world.level.ServerLevelAccessor; + import net.minecraft.world.level.block.Blocks; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.state.IBlockData; + ++// CraftBukkit start ++import java.util.stream.Collectors; ++import java.util.HashSet; ++import java.util.Set; ++import net.minecraft.core.BlockPos; ++import net.minecraft.core.registries.BuiltInRegistries; ++import net.minecraft.nbt.CompoundTag; ++import net.minecraft.nbt.ListTag; ++import net.minecraft.nbt.StringTag; ++import net.minecraft.nbt.Tag; ++import net.minecraft.network.syncher.EntityDataAccessor; ++import net.minecraft.network.syncher.EntityDataSerializers; ++import net.minecraft.network.syncher.SynchedEntityData; ++import net.minecraft.resources.ResourceLocation; ++import net.minecraft.server.level.ServerLevel; ++import net.minecraft.sounds.SoundEvent; ++import net.minecraft.sounds.SoundEvents; ++import net.minecraft.world.item.Item; ++// CraftBukkit end ++ + public class Piglin extends AbstractPiglin implements CrossbowAttackMob, InventoryCarrier { ++ + private static final EntityDataAccessor<Boolean> DATA_BABY_ID = SynchedEntityData.defineId(Piglin.class, EntityDataSerializers.BOOLEAN); + private static final EntityDataAccessor<Boolean> DATA_IS_CHARGING_CROSSBOW = SynchedEntityData.defineId(Piglin.class, EntityDataSerializers.BOOLEAN); + private static final EntityDataAccessor<Boolean> DATA_IS_DANCING = SynchedEntityData.defineId(Piglin.class, EntityDataSerializers.BOOLEAN); + private static final UUID SPEED_MODIFIER_BABY_UUID = UUID.fromString("766bfa64-11f3-11ea-8d71-362b9e155667"); +- private static final AttributeModifier SPEED_MODIFIER_BABY = new AttributeModifier( +- SPEED_MODIFIER_BABY_UUID, "Baby speed boost", 0.2F, AttributeModifier.Operation.MULTIPLY_BASE +- ); ++ private static final AttributeModifier SPEED_MODIFIER_BABY = new AttributeModifier(Piglin.SPEED_MODIFIER_BABY_UUID, "Baby speed boost", 0.20000000298023224D, AttributeModifier.Operation.MULTIPLY_BASE); + private static final int MAX_HEALTH = 16; + private static final float MOVEMENT_SPEED_WHEN_FIGHTING = 0.35F; + private static final int ATTACK_DAMAGE = 5; +@@ -71,53 +82,15 @@ + private static final int MAX_PASSENGERS_ON_ONE_HOGLIN = 3; + private static final float PROBABILITY_OF_SPAWNING_AS_BABY = 0.2F; + private static final float BABY_EYE_HEIGHT_ADJUSTMENT = 0.82F; +- private static final double PROBABILITY_OF_SPAWNING_WITH_CROSSBOW_INSTEAD_OF_SWORD = 0.5; +- private final SimpleContainer inventory = new SimpleContainer(8); +- private boolean cannotHunt; +- protected static final ImmutableList<SensorType<? extends Sensor<? super Piglin>>> SENSOR_TYPES = ImmutableList.of( +- SensorType.NEAREST_LIVING_ENTITIES, SensorType.NEAREST_PLAYERS, SensorType.NEAREST_ITEMS, SensorType.HURT_BY, SensorType.PIGLIN_SPECIFIC_SENSOR +- ); +- protected static final ImmutableList<MemoryModuleType<?>> MEMORY_TYPES = ImmutableList.of( +- MemoryModuleType.LOOK_TARGET, +- MemoryModuleType.DOORS_TO_CLOSE, +- MemoryModuleType.NEAREST_LIVING_ENTITIES, +- MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES, +- MemoryModuleType.NEAREST_VISIBLE_PLAYER, +- MemoryModuleType.NEAREST_VISIBLE_ATTACKABLE_PLAYER, +- MemoryModuleType.NEAREST_VISIBLE_ADULT_PIGLINS, +- MemoryModuleType.NEARBY_ADULT_PIGLINS, +- MemoryModuleType.NEAREST_VISIBLE_WANTED_ITEM, +- MemoryModuleType.ITEM_PICKUP_COOLDOWN_TICKS, +- MemoryModuleType.HURT_BY, +- MemoryModuleType.HURT_BY_ENTITY, +- MemoryModuleType.WALK_TARGET, +- MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE, +- MemoryModuleType.ATTACK_TARGET, +- MemoryModuleType.ATTACK_COOLING_DOWN, +- MemoryModuleType.INTERACTION_TARGET, +- MemoryModuleType.PATH, +- MemoryModuleType.ANGRY_AT, +- MemoryModuleType.UNIVERSAL_ANGER, +- MemoryModuleType.AVOID_TARGET, +- MemoryModuleType.ADMIRING_ITEM, +- MemoryModuleType.TIME_TRYING_TO_REACH_ADMIRE_ITEM, +- MemoryModuleType.ADMIRING_DISABLED, +- MemoryModuleType.DISABLE_WALK_TO_ADMIRE_ITEM, +- MemoryModuleType.CELEBRATE_LOCATION, +- MemoryModuleType.DANCING, +- MemoryModuleType.HUNTED_RECENTLY, +- MemoryModuleType.NEAREST_VISIBLE_BABY_HOGLIN, +- MemoryModuleType.NEAREST_VISIBLE_NEMESIS, +- MemoryModuleType.NEAREST_VISIBLE_ZOMBIFIED, +- MemoryModuleType.RIDE_TARGET, +- MemoryModuleType.VISIBLE_ADULT_PIGLIN_COUNT, +- MemoryModuleType.VISIBLE_ADULT_HOGLIN_COUNT, +- MemoryModuleType.NEAREST_VISIBLE_HUNTABLE_HOGLIN, +- MemoryModuleType.NEAREST_TARGETABLE_PLAYER_NOT_WEARING_GOLD, +- MemoryModuleType.NEAREST_PLAYER_HOLDING_WANTED_ITEM, +- MemoryModuleType.ATE_RECENTLY, +- MemoryModuleType.NEAREST_REPELLENT +- ); ++ private static final double PROBABILITY_OF_SPAWNING_WITH_CROSSBOW_INSTEAD_OF_SWORD = 0.5D; ++ public final SimpleContainer inventory = new SimpleContainer(8); ++ public boolean cannotHunt; ++ protected static final ImmutableList<SensorType<? extends Sensor<? super Piglin>>> SENSOR_TYPES = ImmutableList.of(SensorType.NEAREST_LIVING_ENTITIES, SensorType.NEAREST_PLAYERS, SensorType.NEAREST_ITEMS, SensorType.HURT_BY, SensorType.PIGLIN_SPECIFIC_SENSOR); ++ protected static final ImmutableList<MemoryModuleType<?>> MEMORY_TYPES = ImmutableList.of(MemoryModuleType.LOOK_TARGET, MemoryModuleType.DOORS_TO_CLOSE, MemoryModuleType.NEAREST_LIVING_ENTITIES, MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES, MemoryModuleType.NEAREST_VISIBLE_PLAYER, MemoryModuleType.NEAREST_VISIBLE_ATTACKABLE_PLAYER, MemoryModuleType.NEAREST_VISIBLE_ADULT_PIGLINS, MemoryModuleType.NEARBY_ADULT_PIGLINS, MemoryModuleType.NEAREST_VISIBLE_WANTED_ITEM, MemoryModuleType.ITEM_PICKUP_COOLDOWN_TICKS, MemoryModuleType.HURT_BY, MemoryModuleType.HURT_BY_ENTITY, new MemoryModuleType[]{MemoryModuleType.WALK_TARGET, MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE, MemoryModuleType.ATTACK_TARGET, MemoryModuleType.ATTACK_COOLING_DOWN, MemoryModuleType.INTERACTION_TARGET, MemoryModuleType.PATH, MemoryModuleType.ANGRY_AT, MemoryModuleType.UNIVERSAL_ANGER, MemoryModuleType.AVOID_TARGET, MemoryModuleType.ADMIRING_ITEM, MemoryModuleType.TIME_TRYING_TO_REACH_ADMIRE_ITEM, MemoryModuleType.ADMIRING_DISABLED, MemoryModuleType.DISABLE_WALK_TO_ADMIRE_ITEM, MemoryModuleType.CELEBRATE_LOCATION, MemoryModuleType.DANCING, MemoryModuleType.HUNTED_RECENTLY, MemoryModuleType.NEAREST_VISIBLE_BABY_HOGLIN, MemoryModuleType.NEAREST_VISIBLE_NEMESIS, MemoryModuleType.NEAREST_VISIBLE_ZOMBIFIED, MemoryModuleType.RIDE_TARGET, MemoryModuleType.VISIBLE_ADULT_PIGLIN_COUNT, MemoryModuleType.VISIBLE_ADULT_HOGLIN_COUNT, MemoryModuleType.NEAREST_VISIBLE_HUNTABLE_HOGLIN, MemoryModuleType.NEAREST_TARGETABLE_PLAYER_NOT_WEARING_GOLD, MemoryModuleType.NEAREST_PLAYER_HOLDING_WANTED_ITEM, MemoryModuleType.ATE_RECENTLY, MemoryModuleType.NEAREST_REPELLENT}); ++ // CraftBukkit start - Custom bartering and interest list ++ public Set<Item> allowedBarterItems = new HashSet<>(); ++ public Set<Item> interestItems = new HashSet<>(); ++ // CraftBukkit end + + public Piglin(EntityType<? extends AbstractPiglin> entityType, Level level) { + super(entityType, level); +@@ -136,6 +109,14 @@ + } + + this.writeInventoryToTag(compound); ++ // CraftBukkit start ++ ListTag barterList = new ListTag(); ++ allowedBarterItems.stream().map(BuiltInRegistries.ITEM::getKey).map(ResourceLocation::toString).map(StringTag::valueOf).forEach(barterList::add); ++ compound.put("Bukkit.BarterList", barterList); ++ ListTag interestList = new ListTag(); ++ interestItems.stream().map(BuiltInRegistries.ITEM::getKey).map(ResourceLocation::toString).map(StringTag::valueOf).forEach(interestList::add); ++ compound.put("Bukkit.InterestList", interestList); ++ // CraftBukkit end + } + + @Override +@@ -144,6 +125,10 @@ + this.setBaby(compound.getBoolean("IsBaby")); + this.setCannotHunt(compound.getBoolean("CannotHunt")); + this.readInventoryFromTag(compound); ++ // CraftBukkit start ++ this.allowedBarterItems = compound.getList("Bukkit.BarterList", 8).stream().map(Tag::getAsString).map(ResourceLocation::tryParse).map(BuiltInRegistries.ITEM::get).collect(Collectors.toCollection(HashSet::new)); ++ this.interestItems = compound.getList("Bukkit.InterestList", 8).stream().map(Tag::getAsString).map(ResourceLocation::tryParse).map(BuiltInRegistries.ITEM::get).collect(Collectors.toCollection(HashSet::new)); ++ // CraftBukkit end + } + + @VisibleForDebug +@@ -155,10 +140,17 @@ + @Override + protected void dropCustomDeathLoot(DamageSource source, int looting, boolean recentlyHit) { + super.dropCustomDeathLoot(source, looting, recentlyHit); +- if (source.getEntity() instanceof Creeper creeper && creeper.canDropMobsSkull()) { +- ItemStack itemStack = new ItemStack(Items.PIGLIN_HEAD); +- creeper.increaseDroppedSkulls(); +- this.spawnAtLocation(itemStack); ++ Entity entity = source.getEntity(); ++ ++ if (entity instanceof Creeper) { ++ Creeper entitycreeper = (Creeper) entity; ++ ++ if (entitycreeper.canDropMobsSkull()) { ++ ItemStack itemstack = new ItemStack(Items.PIGLIN_HEAD); ++ ++ entitycreeper.increaseDroppedSkulls(); ++ this.spawnAtLocation(itemstack); ++ } + } + + this.inventory.removeAllItems().forEach(this::spawnAtLocation); +@@ -175,35 +167,35 @@ + @Override + protected void defineSynchedData() { + super.defineSynchedData(); +- this.entityData.define(DATA_BABY_ID, false); +- this.entityData.define(DATA_IS_CHARGING_CROSSBOW, false); +- this.entityData.define(DATA_IS_DANCING, false); ++ this.entityData.define(Piglin.DATA_BABY_ID, false); ++ this.entityData.define(Piglin.DATA_IS_CHARGING_CROSSBOW, false); ++ this.entityData.define(Piglin.DATA_IS_DANCING, false); + } + + @Override + public void onSyncedDataUpdated(EntityDataAccessor<?> key) { + super.onSyncedDataUpdated(key); +- if (DATA_BABY_ID.equals(key)) { ++ if (Piglin.DATA_BABY_ID.equals(key)) { + this.refreshDimensions(); + } ++ + } + + public static AttributeSupplier.Builder createAttributes() { +- return Monster.createMonsterAttributes().add(Attributes.MAX_HEALTH, 16.0).add(Attributes.MOVEMENT_SPEED, 0.35F).add(Attributes.ATTACK_DAMAGE, 5.0); ++ return Monster.createMonsterAttributes().add(Attributes.MAX_HEALTH, 16.0D).add(Attributes.MOVEMENT_SPEED, 0.3499999940395355D).add(Attributes.ATTACK_DAMAGE, 5.0D); + } + +- public static boolean checkPiglinSpawnRules(EntityType<Piglin> piglin, LevelAccessor level, MobSpawnType spawnType, BlockPos pos, RandomSource random) { ++ public static boolean checkPiglinSpawnRules(EntityType<Piglin> piglin, LevelAccessor level, EnumMobSpawn spawnType, BlockPos pos, RandomSource random) { + return !level.getBlockState(pos.below()).is(Blocks.NETHER_WART_BLOCK); + } + + @Nullable + @Override +- public SpawnGroupData finalizeSpawn( +- ServerLevelAccessor level, DifficultyInstance difficulty, MobSpawnType reason, @Nullable SpawnGroupData spawnData, @Nullable CompoundTag dataTag +- ) { +- RandomSource random = level.getRandom(); +- if (reason != MobSpawnType.STRUCTURE) { +- if (random.nextFloat() < 0.2F) { ++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) { ++ RandomSource randomsource = level.getRandom(); ++ ++ if (reason != EnumMobSpawn.STRUCTURE) { ++ if (randomsource.nextFloat() < 0.2F) { + this.setBaby(true); + } else if (this.isAdult()) { + this.setItemSlot(EquipmentSlot.MAINHAND, this.createSpawnWeapon()); +@@ -211,8 +203,8 @@ + } + + PiglinAi.initMemories(this, level.getRandom()); +- this.populateDefaultEquipmentSlots(random, difficulty); +- this.populateDefaultEquipmentEnchantments(random, difficulty); ++ this.populateDefaultEquipmentSlots(randomsource, difficulty); ++ this.populateDefaultEquipmentEnchantments(randomsource, difficulty); + return super.finalizeSpawn(level, difficulty, reason, spawnData, dataTag); + } + +@@ -234,17 +226,19 @@ + this.maybeWearArmor(EquipmentSlot.LEGS, new ItemStack(Items.GOLDEN_LEGGINGS), random); + this.maybeWearArmor(EquipmentSlot.FEET, new ItemStack(Items.GOLDEN_BOOTS), random); + } ++ + } + + private void maybeWearArmor(EquipmentSlot slot, ItemStack stack, RandomSource random) { + if (random.nextFloat() < 0.1F) { + this.setItemSlot(slot, stack); + } ++ + } + + @Override + protected Brain.Provider<Piglin> brainProvider() { +- return Brain.provider(MEMORY_TYPES, SENSOR_TYPES); ++ return Brain.provider(Piglin.MEMORY_TYPES, Piglin.SENSOR_TYPES); + } + + @Override +@@ -254,43 +248,48 @@ + + @Override + public Brain<Piglin> getBrain() { +- return (Brain<Piglin>)super.getBrain(); ++ return (Brain<Piglin>) super.getBrain(); // CraftBukkit - Decompile error + } + + @Override +- public InteractionResult mobInteract(Player player, InteractionHand hand) { +- InteractionResult interactionResult = super.mobInteract(player, hand); +- if (interactionResult.consumesAction()) { +- return interactionResult; ++ public InteractionResult mobInteract(Player player, EnumHand hand) { ++ InteractionResult enuminteractionresult = super.mobInteract(player, hand); ++ ++ if (enuminteractionresult.consumesAction()) { ++ return enuminteractionresult; + } else if (!this.level().isClientSide) { + return PiglinAi.mobInteract(this, player, hand); + } else { +- boolean flag = PiglinAi.canAdmire(this, player.getItemInHand(hand)) && this.getArmPose() != PiglinArmPose.ADMIRING_ITEM; ++ boolean flag = PiglinAi.canAdmire(this, player.getItemInHand(hand)) && this.getArmPose() != EntityPiglinArmPose.ADMIRING_ITEM; ++ + return flag ? InteractionResult.SUCCESS : InteractionResult.PASS; + } + } + + @Override +- protected float getStandingEyeHeight(Pose pose, EntityDimensions size) { ++ protected float getStandingEyeHeight(EntityPose pose, EntityDimensions size) { + float f = super.getStandingEyeHeight(pose, size); ++ + return this.isBaby() ? f - 0.82F : f; + } + + @Override + public void setBaby(boolean childZombie) { +- this.getEntityData().set(DATA_BABY_ID, childZombie); ++ this.getEntityData().set(Piglin.DATA_BABY_ID, childZombie); + if (!this.level().isClientSide) { +- AttributeInstance attribute = this.getAttribute(Attributes.MOVEMENT_SPEED); +- attribute.removeModifier(SPEED_MODIFIER_BABY.getId()); ++ AttributeInstance attributemodifiable = this.getAttribute(Attributes.MOVEMENT_SPEED); ++ ++ attributemodifiable.removeModifier(Piglin.SPEED_MODIFIER_BABY.getId()); + if (childZombie) { +- attribute.addTransientModifier(SPEED_MODIFIER_BABY); ++ attributemodifiable.addTransientModifier(Piglin.SPEED_MODIFIER_BABY); + } + } ++ + } + + @Override + public boolean isBaby() { +- return this.getEntityData().get(DATA_BABY_ID); ++ return (Boolean) this.getEntityData().get(Piglin.DATA_BABY_ID); + } + + private void setCannotHunt(boolean cannotHunt) { +@@ -305,7 +304,7 @@ + @Override + protected void customServerAiStep() { + this.level().getProfiler().push("piglinBrain"); +- this.getBrain().tick((ServerLevel)this.level(), this); ++ this.getBrain().tick((ServerLevel) this.level(), this); + this.level().getProfiler().pop(); + PiglinAi.updateActivity(this); + super.customServerAiStep(); +@@ -324,16 +323,16 @@ + } + + private ItemStack createSpawnWeapon() { +- return (double)this.random.nextFloat() < 0.5 ? new ItemStack(Items.CROSSBOW) : new ItemStack(Items.GOLDEN_SWORD); ++ return (double) this.random.nextFloat() < 0.5D ? new ItemStack(Items.CROSSBOW) : new ItemStack(Items.GOLDEN_SWORD); + } + + private boolean isChargingCrossbow() { +- return this.entityData.get(DATA_IS_CHARGING_CROSSBOW); ++ return (Boolean) this.entityData.get(Piglin.DATA_IS_CHARGING_CROSSBOW); + } + + @Override + public void setChargingCrossbow(boolean isCharging) { +- this.entityData.set(DATA_IS_CHARGING_CROSSBOW, isCharging); ++ this.entityData.set(Piglin.DATA_IS_CHARGING_CROSSBOW, isCharging); + } + + @Override +@@ -342,36 +341,27 @@ + } + + @Override +- public PiglinArmPose getArmPose() { +- if (this.isDancing()) { +- return PiglinArmPose.DANCING; +- } else if (PiglinAi.isLovedItem(this.getOffhandItem())) { +- return PiglinArmPose.ADMIRING_ITEM; +- } else if (this.isAggressive() && this.isHoldingMeleeWeapon()) { +- return PiglinArmPose.ATTACKING_WITH_MELEE_WEAPON; +- } else if (this.isChargingCrossbow()) { +- return PiglinArmPose.CROSSBOW_CHARGE; +- } else { +- return this.isAggressive() && this.isHolding(Items.CROSSBOW) ? PiglinArmPose.CROSSBOW_HOLD : PiglinArmPose.DEFAULT; +- } ++ public EntityPiglinArmPose getArmPose() { ++ return this.isDancing() ? EntityPiglinArmPose.DANCING : (PiglinAi.isLovedItem(this.getOffhandItem()) ? EntityPiglinArmPose.ADMIRING_ITEM : (this.isAggressive() && this.isHoldingMeleeWeapon() ? EntityPiglinArmPose.ATTACKING_WITH_MELEE_WEAPON : (this.isChargingCrossbow() ? EntityPiglinArmPose.CROSSBOW_CHARGE : (this.isAggressive() && this.isHolding(Items.CROSSBOW) ? EntityPiglinArmPose.CROSSBOW_HOLD : EntityPiglinArmPose.DEFAULT)))); + } + + public boolean isDancing() { +- return this.entityData.get(DATA_IS_DANCING); ++ return (Boolean) this.entityData.get(Piglin.DATA_IS_DANCING); + } + + public void setDancing(boolean dancing) { +- this.entityData.set(DATA_IS_DANCING, dancing); ++ this.entityData.set(Piglin.DATA_IS_DANCING, dancing); + } + + @Override + public boolean hurt(DamageSource source, float amount) { + boolean flag = super.hurt(source, amount); ++ + if (this.level().isClientSide) { + return false; + } else { + if (flag && source.getEntity() instanceof LivingEntity) { +- PiglinAi.wasHurtBy(this, (LivingEntity)source.getEntity()); ++ PiglinAi.wasHurtBy(this, (LivingEntity) source.getEntity()); + } + + return flag; +@@ -398,12 +388,13 @@ + } + + protected void holdInOffHand(ItemStack stack) { +- if (stack.is(PiglinAi.BARTERING_ITEM)) { ++ if (stack.is(PiglinAi.BARTERING_ITEM) || allowedBarterItems.contains(stack.getItem())) { // CraftBukkit - Changes to accept custom payment items + this.setItemSlot(EquipmentSlot.OFFHAND, stack); + this.setGuaranteedDrop(EquipmentSlot.OFFHAND); + } else { + this.setItemSlotAndDropWhenKilled(EquipmentSlot.OFFHAND, stack); + } ++ + } + + @Override +@@ -412,9 +403,10 @@ + } + + protected boolean canReplaceCurrentItem(ItemStack candidate) { +- EquipmentSlot equipmentSlotForItem = Mob.getEquipmentSlotForItem(candidate); +- ItemStack itemBySlot = this.getItemBySlot(equipmentSlotForItem); +- return this.canReplaceCurrentItem(candidate, itemBySlot); ++ EquipmentSlot enumitemslot = Mob.getEquipmentSlotForItem(candidate); ++ ItemStack itemstack1 = this.getItemBySlot(enumitemslot); ++ ++ return this.canReplaceCurrentItem(candidate, itemstack1); + } + + @Override +@@ -422,12 +414,10 @@ + if (EnchantmentHelper.hasBindingCurse(existing)) { + return false; + } else { +- boolean flag = PiglinAi.isLovedItem(candidate) || candidate.is(Items.CROSSBOW); +- boolean flag1 = PiglinAi.isLovedItem(existing) || existing.is(Items.CROSSBOW); +- return flag && !flag1 +- || (flag || !flag1) +- && (!this.isAdult() || candidate.is(Items.CROSSBOW) || !existing.is(Items.CROSSBOW)) +- && super.canReplaceCurrentItem(candidate, existing); ++ boolean flag = PiglinAi.isLovedItem(candidate, this) || candidate.is(Items.CROSSBOW); // CraftBukkit ++ boolean flag1 = PiglinAi.isLovedItem(existing, this) || existing.is(Items.CROSSBOW); // CraftBukkit ++ ++ return flag && !flag1 ? true : (!flag && flag1 ? false : (this.isAdult() && !candidate.is(Items.CROSSBOW) && existing.is(Items.CROSSBOW) ? false : super.canReplaceCurrentItem(candidate, existing))); + } + } + +@@ -447,13 +437,14 @@ + } + + private Entity getTopPassenger(Entity vehicle, int maxPosition) { +- List<Entity> passengers = vehicle.getPassengers(); +- return maxPosition != 1 && !passengers.isEmpty() ? this.getTopPassenger(passengers.get(0), maxPosition - 1) : vehicle; ++ List<Entity> list = vehicle.getPassengers(); ++ ++ return maxPosition != 1 && !list.isEmpty() ? this.getTopPassenger((Entity) list.get(0), maxPosition - 1) : vehicle; + } + + @Override + protected SoundEvent getAmbientSound() { +- return this.level().isClientSide ? null : PiglinAi.getSoundForCurrentActivity(this).orElse(null); ++ return this.level().isClientSide ? null : (SoundEvent) PiglinAi.getSoundForCurrentActivity(this).orElse(null); // CraftBukkit - Decompile error + } + + @Override +@@ -467,7 +458,7 @@ + } + + @Override +- protected void playStepSound(BlockPos pos, BlockState block) { ++ protected void playStepSound(BlockPos pos, IBlockData block) { + this.playSound(SoundEvents.PIGLIN_STEP, 0.15F, 1.0F); + } + diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/piglin/PiglinAi.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/piglin/PiglinAi.java.patch new file mode 100644 index 0000000000..da1bd1d9a0 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/piglin/PiglinAi.java.patch @@ -0,0 +1,967 @@ +--- a/net/minecraft/world/entity/monster/piglin/PiglinAi.java ++++ b/net/minecraft/world/entity/monster/piglin/PiglinAi.java +@@ -4,7 +4,9 @@ + import com.google.common.collect.ImmutableSet; + import com.mojang.datafixers.util.Pair; + import java.util.Collections; ++import java.util.Iterator; + import java.util.List; ++import java.util.Objects; + import java.util.Optional; + import net.minecraft.server.level.ServerLevel; + import net.minecraft.sounds.SoundEvent; +@@ -13,7 +15,7 @@ + import net.minecraft.util.RandomSource; + import net.minecraft.util.TimeUtil; + import net.minecraft.util.valueproviders.UniformInt; +-import net.minecraft.world.InteractionHand; ++import net.minecraft.world.EnumHand; + import net.minecraft.world.InteractionResult; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityType; +@@ -52,7 +54,6 @@ + import net.minecraft.world.entity.ai.behavior.StopBeingAngryIfTargetDead; + import net.minecraft.world.entity.ai.behavior.TriggerGate; + import net.minecraft.world.entity.ai.behavior.declarative.BehaviorBuilder; +-import net.minecraft.world.entity.ai.behavior.declarative.Trigger; + import net.minecraft.world.entity.ai.memory.MemoryModuleType; + import net.minecraft.world.entity.ai.sensing.Sensor; + import net.minecraft.world.entity.ai.util.LandRandomPos; +@@ -72,8 +73,15 @@ + import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets; + import net.minecraft.world.level.storage.loot.parameters.LootContextParams; + import net.minecraft.world.phys.Vec3; ++// CraftBukkit start ++import java.util.stream.Collectors; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.event.entity.PiglinBarterEvent; ++// CraftBukkit end + + public class PiglinAi { ++ + public static final int REPELLENT_DETECTION_RANGE_HORIZONTAL = 8; + public static final int REPELLENT_DETECTION_RANGE_VERTICAL = 4; + public static final Item BARTERING_ITEM = Items.GOLD_INGOT; +@@ -111,6 +119,8 @@ + private static final float SPEED_MULTIPLIER_WHEN_DANCING = 0.6F; + private static final float SPEED_MULTIPLIER_WHEN_IDLING = 0.6F; + ++ public PiglinAi() {} ++ + protected static Brain<?> makeBrain(Piglin piglin, Brain<Piglin> brain) { + initCoreActivity(brain); + initIdleActivity(brain); +@@ -126,159 +136,56 @@ + } + + protected static void initMemories(Piglin piglin, RandomSource random) { +- int i = TIME_BETWEEN_HUNTS.sample(random); +- piglin.getBrain().setMemoryWithExpiry(MemoryModuleType.HUNTED_RECENTLY, true, (long)i); ++ int i = PiglinAi.TIME_BETWEEN_HUNTS.sample(random); ++ ++ piglin.getBrain().setMemoryWithExpiry(MemoryModuleType.HUNTED_RECENTLY, true, (long) i); + } + + private static void initCoreActivity(Brain<Piglin> brain) { +- brain.addActivity( +- Activity.CORE, +- 0, +- ImmutableList.of( +- new LookAtTargetSink(45, 90), +- new MoveToTargetSink(), +- InteractWithDoor.create(), +- babyAvoidNemesis(), +- avoidZombified(), +- StopHoldingItemIfNoLongerAdmiring.create(), +- StartAdmiringItemIfSeen.create(119), +- StartCelebratingIfTargetDead.create(300, PiglinAi::wantsToDance), +- StopBeingAngryIfTargetDead.create() +- ) +- ); ++ brain.addActivity(Activity.CORE, 0, ImmutableList.of(new LookAtTargetSink(45, 90), new MoveToTargetSink(), InteractWithDoor.create(), babyAvoidNemesis(), avoidZombified(), StopHoldingItemIfNoLongerAdmiring.create(), StartAdmiringItemIfSeen.create(119), StartCelebratingIfTargetDead.create(300, PiglinAi::wantsToDance), StopBeingAngryIfTargetDead.create())); + } + + private static void initIdleActivity(Brain<Piglin> brain) { +- brain.addActivity( +- Activity.IDLE, +- 10, +- ImmutableList.of( +- SetEntityLookTarget.create(PiglinAi::isPlayerHoldingLovedItem, 14.0F), +- StartAttacking.<Piglin>create(AbstractPiglin::isAdult, PiglinAi::findNearestValidAttackTarget), +- BehaviorBuilder.triggerIf(Piglin::canHunt, StartHuntingHoglin.create()), +- avoidRepellent(), +- babySometimesRideBabyHoglin(), +- createIdleLookBehaviors(), +- createIdleMovementBehaviors(), +- SetLookAndInteract.create(EntityType.PLAYER, 4) +- ) +- ); ++ brain.addActivity(Activity.IDLE, 10, ImmutableList.of(SetEntityLookTarget.create(PiglinAi::isPlayerHoldingLovedItem, 14.0F), StartAttacking.create(AbstractPiglin::isAdult, PiglinAi::findNearestValidAttackTarget), BehaviorBuilder.triggerIf(Piglin::canHunt, StartHuntingHoglin.create()), avoidRepellent(), babySometimesRideBabyHoglin(), createIdleLookBehaviors(), createIdleMovementBehaviors(), SetLookAndInteract.create(EntityType.PLAYER, 4))); + } + + private static void initFightActivity(Piglin piglin, Brain<Piglin> brain) { +- brain.addActivityAndRemoveMemoryWhenStopped( +- Activity.FIGHT, +- 10, +- ImmutableList.<BehaviorControl<? super Piglin>>of( +- StopAttackingIfTargetInvalid.create(entity -> !isNearestValidAttackTarget(piglin, entity)), +- BehaviorBuilder.triggerIf(PiglinAi::hasCrossbow, BackUpIfTooClose.create(5, 0.75F)), +- SetWalkTargetFromAttackTargetIfTargetOutOfReach.create(1.0F), +- MeleeAttack.create(20), +- new CrossbowAttack(), +- RememberIfHoglinWasKilled.create(), +- EraseMemoryIf.create(PiglinAi::isNearZombified, MemoryModuleType.ATTACK_TARGET) +- ), +- MemoryModuleType.ATTACK_TARGET +- ); ++ brain.addActivityAndRemoveMemoryWhenStopped(Activity.FIGHT, 10, ImmutableList.of(StopAttackingIfTargetInvalid.create((entityliving) -> { ++ return !isNearestValidAttackTarget(piglin, entityliving); ++ }), BehaviorBuilder.triggerIf(PiglinAi::hasCrossbow, BackUpIfTooClose.create(5, 0.75F)), SetWalkTargetFromAttackTargetIfTargetOutOfReach.create(1.0F), MeleeAttack.create(20), new CrossbowAttack<>(), RememberIfHoglinWasKilled.create(), EraseMemoryIf.create(PiglinAi::isNearZombified, MemoryModuleType.ATTACK_TARGET)), MemoryModuleType.ATTACK_TARGET); + } + + private static void initCelebrateActivity(Brain<Piglin> brain) { +- brain.addActivityAndRemoveMemoryWhenStopped( +- Activity.CELEBRATE, +- 10, +- ImmutableList.of( +- avoidRepellent(), +- SetEntityLookTarget.create(PiglinAi::isPlayerHoldingLovedItem, 14.0F), +- StartAttacking.<Piglin>create(AbstractPiglin::isAdult, PiglinAi::findNearestValidAttackTarget), +- BehaviorBuilder.triggerIf(piglin -> !piglin.isDancing(), GoToTargetLocation.create(MemoryModuleType.CELEBRATE_LOCATION, 2, 1.0F)), +- BehaviorBuilder.triggerIf(Piglin::isDancing, GoToTargetLocation.create(MemoryModuleType.CELEBRATE_LOCATION, 4, 0.6F)), +- new RunOne<>( +- ImmutableList.of( +- Pair.of(SetEntityLookTarget.create(EntityType.PIGLIN, 8.0F), 1), +- Pair.of(RandomStroll.stroll(0.6F, 2, 1), 1), +- Pair.of(new DoNothing(10, 20), 1) +- ) +- ) +- ), +- MemoryModuleType.CELEBRATE_LOCATION +- ); ++ brain.addActivityAndRemoveMemoryWhenStopped(Activity.CELEBRATE, 10, ImmutableList.of(avoidRepellent(), SetEntityLookTarget.create(PiglinAi::isPlayerHoldingLovedItem, 14.0F), StartAttacking.create(AbstractPiglin::isAdult, PiglinAi::findNearestValidAttackTarget), BehaviorBuilder.triggerIf((entitypiglin) -> { ++ return !entitypiglin.isDancing(); ++ }, GoToTargetLocation.create(MemoryModuleType.CELEBRATE_LOCATION, 2, 1.0F)), BehaviorBuilder.triggerIf(Piglin::isDancing, GoToTargetLocation.create(MemoryModuleType.CELEBRATE_LOCATION, 4, 0.6F)), new RunOne<>(ImmutableList.of(Pair.of(SetEntityLookTarget.create(EntityType.PIGLIN, 8.0F), 1), Pair.of(RandomStroll.stroll(0.6F, 2, 1), 1), Pair.of(new DoNothing(10, 20), 1)))), MemoryModuleType.CELEBRATE_LOCATION); + } + + private static void initAdmireItemActivity(Brain<Piglin> brain) { +- brain.addActivityAndRemoveMemoryWhenStopped( +- Activity.ADMIRE_ITEM, +- 10, +- ImmutableList.of( +- GoToWantedItem.create(PiglinAi::isNotHoldingLovedItemInOffHand, 1.0F, true, 9), +- StopAdmiringIfItemTooFarAway.create(9), +- StopAdmiringIfTiredOfTryingToReachItem.create(200, 200) +- ), +- MemoryModuleType.ADMIRING_ITEM +- ); ++ brain.addActivityAndRemoveMemoryWhenStopped(Activity.ADMIRE_ITEM, 10, ImmutableList.of(GoToWantedItem.create(PiglinAi::isNotHoldingLovedItemInOffHand, 1.0F, true, 9), StopAdmiringIfItemTooFarAway.create(9), StopAdmiringIfTiredOfTryingToReachItem.create(200, 200)), MemoryModuleType.ADMIRING_ITEM); + } + + private static void initRetreatActivity(Brain<Piglin> brain) { +- brain.addActivityAndRemoveMemoryWhenStopped( +- Activity.AVOID, +- 10, +- ImmutableList.of( +- SetWalkTargetAwayFrom.entity(MemoryModuleType.AVOID_TARGET, 1.0F, 12, true), +- createIdleLookBehaviors(), +- createIdleMovementBehaviors(), +- EraseMemoryIf.create(PiglinAi::wantsToStopFleeing, MemoryModuleType.AVOID_TARGET) +- ), +- MemoryModuleType.AVOID_TARGET +- ); ++ brain.addActivityAndRemoveMemoryWhenStopped(Activity.AVOID, 10, ImmutableList.of(SetWalkTargetAwayFrom.entity(MemoryModuleType.AVOID_TARGET, 1.0F, 12, true), createIdleLookBehaviors(), createIdleMovementBehaviors(), EraseMemoryIf.create(PiglinAi::wantsToStopFleeing, MemoryModuleType.AVOID_TARGET)), MemoryModuleType.AVOID_TARGET); + } + + private static void initRideHoglinActivity(Brain<Piglin> brain) { +- brain.addActivityAndRemoveMemoryWhenStopped( +- Activity.RIDE, +- 10, +- ImmutableList.of( +- Mount.create(0.8F), +- SetEntityLookTarget.create(PiglinAi::isPlayerHoldingLovedItem, 8.0F), +- BehaviorBuilder.sequence( +- BehaviorBuilder.triggerIf(Entity::isPassenger), +- TriggerGate.triggerOneShuffled( +- ImmutableList.<Pair<? extends Trigger<? super LivingEntity>, Integer>>builder() +- .addAll(createLookBehaviors()) +- .add(Pair.of(BehaviorBuilder.triggerIf(piglin -> true), 1)) +- .build() +- ) +- ), +- DismountOrSkipMounting.create(8, PiglinAi::wantsToStopRiding) +- ), +- MemoryModuleType.RIDE_TARGET +- ); ++ // CraftBukkit - decompile error ++ brain.addActivityAndRemoveMemoryWhenStopped(Activity.RIDE, 10, ImmutableList.of(Mount.create(0.8F), SetEntityLookTarget.create(PiglinAi::isPlayerHoldingLovedItem, 8.0F), BehaviorBuilder.sequence(BehaviorBuilder.triggerIf(Entity::isPassenger), TriggerGate.triggerOneShuffled(ImmutableList.<Pair<? extends net.minecraft.world.entity.ai.behavior.declarative.Trigger<? super LivingEntity>, Integer>>builder().addAll(createLookBehaviors()).add(Pair.of(BehaviorBuilder.triggerIf((entitypiglin) -> { ++ return true; ++ }), 1)).build())), DismountOrSkipMounting.create(8, PiglinAi::wantsToStopRiding)), MemoryModuleType.RIDE_TARGET); + } + + private static ImmutableList<Pair<OneShot<LivingEntity>, Integer>> createLookBehaviors() { +- return ImmutableList.of( +- Pair.of(SetEntityLookTarget.create(EntityType.PLAYER, 8.0F), 1), +- Pair.of(SetEntityLookTarget.create(EntityType.PIGLIN, 8.0F), 1), +- Pair.of(SetEntityLookTarget.create(8.0F), 1) +- ); ++ return ImmutableList.of(Pair.of(SetEntityLookTarget.create(EntityType.PLAYER, 8.0F), 1), Pair.of(SetEntityLookTarget.create(EntityType.PIGLIN, 8.0F), 1), Pair.of(SetEntityLookTarget.create(8.0F), 1)); + } + + private static RunOne<LivingEntity> createIdleLookBehaviors() { +- return new RunOne<>( +- ImmutableList.<Pair<? extends BehaviorControl<? super LivingEntity>, Integer>>builder() +- .addAll(createLookBehaviors()) +- .add(Pair.of(new DoNothing(30, 60), 1)) +- .build() +- ); ++ return new RunOne<>(ImmutableList.<Pair<? extends BehaviorControl<? super LivingEntity>, Integer>>builder().addAll(createLookBehaviors()).add(Pair.of(new DoNothing(30, 60), 1)).build()); // CraftBukkit - decompile error + } + + private static RunOne<Piglin> createIdleMovementBehaviors() { +- return new RunOne<>( +- ImmutableList.of( +- Pair.of(RandomStroll.stroll(0.6F), 2), +- Pair.of(InteractWith.of(EntityType.PIGLIN, 8, MemoryModuleType.INTERACTION_TARGET, 0.6F, 2), 2), +- Pair.of(BehaviorBuilder.triggerIf(PiglinAi::doesntSeeAnyPlayerHoldingLovedItem, SetWalkTargetFromLookTarget.create(0.6F, 3)), 2), +- Pair.of(new DoNothing(30, 60), 1) +- ) +- ); ++ return new RunOne<>(ImmutableList.of(Pair.of(RandomStroll.stroll(0.6F), 2), Pair.of(InteractWith.of(EntityType.PIGLIN, 8, MemoryModuleType.INTERACTION_TARGET, 0.6F, 2), 2), Pair.of(BehaviorBuilder.triggerIf(PiglinAi::doesntSeeAnyPlayerHoldingLovedItem, SetWalkTargetFromLookTarget.create(0.6F, 3)), 2), Pair.of(new DoNothing(30, 60), 1))); + } + + private static BehaviorControl<PathfinderMob> avoidRepellent() { +@@ -286,140 +193,164 @@ + } + + private static BehaviorControl<Piglin> babyAvoidNemesis() { +- return CopyMemoryWithExpiry.create(Piglin::isBaby, MemoryModuleType.NEAREST_VISIBLE_NEMESIS, MemoryModuleType.AVOID_TARGET, BABY_AVOID_NEMESIS_DURATION); ++ return CopyMemoryWithExpiry.create(Piglin::isBaby, MemoryModuleType.NEAREST_VISIBLE_NEMESIS, MemoryModuleType.AVOID_TARGET, PiglinAi.BABY_AVOID_NEMESIS_DURATION); + } + + private static BehaviorControl<Piglin> avoidZombified() { +- return CopyMemoryWithExpiry.create( +- PiglinAi::isNearZombified, MemoryModuleType.NEAREST_VISIBLE_ZOMBIFIED, MemoryModuleType.AVOID_TARGET, AVOID_ZOMBIFIED_DURATION +- ); ++ return CopyMemoryWithExpiry.create(PiglinAi::isNearZombified, MemoryModuleType.NEAREST_VISIBLE_ZOMBIFIED, MemoryModuleType.AVOID_TARGET, PiglinAi.AVOID_ZOMBIFIED_DURATION); + } + + protected static void updateActivity(Piglin piglin) { +- Brain<Piglin> brain = piglin.getBrain(); +- Activity activity = brain.getActiveNonCoreActivity().orElse(null); +- brain.setActiveActivityToFirstValid( +- ImmutableList.of(Activity.ADMIRE_ITEM, Activity.FIGHT, Activity.AVOID, Activity.CELEBRATE, Activity.RIDE, Activity.IDLE) +- ); +- Activity activity1 = brain.getActiveNonCoreActivity().orElse(null); ++ Brain<Piglin> behaviorcontroller = piglin.getBrain(); ++ Activity activity = (Activity) behaviorcontroller.getActiveNonCoreActivity().orElse(null); // CraftBukkit - decompile error ++ ++ behaviorcontroller.setActiveActivityToFirstValid(ImmutableList.of(Activity.ADMIRE_ITEM, Activity.FIGHT, Activity.AVOID, Activity.CELEBRATE, Activity.RIDE, Activity.IDLE)); ++ Activity activity1 = (Activity) behaviorcontroller.getActiveNonCoreActivity().orElse(null); // CraftBukkit - decompile error ++ + if (activity != activity1) { +- getSoundForCurrentActivity(piglin).ifPresent(piglin::playSoundEvent); ++ Optional<SoundEvent> optional = getSoundForCurrentActivity(piglin); // CraftBukkit - decompile error ++ ++ Objects.requireNonNull(piglin); ++ optional.ifPresent(piglin::playSoundEvent); + } + +- piglin.setAggressive(brain.hasMemoryValue(MemoryModuleType.ATTACK_TARGET)); +- if (!brain.hasMemoryValue(MemoryModuleType.RIDE_TARGET) && isBabyRidingBaby(piglin)) { ++ piglin.setAggressive(behaviorcontroller.hasMemoryValue(MemoryModuleType.ATTACK_TARGET)); ++ if (!behaviorcontroller.hasMemoryValue(MemoryModuleType.RIDE_TARGET) && isBabyRidingBaby(piglin)) { + piglin.stopRiding(); + } + +- if (!brain.hasMemoryValue(MemoryModuleType.CELEBRATE_LOCATION)) { +- brain.eraseMemory(MemoryModuleType.DANCING); ++ if (!behaviorcontroller.hasMemoryValue(MemoryModuleType.CELEBRATE_LOCATION)) { ++ behaviorcontroller.eraseMemory(MemoryModuleType.DANCING); + } + +- piglin.setDancing(brain.hasMemoryValue(MemoryModuleType.DANCING)); ++ piglin.setDancing(behaviorcontroller.hasMemoryValue(MemoryModuleType.DANCING)); + } + + private static boolean isBabyRidingBaby(Piglin passenger) { + if (!passenger.isBaby()) { + return false; + } else { +- Entity vehicle = passenger.getVehicle(); +- return vehicle instanceof Piglin && ((Piglin)vehicle).isBaby() || vehicle instanceof Hoglin && ((Hoglin)vehicle).isBaby(); ++ Entity entity = passenger.getVehicle(); ++ ++ return entity instanceof Piglin && ((Piglin) entity).isBaby() || entity instanceof Hoglin && ((Hoglin) entity).isBaby(); + } + } + + protected static void pickUpItem(Piglin piglin, ItemEntity itemEntity) { + stopWalking(piglin); +- ItemStack item; +- if (itemEntity.getItem().is(Items.GOLD_NUGGET)) { ++ ItemStack itemstack; ++ ++ // CraftBukkit start ++ if (itemEntity.getItem().is(Items.GOLD_NUGGET) && !org.bukkit.craftbukkit.event.CraftEventFactory.callEntityPickupItemEvent(piglin, itemEntity, 0, false).isCancelled()) { + piglin.take(itemEntity, itemEntity.getItem().getCount()); +- item = itemEntity.getItem(); ++ itemstack = itemEntity.getItem(); + itemEntity.discard(); +- } else { ++ } else if (!org.bukkit.craftbukkit.event.CraftEventFactory.callEntityPickupItemEvent(piglin, itemEntity, itemEntity.getItem().getCount() - 1, false).isCancelled()) { + piglin.take(itemEntity, 1); +- item = removeOneItemFromItemEntity(itemEntity); ++ itemstack = removeOneItemFromItemEntity(itemEntity); ++ } else { ++ return; + } ++ // CraftBukkit end + +- if (isLovedItem(item)) { ++ if (isLovedItem(itemstack, piglin)) { // CraftBukkit - Changes to allow for custom payment in bartering + piglin.getBrain().eraseMemory(MemoryModuleType.TIME_TRYING_TO_REACH_ADMIRE_ITEM); +- holdInOffhand(piglin, item); ++ holdInOffhand(piglin, itemstack); + admireGoldItem(piglin); +- } else if (isFood(item) && !hasEatenRecently(piglin)) { ++ } else if (isFood(itemstack) && !hasEatenRecently(piglin)) { + eat(piglin); + } else { +- boolean flag = !piglin.equipItemIfPossible(item).equals(ItemStack.EMPTY); ++ boolean flag = !piglin.equipItemIfPossible(itemstack, itemEntity).equals(ItemStack.EMPTY); // CraftBukkit ++ + if (!flag) { +- putInInventory(piglin, item); ++ putInInventory(piglin, itemstack); + } + } + } + + private static void holdInOffhand(Piglin piglin, ItemStack stack) { + if (isHoldingItemInOffHand(piglin)) { +- piglin.spawnAtLocation(piglin.getItemInHand(InteractionHand.OFF_HAND)); ++ piglin.spawnAtLocation(piglin.getItemInHand(EnumHand.OFF_HAND)); + } + + piglin.holdInOffHand(stack); + } + + private static ItemStack removeOneItemFromItemEntity(ItemEntity itemEntity) { +- ItemStack item = itemEntity.getItem(); +- ItemStack itemStack = item.split(1); +- if (item.isEmpty()) { ++ ItemStack itemstack = itemEntity.getItem(); ++ ItemStack itemstack1 = itemstack.split(1); ++ ++ if (itemstack.isEmpty()) { + itemEntity.discard(); + } else { +- itemEntity.setItem(item); ++ itemEntity.setItem(itemstack); + } + +- return itemStack; ++ return itemstack1; + } + + protected static void stopHoldingOffHandItem(Piglin piglin, boolean shouldBarter) { +- ItemStack itemInHand = piglin.getItemInHand(InteractionHand.OFF_HAND); +- piglin.setItemInHand(InteractionHand.OFF_HAND, ItemStack.EMPTY); ++ ItemStack itemstack = piglin.getItemInHand(EnumHand.OFF_HAND); ++ ++ piglin.setItemInHand(EnumHand.OFF_HAND, ItemStack.EMPTY); ++ boolean flag1; ++ + if (piglin.isAdult()) { +- boolean isBarterCurrency = isBarterCurrency(itemInHand); +- if (shouldBarter && isBarterCurrency) { +- throwItems(piglin, getBarterResponseItems(piglin)); +- } else if (!isBarterCurrency) { +- boolean flag = !piglin.equipItemIfPossible(itemInHand).isEmpty(); +- if (!flag) { +- putInInventory(piglin, itemInHand); ++ flag1 = isBarterCurrency(itemstack, piglin); // CraftBukkit - Changes to allow custom payment for bartering ++ if (shouldBarter && flag1) { ++ // CraftBukkit start ++ PiglinBarterEvent event = CraftEventFactory.callPiglinBarterEvent(piglin, getBarterResponseItems(piglin), itemstack); ++ if (!event.isCancelled()) { ++ throwItems(piglin, event.getOutcome().stream().map(CraftItemStack::asNMSCopy).collect(Collectors.toList())); + } ++ // CraftBukkit end ++ } else if (!flag1) { ++ boolean flag2 = !piglin.equipItemIfPossible(itemstack).isEmpty(); ++ ++ if (!flag2) { ++ putInInventory(piglin, itemstack); ++ } + } + } else { +- boolean isBarterCurrency = !piglin.equipItemIfPossible(itemInHand).isEmpty(); +- if (!isBarterCurrency) { +- ItemStack mainHandItem = piglin.getMainHandItem(); +- if (isLovedItem(mainHandItem)) { +- putInInventory(piglin, mainHandItem); ++ flag1 = !piglin.equipItemIfPossible(itemstack).isEmpty(); ++ if (!flag1) { ++ ItemStack itemstack1 = piglin.getMainHandItem(); ++ ++ if (isLovedItem(itemstack1, piglin)) { // CraftBukkit - Changes to allow for custom payment in bartering ++ putInInventory(piglin, itemstack1); + } else { +- throwItems(piglin, Collections.singletonList(mainHandItem)); ++ throwItems(piglin, Collections.singletonList(itemstack1)); + } + +- piglin.holdInMainHand(itemInHand); ++ piglin.holdInMainHand(itemstack); + } + } ++ + } + + protected static void cancelAdmiring(Piglin piglin) { + if (isAdmiringItem(piglin) && !piglin.getOffhandItem().isEmpty()) { + piglin.spawnAtLocation(piglin.getOffhandItem()); +- piglin.setItemInHand(InteractionHand.OFF_HAND, ItemStack.EMPTY); ++ piglin.setItemInHand(EnumHand.OFF_HAND, ItemStack.EMPTY); + } ++ + } + + private static void putInInventory(Piglin piglin, ItemStack stack) { +- ItemStack itemStack = piglin.addToInventory(stack); +- throwItemsTowardRandomPos(piglin, Collections.singletonList(itemStack)); ++ ItemStack itemstack1 = piglin.addToInventory(stack); ++ ++ throwItemsTowardRandomPos(piglin, Collections.singletonList(itemstack1)); + } + + private static void throwItems(Piglin pilgin, List<ItemStack> stacks) { +- Optional<Player> memory = pilgin.getBrain().getMemory(MemoryModuleType.NEAREST_VISIBLE_PLAYER); +- if (memory.isPresent()) { +- throwItemsTowardPlayer(pilgin, memory.get(), stacks); ++ Optional<Player> optional = pilgin.getBrain().getMemory(MemoryModuleType.NEAREST_VISIBLE_PLAYER); ++ ++ if (optional.isPresent()) { ++ throwItemsTowardPlayer(pilgin, (Player) optional.get(), stacks); + } else { + throwItemsTowardRandomPos(pilgin, stacks); + } ++ + } + + private static void throwItemsTowardRandomPos(Piglin piglin, List<ItemStack> stacks) { +@@ -432,24 +363,27 @@ + + private static void throwItemsTowardPos(Piglin piglin, List<ItemStack> stacks, Vec3 pos) { + if (!stacks.isEmpty()) { +- piglin.swing(InteractionHand.OFF_HAND); ++ piglin.swing(EnumHand.OFF_HAND); ++ Iterator iterator = stacks.iterator(); + +- for (ItemStack itemStack : stacks) { +- BehaviorUtils.throwItem(piglin, itemStack, pos.add(0.0, 1.0, 0.0)); ++ while (iterator.hasNext()) { ++ ItemStack itemstack = (ItemStack) iterator.next(); ++ ++ BehaviorUtils.throwItem(piglin, itemstack, pos.add(0.0D, 1.0D, 0.0D)); + } + } ++ + } + + private static List<ItemStack> getBarterResponseItems(Piglin piglin) { +- LootTable lootTable = piglin.level().getServer().getLootData().getLootTable(BuiltInLootTables.PIGLIN_BARTERING); +- List<ItemStack> randomItems = lootTable.getRandomItems( +- new LootParams.Builder((ServerLevel)piglin.level()).withParameter(LootContextParams.THIS_ENTITY, piglin).create(LootContextParamSets.PIGLIN_BARTER) +- ); +- return randomItems; ++ LootTable loottable = piglin.level().getServer().getLootData().getLootTable(BuiltInLootTables.PIGLIN_BARTERING); ++ List<ItemStack> list = loottable.getRandomItems((new LootParams.Builder((ServerLevel) piglin.level())).withParameter(LootContextParams.THIS_ENTITY, piglin).create(LootContextParamSets.PIGLIN_BARTER)); ++ ++ return list; + } + + private static boolean wantsToDance(LivingEntity piglin, LivingEntity target) { +- return target.getType() == EntityType.HOGLIN && RandomSource.create(piglin.level().getGameTime()).nextFloat() < 0.1F; ++ return target.getType() != EntityType.HOGLIN ? false : RandomSource.create(piglin.level().getGameTime()).nextFloat() < 0.1F; + } + + protected static boolean wantsToPickup(Piglin piglin, ItemStack stack) { +@@ -459,86 +393,107 @@ + return false; + } else if (isAdmiringDisabled(piglin) && piglin.getBrain().hasMemoryValue(MemoryModuleType.ATTACK_TARGET)) { + return false; +- } else if (isBarterCurrency(stack)) { ++ } else if (isBarterCurrency(stack, piglin)) { // CraftBukkit + return isNotHoldingLovedItemInOffHand(piglin); + } else { +- boolean canAddToInventory = piglin.canAddToInventory(stack); +- if (stack.is(Items.GOLD_NUGGET)) { +- return canAddToInventory; +- } else if (isFood(stack)) { +- return !hasEatenRecently(piglin) && canAddToInventory; +- } else { +- return !isLovedItem(stack) ? piglin.canReplaceCurrentItem(stack) : isNotHoldingLovedItemInOffHand(piglin) && canAddToInventory; +- } ++ boolean flag = piglin.canAddToInventory(stack); ++ ++ return stack.is(Items.GOLD_NUGGET) ? flag : (isFood(stack) ? !hasEatenRecently(piglin) && flag : (!isLovedItem(stack) ? piglin.canReplaceCurrentItem(stack) : isNotHoldingLovedItemInOffHand(piglin) && flag)); + } + } + ++ // CraftBukkit start - Added method to allow checking for custom payment items ++ protected static boolean isLovedItem(ItemStack itemstack, Piglin piglin) { ++ return isLovedItem(itemstack) || (piglin.interestItems.contains(itemstack.getItem()) || piglin.allowedBarterItems.contains(itemstack.getItem())); ++ } ++ // CraftBukkit end ++ + protected static boolean isLovedItem(ItemStack item) { + return item.is(ItemTags.PIGLIN_LOVED); + } + + private static boolean wantsToStopRiding(Piglin piglin, Entity vehicle) { +- return vehicle instanceof Mob mob +- && (!mob.isBaby() || !mob.isAlive() || wasHurtRecently(piglin) || wasHurtRecently(mob) || mob instanceof Piglin && mob.getVehicle() == null); ++ if (!(vehicle instanceof Mob)) { ++ return false; ++ } else { ++ Mob entityinsentient = (Mob) vehicle; ++ ++ return !entityinsentient.isBaby() || !entityinsentient.isAlive() || wasHurtRecently(piglin) || wasHurtRecently(entityinsentient) || entityinsentient instanceof Piglin && entityinsentient.getVehicle() == null; ++ } + } + + private static boolean isNearestValidAttackTarget(Piglin piglin, LivingEntity target) { +- return findNearestValidAttackTarget(piglin).filter(entity -> entity == target).isPresent(); ++ return findNearestValidAttackTarget(piglin).filter((entityliving1) -> { ++ return entityliving1 == target; ++ }).isPresent(); + } + + private static boolean isNearZombified(Piglin piglin) { +- Brain<Piglin> brain = piglin.getBrain(); +- if (brain.hasMemoryValue(MemoryModuleType.NEAREST_VISIBLE_ZOMBIFIED)) { +- LivingEntity livingEntity = brain.getMemory(MemoryModuleType.NEAREST_VISIBLE_ZOMBIFIED).get(); +- return piglin.closerThan(livingEntity, 6.0); ++ Brain<Piglin> behaviorcontroller = piglin.getBrain(); ++ ++ if (behaviorcontroller.hasMemoryValue(MemoryModuleType.NEAREST_VISIBLE_ZOMBIFIED)) { ++ LivingEntity entityliving = (LivingEntity) behaviorcontroller.getMemory(MemoryModuleType.NEAREST_VISIBLE_ZOMBIFIED).get(); ++ ++ return piglin.closerThan(entityliving, 6.0D); + } else { + return false; + } + } + + private static Optional<? extends LivingEntity> findNearestValidAttackTarget(Piglin piglin) { +- Brain<Piglin> brain = piglin.getBrain(); ++ Brain<Piglin> behaviorcontroller = piglin.getBrain(); ++ + if (isNearZombified(piglin)) { + return Optional.empty(); + } else { +- Optional<LivingEntity> livingEntityFromUUIDMemory = BehaviorUtils.getLivingEntityFromUUIDMemory(piglin, MemoryModuleType.ANGRY_AT); +- if (livingEntityFromUUIDMemory.isPresent() && Sensor.isEntityAttackableIgnoringLineOfSight(piglin, livingEntityFromUUIDMemory.get())) { +- return livingEntityFromUUIDMemory; ++ Optional<LivingEntity> optional = BehaviorUtils.getLivingEntityFromUUIDMemory(piglin, MemoryModuleType.ANGRY_AT); ++ ++ if (optional.isPresent() && Sensor.isEntityAttackableIgnoringLineOfSight(piglin, (LivingEntity) optional.get())) { ++ return optional; + } else { +- if (brain.hasMemoryValue(MemoryModuleType.UNIVERSAL_ANGER)) { +- Optional<Player> memory = brain.getMemory(MemoryModuleType.NEAREST_VISIBLE_ATTACKABLE_PLAYER); +- if (memory.isPresent()) { +- return memory; ++ Optional optional1; ++ ++ if (behaviorcontroller.hasMemoryValue(MemoryModuleType.UNIVERSAL_ANGER)) { ++ optional1 = behaviorcontroller.getMemory(MemoryModuleType.NEAREST_VISIBLE_ATTACKABLE_PLAYER); ++ if (optional1.isPresent()) { ++ return optional1; + } + } + +- Optional<Mob> memory = brain.getMemory(MemoryModuleType.NEAREST_VISIBLE_NEMESIS); +- if (memory.isPresent()) { +- return memory; ++ optional1 = behaviorcontroller.getMemory(MemoryModuleType.NEAREST_VISIBLE_NEMESIS); ++ if (optional1.isPresent()) { ++ return optional1; + } else { +- Optional<Player> memory1 = brain.getMemory(MemoryModuleType.NEAREST_TARGETABLE_PLAYER_NOT_WEARING_GOLD); +- return memory1.isPresent() && Sensor.isEntityAttackable(piglin, memory1.get()) ? memory1 : Optional.empty(); ++ Optional<Player> optional2 = behaviorcontroller.getMemory(MemoryModuleType.NEAREST_TARGETABLE_PLAYER_NOT_WEARING_GOLD); ++ ++ return optional2.isPresent() && Sensor.isEntityAttackable(piglin, (LivingEntity) optional2.get()) ? optional2 : Optional.empty(); + } + } + } + } + + public static void angerNearbyPiglins(Player player, boolean angerOnlyIfCanSee) { +- List<Piglin> entitiesOfClass = player.level().getEntitiesOfClass(Piglin.class, player.getBoundingBox().inflate(16.0)); +- entitiesOfClass.stream().filter(PiglinAi::isIdle).filter(piglin -> !angerOnlyIfCanSee || BehaviorUtils.canSee(piglin, player)).forEach(piglin -> { +- if (piglin.level().getGameRules().getBoolean(GameRules.RULE_UNIVERSAL_ANGER)) { +- setAngerTargetToNearestTargetablePlayerIfFound(piglin, player); ++ List<Piglin> list = player.level().getEntitiesOfClass(Piglin.class, player.getBoundingBox().inflate(16.0D)); ++ ++ list.stream().filter(PiglinAi::isIdle).filter((entitypiglin) -> { ++ return !angerOnlyIfCanSee || BehaviorUtils.canSee(entitypiglin, player); ++ }).forEach((entitypiglin) -> { ++ if (entitypiglin.level().getGameRules().getBoolean(GameRules.RULE_UNIVERSAL_ANGER)) { ++ setAngerTargetToNearestTargetablePlayerIfFound(entitypiglin, player); + } else { +- setAngerTarget(piglin, player); ++ setAngerTarget(entitypiglin, player); + } ++ + }); + } + +- public static InteractionResult mobInteract(Piglin piglin, Player player, InteractionHand hand) { +- ItemStack itemInHand = player.getItemInHand(hand); +- if (canAdmire(piglin, itemInHand)) { +- ItemStack itemStack = itemInHand.split(1); +- holdInOffhand(piglin, itemStack); ++ public static InteractionResult mobInteract(Piglin piglin, Player player, EnumHand hand) { ++ ItemStack itemstack = player.getItemInHand(hand); ++ ++ if (canAdmire(piglin, itemstack)) { ++ ItemStack itemstack1 = itemstack.split(1); ++ ++ holdInOffhand(piglin, itemstack1); + admireGoldItem(piglin); + stopWalking(piglin); + return InteractionResult.CONSUME; +@@ -548,7 +503,7 @@ + } + + protected static boolean canAdmire(Piglin piglin, ItemStack stack) { +- return !isAdmiringDisabled(piglin) && !isAdmiringItem(piglin) && piglin.isAdult() && isBarterCurrency(stack); ++ return !isAdmiringDisabled(piglin) && !isAdmiringItem(piglin) && piglin.isAdult() && isBarterCurrency(stack, piglin); // CraftBukkit + } + + protected static void wasHurtBy(Piglin piglin, LivingEntity target) { +@@ -557,24 +512,27 @@ + stopHoldingOffHandItem(piglin, false); + } + +- Brain<Piglin> brain = piglin.getBrain(); +- brain.eraseMemory(MemoryModuleType.CELEBRATE_LOCATION); +- brain.eraseMemory(MemoryModuleType.DANCING); +- brain.eraseMemory(MemoryModuleType.ADMIRING_ITEM); ++ Brain<Piglin> behaviorcontroller = piglin.getBrain(); ++ ++ behaviorcontroller.eraseMemory(MemoryModuleType.CELEBRATE_LOCATION); ++ behaviorcontroller.eraseMemory(MemoryModuleType.DANCING); ++ behaviorcontroller.eraseMemory(MemoryModuleType.ADMIRING_ITEM); + if (target instanceof Player) { +- brain.setMemoryWithExpiry(MemoryModuleType.ADMIRING_DISABLED, true, 400L); ++ behaviorcontroller.setMemoryWithExpiry(MemoryModuleType.ADMIRING_DISABLED, true, 400L); + } + +- getAvoidTarget(piglin).ifPresent(entity -> { +- if (entity.getType() != target.getType()) { +- brain.eraseMemory(MemoryModuleType.AVOID_TARGET); ++ getAvoidTarget(piglin).ifPresent((entityliving1) -> { ++ if (entityliving1.getType() != target.getType()) { ++ behaviorcontroller.eraseMemory(MemoryModuleType.AVOID_TARGET); + } ++ + }); + if (piglin.isBaby()) { +- brain.setMemoryWithExpiry(MemoryModuleType.AVOID_TARGET, target, 100L); ++ behaviorcontroller.setMemoryWithExpiry(MemoryModuleType.AVOID_TARGET, target, 100L); + if (Sensor.isEntityAttackableIgnoringLineOfSight(piglin, target)) { + broadcastAngerTarget(piglin, target); + } ++ + } else if (target.getType() == EntityType.HOGLIN && hoglinsOutnumberPiglins(piglin)) { + setAvoidTargetAndDontHuntForAWhile(piglin, target); + broadcastRetreat(piglin, target); +@@ -587,7 +545,7 @@ + protected static void maybeRetaliate(AbstractPiglin piglin, LivingEntity target) { + if (!piglin.getBrain().isActive(Activity.AVOID)) { + if (Sensor.isEntityAttackableIgnoringLineOfSight(piglin, target)) { +- if (!BehaviorUtils.isOtherTargetMuchFurtherAwayThanCurrentAttackTarget(piglin, target, 4.0)) { ++ if (!BehaviorUtils.isOtherTargetMuchFurtherAwayThanCurrentAttackTarget(piglin, target, 4.0D)) { + if (target.getType() == EntityType.PLAYER && piglin.level().getGameRules().getBoolean(GameRules.RULE_UNIVERSAL_ANGER)) { + setAngerTargetToNearestTargetablePlayerIfFound(piglin, target); + broadcastUniversalAnger(piglin); +@@ -595,55 +553,53 @@ + setAngerTarget(piglin, target); + broadcastAngerTarget(piglin, target); + } ++ + } + } + } + } + + public static Optional<SoundEvent> getSoundForCurrentActivity(Piglin piglin) { +- return piglin.getBrain().getActiveNonCoreActivity().map(activity -> getSoundForActivity(piglin, activity)); ++ return piglin.getBrain().getActiveNonCoreActivity().map((activity) -> { ++ return getSoundForActivity(piglin, activity); ++ }); + } + + private static SoundEvent getSoundForActivity(Piglin piglin, Activity activity) { +- if (activity == Activity.FIGHT) { +- return SoundEvents.PIGLIN_ANGRY; +- } else if (piglin.isConverting()) { +- return SoundEvents.PIGLIN_RETREAT; +- } else if (activity == Activity.AVOID && isNearAvoidTarget(piglin)) { +- return SoundEvents.PIGLIN_RETREAT; +- } else if (activity == Activity.ADMIRE_ITEM) { +- return SoundEvents.PIGLIN_ADMIRING_ITEM; +- } else if (activity == Activity.CELEBRATE) { +- return SoundEvents.PIGLIN_CELEBRATE; +- } else if (seesPlayerHoldingLovedItem(piglin)) { +- return SoundEvents.PIGLIN_JEALOUS; +- } else { +- return isNearRepellent(piglin) ? SoundEvents.PIGLIN_RETREAT : SoundEvents.PIGLIN_AMBIENT; +- } ++ return activity == Activity.FIGHT ? SoundEvents.PIGLIN_ANGRY : (piglin.isConverting() ? SoundEvents.PIGLIN_RETREAT : (activity == Activity.AVOID && isNearAvoidTarget(piglin) ? SoundEvents.PIGLIN_RETREAT : (activity == Activity.ADMIRE_ITEM ? SoundEvents.PIGLIN_ADMIRING_ITEM : (activity == Activity.CELEBRATE ? SoundEvents.PIGLIN_CELEBRATE : (seesPlayerHoldingLovedItem(piglin) ? SoundEvents.PIGLIN_JEALOUS : (isNearRepellent(piglin) ? SoundEvents.PIGLIN_RETREAT : SoundEvents.PIGLIN_AMBIENT)))))); + } + + private static boolean isNearAvoidTarget(Piglin piglin) { +- Brain<Piglin> brain = piglin.getBrain(); +- return brain.hasMemoryValue(MemoryModuleType.AVOID_TARGET) && brain.getMemory(MemoryModuleType.AVOID_TARGET).get().closerThan(piglin, 12.0); ++ Brain<Piglin> behaviorcontroller = piglin.getBrain(); ++ ++ return !behaviorcontroller.hasMemoryValue(MemoryModuleType.AVOID_TARGET) ? false : ((LivingEntity) behaviorcontroller.getMemory(MemoryModuleType.AVOID_TARGET).get()).closerThan(piglin, 12.0D); + } + + protected static List<AbstractPiglin> getVisibleAdultPiglins(Piglin piglin) { +- return piglin.getBrain().getMemory(MemoryModuleType.NEAREST_VISIBLE_ADULT_PIGLINS).orElse(ImmutableList.of()); ++ return (List) piglin.getBrain().getMemory(MemoryModuleType.NEAREST_VISIBLE_ADULT_PIGLINS).orElse(ImmutableList.of()); + } + + private static List<AbstractPiglin> getAdultPiglins(AbstractPiglin piglin) { +- return piglin.getBrain().getMemory(MemoryModuleType.NEARBY_ADULT_PIGLINS).orElse(ImmutableList.of()); ++ return (List) piglin.getBrain().getMemory(MemoryModuleType.NEARBY_ADULT_PIGLINS).orElse(ImmutableList.of()); + } + + public static boolean isWearingGold(LivingEntity livingEntity) { +- for (ItemStack itemStack : livingEntity.getArmorSlots()) { +- Item item = itemStack.getItem(); +- if (item instanceof ArmorItem && ((ArmorItem)item).getMaterial() == ArmorMaterials.GOLD) { +- return true; ++ Iterable<ItemStack> iterable = livingEntity.getArmorSlots(); ++ Iterator iterator = iterable.iterator(); ++ ++ Item item; ++ ++ do { ++ if (!iterator.hasNext()) { ++ return false; + } +- } + +- return false; ++ ItemStack itemstack = (ItemStack) iterator.next(); ++ ++ item = itemstack.getItem(); ++ } while (!(item instanceof ArmorItem) || ((ArmorItem) item).getMaterial() != ArmorMaterials.GOLD); ++ ++ return true; + } + + private static void stopWalking(Piglin piglin) { +@@ -652,25 +608,27 @@ + } + + private static BehaviorControl<LivingEntity> babySometimesRideBabyHoglin() { +- SetEntityLookTargetSometimes.Ticker ticker = new SetEntityLookTargetSometimes.Ticker(RIDE_START_INTERVAL); +- return CopyMemoryWithExpiry.create( +- livingEntity -> livingEntity.isBaby() && ticker.tickDownAndCheck(livingEntity.level().random), +- MemoryModuleType.NEAREST_VISIBLE_BABY_HOGLIN, +- MemoryModuleType.RIDE_TARGET, +- RIDE_DURATION +- ); ++ SetEntityLookTargetSometimes.Ticker setentitylooktargetsometimes_a = new SetEntityLookTargetSometimes.Ticker(PiglinAi.RIDE_START_INTERVAL); ++ ++ return CopyMemoryWithExpiry.create((entityliving) -> { ++ return entityliving.isBaby() && setentitylooktargetsometimes_a.tickDownAndCheck(entityliving.level().random); ++ }, MemoryModuleType.NEAREST_VISIBLE_BABY_HOGLIN, MemoryModuleType.RIDE_TARGET, PiglinAi.RIDE_DURATION); + } + + protected static void broadcastAngerTarget(AbstractPiglin piglin, LivingEntity target) { +- getAdultPiglins(piglin).forEach(adultPiglin -> { +- if (target.getType() != EntityType.HOGLIN || adultPiglin.canHunt() && ((Hoglin)target).canBeHunted()) { +- setAngerTargetIfCloserThanCurrent(adultPiglin, target); ++ getAdultPiglins(piglin).forEach((entitypiglinabstract1) -> { ++ if (target.getType() != EntityType.HOGLIN || entitypiglinabstract1.canHunt() && ((Hoglin) target).canBeHunted()) { ++ setAngerTargetIfCloserThanCurrent(entitypiglinabstract1, target); + } + }); + } + + protected static void broadcastUniversalAnger(AbstractPiglin piglin) { +- getAdultPiglins(piglin).forEach(adultPiglin -> getNearestVisibleTargetablePlayer(adultPiglin).ifPresent(player -> setAngerTarget(adultPiglin, player))); ++ getAdultPiglins(piglin).forEach((entitypiglinabstract1) -> { ++ getNearestVisibleTargetablePlayer(entitypiglinabstract1).ifPresent((entityhuman) -> { ++ setAngerTarget(entitypiglinabstract1, entityhuman); ++ }); ++ }); + } + + protected static void setAngerTarget(AbstractPiglin piglin, LivingEntity target) { +@@ -684,23 +642,27 @@ + if (target.getType() == EntityType.PLAYER && piglin.level().getGameRules().getBoolean(GameRules.RULE_UNIVERSAL_ANGER)) { + piglin.getBrain().setMemoryWithExpiry(MemoryModuleType.UNIVERSAL_ANGER, true, 600L); + } ++ + } + } + + private static void setAngerTargetToNearestTargetablePlayerIfFound(AbstractPiglin piglin, LivingEntity currentTarget) { +- Optional<Player> nearestVisibleTargetablePlayer = getNearestVisibleTargetablePlayer(piglin); +- if (nearestVisibleTargetablePlayer.isPresent()) { +- setAngerTarget(piglin, nearestVisibleTargetablePlayer.get()); ++ Optional<Player> optional = getNearestVisibleTargetablePlayer(piglin); ++ ++ if (optional.isPresent()) { ++ setAngerTarget(piglin, (LivingEntity) optional.get()); + } else { + setAngerTarget(piglin, currentTarget); + } ++ + } + + private static void setAngerTargetIfCloserThanCurrent(AbstractPiglin piglin, LivingEntity currentTarget) { +- Optional<LivingEntity> angerTarget = getAngerTarget(piglin); +- LivingEntity nearestTarget = BehaviorUtils.getNearestTarget(piglin, angerTarget, currentTarget); +- if (!angerTarget.isPresent() || angerTarget.get() != nearestTarget) { +- setAngerTarget(piglin, nearestTarget); ++ Optional<LivingEntity> optional = getAngerTarget(piglin); ++ LivingEntity entityliving1 = BehaviorUtils.getNearestTarget(piglin, optional, currentTarget); ++ ++ if (!optional.isPresent() || optional.get() != entityliving1) { ++ setAngerTarget(piglin, entityliving1); + } + } + +@@ -713,35 +675,35 @@ + } + + public static Optional<Player> getNearestVisibleTargetablePlayer(AbstractPiglin piglin) { +- return piglin.getBrain().hasMemoryValue(MemoryModuleType.NEAREST_VISIBLE_ATTACKABLE_PLAYER) +- ? piglin.getBrain().getMemory(MemoryModuleType.NEAREST_VISIBLE_ATTACKABLE_PLAYER) +- : Optional.empty(); ++ return piglin.getBrain().hasMemoryValue(MemoryModuleType.NEAREST_VISIBLE_ATTACKABLE_PLAYER) ? piglin.getBrain().getMemory(MemoryModuleType.NEAREST_VISIBLE_ATTACKABLE_PLAYER) : Optional.empty(); + } + + private static void broadcastRetreat(Piglin piglin, LivingEntity target) { +- getVisibleAdultPiglins(piglin) +- .stream() +- .filter(adultPiglin -> adultPiglin instanceof Piglin) +- .forEach(adultPiglin -> retreatFromNearestTarget((Piglin)adultPiglin, target)); ++ getVisibleAdultPiglins(piglin).stream().filter((entitypiglinabstract) -> { ++ return entitypiglinabstract instanceof Piglin; ++ }).forEach((entitypiglinabstract) -> { ++ retreatFromNearestTarget((Piglin) entitypiglinabstract, target); ++ }); + } + + private static void retreatFromNearestTarget(Piglin piglin, LivingEntity target) { +- Brain<Piglin> brain = piglin.getBrain(); +- LivingEntity livingEntity = BehaviorUtils.getNearestTarget(piglin, brain.getMemory(MemoryModuleType.AVOID_TARGET), target); +- livingEntity = BehaviorUtils.getNearestTarget(piglin, brain.getMemory(MemoryModuleType.ATTACK_TARGET), livingEntity); +- setAvoidTargetAndDontHuntForAWhile(piglin, livingEntity); ++ Brain<Piglin> behaviorcontroller = piglin.getBrain(); ++ LivingEntity entityliving1 = BehaviorUtils.getNearestTarget(piglin, behaviorcontroller.getMemory(MemoryModuleType.AVOID_TARGET), target); ++ ++ entityliving1 = BehaviorUtils.getNearestTarget(piglin, behaviorcontroller.getMemory(MemoryModuleType.ATTACK_TARGET), entityliving1); ++ setAvoidTargetAndDontHuntForAWhile(piglin, entityliving1); + } + + private static boolean wantsToStopFleeing(Piglin piglin) { +- Brain<Piglin> brain = piglin.getBrain(); +- if (!brain.hasMemoryValue(MemoryModuleType.AVOID_TARGET)) { ++ Brain<Piglin> behaviorcontroller = piglin.getBrain(); ++ ++ if (!behaviorcontroller.hasMemoryValue(MemoryModuleType.AVOID_TARGET)) { + return true; + } else { +- LivingEntity livingEntity = brain.getMemory(MemoryModuleType.AVOID_TARGET).get(); +- EntityType<?> type = livingEntity.getType(); +- return type == EntityType.HOGLIN +- ? piglinsEqualOrOutnumberHoglins(piglin) +- : isZombified(type) && !brain.isMemoryValue(MemoryModuleType.NEAREST_VISIBLE_ZOMBIFIED, livingEntity); ++ LivingEntity entityliving = (LivingEntity) behaviorcontroller.getMemory(MemoryModuleType.AVOID_TARGET).get(); ++ EntityType<?> entitytypes = entityliving.getType(); ++ ++ return entitytypes == EntityType.HOGLIN ? piglinsEqualOrOutnumberHoglins(piglin) : (isZombified(entitytypes) ? !behaviorcontroller.isMemoryValue(MemoryModuleType.NEAREST_VISIBLE_ZOMBIFIED, entityliving) : false); + } + } + +@@ -750,21 +712,22 @@ + } + + private static boolean hoglinsOutnumberPiglins(Piglin piglin) { +- int i = piglin.getBrain().getMemory(MemoryModuleType.VISIBLE_ADULT_PIGLIN_COUNT).orElse(0) + 1; +- int i1 = piglin.getBrain().getMemory(MemoryModuleType.VISIBLE_ADULT_HOGLIN_COUNT).orElse(0); +- return i1 > i; ++ int i = (Integer) piglin.getBrain().getMemory(MemoryModuleType.VISIBLE_ADULT_PIGLIN_COUNT).orElse(0) + 1; ++ int j = (Integer) piglin.getBrain().getMemory(MemoryModuleType.VISIBLE_ADULT_HOGLIN_COUNT).orElse(0); ++ ++ return j > i; + } + + private static void setAvoidTargetAndDontHuntForAWhile(Piglin piglin, LivingEntity target) { + piglin.getBrain().eraseMemory(MemoryModuleType.ANGRY_AT); + piglin.getBrain().eraseMemory(MemoryModuleType.ATTACK_TARGET); + piglin.getBrain().eraseMemory(MemoryModuleType.WALK_TARGET); +- piglin.getBrain().setMemoryWithExpiry(MemoryModuleType.AVOID_TARGET, target, (long)RETREAT_DURATION.sample(piglin.level().random)); ++ piglin.getBrain().setMemoryWithExpiry(MemoryModuleType.AVOID_TARGET, target, (long) PiglinAi.RETREAT_DURATION.sample(piglin.level().random)); + dontKillAnyMoreHoglinsForAWhile(piglin); + } + + protected static void dontKillAnyMoreHoglinsForAWhile(AbstractPiglin piglin) { +- piglin.getBrain().setMemoryWithExpiry(MemoryModuleType.HUNTED_RECENTLY, true, (long)TIME_BETWEEN_HUNTS.sample(piglin.level().random)); ++ piglin.getBrain().setMemoryWithExpiry(MemoryModuleType.HUNTED_RECENTLY, true, (long) PiglinAi.TIME_BETWEEN_HUNTS.sample(piglin.level().random)); + } + + private static void eat(Piglin piglin) { +@@ -772,8 +735,9 @@ + } + + private static Vec3 getRandomNearbyPos(Piglin piglin) { +- Vec3 pos = LandRandomPos.getPos(piglin, 4, 2); +- return pos == null ? piglin.position() : pos; ++ Vec3 vec3d = LandRandomPos.getPos(piglin, 4, 2); ++ ++ return vec3d == null ? piglin.position() : vec3d; + } + + private static boolean hasEatenRecently(Piglin piglin) { +@@ -796,8 +760,14 @@ + return piglin.getBrain().hasMemoryValue(MemoryModuleType.ADMIRING_ITEM); + } + ++ // CraftBukkit start - Changes to allow custom payment for bartering ++ private static boolean isBarterCurrency(ItemStack itemstack, Piglin piglin) { ++ return isBarterCurrency(itemstack) || piglin.allowedBarterItems.contains(itemstack.getItem()); ++ } ++ // CraftBukkit end ++ + private static boolean isBarterCurrency(ItemStack stack) { +- return stack.is(BARTERING_ITEM); ++ return stack.is(PiglinAi.BARTERING_ITEM); + } + + private static boolean isFood(ItemStack stack) { +@@ -833,7 +803,7 @@ + } + + private static boolean isNotHoldingLovedItemInOffHand(Piglin piglin) { +- return piglin.getOffhandItem().isEmpty() || !isLovedItem(piglin.getOffhandItem()); ++ return piglin.getOffhandItem().isEmpty() || !isLovedItem(piglin.getOffhandItem(), piglin); // CraftBukkit - Changes to allow custom payment for bartering + } + + public static boolean isZombified(EntityType<?> entityType) { diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/warden/Warden.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/warden/Warden.java.patch new file mode 100644 index 0000000000..7cb6a96030 --- /dev/null +++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/monster/warden/Warden.java.patch @@ -0,0 +1,615 @@ +--- a/net/minecraft/world/entity/monster/warden/Warden.java ++++ b/net/minecraft/world/entity/monster/warden/Warden.java +@@ -2,8 +2,10 @@ + + import com.google.common.annotations.VisibleForTesting; + import com.mojang.logging.LogUtils; ++import com.mojang.serialization.DataResult; + import com.mojang.serialization.Dynamic; + import java.util.Collections; ++import java.util.Objects; + import java.util.Optional; + import java.util.function.BiConsumer; + import javax.annotation.Nullable; +@@ -12,7 +14,6 @@ + import net.minecraft.core.particles.ParticleTypes; + import net.minecraft.nbt.CompoundTag; + import net.minecraft.nbt.NbtOps; +-import net.minecraft.nbt.Tag; + import net.minecraft.network.protocol.Packet; + import net.minecraft.network.protocol.game.ClientGamePacketListener; + import net.minecraft.network.protocol.game.ClientboundAddEntityPacket; +@@ -37,12 +38,12 @@ + import net.minecraft.world.entity.AnimationState; + import net.minecraft.world.entity.Entity; + import net.minecraft.world.entity.EntityDimensions; ++import net.minecraft.world.entity.EntityPose; + import net.minecraft.world.entity.EntitySelector; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EnumMobSpawn; ++import net.minecraft.world.entity.GroupDataEntity; + import net.minecraft.world.entity.LivingEntity; +-import net.minecraft.world.entity.MobSpawnType; +-import net.minecraft.world.entity.Pose; +-import net.minecraft.world.entity.SpawnGroupData; + import net.minecraft.world.entity.ai.Brain; + import net.minecraft.world.entity.ai.attributes.AttributeSupplier; + import net.minecraft.world.entity.ai.attributes.Attributes; +@@ -56,8 +57,8 @@ + import net.minecraft.world.level.Level; + import net.minecraft.world.level.LevelReader; + import net.minecraft.world.level.ServerLevelAccessor; +-import net.minecraft.world.level.block.RenderShape; +-import net.minecraft.world.level.block.state.BlockState; ++import net.minecraft.world.level.block.EnumRenderType; ++import net.minecraft.world.level.block.state.IBlockData; + import net.minecraft.world.level.gameevent.DynamicGameEventListener; + import net.minecraft.world.level.gameevent.EntityPositionSource; + import net.minecraft.world.level.gameevent.GameEvent; +@@ -73,6 +74,7 @@ + import org.slf4j.Logger; + + public class Warden extends Monster implements VibrationSystem { ++ + private static final Logger LOGGER = LogUtils.getLogger(); + private static final int VIBRATION_COOLDOWN_TICKS = 40; + private static final int TIME_TO_USE_MELEE_UNTIL_SONIC_BOOM = 200; +@@ -106,16 +108,13 @@ + public AnimationState diggingAnimationState = new AnimationState(); + public AnimationState attackAnimationState = new AnimationState(); + public AnimationState sonicBoomAnimationState = new AnimationState(); +- private final DynamicGameEventListener<VibrationSystem.Listener> dynamicGameEventListener; +- private final VibrationSystem.User vibrationUser; +- private VibrationSystem.Data vibrationData; ++ private final DynamicGameEventListener<VibrationSystem.Listener> dynamicGameEventListener = new DynamicGameEventListener<>(new VibrationSystem.Listener(this)); ++ private final VibrationSystem.User vibrationUser = new Warden.a(); ++ private VibrationSystem.Data vibrationData = new VibrationSystem.Data(); + AngerManagement angerManagement = new AngerManagement(this::canTargetEntity, Collections.emptyList()); + + public Warden(EntityType<? extends Monster> entityType, Level level) { + super(entityType, level); +- this.vibrationUser = new Warden.VibrationUser(); +- this.vibrationData = new VibrationSystem.Data(); +- this.dynamicGameEventListener = new DynamicGameEventListener<>(new VibrationSystem.Listener(this)); + this.xpReward = 5; + this.getNavigation().setCanFloat(true); + this.setPathfindingMalus(BlockPathTypes.UNPASSABLE_RAIL, 0.0F); +@@ -128,15 +127,16 @@ + + @Override + public Packet<ClientGamePacketListener> getAddEntityPacket() { +- return new ClientboundAddEntityPacket(this, this.hasPose(Pose.EMERGING) ? 1 : 0); ++ return new ClientboundAddEntityPacket(this, this.hasPose(EntityPose.EMERGING) ? 1 : 0); + } + + @Override + public void recreateFromPacket(ClientboundAddEntityPacket packet) { + super.recreateFromPacket(packet); + if (packet.getData() == 1) { +- this.setPose(Pose.EMERGING); ++ this.setPose(EntityPose.EMERGING); + } ++ + } + + @Override +@@ -151,11 +151,11 @@ + + @Override + public boolean isInvulnerableTo(DamageSource source) { +- return this.isDiggingOrEmerging() && !source.is(DamageTypeTags.BYPASSES_INVULNERABILITY) || super.isInvulnerableTo(source); ++ return this.isDiggingOrEmerging() && !source.is(DamageTypeTags.BYPASSES_INVULNERABILITY) ? true : super.isInvulnerableTo(source); + } + + boolean isDiggingOrEmerging() { +- return this.hasPose(Pose.DIGGING) || this.hasPose(Pose.EMERGING); ++ return this.hasPose(EntityPose.DIGGING) || this.hasPose(EntityPose.EMERGING); + } + + @Override +@@ -174,12 +174,7 @@ + } + + public static AttributeSupplier.Builder createAttributes() { +- return Monster.createMonsterAttributes() +- .add(Attributes.MAX_HEALTH, 500.0) +- .add(Attributes.MOVEMENT_SPEED, 0.3F) +- .add(Attributes.KNOCKBACK_RESISTANCE, 1.0) +- .add(Attributes.ATTACK_KNOCKBACK, 1.5) +- .add(Attributes.ATTACK_DAMAGE, 30.0); ++ return Monster.createMonsterAttributes().add(Attributes.MAX_HEALTH, 500.0D).add(Attributes.MOVEMENT_SPEED, 0.30000001192092896D).add(Attributes.KNOCKBACK_RESISTANCE, 1.0D).add(Attributes.ATTACK_KNOCKBACK, 1.5D).add(Attributes.ATTACK_DAMAGE, 30.0D); + } + + @Override +@@ -195,7 +190,7 @@ + @Nullable + @Override + protected SoundEvent getAmbientSound() { +- return !this.hasPose(Pose.ROARING) && !this.isDiggingOrEmerging() ? this.getAngerLevel().getAmbientSound() : null; ++ return !this.hasPose(EntityPose.ROARING) && !this.isDiggingOrEmerging() ? this.getAngerLevel().getAmbientSound() : null; + } + + @Override +@@ -209,36 +204,40 @@ + } + + @Override +- protected void playStepSound(BlockPos pos, BlockState state) { ++ protected void playStepSound(BlockPos pos, IBlockData state) { + this.playSound(SoundEvents.WARDEN_STEP, 10.0F, 1.0F); + } + + @Override +- public boolean doHurtTarget(Entity entity) { +- this.level().broadcastEntityEvent(this, (byte)4); ++ public boolean doHurtTarget(Entity target) { ++ this.level().broadcastEntityEvent(this, (byte) 4); + this.playSound(SoundEvents.WARDEN_ATTACK_IMPACT, 10.0F, this.getVoicePitch()); + SonicBoom.setCooldown(this, 40); +- return super.doHurtTarget(entity); ++ return super.doHurtTarget(target); + } + + @Override + protected void defineSynchedData() { + super.defineSynchedData(); +- this.entityData.define(CLIENT_ANGER_LEVEL, 0); ++ this.entityData.define(Warden.CLIENT_ANGER_LEVEL, 0); + } + + public int getClientAngerLevel() { +- return this.entityData.get(CLIENT_ANGER_LEVEL); ++ return (Integer) this.entityData.get(Warden.CLIENT_ANGER_LEVEL); + } + + private void syncClientAngerLevel() { +- this.entityData.set(CLIENT_ANGER_LEVEL, this.getActiveAnger()); ++ this.entityData.set(Warden.CLIENT_ANGER_LEVEL, this.getActiveAnger()); + } + + @Override + public void tick() { +- if (this.level() instanceof ServerLevel serverLevel) { +- VibrationSystem.Ticker.tick(serverLevel, this.vibrationData, this.vibrationUser); ++ Level world = this.level(); ++ ++ if (world instanceof ServerLevel) { ++ ServerLevel worldserver = (ServerLevel) world; ++ ++ VibrationSystem.Ticker.tick(worldserver, this.vibrationData, this.vibrationUser); + if (this.isPersistenceRequired() || this.requiresCustomPersistence()) { + WardenAi.setDigCooldown(this); + } +@@ -249,21 +248,18 @@ + if (this.tickCount % this.getHeartBeatDelay() == 0) { + this.heartAnimation = 10; + if (!this.isSilent()) { +- this.level() +- .playLocalSound( +- this.getX(), this.getY(), this.getZ(), SoundEvents.WARDEN_HEARTBEAT, this.getSoundSource(), 5.0F, this.getVoicePitch(), false +- ); ++ this.level().playLocalSound(this.getX(), this.getY(), this.getZ(), SoundEvents.WARDEN_HEARTBEAT, this.getSoundSource(), 5.0F, this.getVoicePitch(), false); + } + } + + this.tendrilAnimationO = this.tendrilAnimation; + if (this.tendrilAnimation > 0) { +- this.tendrilAnimation--; ++ --this.tendrilAnimation; + } + + this.heartAnimationO = this.heartAnimation; + if (this.heartAnimation > 0) { +- this.heartAnimation--; ++ --this.heartAnimation; + } + + switch (this.getPose()) { +@@ -274,21 +270,23 @@ + this.clientDiggingParticles(this.diggingAnimationState); + } + } ++ + } + + @Override + protected void customServerAiStep() { +- ServerLevel serverLevel = (ServerLevel)this.level(); +- serverLevel.getProfiler().push("wardenBrain"); +- this.getBrain().tick(serverLevel, this); ++ ServerLevel worldserver = (ServerLevel) this.level(); ++ ++ worldserver.getProfiler().push("wardenBrain"); ++ this.getBrain().tick(worldserver, this); + this.level().getProfiler().pop(); + super.customServerAiStep(); + if ((this.tickCount + this.getId()) % 120 == 0) { +- applyDarknessAround(serverLevel, this.position(), this, 20); ++ applyDarknessAround(worldserver, this.position(), this, 20); + } + + if (this.tickCount % 20 == 0) { +- this.angerManagement.tick(serverLevel, this::canTargetEntity); ++ this.angerManagement.tick(worldserver, this::canTargetEntity); + this.syncClientAngerLevel(); + } + +@@ -307,39 +305,44 @@ + } else { + super.handleEntityEvent(id); + } ++ + } + + private int getHeartBeatDelay() { +- float f = (float)this.getClientAngerLevel() / (float)AngerLevel.ANGRY.getMinimumAnger(); ++ float f = (float) this.getClientAngerLevel() / (float) AngerLevel.ANGRY.getMinimumAnger(); ++ + return 40 - Mth.floor(Mth.clamp(f, 0.0F, 1.0F) * 30.0F); + } + + public float getTendrilAnimation(float partialTick) { +- return Mth.lerp(partialTick, (float)this.tendrilAnimationO, (float)this.tendrilAnimation) / 10.0F; ++ return Mth.lerp(partialTick, (float) this.tendrilAnimationO, (float) this.tendrilAnimation) / 10.0F; + } + + public float getHeartAnimation(float partialTick) { +- return Mth.lerp(partialTick, (float)this.heartAnimationO, (float)this.heartAnimation) / 10.0F; ++ return Mth.lerp(partialTick, (float) this.heartAnimationO, (float) this.heartAnimation) / 10.0F; + } + + private void clientDiggingParticles(AnimationState animationState) { +- if ((float)animationState.getAccumulatedTime() < 4500.0F) { +- RandomSource random = this.getRandom(); +- BlockState blockStateOn = this.getBlockStateOn(); +- if (blockStateOn.getRenderShape() != RenderShape.INVISIBLE) { +- for (int i = 0; i < 30; i++) { +- double d = this.getX() + (double)Mth.randomBetween(random, -0.7F, 0.7F); +- double y = this.getY(); +- double d1 = this.getZ() + (double)Mth.randomBetween(random, -0.7F, 0.7F); +- this.level().addParticle(new BlockParticleOption(ParticleTypes.BLOCK, blockStateOn), d, y, d1, 0.0, 0.0, 0.0); ++ if ((float) animationState.getAccumulatedTime() < 4500.0F) { ++ RandomSource randomsource = this.getRandom(); ++ IBlockData iblockdata = this.getBlockStateOn(); ++ ++ if (iblockdata.getRenderShape() != EnumRenderType.INVISIBLE) { ++ for (int i = 0; i < 30; ++i) { ++ double d0 = this.getX() + (double) Mth.randomBetween(randomsource, -0.7F, 0.7F); ++ double d1 = this.getY(); ++ double d2 = this.getZ() + (double) Mth.randomBetween(randomsource, -0.7F, 0.7F); ++ ++ this.level().addParticle(new BlockParticleOption(ParticleTypes.BLOCK, iblockdata), d0, d1, d2, 0.0D, 0.0D, 0.0D); + } + } + } ++ + } + + @Override + public void onSyncedDataUpdated(EntityDataAccessor<?> key) { +- if (DATA_POSE.equals(key)) { ++ if (Warden.DATA_POSE.equals(key)) { + switch (this.getPose()) { + case EMERGING: + this.emergeAnimationState.start(this.tickCount); +@@ -370,7 +373,7 @@ + + @Override + public Brain<Warden> getBrain() { +- return (Brain<Warden>)super.getBrain(); ++ return (Brain<Warden>) super.getBrain(); // CraftBukkit - decompile error + } + + @Override +@@ -381,69 +384,89 @@ + + @Override + public void updateDynamicGameEventListener(BiConsumer<DynamicGameEventListener<?>, ServerLevel> listenerConsumer) { +- if (this.level() instanceof ServerLevel serverLevel) { +- listenerConsumer.accept(this.dynamicGameEventListener, serverLevel); ++ Level world = this.level(); ++ ++ if (world instanceof ServerLevel) { ++ ServerLevel worldserver = (ServerLevel) world; ++ ++ listenerConsumer.accept(this.dynamicGameEventListener, worldserver); + } ++ + } + + @Contract("null->false") + public boolean canTargetEntity(@Nullable Entity entity) { +- if (entity instanceof LivingEntity livingEntity +- && this.level() == entity.level() +- && EntitySelector.NO_CREATIVE_OR_SPECTATOR.test(entity) +- && !this.isAlliedTo(entity) +- && livingEntity.getType() != EntityType.ARMOR_STAND +- && livingEntity.getType() != EntityType.WARDEN +- && !livingEntity.isInvulnerable() +- && !livingEntity.isDeadOrDying() +- && this.level().getWorldBorder().isWithinBounds(livingEntity.getBoundingBox())) { +- return true; ++ boolean flag; ++ ++ if (entity instanceof LivingEntity) { ++ LivingEntity entityliving = (LivingEntity) entity; ++ ++ if (this.level() == entity.level() && EntitySelector.NO_CREATIVE_OR_SPECTATOR.test(entity) && !this.isAlliedTo(entity) && entityliving.getType() != EntityType.ARMOR_STAND && entityliving.getType() != EntityType.WARDEN && !entityliving.isInvulnerable() && !entityliving.isDeadOrDying() && this.level().getWorldBorder().isWithinBounds(entityliving.getBoundingBox())) { ++ flag = true; ++ return flag; ++ } + } + +- return false; ++ flag = false; ++ return flag; + } + + public static void applyDarknessAround(ServerLevel level, Vec3 pos, @Nullable Entity source, int radius) { +- MobEffectInstance mobEffectInstance = new MobEffectInstance(MobEffects.DARKNESS, 260, 0, false, false); +- MobEffectUtil.addEffectToPlayersAround(level, source, pos, (double)radius, mobEffectInstance, 200); ++ MobEffectInstance mobeffect = new MobEffectInstance(MobEffects.DARKNESS, 260, 0, false, false); ++ ++ MobEffectUtil.addEffectToPlayersAround(level, source, pos, radius, mobeffect, 200, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.WARDEN); // CraftBukkit - Add EntityPotionEffectEvent.Cause + } + + @Override + public void addAdditionalSaveData(CompoundTag compound) { + super.addAdditionalSaveData(compound); +- AngerManagement.codec(this::canTargetEntity) +- .encodeStart(NbtOps.INSTANCE, this.angerManagement) +- .resultOrPartial(LOGGER::error) +- .ifPresent(tag -> compound.put("anger", tag)); +- VibrationSystem.Data.CODEC +- .encodeStart(NbtOps.INSTANCE, this.vibrationData) +- .resultOrPartial(LOGGER::error) +- .ifPresent(tag -> compound.put("listener", tag)); ++ DataResult<net.minecraft.nbt.Tag> dataresult = AngerManagement.codec(this::canTargetEntity).encodeStart(NbtOps.INSTANCE, this.angerManagement); // CraftBukkit - decompile error ++ Logger logger = Warden.LOGGER; ++ ++ Objects.requireNonNull(logger); ++ dataresult.resultOrPartial(logger::error).ifPresent((nbtbase) -> { ++ compound.put("anger", nbtbase); ++ }); ++ dataresult = VibrationSystem.Data.CODEC.encodeStart(NbtOps.INSTANCE, this.vibrationData); ++ logger = Warden.LOGGER; ++ Objects.requireNonNull(logger); ++ dataresult.resultOrPartial(logger::error).ifPresent((nbtbase) -> { ++ compound.put("listener", nbtbase); ++ }); + } + + @Override + public void readAdditionalSaveData(CompoundTag compound) { + super.readAdditionalSaveData(compound); ++ DataResult dataresult; ++ Logger logger; ++ + if (compound.contains("anger")) { +- AngerManagement.codec(this::canTargetEntity) +- .parse(new Dynamic<>(NbtOps.INSTANCE, compound.get("anger"))) +- .resultOrPartial(LOGGER::error) +- .ifPresent(angerManagement -> this.angerManagement = angerManagement); ++ dataresult = AngerManagement.codec(this::canTargetEntity).parse(new Dynamic(NbtOps.INSTANCE, compound.get("anger"))); ++ logger = Warden.LOGGER; ++ Objects.requireNonNull(logger); ++ ((DataResult<AngerManagement>) dataresult).resultOrPartial(logger::error).ifPresent((angermanagement) -> { // CraftBukkit - decompile error ++ this.angerManagement = angermanagement; ++ }); + this.syncClientAngerLevel(); + } + + if (compound.contains("listener", 10)) { +- VibrationSystem.Data.CODEC +- .parse(new Dynamic<>(NbtOps.INSTANCE, compound.getCompound("listener"))) +- .resultOrPartial(LOGGER::error) +- .ifPresent(vibrationData -> this.vibrationData = vibrationData); ++ dataresult = VibrationSystem.Data.CODEC.parse(new Dynamic(NbtOps.INSTANCE, compound.getCompound("listener"))); ++ logger = Warden.LOGGER; ++ Objects.requireNonNull(logger); ++ ((DataResult<VibrationSystem.Data>) dataresult).resultOrPartial(logger::error).ifPresent((vibrationsystem_a) -> { // CraftBukkit - decompile error ++ this.vibrationData = vibrationsystem_a; ++ }); + } ++ + } + + private void playListeningSound() { +- if (!this.hasPose(Pose.ROARING)) { ++ if (!this.hasPose(EntityPose.ROARING)) { + this.playSound(this.getAngerLevel().getListeningSound(), 10.0F, this.getVoicePitch()); + } ++ + } + + public AngerLevel getAngerLevel() { +@@ -466,9 +489,10 @@ + public void increaseAngerAt(@Nullable Entity entity, int offset, boolean playListeningSound) { + if (!this.isNoAi() && this.canTargetEntity(entity)) { + WardenAi.setDigCooldown(this); +- boolean flag = !(this.getBrain().getMemory(MemoryModuleType.ATTACK_TARGET).orElse(null) instanceof Player); +- int i = this.angerManagement.increaseAnger(entity, offset); +- if (entity instanceof Player && flag && AngerLevel.byAnger(i).isAngry()) { ++ boolean flag1 = !(this.getBrain().getMemory(MemoryModuleType.ATTACK_TARGET).orElse(null) instanceof Player); // CraftBukkit - decompile error ++ int j = this.angerManagement.increaseAnger(entity, offset); ++ ++ if (entity instanceof Player && flag1 && AngerLevel.byAnger(j).isAngry()) { + this.getBrain().eraseMemory(MemoryModuleType.ATTACK_TARGET); + } + +@@ -476,6 +500,7 @@ + this.playListeningSound(); + } + } ++ + } + + public Optional<LivingEntity> getEntityAngryAt() { +@@ -485,7 +510,7 @@ + @Nullable + @Override + public LivingEntity getTarget() { +- return this.getBrain().getMemory(MemoryModuleType.ATTACK_TARGET).orElse(null); ++ return (LivingEntity) this.getBrain().getMemory(MemoryModuleType.ATTACK_TARGET).orElse(null); // CraftBukkit - decompile error + } + + @Override +@@ -495,13 +520,11 @@ + + @Nullable + @Override +- public SpawnGroupData finalizeSpawn( +- ServerLevelAccessor level, DifficultyInstance difficulty, MobSpawnType reason, @Nullable SpawnGroupData spawnData, @Nullable CompoundTag dataTag +- ) { ++ public GroupDataEntity finalizeSpawn(ServerLevelAccessor level, DifficultyInstance difficulty, EnumMobSpawn reason, @Nullable GroupDataEntity spawnData, @Nullable CompoundTag dataTag) { + this.getBrain().setMemoryWithExpiry(MemoryModuleType.DIG_COOLDOWN, Unit.INSTANCE, 1200L); +- if (reason == MobSpawnType.TRIGGERED) { +- this.setPose(Pose.EMERGING); +- this.getBrain().setMemoryWithExpiry(MemoryModuleType.IS_EMERGING, Unit.INSTANCE, (long)WardenAi.EMERGE_DURATION); ++ if (reason == EnumMobSpawn.TRIGGERED) { ++ this.setPose(EntityPose.EMERGING); ++ this.getBrain().setMemoryWithExpiry(MemoryModuleType.IS_EMERGING, Unit.INSTANCE, (long) WardenAi.EMERGE_DURATION); + this.playSound(SoundEvents.WARDEN_AGITATED, 5.0F, 1.0F); + } + +@@ -511,13 +534,17 @@ + @Override + public boolean hurt(DamageSource source, float amount) { + boolean flag = super.hurt(source, amount); ++ + if (!this.level().isClientSide && !this.isNoAi() && !this.isDiggingOrEmerging()) { + Entity entity = source.getEntity(); ++ + this.increaseAngerAt(entity, AngerLevel.ANGRY.getMinimumAnger() + 20, false); +- if (this.brain.getMemory(MemoryModuleType.ATTACK_TARGET).isEmpty() +- && entity instanceof LivingEntity livingEntity +- && (!source.isIndirect() || this.closerThan(livingEntity, 5.0))) { +- this.setAttackTarget(livingEntity); ++ if (this.brain.getMemory(MemoryModuleType.ATTACK_TARGET).isEmpty() && entity instanceof LivingEntity) { ++ LivingEntity entityliving = (LivingEntity) entity; ++ ++ if (!source.isIndirect() || this.closerThan(entityliving, 5.0D)) { ++ this.setAttackTarget(entityliving); ++ } + } + } + +@@ -526,15 +553,16 @@ + + public void setAttackTarget(LivingEntity attackTarget) { + this.getBrain().eraseMemory(MemoryModuleType.ROAR_TARGET); +- this.getBrain().setMemory(MemoryModuleType.ATTACK_TARGET, attackTarget); ++ this.getBrain().setMemory(MemoryModuleType.ATTACK_TARGET, attackTarget); // CraftBukkit - decompile error + this.getBrain().eraseMemory(MemoryModuleType.CANT_REACH_WALK_TARGET_SINCE); + SonicBoom.setCooldown(this, 200); + } + + @Override +- public EntityDimensions getDimensions(Pose pose) { +- EntityDimensions entityDimensions = super.getDimensions(pose); +- return this.isDiggingOrEmerging() ? EntityDimensions.fixed(entityDimensions.width, 1.0F) : entityDimensions; ++ public EntityDimensions getDimensions(EntityPose pose) { ++ EntityDimensions entitysize = super.getDimensions(pose); ++ ++ return this.isDiggingOrEmerging() ? EntityDimensions.fixed(entitysize.width, 1.0F) : entitysize; + } + + @Override +@@ -576,8 +604,8 @@ + } + + @Override +- protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entityDimensions, float f) { +- return new Vector3f(0.0F, entityDimensions.height + 0.25F * f, 0.0F); ++ protected Vector3f getPassengerAttachmentPoint(Entity entity, EntityDimensions entitysize, float f) { ++ return new Vector3f(0.0F, entitysize.height + 0.25F * f, 0.0F); + } + + @Override +@@ -590,10 +618,13 @@ + return this.vibrationUser; + } + +- class VibrationUser implements VibrationSystem.User { ++ private class a implements VibrationSystem.User { ++ + private static final int GAME_EVENT_LISTENER_RANGE = 16; + private final PositionSource positionSource = new EntityPositionSource(Warden.this, Warden.this.getEyeHeight()); + ++ a() {} ++ + @Override + public int getListenerRadius() { + return 16; +@@ -616,35 +647,39 @@ + + @Override + public boolean canReceiveVibration(ServerLevel level, BlockPos pos, GameEvent gameEvent, GameEvent.Context context) { +- if (!Warden.this.isNoAi() +- && !Warden.this.isDeadOrDying() +- && !Warden.this.getBrain().hasMemoryValue(MemoryModuleType.VIBRATION_COOLDOWN) +- && !Warden.this.isDiggingOrEmerging() +- && level.getWorldBorder().isWithinBounds(pos)) { +- if (context.sourceEntity() instanceof LivingEntity livingEntity && !Warden.this.canTargetEntity(livingEntity)) { +- return false; ++ if (!Warden.this.isNoAi() && !Warden.this.isDeadOrDying() && !Warden.this.getBrain().hasMemoryValue(MemoryModuleType.VIBRATION_COOLDOWN) && !Warden.this.isDiggingOrEmerging() && level.getWorldBorder().isWithinBounds(pos)) { ++ Entity entity = context.sourceEntity(); ++ boolean flag; ++ ++ if (entity instanceof LivingEntity) { ++ LivingEntity entityliving = (LivingEntity) entity; ++ ++ if (!Warden.this.canTargetEntity(entityliving)) { ++ flag = false; ++ return flag; ++ } + } + +- return true; ++ flag = true; ++ return flag; + } else { + return false; + } + } + + @Override +- public void onReceiveVibration( +- ServerLevel level, BlockPos pos, GameEvent gameEvent, @Nullable Entity entity, @Nullable Entity playerEntity, float distance +- ) { ++ public void onReceiveVibration(ServerLevel level, BlockPos pos, GameEvent gameEvent, @Nullable Entity entity, @Nullable Entity playerEntity, float distance) { + if (!Warden.this.isDeadOrDying()) { + Warden.this.brain.setMemoryWithExpiry(MemoryModuleType.VIBRATION_COOLDOWN, Unit.INSTANCE, 40L); +- level.broadcastEntityEvent(Warden.this, (byte)61); ++ level.broadcastEntityEvent(Warden.this, (byte) 61); + Warden.this.playSound(SoundEvents.WARDEN_TENDRIL_CLICKS, 5.0F, Warden.this.getVoicePitch()); +- BlockPos blockPos = pos; ++ BlockPos blockposition1 = pos; ++ + if (playerEntity != null) { +- if (Warden.this.closerThan(playerEntity, 30.0)) { ++ if (Warden.this.closerThan(playerEntity, 30.0D)) { + if (Warden.this.getBrain().hasMemoryValue(MemoryModuleType.RECENT_PROJECTILE)) { + if (Warden.this.canTargetEntity(playerEntity)) { +- blockPos = playerEntity.blockPosition(); ++ blockposition1 = playerEntity.blockPosition(); + } + + Warden.this.increaseAngerAt(playerEntity); +@@ -659,11 +694,13 @@ + } + + if (!Warden.this.getAngerLevel().isAngry()) { +- Optional<LivingEntity> activeEntity = Warden.this.angerManagement.getActiveEntity(); +- if (playerEntity != null || activeEntity.isEmpty() || activeEntity.get() == entity) { +- WardenAi.setDisturbanceLocation(Warden.this, blockPos); ++ Optional<LivingEntity> optional = Warden.this.angerManagement.getActiveEntity(); ++ ++ if (playerEntity != null || optional.isEmpty() || optional.get() == entity) { ++ WardenAi.setDisturbanceLocation(Warden.this, blockposition1); + } + } ++ + } + } + } |