Advertisement
Guest User

Scoreboard

a guest
Apr 19th, 2019
294
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 11.66 KB | None | 0 0
  1. import net.minecraft.server.v1_8_R3.*;
  2. import org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer;
  3. import org.bukkit.entity.Player;
  4.  
  5. import java.lang.reflect.Field;
  6. import java.util.ArrayList;
  7. import java.util.List;
  8.  
  9. /**
  10.  * @author zyuiop
  11.  */
  12. public class ScoreboardSign {
  13.     private boolean created = false;
  14.     private final VirtualTeam[] lines = new VirtualTeam[15];
  15.     private final Player player;
  16.     private String objectiveName;
  17.  
  18.     /**
  19.      * Create a scoreboard sign for a given player and using a specifig objective name
  20.      * @param player the player viewing the scoreboard sign
  21.      * @param objectiveName the name of the scoreboard sign (displayed at the top of the scoreboard)
  22.      */
  23.     public ScoreboardSign(Player player, String objectiveName) {
  24.         this.player = player;
  25.         this.objectiveName = objectiveName;
  26.     }
  27.  
  28.     /**
  29.      * Send the initial creation packets for this scoreboard sign. Must be called at least once.
  30.      */
  31.     public void create() {
  32.         if (created)
  33.             return;
  34.  
  35.         PlayerConnection player = getPlayer();
  36.         player.sendPacket(createObjectivePacket(0, objectiveName));
  37.         player.sendPacket(setObjectiveSlot());
  38.         int i = 0;
  39.         while (i < lines.length)
  40.             sendLine(i++);
  41.  
  42.         created = true;
  43.     }
  44.  
  45.     /**
  46.      * Send the packets to remove this scoreboard sign. A destroyed scoreboard sign must be recreated using {@link ScoreboardSign#create()} in order
  47.      * to be used again
  48.      */
  49.     public void destroy() {
  50.         if (!created)
  51.             return;
  52.  
  53.         getPlayer().sendPacket(createObjectivePacket(1, null));
  54.         for (VirtualTeam team : lines)
  55.             if (team != null)
  56.                 getPlayer().sendPacket(team.removeTeam());
  57.  
  58.         created = false;
  59.     }
  60.  
  61.     /**
  62.      * Change the name of the objective. The name is displayed at the top of the scoreboard.
  63.      * @param name the name of the objective, max 32 char
  64.      */
  65.     public void setObjectiveName(String name) {
  66.         this.objectiveName = name;
  67.         if (created)
  68.             getPlayer().sendPacket(createObjectivePacket(2, name));
  69.     }
  70.  
  71.     /**
  72.      * Change a scoreboard line and send the packets to the player. Can be called async.
  73.      * @param line the number of the line (0 <= line < 15)
  74.      * @param value the new value for the scoreboard line
  75.      */
  76.     public void setLine(int line, String value) {
  77.         VirtualTeam team = getOrCreateTeam(line);
  78.         String old = team.getCurrentPlayer();
  79.  
  80.         if (old != null && created)
  81.             getPlayer().sendPacket(removeLine(old));
  82.  
  83.         team.setValue(value);
  84.         sendLine(line);
  85.     }
  86.  
  87.     /**
  88.      * Remove a given scoreboard line
  89.      * @param line the line to remove
  90.      */
  91.     public void removeLine(int line) {
  92.         VirtualTeam team = getOrCreateTeam(line);
  93.         String old = team.getCurrentPlayer();
  94.  
  95.         if (old != null && created) {
  96.             getPlayer().sendPacket(removeLine(old));
  97.             getPlayer().sendPacket(team.removeTeam());
  98.         }
  99.  
  100.         lines[line] = null;
  101.     }
  102.  
  103.     /**
  104.      * Get the current value for a line
  105.      * @param line the line
  106.      * @return the content of the line
  107.      */
  108.     public String getLine(int line) {
  109.         if (line > 14)
  110.             return null;
  111.         if (line < 0)
  112.             return null;
  113.         return getOrCreateTeam(line).getValue();
  114.     }
  115.  
  116.     /**
  117.      * Get the team assigned to a line
  118.      * @return the {@link VirtualTeam} used to display this line
  119.      */
  120.     public VirtualTeam getTeam(int line) {
  121.         if (line > 14)
  122.             return null;
  123.         if (line < 0)
  124.             return null;
  125.         return getOrCreateTeam(line);
  126.     }
  127.  
  128.     private PlayerConnection getPlayer() {
  129.         return ((CraftPlayer) player).getHandle().playerConnection;
  130.     }
  131.  
  132.     private void sendLine(int line) {
  133.         if (line > 14)
  134.             return;
  135.         if (line < 0)
  136.             return;
  137.         if (!created)
  138.             return;
  139.  
  140.         int score = (15 - line);
  141.         VirtualTeam val = getOrCreateTeam(line);
  142.         for (Packet packet : val.sendLine())
  143.             getPlayer().sendPacket(packet);
  144.         getPlayer().sendPacket(sendScore(val.getCurrentPlayer(), score));
  145.         val.reset();
  146.     }
  147.  
  148.     private VirtualTeam getOrCreateTeam(int line) {
  149.         if (lines[line] == null)
  150.             lines[line] = new VirtualTeam("__fakeScore" + line);
  151.  
  152.         return lines[line];
  153.     }
  154.  
  155.     /*
  156.         Factories
  157.          */
  158.     private PacketPlayOutScoreboardObjective createObjectivePacket(int mode, String displayName) {
  159.         PacketPlayOutScoreboardObjective packet = new PacketPlayOutScoreboardObjective();
  160.         // Nom de l'objectif
  161.         setField(packet, "a", player.getName());
  162.  
  163.         // Mode
  164.         // 0 : créer
  165.         // 1 : Supprimer
  166.         // 2 : Mettre à jour
  167.         setField(packet, "d", mode);
  168.  
  169.         if (mode == 0 || mode == 2) {
  170.             setField(packet, "b", displayName);
  171.             setField(packet, "c", IScoreboardCriteria.EnumScoreboardHealthDisplay.INTEGER);
  172.         }
  173.  
  174.         return packet;
  175.     }
  176.  
  177.     private PacketPlayOutScoreboardDisplayObjective setObjectiveSlot() {
  178.         PacketPlayOutScoreboardDisplayObjective packet = new PacketPlayOutScoreboardDisplayObjective();
  179.         // Slot
  180.         setField(packet, "a", 1);
  181.         setField(packet, "b", player.getName());
  182.  
  183.         return packet;
  184.     }
  185.  
  186.     private PacketPlayOutScoreboardScore sendScore(String line, int score) {
  187.         PacketPlayOutScoreboardScore packet = new PacketPlayOutScoreboardScore(line);
  188.         setField(packet, "b", player.getName());
  189.         setField(packet, "c", score);
  190.         setField(packet, "d", PacketPlayOutScoreboardScore.EnumScoreboardAction.CHANGE);
  191.  
  192.         return packet;
  193.     }
  194.  
  195.     private PacketPlayOutScoreboardScore removeLine(String line) {
  196.         return new PacketPlayOutScoreboardScore(line);
  197.     }
  198.  
  199.     /**
  200.      * This class is used to manage the content of a line. Advanced users can use it as they want, but they are encouraged to read and understand the
  201.      * code before doing so. Use these methods at your own risk.
  202.      */
  203.     public class VirtualTeam {
  204.         private final String name;
  205.         private String prefix;
  206.         private String suffix;
  207.         private String currentPlayer;
  208.         private String oldPlayer;
  209.  
  210.         private boolean prefixChanged, suffixChanged, playerChanged = false;
  211.         private boolean first = true;
  212.  
  213.         private VirtualTeam(String name, String prefix, String suffix) {
  214.             this.name = name;
  215.             this.prefix = prefix;
  216.             this.suffix = suffix;
  217.         }
  218.  
  219.         private VirtualTeam(String name) {
  220.             this(name, "", "");
  221.         }
  222.  
  223.         public String getName() {
  224.             return name;
  225.         }
  226.  
  227.         public String getPrefix() {
  228.             return prefix;
  229.         }
  230.  
  231.         public void setPrefix(String prefix) {
  232.             if (this.prefix == null || !this.prefix.equals(prefix))
  233.                 this.prefixChanged = true;
  234.             this.prefix = prefix;
  235.         }
  236.  
  237.         public String getSuffix() {
  238.             return suffix;
  239.         }
  240.  
  241.         public void setSuffix(String suffix) {
  242.             if (this.suffix == null || !this.suffix.equals(prefix))
  243.                 this.suffixChanged = true;
  244.             this.suffix = suffix;
  245.         }
  246.  
  247.         private PacketPlayOutScoreboardTeam createPacket(int mode) {
  248.             PacketPlayOutScoreboardTeam packet = new PacketPlayOutScoreboardTeam();
  249.             setField(packet, "a", name);
  250.             setField(packet, "h", mode);
  251.             setField(packet, "b", "");
  252.             setField(packet, "c", prefix);
  253.             setField(packet, "d", suffix);
  254.             setField(packet, "i", 0);
  255.             setField(packet, "e", "always");
  256.             setField(packet, "f", 0);
  257.  
  258.             return packet;
  259.         }
  260.  
  261.         public PacketPlayOutScoreboardTeam createTeam() {
  262.             return createPacket(0);
  263.         }
  264.  
  265.         public PacketPlayOutScoreboardTeam updateTeam() {
  266.             return createPacket(2);
  267.         }
  268.  
  269.         public PacketPlayOutScoreboardTeam removeTeam() {
  270.             PacketPlayOutScoreboardTeam packet = new PacketPlayOutScoreboardTeam();
  271.             setField(packet, "a", name);
  272.             setField(packet, "h", 1);
  273.             first = true;
  274.             return packet;
  275.         }
  276.  
  277.         public void setPlayer(String name) {
  278.             if (this.currentPlayer == null || !this.currentPlayer.equals(name))
  279.                 this.playerChanged = true;
  280.             this.oldPlayer = this.currentPlayer;
  281.             this.currentPlayer = name;
  282.         }
  283.  
  284.         public Iterable<PacketPlayOutScoreboardTeam> sendLine() {
  285.             List<PacketPlayOutScoreboardTeam> packets = new ArrayList<>();
  286.  
  287.             if (first) {
  288.                 packets.add(createTeam());
  289.             } else if (prefixChanged || suffixChanged) {
  290.                 packets.add(updateTeam());
  291.             }
  292.  
  293.             if (first || playerChanged) {
  294.                 if (oldPlayer != null)                                      // remove these two lines ?
  295.                     packets.add(addOrRemovePlayer(4, oldPlayer));   //
  296.                 packets.add(changePlayer());
  297.             }
  298.  
  299.             if (first)
  300.                 first = false;
  301.  
  302.             return packets;
  303.         }
  304.  
  305.         public void reset() {
  306.             prefixChanged = false;
  307.             suffixChanged = false;
  308.             playerChanged = false;
  309.             oldPlayer = null;
  310.         }
  311.  
  312.         public PacketPlayOutScoreboardTeam changePlayer() {
  313.             return addOrRemovePlayer(3, currentPlayer);
  314.         }
  315.  
  316.         public PacketPlayOutScoreboardTeam addOrRemovePlayer(int mode, String playerName) {
  317.             PacketPlayOutScoreboardTeam packet = new PacketPlayOutScoreboardTeam();
  318.             setField(packet, "a", name);
  319.             setField(packet, "h", mode);
  320.  
  321.             try {
  322.                 Field f = packet.getClass().getDeclaredField("g");
  323.                 f.setAccessible(true);
  324.                 ((List<String>) f.get(packet)).add(playerName);
  325.             } catch (NoSuchFieldException | IllegalAccessException e) {
  326.                 e.printStackTrace();
  327.             }
  328.  
  329.             return packet;
  330.         }
  331.  
  332.         public String getCurrentPlayer() {
  333.             return currentPlayer;
  334.         }
  335.  
  336.         public String getValue() {
  337.             return getPrefix() + getCurrentPlayer() + getSuffix();
  338.         }
  339.  
  340.         public void setValue(String value) {
  341.             if (value.length() <= 16) {
  342.                 setPrefix("");
  343.                 setSuffix("");
  344.                 setPlayer(value);
  345.             } else if (value.length() <= 32) {
  346.                 setPrefix(value.substring(0, 16));
  347.                 setPlayer(value.substring(16));
  348.                 setSuffix("");
  349.             } else if (value.length() <= 48) {
  350.                 setPrefix(value.substring(0, 16));
  351.                 setPlayer(value.substring(16, 32));
  352.                 setSuffix(value.substring(32));
  353.             } else {
  354.                 throw new IllegalArgumentException("Too long value ! Max 48 characters, value was " + value.length() + " !");
  355.             }
  356.         }
  357.     }
  358.  
  359.     private static void setField(Object edit, String fieldName, Object value) {
  360.         try {
  361.             Field field = edit.getClass().getDeclaredField(fieldName);
  362.             field.setAccessible(true);
  363.             field.set(edit, value);
  364.         } catch (NoSuchFieldException | IllegalAccessException e) {
  365.             e.printStackTrace();
  366.         }
  367.     }
  368. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement