From fc318cc10e26c66b36551a2d2562cecdb7410849 Mon Sep 17 00:00:00 2001 From: Parker Hawke Date: Tue, 24 Mar 2020 19:53:47 +1100 Subject: [PATCH] #642: Add a DragonBattle API to manipulate respawn phases etc --- nms-patches/EnderDragonBattle.patch | 52 ++++++++++++ .../org/bukkit/craftbukkit/CraftWorld.java | 14 +++ .../craftbukkit/boss/CraftDragonBattle.java | 85 +++++++++++++++++++ .../craftbukkit/entity/CraftEnderDragon.java | 20 +++-- 4 files changed, 164 insertions(+), 7 deletions(-) create mode 100644 nms-patches/EnderDragonBattle.patch create mode 100644 src/main/java/org/bukkit/craftbukkit/boss/CraftDragonBattle.java diff --git a/nms-patches/EnderDragonBattle.patch b/nms-patches/EnderDragonBattle.patch new file mode 100644 index 0000000000..0290ce9830 --- /dev/null +++ b/nms-patches/EnderDragonBattle.patch @@ -0,0 +1,52 @@ +--- a/net/minecraft/server/EnderDragonBattle.java ++++ b/net/minecraft/server/EnderDragonBattle.java +@@ -21,7 +21,7 @@ + private static final Logger LOGGER = LogManager.getLogger(); + private static final Predicate b = IEntitySelector.a.and(IEntitySelector.a(0.0D, 128.0D, 0.0D, 192.0D)); + public final BossBattleServer bossBattle; +- private final WorldServer d; ++ public final WorldServer d; // CraftBukkit PAIL private -> public, rename world + private final List e; + private final ShapeDetector f; + private int g; +@@ -30,10 +30,10 @@ + private int j; + private boolean k; + private boolean l; +- private UUID m; ++ public UUID m; // CraftBukkit PAIL private -> public, rename dragonUUID + private boolean n; +- private BlockPosition o; +- private EnumDragonRespawn p; ++ public BlockPosition o; // CraftBukkit PAIL private -> public, rename portalLocation ++ public EnumDragonRespawn p; // CraftBukkit PAIL private -> public, rename respawnPhase + private int q; + private List r; + +@@ -194,7 +194,7 @@ + + } + +- protected void a(EnumDragonRespawn enumdragonrespawn) { ++ public void a(EnumDragonRespawn enumdragonrespawn) { // CraftBukkit PAIL protected -> public, rename setRespawnPhase + if (this.p == null) { + throw new IllegalStateException("Dragon respawn isn't in progress, can't skip ahead in the animation."); + } else { +@@ -376,7 +376,7 @@ + + private void a(BlockPosition blockposition) { + this.d.triggerEffect(3000, blockposition, 0); +- WorldGenerator.END_GATEWAY.b((WorldGenFeatureConfiguration) WorldGenEndGatewayConfiguration.a()).a(this.d, this.d.getChunkProvider().getChunkGenerator(), new Random(), blockposition); ++ WorldGenerator.END_GATEWAY.b(WorldGenEndGatewayConfiguration.a()).a(this.d, this.d.getChunkProvider().getChunkGenerator(), new Random(), blockposition); // CraftBukkit - decompile error + } + + private void a(boolean flag) { +@@ -388,7 +388,7 @@ + } + } + +- worldgenendtrophy.b((WorldGenFeatureConfiguration) WorldGenFeatureConfiguration.e).a(this.d, this.d.getChunkProvider().getChunkGenerator(), new Random(), this.o); ++ worldgenendtrophy.b(WorldGenFeatureConfiguration.e).a(this.d, this.d.getChunkProvider().getChunkGenerator(), new Random(), this.o); // CraftBukkit - decompile error + } + + private EntityEnderDragon o() { diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java index c1cdf857df..b8e0408370 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java @@ -88,6 +88,8 @@ import net.minecraft.server.TicketType; import net.minecraft.server.Unit; import net.minecraft.server.Vec3D; import net.minecraft.server.WorldGenerator; +import net.minecraft.server.WorldProvider; +import net.minecraft.server.WorldProviderTheEnd; import net.minecraft.server.WorldServer; import org.apache.commons.lang.Validate; import org.bukkit.BlockChangeDelegate; @@ -111,9 +113,11 @@ import org.bukkit.block.Block; import org.bukkit.block.BlockFace; import org.bukkit.block.BlockState; import org.bukkit.block.data.BlockData; +import org.bukkit.boss.DragonBattle; import org.bukkit.craftbukkit.block.CraftBlock; import org.bukkit.craftbukkit.block.CraftBlockState; import org.bukkit.craftbukkit.block.data.CraftBlockData; +import org.bukkit.craftbukkit.boss.CraftDragonBattle; import org.bukkit.craftbukkit.entity.CraftEntity; import org.bukkit.craftbukkit.entity.CraftItem; import org.bukkit.craftbukkit.entity.CraftLightningStrike; @@ -2270,4 +2274,14 @@ public class CraftWorld implements World { PersistentRaid persistentRaid = world.getPersistentRaid(); return persistentRaid.raids.values().stream().map(CraftRaid::new).collect(Collectors.toList()); } + + @Override + public DragonBattle getEnderDragonBattle() { + WorldProvider worldProvider = getHandle().worldProvider; + if (!(worldProvider instanceof WorldProviderTheEnd)) { + return null; + } + + return new CraftDragonBattle(((WorldProviderTheEnd) worldProvider).o()); // PAIL rename getDragonBattle + } } diff --git a/src/main/java/org/bukkit/craftbukkit/boss/CraftDragonBattle.java b/src/main/java/org/bukkit/craftbukkit/boss/CraftDragonBattle.java new file mode 100644 index 0000000000..2ec656dcc8 --- /dev/null +++ b/src/main/java/org/bukkit/craftbukkit/boss/CraftDragonBattle.java @@ -0,0 +1,85 @@ +package org.bukkit.craftbukkit.boss; + +import com.google.common.base.Preconditions; +import net.minecraft.server.EnderDragonBattle; +import net.minecraft.server.Entity; +import net.minecraft.server.EnumDragonRespawn; +import org.bukkit.Location; +import org.bukkit.boss.BossBar; +import org.bukkit.boss.DragonBattle; +import org.bukkit.entity.EnderDragon; + +public class CraftDragonBattle implements DragonBattle { + + private final EnderDragonBattle handle; + + public CraftDragonBattle(EnderDragonBattle handle) { + this.handle = handle; + } + + @Override + public EnderDragon getEnderDragon() { + Entity entity = handle.d.getEntity(handle.m); + return (entity != null) ? (EnderDragon) entity.getBukkitEntity() : null; + } + + @Override + public BossBar getBossBar() { + return new CraftBossBar(handle.bossBattle); + } + + @Override + public Location getEndPortalLocation() { + return new Location(handle.d.getWorld(), handle.o.getX(), handle.o.getY(), handle.o.getZ()); + } + + @Override + public boolean hasBeenPreviouslyKilled() { + return handle.d(); // PAIL rename hasBeenPreviouslyKilled + } + + @Override + public void initiateRespawn() { + this.handle.e(); // PAIL rename initiateRespawn + } + + @Override + public RespawnPhase getRespawnPhase() { + return toBukkitRespawnPhase(handle.p); + } + + @Override + public boolean setRespawnPhase(RespawnPhase phase) { + Preconditions.checkArgument(phase != null && phase != RespawnPhase.NONE, "Invalid respawn phase provided: %s", phase); + + if (handle.p == null) { + return false; + } + + this.handle.a(toNMSRespawnPhase(phase)); + return true; + } + + @Override + public void resetCrystals() { + this.handle.f(); // PAIL rename resetCrystals + } + + @Override + public int hashCode() { + return handle.hashCode(); + } + + @Override + public boolean equals(Object obj) { + return obj instanceof CraftDragonBattle && ((CraftDragonBattle) obj).handle == this.handle; + } + + private RespawnPhase toBukkitRespawnPhase(EnumDragonRespawn phase) { + return (phase != null) ? RespawnPhase.values()[phase.ordinal()] : RespawnPhase.NONE; + } + + private EnumDragonRespawn toNMSRespawnPhase(RespawnPhase phase) { + return (phase != RespawnPhase.NONE) ? EnumDragonRespawn.values()[phase.ordinal()] : null; + } +} diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderDragon.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderDragon.java index ee95e4e338..f155441945 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderDragon.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderDragon.java @@ -7,22 +7,18 @@ import net.minecraft.server.DragonControllerPhase; import net.minecraft.server.EntityComplexPart; import net.minecraft.server.EntityEnderDragon; import org.bukkit.boss.BossBar; +import org.bukkit.boss.DragonBattle; import org.bukkit.craftbukkit.CraftServer; import org.bukkit.craftbukkit.boss.CraftBossBar; +import org.bukkit.craftbukkit.boss.CraftDragonBattle; import org.bukkit.entity.ComplexEntityPart; import org.bukkit.entity.EnderDragon; import org.bukkit.entity.EntityType; public class CraftEnderDragon extends CraftComplexLivingEntity implements EnderDragon { - private BossBar bossBar; - public CraftEnderDragon(CraftServer server, EntityEnderDragon entity) { super(server, entity); - - if (entity.getEnderDragonBattle() != null) { - this.bossBar = new CraftBossBar(entity.getEnderDragonBattle().bossBattle); - } } @Override @@ -71,6 +67,16 @@ public class CraftEnderDragon extends CraftComplexLivingEntity implements EnderD @Override public BossBar getBossBar() { - return bossBar; + return getDragonBattle().getBossBar(); + } + + @Override + public DragonBattle getDragonBattle() { + return new CraftDragonBattle(getHandle().getEnderDragonBattle()); + } + + @Override + public int getDeathAnimationTicks() { + return getHandle().bA; // PAIL rename deathAnimationTicks } }