[Komplett] Join-Schilder mit Java-Network und BungeeCord

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

[Komplett] Join-Schilder mit Java-Network und BungeeCord

Beitragvon ilouHD » Sa 29. Mär 2014, 19:05

Vorbereitung

Hallo Zusammen,

ich möchte euch nun nach und nach zeigen, wie ihr ein Java-Netzwerk programmieren könnt. Später könnt ihr dann über Schilder zu einzelnen Servern joinen, oder euch Informationen über die Spieleranzahl, MotD oder Ähnliches holen.

Jetzt, in Teil 1, werden wir nichts programmieren. Ich werde euch jetzt nur mitteilen, was ihr berücksichtigen müsst, und was das Tutorial beinhalten wird.

Achtung! Das hier beschriebene Tutorial wird nichts für Anfänger. Bitte kopiert diese Anleitung nicht einfach, da es euch GARNICHT weiterhilft, wenn ihr sie kopiert und einfügt, ohne auch nur eine Zeile zu verstehen

Das Network-Programming in Java ist eins der wahrscheinlich schwierigsten Themen in Java, bzw. für Bukkit-Programmierer. Diese Methode ist jedoch ziemlich Ressourcensparend (finde ich - ermittelt durch Tests).

Folgendes ist in dieser Anleitung enthalten:
- Server Anpingen ( Teil 2 )
- Schilder mit PlayerCount, MotD, ... ( Teil 3 )
- Updaten der Schilder ( Teil 3 )
- Joinen über Schilder ( Teil 4 )

Nochmal kurz zusammengefasst:
Wenn ihr dieses Tutorial und den in diesem Tutorial beschriebenen Code nicht versteht, kopiert ihn nicht und fügt ihn einfach ein, sondern fragt nach. Ihr könnt mit diesem Code gar nichts anfangen, wenn ihr ihn nicht verstanden habt.

--------------------------------------------------

Teil 2 - Server Anpingen

In diesem Teil, möchte ich euch zeigen, wie ihr einen Server Anpingen könnt. Da dieser Teil sehr lang wird, fangen wir auch direkt an.

Zuerst erstellen wir uns eine Klasse. Ich nenne sie "Server". Dort müssen wir uns einen String, den host, und einen int, den Port, anlegen. Jetzt müssen wir den host, und den port, richtig 'einstellen'. Wenn ihr soweit seid, sollte die "Server"-Klasse bei euch so aussehen:
Code: Alles auswählen
  1. public class Server {
  2.    
  3.    private String host;
  4.    private int port;
  5.    
  6.    public Server(String host, int port) {
  7.       this.host = host;
  8.       this.port = port;
  9.    }
  10.    
  11.    public Server(String host) {
  12.       this.host = host;
  13.       this.port = 25565;
  14.    }
  15.    
  16.    public Server() {
  17.       this.host = "127.0.0.1";
  18.       this.port = 25565;
  19.    }
  20. }

Hier habe ich jetzt eingestellt, dass der host die IP des localhost hat - "127.0.0.1" und den Minecraft-Standard-Port "25565". Diese IP ist die IP, von wo aus wir den Server anpingen. Wenn euer Proxy-Server zum Beispiel die IP "13.08.4.578", dann tragt ihr, statt "127.0.0.1", "13.08.4.578" eintragen, und den Port ebenfalls anpassen.

Der Teil, der jetzt kommt, ist das komplizierteste am ganzen Tutorial. Der eigentliche Ping. Dieser wird auch in der "Server"-Klasse ausgeführt.
Für das Pingen benötigen wir einen Socket, einen OutPutStream, einen DataOutputStream, einen InputStream und einen InputStreamReader. Die "Server"-Klasse sollte bis jetzt wie folgt aussehen:
Code: Alles auswählen
  1. public class Server {
  2.    
  3.    private String host;
  4.    private int port;
  5.    
  6.    public Server(String host, int port) {
  7.       this.host = host;
  8.       this.port = port;
  9.    }
  10.    
  11.    public Server(String host) {
  12.       this.host = host;
  13.       this.port = 25565;
  14.    }
  15.    
  16.    public Server() {
  17.       this.host = "127.0.0.1";
  18.       this.port = 25565;
  19.    }
  20.    
  21.    public String parseData(Connection connection) {
  22.       try {
  23.          
  24.          Socket socket = new Socket();
  25.          OutputStream os;
  26.          DataOutputStream dos;
  27.          InputStream is;
  28.          InputStreamReader isr;
  29.       } catch (Exception e) {
  30.          
  31.       }
  32.       return null;
  33.    }
  34. }


Wenn ihr das soweit habt, müssen wir erstmal ein paar Dinge einstellen.
Zuerst müssen wir dem Socket ein TimeOut geben und dem Socket sagen, 'wo er ist'. Das machen wir so:
Code: Alles auswählen
  1.          socket.setSoTimeout(2500);
  2.          socket.connect(new InetSocketAddress(host, port));


Nun müssen wir den DataOutputStream einstellen. Dazu verwenden wir folgenden Code:
Code: Alles auswählen
  1.          os = socket.getOutputStream();
  2.          dos = new DataOutputStream(os);

Wie man hier sehen kann, sagen wir, dass der oben angegebene OutputStream os der OutputStream des Sockets ist. Diesen OutputStream verbinden wir mit dem DataOutputStream dos.

Weiterhin müssen wir den InputStream regeln. Dieser sieht wie folgt aus:
Code: Alles auswählen
  1.          is = socket.getInputStream();
  2.          isr = new InputStreamReader(is, Charset.forName("UTF-16BE"));


Soweit, so gut.
Wir stellen nun ein, was gesendet und empfangen wird. Das machen wir wieder mit dem InputStream und dem DataOutputStream. Am Ende sollte dies so aussehen:
Code: Alles auswählen
  1.          dos.write(new byte[] { (byte) 0xFE, (byte) 0x01 });
  2.          
  3.          int packetID = is.read();

Wir haben hier jetzt einen neuen int, der packetID heißt. Er regelt den InputStream.
Mit dem DataOutputStream senden wir neue bytes, die für uns wichtig sind.

Der nun folgende Teil, ist für mich (leider) noch nicht ganz klar. Daher verstehe ich ihn nicht wirklich, aber er ist richtig.
Code: Alles auswählen
  1.          if(packetID == -1) {
  2.             System.out.println("Invalid Packet ID! (End Of Stream)");
  3.          }
  4.          if(packetID != 0xFF) {
  5.             System.out.println("Invalid Packet Id! " + packetID);
  6.          }

Hier fragen wir ab, ob die packetID falsch ist. Ist sie das, dann schreiben wir das in die Console.

Nun erstellen wir uns einen neuen int. Er heißt length. Er enthält den InputStreamReader und liest ihn aus. Schließlich sieht es so aus:
Code: Alles auswählen
  1.          int length = isr.read();


So. Wieder zurück, geht es auch direkt weiter.
Wir haben uns jetzt einen InputStreamRead als int angelegt. Er liest den Input. Als nächstes müssen wir abfragen, ob dieser int falsch ist. Das machen wir mit den folgenden 2 Methoden. Hier sind sie:
Code: Alles auswählen
  1.          if(length == -1) {
  2.             System.out.println("End Of Stream");
  3.          }
  4.          
  5.          if(length == 0) {
  6.             System.out.println("Invalid length");
  7.          }

Wenn der Stream -1 ist, also keine Verbindung besteht, dann senden wir der Konsole "End Of Stream". Ist er 0, stimmt etwas nicht, obwohl eine Verbindung besteht. Auch in diesem Fall senden wir es der Konsole.
Weiter gehts. Der ping ist fast fertig.

Nun benötigen wir einen Character, kurz char. Dies ist ein Datentyp um Datenbereiche (z.B: length) zu repräsentieren. Das sieht dann so aus:
Code: Alles auswählen
  1.          char[] chars = new char[length];


Vorletzter Schritt beim Anpingen ist die chars zu Vergleichen. Das machen wir so:
Code: Alles auswählen
  1.          if(isr.read(chars, 0, length) != length) {
  2.             System.out.println("End Of Stream");
  3.          }

Stimmt der Char und die length nicht mit der length überein, senden wir - wer hätte es gedacht - an die Konsole eine Fehlermeldung.

Wenn wir dann soweit wären, können wir uns zum letzten Schritt begeben:
Die benötigten Daten holen. Das ganze wird so gemacht:
Code: Alles auswählen
  1.          String string = new String(chars);
  2.          String[] data = string.split("\0");
  3.          
  4.          if(connection == Connection.ONLINE_PLAYERS) {
  5.             return data[4];
  6.          } else if(connection == Connection.MOTD) {
  7.             return data[3];
  8.          } else if(connection == Connection.MAX_PLAYERS) {
  9.             return data[5];
  10.          } else {
  11.             System.out.println("Connection value not handled!");
  12.          }

Das ist eigentlich ganz einfach. Wir fragen die einzelnen Enums (ONLINE_PLAYERS, MOTD, MAX_PLAYERS) ab und returnen die dafür wichtige Information. Das Enum machen wir ganz einfach. Es ist in der kompletten vor der letzten geschweiften Klammer zu ("}"). Das Enum MUSS, wenn ihr es nach diesem Tutorial hier macht, "Connection" heißen, sonst funktioniert es nicht. Wenn ihr fertig seid, sollte eure "Server"-Klasse so aussehen:
Code: Alles auswählen
  1. package de.Test.Test;
  2. import java.io.DataOutputStream;
  3. import java.io.InputStream;
  4. import java.io.InputStreamReader;
  5. import java.io.OutputStream;
  6. import java.net.InetSocketAddress;
  7. import java.net.Socket;
  8. import java.nio.charset.Charset;
  9. public class Server {
  10.    
  11.    private String host;
  12.    private int port;
  13.    
  14.    public Server(String host, int port) {
  15.       this.host = host;
  16.       this.port = port;
  17.    }
  18.    
  19.    public Server(String host) {
  20.       this.host = host;
  21.       this.port = 25565;
  22.    }
  23.    
  24.    public Server() {
  25.       this.host = "127.0.0.1";
  26.       this.port = 25565;
  27.    }
  28.    
  29.    public String parseData(Connection connection) {
  30.       try {
  31.          
  32.          Socket socket = new Socket();
  33.          OutputStream os;
  34.          DataOutputStream dos;
  35.          InputStream is;
  36.          InputStreamReader isr;
  37.          
  38.          socket.setSoTimeout(2500);
  39.          socket.connect(new InetSocketAddress(host, port));
  40.          
  41.          os = socket.getOutputStream();
  42.          dos = new DataOutputStream(os);
  43.          
  44.          is = socket.getInputStream();
  45.          isr = new InputStreamReader(is, Charset.forName("UTF-16BE"));
  46.          
  47.          dos.write(new byte[] { (byte) 0xFE, (byte) 0x01 });
  48.          
  49.          int packetID = is.read();
  50.          
  51.          if(packetID == -1) {
  52.             System.out.println("Invalid Packet ID! (End Of Stream)");
  53.          }
  54.          if(packetID != 0xFF) {
  55.             System.out.println("Invalid Packet Id! " + packetID);
  56.          }
  57.          
  58.          int length = isr.read();
  59.          
  60.          if(length == -1) {
  61.             System.out.println("End Of Stream");
  62.          }
  63.          
  64.          if(length == 0) {
  65.             System.out.println("Invalid length");
  66.          }
  67.          
  68.          char[] chars = new char[length];
  69.          
  70.          if(isr.read(chars, 0, length) != length) {
  71.             System.out.println("End Of Stream");
  72.          }
  73.          
  74.          String string = new String(chars);
  75.          String[] data = string.split("\0");
  76.          
  77.          if(connection == Connection.ONLINE_PLAYERS) {
  78.             return data[4];
  79.          } else if(connection == Connection.MOTD) {
  80.             return data[3];
  81.          } else if(connection == Connection.MAX_PLAYERS) {
  82.             return data[5];
  83.          } else {
  84.             System.out.println("Connection value not handled!");
  85.          }
  86.          
  87.       } catch (Exception e) {
  88.          
  89.       }
  90.       return null;
  91.    }
  92.    
  93.    public enum Connection {
  94.       ONLINE_PLAYERS, MAX_PLAYERS, MOTD
  95.    }
  96. }


Wie man sieht, habe ich jetzt in diesem Falle nicht die Exception und das return-Statement mit reingebaut. Aber dafür die ganze Klasse zur Übersicht.

--------------------------------------------------

Teil 3 - Schilder erstellen und Updaten

In diesem teil möchte ich euch zeigen, wie ihr Schilder setzen könnt, und diese dann auch updatet. Also, verschwenden wir keine Zeit, sonder fangen direkt an:

Zuerst einmal erstellen wir uns die Klasse "Game". So heißt meine Main-Klasse. Jedoch könnt ihr auch eine eigene Listener-Klasse erstellen.
Wir implementieren den Listener.

In dieser "Game"-Klasse erstellen wir uns nun eine Instance, da wir die später brauchen. Das machen wir wie folgt:
Code: Alles auswählen
  1. public class Game extends JavaPlugin implements Listener {
  2.    
  3.    public static Game instance;
  4.    
  5.    public Game() {
  6.       instance = this;
  7.    }
  8.    
  9.    public static Game getInstance() {
  10.       return instance;
  11.    }
  12. }


Wenn wir das gemacht haben, dann erstellen wir uns erst einmal eine .yml-Datei zum Speichern der Location des Schildes. Bei mir sieht das so aus:
Code: Alles auswählen
  1.    public static File locFile = new File("plugins/Test", "Locations.yml");
  2.    public static FileConfiguration locCfg = YamlConfiguration.loadConfiguration(locFile);


In den onEnable()-teil eures Plugins, könnt ihr direkt den Listener registrieren. Dazu kommt meine updateSign()-Methode.
Diese Methode verwendet einen Scheduler, der das Schild updatet und daher im OnEnable()-Teil gestartet werden sollte
Gesagt, getan, das Beispiel:
Code: Alles auswählen
  1.    @Override
  2.    public void onEnable() {
  3.       Bukkit.getPluginManager().registerEvents(this, this);
  4.       updateSign();
  5.       Messenger();
  6.    }


Soweit so gut. Als nächstes brauchen wir einen EventHandler mit dem SignChangeEvent in der Variablen e. Wir setzen außerdem direkt den Spieler mit der Variable p und die Location des Schildes als loc. So weit, so gut. So sieht das Event bis jetzt aus.
Code: Alles auswählen
  1.    @EventHandler
  2.    public void onSignChange(SignChangeEvent e) {
  3.       Player p = e.getPlayer();
  4.       Location loc = e.getBlock().getLocation();
  5.    }

Ziemlich mager. Was jetzt kommt, ist das wichtigste. Das speichern der Location des Schildes, damit wir es später Updaten können. Wenn wir das haben, ist das Event fertig. Am Ende sieht das komplette Event so aus:
Code: Alles auswählen
  1.    @EventHandler
  2.    public void onSignChange(SignChangeEvent e) {
  3.       Player p = e.getPlayer();
  4.       Location loc = e.getBlock().getLocation();
  5.       if(e.getLine(0).toLowerCase().contains("[join]")) {
  6.          locCfg.set("loc.sign.X", loc.getX());
  7.          locCfg.set("loc.sign.Y", loc.getY());
  8.          locCfg.set("loc.sign.Z", loc.getZ());
  9.          locCfg.set("loc.sign.World", loc.getWorld().getName());
  10.          
  11.          e.setLine(0, "§4§l█████████");
  12.          e.setLine(1, "§4§lPinging");
  13.          e.setLine(2, "§4§l...");
  14.          e.setLine(3, "§4§l█████████");
  15.          try {
  16.             locCfg.save(locFile);
  17.             p.sendMessage("§aSchild erstellt");
  18.          } catch (IOException e1) {
  19.             p.sendMessage("§cSchild NICHT erstellt");
  20.             e1.printStackTrace();
  21.          }
  22.       }
  23.    }

Das Pinging... habe ich nur so gesetzt.

Jetzt wollen wir das Schild updaten. Dazu verwenden wir einen Scheduler. Scheduler MUSS Asynchron laufen. Sonst besteht die Gefahr, dass bei Laggs, oder Ähnlichem, das Schild nicht mehr geupdatet wird.
Wenn wird den Scheduler haben, sieht es so aus:
Code: Alles auswählen
  1.    public void updateSign() {
  2.       Bukkit.getScheduler().runTaskTimerAsynchronously(this, new Runnable() {
  3.          @Override
  4.          public void run() {
  5.          }
  6.       }, 200L, 5L);
  7.    }

In diesem Fall, dauert das erste Updaten, sprich nach dem Start 10 Sekunden, damit sich der Server nicht aufhängt, oder Ähnliches. Das Updaten geschieht dann etwa alle 0.25 Sekunden, wobei es reicht, wenn ihr den Long auf 20 stellt. Das bleibt euch jedoch überlassen.

Habt ihr das, machen wir in der void run() folgendes:
- Wir getten die Location des Schildes
- Setzen diese Location zu einem Schild
- Sagen dem Server, welches Schild wir updaten
- Updaten es

Es hört sich kompliziert an, ist aber nicht mehr als das:
Code: Alles auswählen
  1.             double x = locCfg.getDouble("loc.sign.X");
  2.             double y = locCfg.getDouble("loc.sign.Y");
  3.             double z = locCfg.getDouble("loc.sign.Z");
  4.             World w = Bukkit.getWorld(locCfg.getString("loc.sign.World"));
  5.             
  6.             Location loc = new Location(w, x, y, z);
  7.             
  8.             Sign s = (Sign) loc.getBlock().getState();
  9.             
  10.             Server server = new Server("127.0.0.1"); //localhost-IP
  11.             
  12.             s.setLine(3, server.parseData(Connection.ONLINE_PLAYERS) + " / " + server.parseData(Connection.MAX_PLAYERS));
  13.             s.setLine(2, server.parseData(Connection.MOTD));
  14.             


Das sähe auf dem Schild jetzt aber hässlig aus. Wir erstellen uns jetzt ein paar if-Abfragen. Ich mache jetzt 2. Die sehen dann so aus:
Code: Alles auswählen
  1.             if(s.getLine(2).equalsIgnoreCase("null")) {
  2.                s.setLine(0, "§4§l█████████");
  3.                s.setLine(1, "§4§lOFFLINE");
  4.                s.setLine(2, "§4§l- / -");
  5.                s.setLine(3, "§4§l█████████");
  6.             } else if (!s.getLine(2).equalsIgnoreCase("null")){
  7.                s.setLine(0, "§7[Join]");
  8.                s.setLine(1, null);
  9.                s.setLine(2, "§2" + server.parseData(Connection.MOTD));
  10.                s.setLine(3, "§f" + server.parseData(Connection.ONLINE_PLAYERS) + "/" + server.parseData(Connection.MAX_PLAYERS));
  11.             }

Das mit der ersten if-Abfrage will ich kurz erklären.
Wenn der Server Unerreichbar ist, gibt der Server null aus, und würde somit auch null auf das Schild setzen. Deswegen Fragen wir ab, ob es null ist und setzen dann den "OFFLINE-Bildschirm" auf das Schild. Ansonsten setzen wir den "JOIN-Bildschirm"

Wenn das getan ist, müssen wir das Schild updaten. das machen wir im Scheduler, nach den if-Abfragen mit:
Code: Alles auswählen
  1. s.update();


Hört sich unverständlich an? Hier ist der komplette Scheduler:
Code: Alles auswählen
  1.    public void updateSign() {
  2.       Bukkit.getScheduler().runTaskTimerAsynchronously(this, new Runnable() {
  3.          @Override
  4.          public void run() {
  5.             double x = locCfg.getDouble("loc.sign.X");
  6.             double y = locCfg.getDouble("loc.sign.Y");
  7.             double z = locCfg.getDouble("loc.sign.Z");
  8.             World w = Bukkit.getWorld(locCfg.getString("loc.sign.World"));
  9.             
  10.             Location loc = new Location(w, x, y, z);
  11.             
  12.             Sign s = (Sign) loc.getBlock().getState();
  13.             
  14.             Server server = new Server(Game.SrvCfg.getString("Server." + s.getLine(1) + ".IP"));
  15.             
  16.             s.setLine(3, server.parseData(Connection.ONLINE_PLAYERS) + " / " + server.parseData(Connection.MAX_PLAYERS));
  17.             s.setLine(2, server.parseData(Connection.MOTD));
  18.             
  19.             if(s.getLine(2).equalsIgnoreCase("null")) {
  20.                s.setLine(0, "§4§l█████████");
  21.                s.setLine(1, "§4§lOFFLINE");
  22.                s.setLine(2, "§4§l- / -");
  23.                s.setLine(3, "§4§l█████████");
  24.             } else if (!s.getLine(2).equalsIgnoreCase("null")){
  25.                s.setLine(0, "§7[Join]");
  26.                s.setLine(1, null);
  27.                s.setLine(2, "§2" + server.parseData(Connection.MOTD));
  28.                s.setLine(3, "§f" + server.parseData(Connection.ONLINE_PLAYERS) + "/" + server.parseData(Connection.MAX_PLAYERS));
  29.             }
  30.             s.update();
  31.          }
  32.          
  33.       }, 100L, 10L);
  34.    }


--------------------------------------------------

Teil 4 - Auf den Server connecten

Tut mir Leid, dass dieser Teil jetzt so spät erst kommt. Aber das ändert nichts. Machen wir weiter!:

Als erstes erstelle ich mir wieder mal eine neue Klasse. Sie heißt bei mir "ClickListener". Da fragen wir erstmal ab, ob der Block, mit dem wir im PlayerInteractEvent interagieren, ein Schild ist und fragen nach der ersten Zeile, ob diese unseren "Bedingungen" entspricht. Soweit sollte dies so aussehen:
Code: Alles auswählen
  1. public class ClickListener implements Listener {
  2.    
  3.    @EventHandler
  4.    public void onClick(PlayerInteractEvent e) {
  5.       if(e.getAction() == Action.RIGHT_CLICK_BLOCK) {
  6.          if(e.getClickedBlock().getState() instanceof Sign) {
  7.             Player p = e.getPlayer();
  8.             if(s.getLine(0).equalsIgnoreCase("§7[Join]")) {
  9.             }
  10.          }
  11.       }
  12.    }


Nun setzen wir bestimmte Funktionen, die uns weiterleiten. Dass sollte dann in etwa so aussehen:
Code: Alles auswählen
  1.    @EventHandler
  2.    public void onClick(PlayerInteractEvent e) {
  3.       if(e.getAction() == Action.RIGHT_CLICK_BLOCK) {
  4.          if(e.getClickedBlock().getState() instanceof Sign) {
  5.             Player p = e.getPlayer();
  6.             Sign s = (Sign) e.getClickedBlock().getState();
  7.             ByteArrayOutputStream b = new ByteArrayOutputStream();
  8.             DataOutputStream out = new DataOutputStream(b);
  9.             if(s.getLine(0).equalsIgnoreCase("§7[Join]")) {
  10.                
  11.             }
  12.          }
  13.       }
  14.    }


Wir senden in diesem Falle, einen Array an bytes über unseren OutputStream. Diesen benötigen wir, um den Spieler zu den Servern zu teleportieren.

Wenn der Spieler jetzt auf das Schild klickt, passiert noch rein gar nichts. Wir müssen jetzt über unseren DataOutputStream ein UTF "schreiben", dass es uns ermöglicht, die Daten auszutauschen. Gesagt, getan -> So sieht der ganze ClickListener aus.
Code: Alles auswählen
  1. public class ClickListener implements Listener {
  2.    
  3.    @EventHandler
  4.    public void onClick(PlayerInteractEvent e) {
  5.       if(e.getAction() == Action.RIGHT_CLICK_BLOCK) {
  6.          if(e.getClickedBlock().getState() instanceof Sign) {
  7.             Player p = e.getPlayer();
  8.             Sign s = (Sign) e.getClickedBlock().getState();
  9.             ByteArrayOutputStream b = new ByteArrayOutputStream();
  10.             DataOutputStream out = new DataOutputStream(b);
  11.             if(s.getLine(0).equalsIgnoreCase("§7[Join]")) {
  12.                e.getPlayer().sendMessage("Verbinde zu Server...");
  13.                try {
  14.                   out.writeUTF("Connect");
  15.                   out.writeUTF("127.0.0.1:25565");
  16.                } catch (IOException ioe) {
  17.                   ioe.printStackTrace();
  18.                }
  19.                p.sendPluginMessage(Game.getInstance(), "BungeeCord", b.toByteArray());
  20.             }
  21.          }
  22.       }
  23.    }
  24. }

Das senden des Spielers muss in einen try/catch-Block. Darunter senden wir über unser Plugin eine Message, mit der, der Spieler teleportiert wird.

Damit das ganze mit BungeeCord auch funktioniert, müssen wir BungeeCord noch registrieren. Das findet in der onEnable-Methode statt:
Code: Alles auswählen
  1.    @Override
  2.    public void onEnable() {
  3.       getServer().getMessenger().registerOutgoingPluginChannel(this, "BungeeCord");
  4.    }


Das war es dann. Unser Spieler kann jetzt die Kabel zum glühen bringen, und auf jeden Server, der in dem Netzwerk registriert ist, sich teleportieren.

--------------------------------------------------

Ich hoffe, ich konnte euch weiterhelfen. Bei Bedarf, lade ich noch den kompletten SourceCode bei github oder so hoch. Dann ist es übersichtlicher, da ich vieles doppelt und dreifach gemacht habe.

Mit freundlichen Grüßen,
marcsven
Zuletzt geändert von ilouHD am Do 24. Apr 2014, 12:14, insgesamt 12-mal geändert.
Bild
Benutzeravatar
ilouHD
 
Beiträge: 1733
Registriert: Do 9. Jan 2014, 14:49

Re: Network-Programming #1

Beitragvon tahu98 » Sa 29. Mär 2014, 21:06

Und wo ist jetzt das Tutorial?
Bild
Benutzeravatar
tahu98
 
Beiträge: 231
Registriert: Mo 2. Sep 2013, 13:46

Re: Network-Programming

Beitragvon ilouHD » So 30. Mär 2014, 07:46

tahu98 hat geschrieben:Und wo ist jetzt das Tutorial?


Ist doch da. Kam nur etwas später, wegen eclipse-Problemen.
Bild
Benutzeravatar
ilouHD
 
Beiträge: 1733
Registriert: Do 9. Jan 2014, 14:49

Re: Network-Programming

Beitragvon DonXs » So 30. Mär 2014, 08:16

Hey marcsven,
das Tutorial ist zwar ganz gut und gut für anfänger,
jedoch ist es fast genau das gleiche Tutorial wie das von BastiFreak2000,
nur das du es ein wenig genauer erklärst.
Ausserdem passt das Thema überhaupt nicht mit dem was du erklärt hast,
denn Network-Programming bezieht sich nicht nur auf Schilder mit Onlinecount...,
sondern auch mit z.b. einer erklärung der einzelnen Outputstream/Inputstreams oder z.b. Der unterschiedlichen Sockets: ServerSocket, DatagramSocket... .

MfG DonXs
Benutzeravatar
DonXs
 
Beiträge: 102
Registriert: So 2. Feb 2014, 17:15
Wohnort: NRW

Re: Network-Programming

Beitragvon ilouHD » So 30. Mär 2014, 12:30

DonXs hat geschrieben:Hey marcsven,
das Tutorial ist zwar ganz gut und gut für anfänger,
jedoch ist es fast genau das gleiche Tutorial wie das von BastiFreak2000,
nur das du es ein wenig genauer erklärst.
Ausserdem passt das Thema überhaupt nicht mit dem was du erklärt hast,
denn Network-Programming bezieht sich nicht nur auf Schilder mit Onlinecount...,
sondern auch mit z.b. einer erklärung der einzelnen Outputstream/Inputstreams oder z.b. Der unterschiedlichen Sockets: ServerSocket, DatagramSocket... .

MfG DonXs


Überschrift geändert. Das Tutorial hier bezieht sich nämlich nur auf diese Schilder-Sache.
Bild
Benutzeravatar
ilouHD
 
Beiträge: 1733
Registriert: Do 9. Jan 2014, 14:49

Re: Network-Programming

Beitragvon Summerfeeling » So 30. Mär 2014, 13:08

DonXs hat geschrieben:Hey marcsven,
das Tutorial ist zwar ganz gut und gut für anfänger,
jedoch ist es fast genau das gleiche Tutorial wie das von BastiFreak2000,
nur das du es ein wenig genauer erklärst.
Ausserdem passt das Thema überhaupt nicht mit dem was du erklärt hast,
denn Network-Programming bezieht sich nicht nur auf Schilder mit Onlinecount...,
sondern auch mit z.b. einer erklärung der einzelnen Outputstream/Inputstreams oder z.b. Der unterschiedlichen Sockets: ServerSocket, DatagramSocket... .

MfG DonXs


Nur mit dem Unterschied, dass das Tutorial von BastiFreak nicht mehr geht.
Grüße
Summerfeeling | Timo
Benutzeravatar
Summerfeeling
 
Beiträge: 1300
Registriert: Sa 15. Jun 2013, 18:43
Wohnort: Viersen

Re: Join-Schilder mit Java-Network

Beitragvon tahu98 » Mo 31. Mär 2014, 17:51

Ich bin mir da aber auch nicht sicher ob er das alles selbst gemacht hat, da er hier noch danache gefagt hat wie man so etwas erreicht. Er hatte dort auch den falschen Ansatz gemcht und gestern nochmal gepusht.
Bild
Benutzeravatar
tahu98
 
Beiträge: 231
Registriert: Mo 2. Sep 2013, 13:46

Re: Join-Schilder mit Java-Network

Beitragvon ilouHD » Mo 31. Mär 2014, 18:03

tahu98 hat geschrieben:Ich bin mir da aber auch nicht sicher ob er das alles selbst gemacht hat, da er hier noch danache gefagt hat wie man so etwas erreicht. Er hatte dort auch den falschen Ansatz gemcht und gestern nochmal gepusht.


1. Habe gepusht, weil nicht auf das Schild "FULL" geschrieben wurde
2. Das Problem habe ich jetzt aber gelöst bekommen.

Außerdem habe ich auch nicht alles selber gemacht. Das Anpingen nicht. Das habe ich, wie hier auch schon geschrieben, von einem YouTube-Tutorial.

Der Rest ist selber geschrieben.
Bild
Benutzeravatar
ilouHD
 
Beiträge: 1733
Registriert: Do 9. Jan 2014, 14:49

Re: Join-Schilder mit Java-Network

Beitragvon IK_Raptor » Mo 31. Mär 2014, 19:33

Wäre es nicht klüger den Server einmal anzupingen und alle Daten (motd, Spieler etc,) aufeinmal zu returnen? Momentan pingt man pro schild dreimal an...
Benutzeravatar
IK_Raptor
 
Beiträge: 609
Registriert: Mo 12. Aug 2013, 15:37

Re: Join-Schilder mit Java-Network

Beitragvon ilouHD » Mo 31. Mär 2014, 22:00

IK_Raptor hat geschrieben:Wäre es nicht klüger den Server einmal anzupingen und alle Daten (motd, Spieler etc,) aufeinmal zu returnen? Momentan pingt man pro schild dreimal an...


Wie soll man das denn auf das Schild bekommen?
Du kannst ihn 2 mal Anpingen, dann hast du ONLINE_PLAYERS/MAX_PLAYERS und MOTD. Aber ich wüsste gerade - aus dem Kopf, bin am Handy - nicht, wie man den nur einmal anpingen kann. Gucke es mir morgen mal an, wenn ich am PC bin
Bild
Benutzeravatar
ilouHD
 
Beiträge: 1733
Registriert: Do 9. Jan 2014, 14:49

Nächste

Zurück zu Anleitungen

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 5 Gäste

cron