Hallo,
Ich wollte eigentlich ein Programm schreiben mit den ich mich auf einen Minecraftserver als Spieler verbinden und Nachrichten/Befehle senden kann.
Ich habe zwar im Internet schon Beispiele gesehen und Probiert nur es klappt nicht und es kommt das Verbindung verloren hat.
http://stackoverflow.com/questions/9520 ... -in-python
Wie könnte ich das realisieren ich? Ich kapier das mit dem Pakets nicht ganz.
Wie sende ich Packets mit Daten wie Nachrichten und so?
http://wiki.vg/Protocol
Socket - Auf einen Minecraftserver als Spieler verbinden
Meine Webseite http://www.develos.de
Forum: http://www.develos.de/forum
Mein Minecraft-Server: jonel.minecraft.to [dynmap(:8123)] | Webseite: http://jonel-minecraft.tk
Forum: http://www.develos.de/forum
Mein Minecraft-Server: jonel.minecraft.to [dynmap(:8123)] | Webseite: http://jonel-minecraft.tk
-
- Python-Forum Veteran
- Beiträge: 16025
- Registriert: Freitag 20. Juni 2003, 16:30
- Kontaktdaten:
Das was in der StackOverflow-Diskussion zu sehen ist, ist halt Minecraft Classic.
Letztendlich verbindest du dich als Client mit der Socket Library. Mit dieser kannst du Strings in bestimmtem Format senden und empfangen. Das Format wird ja in der von dir verlinkten Webseite erklärt. Zudem gibt es das mitgelieferte Modul `struct` mit dem du solche Pakete bauen kannst, sowie die externe Library `bitstring` mit der das etwas einfacher geht.
Letztendlich verbindest du dich als Client mit der Socket Library. Mit dieser kannst du Strings in bestimmtem Format senden und empfangen. Das Format wird ja in der von dir verlinkten Webseite erklärt. Zudem gibt es das mitgelieferte Modul `struct` mit dem du solche Pakete bauen kannst, sowie die externe Library `bitstring` mit der das etwas einfacher geht.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
-
- User
- Beiträge: 7
- Registriert: Dienstag 16. März 2010, 15:09
- Wohnort: Ruhla
Hallo!
Soetwas habe ich schoneinmal gemacht, aber vor einiger Zeit (naja, paar Monate, aber bei der rasanten Entwicklung).
Zuerst etwas Allgemeines: Das Minecraft-Protokoll ist ganz und garnicht benutzerfreundlich. Wenn ich vorhätte, so ein Protokoll zu entwerfen, sähe dass so aus:
1Byte: Packettyp/id 4Byte: Packelänge 4Byte: Irgendeine Prüfsumme
Es ist aber längst nicht so! Das Minecraftprotokoll kenn nur den ersten Wert, den Packettyp. Die Länge musst du selbst berechnen können. Das ist bei vielen vorgegeben, bei anderen ist es doch irgendwo in dem Packet gespiechert. Auch eine Prüfsumme gibt es nicht. Da höhrt sich harmlos an, aber - wenn ein Packet kommt, welches du nicht verstehst, das du fast keine Chanche, dich wieder in den Datenstrom einzuklinken. Du weist ja nicht, wie groß das letzte Packet war, kannst also auch den Anfang des nächsten nicht finden, um dessen Größe zu berechnen. Auch die Idee, ich warte, bis einen Moment nichts aus der Leitung kommt und dann muss ja das nächste Byte der Anfang eines Packet sein, funktioniert in der Praxis nicht, das ein schon ein Pixelhuhn bei jedem Schritt nen Packet erzeugt.
Hier ist ein Zip-Packet: http://ubuntuone.com/40UEwctc5W33LmLsCHKCbu
Woher die informationen, wie die Pakete aufgebaut sind (Weiter ober ist aktueller aber auch mehr Aufwand):
Soetwas habe ich schoneinmal gemacht, aber vor einiger Zeit (naja, paar Monate, aber bei der rasanten Entwicklung).
Zuerst etwas Allgemeines: Das Minecraft-Protokoll ist ganz und garnicht benutzerfreundlich. Wenn ich vorhätte, so ein Protokoll zu entwerfen, sähe dass so aus:
1Byte: Packettyp/id 4Byte: Packelänge 4Byte: Irgendeine Prüfsumme
Es ist aber längst nicht so! Das Minecraftprotokoll kenn nur den ersten Wert, den Packettyp. Die Länge musst du selbst berechnen können. Das ist bei vielen vorgegeben, bei anderen ist es doch irgendwo in dem Packet gespiechert. Auch eine Prüfsumme gibt es nicht. Da höhrt sich harmlos an, aber - wenn ein Packet kommt, welches du nicht verstehst, das du fast keine Chanche, dich wieder in den Datenstrom einzuklinken. Du weist ja nicht, wie groß das letzte Packet war, kannst also auch den Anfang des nächsten nicht finden, um dessen Größe zu berechnen. Auch die Idee, ich warte, bis einen Moment nichts aus der Leitung kommt und dann muss ja das nächste Byte der Anfang eines Packet sein, funktioniert in der Praxis nicht, das ein schon ein Pixelhuhn bei jedem Schritt nen Packet erzeugt.
Hier ist ein Zip-Packet: http://ubuntuone.com/40UEwctc5W33LmLsCHKCbu
- bot.py sollte ein Farmbot werden
- proto.py die Protokolldefinitionen. Die hatte ich irgendwo her, weis aber nicht mehr woher!
- ucs2 und construct Bibliotheken, die waren bei proto.py dabei, vlt. ist das ein Anhaltspunkt für sich, die Quelle zu suchen. Ich weis aber nicht, ob die noch weiterentwickelt worden ist
Woher die informationen, wie die Pakete aufgebaut sind (Weiter ober ist aktueller aber auch mehr Aufwand):
- Minecraft dekompilieren (gibt Anleitungen und Packete im Netzt)
- http://www.wiki.vg/Protocol (in english)
- Die Quelle von proto.py, die war auch damals nicht wirklich aktuell
Vielen Dank, ich werde mir das Ganze mal ansehen.
Ich weis selbst das das Minecraftprotokoll eine Katastrophe ist.
Ich weis selbst das das Minecraftprotokoll eine Katastrophe ist.
Dies hatte ich schon selbst rausgefunden und wusste wie das geht.Letztendlich verbindest du dich als Client mit der Socket Library. Mit dieser kannst du Strings in bestimmtem Format senden und empfangen.
Meine Webseite http://www.develos.de
Forum: http://www.develos.de/forum
Mein Minecraft-Server: jonel.minecraft.to [dynmap(:8123)] | Webseite: http://jonel-minecraft.tk
Forum: http://www.develos.de/forum
Mein Minecraft-Server: jonel.minecraft.to [dynmap(:8123)] | Webseite: http://jonel-minecraft.tk
Na wie ich genau die Sockets in die Form bringe das sie der Server annimmt, denn ich versehe noch nicht ganz wie ich z.B. eine Chatnachricht sende.
Was ich verstanden habe ist das System mit den Socket, oder besser gesagt das Protokoll das der Server halt die bestimmten Bytes annimmt und mir eventuell eine Antwort zurücksendet.
Mein Eigentliches Ziel ist es das ich die gerade Online befindenden Spieler namen abfange und aufzulisten, ist dies Möglich ohne erst über das Protokoll sich als Spieler einzuloggen?
Hier hatte ich mal einen Abschnitt aus dem Internet um einen Server anzupingen, daraus hatte ich das Script noch mit dem Modul curses erweitert, eine kleine Anzeige erstellen lassen.
Bissel doof Formuliert egal.
Hier der Code:
Was ich verstanden habe ist das System mit den Socket, oder besser gesagt das Protokoll das der Server halt die bestimmten Bytes annimmt und mir eventuell eine Antwort zurücksendet.
Mein Eigentliches Ziel ist es das ich die gerade Online befindenden Spieler namen abfange und aufzulisten, ist dies Möglich ohne erst über das Protokoll sich als Spieler einzuloggen?
Hier hatte ich mal einen Abschnitt aus dem Internet um einen Server anzupingen, daraus hatte ich das Script noch mit dem Modul curses erweitert, eine kleine Anzeige erstellen lassen.
Bissel doof Formuliert egal.
Hier der Code:
Code: Alles auswählen
#!/usr/bin/python
# -*- coding: utf-8 -*-
import curses
import socket
import struct, time, sys
#http://wiki.vg/Pocket_Minecraft_Protocol
def get_info(host='128.65.218.229', port=25565):
try:
#Set up our socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
#Send 0xFE: Server list ping
s.send('\xfe\x01')
#Read some data
d = s.recv(1024)
s.close()
#Check we've got a 0xFF Disconnect
assert d[0] == '\xff'
#Remove the packet ident (0xFF) and the short containing the length of the string
#Decode UCS-2 string
d = d[3:].decode('utf-16be')
#Check the first 3 characters of the string are what we expect
assert d[:3] == u'\xa7\x31\x00'
#Split
d = d[3:].split('\x00')
#Return a dict of values
except:
d = [u'Konnte Protokollversion nicht ermitteln!', u'Konnte Serverversion nicht ermitteln!', u'Nicht Vorhanden ', u'0', u'0']
return {'protocol_version': (d[0]),
'server_version': d[1],
'motd': d[2],
'players': (d[3]),
'max_players': (d[4])}
def make_window(name, players, max_players, protocol_version, server_version):
stdscr.addstr(2, 3, "Serverstatus ")
stdscr.addstr(3, 3, "======================================== ")
stdscr.addstr(5, 4, "Servername: {0} ".format(name))
stdscr.addstr(6, 4, "======================================== ")
stdscr.addstr(7, 4, "Aktuell Online: [{0} / {1}] ".format(players, max_players))
stdscr.addstr(8, 4, "Minecraft Server Version: Minecraft {0} ".format(server_version))
stdscr.addstr(10, 4, "Protokoll Version: {0} ".format(protocol_version))
stdscr.refresh()
if __name__ == "__main__":
stdscr = curses.initscr()
curses.noecho()
curses.cbreak()
try:
while(1):
info = get_info()
make_window(info["motd"], info["players"], info["max_players"], info["protocol_version"], info["server_version"])
time.sleep(5)
finally:
curses.echo()
curses.nocbreak()
curses.endwin()
Meine Webseite http://www.develos.de
Forum: http://www.develos.de/forum
Mein Minecraft-Server: jonel.minecraft.to [dynmap(:8123)] | Webseite: http://jonel-minecraft.tk
Forum: http://www.develos.de/forum
Mein Minecraft-Server: jonel.minecraft.to [dynmap(:8123)] | Webseite: http://jonel-minecraft.tk
-
- User
- Beiträge: 7
- Registriert: Dienstag 16. März 2010, 15:09
- Wohnort: Ruhla
Naja, ein Anfang wäre vielleicht ein "Spam-bot" - den bekommst du ohne Auswertung der vom Server gesendeten Daten hin.
(EDIT: Die Längenangabe der Zeichenkette ist ein Short, du musst also 2 Bytes überspringen und natürlich auch das Encoding beachten)
- Verbinden
- Packet erzeugen: Handshake (0x02)
- Ein paar Sekunden warten
- Packet erzeugen: Client Statuses (0xCD)
(EDIT: Die Längenangabe der Zeichenkette ist ein Short, du musst also 2 Bytes überspringen und natürlich auch das Encoding beachten)
Zuletzt geändert von Armageddon am Dienstag 19. Februar 2013, 17:44, insgesamt 1-mal geändert.
@Armageddon: Aber war nicht gerade das Problem von diesem Protokoll, dass man alle Pakete verstehen und verarbeiten *muss*, zumindest so weit, dass man die Paketgrösse kennt. Denn sonst weiss man ja gar nicht wo die Paketgrenzen sind.
-
- User
- Beiträge: 7
- Registriert: Dienstag 16. März 2010, 15:09
- Wohnort: Ruhla
Naja, war halt nur ein QaD-Vorschlag. Es gibt nun mal einen bestimmten Protokollablauf und man kann davon ausgehen, dass der Server ihn einhält. Also einfach seine Packete senden, dabei den Server zwischendurch Zeit lassen, seine Daten zu senden, die man aber garnicht beachtet!
Die Lösung, um den Kick-Grund herrauszufinden basirt darauf, dass das letzte Packet der Übertragung, wenn nicht vom Client abgebrochen, mit 99% Wahrscheinlichkeit das Packet 0xFF ist. In einem normalen String kommt kommt dieses Byte nicht vor. Also sucht man von hinten her das letzte \xFF, geht noch zwei Zeichen, welche ja die Länge des nun folgenden Strings kodieren, weiter und hat dann den Grund. Natürlich kann die Verbindung auch ungeplant beendet werden, für diesen Fall sollte man schauen, ob der len(Grund) > 240, denn laut http://www.wiki.vg/Data_Types kann die Zeichenkette nicht länger sein.
Die Lösung, um den Kick-Grund herrauszufinden basirt darauf, dass das letzte Packet der Übertragung, wenn nicht vom Client abgebrochen, mit 99% Wahrscheinlichkeit das Packet 0xFF ist. In einem normalen String kommt kommt dieses Byte nicht vor. Also sucht man von hinten her das letzte \xFF, geht noch zwei Zeichen, welche ja die Länge des nun folgenden Strings kodieren, weiter und hat dann den Grund. Natürlich kann die Verbindung auch ungeplant beendet werden, für diesen Fall sollte man schauen, ob der len(Grund) > 240, denn laut http://www.wiki.vg/Data_Types kann die Zeichenkette nicht länger sein.