Minecraft-Chat-Bot, Packet handling & Tipps ?

  • VB.NET

Es gibt 5 Antworten in diesem Thema. Der letzte Beitrag () ist von Manawyrm.

    Minecraft-Chat-Bot, Packet handling & Tipps ?

    Hallo, Liebes VB-Forum !
    Vor einigen Tagen bin ich mal auf das Spiel "Minecraft" gestossen und war sofort begeistert... Ich habe ein Paar Dinge recherchiert und bin dabei auf den Sourcecode vom sogenannten Minebot[Klick] gestossen.
    Da ich schon immer mal vor hatte auch etwas in die Richtung zu machen habe ich angefangen mir das Grundwissen dafür anzueignen...
    Nun zu meinem Vorhaben:
    Ich habe vor einen kleinen "Bot" (vorerst für private Zwecke) zu schreiben, Der sich auf einen sogenannten Vanilla-Server (ein Minecraft-Server ohne Mods) verbinden kann. Das Ziel davon wäre, dass dieser Benutzername dann Operator-Rechte bekommt und im Chat nach z.B Beleidigungen sucht und dann den dementsprechenden Nutzer kickt... Ich weiss es gibt auch die Möglichkeit mit Plugins/Mods, aber das ist ja nicht mein Ziel ^^

    Was ich bis jetzt schon habe: Die "Einloggprozedur" für Premium-Accounts, einen Socket, die nötigen Form-Elemente (Buttons, Listboxen usw.) und das Minecraft packet-Protocoll
    Was noch fehlt: das ganze Packet-Management

    Meine Bitte:
    könnt ihr mir einen Ansatz geben, wo ich mich über Packets,Packethandling,Packetid's usw informieren kann bzw wo man Anfangen muss wenn man so etwas vor hat ?
    Vielleicht hat einer von euch ja schonmal mit so etwas zutun gehabt und kann mir Tipps geben was beachtet werden muss... oder hat sogar ein CodeBeispiel dafür

    Ich danke schonmal voller Erwartung im Vorraus :)
    mfg.
    Servus THExBASIC,

    ich habe aktuell weder Minecraft zur Verfügung, noch habe ich mich bisher genauer mit dem Protokoll befasst, aber als erster Ansatz:

    Besorg dir einen PacketSniffer (bsw. die Freeware SmartSniff). Schau dir die Client-Server Kommunikation an.
    Für alle weiteren Fragen sollte das Minecraft Protocol herhalten können:
    Spoiler anzeigen
    The default server will check the message to see if it begins with a '/'. If it doesn't, the username of the sender is prepended and sent to all other clients (including the original sender). If it does, the server assumes it to be a command and attempts to process it. A message longer than 100 characters will cause the server to kick the client. (Asof 1.3.2, the vanilla client appears to limit the text a user can enter to 100 charaters.) This limits the chat message packet length to 203 bytes (as characters are encoded on 2 bytes). Note that this limit does not apply to chat messages sent by the server, which are limited to 32767 characters since 1.2.5. This change was initially done by allowing the client to not slice the message up to 119 (the previous limit), without changes to the server. For this reason, the vanilla server kept the code to cut messages at 119, but this isn't a protocol limitation and can be ignored.


    Alternativ gibt es eine C# Minecraft Class.

    Viel Spass dabei :)

    Edit sagt:
    Klasse 1:1 durch den Converter geschoben, 3 Zeilen angepasst, give it a try:

    Module Program:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Imports System.Collections.Generic
    2. Imports System.Linq
    3. Imports System.Text
    4. Imports System.Net.Sockets
    5. Imports System.Net
    6. Imports System.Threading
    7. Module Program
    8. Private Function getInput() As String
    9. Console.ForegroundColor = ConsoleColor.White
    10. Dim input As String = Console.ReadLine()
    11. Console.ForegroundColor = ConsoleColor.Gray
    12. Return input
    13. End Function
    14. Sub Main(ByVal args As String())
    15. 'welcome msg
    16. Console.BackgroundColor = ConsoleColor.DarkBlue
    17. Console.ForegroundColor = ConsoleColor.White
    18. Console.WriteLine(" Minecraft client console ")
    19. Console.WriteLine("V1.0 alpha - © Gamer931215")
    20. 'etc
    21. Console.BackgroundColor = ConsoleColor.Black
    22. Console.ForegroundColor = ConsoleColor.Gray
    23. Console.WriteLine("")
    24. 'begin t00l
    25. Dim client As New TcpClient()
    26. Dim m As New Minecraft()
    27. '############################## Requesting ip/port from user ##############################
    28. Dim username As String
    29. Dim ip As String
    30. Dim port As Integer
    31. Console.WriteLine("Please write here the name you want to join with:")
    32. username = getInput()
    33. Console.WriteLine("Please write here the target IP:")
    34. ip = getInput()
    35. Console.WriteLine("Please write the target port here (leave blank if you want to use the default port 25565):")
    36. Try
    37. port = Convert.ToInt16(getInput())
    38. Catch
    39. port = 25565
    40. End Try
    41. Console.WriteLine("Connecting to " & ip & ":" & port.ToString() & "...")
    42. Try
    43. client.Connect(ip, port)
    44. Catch e As Exception
    45. Console.WriteLine("Cannot connect to server (" & e.Message & ")!")
    46. While True
    47. End While
    48. End Try
    49. '############################## Connecting/login ##############################
    50. If client.Connected Then
    51. m.setClient(client)
    52. 'handshake and login request
    53. If m.Handshake(username) Then
    54. Console.WriteLine("Connection established with " & Convert.ToString(IPAddress.Parse(DirectCast(client.Client.RemoteEndPoint, IPEndPoint).Address.ToString())) & " on port " & port.ToString())
    55. Console.WriteLine("Connection accepted by server, now attempting to login...")
    56. If m.RequestLogin(username) Then
    57. Console.WriteLine("Server accepted login request.")
    58. '############################## Starting update thread ##############################
    59. Dim updater As New Thread(New ThreadStart(AddressOf Update))
    60. updater.Start()
    61. While True
    62. Dim input As String = getInput()
    63. m.SendChatMessage(input)
    64. Console.WriteLine("<" & username & "> " & input)
    65. End While
    66. End If
    67. End If
    68. While True
    69. End While
    70. End If
    71. End Sub
    72. Private Sub Update()
    73. Dim m As New Minecraft()
    74. While True
    75. m.Update()
    76. System.Threading.Thread.Sleep(800)
    77. End While
    78. End Sub
    79. End Module


    Class Minecraft:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Imports System.Collections.Generic
    2. Imports System.Linq
    3. Imports System.Text
    4. Imports System.Net.Sockets
    5. Class Minecraft
    6. Shared c As New TcpClient()
    7. Public Sub Update()
    8. Dim data As Byte() = New Byte(4) {}
    9. data(0) = CByte(0)
    10. Dim id As Byte() = New Byte(0) {}
    11. retry:
    12. Try
    13. c.Client.Receive(id, 0, 1, SocketFlags.None)
    14. Catch
    15. If c.Connected Then
    16. Console.WriteLine("Could not receive package! Retrying in 1 second...")
    17. System.Threading.Thread.Sleep(1000)
    18. GoTo retry
    19. Else
    20. Console.ForegroundColor = ConsoleColor.Red
    21. Console.WriteLine("Server closed connection.")
    22. While True
    23. End While
    24. End If
    25. End Try
    26. If id(0) = CByte(0) Then
    27. 'Ping/alive package (send back!)
    28. Dim buffer As Byte() = New Byte(3) {}
    29. c.Client.Receive(buffer, 0, 4, SocketFlags.None)
    30. buffer.CopyTo(data, 1)
    31. c.Client.Send(data)
    32. ElseIf id(0) = CByte(3) Then
    33. Console.WriteLine("Chat")
    34. End If
    35. End Sub
    36. Public Sub setClient(ByVal n As TcpClient)
    37. c = n
    38. End Sub
    39. Public Function Handshake(ByVal username As String) As Boolean
    40. username = reverse(username)
    41. 'array
    42. Dim data As Byte() = New Byte(3 + ((username.Length * 2) - 1)) {}
    43. 'packet id
    44. data(0) = CByte(2)
    45. 'short len
    46. Dim sh As Byte() = New Byte(1) {}
    47. sh = BitConverter.GetBytes(CShort(username.Length))
    48. Array.Reverse(sh)
    49. sh.CopyTo(data, 1)
    50. 'username
    51. Dim name As Byte() = Encoding.Unicode.GetBytes(username)
    52. Array.Reverse(name)
    53. name.CopyTo(data, 3)
    54. c.Client.Send(data)
    55. Dim pid As Byte() = New Byte(0) {}
    56. c.Client.Receive(pid, 0, 1, SocketFlags.None)
    57. If pid(0) = CByte(2) Then
    58. Return True
    59. Else
    60. Return False
    61. End If
    62. End Function
    63. Public Function RequestLogin(ByVal username As String) As Boolean
    64. username = reverse(username)
    65. 'Preparing data
    66. Dim id As Byte = CByte(1)
    67. Dim protecol As Byte() = New Byte(3) {}
    68. protecol = BitConverter.GetBytes(CInt(22))
    69. Array.Reverse(protecol)
    70. 'v1.0
    71. Dim len As Byte() = New Byte(1) {}
    72. len = BitConverter.GetBytes(CShort(username.Length))
    73. Array.Reverse(len)
    74. Dim usrname As Byte() = New Byte(username.Length * 2 - 1) {}
    75. usrname = Encoding.Unicode.GetBytes(username)
    76. Array.Reverse(usrname)
    77. Dim lon As Byte() = New Byte(7) {}
    78. lon = BitConverter.GetBytes(CLng(0))
    79. Array.Reverse(lon)
    80. Dim intt As Byte() = New Byte(3) {}
    81. intt = BitConverter.GetBytes(CInt(0))
    82. Array.Reverse(intt)
    83. Dim empty As Byte = CByte(0)
    84. 'Creating byte array
    85. Dim data As Byte() = New Byte(23 + ((username.Length * 2) - 1)) {}
    86. 'adding id
    87. data(0) = id
    88. 'adding protecol
    89. protecol.CopyTo(data, 1)
    90. 'adding username length short
    91. len.CopyTo(data, 5)
    92. 'adding username
    93. usrname.CopyTo(data, 7)
    94. 'new index calculation
    95. Dim index As Integer = (7 + (username.Length * 2))
    96. 'adding long
    97. lon.CopyTo(data, index)
    98. index = index + 8
    99. 'adding int
    100. intt.CopyTo(data, index)
    101. index = index + 4
    102. 'adding bytes
    103. data(index) = empty
    104. data(index + 1) = empty
    105. data(index + 2) = empty
    106. data(index + 3) = empty
    107. c.Client.Send(data)
    108. Try
    109. Dim pid As Byte() = New Byte(0) {}
    110. Try
    111. If c.Connected Then
    112. retry:
    113. c.Client.Receive(pid, 0, 1, SocketFlags.None)
    114. If pid(0) = CByte(1) Then
    115. 'package delivered
    116. Return True
    117. Else
    118. GoTo retry
    119. End If
    120. Else
    121. Return False
    122. 'kick
    123. End If
    124. Catch
    125. 'server disconnected
    126. Return False
    127. End Try
    128. Catch
    129. Console.ForegroundColor = ConsoleColor.Red
    130. Console.WriteLine("Server closed connection.")
    131. While True
    132. End While
    133. End Try
    134. End Function
    135. Public Sub SendChatMessage(ByVal message As String)
    136. message = reverse(message)
    137. Dim chat As Byte() = New Byte(3 + ((message.Length * 2) - 1)) {}
    138. chat(0) = CByte(3)
    139. Dim msglen As Byte() = New Byte(1) {}
    140. msglen = BitConverter.GetBytes(CShort(message.Length))
    141. Array.Reverse(msglen)
    142. msglen.CopyTo(chat, 1)
    143. Dim msg As Byte() = New Byte(message.Length * 2 - 1) {}
    144. msg = Encoding.Unicode.GetBytes(message)
    145. Array.Reverse(msg)
    146. msg.CopyTo(chat, 3)
    147. c.Client.Send(chat)
    148. End Sub
    149. 'local functions
    150. Private Shared Function reverse(ByVal a As String) As String
    151. Dim temp As String = ""
    152. Dim i As Integer, j As Integer
    153. j = 0
    154. i = a.Length - 1
    155. While i >= 0
    156. temp += a(i)
    157. i -= 1
    158. j += 1
    159. End While
    160. Return temp
    161. End Function
    162. End Class


    Dürfte sich für deine Zwecke in ein paar Minuten angepasst haben.

    Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von „hate_regex“ ()

    Hallo Leute, Danke schonmal für eure Bemühungen...

    Ich werde mich im Verlauf des Tages mal durch Craft.Net und das ganze "Zeug" durcharbeiten und mal schauen wie weit ich damit komme :)
    Wenn noch was ist bzw ich irgendwo stecken bleibe editiere ich den Post nochmal...
    Weitere Quellen / Tipps sind natürlich weiterhin Willkommen.

    #Edit:

    @"hate_regex"
    Ich habe mal eine Konsolenanwendung mit deinem Source erstellt und einfach etwas rumgetestet... Fehler in dem Sinne gab es keine... jetzt kommt das aber
    Ich habe dabei versucht mich auf einen lokal gehosteten Server "einzuloggen"
    Wobei in der Serverkonsole stand: " [INFO] /127.0.0.1:2922 lost connection" und in der Andwendung nur "Connecting to localhost:25565..." (habe etwa 5 Minuten gewartet)
    -> Ist es/bzw. wäre es überhaupt möglich auf einen lokalserver zu verbinden ?... bevor ich weiterprobiere und denke ich wär zu doof ? ^^

    mfg.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „THExBASIC“ ()

    Weitere Quellen / Tipps sind natürlich weiterhin Willkommen
    Moin,

    ich denke mit dem oben verlinkten Protokoll, nebst einem 'fertigen' Sample-Project (du musst je nach Serverversion/Protokoll die Handshake-Kommunikation anpassen, die im Code funktioniert nur bis v1.52) dürfte die Sache abgefrühstückt sein ;)