Armor stand to view player stats problem [1.12.2]

Discussion in 'Plugin Development' started by Wimowa, Jan 19, 2023.

Thread Status:
Not open for further replies.
  1. Offline

    Wimowa

    Hi, I'm trying to make a scoreboard plugin for my own use. I would like to display the stats for that player above the player's head.
    I've tried using the scoreboards, but they give problems that I've already tried to solve with other people in the forum and we've come to the conclusion that it can't be done.

    So I'm trying to do it with armor stands, but the problem is as follows.

    Player 1: Enters, sees above his head his stats like level and life (everything works fine).

    Player 2: Enters, from his point of view everything works fine (player 1's stats are also correct), but player 1 sees the armor stand of the player who entered after him.

    I leave some screenshots for you to understand better.
    In the scoreboard to the side you can view the name of the player. The player named Wimowa entered first.

    Cattura.jpg

    Code:
    public class PlayerListener implements Listener {
    
        Scoreboard plugin = Scoreboard.getInstance();
        HashMap<Player, ArmorStand> stands = new HashMap<>();
        String[] statsValue;
    
        @EventHandler
        public void onPlayerJoin(PlayerJoinEvent e) throws IOException {
    
            Player p = e.getPlayer();
            ArmorStand stand = (ArmorStand) Bukkit.getServer().getWorld(p.getWorld().getUID()).spawnEntity(p.getLocation().add(0,0.2,0), EntityType.ARMOR_STAND);
            stands.put(p,stand);
            stands.get(p).setVisible(false);
            stands.get(p).setInvulnerable(true);
            stands.get(p).setCanPickupItems(false);
            stands.get(p).setGravity(false);
            stands.get(p).setArms(false);
            stands.get(p).setCustomNameVisible(true);
            stands.get(p).setBasePlate(false);
            stands.get(p).setCollidable(false);
            p.sendMessage("Visibile: "+stands.get(p).isVisible());
    
    
    
    
            new BukkitRunnable() {
                @Override
                public void run() {
                    if (p.isOnline()){
                        stands.get(p).teleport(p.getLocation().add(0,0.2,0));
                        try {
                            statsValue = FileOperation.readStats(p).split(" ");
                        } catch (IOException ex) {
                            ex.printStackTrace();
                        }
                        stands.get(p).setCustomName(ColorUtil.convert("&a&lLv &6"+statsValue[0]+" &c&l❤ &6"+(int)p.getHealth()));
                    }else{this.cancel();}
                }
            }.runTaskTimerAsynchronously(plugin, 0, 5);
    
            new BukkitRunnable() {
                @Override
                public void run() {
                    try {
                        p.setScoreboard(UserScoreboard.createScoreboard(p));
                    } catch (IOException ex) {
                        ex.printStackTrace();
                    }
                }
            }.runTaskTimer(plugin,0,100);
    
        }
    
        @EventHandler
        public void onExit(PlayerQuitEvent e){
    
            stands.get(e.getPlayer()).remove();
            stands.remove(e.getPlayer());
    
        }
     
  2. Offline

    Chr0mosom3

    What I'm assuming happens, is that when player 1 joins, you need to hide his armor stand for player 2. What I recommend is trying this with packets, specifically ClientboundRemoveEntitiesPacket, instead of using built in invisible, since it's not working.

    I did something like this long time ago, except instead of teleporting the armor stands I made them ride the player, if you want to look at the code here it is (feel free to steal).
    Show Spoiler

    Code:
    package eu.ladeira.rebirth.core.modules;
    
    import java.util.ArrayList;
    import java.util.HashMap;
    
    import org.bukkit.Bukkit;
    import org.bukkit.GameMode;
    import org.bukkit.Location;
    import org.bukkit.Material;
    import org.bukkit.craftbukkit.v1_19_R1.entity.CraftArmorStand;
    import org.bukkit.craftbukkit.v1_19_R1.entity.CraftPlayer;
    import org.bukkit.craftbukkit.v1_19_R1.entity.CraftSilverfish;
    import org.bukkit.entity.ArmorStand;
    import org.bukkit.entity.Entity;
    import org.bukkit.entity.EntityType;
    import org.bukkit.entity.Player;
    import org.bukkit.entity.Silverfish;
    import org.bukkit.event.EventHandler;
    import org.bukkit.event.Listener;
    import org.bukkit.event.player.PlayerJoinEvent;
    import org.bukkit.event.player.PlayerQuitEvent;
    import org.bukkit.event.player.PlayerTeleportEvent;
    import org.bukkit.scheduler.BukkitRunnable;
    import org.bukkit.util.Vector;
    
    import eu.ladeira.rebirth.core.Core;
    import eu.ladeira.rebirth.core.Database;
    import eu.ladeira.rebirth.core.LadeiraModule;
    import net.minecraft.network.protocol.game.ClientboundRemoveEntitiesPacket;
    
    public class TagModule extends LadeiraModule implements Listener {
    
        public HashMap<Player, PlayerDescriptor> descriptors;
        private Database db;
    
        public TagModule(Core core) {
            this.db = core.getDatabase();
            descriptors = new HashMap<>();
    
            for (Player online : Bukkit.getOnlinePlayers()) {
                descriptors.put(online, new PlayerDescriptor(online));
            }
    
            new BukkitRunnable() {
                @Override
                public void run() {
                    for (Player online : descriptors.keySet()) {
                        PlayerDescriptor descriptor = descriptors.get(online);
    
                        if (!online.getGameMode().equals(GameMode.SPECTATOR) && !online.isInWater()) {
                            if (online.isSneaking()) {
                                descriptor.hideText();
                            } else {
                                descriptor.setText(0, db.getName(online.getUniqueId()));
                                descriptor.showText();
                            }
    
                            // The player can't go through portals with passengers, so we need to eject them
                            // when he wants to portal
                            Material standingIn = online.getWorld().getBlockAt(online.getLocation()).getType();
                            if (standingIn.equals(Material.NETHER_PORTAL) || standingIn.equals(Material.END_PORTAL)) {
                                online.eject();
                            } else {
                                if (online.getPassengers().size() < 1 && online.getHealth() > 0) {
                                    descriptor.reload();
                                }
                            }
                        } else {
                            descriptors.get(online).remove();
                        }
                        descriptor.removeForPlayer(online);
                    }
                }
            }.runTaskTimer(core.getJavaPlugin(), 1, 1);
    
        }
    
        @Override
        public void onDisable() {
            for (Player online : descriptors.keySet()) {
                descriptors.get(online).remove();
            }
        }
    
        @EventHandler
        public void addDescriptor(PlayerJoinEvent e) {
            Player player = e.getPlayer();
            descriptors.put(player, new PlayerDescriptor(player));
        }
    
        @EventHandler
        public void removeDescriptor(PlayerQuitEvent e) {
            Player player = e.getPlayer();
            PlayerDescriptor descriptor = descriptors.get(player);
            if (descriptor != null) {
                descriptor.remove();
            }
            descriptors.remove(player);
        }
    
        @EventHandler
        public void removeNameOnWorldSwitch(PlayerTeleportEvent e) {
            Player player = e.getPlayer();
            if (!e.getFrom().getWorld().getName().equals(e.getTo().getWorld().getName())) {
                descriptors.get(player).removeEntities();
            }
        }
    
        private class PlayerDescriptor {
            private Player player;
            private HashMap<Integer, Layer> layers;
    
            private final Vector OFFSET = new Vector(0, 1.8, 0);
    
            public PlayerDescriptor(Player player) {
                this.player = player;
                layers = new HashMap<>();
    
                Layer nameLayer;
                nameLayer = new Layer(db.getName(player.getUniqueId()), player.getLocation().add(OFFSET));
                nameLayer.rideEntity(player);
                layers.put(0, nameLayer);
            }
    
            public void setText(int layerIndex, String text) {
                Layer layer = layers.get(layerIndex);
                if (layer != null) {
                    layer.setText(text);
                } else {
                    layers.put(layerIndex, new Layer(text, player.getLocation().add(OFFSET)));
                    reload();
                }
            }
    
            public void hideText() {
                for (int layer : layers.keySet()) {
                    layers.get(layer).hideText();
                }
            }
    
            public void showText() {
                for (int layer : layers.keySet()) {
                    layers.get(layer).showText();
                }
            }
    
            public void reload() {
                ArrayList<String> texts = new ArrayList<>();
                for (Integer layerIndex : layers.keySet()) {
                    Layer layer = layers.get(layerIndex);
                    texts.add(layer.getText());
                    layer.remove();
                }
    
                layers = new HashMap<>();
                Layer lastLayer = null;
                int counter = 0;
                for (String text : texts) {
                    Layer layer = new Layer(text, player.getLocation().add(OFFSET));
                    layers.put(counter++, layer);
    
                    if (lastLayer == null) {
                        layer.rideEntity(player);
                    } else {
                        layer.rideEntity(lastLayer.stand);
                    }
    
                    lastLayer = layer;
                }
            }
    
            public void remove() {
                removeEntities();
    
                layers = new HashMap<>();
            }
    
            public void removeEntities() {
                for (Integer layerIndex : layers.keySet()) {
                    Layer layer = layers.get(layerIndex);
                    layer.remove();
                }
            }
    
            public void removeForPlayer(Player player) {
                for (Integer layerIndex : layers.keySet()) {
                    Layer layer = layers.get(layerIndex);
                    layer.sendRemovePacket(player);
                }
            }
    
            private class Layer {
    
                private String name;
                private Silverfish silverfish;
                private ArmorStand stand;
    
                public Layer(String name, Location location) {
                    this.name = name;
                    silverfish = getSilverfish(location);
                    stand = getStand(location);
                    stand.setCustomName(name);
                }
    
                public void setText(String name) {
                    this.name = name;
                    stand.setCustomName(name);
                }
    
                public void hideText() {
                    stand.setCustomNameVisible(false);
                }
    
                public void showText() {
                    stand.setCustomNameVisible(true);
                }
    
                public String getText() {
                    return this.name;
                }
    
                public void rideEntity(Entity entity) {
                    entity.addPassenger(silverfish);
                    silverfish.addPassenger(stand);
                }
    
                public Silverfish getSilverfish(Location location) {
                    Silverfish fish = (Silverfish) location.getWorld().spawnEntity(location, EntityType.SILVERFISH);
    
                    fish.setAI(false);
                    fish.setInvisible(true);
                    fish.setInvulnerable(true);
                    fish.setSilent(true);
    
                    return fish;
                }
    
                public ArmorStand getStand(Location location) {
                    ArmorStand stand = (ArmorStand) location.getWorld().spawnEntity(location, EntityType.ARMOR_STAND);
    
                    stand.setInvulnerable(true);
                    stand.setInvisible(true);
                    stand.setMarker(true);
                    stand.setSmall(true);
                    stand.setCustomNameVisible(true);
    
                    return stand;
                }
    
                public void sendRemovePacket(Player player) {
                    ((CraftPlayer) player).getHandle().connection.send(new ClientboundRemoveEntitiesPacket(((CraftSilverfish) silverfish).getEntityId()));
                    ((CraftPlayer) player).getHandle().connection.send((new ClientboundRemoveEntitiesPacket(((CraftArmorStand) stand).getEntityId())));
                }
    
                public void remove() {
                    stand.remove();
                    silverfish.remove();
                }
            }
        }
    }
    
    
     
Thread Status:
Not open for further replies.

Share This Page