1.21.5
Co-authored-by: Bjarne Koll <git@lynxplay.dev> Co-authored-by: Jake Potrebic <jake.m.potrebic@gmail.com> Co-authored-by: Lulu13022002 <41980282+Lulu13022002@users.noreply.github.com> Co-authored-by: MiniDigger | Martin <admin@minidigger.dev> Co-authored-by: Nassim Jahnke <nassim@njahnke.dev> Co-authored-by: Noah van der Aa <ndvdaa@gmail.com> Co-authored-by: Owen1212055 <23108066+Owen1212055@users.noreply.github.com> Co-authored-by: Shane Freeder <theboyetronic@gmail.com> Co-authored-by: Spottedleaf <Spottedleaf@users.noreply.github.com> Co-authored-by: Tamion <70228790+notTamion@users.noreply.github.com> Co-authored-by: Warrior <50800980+Warriorrrr@users.noreply.github.com>
This commit is contained in:
@@ -1,14 +1,14 @@
|
||||
--- a/net/minecraft/world/entity/boss/enderdragon/EndCrystal.java
|
||||
+++ b/net/minecraft/world/entity/boss/enderdragon/EndCrystal.java
|
||||
@@ -25,6 +_,7 @@
|
||||
);
|
||||
private static final EntityDataAccessor<Boolean> DATA_SHOW_BOTTOM = SynchedEntityData.defineId(EndCrystal.class, EntityDataSerializers.BOOLEAN);
|
||||
private static final boolean DEFAULT_SHOW_BOTTOM = true;
|
||||
public int time;
|
||||
+ public boolean generatedByDragonFight = false; // Paper - Fix invulnerable end crystals
|
||||
|
||||
public EndCrystal(EntityType<? extends EndCrystal> entityType, Level level) {
|
||||
super(entityType, level);
|
||||
@@ -56,9 +_,23 @@
|
||||
@@ -56,21 +_,37 @@
|
||||
if (this.level() instanceof ServerLevel) {
|
||||
BlockPos blockPos = this.blockPosition();
|
||||
if (((ServerLevel)this.level()).getDragonFight() != null && this.level().getBlockState(blockPos).isAir()) {
|
||||
@@ -22,7 +22,7 @@
|
||||
+
|
||||
+ // Paper start - Fix invulnerable end crystals
|
||||
+ if (this.level().paperConfig().unsupportedSettings.fixInvulnerableEndCrystalExploit && this.generatedByDragonFight && this.isInvulnerable()) {
|
||||
+ if (!java.util.Objects.equals(((ServerLevel) this.level()).uuid, this.getOriginWorld())
|
||||
+ if (!java.util.Objects.equals(((ServerLevel) this.level()).uuid, this.originWorld)
|
||||
+ || ((ServerLevel) this.level()).getDragonFight() == null
|
||||
+ || ((ServerLevel) this.level()).getDragonFight().respawnStage == null
|
||||
+ || ((ServerLevel) this.level()).getDragonFight().respawnStage.ordinal() > net.minecraft.world.level.dimension.end.DragonRespawnAnimation.SUMMONING_DRAGON.ordinal()) {
|
||||
@@ -34,23 +34,21 @@
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -68,6 +_,7 @@
|
||||
}
|
||||
|
||||
protected void addAdditionalSaveData(CompoundTag compound) {
|
||||
compound.storeNullable("beam_target", BlockPos.CODEC, this.getBeamTarget());
|
||||
compound.putBoolean("ShowBottom", this.showsBottom());
|
||||
+ if (this.generatedByDragonFight) compound.putBoolean("Paper.GeneratedByDragonFight", this.generatedByDragonFight); // Paper - Fix invulnerable end crystals
|
||||
+ compound.putBoolean("Paper.GeneratedByDragonFight", this.generatedByDragonFight); // Paper - Fix invulnerable end crystals
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -76,6 +_,7 @@
|
||||
if (compound.contains("ShowBottom", 1)) {
|
||||
this.setShowBottom(compound.getBoolean("ShowBottom"));
|
||||
}
|
||||
+ if (compound.contains("Paper.GeneratedByDragonFight", 1)) this.generatedByDragonFight = compound.getBoolean("Paper.GeneratedByDragonFight"); // Paper - Fix invulnerable end crystals
|
||||
protected void readAdditionalSaveData(CompoundTag compound) {
|
||||
this.setBeamTarget(compound.read("beam_target", BlockPos.CODEC).orElse(null));
|
||||
this.setShowBottom(compound.getBooleanOr("ShowBottom", true));
|
||||
+ this.generatedByDragonFight = compound.getBooleanOr("Paper.GeneratedByDragonFight", false); // Paper - Fix invulnerable end crystals
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -96,10 +_,24 @@
|
||||
@@ -91,10 +_,24 @@
|
||||
return false;
|
||||
} else {
|
||||
if (!this.isRemoved()) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java
|
||||
+++ b/net/minecraft/world/entity/boss/enderdragon/EnderDragon.java
|
||||
@@ -86,6 +_,10 @@
|
||||
@@ -87,6 +_,10 @@
|
||||
private final Node[] nodes = new Node[24];
|
||||
private final int[] nodeAdjacency = new int[24];
|
||||
private final BinaryHeap openSet = new BinaryHeap();
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
public EnderDragon(EntityType<? extends EnderDragon> entityType, Level level) {
|
||||
super(EntityType.ENDER_DRAGON, level);
|
||||
@@ -101,6 +_,7 @@
|
||||
@@ -102,6 +_,7 @@
|
||||
this.setHealth(this.getMaxHealth());
|
||||
this.noPhysics = true;
|
||||
this.phaseManager = new EnderDragonPhaseManager(this);
|
||||
@@ -19,7 +19,7 @@
|
||||
}
|
||||
|
||||
public void setDragonFight(EndDragonFight dragonFight) {
|
||||
@@ -119,6 +_,19 @@
|
||||
@@ -120,6 +_,19 @@
|
||||
return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 200.0);
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
@Override
|
||||
public boolean isFlapping() {
|
||||
float cos = Mth.cos(this.flapTime * (float) (Math.PI * 2));
|
||||
@@ -210,7 +_,7 @@
|
||||
@@ -211,7 +_,7 @@
|
||||
}
|
||||
|
||||
Vec3 flyTargetLocation = currentPhase.getFlyTargetLocation();
|
||||
@@ -48,7 +48,7 @@
|
||||
double d = flyTargetLocation.x - this.getX();
|
||||
double d1 = flyTargetLocation.y - this.getY();
|
||||
double d2 = flyTargetLocation.z - this.getZ();
|
||||
@@ -369,7 +_,12 @@
|
||||
@@ -366,7 +_,12 @@
|
||||
if (this.nearestCrystal.isRemoved()) {
|
||||
this.nearestCrystal = null;
|
||||
} else if (this.tickCount % 10 == 0 && this.getHealth() < this.getMaxHealth()) {
|
||||
@@ -62,7 +62,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -400,7 +_,7 @@
|
||||
@@ -396,7 +_,7 @@
|
||||
double d2 = entity.getX() - d;
|
||||
double d3 = entity.getZ() - d1;
|
||||
double max = Math.max(d2 * d2 + d3 * d3, 0.1);
|
||||
@@ -71,7 +71,7 @@
|
||||
if (!this.phaseManager.getCurrentPhase().isSitting() && livingEntity.getLastHurtByMobTimestamp() < entity.tickCount - 2) {
|
||||
DamageSource damageSource = this.damageSources().mobAttack(this);
|
||||
entity.hurtServer(level, damageSource, 5.0F);
|
||||
@@ -433,6 +_,7 @@
|
||||
@@ -429,6 +_,7 @@
|
||||
int floor5 = Mth.floor(box.maxZ);
|
||||
boolean flag = false;
|
||||
boolean flag1 = false;
|
||||
@@ -79,7 +79,7 @@
|
||||
|
||||
for (int i = floor; i <= floor3; i++) {
|
||||
for (int i1 = floor1; i1 <= floor4; i1++) {
|
||||
@@ -441,7 +_,11 @@
|
||||
@@ -437,7 +_,11 @@
|
||||
BlockState blockState = level.getBlockState(blockPos);
|
||||
if (!blockState.isAir() && !blockState.is(BlockTags.DRAGON_TRANSPARENT)) {
|
||||
if (level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) && !blockState.is(BlockTags.DRAGON_IMMUNE)) {
|
||||
@@ -92,7 +92,7 @@
|
||||
} else {
|
||||
flag = true;
|
||||
}
|
||||
@@ -450,6 +_,58 @@
|
||||
@@ -446,6 +_,58 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,7 +151,7 @@
|
||||
if (flag1) {
|
||||
BlockPos blockPos1 = new BlockPos(
|
||||
floor + this.random.nextInt(floor3 - floor + 1),
|
||||
@@ -507,7 +_,15 @@
|
||||
@@ -503,7 +_,15 @@
|
||||
|
||||
@Override
|
||||
public void kill(ServerLevel level) {
|
||||
@@ -168,7 +168,7 @@
|
||||
this.gameEvent(GameEvent.ENTITY_DIE);
|
||||
if (this.dragonFight != null) {
|
||||
this.dragonFight.updateDragon(this);
|
||||
@@ -529,18 +_,41 @@
|
||||
@@ -525,18 +_,41 @@
|
||||
this.level().addParticle(ParticleTypes.EXPLOSION_EMITTER, this.getX() + f, this.getY() + 2.0 + f1, this.getZ() + f2, 0.0, 0.0, 0.0);
|
||||
}
|
||||
|
||||
@@ -186,7 +186,7 @@
|
||||
- if (this.dragonDeathTime > 150 && this.dragonDeathTime % 5 == 0 && serverLevel.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) {
|
||||
- ExperienceOrb.award(serverLevel, this.position(), Mth.floor(i * 0.08F));
|
||||
+ if (this.dragonDeathTime > 150 && this.dragonDeathTime % 5 == 0) { // CraftBukkit - SPIGOT-2420: Already checked for the game rule when calculating the xp
|
||||
+ ExperienceOrb.award(serverLevel, this.position(), Mth.floor(i * 0.08F), org.bukkit.entity.ExperienceOrb.SpawnReason.ENTITY_DEATH, this.lastHurtByPlayer, this); // Paper
|
||||
+ ExperienceOrb.award(serverLevel, this.position(), Mth.floor(i * 0.08F), org.bukkit.entity.ExperienceOrb.SpawnReason.ENTITY_DEATH, net.minecraft.Optionull.map(this.lastHurtByPlayer, lastHurtByPlayer -> lastHurtByPlayer.getEntity(this.level(), Player.class)), this); // Paper
|
||||
}
|
||||
|
||||
if (this.dragonDeathTime == 1 && !this.isSilent()) {
|
||||
@@ -213,14 +213,14 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -553,15 +_,15 @@
|
||||
@@ -549,15 +_,15 @@
|
||||
}
|
||||
|
||||
if (this.dragonDeathTime == 200 && this.level() instanceof ServerLevel serverLevel1) {
|
||||
- if (serverLevel1.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) {
|
||||
- ExperienceOrb.award(serverLevel1, this.position(), Mth.floor(i * 0.2F));
|
||||
+ if (true) { // Paper - SPIGOT-2420: Already checked for the game rule when calculating the xp
|
||||
+ ExperienceOrb.award(serverLevel1, this.position(), Mth.floor(i * 0.2F), org.bukkit.entity.ExperienceOrb.SpawnReason.ENTITY_DEATH, this.lastHurtByPlayer, this); // Paper
|
||||
+ ExperienceOrb.award(serverLevel1, this.position(), Mth.floor(i * 0.2F), org.bukkit.entity.ExperienceOrb.SpawnReason.ENTITY_DEATH, net.minecraft.Optionull.map(this.lastHurtByPlayer, lastHurtByPlayer -> lastHurtByPlayer.getEntity(this.level(), Player.class)), this); // Paper
|
||||
}
|
||||
|
||||
if (this.dragonFight != null) {
|
||||
@@ -232,7 +232,7 @@
|
||||
this.gameEvent(GameEvent.ENTITY_DIE);
|
||||
}
|
||||
}
|
||||
@@ -743,6 +_,7 @@
|
||||
@@ -739,6 +_,7 @@
|
||||
super.addAdditionalSaveData(compound);
|
||||
compound.putInt("DragonPhase", this.phaseManager.getCurrentPhase().getPhase().getId());
|
||||
compound.putInt("DragonDeathTime", this.dragonDeathTime);
|
||||
@@ -240,20 +240,15 @@
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -755,6 +_,12 @@
|
||||
if (compound.contains("DragonDeathTime")) {
|
||||
this.dragonDeathTime = compound.getInt("DragonDeathTime");
|
||||
}
|
||||
+
|
||||
+ // CraftBukkit start - SPIGOT-2420: The ender dragon drops xp over time which can also happen between server starts
|
||||
+ if (compound.contains("Bukkit.expToDrop")) {
|
||||
+ this.expToDrop = compound.getInt("Bukkit.expToDrop");
|
||||
+ }
|
||||
+ // CraftBukkit end
|
||||
@@ -746,6 +_,7 @@
|
||||
super.readAdditionalSaveData(compound);
|
||||
compound.getInt("DragonPhase").ifPresent(integer -> this.phaseManager.setPhase(EnderDragonPhase.getById(integer)));
|
||||
this.dragonDeathTime = compound.getIntOr("DragonDeathTime", 0);
|
||||
+ this.expToDrop = compound.getIntOr("Bukkit.expToDrop", 0); // CraftBukkit - SPIGOT-2420: The ender dragon drops xp over time which can also happen between server starts
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -795,7 +_,7 @@
|
||||
@@ -786,7 +_,7 @@
|
||||
EnderDragonPhase<? extends DragonPhaseInstance> phase = currentPhase.getPhase();
|
||||
Vec3 viewVector;
|
||||
if (phase == EnderDragonPhase.LANDING || phase == EnderDragonPhase.TAKEOFF) {
|
||||
@@ -262,16 +257,16 @@
|
||||
float max = Math.max((float)Math.sqrt(heightmapPos.distToCenterSqr(this.position())) / 4.0F, 1.0F);
|
||||
float f = 6.0F / max;
|
||||
float xRot = this.getXRot();
|
||||
@@ -883,4 +_,19 @@
|
||||
@@ -874,4 +_,19 @@
|
||||
protected float sanitizeScale(float scale) {
|
||||
return 1.0F;
|
||||
}
|
||||
+
|
||||
+ // CraftBukkit start - SPIGOT-2420: Special case, the ender dragon drops 12000 xp for the first kill and 500 xp for every other kill and this over time.
|
||||
+ @Override
|
||||
+ public int getExpReward(ServerLevel worldserver, Entity entity) {
|
||||
+ public int getExpReward(ServerLevel level, Entity entity) {
|
||||
+ // CraftBukkit - Moved from #tickDeath method
|
||||
+ boolean flag = worldserver.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT);
|
||||
+ boolean flag = level.getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT);
|
||||
+ int i = 500;
|
||||
+
|
||||
+ if (this.dragonFight != null && !this.dragonFight.hasPreviouslyKilledDragon()) {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
--- a/net/minecraft/world/entity/boss/enderdragon/phases/DragonSittingFlamingPhase.java
|
||||
+++ b/net/minecraft/world/entity/boss/enderdragon/phases/DragonSittingFlamingPhase.java
|
||||
@@ -82,7 +_,13 @@
|
||||
this.flame.setDuration(200);
|
||||
@@ -83,7 +_,13 @@
|
||||
this.flame.setParticle(ParticleTypes.DRAGON_BREATH);
|
||||
this.flame.addEffect(new MobEffectInstance(MobEffects.HARM));
|
||||
this.flame.setPotionDurationScale(0.25F);
|
||||
this.flame.addEffect(new MobEffectInstance(MobEffects.INSTANT_DAMAGE));
|
||||
+ if (new com.destroystokyo.paper.event.entity.EnderDragonFlameEvent((org.bukkit.entity.EnderDragon) this.dragon.getBukkitEntity(), (org.bukkit.entity.AreaEffectCloud) this.flame.getBukkitEntity()).callEvent()) { // Paper - EnderDragon Events
|
||||
level.addFreshEntity(this.flame);
|
||||
+ // Paper start - EnderDragon Events
|
||||
@@ -14,7 +14,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,7 +_,7 @@
|
||||
@@ -96,7 +_,7 @@
|
||||
@Override
|
||||
public void end() {
|
||||
if (this.flame != null) {
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
DragonFireball dragonFireball = new DragonFireball(level, this.dragon, vec32.normalize());
|
||||
+ dragonFireball.preserveMotion = true; // Paper - Fix Entity Teleportation and cancel velocity if teleported
|
||||
dragonFireball.moveTo(d2, d3, d4, 0.0F, 0.0F);
|
||||
dragonFireball.snapTo(d2, d3, d4, 0.0F, 0.0F);
|
||||
+ if (new com.destroystokyo.paper.event.entity.EnderDragonShootFireballEvent((org.bukkit.entity.EnderDragon) this.dragon.getBukkitEntity(), (org.bukkit.entity.DragonFireball) dragonFireball.getBukkitEntity()).callEvent()) // Paper - EnderDragon Events
|
||||
level.addFreshEntity(dragonFireball);
|
||||
+ else dragonFireball.discard(null); // Paper - EnderDragon Events
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- a/net/minecraft/world/entity/boss/wither/WitherBoss.java
|
||||
+++ b/net/minecraft/world/entity/boss/wither/WitherBoss.java
|
||||
@@ -69,6 +_,7 @@
|
||||
@@ -70,6 +_,7 @@
|
||||
private final int[] nextHeadUpdate = new int[2];
|
||||
private final int[] idleHeadUpdates = new int[2];
|
||||
private int destroyBlocksTick;
|
||||
@@ -8,7 +8,7 @@
|
||||
public final ServerBossEvent bossEvent = (ServerBossEvent)new ServerBossEvent(
|
||||
this.getDisplayName(), BossEvent.BossBarColor.PURPLE, BossEvent.BossBarOverlay.PROGRESS
|
||||
)
|
||||
@@ -260,15 +_,40 @@
|
||||
@@ -261,15 +_,40 @@
|
||||
int i = this.getInvulnerableTicks() - 1;
|
||||
this.bossEvent.setProgress(1.0F - i / 220.0F);
|
||||
if (i <= 0) {
|
||||
@@ -52,7 +52,7 @@
|
||||
}
|
||||
} else {
|
||||
super.customServerAiStep(level);
|
||||
@@ -305,6 +_,7 @@
|
||||
@@ -306,6 +_,7 @@
|
||||
);
|
||||
if (!nearbyEntities.isEmpty()) {
|
||||
LivingEntity livingEntity1 = nearbyEntities.get(this.random.nextInt(nearbyEntities.size()));
|
||||
@@ -60,7 +60,7 @@
|
||||
this.setAlternativeTarget(ix, livingEntity1.getId());
|
||||
}
|
||||
}
|
||||
@@ -334,6 +_,11 @@
|
||||
@@ -335,6 +_,11 @@
|
||||
)) {
|
||||
BlockState blockState = level.getBlockState(blockPos);
|
||||
if (canDestroy(blockState)) {
|
||||
@@ -72,7 +72,7 @@
|
||||
flag = level.destroyBlock(blockPos, true, this) || flag;
|
||||
}
|
||||
}
|
||||
@@ -345,7 +_,7 @@
|
||||
@@ -346,7 +_,7 @@
|
||||
}
|
||||
|
||||
if (this.tickCount % 20 == 0) {
|
||||
@@ -81,7 +81,7 @@
|
||||
}
|
||||
|
||||
this.bossEvent.setProgress(this.getHealth() / this.getMaxHealth());
|
||||
@@ -483,16 +_,16 @@
|
||||
@@ -484,16 +_,16 @@
|
||||
@Override
|
||||
protected void dropCustomDeathLoot(ServerLevel level, DamageSource damageSource, boolean recentlyHit) {
|
||||
super.dropCustomDeathLoot(level, damageSource, recentlyHit);
|
||||
@@ -101,7 +101,7 @@
|
||||
} else {
|
||||
this.noActionTime = 0;
|
||||
}
|
||||
@@ -547,12 +_,18 @@
|
||||
@@ -548,12 +_,18 @@
|
||||
|
||||
@Override
|
||||
public boolean canUsePortal(boolean allowPassengers) {
|
||||
|
||||
Reference in New Issue
Block a user