diff --git a/nms-patches/net/minecraft/world/level/dimension/end/EnderDragonBattle.patch b/nms-patches/net/minecraft/world/level/dimension/end/EnderDragonBattle.patch new file mode 100644 index 000000000..92fd71697 --- /dev/null +++ b/nms-patches/net/minecraft/world/level/dimension/end/EnderDragonBattle.patch @@ -0,0 +1,63 @@ +--- a/net/minecraft/world/level/dimension/end/EnderDragonBattle.java ++++ b/net/minecraft/world/level/dimension/end/EnderDragonBattle.java +@@ -110,14 +110,14 @@ + this.origin = blockposition; + this.validPlayer = IEntitySelector.ENTITY_STILL_ALIVE.and(IEntitySelector.withinDistance((double) blockposition.getX(), (double) (128 + blockposition.getY()), (double) blockposition.getZ(), 192.0D)); + this.needsStateScanning = enderdragonbattle_a.needsStateScanning; +- this.dragonUUID = (UUID) enderdragonbattle_a.dragonUUID.orElse((Object) null); ++ this.dragonUUID = (UUID) enderdragonbattle_a.dragonUUID.orElse(null); // CraftBukkit - decompile error + this.dragonKilled = enderdragonbattle_a.dragonKilled; + this.previouslyKilled = enderdragonbattle_a.previouslyKilled; + if (enderdragonbattle_a.isRespawning) { + this.respawnStage = EnumDragonRespawn.START; + } + +- this.portalLocation = (BlockPosition) enderdragonbattle_a.exitPortalLocation.orElse((Object) null); ++ this.portalLocation = (BlockPosition) enderdragonbattle_a.exitPortalLocation.orElse(null); // CraftBukkit - decompile error + this.gateways.addAll((Collection) enderdragonbattle_a.gateways.orElseGet(() -> { + ObjectArrayList objectarraylist = new ObjectArrayList(ContiguousSet.create(Range.closedOpen(0, 20), DiscreteDomain.integers())); + +@@ -505,7 +505,7 @@ + return this.previouslyKilled; + } + +- public void tryRespawn() { ++ public boolean tryRespawn() { // CraftBukkit - return boolean + if (this.dragonKilled && this.respawnStage == null) { + BlockPosition blockposition = this.portalLocation; + +@@ -532,19 +532,19 @@ + List list1 = this.level.getEntitiesOfClass(EntityEnderCrystal.class, new AxisAlignedBB(blockposition1.relative(enumdirection, 2))); + + if (list1.isEmpty()) { +- return; ++ return false; // CraftBukkit - return value + } + + list.addAll(list1); + } + + EnderDragonBattle.LOGGER.debug("Found all crystals, respawning dragon."); +- this.respawnDragon(list); ++ return this.respawnDragon(list); // CraftBukkit - return value + } +- ++ return false; // CraftBukkit - return value + } + +- private void respawnDragon(List list) { ++ public boolean respawnDragon(List list) { // PAIL private -> public // CraftBukkit - return boolean + if (this.dragonKilled && this.respawnStage == null) { + for (ShapeDetector.ShapeDetectorCollection shapedetector_shapedetectorcollection = this.findExitPortal(); shapedetector_shapedetectorcollection != null; shapedetector_shapedetectorcollection = this.findExitPortal()) { + for (int i = 0; i < this.exitPortalPattern.getWidth(); ++i) { +@@ -564,8 +564,9 @@ + this.respawnTime = 0; + this.spawnExitPortal(false); + this.respawnCrystals = list; ++ return true; // CraftBukkit - return value + } +- ++ return false; // CraftBukkit - return value + } + + public void resetSpikeCrystals() { diff --git a/src/main/java/org/bukkit/craftbukkit/boss/CraftDragonBattle.java b/src/main/java/org/bukkit/craftbukkit/boss/CraftDragonBattle.java index e5867224b..c5269942e 100644 --- a/src/main/java/org/bukkit/craftbukkit/boss/CraftDragonBattle.java +++ b/src/main/java/org/bukkit/craftbukkit/boss/CraftDragonBattle.java @@ -1,14 +1,22 @@ package org.bukkit.craftbukkit.boss; import com.google.common.base.Preconditions; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.stream.Collectors; import net.minecraft.world.entity.Entity; +import net.minecraft.world.level.block.state.pattern.ShapeDetector; import net.minecraft.world.level.dimension.end.EnderDragonBattle; import net.minecraft.world.level.dimension.end.EnumDragonRespawn; import org.bukkit.Location; +import org.bukkit.World; import org.bukkit.boss.BossBar; import org.bukkit.boss.DragonBattle; -import org.bukkit.boss.DragonBattle.RespawnPhase; +import org.bukkit.craftbukkit.CraftWorld; +import org.bukkit.craftbukkit.entity.CraftEnderCrystal; import org.bukkit.craftbukkit.util.CraftLocation; +import org.bukkit.entity.EnderCrystal; import org.bukkit.entity.EnderDragon; public class CraftDragonBattle implements DragonBattle { @@ -59,6 +67,32 @@ public class CraftDragonBattle implements DragonBattle { this.handle.tryRespawn(); } + @Override + public boolean initiateRespawn(Collection list) { + if (hasBeenPreviouslyKilled() && getRespawnPhase() == RespawnPhase.NONE) { + // Copy from EnderDragonBattle#tryRespawn for generate exit portal if not exists + if (this.handle.portalLocation == null) { + ShapeDetector.ShapeDetectorCollection shapedetector_shapedetectorcollection = this.handle.findExitPortal(); + if (shapedetector_shapedetectorcollection == null) { + this.handle.spawnExitPortal(true); + } + } + + list = (list != null) ? new ArrayList<>(list) : Collections.emptyList(); + list.removeIf(enderCrystal -> { + if (enderCrystal == null) { + return true; + } + + World world = enderCrystal.getWorld(); + return !((CraftWorld) world).getHandle().equals(handle.level); + }); + + return this.handle.respawnDragon(list.stream().map(enderCrystal -> ((CraftEnderCrystal) enderCrystal).getHandle()).collect(Collectors.toList())); + } + return false; + } + @Override public RespawnPhase getRespawnPhase() { return toBukkitRespawnPhase(handle.respawnStage);