diff --git a/paper-server/patches/sources/net/minecraft/world/item/EndCrystalItem.java.patch b/paper-server/patches/sources/net/minecraft/world/item/EndCrystalItem.java.patch index ba84da3813..89844fdef2 100644 --- a/paper-server/patches/sources/net/minecraft/world/item/EndCrystalItem.java.patch +++ b/paper-server/patches/sources/net/minecraft/world/item/EndCrystalItem.java.patch @@ -1,6 +1,15 @@ --- a/net/minecraft/world/item/EndCrystalItem.java +++ b/net/minecraft/world/item/EndCrystalItem.java -@@ -47,6 +47,12 @@ +@@ -30,7 +30,7 @@ + if (!iblockdata.is(Blocks.OBSIDIAN) && !iblockdata.is(Blocks.BEDROCK)) { + return InteractionResult.FAIL; + } else { +- BlockPos blockposition1 = blockposition.above(); ++ BlockPos blockposition1 = blockposition.above(); final BlockPos aboveBlockPosition = blockposition1; // Paper - OBFHELPER + + if (!world.isEmptyBlock(blockposition1)) { + return InteractionResult.FAIL; +@@ -47,12 +47,18 @@ EndCrystal entityendercrystal = new EndCrystal(world, d0 + 0.5D, d1, d2 + 0.5D); entityendercrystal.setShowBottom(false); @@ -13,3 +22,10 @@ world.addFreshEntity(entityendercrystal); world.gameEvent((Entity) context.getPlayer(), (Holder) GameEvent.ENTITY_PLACE, blockposition1); EndDragonFight enderdragonbattle = ((ServerLevel) world).getDragonFight(); + + if (enderdragonbattle != null) { +- enderdragonbattle.tryRespawn(); ++ enderdragonbattle.tryRespawn(aboveBlockPosition); // Paper - Perf: Do crystal-portal proximity check before entity lookup + } + } + diff --git a/paper-server/patches/sources/net/minecraft/world/level/dimension/end/EndDragonFight.java.patch b/paper-server/patches/sources/net/minecraft/world/level/dimension/end/EndDragonFight.java.patch index b0ef43a495..5514be96df 100644 --- a/paper-server/patches/sources/net/minecraft/world/level/dimension/end/EndDragonFight.java.patch +++ b/paper-server/patches/sources/net/minecraft/world/level/dimension/end/EndDragonFight.java.patch @@ -78,7 +78,7 @@ this.previouslyKilled = true; this.dragonKilled = true; -@@ -419,8 +440,26 @@ +@@ -419,7 +440,25 @@ @VisibleForTesting public void removeAllGateways() { this.gateways.clear(); @@ -91,20 +91,19 @@ + return true; + } + return false; - } - ++ } ++ + public List<EndCrystal> getSpikeCrystals() { + final List<EndCrystal> endCrystals = new java.util.ArrayList<>(); + for (final SpikeFeature.EndSpike spike : SpikeFeature.getSpikesForLevel(this.level)) { + endCrystals.addAll(this.level.getEntitiesOfClass(EndCrystal.class, spike.getTopBoundingBox())); + } + return endCrystals; -+ } + } + // Paper end - More DragonBattle API -+ + private void spawnNewGateway() { if (!this.gateways.isEmpty()) { - int i = (Integer) this.gateways.remove(this.gateways.size() - 1); @@ -449,6 +488,11 @@ } } @@ -136,16 +135,45 @@ } } -@@ -513,7 +562,7 @@ +@@ -513,7 +562,13 @@ return this.previouslyKilled; } - public void tryRespawn() { + public boolean tryRespawn() { // CraftBukkit - return boolean ++ // Paper start - Perf: Do crystal-portal proximity check before entity lookup ++ return this.tryRespawn(null); ++ } ++ ++ public boolean tryRespawn(@Nullable BlockPos placedEndCrystalPos) { // placedEndCrystalPos is null if the tryRespawn() call was not caused by a placed end crystal ++ // Paper end - Perf: Do crystal-portal proximity check before entity lookup if (this.dragonKilled && this.respawnStage == null) { BlockPos blockposition = this.portalLocation; -@@ -540,19 +589,19 @@ +@@ -531,6 +586,22 @@ + blockposition = this.portalLocation; + } + ++ // Paper start - Perf: Do crystal-portal proximity check before entity lookup ++ if (placedEndCrystalPos != null) { ++ // The end crystal must be 0 or 1 higher than the portal origin ++ int dy = placedEndCrystalPos.getY() - blockposition.getY(); ++ if (dy != 0 && dy != 1) { ++ return false; ++ } ++ // The end crystal must be within a distance of 1 in one planar direction, and 3 in the other ++ int dx = placedEndCrystalPos.getX() - blockposition.getX(); ++ int dz = placedEndCrystalPos.getZ() - blockposition.getZ(); ++ if (!((dx >= -1 && dx <= 1 && dz >= -3 && dz <= 3) || (dx >= -3 && dx <= 3 && dz >= -1 && dz <= 1))) { ++ return false; ++ } ++ } ++ // Paper end - Perf: Do crystal-portal proximity check before entity lookup ++ + List<EndCrystal> list = Lists.newArrayList(); + BlockPos blockposition1 = blockposition.above(1); + Iterator iterator = Direction.Plane.HORIZONTAL.iterator(); +@@ -540,19 +611,19 @@ List<EndCrystal> list1 = this.level.getEntitiesOfClass(EndCrystal.class, new AABB(blockposition1.relative(enumdirection, 2))); if (list1.isEmpty()) { @@ -169,7 +197,7 @@ if (this.dragonKilled && this.respawnStage == null) { for (BlockPattern.BlockPatternMatch shapedetector_shapedetectorcollection = this.findExitPortal(); shapedetector_shapedetectorcollection != null; shapedetector_shapedetectorcollection = this.findExitPortal()) { for (int i = 0; i < this.exitPortalPattern.getWidth(); ++i) { -@@ -571,9 +620,10 @@ +@@ -571,9 +642,10 @@ this.respawnStage = DragonRespawnAnimation.START; this.respawnTime = 0; this.spawnExitPortal(false);