diff --git a/patches/server/0003-Ridables.patch b/patches/server/0003-Ridables.patch index 0b7864734..a5113eeda 100644 --- a/patches/server/0003-Ridables.patch +++ b/patches/server/0003-Ridables.patch @@ -2857,6 +2857,620 @@ index e8c36e8541f041a0d72a86f49ced2a3ce1549be0..1bf65519883585569a1acc780554505d } } // Paper end +diff --git a/src/main/java/net/minecraft/world/entity/monster/Drowned.java b/src/main/java/net/minecraft/world/entity/monster/Drowned.java +index 50228e59d629e75e97d23bd3ec92088f75480827..312543a866b99192401dc7e8662634de3ae4d41b 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Drowned.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Drowned.java +@@ -69,6 +69,18 @@ public class Drowned extends Zombie implements RangedAttackMob { + this.groundNavigation = new GroundPathNavigation(this, world); + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return level.purpurConfig.drownedRidable; ++ } ++ ++ @Override ++ public boolean rideableUnderWater() { ++ return level.purpurConfig.drownedRidableInWater; ++ } ++ // Purpur end ++ + @Override + protected void addBehaviourGoals() { + this.goalSelector.addGoal(1, new Drowned.DrownedGoToWaterGoal(this, 1.0D)); +@@ -378,7 +390,7 @@ public class Drowned extends Zombie implements RangedAttackMob { + } + } + +- static class DrownedMoveControl extends MoveControl { ++ static class DrownedMoveControl extends net.pl3x.purpur.controller.MoveControllerWASD { // Purpur + private final Drowned drowned; + + public DrownedMoveControl(Drowned drowned) { +@@ -387,7 +399,7 @@ public class Drowned extends Zombie implements RangedAttackMob { + } + + @Override +- public void tick() { ++ public void vanillaTick() { // Purpur + LivingEntity livingEntity = this.drowned.getTarget(); + if (this.drowned.wantsToSwim() && this.drowned.isInWater()) { + if (livingEntity != null && livingEntity.getY() > this.drowned.getY() || this.drowned.searchingForLand) { +@@ -416,7 +428,7 @@ public class Drowned extends Zombie implements RangedAttackMob { + this.drowned.setDeltaMovement(this.drowned.getDeltaMovement().add(0.0D, -0.008D, 0.0D)); + } + +- super.tick(); ++ super.vanillaTick(); // Purpur + } + + } +diff --git a/src/main/java/net/minecraft/world/entity/monster/ElderGuardian.java b/src/main/java/net/minecraft/world/entity/monster/ElderGuardian.java +index ee2febe92309f277f1607c0ea024d6cd291490bc..5f8233c1be6f92bcf58c5c5db360b2660c9439ad 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/ElderGuardian.java ++++ b/src/main/java/net/minecraft/world/entity/monster/ElderGuardian.java +@@ -30,6 +30,18 @@ public class ElderGuardian extends Guardian { + + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return level.purpurConfig.elderGuardianRidable; ++ } ++ ++ @Override ++ public boolean rideableUnderWater() { ++ return true; ++ } ++ // Purpur end ++ + public static AttributeSupplier.Builder createAttributes() { + return Guardian.createAttributes().add(Attributes.MOVEMENT_SPEED, 0.30000001192092896D).add(Attributes.ATTACK_DAMAGE, 8.0D).add(Attributes.MAX_HEALTH, 80.0D); + } +diff --git a/src/main/java/net/minecraft/world/entity/monster/EnderMan.java b/src/main/java/net/minecraft/world/entity/monster/EnderMan.java +index a39f4a1585ba888d27588a86130f6dae24f5a71b..a9c247d9c1f1eddd8ef884c0c8d80dee3bb4bf68 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/EnderMan.java ++++ b/src/main/java/net/minecraft/world/entity/monster/EnderMan.java +@@ -83,9 +83,22 @@ public class EnderMan extends Monster implements NeutralMob { + this.setPathfindingMalus(BlockPathTypes.WATER, -1.0F); + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return level.purpurConfig.endermanRidable; ++ } ++ ++ @Override ++ public boolean rideableUnderWater() { ++ return level.purpurConfig.endermanRidableInWater; ++ } ++ // Purpur end ++ + @Override + protected void registerGoals() { + this.goalSelector.addGoal(0, new FloatGoal(this)); ++ this.goalSelector.addGoal(0, new net.pl3x.purpur.entity.ai.HasRider(this)); // Purpur + this.goalSelector.addGoal(1, new EnderMan.EndermanFreezeWhenLookedAt(this)); + this.goalSelector.addGoal(2, new MeleeAttackGoal(this, 1.0D, false)); + this.goalSelector.addGoal(7, new WaterAvoidingRandomStrollGoal(this, 1.0D, 0.0F)); +@@ -93,6 +106,7 @@ public class EnderMan extends Monster implements NeutralMob { + 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(0, new net.pl3x.purpur.entity.ai.HasRider(this)); // Purpur + this.targetSelector.addGoal(1, new EnderMan.EndermanLookForPlayerGoal(this, this::isAngryAt)); + this.targetSelector.addGoal(2, new HurtByTargetGoal(this, new Class[0])); + this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, Endermite.class, true, false)); +@@ -273,7 +287,7 @@ public class EnderMan extends Monster implements NeutralMob { + + @Override + protected void customServerAiStep() { +- if (this.level.isDay() && this.tickCount >= this.targetChangeTime + 600) { ++ if (getRider() == null && this.level.isDay() && this.tickCount >= this.targetChangeTime + 600) { // Purpur - no random teleporting + float f = this.getBrightness(); + + if (f > 0.5F && this.level.canSeeSky(this.blockPosition()) && this.random.nextFloat() * 30.0F < (f - 0.4F) * 2.0F && this.tryEscape(com.destroystokyo.paper.event.entity.EndermanEscapeEvent.Reason.RUNAWAY)) { // Paper +@@ -373,6 +387,7 @@ public class EnderMan extends Monster implements NeutralMob { + public boolean hurt(DamageSource source, float amount) { + if (this.isInvulnerableTo(source)) { + return false; ++ } else if (getRider() != null) { return super.hurt(source, amount); // Purpur - no teleporting on damage + } else if (source instanceof IndirectEntityDamageSource) { + if (this.tryEscape(com.destroystokyo.paper.event.entity.EndermanEscapeEvent.Reason.INDIRECT)) { // Paper start + for (int i = 0; i < 64; ++i) { +diff --git a/src/main/java/net/minecraft/world/entity/monster/Endermite.java b/src/main/java/net/minecraft/world/entity/monster/Endermite.java +index 4aecf69a335c2c6b6457f3b15a1420400878b6e6..1f315cc57f6365a782ca4e645b0dcfbe5485138a 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Endermite.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Endermite.java +@@ -36,13 +36,27 @@ public class Endermite extends Monster { + this.xpReward = 3; + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return level.purpurConfig.endermiteRidable; ++ } ++ ++ @Override ++ public boolean rideableUnderWater() { ++ return level.purpurConfig.endermiteRidableInWater; ++ } ++ // Purpur end ++ + @Override + protected void registerGoals() { + this.goalSelector.addGoal(1, new FloatGoal(this)); ++ this.goalSelector.addGoal(1, new net.pl3x.purpur.entity.ai.HasRider(this)); // Purpur + this.goalSelector.addGoal(2, new MeleeAttackGoal(this, 1.0D, false)); + this.goalSelector.addGoal(3, new WaterAvoidingRandomStrollGoal(this, 1.0D)); + this.goalSelector.addGoal(7, new LookAtPlayerGoal(this, Player.class, 8.0F)); + this.goalSelector.addGoal(8, new RandomLookAroundGoal(this)); ++ this.targetSelector.addGoal(0, new net.pl3x.purpur.entity.ai.HasRider(this)); // Purpur + this.targetSelector.addGoal(1, (new HurtByTargetGoal(this)).setAlertOthers()); + this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, true)); + } +diff --git a/src/main/java/net/minecraft/world/entity/monster/Evoker.java b/src/main/java/net/minecraft/world/entity/monster/Evoker.java +index 4b812fc118126040d773f87ab50047cbbda79d1c..053374baf3ec7730bcddf072ddf98e3176656435 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Evoker.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Evoker.java +@@ -46,10 +46,23 @@ public class Evoker extends SpellcasterIllager { + this.xpReward = 10; + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return level.purpurConfig.evokerRidable; ++ } ++ ++ @Override ++ public boolean rideableUnderWater() { ++ return level.purpurConfig.evokerRidableInWater; ++ } ++ // Purpur end ++ + @Override + protected void registerGoals() { + super.registerGoals(); + this.goalSelector.addGoal(0, new FloatGoal(this)); ++ this.goalSelector.addGoal(0, new net.pl3x.purpur.entity.ai.HasRider(this)); // Purpur + this.goalSelector.addGoal(1, new Evoker.EvokerCastingSpellGoal()); + this.goalSelector.addGoal(2, new AvoidEntityGoal<>(this, Player.class, 8.0F, 0.6D, 1.0D)); + this.goalSelector.addGoal(4, new Evoker.EvokerSummonSpellGoal()); +@@ -58,6 +71,7 @@ public class Evoker extends SpellcasterIllager { + 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(0, new net.pl3x.purpur.entity.ai.HasRider(this)); // Purpur + 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)); +diff --git a/src/main/java/net/minecraft/world/entity/monster/Ghast.java b/src/main/java/net/minecraft/world/entity/monster/Ghast.java +index 886b6eac6c6ae4d97b1b25624504c0f48e20efc4..bb1a6f6847d0e459eb26a029d8a1f5646168a422 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Ghast.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Ghast.java +@@ -44,11 +44,42 @@ public class Ghast extends FlyingMob implements Enemy { + this.moveControl = new Ghast.GhastMoveControl(this); + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return level.purpurConfig.ghastRidable; ++ } ++ ++ @Override ++ public boolean rideableUnderWater() { ++ return level.purpurConfig.ghastRidableInWater; ++ } ++ ++ @Override ++ public double getMaxY() { ++ return level.purpurConfig.ghastMaxY; ++ } ++ ++ @Override ++ public void travel(Vec3 vec3) { ++ super.travel(vec3); ++ if (getRider() != null && !onGround) { ++ float speed = (float) getAttributeValue(Attributes.FLYING_SPEED); ++ setSpeed(speed); ++ Vec3 mot = getDeltaMovement(); ++ move(net.minecraft.world.entity.MoverType.SELF, mot.multiply(speed, 1.0, speed)); ++ setDeltaMovement(mot.scale(0.9D)); ++ } ++ } ++ // Purpur end ++ + @Override + protected void registerGoals() { ++ this.goalSelector.addGoal(0, new net.pl3x.purpur.entity.ai.HasRider(this)); // Purpur + 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(0, new net.pl3x.purpur.entity.ai.HasRider(this)); // Purpur + this.targetSelector.addGoal(1, new NearestAttackableTargetGoal<>(this, Player.class, 10, true, false, (entityliving) -> { + return Math.abs(entityliving.getY() - this.getY()) <= 4.0D; + })); +@@ -90,7 +121,7 @@ public class Ghast extends FlyingMob implements Enemy { + } + + public static AttributeSupplier.Builder createAttributes() { +- return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 10.0D).add(Attributes.FOLLOW_RANGE, 100.0D); ++ return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 10.0D).add(Attributes.FOLLOW_RANGE, 100.0D).add(Attributes.FLYING_SPEED, 0.6D); // Purpur + } + + @Override +@@ -147,7 +178,7 @@ public class Ghast extends FlyingMob implements Enemy { + return 2.6F; + } + +- private static class GhastMoveControl extends MoveControl { ++ private static class GhastMoveControl extends net.pl3x.purpur.controller.FlyingMoveControllerWASD { // Purpur + + private final Ghast ghast; + private int floatDuration; +@@ -158,7 +189,7 @@ public class Ghast extends FlyingMob implements Enemy { + } + + @Override +- public void tick() { ++ public void vanillaTick() { // Purpur + if (this.operation == MoveControl.Operation.MOVE_TO) { + if (this.floatDuration-- <= 0) { + this.floatDuration += this.ghast.getRandom().nextInt(5) + 2; +diff --git a/src/main/java/net/minecraft/world/entity/monster/Giant.java b/src/main/java/net/minecraft/world/entity/monster/Giant.java +index 0d578ab12c874bd2daccc4322a3fe1abafa4bc18..d95b110a025d48e7ab18f172e455593740e45252 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Giant.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Giant.java +@@ -14,6 +14,24 @@ public class Giant extends Monster { + super(type, world); + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return level.purpurConfig.giantRidable; ++ } ++ ++ @Override ++ public boolean rideableUnderWater() { ++ return level.purpurConfig.giantRidableInWater; ++ } ++ ++ @Override ++ protected void registerGoals() { ++ this.goalSelector.addGoal(0, new net.pl3x.purpur.entity.ai.HasRider(this)); ++ this.targetSelector.addGoal(0, new net.pl3x.purpur.entity.ai.HasRider(this)); ++ } ++ // Purpur end ++ + @Override + protected float getStandingEyeHeight(Pose pose, EntityDimensions dimensions) { + return 10.440001F; +diff --git a/src/main/java/net/minecraft/world/entity/monster/Guardian.java b/src/main/java/net/minecraft/world/entity/monster/Guardian.java +index 012e43aa6e2f6e4970257988620ab76d0f75f494..4aaad673f49988be6470b817d42f3fc4e6936400 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Guardian.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Guardian.java +@@ -63,14 +63,35 @@ public class Guardian extends Monster { + this.xpReward = 10; + this.setPathfindingMalus(BlockPathTypes.WATER, 0.0F); + this.moveControl = new Guardian.GuardianMoveControl(this); ++ // Purpur start ++ this.lookControl = new net.pl3x.purpur.controller.LookControllerWASD(this) { ++ @Override ++ public void setYawPitch(float yaw, float pitch) { ++ super.setYawPitch(yaw, pitch * 0.35F); ++ } ++ }; ++ // Purpur end + this.clientSideTailAnimation = this.random.nextFloat(); + this.clientSideTailAnimationO = this.clientSideTailAnimation; + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return level.purpurConfig.guardianRidable; ++ } ++ ++ @Override ++ public boolean rideableUnderWater() { ++ return true; ++ } ++ // Purpur end ++ + @Override + protected void registerGoals() { + MoveTowardsRestrictionGoal moveTowardsRestrictionGoal = new MoveTowardsRestrictionGoal(this, 1.0D); + this.randomStrollGoal = new RandomStrollGoal(this, 1.0D, 80); ++ this.goalSelector.addGoal(0, new net.pl3x.purpur.entity.ai.HasRider(this)); // Purpur + this.goalSelector.addGoal(4, new Guardian.GuardianAttackGoal(this)); + this.goalSelector.addGoal(5, moveTowardsRestrictionGoal); + this.goalSelector.addGoal(7, this.randomStrollGoal); +@@ -79,6 +100,7 @@ public class Guardian extends Monster { + 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.targetSelector.addGoal(0, new net.pl3x.purpur.entity.ai.HasRider(this)); // Purpur + this.targetSelector.addGoal(1, new NearestAttackableTargetGoal<>(this, LivingEntity.class, 10, true, false, new Guardian.GuardianAttackSelector(this))); + } + +@@ -328,7 +350,7 @@ public class Guardian extends Monster { + @Override + public void travel(Vec3 movementInput) { + if (this.isEffectiveAi() && this.isInWater()) { +- this.moveRelative(0.1F, movementInput); ++ this.moveRelative(getRider() != null ? getSpeed() : 0.1F, movementInput); // Purpur + this.move(MoverType.SELF, this.getDeltaMovement()); + this.setDeltaMovement(this.getDeltaMovement().scale(0.9D)); + if (!this.isMoving() && this.getTarget() == null) { +@@ -424,7 +446,7 @@ public class Guardian extends Monster { + } + } + +- static class GuardianMoveControl extends MoveControl { ++ static class GuardianMoveControl extends net.pl3x.purpur.controller.WaterMoveControllerWASD { // Purpur + private final Guardian guardian; + + public GuardianMoveControl(Guardian guardian) { +@@ -432,8 +454,17 @@ public class Guardian extends Monster { + this.guardian = guardian; + } + ++ // Purpur start + @Override +- public void tick() { ++ public void purpurTick(Player rider) { ++ super.purpurTick(rider); ++ guardian.setDeltaMovement(guardian.getDeltaMovement().add(0.0D, 0.005D, 0.0D)); ++ guardian.setMoving(guardian.getForwardMot() > 0.0F); // control tail speed ++ } ++ // Purpur end ++ ++ @Override ++ public void vanillaTick() { // Purpur + 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 d = vec3.length(); +@@ -443,7 +474,7 @@ public class Guardian extends Monster { + float h = (float)(Mth.atan2(vec3.z, vec3.x) * (double)(180F / (float)Math.PI)) - 90.0F; + this.guardian.setYRot(this.rotlerp(this.guardian.getYRot(), h, 90.0F)); + this.guardian.yBodyRot = this.guardian.getYRot(); +- float i = (float)(this.speedModifier * this.guardian.getAttributeValue(Attributes.MOVEMENT_SPEED)); ++ float i = (float)(this.getSpeedModifier() * this.guardian.getAttributeValue(Attributes.MOVEMENT_SPEED)); // Purpur + float j = Mth.lerp(0.125F, this.guardian.getSpeed(), i); + this.guardian.setSpeed(j); + double k = Math.sin((double)(this.guardian.tickCount + this.guardian.getId()) * 0.5D) * 0.05D; +diff --git a/src/main/java/net/minecraft/world/entity/monster/Illusioner.java b/src/main/java/net/minecraft/world/entity/monster/Illusioner.java +index c9fa01b910de7ecb494d3000afebea9a2bd1276a..5f57c14a7ba03af9432a839e6caed47286638b2c 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Illusioner.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Illusioner.java +@@ -59,10 +59,23 @@ public class Illusioner extends SpellcasterIllager implements RangedAttackMob { + + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return level.purpurConfig.illusionerRidable; ++ } ++ ++ @Override ++ public boolean rideableUnderWater() { ++ return level.purpurConfig.illusionerRidableInWater; ++ } ++ // Purpur end ++ + @Override + protected void registerGoals() { + super.registerGoals(); + this.goalSelector.addGoal(0, new FloatGoal(this)); ++ this.goalSelector.addGoal(0, new net.pl3x.purpur.entity.ai.HasRider(this)); // Purpur + this.goalSelector.addGoal(1, new SpellcasterIllager.SpellcasterCastingSpellGoal()); + this.goalSelector.addGoal(4, new Illusioner.IllusionerMirrorSpellGoal()); + this.goalSelector.addGoal(5, new Illusioner.IllusionerBlindnessSpellGoal()); +@@ -70,6 +83,7 @@ public class Illusioner extends SpellcasterIllager implements RangedAttackMob { + 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(0, new net.pl3x.purpur.entity.ai.HasRider(this)); // Purpur + this.targetSelector.addGoal(1, (new HurtByTargetGoal(this, new Class[]{Raider.class})).setAlertOthers(new Class[0])); // CraftBukkit - decompile error + this.targetSelector.addGoal(2, (new NearestAttackableTargetGoal<>(this, Player.class, true)).setUnseenMemoryTicks(300)); + this.targetSelector.addGoal(3, (new NearestAttackableTargetGoal<>(this, AbstractVillager.class, false)).setUnseenMemoryTicks(300)); +diff --git a/src/main/java/net/minecraft/world/entity/monster/MagmaCube.java b/src/main/java/net/minecraft/world/entity/monster/MagmaCube.java +index 130205f0d101debaa74c1172fb80863e6fa0ebe1..7d39f25734f2c52b11931e141524acd2c244c2c5 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/MagmaCube.java ++++ b/src/main/java/net/minecraft/world/entity/monster/MagmaCube.java +@@ -27,6 +27,23 @@ public class MagmaCube extends Slime { + super(type, world); + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return level.purpurConfig.magmaCubeRidable; ++ } ++ ++ @Override ++ public boolean rideableUnderWater() { ++ return level.purpurConfig.magmaCubeRidableInWater; ++ } ++ ++ @Override ++ public float getJumpPower() { ++ return 0.42F * this.getBlockJumpFactor(); // from EntityLiving ++ } ++ // Purpur end ++ + public static AttributeSupplier.Builder createAttributes() { + return Monster.createMonsterAttributes().add(Attributes.MOVEMENT_SPEED, (double)0.2F); + } +@@ -57,7 +74,7 @@ public class MagmaCube extends Slime { + } + + @Override +- protected ResourceLocation getDefaultLootTable() { ++ public ResourceLocation getDefaultLootTable() { // Purpur - decompile fix + return this.isTiny() ? BuiltInLootTables.EMPTY : this.getType().getDefaultLootTable(); + } + +@@ -77,10 +94,11 @@ public class MagmaCube extends Slime { + } + + @Override +- protected void jumpFromGround() { ++ public void jumpFromGround() { // Purpur - protected -> public + Vec3 vec3 = this.getDeltaMovement(); + this.setDeltaMovement(vec3.x, (double)(this.getJumpPower() + (float)this.getSize() * 0.1F), vec3.z); + this.hasImpulse = true; ++ this.actualJump = false; // Purpur + } + + @Override +diff --git a/src/main/java/net/minecraft/world/entity/monster/Phantom.java b/src/main/java/net/minecraft/world/entity/monster/Phantom.java +index 1ffe939bb66358391d92d3e5378865b1cc8690fd..d35e1338c0c11b89e093f8748341ce6980071485 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/Phantom.java ++++ b/src/main/java/net/minecraft/world/entity/monster/Phantom.java +@@ -61,6 +61,59 @@ public class Phantom extends FlyingMob implements Enemy { + this.lookControl = new Phantom.PhantomLookControl(this); + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return level.purpurConfig.phantomRidable; ++ } ++ ++ @Override ++ public boolean rideableUnderWater() { ++ return level.purpurConfig.phantomRidableInWater; ++ } ++ ++ @Override ++ public double getMaxY() { ++ return level.purpurConfig.phantomMaxY; ++ } ++ ++ @Override ++ public void travel(Vec3 vec3) { ++ super.travel(vec3); ++ if (getRider() != null && !onGround) { ++ float speed = (float) getAttributeValue(Attributes.FLYING_SPEED); ++ setSpeed(speed); ++ Vec3 mot = getDeltaMovement(); ++ move(net.minecraft.world.entity.MoverType.SELF, mot.multiply(speed, speed, speed)); ++ setDeltaMovement(mot.scale(0.9D)); ++ } ++ } ++ ++ public static net.minecraft.world.entity.ai.attributes.AttributeSupplier.Builder createAttributes() { ++ return Monster.createMonsterAttributes().add(Attributes.FLYING_SPEED, 3.0D); ++ } ++ ++ @Override ++ public boolean onSpacebar() { ++ if (getRider() != null && getRider().getBukkitEntity().hasPermission("allow.special.phantom")) { ++ shoot(); ++ } ++ return false; ++ } ++ ++ public boolean shoot() { ++ org.bukkit.Location loc = ((org.bukkit.entity.LivingEntity) getBukkitEntity()).getEyeLocation(); ++ loc.setPitch(-loc.getPitch()); ++ org.bukkit.util.Vector target = loc.getDirection().normalize().multiply(100).add(loc.toVector()); ++ ++ net.pl3x.purpur.entity.PhantomFlames flames = new net.pl3x.purpur.entity.PhantomFlames(level, this); ++ flames.canGrief = level.purpurConfig.phantomAllowGriefing; ++ flames.shoot(target.getX() - getX(), target.getY() - getY(), target.getZ() - getZ(), 1.0F, 5.0F); ++ level.addFreshEntity(flames); ++ return true; ++ } ++ // Purpur end ++ + @Override + public boolean isFlapping() { + return (this.getUniqueFlapTickOffset() + this.tickCount) % Phantom.TICKS_PER_FLAP == 0; +@@ -73,9 +126,11 @@ public class Phantom extends FlyingMob implements Enemy { + + @Override + protected void registerGoals() { ++ this.goalSelector.addGoal(0, new net.pl3x.purpur.entity.ai.HasRider(this)); // Purpur + this.goalSelector.addGoal(1, new Phantom.PhantomAttackStrategyGoal()); + this.goalSelector.addGoal(2, new Phantom.PhantomSweepAttackGoal()); + this.goalSelector.addGoal(3, new Phantom.PhantomCircleAroundAnchorGoal()); ++ this.targetSelector.addGoal(0, new net.pl3x.purpur.entity.ai.HasRider(this)); // Purpur + this.targetSelector.addGoal(1, new Phantom.PhantomAttackPlayerTargetGoal()); + } + +@@ -145,7 +200,7 @@ public class Phantom extends FlyingMob implements Enemy { + + @Override + public void aiStep() { +- if (this.isAlive() && shouldBurnInDay && this.isSunBurnTick()) { // Paper - Configurable Burning ++ if (this.isAlive() && getRider() == null && shouldBurnInDay && this.isSunBurnTick()) { // Paper - Configurable Burning // Purpur + this.setSecondsOnFire(8); + } + +@@ -263,7 +318,7 @@ public class Phantom extends FlyingMob implements Enemy { + private AttackPhase() {} + } + +- private class PhantomMoveControl extends MoveControl { ++ private class PhantomMoveControl extends net.pl3x.purpur.controller.FlyingMoveControllerWASD { // Purpur + + private float speed = 0.1F; + +@@ -271,8 +326,19 @@ public class Phantom extends FlyingMob implements Enemy { + super(entity); + } + ++ // Purpur start ++ public void purpurTick(Player rider) { ++ if (!Phantom.this.onGround) { ++ // phantom is always in motion when flying ++ // TODO - FIX THIS ++ // rider.setForward(1.0F); ++ } ++ super.purpurTick(rider); ++ } ++ // Purpur end ++ + @Override +- public void tick() { ++ public void vanillaTick() { // Purpur + if (Phantom.this.horizontalCollision) { + Phantom.this.setYRot(Phantom.this.getYRot() + 180.0F); + this.speed = 0.1F; +@@ -318,14 +384,20 @@ public class Phantom extends FlyingMob implements Enemy { + } + } + +- private class PhantomLookControl extends LookControl { ++ private class PhantomLookControl extends net.pl3x.purpur.controller.LookControllerWASD { // Purpur + + public PhantomLookControl(Mob entity) { + super(entity); + } + ++ // Purpur start ++ public void purpurTick(Player rider) { ++ setYawPitch(rider.yRot, -rider.xRotO * 0.75F); ++ } ++ // Purpur end ++ + @Override +- public void tick() {} ++ public void vanillaTick() {} // Purpur + } + + private class PhantomBodyRotationControl extends BodyRotationControl { diff --git a/src/main/java/net/minecraft/world/entity/monster/Slime.java b/src/main/java/net/minecraft/world/entity/monster/Slime.java index fdc01dee8a81f0376f3c0a154c4291d03ead7f8f..058f4e8729736f9650bb6b08e7aed28f9f78a89b 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Slime.java @@ -2870,6 +3484,29 @@ index fdc01dee8a81f0376f3c0a154c4291d03ead7f8f..058f4e8729736f9650bb6b08e7aed28f Vec3 vec3d = this.getDeltaMovement(); this.setDeltaMovement(vec3d.x, (double) this.getJumpPower(), vec3d.z); +diff --git a/src/main/java/net/minecraft/world/entity/monster/ZombifiedPiglin.java b/src/main/java/net/minecraft/world/entity/monster/ZombifiedPiglin.java +index 233b390541acddcf815db4a8f299496eaea4f758..b86d29a16f4c4ad0b166506fe31e64b902ecc06b 100644 +--- a/src/main/java/net/minecraft/world/entity/monster/ZombifiedPiglin.java ++++ b/src/main/java/net/minecraft/world/entity/monster/ZombifiedPiglin.java +@@ -58,6 +58,18 @@ public class ZombifiedPiglin extends Zombie implements NeutralMob { + this.setPathfindingMalus(BlockPathTypes.LAVA, 8.0F); + } + ++ // Purpur start ++ @Override ++ public boolean isRidable() { ++ return level.purpurConfig.zombifiedPiglinRidable; ++ } ++ ++ @Override ++ public boolean rideableUnderWater() { ++ return level.purpurConfig.zombifiedPiglinRidableInWater; ++ } ++ // Purpur end ++ + @Override + public void setPersistentAngerTarget(@Nullable UUID uuid) { + this.persistentAngerTarget = uuid; diff --git a/src/main/java/net/minecraft/world/entity/player/Player.java b/src/main/java/net/minecraft/world/entity/player/Player.java index d286d88a3c3f93dbfa92de9421e320c92cd96350..b4ebd8d3ad90e51ed953d091610eafe558a3184f 100644 --- a/src/main/java/net/minecraft/world/entity/player/Player.java diff --git a/patches/server/0011-LivingEntity-safeFallDistance.patch b/patches/server/0011-LivingEntity-safeFallDistance.patch index a8a0dbf88..6f95b5582 100644 --- a/patches/server/0011-LivingEntity-safeFallDistance.patch +++ b/patches/server/0011-LivingEntity-safeFallDistance.patch @@ -50,7 +50,7 @@ index 919410ce27e7e42e297c2caba7d3d7c1b623aede..4dcacd1d156309abd29f48b9ac2d4023 protected int getInventorySize() { diff --git a/src/main/java/net/minecraft/world/entity/monster/Giant.java b/src/main/java/net/minecraft/world/entity/monster/Giant.java -index 0d578ab12c874bd2daccc4322a3fe1abafa4bc18..a183226bb0cf01c5aaf7babe1d08fa9ab7388648 100644 +index d95b110a025d48e7ab18f172e455593740e45252..8be06ef6e876219cb8130938fabe7ec6c99cf408 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Giant.java +++ b/src/main/java/net/minecraft/world/entity/monster/Giant.java @@ -12,6 +12,7 @@ import net.minecraft.world.level.LevelReader; @@ -60,7 +60,7 @@ index 0d578ab12c874bd2daccc4322a3fe1abafa4bc18..a183226bb0cf01c5aaf7babe1d08fa9a + this.safeFallDistance = 10.0F; // Purpur } - @Override + // Purpur start diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java index 53b61b609361c305fb8d1f1a8700e81ce139fde4..3e4ad876fa34d0e509fe6331767d31068c4ddb20 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java diff --git a/patches/server/0025-Giants-AI-settings.patch b/patches/server/0025-Giants-AI-settings.patch index e09955f01..b1fba9b7e 100644 --- a/patches/server/0025-Giants-AI-settings.patch +++ b/patches/server/0025-Giants-AI-settings.patch @@ -26,21 +26,22 @@ index 0fc358d5491900affb61545d89a788bbb2435c04..c150a898c60a3477012e7d49e30f98cf return this.brain; } diff --git a/src/main/java/net/minecraft/world/entity/monster/Giant.java b/src/main/java/net/minecraft/world/entity/monster/Giant.java -index a183226bb0cf01c5aaf7babe1d08fa9ab7388648..8f86797cd47b338a599dc053a515e16cb23e56f4 100644 +index 8be06ef6e876219cb8130938fabe7ec6c99cf408..4f0449ed1acdcc85a659973e5c40c6c62868ecf2 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Giant.java +++ b/src/main/java/net/minecraft/world/entity/monster/Giant.java -@@ -1,19 +1,93 @@ +@@ -1,13 +1,36 @@ package net.minecraft.world.entity.monster; import net.minecraft.core.BlockPos; --import net.minecraft.world.entity.EntityDimensions; --import net.minecraft.world.entity.EntityType; --import net.minecraft.world.entity.Pose; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.Difficulty; +import net.minecraft.world.DifficultyInstance; -+import net.minecraft.world.entity.*; -+import net.minecraft.world.entity.ai.attributes.AttributeModifier; + import net.minecraft.world.entity.EntityDimensions; + import net.minecraft.world.entity.EntityType; ++import net.minecraft.world.entity.EquipmentSlot; ++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.entity.ai.goal.FloatGoal; @@ -65,22 +66,22 @@ index a183226bb0cf01c5aaf7babe1d08fa9ab7388648..8f86797cd47b338a599dc053a515e16c public class Giant extends Monster { public Giant(EntityType type, Level world) { - super(type, world); - this.safeFallDistance = 10.0F; // Purpur -+ maxUpStep = world.purpurConfig.giantStepHeight; -+ } -+ -+ // Purpur start -+ @Override -+ protected void registerGoals() { +@@ -28,8 +51,56 @@ public class Giant extends Monster { + + @Override + protected void registerGoals() { +- this.goalSelector.addGoal(0, new net.pl3x.purpur.entity.ai.HasRider(this)); +- this.targetSelector.addGoal(0, new net.pl3x.purpur.entity.ai.HasRider(this)); + if (level.purpurConfig.giantHaveAI) { + this.goalSelector.addGoal(0, new FloatGoal(this)); ++ this.goalSelector.addGoal(0, new net.pl3x.purpur.entity.ai.HasRider(this)); + this.goalSelector.addGoal(7, new WaterAvoidingRandomStrollGoal(this, 1.0D)); + this.goalSelector.addGoal(8, new LookAtPlayerGoal(this, Player.class, 16.0F)); + this.goalSelector.addGoal(8, new RandomLookAroundGoal(this)); + this.goalSelector.addGoal(5, new MoveTowardsRestrictionGoal(this, 1.0D)); + if (level.purpurConfig.giantHaveHostileAI) { + this.goalSelector.addGoal(2, new MeleeAttackGoal(this, 1.0D, false)); ++ this.targetSelector.addGoal(0, new net.pl3x.purpur.entity.ai.HasRider(this)); + this.targetSelector.addGoal(1, new HurtByTargetGoal(this).setAlertOthers(ZombifiedPiglin.class)); + this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, true)); + this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, Villager.class, false)); @@ -122,11 +123,9 @@ index a183226bb0cf01c5aaf7babe1d08fa9ab7388648..8f86797cd47b338a599dc053a515e16c + // 1.0 makes bottom of feet about as high as their waist when they jump + return level.purpurConfig.giantJumpHeight; } -+ // Purpur end + // Purpur end - @Override - protected float getStandingEyeHeight(Pose pose, EntityDimensions dimensions) { -@@ -26,6 +100,6 @@ public class Giant extends Monster { +@@ -44,6 +115,6 @@ public class Giant extends Monster { @Override public float getWalkTargetValue(BlockPos pos, LevelReader world) { @@ -135,7 +134,7 @@ index a183226bb0cf01c5aaf7babe1d08fa9ab7388648..8f86797cd47b338a599dc053a515e16c } } diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 148cc428b17e0db46a86079bf4e2199b52f1ad84..3f92159deba19bb7257d920ec3b1f31c0e2bcf87 100644 +index cee4c24b792c31e35c3d84fc3d435b3ebe1642cf..2d9319d3fcf3a52f404a44e38bb6a71de5ab7ef0 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -261,9 +261,28 @@ public class PurpurWorldConfig { diff --git a/patches/server/0026-Illusioners-AI-settings.patch b/patches/server/0026-Illusioners-AI-settings.patch index 778654b2a..698df2c24 100644 --- a/patches/server/0026-Illusioners-AI-settings.patch +++ b/patches/server/0026-Illusioners-AI-settings.patch @@ -5,27 +5,25 @@ Subject: [PATCH] Illusioners AI settings diff --git a/src/main/java/net/minecraft/world/entity/monster/Illusioner.java b/src/main/java/net/minecraft/world/entity/monster/Illusioner.java -index c9fa01b910de7ecb494d3000afebea9a2bd1276a..c3ba23ed30d2e46a8e66d239ce02618780a803b1 100644 +index 5f57c14a7ba03af9432a839e6caed47286638b2c..c4c239ab51c48a2b9c12e547dc7e125955911794 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Illusioner.java +++ b/src/main/java/net/minecraft/world/entity/monster/Illusioner.java -@@ -59,6 +59,15 @@ public class Illusioner extends SpellcasterIllager implements RangedAttackMob { - +@@ -69,6 +69,13 @@ public class Illusioner extends SpellcasterIllager implements RangedAttackMob { + public boolean rideableUnderWater() { + return level.purpurConfig.illusionerRidableInWater; } - -+ // Purpur start ++ + @Override + protected void initAttributes() { + this.getAttribute(Attributes.MOVEMENT_SPEED).setBaseValue(this.level.purpurConfig.illusionerMovementSpeed); + this.getAttribute(Attributes.FOLLOW_RANGE).setBaseValue(this.level.purpurConfig.illusionerFollowRange); + this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(this.level.purpurConfig.illusionerMaxHealth); + } -+ // Purpur end -+ + // Purpur end + @Override - protected void registerGoals() { - super.registerGoals(); diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 3f92159deba19bb7257d920ec3b1f31c0e2bcf87..6790836b719bbab7c5ab8ead6efd9723b4f58cd1 100644 +index 2d9319d3fcf3a52f404a44e38bb6a71de5ab7ef0..983ad996bef9f05772f176357ab3f78fd330f8f4 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -323,9 +323,20 @@ public class PurpurWorldConfig { diff --git a/patches/server/0057-Add-enderman-and-creeper-griefing-controls.patch b/patches/server/0057-Add-enderman-and-creeper-griefing-controls.patch index 428e8263a..c3618a9ec 100644 --- a/patches/server/0057-Add-enderman-and-creeper-griefing-controls.patch +++ b/patches/server/0057-Add-enderman-and-creeper-griefing-controls.patch @@ -18,10 +18,10 @@ index f8fba694d53356036e302f66cfe92b15726242dc..72edd66a7e0b46b9575982210d8c9af0 // CraftBukkit start diff --git a/src/main/java/net/minecraft/world/entity/monster/EnderMan.java b/src/main/java/net/minecraft/world/entity/monster/EnderMan.java -index a39f4a1585ba888d27588a86130f6dae24f5a71b..b9cc542db0b5b9f7710c2f747cb9a4edc1feb70a 100644 +index a9c247d9c1f1eddd8ef884c0c8d80dee3bb4bf68..b774647be64884e3334db2b395bf21e948494c80 100644 --- a/src/main/java/net/minecraft/world/entity/monster/EnderMan.java +++ b/src/main/java/net/minecraft/world/entity/monster/EnderMan.java -@@ -454,6 +454,7 @@ public class EnderMan extends Monster implements NeutralMob { +@@ -469,6 +469,7 @@ public class EnderMan extends Monster implements NeutralMob { @Override public boolean canUse() { @@ -29,7 +29,7 @@ index a39f4a1585ba888d27588a86130f6dae24f5a71b..b9cc542db0b5b9f7710c2f747cb9a4ed return this.enderman.getCarriedBlock() == null ? false : (!this.enderman.level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) ? false : this.enderman.getRandom().nextInt(2000) == 0); } -@@ -501,6 +502,7 @@ public class EnderMan extends Monster implements NeutralMob { +@@ -516,6 +517,7 @@ public class EnderMan extends Monster implements NeutralMob { @Override public boolean canUse() { diff --git a/patches/server/0075-Configurable-jockey-options.patch b/patches/server/0075-Configurable-jockey-options.patch index 3d8aeeb96..b7e3f81f5 100644 --- a/patches/server/0075-Configurable-jockey-options.patch +++ b/patches/server/0075-Configurable-jockey-options.patch @@ -5,15 +5,14 @@ Subject: [PATCH] Configurable jockey options diff --git a/src/main/java/net/minecraft/world/entity/monster/Drowned.java b/src/main/java/net/minecraft/world/entity/monster/Drowned.java -index 50228e59d629e75e97d23bd3ec92088f75480827..2758a312a002d8752d79fd297bc25853621c2171 100644 +index 312543a866b99192401dc7e8662634de3ae4d41b..ab7a6c7c0893b6737cfb3204f8fbfef7fd1e94c3 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Drowned.java +++ b/src/main/java/net/minecraft/world/entity/monster/Drowned.java -@@ -69,6 +69,23 @@ public class Drowned extends Zombie implements RangedAttackMob { - this.groundNavigation = new GroundPathNavigation(this, world); +@@ -79,6 +79,20 @@ public class Drowned extends Zombie implements RangedAttackMob { + public boolean rideableUnderWater() { + return level.purpurConfig.drownedRidableInWater; } - -+ // Purpur start -+ @Override ++ + public boolean jockeyOnlyBaby() { + return level.purpurConfig.drownedJockeyOnlyBaby; + } @@ -27,11 +26,9 @@ index 50228e59d629e75e97d23bd3ec92088f75480827..2758a312a002d8752d79fd297bc25853 + public boolean jockeyTryExistingChickens() { + return level.purpurConfig.drownedJockeyTryExistingChickens; + } -+ // Purpur end -+ + // Purpur end + @Override - protected void addBehaviourGoals() { - this.goalSelector.addGoal(1, new Drowned.DrownedGoToWaterGoal(this, 1.0D)); diff --git a/src/main/java/net/minecraft/world/entity/monster/Husk.java b/src/main/java/net/minecraft/world/entity/monster/Husk.java index 28fb67c0a5992cbd77c5d3c6efa0f0493466d81c..26ce4223cdb00acf7aa21f14c4ea6e426692b536 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Husk.java @@ -156,15 +153,14 @@ index a2fbab27980d7f52033fd542220d534cefcc4747..c4a653f9b593654a831905ba5f39c412 protected void defineSynchedData() { super.defineSynchedData(); diff --git a/src/main/java/net/minecraft/world/entity/monster/ZombifiedPiglin.java b/src/main/java/net/minecraft/world/entity/monster/ZombifiedPiglin.java -index 233b390541acddcf815db4a8f299496eaea4f758..a50191aac887dffd3a7930455cb222fa0dc4e91a 100644 +index b86d29a16f4c4ad0b166506fe31e64b902ecc06b..dd5e29a9981d490d8ef54cc580fbbde831f86bf8 100644 --- a/src/main/java/net/minecraft/world/entity/monster/ZombifiedPiglin.java +++ b/src/main/java/net/minecraft/world/entity/monster/ZombifiedPiglin.java -@@ -58,6 +58,23 @@ public class ZombifiedPiglin extends Zombie implements NeutralMob { - this.setPathfindingMalus(BlockPathTypes.LAVA, 8.0F); +@@ -68,6 +68,20 @@ public class ZombifiedPiglin extends Zombie implements NeutralMob { + public boolean rideableUnderWater() { + return level.purpurConfig.zombifiedPiglinRidableInWater; } - -+ // Purpur start -+ @Override ++ + public boolean jockeyOnlyBaby() { + return level.purpurConfig.zombifiedPiglinJockeyOnlyBaby; + } @@ -178,11 +174,9 @@ index 233b390541acddcf815db4a8f299496eaea4f758..a50191aac887dffd3a7930455cb222fa + public boolean jockeyTryExistingChickens() { + return level.purpurConfig.zombifiedPiglinJockeyTryExistingChickens; + } -+ // Purpur end -+ + // Purpur end + @Override - public void setPersistentAngerTarget(@Nullable UUID uuid) { - this.persistentAngerTarget = uuid; diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java index 0453764a9b47e3997aa32cda489e7f71d94b7e04..87f9ad516e8dd0c92b08c9054e086d8315c87c41 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java diff --git a/patches/server/0076-Phantoms-attracted-to-crystals-and-crystals-shoot-ph.patch b/patches/server/0076-Phantoms-attracted-to-crystals-and-crystals-shoot-ph.patch index f5e001fe5..1402b9c1b 100644 --- a/patches/server/0076-Phantoms-attracted-to-crystals-and-crystals-shoot-ph.patch +++ b/patches/server/0076-Phantoms-attracted-to-crystals-and-crystals-shoot-ph.patch @@ -5,23 +5,15 @@ Subject: [PATCH] Phantoms attracted to crystals and crystals shoot phantoms diff --git a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EndCrystal.java b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EndCrystal.java -index b643a2449e329560c936c0a06fb4cc494d0737a7..c90c46e08bb3d664465b01616ae80c133bc3f733 100644 +index b643a2449e329560c936c0a06fb4cc494d0737a7..92e65f3fbc8f5d77bb8cc31e7a7780c2589f4227 100644 --- a/src/main/java/net/minecraft/world/entity/boss/enderdragon/EndCrystal.java +++ b/src/main/java/net/minecraft/world/entity/boss/enderdragon/EndCrystal.java -@@ -14,6 +14,7 @@ import net.minecraft.server.level.ServerLevel; - import net.minecraft.world.damagesource.DamageSource; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.EntityType; -+import net.minecraft.world.entity.monster.Phantom; - import net.minecraft.world.item.ItemStack; - import net.minecraft.world.item.Items; - import net.minecraft.world.level.BlockGetter; -@@ -32,6 +33,12 @@ public class EndCrystal extends Entity { +@@ -32,6 +32,12 @@ public class EndCrystal extends Entity { private static final EntityDataAccessor DATA_SHOW_BOTTOM = SynchedEntityData.defineId(EndCrystal.class, EntityDataSerializers.BOOLEAN); public int time; public boolean generatedByDragonFight = false; // Paper - Fix invulnerable end crystals + // Purpur start -+ private Phantom targetPhantom; ++ private net.minecraft.world.entity.monster.Phantom targetPhantom; + private int phantomBeamTicks = 0; + private int phantomDamageCooldown = 0; + private int idleCooldown = 0; @@ -29,7 +21,7 @@ index b643a2449e329560c936c0a06fb4cc494d0737a7..c90c46e08bb3d664465b01616ae80c13 public EndCrystal(EntityType type, Level world) { super(type, world); -@@ -81,7 +88,50 @@ public class EndCrystal extends Entity { +@@ -81,7 +87,50 @@ public class EndCrystal extends Entity { // Paper end } @@ -39,7 +31,7 @@ index b643a2449e329560c936c0a06fb4cc494d0737a7..c90c46e08bb3d664465b01616ae80c13 + } + + if (targetPhantom == null) { -+ for (Phantom phantom : level.getEntitiesOfClass(Phantom.class, getBoundingBox().inflate(level.purpurConfig.phantomAttackedByCrystalRadius))) { ++ for (net.minecraft.world.entity.monster.Phantom phantom : level.getEntitiesOfClass(net.minecraft.world.entity.monster.Phantom.class, getBoundingBox().inflate(level.purpurConfig.phantomAttackedByCrystalRadius))) { + if (phantom.hasLineOfSight(this)) { + attackPhantom(phantom); + break; @@ -63,7 +55,7 @@ index b643a2449e329560c936c0a06fb4cc494d0737a7..c90c46e08bb3d664465b01616ae80c13 + } + } + -+ private void attackPhantom(Phantom phantom) { ++ private void attackPhantom(net.minecraft.world.entity.monster.Phantom phantom) { + phantomDamageCooldown = 0; + phantomBeamTicks = 60; + targetPhantom = phantom; @@ -81,34 +73,10 @@ index b643a2449e329560c936c0a06fb4cc494d0737a7..c90c46e08bb3d664465b01616ae80c13 @Override protected void addAdditionalSaveData(CompoundTag nbt) { diff --git a/src/main/java/net/minecraft/world/entity/monster/Phantom.java b/src/main/java/net/minecraft/world/entity/monster/Phantom.java -index 1ffe939bb66358391d92d3e5378865b1cc8690fd..6058fb62baa388febc8e36cb680ab2ddcd1306f4 100644 +index d35e1338c0c11b89e093f8748341ce6980071485..7ba080b98abf1c83647065f4a75257b66c6a352c 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Phantom.java +++ b/src/main/java/net/minecraft/world/entity/monster/Phantom.java -@@ -12,6 +12,7 @@ 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.sounds.SoundSource; -@@ -36,10 +37,15 @@ import net.minecraft.world.entity.ai.control.MoveControl; - import net.minecraft.world.entity.ai.goal.Goal; - import net.minecraft.world.entity.ai.targeting.TargetingConditions; - import net.minecraft.world.entity.animal.Cat; -+import net.minecraft.world.entity.boss.enderdragon.EndCrystal; - import net.minecraft.world.entity.player.Player; -+import net.minecraft.world.item.ItemStack; -+import net.minecraft.world.item.Items; - import net.minecraft.world.level.Level; - import net.minecraft.world.level.ServerLevelAccessor; - import net.minecraft.world.level.levelgen.Heightmap; -+import net.minecraft.world.level.storage.loot.LootContext; -+import net.minecraft.world.level.storage.loot.parameters.LootContextParams; - import net.minecraft.world.phys.Vec3; - - public class Phantom extends FlyingMob implements Enemy { -@@ -50,6 +56,7 @@ public class Phantom extends FlyingMob implements Enemy { +@@ -50,6 +50,7 @@ public class Phantom extends FlyingMob implements Enemy { Vec3 moveTargetPoint; BlockPos anchorPoint; Phantom.AttackPhase attackPhase; @@ -116,14 +84,42 @@ index 1ffe939bb66358391d92d3e5378865b1cc8690fd..6058fb62baa388febc8e36cb680ab2dd public Phantom(EntityType type, Level world) { super(type, world); -@@ -73,12 +80,38 @@ public class Phantom extends FlyingMob implements Enemy { +@@ -112,6 +113,24 @@ public class Phantom extends FlyingMob implements Enemy { + level.addFreshEntity(flames); + return true; + } ++ ++ @Override ++ protected net.minecraft.world.level.storage.loot.LootContext.Builder createLootContext(boolean causedByPlayer, DamageSource source) { ++ boolean dropped = false; ++ if (lastHurtByPlayer == null && source.getEntity() instanceof net.minecraft.world.entity.boss.enderdragon.EndCrystal) { ++ if (random.nextInt(5) < 1) { ++ dropped = spawnAtLocation(new net.minecraft.world.item.ItemStack(net.minecraft.world.item.Items.PHANTOM_MEMBRANE)) != null; ++ } ++ } ++ if (!dropped) { ++ return super.createLootContext(causedByPlayer, source); ++ } ++ return new net.minecraft.world.level.storage.loot.LootContext.Builder((net.minecraft.server.level.ServerLevel) level); ++ } ++ ++ public boolean isCirclingCrystal() { ++ return crystalPosition != null; ++ } + // Purpur end + + @Override +@@ -126,11 +145,17 @@ public class Phantom extends FlyingMob implements Enemy { @Override protected void registerGoals() { +- this.goalSelector.addGoal(0, new net.pl3x.purpur.entity.ai.HasRider(this)); // Purpur - this.goalSelector.addGoal(1, new Phantom.PhantomAttackStrategyGoal()); - this.goalSelector.addGoal(2, new Phantom.PhantomSweepAttackGoal()); - this.goalSelector.addGoal(3, new Phantom.PhantomCircleAroundAnchorGoal()); +- this.targetSelector.addGoal(0, new net.pl3x.purpur.entity.ai.HasRider(this)); // Purpur + // Purpur start ++ this.goalSelector.addGoal(0, new net.pl3x.purpur.entity.ai.HasRider(this)); + if (level.purpurConfig.phantomOrbitCrystalRadius > 0) { + this.goalSelector.addGoal(1, new FindCrystalGoal(this)); + this.goalSelector.addGoal(2, new OrbitCrystalGoal(this)); @@ -131,42 +127,20 @@ index 1ffe939bb66358391d92d3e5378865b1cc8690fd..6058fb62baa388febc8e36cb680ab2dd + this.goalSelector.addGoal(3, new Phantom.PhantomAttackStrategyGoal()); + this.goalSelector.addGoal(4, new Phantom.PhantomSweepAttackGoal()); + this.goalSelector.addGoal(5, new Phantom.PhantomCircleAroundAnchorGoal()); - this.targetSelector.addGoal(1, new Phantom.PhantomAttackPlayerTargetGoal()); ++ this.targetSelector.addGoal(0, new net.pl3x.purpur.entity.ai.HasRider(this)); + // Purpur end + this.targetSelector.addGoal(1, new Phantom.PhantomAttackPlayerTargetGoal()); } -+ // Purpur start -+ @Override -+ protected LootContext.Builder createLootContext(boolean causedByPlayer, DamageSource source) { -+ boolean dropped = false; -+ if (lastHurtByPlayer == null && source.getEntity() instanceof EndCrystal) { -+ if (random.nextInt(5) < 1) { -+ dropped = spawnAtLocation(new ItemStack(Items.PHANTOM_MEMBRANE)) != null; -+ } -+ } -+ if (!dropped) { -+ return super.createLootContext(causedByPlayer, source); -+ } -+ return new LootContext.Builder((ServerLevel) level); -+ } -+ -+ public boolean isCirclingCrystal() { -+ return crystalPosition != null; -+ } -+ // Purpur end -+ - @Override - protected void defineSynchedData() { - super.defineSynchedData(); -@@ -263,6 +296,124 @@ public class Phantom extends FlyingMob implements Enemy { +@@ -318,6 +343,124 @@ public class Phantom extends FlyingMob implements Enemy { private AttackPhase() {} } + // Purpur start + class FindCrystalGoal extends Goal { + private final Phantom phantom; -+ private EndCrystal crystal; -+ private Comparator comparator; ++ private net.minecraft.world.entity.boss.enderdragon.EndCrystal crystal; ++ private Comparator comparator; + + FindCrystalGoal(Phantom phantom) { + this.phantom = phantom; @@ -177,7 +151,7 @@ index 1ffe939bb66358391d92d3e5378865b1cc8690fd..6058fb62baa388febc8e36cb680ab2dd + @Override + public boolean shouldActivate() { + double range = maxTargetRange(); -+ List crystals = level.getEntitiesOfClass(EndCrystal.class, phantom.getBoundingBox().inflate(range)); ++ List crystals = level.getEntitiesOfClass(net.minecraft.world.entity.boss.enderdragon.EndCrystal.class, phantom.getBoundingBox().inflate(range)); + if (crystals.isEmpty()) { + return false; + } @@ -280,35 +254,11 @@ index 1ffe939bb66358391d92d3e5378865b1cc8690fd..6058fb62baa388febc8e36cb680ab2dd + } + // Purpur end + - private class PhantomMoveControl extends MoveControl { + private class PhantomMoveControl extends net.pl3x.purpur.controller.FlyingMoveControllerWASD { // Purpur private float speed = 0.1F; -@@ -349,6 +500,7 @@ public class Phantom extends FlyingMob implements Enemy { - - @Override - public boolean canUse() { -+ if (isCirclingCrystal()) return false; - LivingEntity entityliving = Phantom.this.getTarget(); - - return entityliving != null ? Phantom.this.canAttack(Phantom.this.getTarget(), TargetingConditions.DEFAULT) : false; -@@ -538,6 +690,7 @@ public class Phantom extends FlyingMob implements Enemy { - - @Override - public boolean canUse() { -+ if (isCirclingCrystal()) return false; - if (this.nextScanTick > 0) { - --this.nextScanTick; - return false; -@@ -566,6 +719,7 @@ public class Phantom extends FlyingMob implements Enemy { - - @Override - public boolean canContinueToUse() { -+ if (isCirclingCrystal()) return false; - LivingEntity entityliving = Phantom.this.getTarget(); - - return entityliving != null ? Phantom.this.canAttack(entityliving, TargetingConditions.DEFAULT) : false; diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index e39e1ff19f49b093ae27a98cba280ad2643df7a2..8985cc0ca2e5f1f673ef6ae59976095993332559 100644 +index 87f9ad516e8dd0c92b08c9054e086d8315c87c41..e48fe5334e82a1c91acde2ec23584fc92f97923c 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -617,6 +617,9 @@ public class PurpurWorldConfig { diff --git a/patches/server/0087-Phantoms-burn-in-light.patch b/patches/server/0087-Phantoms-burn-in-light.patch index 46791dd02..e42db5c8a 100644 --- a/patches/server/0087-Phantoms-burn-in-light.patch +++ b/patches/server/0087-Phantoms-burn-in-light.patch @@ -5,64 +5,49 @@ Subject: [PATCH] Phantoms burn in light diff --git a/src/main/java/net/minecraft/world/entity/monster/Phantom.java b/src/main/java/net/minecraft/world/entity/monster/Phantom.java -index 6058fb62baa388febc8e36cb680ab2ddcd1306f4..f68b4e3db39934c6b8334a1049025b3c1b3af5e2 100644 +index 7ba080b98abf1c83647065f4a75257b66c6a352c..17150611d36d41fd75b3a3dffd7b000330885b0e 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Phantom.java +++ b/src/main/java/net/minecraft/world/entity/monster/Phantom.java -@@ -18,6 +18,7 @@ import net.minecraft.sounds.SoundEvents; - import net.minecraft.sounds.SoundSource; - import net.minecraft.util.Mth; - import net.minecraft.world.DifficultyInstance; -+import net.minecraft.world.InteractionHand; - import net.minecraft.world.damagesource.DamageSource; - import net.minecraft.world.entity.Entity; - import net.minecraft.world.entity.EntityDimensions; -@@ -41,6 +42,7 @@ import net.minecraft.world.entity.boss.enderdragon.EndCrystal; - import net.minecraft.world.entity.player.Player; - import net.minecraft.world.item.ItemStack; - import net.minecraft.world.item.Items; -+import net.minecraft.world.item.crafting.Ingredient; - import net.minecraft.world.level.Level; - import net.minecraft.world.level.ServerLevelAccessor; - import net.minecraft.world.level.levelgen.Heightmap; -@@ -57,6 +59,7 @@ public class Phantom extends FlyingMob implements Enemy { +@@ -51,6 +51,7 @@ public class Phantom extends FlyingMob implements Enemy { BlockPos anchorPoint; Phantom.AttackPhase attackPhase; Vec3 crystalPosition; // Purpur -+ private static final Ingredient TORCH = Ingredient.of(Items.TORCH, Items.SOUL_TORCH); // Purpur ++ private static final net.minecraft.world.item.crafting.Ingredient TORCH = net.minecraft.world.item.crafting.Ingredient.of(net.minecraft.world.item.Items.TORCH, net.minecraft.world.item.Items.SOUL_TORCH); // Purpur public Phantom(EntityType type, Level world) { super(type, world); -@@ -178,7 +181,7 @@ public class Phantom extends FlyingMob implements Enemy { +@@ -225,7 +226,7 @@ public class Phantom extends FlyingMob implements Enemy { @Override public void aiStep() { -- if (this.isAlive() && shouldBurnInDay && this.isSunBurnTick()) { // Paper - Configurable Burning -+ if (this.isAlive() && (((shouldBurnInDay || level.purpurConfig.phantomBurnInDaylight) && this.isSunBurnTick()) || (level.purpurConfig.phantomBurnInLight > 0 && level.getLightEmission(new BlockPos(this)) >= level.purpurConfig.phantomBurnInLight))) { // Paper - Configurable Burning // Purpur +- if (this.isAlive() && getRider() == null && shouldBurnInDay && this.isSunBurnTick()) { // Paper - Configurable Burning // Purpur ++ if (this.isAlive() && getRider() == null && (((shouldBurnInDay || level.purpurConfig.phantomBurnInDaylight) && this.isSunBurnTick()) || (level.purpurConfig.phantomBurnInLight > 0 && level.getLightEmission(new BlockPos(this)) >= level.purpurConfig.phantomBurnInLight))) { // Paper - Configurable Burning // Purpur this.setSecondsOnFire(8); } -@@ -560,6 +563,11 @@ public class Phantom extends FlyingMob implements Enemy { +@@ -623,6 +624,12 @@ public class Phantom extends FlyingMob implements Enemy { return false; } else if (!entityliving.isAlive()) { return false; + // Purpur start + } else if (level.purpurConfig.phantomBurnInLight > 0 && level.getLightEmission(new BlockPos(Phantom.this)) >= level.purpurConfig.phantomBurnInLight) { + return false; -+ } else if (level.purpurConfig.phantomIgnorePlayersWithTorch && (TORCH.test(entityliving.getItemInHand(InteractionHand.MAIN_HAND)) || TORCH.test(entityliving.getItemInHand(InteractionHand.OFF_HAND)))) { ++ } else if (level.purpurConfig.phantomIgnorePlayersWithTorch && (TORCH.test(entityliving.getItemInHand(net.minecraft.world.InteractionHand.MAIN_HAND)) || TORCH.test(entityliving.getItemInHand(net.minecraft.world.InteractionHand.OFF_HAND)))) { + return false; ++ // Purpur end } else if (entityliving instanceof Player && (((Player) entityliving).isSpectator() || ((Player) entityliving).isCreative())) { return false; } else if (!this.canUse()) { -@@ -698,6 +706,7 @@ public class Phantom extends FlyingMob implements Enemy { +@@ -760,6 +767,7 @@ public class Phantom extends FlyingMob implements Enemy { this.nextScanTick = 60; List list = Phantom.this.level.getNearbyPlayers(this.attackTargeting, (LivingEntity) Phantom.this, Phantom.this.getBoundingBox().inflate(16.0D, 64.0D, 16.0D)); -+ if (level.purpurConfig.phantomIgnorePlayersWithTorch) list.removeIf(human -> TORCH.test(human.getItemInHand(InteractionHand.MAIN_HAND)) || TORCH.test(human.getItemInHand(InteractionHand.OFF_HAND)));// Purpur ++ if (level.purpurConfig.phantomIgnorePlayersWithTorch) list.removeIf(human -> TORCH.test(human.getItemInHand(net.minecraft.world.InteractionHand.MAIN_HAND)) || TORCH.test(human.getItemInHand(net.minecraft.world.InteractionHand.OFF_HAND)));// Purpur if (!list.isEmpty()) { list.sort(Comparator.comparing(Entity::getY).reversed()); // Paper - decomp fix Iterator iterator = list.iterator(); diff --git a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java -index 9dd7b62e3b9c7f6590c9b79f5c206d36adbe4cd6..9d054fb175a80874869f630d6e15122530270661 100644 +index a99389784c48191606a9b0f5a63fbecb204164d0..52a52a50be91d09a4241e14812f26c9113bc0e12 100644 --- a/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java +++ b/src/main/java/net/pl3x/purpur/PurpurWorldConfig.java @@ -676,6 +676,9 @@ public class PurpurWorldConfig { diff --git a/patches/server/0097-Short-enderman-height.patch b/patches/server/0097-Short-enderman-height.patch index 1d620f1a1..df215c36f 100644 --- a/patches/server/0097-Short-enderman-height.patch +++ b/patches/server/0097-Short-enderman-height.patch @@ -19,13 +19,13 @@ index 63e3105daeb697ff76cca15d55d14b14ca1523f6..368f6fb3697a57a96f5677bd69d2ae3d private static EntityType register(String id, EntityType.Builder type) { // CraftBukkit - decompile error return (EntityType) Registry.register((Registry) Registry.ENTITY_TYPE, id, (Object) type.build(id)); diff --git a/src/main/java/net/minecraft/world/entity/monster/EnderMan.java b/src/main/java/net/minecraft/world/entity/monster/EnderMan.java -index b9cc542db0b5b9f7710c2f747cb9a4edc1feb70a..a66964d574d799f739349b823eb6bce552181ec7 100644 +index b774647be64884e3334db2b395bf21e948494c80..ca3fcb86695f3d01b1fff5d0bb1d6e16dea39a11 100644 --- a/src/main/java/net/minecraft/world/entity/monster/EnderMan.java +++ b/src/main/java/net/minecraft/world/entity/monster/EnderMan.java -@@ -373,6 +373,7 @@ public class EnderMan extends Monster implements NeutralMob { - public boolean hurt(DamageSource source, float amount) { +@@ -388,6 +388,7 @@ public class EnderMan extends Monster implements NeutralMob { if (this.isInvulnerableTo(source)) { return false; + } else if (getRider() != null) { return super.hurt(source, amount); // Purpur - no teleporting on damage + } else if (net.pl3x.purpur.PurpurConfig.endermanShortHeight && source == DamageSource.IN_WALL) { return false; // Purpur - no suffocation damage if short height } else if (source instanceof IndirectEntityDamageSource) { if (this.tryEscape(com.destroystokyo.paper.event.entity.EndermanEscapeEvent.Reason.INDIRECT)) { // Paper start diff --git a/patches/server/0107-Add-option-to-disable-zombie-aggressiveness-towards-.patch b/patches/server/0107-Add-option-to-disable-zombie-aggressiveness-towards-.patch index ea80d354d..c4f702858 100644 --- a/patches/server/0107-Add-option-to-disable-zombie-aggressiveness-towards-.patch +++ b/patches/server/0107-Add-option-to-disable-zombie-aggressiveness-towards-.patch @@ -21,10 +21,10 @@ index dfc026d183adab1dde5942f36e7a281b3a2fc699..589f4fafeb4600e9923499c87d5f6232 ignored.add("goal_selector_1"); ignored.add("goal_selector_2"); diff --git a/src/main/java/net/minecraft/world/entity/monster/Drowned.java b/src/main/java/net/minecraft/world/entity/monster/Drowned.java -index 2758a312a002d8752d79fd297bc25853621c2171..03f697ae4e53e85093504e175655e465f6fff58a 100644 +index ab7a6c7c0893b6737cfb3204f8fbfef7fd1e94c3..df5be208c2f58faea3c1989f4344f67fac2fcf67 100644 --- a/src/main/java/net/minecraft/world/entity/monster/Drowned.java +++ b/src/main/java/net/minecraft/world/entity/monster/Drowned.java -@@ -96,7 +96,19 @@ public class Drowned extends Zombie implements RangedAttackMob { +@@ -105,7 +105,19 @@ public class Drowned extends Zombie implements RangedAttackMob { this.goalSelector.addGoal(7, new RandomStrollGoal(this, 1.0D)); this.targetSelector.addGoal(1, (new HurtByTargetGoal(this, Drowned.class)).setAlertOthers(ZombifiedPiglin.class)); this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, 10, true, false, this::okTarget));