1.12.2 BossBar showing Y Coordinate?

Discussion in 'Spigot Plugin Development' started by JonasArgent, Aug 1, 2020 at 10:48 PM.

  1. Heya,

    I'm trying to have it so when a player changes world using PlayerChangeWorldEvent, it displays a bossbar to the player which shows the player's Y coordinate live.

    What would be the best way to achieve this?
     
  2. Create an enderdragon entity and either make it invisible or hide it somewhere in your world, and set the display name to whatever you want.

    EDIT: just realised you want it per player, hmm that's tricky, maybe try packets? I don't know much about them but they might be useful
     
  3. In 1.12 the BossBar interface doesn't exist but you could take a look to this resource. It's 1.8 but i think it should be possible to use it in 1.12 or you are able to refractor it to your version.
     
  4. Wither entity is better than enderdragon (My opinion), I use it in version 1.8
     
    • Like Like x 1
  5. This is my bossbar class
    Code (Text):
    package me.filipenock.cypherapi.API.Bossbar;

    import java.lang.reflect.Field;
    import java.util.Map;

    import org.apache.commons.lang.Validate;
    import org.bukkit.Bukkit;
    import org.bukkit.Location;
    import org.bukkit.World;
    import org.bukkit.craftbukkit.v1_8_R3.CraftWorld;
    import org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer;
    import org.bukkit.entity.Player;

    import com.google.common.collect.Maps;

    import net.minecraft.server.v1_8_R3.DataWatcher;
    import net.minecraft.server.v1_8_R3.EntityWither;
    import net.minecraft.server.v1_8_R3.PacketPlayOutEntityDestroy;
    import net.minecraft.server.v1_8_R3.PacketPlayOutEntityMetadata;
    import net.minecraft.server.v1_8_R3.PacketPlayOutEntityTeleport;
    import net.minecraft.server.v1_8_R3.PacketPlayOutSpawnEntityLiving;
    import net.minecraft.server.v1_8_R3.PlayerConnection;

    public class BossBar {

        public static Map<Player, WitherBossbar> players = Maps.newHashMap();

        protected static int ENTITY_DISTANCE = 32;

        public void unload() {
            for (Player player : players.keySet()) {
                ((CraftPlayer) player).getHandle().playerConnection.sendPacket(getWither(player, "").getDestroyPacket());
                players.remove(player);
            }
        }

        public void sendMessage(Player player, String message, float percent) {
            Validate.isTrue(0F <= percent && percent <= 100F, "Percent must be between 0F and 100F, but was: ", percent);
            WitherBossbar wither = players.get(player);
            if (wither == null) {
                addWither(player, message, true);
                wither = players.get(player);
            }
            if (wither != null) {
                wither.name = message;
                wither.health = percent * 100F / wither.getMaxHealth();
            }
            updateWither(wither, player);
        }

        private String checkMessageLength(String message) {
            if (message.length() > 64) {
                message = message.substring(0, 63);
            }
            return message;
        }

        //NOT USED
        public void handleTeleport(final Player player) {
            if (players.containsKey(player)) {
                //Block b = player.getTargetBlock((HashSet<Byte>) null, 7);
                //Location loc = b.getLocation();
                //((CraftPlayer) player).getHandle().playerConnection
                //        .sendPacket(getWither(player, "").getTeleportPacket(loc));
            }
        }

        public void updateWither(WitherBossbar wither, Player player) {
            PlayerConnection connection = ((CraftPlayer) player).getHandle().playerConnection;
            connection.sendPacket(wither.getMetaPacket(wither.updateDataWatcher()));
            connection.sendPacket(wither.getTeleportPacket(getWitherLocation(player)));
        }

        public WitherBossbar getWither(Player player, String message) {
            if (players.containsKey(player)) {
                return players.get(player);
            } else {
                return addWither(player, checkMessageLength(message), false);
            }
        }

        public WitherBossbar addWither(Player player, String message, boolean visible) {
            WitherBossbar wither = new WitherBossbar(player, message, getWitherLocation(player));
            wither.setVisible(visible);
            if (visible) {
                ((CraftPlayer) player).getHandle().playerConnection.sendPacket(wither.getSpawnPacket());
            }
            players.put(player, wither);
            return wither;
        }

        private Location getWitherLocation(Player player) {
            Location loc = player.getEyeLocation();
            loc.setPitch(loc.getPitch() - 20);
            return player.getEyeLocation().add(loc.getDirection().multiply(ENTITY_DISTANCE));
        }

        public void destroy(Player player) {
            WitherBossbar wither = players.get(player);
            if (wither == null)
                return;
            ((CraftPlayer) player).getHandle().playerConnection.sendPacket(wither.getDestroyPacket());
            players.remove(player);
        }

        public void sendBossBar(Player player, String message, float percent) {
            sendMessage(player, message, percent);
        }

        public void delete() {
            for (Player player : Bukkit.getOnlinePlayers()) {
                destroy(player);
            }
        }
     
        public class WitherBossbar {

            public float health = 0;
            private float maxHealth = 100 / 3;
            private float minHealth = 1;

            private Location location;
            public String name;
            private EntityWither wither;

            private byte xvel = 0;
            private byte yvel = 0;
            private byte zvel = 0;

            private boolean visible = false;

            private int id;

            public WitherBossbar(String name, Location location, int percent) {
                this.name = name;
                this.location = location;
                this.health = percent / 100F * maxHealth;
            }

            public WitherBossbar(Player player, String name, Location location) {
                this.name = name;
                this.location = location;
            }

            public float getMaxHealth() {
                return maxHealth;
            }

            public void setMaxHealth(float max) {
                maxHealth = max;
            }

            public float getMinHealth() {
                return minHealth;
            }

            public void setMinHealth(float min) {
                minHealth = min;
            }

            public void setHealth(int percent) {
                this.health = percent / 100F * maxHealth;
                if (this.health <= this.minHealth) {
                    delete();
                }
            }

            public void setName(String name) {
                this.name = name;
            }

            public Location getLocation() {
                return location;
            }

            public void setLocation(Location location) {
                this.location = location;
            }

            public byte getXvel() {
                return xvel;
            }

            public void setXvel(byte xvel) {
                this.xvel = xvel;
            }

            public byte getYvel() {
                return yvel;
            }

            public void setYvel(byte yvel) {
                this.yvel = yvel;
            }

            public byte getZvel() {
                return zvel;
            }

            public void setZvel(byte zvel) {
                this.zvel = zvel;
            }

            public boolean isVisible() {
                return visible;
            }

            public void setVisible(boolean visible) {
                if (visible == this.visible) {
                    return;
                }
                if (visible) {
                    this.visible = true;
                } else {
                    delete();
                }
            }

            public World getWorld() {
                return location.getWorld();
            }

            public void setWorld(World world) {
                this.location.setWorld(world);
            }

            public void run() {
                this.health -= this.minHealth;
                if (this.health <= this.minHealth || this.health > this.maxHealth) {
                    delete();
                }
            }

            public PacketPlayOutSpawnEntityLiving getSpawnPacket() {
                wither = new EntityWither(((CraftWorld) getWorld()).getHandle());
                wither.setLocation(location.getX(), location.getY(), location.getZ(), location.getPitch(), location.getYaw());
                wither.setInvisible(true);
                wither.setCustomName(name);
                wither.setHealth(health);
                wither.motX = getXvel();
                wither.motY = getYvel();
                wither.motZ = getZvel();
                this.id = wither.getId();
                return new PacketPlayOutSpawnEntityLiving(wither);
            }

            public PacketPlayOutEntityDestroy getDestroyPacket() {
                PacketPlayOutEntityDestroy packet = new PacketPlayOutEntityDestroy();
                try {
                    Field a = packet.getClass().getDeclaredField("a");
                    a.setAccessible(true);
                    a.set(packet, new int[] { id });
                } catch (SecurityException | NoSuchFieldException | IllegalAccessException | IllegalArgumentException e) {
                    e.printStackTrace();
                }
                return packet;
            }

            public PacketPlayOutEntityMetadata getMetaPacket(DataWatcher watcher) {
                return new PacketPlayOutEntityMetadata(id, watcher, true);
            }

            public PacketPlayOutEntityTeleport getTeleportPacket(Location loc) {
                this.location = loc;
                return new PacketPlayOutEntityTeleport(this.id, loc.getBlockX() * 32, loc.getBlockY() * 32,
                        loc.getBlockZ() * 32, (byte) ((int) loc.getYaw() * 256 / 360),
                        (byte) ((int) loc.getPitch() * 256 / 360), false);
            }

            public DataWatcher updateDataWatcher() {
                DataWatcher watcher = new DataWatcher(wither);
                watcher.a(0, (byte) (0 | 1 << 5)); // Make it invisible
                watcher.a(2, this.name); // Name of the bar
                //IF THIS IS IN USE, CAUSE ERROR WITH ViaVersion plugin
                //watcher.a(5, isVisible() ? (byte) 0 : (byte) 0); // Visibility of the
                                                                    // wither
                watcher.a(6, health); // Health of the wither
                watcher.a(7, 0); // Pottion effect color, zero is invisible
                watcher.a(8, (byte) 0); // Potion effect ambient
                watcher.a(10, name); // Name of the wither
                watcher.a(11, (byte) 1); // Makes the bar still working if the player
                                            // isn't moving
                watcher.a(15, 1); // Prevent wither from moving
                watcher.a(17, 0); // Watched target
                watcher.a(18, 0); // Watched target
                watcher.a(19, 0); // Watched target
                watcher.a(20, 890); // Invul, makes the wither tiny
                return watcher;
            }

        }
    }
     

    How to use:
    Code (Text):
        BossBar bar = BossBar.getAPI();;
     
        @EventHandler
        public void login(PlayerJoinEvent e) {
            bar.sendBossBar(e.getPlayer(), "You bossbar is read", 100);
        }
     
        @EventHandler
        public void moveUpdate(PlayerMoveEvent e) {
            Player p = e.getPlayer();
            BossBar.players.get(p).setName("You bar is updated");
            BossBar.players.get(p).setHealth(500); // 1000 = 100%, 500 = 50%
            bar.updateWither(BossBar.players.get(p), e.getPlayer());
        }