From 5fe510da591a009c9550678d50a9fc0b1072b6f3 Mon Sep 17 00:00:00 2001 From: Matthew Date: Tue, 15 Mar 2016 23:32:37 -0400 Subject: [PATCH] SPIGOT-1934: Expand EnderDragon API - implement dragon phases --- nms-patches/DragonControllerManager.patch | 64 +++++++++++++++++++ nms-patches/EntityEnderDragon.patch | 9 +++ .../craftbukkit/entity/CraftEnderDragon.java | 19 ++++++ .../bukkit/entity/EnderDragonPhaseTest.java | 50 +++++++++++++++ 4 files changed, 142 insertions(+) create mode 100644 nms-patches/DragonControllerManager.patch create mode 100644 src/test/java/org/bukkit/entity/EnderDragonPhaseTest.java diff --git a/nms-patches/DragonControllerManager.patch b/nms-patches/DragonControllerManager.patch new file mode 100644 index 0000000000..f33447d330 --- /dev/null +++ b/nms-patches/DragonControllerManager.patch @@ -0,0 +1,64 @@ +--- a/net/minecraft/server/DragonControllerManager.java ++++ b/net/minecraft/server/DragonControllerManager.java +@@ -2,32 +2,44 @@ + + import org.apache.logging.log4j.LogManager; + import org.apache.logging.log4j.Logger; ++import org.bukkit.craftbukkit.entity.CraftEnderDragon; ++import org.bukkit.entity.EnderDragon; ++import org.bukkit.event.entity.EnderDragonChangePhaseEvent; + + public class DragonControllerManager { + + private static final Logger a = LogManager.getLogger(); +- private final EntityEnderDragon b; +- private final IDragonController[] c = new IDragonController[DragonControllerPhase.c()]; +- private IDragonController d; ++ private final EntityEnderDragon b; // PAIL: Rename enderDragon ++ private final IDragonController[] c = new IDragonController[DragonControllerPhase.c()]; // PAIL: Rename dragonControllers ++ private IDragonController d; // PAIL: Rename currentDragonController + + public DragonControllerManager(EntityEnderDragon entityenderdragon) { + this.b = entityenderdragon; + this.a(DragonControllerPhase.k); + } + +- public void a(DragonControllerPhase dragoncontrollerphase) { +- if (this.d == null || dragoncontrollerphase != this.d.i()) { ++ public void a(DragonControllerPhase dragoncontrollerphase) { // PAIL: Rename setControllerPhase ++ if (this.d == null || dragoncontrollerphase != this.d.i()) { // PAIL: Rename getControllerPhase + if (this.d != null) { +- this.d.e(); ++ this.d.e(); // PAIL: Rename + } + +- this.d = this.b(dragoncontrollerphase); ++ // CraftBukkit start - Call EnderDragonChangePhaseEvent ++ EnderDragonChangePhaseEvent event = new EnderDragonChangePhaseEvent((CraftEnderDragon) this.b.getBukkitEntity(), this.d == null ? null : CraftEnderDragon.getBukkitPhase(this.d.i()), CraftEnderDragon.getBukkitPhase(dragoncontrollerphase)); ++ this.b.world.getServer().getPluginManager().callEvent(event); ++ if (event.isCancelled()) { ++ return; ++ } ++ dragoncontrollerphase = CraftEnderDragon.getMinecraftPhase(event.getNewPhase()); ++ // CraftBukkit end ++ ++ this.d = this.b(dragoncontrollerphase); // PAIL: Rename getDragonController + if (!this.b.world.isClientSide) { +- this.b.getDataWatcher().set(EntityEnderDragon.a, Integer.valueOf(dragoncontrollerphase.b())); ++ this.b.getDataWatcher().set(EntityEnderDragon.a, Integer.valueOf(dragoncontrollerphase.b())); // PAIL: Rename getId + } + + DragonControllerManager.a.debug("Dragon is now in phase {} on the {}", new Object[] { dragoncontrollerphase, this.b.world.isClientSide ? "client" : "server"}); +- this.d.d(); ++ this.d.d(); // PAIL: Rename reset + } + } + +@@ -42,6 +54,6 @@ + this.c[i] = dragoncontrollerphase.a(this.b); + } + +- return this.c[i]; ++ return (T) this.c[i]; + } + } diff --git a/nms-patches/EntityEnderDragon.patch b/nms-patches/EntityEnderDragon.patch index 974f5d4f4b..456f569a44 100644 --- a/nms-patches/EntityEnderDragon.patch +++ b/nms-patches/EntityEnderDragon.patch @@ -21,6 +21,15 @@ public EntityEnderDragon(World world) { super(world); +@@ -169,7 +175,7 @@ + + Vec3D vec3d = idragoncontroller.g(); + +- if (vec3d != null) { ++ if (vec3d != null && idragoncontroller.i() != DragonControllerPhase.k) { // CraftBukkit - Don't move when hovering + d0 = vec3d.x - this.locX; + d1 = vec3d.y - this.locY; + d2 = vec3d.z - this.locZ; @@ -308,7 +314,14 @@ if (this.currentEnderCrystal.dead) { this.currentEnderCrystal = null; diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderDragon.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderDragon.java index fa0d63aea5..9b2df6adf9 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderDragon.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEnderDragon.java @@ -5,6 +5,7 @@ import com.google.common.collect.ImmutableSet.Builder; import java.util.Set; +import net.minecraft.server.DragonControllerPhase; import net.minecraft.server.EntityComplexPart; import net.minecraft.server.EntityEnderDragon; @@ -41,4 +42,22 @@ public class CraftEnderDragon extends CraftComplexLivingEntity implements EnderD public EntityType getType() { return EntityType.ENDER_DRAGON; } + + @Override + public Phase getPhase() { + return Phase.values()[getHandle().getDataWatcher().get(EntityEnderDragon.a)]; // PAIL: Rename PHASE + } + + @Override + public void setPhase(Phase phase) { + getHandle().cT().a(getMinecraftPhase(phase)); // PAIL: Rename getDragonControllerManager setPhase + } + + public static Phase getBukkitPhase(DragonControllerPhase phase) { + return Phase.values()[phase.b()]; + } + + public static DragonControllerPhase getMinecraftPhase(Phase phase) { + return DragonControllerPhase.a(phase.ordinal()); // PAIL: Rename getById + } } diff --git a/src/test/java/org/bukkit/entity/EnderDragonPhaseTest.java b/src/test/java/org/bukkit/entity/EnderDragonPhaseTest.java new file mode 100644 index 0000000000..8bd4e82c60 --- /dev/null +++ b/src/test/java/org/bukkit/entity/EnderDragonPhaseTest.java @@ -0,0 +1,50 @@ +package org.bukkit.entity; + +import net.minecraft.server.DragonControllerPhase; +import org.bukkit.craftbukkit.entity.CraftEnderDragon; +import org.junit.Assert; +import org.junit.Test; + +import static junit.framework.TestCase.assertNotNull; + +public class EnderDragonPhaseTest { + + @Test + public void testNotNull() { + for (EnderDragon.Phase phase : EnderDragon.Phase.values()) { + DragonControllerPhase dragonControllerPhase = CraftEnderDragon.getMinecraftPhase(phase); + assertNotNull(phase.name(), dragonControllerPhase); + assertNotNull(phase.name(), CraftEnderDragon.getBukkitPhase(dragonControllerPhase)); + } + } + + @Test + public void testBukkitToMinecraft() { + Assert.assertEquals("CIRCLING", CraftEnderDragon.getMinecraftPhase(EnderDragon.Phase.CIRCLING), DragonControllerPhase.a); // PAIL: Rename HOLDING_PATTERN + Assert.assertEquals("STRAFING", CraftEnderDragon.getMinecraftPhase(EnderDragon.Phase.STRAFING), DragonControllerPhase.b); // PAIL: Rename STRAFE_PLAYER + Assert.assertEquals("FLY_TO_PORTAL", CraftEnderDragon.getMinecraftPhase(EnderDragon.Phase.FLY_TO_PORTAL), DragonControllerPhase.c); // PAIL: Rename LANDING_APPROACH + Assert.assertEquals("LAND_ON_PORTAL", CraftEnderDragon.getMinecraftPhase(EnderDragon.Phase.LAND_ON_PORTAL), DragonControllerPhase.d); // PAIL: Rename LANDING + Assert.assertEquals("LEAVE_PORTAL", CraftEnderDragon.getMinecraftPhase(EnderDragon.Phase.LEAVE_PORTAL), DragonControllerPhase.e); // PAIL: Rename TAKEOFF + Assert.assertEquals("BREATH_ATTACK", CraftEnderDragon.getMinecraftPhase(EnderDragon.Phase.BREATH_ATTACK), DragonControllerPhase.f); // PAIL: Rename SITTING_FLAMING + Assert.assertEquals("SEARCH_FOR_BREATH_ATTACK_TARGET", CraftEnderDragon.getMinecraftPhase(EnderDragon.Phase.SEARCH_FOR_BREATH_ATTACK_TARGET), DragonControllerPhase.g); // PAIL: Rename SITTING_SCANNING + Assert.assertEquals("ROAR_BEFORE_ATTACK", CraftEnderDragon.getMinecraftPhase(EnderDragon.Phase.ROAR_BEFORE_ATTACK), DragonControllerPhase.h); // PAIL: Rename SITTING_ATTACKING + Assert.assertEquals("CHARGE_PLAYER", CraftEnderDragon.getMinecraftPhase(EnderDragon.Phase.CHARGE_PLAYER), DragonControllerPhase.i); // PAIL: Rename CHARGING_PLAYER + Assert.assertEquals("DYING", CraftEnderDragon.getMinecraftPhase(EnderDragon.Phase.DYING), DragonControllerPhase.j); // PAIL: Rename DYING + Assert.assertEquals("HOVER", CraftEnderDragon.getMinecraftPhase(EnderDragon.Phase.HOVER), DragonControllerPhase.k); // PAIL: Rename HOVER + } + + @Test + public void testMinecraftToBukkit() { + Assert.assertEquals("CIRCLING", CraftEnderDragon.getBukkitPhase(DragonControllerPhase.a), EnderDragon.Phase.CIRCLING); + Assert.assertEquals("STRAFING", CraftEnderDragon.getBukkitPhase(DragonControllerPhase.b), EnderDragon.Phase.STRAFING); + Assert.assertEquals("FLY_TO_PORTAL", CraftEnderDragon.getBukkitPhase(DragonControllerPhase.c), EnderDragon.Phase.FLY_TO_PORTAL); + Assert.assertEquals("LAND_ON_PORTAL", CraftEnderDragon.getBukkitPhase(DragonControllerPhase.d), EnderDragon.Phase.LAND_ON_PORTAL); + Assert.assertEquals("LEAVE_PORTAL", CraftEnderDragon.getBukkitPhase(DragonControllerPhase.e), EnderDragon.Phase.LEAVE_PORTAL); + Assert.assertEquals("BREATH_ATTACK", CraftEnderDragon.getBukkitPhase(DragonControllerPhase.f), EnderDragon.Phase.BREATH_ATTACK); + Assert.assertEquals("SEARCH_FOR_BREATH_ATTACK_TARGET", CraftEnderDragon.getBukkitPhase(DragonControllerPhase.g), EnderDragon.Phase.SEARCH_FOR_BREATH_ATTACK_TARGET); + Assert.assertEquals("ROAR_BEFORE_ATTACK", CraftEnderDragon.getBukkitPhase(DragonControllerPhase.h), EnderDragon.Phase.ROAR_BEFORE_ATTACK); + Assert.assertEquals("CHARGE_PLAYER", CraftEnderDragon.getBukkitPhase(DragonControllerPhase.i), EnderDragon.Phase.CHARGE_PLAYER); + Assert.assertEquals("DYING", CraftEnderDragon.getBukkitPhase(DragonControllerPhase.j), EnderDragon.Phase.DYING); + Assert.assertEquals("HOVER", CraftEnderDragon.getBukkitPhase(DragonControllerPhase.k), EnderDragon.Phase.HOVER); + } +}