1.16.5 Make enderdragon go to specific location

Discussion in 'Spigot Plugin Development' started by korobaka, Jun 29, 2021.

  1. Hi!
    I'm currently working on an event on a minecraft server with friends, which includes... using a dragon.
    The thing is, I want to lead him to specific coordinates instead of going to X=0 Z=0...
    any idea about how I can do this?
    Any help would be welcome!
     
  2. Never tried this, but here's a solution that might work (hasn't been tested AT ALL):
    Spawn a dragon and get its battle using #getDragonBattle.
    Then, using NMS on "net.minecraft.server.<version>.EnderDragonBattle", change the values of "exitPortalLocation" and "gateways" (after spawning/making? - not sure).
    This (in VERY hypothetical theory) should work.
    Although IMO you should just shift everything to work around (0,0) like it already is and save yourself the hassle...
    Good luck!
     
  3. thanks for your help!
    just tried using this:

    Code (Java):
    package dev.krbk.pl.dragon.phases;

    import org.bukkit.Location;
    import org.bukkit.World;
    import org.bukkit.craftbukkit.v1_16_R3.entity.CraftEnderDragon;
    import org.bukkit.entity.EntityType;
    import org.bukkit.plugin.java.JavaPlugin;

    import net.minecraft.server.v1_16_R3.BlockPosition;
    import net.minecraft.server.v1_16_R3.EntityEnderDragon;
    import net.minecraft.server.v1_16_R3.EnumDragonRespawn;

    public class Phase3 {
        public static void begin(JavaPlugin pl, World w) {
            Location l = new Location(w, -48, 87, -18);
            CraftEnderDragon de = (CraftEnderDragon) w.spawnEntity(l, EntityType.ENDER_DRAGON);
            EntityEnderDragon d = de.getHandle();
            d.getEnderDragonBattle().exitPortalLocation = new BlockPosition(-5, 76, -18);
            d.getEnderDragonBattle().generateExitPortal(false);
            d.getEnderDragonBattle().setRespawnPhase(EnumDragonRespawn.END);
           
        }
    }
     
    this is returning me an error:

    Code (Text):
    [15:15:13] [Server thread/WARN]: [LeDragonDes6M] Task #22 for LeDragonDes6M v1.0 generated an exception
    java.lang.NullPointerException: null
            at dev.krbk.pl.dragon.phases.Phase3.begin(Phase3.java:18) ~[?:?]
            at dev.krbk.pl.dragon.events.Events$3.run(Events.java:204) ~[?:?]
            at org.bukkit.craftbukkit.v1_16_R3.scheduler.CraftTask.run(CraftTask.java:81) ~[spigot-1.16.5.jar:2991-Spigot-018b9a0-f3f3094]
            at org.bukkit.craftbukkit.v1_16_R3.scheduler.CraftScheduler.mainThreadHeartbeat(CraftScheduler.java:400) ~[spigot-1.16.5.jar:2991-Spigot-018b9a0-f3f3094]
            at net.minecraft.server.v1_16_R3.MinecraftServer.b(MinecraftServer.java:1060) ~[spigot-1.16.5.jar:2991-Spigot-018b9a0-f3f3094]
            at net.minecraft.server.v1_16_R3.DedicatedServer.b(DedicatedServer.java:355) ~[spigot-1.16.5.jar:2991-Spigot-018b9a0-f3f3094]
            at net.minecraft.server.v1_16_R3.MinecraftServer.a(MinecraftServer.java:1008) ~[spigot-1.16.5.jar:2991-Spigot-018b9a0-f3f3094]
            at net.minecraft.server.v1_16_R3.MinecraftServer.w(MinecraftServer.java:847) ~[spigot-1.16.5.jar:2991-Spigot-018b9a0-f3f3094]
            at net.minecraft.server.v1_16_R3.MinecraftServer.lambda$0(MinecraftServer.java:164) ~[spigot-1.16.5.jar:2991-Spigot-018b9a0-f3f3094]
            at java.lang.Thread.run(Unknown Source) [?:1.8.0_281]
    can you help me with this?
    thanks in advance!
     
  4. When you spawn a dragon it doesn't necessarily start a DragonBattle.
    You need to create a DragonBattle manually and put the spawned Dragon in it (as its Dragon).
     
  5. how do I do that?
     
  6. Code (Text):
    DragonBattle battle = new DragonBattle();
    Then it'll prompt you to import the necessary functions within the constructor - fill them up and you're done.
     
  7. isn't it EnderDragonBattle? here are the arguments prompted:
    upload_2021-6-30_16-47-13.png
     
  8. Yeah, my bad. Just add all the arguments and fill them up.
     
  9. Hmm, I don't understand what kind of arguments it's waiting for... What is the long and NBTTagCompound for?
     
  10. Ok so I was right the first time: do NOT use EnderDragonBattle - it's the NMS version of what you want. Use DragonBattle (
    org.bukkit.boss.DragonBattle), import its 9 functions and fill them with the info.
     
  11. When using
    Code (Text):
    DragonBattle b = new DragonBattle();
    I'm getting the following error: Cannot instantiate the type DragonBattle

    Am I doing it the right way?
     
  12. Hover over it (or however your program does it) and import its initiation functions (should be 9 functions)
     
  13. I don't get any initiation function to import...
    upload_2021-7-1_12-8-30.png
    Tho, DragonBattle is imported.
     
  14. OK so I was wrong... again... :rolleyes:
    You need to use NMS classes for this. Here's some code I whipped up from the vanilla creation of DragonBattle:
    Code (Java):
    World world;
    ...
    WorldServer worldServer = ((CraftWorld) world).getHandle();
    EnderDragonBattle battleNMS = new EnderDragonBattle(worldServer,worldServer.worldDataServer.getGeneratorSettings().getSeed(),worldServer.worldDataServer.C());
    DragonBattle battle = new CraftDragonBattle(battleNMS);
    You can use this code as is but will only work for the current version (cuz NMS...), or you can do this with Reflection.
    To do what you wanted you need to use Reflection anyway to change the necessary values within battleNMS before creating battle or you can try to work with NBTTagCompound before the creation of battleNMS (i.e. alter "worldServer.worldDataServer.C()" before using it to create battleNMS) so it can be initiated to those values from the start (I don't understand NBTTagCompound that well so I personally would opt for using Reflection since I'd be using it anyway to do all of this cuz NMS sucks...)
    Let me know if you need any further help.
     
  15. thanks for your help! Last thing, how can I assign this to my dragon?
     
    #15 korobaka, Jul 1, 2021
    Last edited: Jul 1, 2021
  16. If you already have a Dragon spawned (default spawning or some other way that generates its battle) you can just get its battle using EnderDragon#getDragonBattle and work on it.
    The method I wrote is to generate a new Dragon with a battle.
    If you use my method I suggest you work on battleNMS before using it to create battle.
    To change the values you'll have to use Reflection to edit them.
     
  17. I don't understand how to generate the dragon using the battle...
    My code:
    Code (Text):
    package dev.krbk.pl.dragon.cmds;

    import org.bukkit.Location;
    import org.bukkit.World;
    import org.bukkit.boss.DragonBattle;
    import org.bukkit.command.Command;
    import org.bukkit.command.CommandExecutor;
    import org.bukkit.command.CommandSender;
    import org.bukkit.craftbukkit.v1_16_R3.CraftWorld;
    import org.bukkit.craftbukkit.v1_16_R3.boss.CraftDragonBattle;
    import org.bukkit.entity.EnderDragon;
    import org.bukkit.entity.Player;

    import net.minecraft.server.v1_16_R3.BlockPosition;
    import net.minecraft.server.v1_16_R3.EnderDragonBattle;
    import net.minecraft.server.v1_16_R3.EnumDragonRespawn;
    import net.minecraft.server.v1_16_R3.WorldServer;

    public class EnderSummon implements CommandExecutor {
       
        @Override
        public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
            if (sender instanceof Player) {
               
                Player p = (Player) sender;
                World w = p.getWorld();
                Location l = new Location(w, -48, 87, -18);
                //CraftEnderDragon de = (CraftEnderDragon) w.spawnEntity(l, EntityType.ENDER_DRAGON);
                //EntityEnderDragon d = de.getHandle();
                WorldServer worldServer = ((CraftWorld) w).getHandle();
                EnderDragonBattle battleNMS = new EnderDragonBattle(worldServer, worldServer.worldDataServer.getGeneratorSettings().getSeed(), worldServer.worldDataServer.C());
                battleNMS.exitPortalLocation = new BlockPosition(-5, 76, -18);
                battleNMS.generateExitPortal(false);
                DragonBattle battle = new CraftDragonBattle(battleNMS);
                battle.
                EnderDragon e = battle.getEnderDragon();
                e.teleport(l);
                //de.setCustomName("");
                //d.getEnderDragonBattle().exitPortalLocation = new BlockPosition(-5, 76, -18);
                //d.getEnderDragonBattle().generateExitPortal(false);
                //d.getEnderDragonBattle().setRespawnPhase(EnumDragonRespawn.END);
               
                return true;

            }
            return true;
        }

    }
     
    and my error:
    Code (Text):
    [13:27:39] [Server thread/ERROR]: null
    org.bukkit.command.CommandException: Unhandled exception executing command 'cd' in plugin LeDragonDes6M v1.0
            at org.bukkit.command.PluginCommand.execute(PluginCommand.java:47) ~[spigot-1.16.5.jar:2991-Spigot-018b9a0-f3f3094]
            at org.bukkit.command.SimpleCommandMap.dispatch(SimpleCommandMap.java:149) ~[spigot-1.16.5.jar:2991-Spigot-018b9a0-f3f3094]
            at org.bukkit.craftbukkit.v1_16_R3.CraftServer.dispatchCommand(CraftServer.java:763) ~[spigot-1.16.5.jar:2991-Spigot-018b9a0-f3f3094]
            at net.minecraft.server.v1_16_R3.PlayerConnection.handleCommand(PlayerConnection.java:1788) ~[spigot-1.16.5.jar:2991-Spigot-018b9a0-f3f3094]
            at net.minecraft.server.v1_16_R3.PlayerConnection.c(PlayerConnection.java:1631) ~[spigot-1.16.5.jar:2991-Spigot-018b9a0-f3f3094]
            at net.minecraft.server.v1_16_R3.PlayerConnection.a(PlayerConnection.java:1584) ~[spigot-1.16.5.jar:2991-Spigot-018b9a0-f3f3094]
            at net.minecraft.server.v1_16_R3.PacketPlayInChat.a(PacketPlayInChat.java:47) ~[spigot-1.16.5.jar:2991-Spigot-018b9a0-f3f3094]
            at net.minecraft.server.v1_16_R3.PacketPlayInChat.a(PacketPlayInChat.java:1) ~[spigot-1.16.5.jar:2991-Spigot-018b9a0-f3f3094]
            at net.minecraft.server.v1_16_R3.PlayerConnectionUtils.lambda$0(PlayerConnectionUtils.java:19) ~[spigot-1.16.5.jar:2991-Spigot-018b9a0-f3f3094]
            at net.minecraft.server.v1_16_R3.TickTask.run(SourceFile:18) ~[spigot-1.16.5.jar:2991-Spigot-018b9a0-f3f3094]
            at net.minecraft.server.v1_16_R3.IAsyncTaskHandler.executeTask(SourceFile:144) ~[spigot-1.16.5.jar:2991-Spigot-018b9a0-f3f3094]
            at net.minecraft.server.v1_16_R3.IAsyncTaskHandlerReentrant.executeTask(SourceFile:23) ~[spigot-1.16.5.jar:2991-Spigot-018b9a0-f3f3094]
            at net.minecraft.server.v1_16_R3.IAsyncTaskHandler.executeNext(SourceFile:118) ~[spigot-1.16.5.jar:2991-Spigot-018b9a0-f3f3094]
            at net.minecraft.server.v1_16_R3.MinecraftServer.bb(MinecraftServer.java:942) ~[spigot-1.16.5.jar:2991-Spigot-018b9a0-f3f3094]
            at net.minecraft.server.v1_16_R3.MinecraftServer.executeNext(MinecraftServer.java:935) ~[spigot-1.16.5.jar:2991-Spigot-018b9a0-f3f3094]
            at net.minecraft.server.v1_16_R3.IAsyncTaskHandler.awaitTasks(SourceFile:127) ~[spigot-1.16.5.jar:2991-Spigot-018b9a0-f3f3094]
            at net.minecraft.server.v1_16_R3.MinecraftServer.sleepForTick(MinecraftServer.java:919) ~[spigot-1.16.5.jar:2991-Spigot-018b9a0-f3f3094]
            at net.minecraft.server.v1_16_R3.MinecraftServer.w(MinecraftServer.java:851) ~[spigot-1.16.5.jar:2991-Spigot-018b9a0-f3f3094]
            at net.minecraft.server.v1_16_R3.MinecraftServer.lambda$0(MinecraftServer.java:164) ~[spigot-1.16.5.jar:2991-Spigot-018b9a0-f3f3094]
            at java.lang.Thread.run(Unknown Source) [?:1.8.0_281]
    Caused by: java.lang.NullPointerException
            at dev.krbk.pl.dragon.cmds.EnderSummon.onCommand(EnderSummon.java:36) ~[?:?]
            at org.bukkit.command.PluginCommand.execute(PluginCommand.java:45) ~[spigot-1.16.5.jar:2991-Spigot-018b9a0-f3f3094]
            ... 19 more
    line 36 is e.teleport(l).
    Does it mean e is undefined? how can I define it?
     
  18. You created the battle but didn't spawn the Dragon - try doing "battle.initiateRespawn()" before teleporting the Dragon
     
  19. Even by doing that, the dragon is not spawning... Same error, even by delaying the time before I'm using initiateRespawn(); and e.teleport(l)...
     
  20. I looked at the coding for EnderDragonBattle - spawn a new EnderDragon yourself and change battleNMS's variable named "dragonUUID" to the spawned Dragon's UUID. I think that'll solve it (and afterwards run the "battle.initiateRespawn()" just in case).