[Class] DiscoArmor mit Packets

Hier könnt ihr anderen Leuten helfen, indem ihr Anleitungen oder praktische Codesegmente zur Verfügung stellt.

[Class] DiscoArmor mit Packets

Beitragvon Sep2703 » Mo 5. Jan 2015, 11:59

Hey,

ich habe mir mal die Zeit genommen und eine kleine Klasse geschrieben.
Auf vielen Servern gibt es eine "DiscoArmor", darunter versteht sich eine Lederrüstung, deren Farbe sich in einem kurzen Intervall immer wieder verändert. Dies hat einen besonders auffälligen Effekt. Das Vorhaben setzen viele mithilfe der Bukkit-API um. Das führt dazu, dass der Server für jeden Spieler auch Rüstungspunkte berechnet und entsprechend Ressourcen verbraucht.
Dieser kleine "Nachteil" hat mich dazu veranlasst, eine Klasse zu schreiben, die diese Lederrüstung nur "vortäuscht" beziehungsweise einfach nur die nötigen Packets sendet, um Ressourcen zu sparen.
Zunächst der Code:
Code: Alles auswählen
  1. package <your-package>;
  2. import java.util.ArrayList;
  3. import java.util.List;
  4. import java.util.Random;
  5. import net.minecraft.server.v1_8_R1.ItemStack;
  6. import net.minecraft.server.v1_8_R1.PacketPlayOutEntityEquipment;
  7. import org.bukkit.Bukkit;
  8. import org.bukkit.Color;
  9. import org.bukkit.Material;
  10. import org.bukkit.craftbukkit.v1_8_R1.entity.CraftPlayer;
  11. import org.bukkit.craftbukkit.v1_8_R1.inventory.CraftItemStack;
  12. import org.bukkit.entity.Player;
  13. import org.bukkit.inventory.meta.LeatherArmorMeta;
  14. import org.bukkit.plugin.Plugin;
  15. public class DiscoArmor {
  16.    private int interval;
  17.    private List<String> armorPlayers;
  18.    
  19.    public DiscoArmor(Plugin plugin, int ticksInterval) {
  20.       this.interval = ticksInterval;
  21.       this.armorPlayers = new ArrayList<String>();
  22.       Bukkit.getScheduler().runTaskTimer(plugin, new Runnable() {
  23.          
  24.          @Override
  25.          public void run() {
  26.             for (String name : armorPlayers) {
  27.                if (Bukkit.getPlayerExact(name) == null) {
  28.                   armorPlayers.remove(name);
  29.                   continue;
  30.                }
  31.                Player p = Bukkit.getPlayerExact(name);
  32.                setArmor(p, (byte) 1);
  33.             }
  34.          }
  35.       }, 0L, interval);
  36.    }
  37.    
  38.    public void addPlayer(Player p) {
  39.       armorPlayers.add(p.getName());
  40.    }
  41.    
  42.    @SuppressWarnings("deprecation")
  43.    private void setArmor(Player p, byte mode) { // Mode: 1 = New Armor, 0 = Remove Armor
  44.       List<PacketPlayOutEntityEquipment> packets = new ArrayList<PacketPlayOutEntityEquipment>(4);
  45.       for (int i = 1; i <= 4; i++) {
  46.          int id = p.getEntityId();
  47.          ItemStack istack = CraftItemStack.asNMSCopy(DiscoUtil.getBukkitArmor(i, DiscoUtil.randomColor()));
  48.          packets.add(new PacketPlayOutEntityEquipment(id, i, mode == 0 ? null : istack));
  49.       }
  50.       
  51.       for (Player on : Bukkit.getOnlinePlayers()) {
  52.          for (PacketPlayOutEntityEquipment packet : packets) {
  53.             ((CraftPlayer)on).getHandle().playerConnection.sendPacket(packet);
  54.          }
  55.       }
  56.    }
  57.    
  58.    public void removeArmor(Player p) {
  59.       armorPlayers.remove(p.getName());
  60.       setArmor(p, (byte) 0);
  61.    }
  62.    
  63.    private static class DiscoUtil {
  64.       private static org.bukkit.inventory.ItemStack boots;
  65.       private static org.bukkit.inventory.ItemStack leggings;
  66.       private static org.bukkit.inventory.ItemStack chestplate;
  67.       private static org.bukkit.inventory.ItemStack helmet;
  68.       private static Random rnd;
  69.       
  70.       static {
  71.          boots = new org.bukkit.inventory.ItemStack(Material.LEATHER_BOOTS);
  72.          leggings = new org.bukkit.inventory.ItemStack(Material.LEATHER_LEGGINGS);
  73.          chestplate = new org.bukkit.inventory.ItemStack(Material.LEATHER_CHESTPLATE);
  74.          helmet = new org.bukkit.inventory.ItemStack(Material.LEATHER_HELMET);
  75.          rnd = new Random();
  76.       }
  77.       
  78.       private static org.bukkit.inventory.ItemStack getBukkitArmor(int slot, Color bukkitColor) { // Slot: 1 = Boots, 2 = Leggings, 3 = Chestplate, 4 = Helmet
  79.          switch (slot) {
  80.          case 1:
  81.          {
  82.             LeatherArmorMeta meta = (LeatherArmorMeta) boots.getItemMeta();
  83.             meta.setColor(bukkitColor);
  84.             boots.setItemMeta(meta);
  85.             return boots;
  86.          }
  87.          case 2:
  88.          {
  89.             LeatherArmorMeta meta = (LeatherArmorMeta) leggings.getItemMeta();
  90.             meta.setColor(bukkitColor);
  91.             leggings.setItemMeta(meta);
  92.             return leggings;
  93.          }
  94.          case 3:
  95.          {
  96.             LeatherArmorMeta meta = (LeatherArmorMeta) chestplate.getItemMeta();
  97.             meta.setColor(bukkitColor);
  98.             chestplate.setItemMeta(meta);
  99.             return chestplate;
  100.          }
  101.          case 4:
  102.          {
  103.             LeatherArmorMeta meta = (LeatherArmorMeta) helmet.getItemMeta();
  104.             meta.setColor(bukkitColor);
  105.             helmet.setItemMeta(meta);
  106.             return helmet;
  107.          }
  108.          default:
  109.             return boots;
  110.          }
  111.       }
  112.       
  113.       private static Color randomColor() {
  114.          switch (rnd.nextInt(16)) { // 0 to 15
  115.          case 0: return Color.AQUA;
  116.          case 1: return Color.BLACK;
  117.          case 2: return Color.BLUE;
  118.          case 3: return Color.FUCHSIA;
  119.          case 4: return Color.GRAY;
  120.          case 5: return Color.GREEN;
  121.          case 6: return Color.LIME;
  122.          case 7: return Color.MAROON;
  123.          case 8: return Color.NAVY;
  124.          case 9: return Color.OLIVE;
  125.          case 10: return Color.ORANGE;
  126.          case 11: return Color.PURPLE;
  127.          case 12: return Color.RED;
  128.          case 13: return Color.SILVER;
  129.          case 14: return Color.TEAL;
  130.          case 15: return Color.WHITE;
  131.          default:
  132.             return Color.YELLOW;
  133.          }
  134.       }
  135.    }
  136. }


Die Klasse könnt ihr einfach kopieren und in euer Projekt übernehmen. Ein Blick auf die ersten Zeilen verrät, dass ihr (Spigot) für Minecraft 1.8 benötigt. Mit ein paar kleinen Änderungen sollte die Klasse jedoch auch für ältere Versionen funktionieren.



Verwendung

Um die Klasse zu verwenden, braucht ihr eine Instanz. Diese lässt sich einfach über den gegebenen Konstruktor erzeugen. Ich empfehle euch, diese Instanz statisch in irgendeiner Klasse (z.B. Haupt-Klasse) zu hinterlegen, oder sie über Membervariablen in den einzelnen Klassen immer zu referenzieren.
Wenn ihn nun eine Instanz vorliegen habt, könnt ihr mit der addPlayer(Player p) Methode einfach einen neuen Spieler hinzufügen. Hinzugefügte Spieler werden den anderen Spielern (und sich selbst) mit einer "DiscoArmor" angezeigt.
Die removeArmor(Player p) Methode entfernt einen Spieler wieder, sodass dieser seine Rüstung verliert / sie nicht mehr angezeigt wird.

Das war's auch schon ;)

_______________________________________________

Bugs und Verbesserungsvorschläge könnt ihr mir hier natürlich gerne mitteilen.
Die Klasse dürft ihr in euren Projekten frei verwenden. Wenn eine andere Person explizit nach dem Entwickler fragt, wäre es nett, mich zu erwähnen.


Janhektor / Sep2703
Du möchtest programmieren lernen oder dein Bukkit-/Spigot-Wissen erweitern?
Hier habe ich für dich kostenlose Tutorials: https://youtube.com/janhektor
Benutzeravatar
Sep2703
 
Beiträge: 677
Registriert: Mi 8. Jan 2014, 15:13
Wohnort: 127.0.0.1

Re: [Class] DiscoArmor mit Packets

Beitragvon TVXtrem » Mo 17. Aug 2015, 16:35

Hey :),

ich verwende momentan die Spigot 1.8.3 und irgendwie geht das ganze nicht, wie es soll. Ich verwende lediglich diese Methode (ein wenig abgeändert), um die unterschiedlichen Rüstungsfarben bei meinem TTT Plugin zu regeln.
Code: Alles auswählen
  1. private static void setArmor(Player p, Color c, Collection<? extends Player> recievers) {
  2.       int id = p.getEntityId();
  3.       ItemStack armor = new ItemStack(Material.LEATHER_CHESTPLATE);
  4.       LeatherArmorMeta meta = (LeatherArmorMeta) armor.getItemMeta();
  5.       meta.setColor(c);
  6.       armor.setItemMeta(meta);
  7.       net.minecraft.server.v1_8_R2.ItemStack istack = CraftItemStack.asNMSCopy(armor);
  8.       PacketPlayOutEntityEquipment packet = new PacketPlayOutEntityEquipment(id, 2, istack);
  9.       for (Player on : recievers) {
  10.          ((CraftPlayer) on).getHandle().playerConnection
  11.                   .sendPacket(packet);
  12.       }
  13.    }


Die Methode verwende ich zu Beginn der Runde beziehungsweise nach der Rollenverteilung folgendermaßen:

Code: Alles auswählen
  1. for(Player a : PlayerManager.getInnocents()){
  2.          setArmor(a, Color.GRAY, Bukkit.getOnlinePlayers());
  3.       }
  4.       for(Player a : PlayerManager.getDetectives()){
  5.          setArmor(a, Color.BLUE, Bukkit.getOnlinePlayers());
  6.       }
  7.       for(Player a : PlayerManager.getTraitors()){
  8.          setArmor(a, Color.GRAY, PlayerManager.getInnocents());
  9.          setArmor(a, Color.GRAY, PlayerManager.getDetectives());
  10.          setArmor(a, Color.RED, PlayerManager.getTraitors());
  11.       }


Doch irgendwie sehe ich keinerlei Rüstung. :/
Vielen Dank im Vorraus!

MfG,
TVXtrem :)
Benutzeravatar
TVXtrem
 
Beiträge: 8
Registriert: Di 6. Mai 2014, 15:30

Re: [Class] DiscoArmor mit Packets

Beitragvon Summerfeeling » Di 18. Aug 2015, 13:42

TVXtrem hat geschrieben:Hey :),

ich verwende momentan die Spigot 1.8.3 und irgendwie geht das ganze nicht, wie es soll. Ich verwende lediglich diese Methode (ein wenig abgeändert), um die unterschiedlichen Rüstungsfarben bei meinem TTT Plugin zu regeln.
Code: Alles auswählen
  1. private static void setArmor(Player p, Color c, Collection<? extends Player> recievers) {
  2.       int id = p.getEntityId();
  3.       ItemStack armor = new ItemStack(Material.LEATHER_CHESTPLATE);
  4.       LeatherArmorMeta meta = (LeatherArmorMeta) armor.getItemMeta();
  5.       meta.setColor(c);
  6.       armor.setItemMeta(meta);
  7.       net.minecraft.server.v1_8_R2.ItemStack istack = CraftItemStack.asNMSCopy(armor);
  8.       PacketPlayOutEntityEquipment packet = new PacketPlayOutEntityEquipment(id, 2, istack);
  9.       for (Player on : recievers) {
  10.          ((CraftPlayer) on).getHandle().playerConnection
  11.                   .sendPacket(packet);
  12.       }
  13.    }


Die Methode verwende ich zu Beginn der Runde beziehungsweise nach der Rollenverteilung folgendermaßen:

Code: Alles auswählen
  1. for(Player a : PlayerManager.getInnocents()){
  2.          setArmor(a, Color.GRAY, Bukkit.getOnlinePlayers());
  3.       }
  4.       for(Player a : PlayerManager.getDetectives()){
  5.          setArmor(a, Color.BLUE, Bukkit.getOnlinePlayers());
  6.       }
  7.       for(Player a : PlayerManager.getTraitors()){
  8.          setArmor(a, Color.GRAY, PlayerManager.getInnocents());
  9.          setArmor(a, Color.GRAY, PlayerManager.getDetectives());
  10.          setArmor(a, Color.RED, PlayerManager.getTraitors());
  11.       }


Doch irgendwie sehe ich keinerlei Rüstung. :/
Vielen Dank im Vorraus!

MfG,
TVXtrem :)

Die 2 ist meines Wissens nach die Hose. Versuch mal die 3.
Grüße
Summerfeeling | Timo
Benutzeravatar
Summerfeeling
 
Beiträge: 1300
Registriert: Sa 15. Jun 2013, 18:43
Wohnort: Viersen

Re: [Class] DiscoArmor mit Packets

Beitragvon TVXtrem » Di 18. Aug 2015, 21:45

Summerfeeling hat geschrieben:Die 2 ist meines Wissens nach die Hose. Versuch mal die 3.


// EDIT Der Slot ist schon 2 für Brustpanzer, jedoch sieht nur jeder Spieler seine eigene Rüstung und nicht die der anderen. :(
Benutzeravatar
TVXtrem
 
Beiträge: 8
Registriert: Di 6. Mai 2014, 15:30

Re: [Class] DiscoArmor mit Packets

Beitragvon Summerfeeling » Mi 19. Aug 2015, 20:17

TVXtrem hat geschrieben:
Summerfeeling hat geschrieben:Die 2 ist meines Wissens nach die Hose. Versuch mal die 3.


// EDIT Der Slot ist schon 2 für Brustpanzer, jedoch sieht nur jeder Spieler seine eigene Rüstung und nicht die der anderen. :(

Hm, Code sieht gut aus. Wüsste nicht woran es liegt.
Grüße
Summerfeeling | Timo
Benutzeravatar
Summerfeeling
 
Beiträge: 1300
Registriert: Sa 15. Jun 2013, 18:43
Wohnort: Viersen

Re: [Class] DiscoArmor mit Packets

Beitragvon TVXtrem » Do 20. Aug 2015, 10:49

Schade. :/ Werde wohl mal eine andere Möglichkeit suchen müssen.
Benutzeravatar
TVXtrem
 
Beiträge: 8
Registriert: Di 6. Mai 2014, 15:30


Zurück zu Anleitungen

Wer ist online?

Mitglieder in diesem Forum: Google [Bot] und 5 Gäste

cron