Minecraft Query

    Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

      Minecraft Query

      Hallo Leute,

      ich wollte ein wenig mit Java Spielen und möchte gerne die SpielerListe + Namen eines Servers auslesen.

      Am Anfang habe ich eine Packet ID an den Server geschickt und habe dafür MOTD, Spieler und MaxSpieler auslesen können (wiki.vg/Protocol#Server_List_Ping_.280xFE.29)

      Nun habe ich mein Ziel aber nicht erreicht und habe weiter gesucht. Nach einiger Zeit habe ich dann diese Seite gefunden: wiki.vg/Query

      Nachdem ich mich ein wenig informiert habe habe ich es zustande bekommen einen Token mittels des Handshakes als Paket zu empfangen. Danach wollte ich die BasicStats auslesen und dafür benötige ich den Token. Nur weiß ich nicht ganz wie das ganze aussehen muss. Das Paket muss ca. so aussehen: FE FD 00 00 00 00 01 00 91 29 5B

      Wobei vier der Bytes durch den Token ersetzt werden müssen...


      Quellcode

      1. out.println("<p>Beginne...</p>");
      2. //Adresse/Socket
      3. int port = 25565;
      4. String host = "server.herobrine.de";
      5. InetSocketAddress address = new InetSocketAddress(host, port);
      6. DatagramSocket socket = new DatagramSocket();
      7. socket.setSoTimeout(4000);
      8. //handshake
      9. byte[] h_recv = new byte[10240];
      10. byte[] h_message = new byte[7];
      11. //status
      12. byte[] s_recv = new byte[10240];
      13. byte[] s_message = new byte[11];
      14. h_message[0] = (byte) 0xFE;
      15. h_message[1] = (byte) 0xFD;
      16. h_message[2] = (byte) 0x09;
      17. h_message[3] = (byte) 0x01;
      18. h_message[4] = (byte) 0x01;
      19. h_message[5] = (byte) 0x01;
      20. h_message[6] = (byte) 0x01;
      21. DatagramPacket send_packet = new DatagramPacket(h_message, h_message.length, address.getAddress(), address.getPort());
      22. socket.send(send_packet);
      23. DatagramPacket recv_packet = new DatagramPacket(h_recv, h_recv.length);
      24. socket.receive(recv_packet);
      25. socket.close();
      26. String answere = new String(h_recv, "Cp1252");
      27. out.println("<p> Token: "+ answere +"</p>");
      Alles anzeigen


      Nach erfolglosen probieren wende ich mich nun an euch. Ich habe mir den Beispielcode angeschaut und mein jetziger Code sieht so aus:

      Quellcode

      1. /*
      2. final int challengeInteger;
      3. {
      4. byte byte1 = -1;
      5. int i = 0;
      6. byte[] buffer = new byte[8];
      7. for(int count = 5; (byte1 = h_recv[count++]) != 0;)
      8. buffer[i++] = byte1;
      9. challengeInteger = Integer.parseInt(new String(buffer).trim());
      10. }
      11. s_message[0] = (byte) 0xFE;
      12. s_message[1] = (byte) 0xFD;
      13. s_message[2] = (byte) 0x00;
      14. s_message[3] = (byte) 0x01;
      15. s_message[4] = (byte) 0x01;
      16. s_message[4] = (byte) 0x01;
      17. s_message[5] = (byte) 0x01;
      18. s_message[6] = (byte) (challengeInteger >> 24);
      19. s_message[7] = (byte) (challengeInteger >> 16);
      20. s_message[8] = (byte) (challengeInteger >> 8);
      21. s_message[9] = (byte) challengeInteger;
      22. packet = new DatagramPacket (s_message, s_message.length, address.getAddress(), address.getPort());
      23. socket.send(packet);
      24. packet = new DatagramPacket(s_recv, s_recv.length);
      25. socket.receive(dp);
      26. answere = new String(s_recv, "Cp1252");
      27. out.println("<p> ABC: "+ answere +"</p>");
      28. */
      Alles anzeigen


      Nach einigen versuchen habe ich dann ein Stück von dem Beispielcode kopiert: github.com/ryanshawty/MCJQuery…ryanshaw/Query/Query.java
      Doch leider verstehe ich den nicht ganz. :X

      Du hast bei dem MC Query-Zeugs, so wie ich das sehe, drei Schritte.

      1.

      Quellcode

      1. sendPacket(socket, address, 0xFE, 0xFD, 0x09, 0x01, 0x01, 0x01, 0x01);

      2.

      Quellcode

      1. final int challengeInteger;
      2. {
      3. receivePacket(socket, receiveData);
      4. byte byte1 = -1;
      5. int i = 0;
      6. byte[] buffer = new byte[8];
      7. for(int count = 5; (byte1 = receiveData[count++]) != 0;)
      8. {
      9. buffer[i++] = byte1;
      10. }
      11. challengeInteger = Integer.parseInt(new String(buffer).trim());
      12. }
      Alles anzeigen


      3.

      Quellcode

      1. sendPacket(socket, address, 0xFE, 0xFD, 0x00, 0x01, 0x01, 0x01, 0x01, challengeInteger >> 24, challengeInteger >> 16, challengeInteger >> 8, challengeInteger, 0x00, 0x00, 0x00, 0x00);


      Beim zweiten Schritt besorgst du dir dann einfach den "challengeInteger".
      Habe ich es nicht genau so gemacht? Das ist ja eig. der Code den ich übernommen habe. Was ich auch nicht ganz verstehe ist, dass mein Handshake nur eine Nummer hat. Normalerweise müsste dort ja noch eine ID stehen.

      Token: 3463115
      Token: 2867369
      Token: 4984753

      type Exception report
      message
      descriptionThe server encountered an internal error () that prevented it from fulfilling this request.
      exception
      java.net.SocketTimeoutException: Receive timed out
      note The full stack traces of the exception and its root causes are available in the GlassFish Server Open Source Edition 3.1 logs.

      Er nimmt den Token ja nicht an also muss etwas falsch laufen. :/
      Ohne einen Time out würde der ewig auf eine Antwort warten.

      Mit Token meine ich die Bytes 6-9 die ich vom Handshake bekomme und die ich für weitere Pakete benötige.

      EDIT:

      dinnerbone.com/blog/2011/10/14…ft-19-has-rcon-and-query/

      Sogesehn muss ich doch nur die letzten Bytes in meinem nächsten Paket mitschicken d.H:

      s_message[0] = (byte) 0xFE;
      s_message[1] = (byte) 0xFD;
      s_message[2] = (byte) 0x00;
      s_message[3] = (byte) 0x01;
      s_message[4] = (byte) 0x01;
      s_message[4] = (byte) 0x01;
      s_message[5] = (byte) 0x01;
      s_message[6] = h_recv[5];
      s_message[7] = h_recv[6];
      s_message[8] = h_recv[7];
      s_message[9] = h_recv[8];

      oder sehe ich das falsch?

      Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von Boomer2084 ()

      In this example, after parsing the string "9513307\0" as an integer and
      packing it as a big endian int32, the result should be 00 91 29 5B
      Das sollte dir helfen. Du musst den Integer in big endian int32 konvertieren, wenn du das Token in hexadezimaler Form haben möchtest.
      Ändert aber nichts am Wert des Tokens.

      E: Nee, das geht nicht ganz so einfach. Du musst die bytes erst in einen String wandeln und den String dann in einen Integer.

      Quellcode

      1. 09 00 00 00 01 39 35 31 33 33 30 37 00 | .....9513307.


      Hab das mal eben schnell in C# nachgecoded. Klappt einwandfrei. Wenn du noch Hilfe brauchst, dann regeln wir das am besten über TeamViewer, falls deine Leitung gut genug ist :)

      Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von kuhkuh ()