Jump to content

Minecraft EmuServer


JRSmile
 Share

Recommended Posts

currently it just crashes/freezeloops the client after login :)

I can only work on this project in my sparetime, so expect slow progress...

what i changed so far:

#NoTrayIcon
#include "TCP.au3"
#Include "ZLIB.au3"

;~ ConsoleWrite(_MC_String_decrypt(Binary("0x0007006A00720073006D0069006C0065")))
;~ Exit

; >>>>>>>>>> http://wiki.vg/Protocol

$hServer = _TCP_Server_Create(25565); A MineCraftServer. Tadaa!

_TCP_RegisterEvent($hServer, $TCP_NEWCLIENT, "NewClient")
_TCP_RegisterEvent($hServer, $TCP_DISCONNECT, "Disconnect")
_TCP_RegisterEvent($hServer, $TCP_RECEIVE, "Received")
While 1

WEnd

Func NewClient($hSocket, $iError)
;~     ToolTip("SERVER: New client connected.", 10, 30)
EndFunc   ;==>NewClient

Func Disconnect($hSocket, $iError)
;~     ToolTip("SERVER: Client disconnected.", 10, 30)
EndFunc   ;==>Disconnect

Func Received($hSocket, $sReceived, $iError)
    ConsoleWrite(">| " & Binary($sReceived) & @CRLF)
    Protocol(Binary($sReceived),$hSocket)
EndFunc   ;==>Disconnect

Func Protocol($stream,$hSocket)
    switch BinaryMid($stream,1,1);StringLeft($stream,4)
        Case 0xFE
            ConsoleWrite("+| Server List Ping" & @CRLF)
            _TCP_Send($hSocket, 0xFF)
        Case 0x02
            $username = _MC_String_decrypt(BinaryMid($stream,2)); all strings are UCS-2 encoded which is luckily the same as UTF-16 BigEndian.
            ConsoleWrite("+| Handshake by " & $username & @CRLF)
            _TCP_Send($hSocket, "0x020001002D"); StringToBinary("-",3)
        case 0x01
            $loginname = _MC_String_decrypt(BinaryMid($stream,6))
            ConsoleWrite("+| Login Request by " & $loginname & @CRLF)
            _TCP_Send($hSocket, "0x0100000148000060440b732bf1f642000000000001801406fffffbd600000040000001ef0400000000003fbb1503000800a7003500a7003600a7003400a70035") ; Login accepted
            _TCP_Send($hSocket, "0x05") ; Entity Equipment (Head,Body,pants,boots) ;EntitiyID (int), Slot 0= Hand 1-4 armor slot (short), Item ID (short), Damaged (short)...
            _TCP_Send($hSocket, "0x32000000001") ; Chunk init
            _TCP_Send($hSocket, "0x330000000000037F03") ; Chunk region data
            _TCP_Send($hSocket, "0x0D00000000000000000000000000000000000000001") ; player pos and Look
        case 0x03
            $message = BinaryToString("0x" & StringTrimLeft($stream,5),3)
            ConsoleWrite("-| Chat: " & $message & @CRLF)
        case Else
            ConsoleWrite("!| Unimplemented Packettype! Player KICKED!" & @CRLF)
            _TCP_Send($hSocket, 0xFF)
    EndSwitch
EndFunc

Func _MC_String_Encrypt($sText)
    Local $iLen = StringLen($sText)
    Local $bLen = Binary("0x" & hex(StringLen($sText),4))
    Local $bText = StringTrimLeft(StringToBinary($sText,3),2)
    Return Binary($bLen & $bText)
EndFunc

func _MC_String_decrypt($bin_str)
    Local $bLen = BinaryMid($bin_str,1,2)
    Local $bStr = BinaryMid($bin_str,3, _toInt($bLen)*2)
    Local $sStr = BinaryToString($bStr,3)
    Return $sStr
EndFunc

Func _toInt($2byte)
    Local $2 = int(BinaryMid($2byte,1,1))
    Local $1 = int(BinaryMid($2byte,2,1))
    if $2 > 0 Then $2 += 255
    Return $1 + $2
EndFunc


;~ Dim $Compressed = _ZLIB_Compress($Original, 9)
;~ Dim $Decompressed = _ZLIB_Uncompress($Compressed)

#cs
What's the normal login sequence for a client?

See Authentication for communication with minecraft.net

    The recommended login sequence looks like this, where C is the client and S is the server:

    C <> S : Connects
    C >  S : Sends handshake
    C <  S : Sends handshake response
    C >  S : After authenticating (if needed), sends the login packet
    C <  S : Either kicks (invalid login) or sends a login response
    C <  S : Sends pre-chunks and chunks and entities
    C <  S : Sends spawn position
    C <  S : Sends inventory [Need to verify this since inventory changed] (beta 1.1_02: looks like Window items with type=0, then a Set slot with window id = -1 and slot = -1)
    C <  S : Tell the client they're ready to spawn by sending a position + look packet. Note: The stance and Y should be swapped when the server sends it to the client (See Protocol Page)!
    C >  S : Sends a position + look packet to confirm the spawn position, with the stance and Y swapped back to the correct positions

I think I've done everything right, but…
…my player isn't spawning!

    After sending the common-sense packets (Handshake, Login, Inventory, Compass and Pre-chunk/Chunk pairs) you need to finally send the player their initial position for them to leave the "Loading Map" screen.

…my client isn't receiving complete map chunks!

    The standard Minecraft server server sends full chunks only when your client is sending player status update packets (any of Player (0x0A) through Player Position & Look (0x0D)).

…all connecting clients spasm and jerk uncontrollably!

    For newer clients, your server needs to send 49 chunks ahead of time, not just one. Send a 7x7 square of chunks, centered on the connecting client's position, before spawning them.
#ce
Edited by JRSmile
$a=StringSplit("547275737420796F757220546563686E6F6C75737421","")
For $b=1 To UBound($a)+(-1*-1*-1)step(2^4/8);&$b+=1*2/40*µ&Asc(4)
Assign("c",Eval("c")&Chr(Dec($a[$b]&$a[$b+1])));''Chr("a")&"HI"
Next ;time_U&r34d,ths,U-may=get$the&c.l.u.e;b3st-regards,JRSmile;
MsgBox(0x000000,"",Eval("c"));PiEs:d0nt+*b3.s4d.4ft3r.1st-try:-)
Link to comment
Share on other sites

I had some time, and some time to think:

Local $bData = Binary("0x00000001")
Local $sType = "int"

ConsoleWrite(LittleEndian($bData, $sType) & @CRLF)
ConsoleWrite(BigEndian($bData, $sType) & @CRLF)

Func LittleEndian(ByRef $byte_stream, $type)
    Local $temp = DllStructCreate($type), $output = DllStructCreate("byte[" & DllStructGetSize($temp) & "]", DllStructGetPtr($temp))
    DllStructSetData($output, 1, BinaryMid($byte_stream, 1, DllStructGetSize($temp)))
;~  $byte_stream = BinaryMid($byte_stream, 1 + DllStructGetSize($temp))
    Return DllStructGetData($temp, 1)
EndFunc

Func BigEndian(ByRef $byte_stream, $type)
    Local $temp = DllStructCreate($type), $output = DllStructCreate("byte[" & DllStructGetSize($temp) & "]", DllStructGetPtr($temp))
    For $i = DllStructGetSize($temp) To 1 Step -1
        DllStructSetData($output, 1, BinaryMid($byte_stream, $i, 1), DllStructGetSize($temp) - $i + 1)
    Next
;~  $byte_stream = BinaryMid($byte_stream, 1 + DllStructGetSize($temp))
    Return DllStructGetData($temp, 1)
EndFunc

Obviously, uncomment the lines in the functions to give it back the stream forwarding option the other one had.

Link to comment
Share on other sites

didn't know the byref is speed/performance critical when dealing with large amounts if data, thanks already for that.

$a=StringSplit("547275737420796F757220546563686E6F6C75737421","")
For $b=1 To UBound($a)+(-1*-1*-1)step(2^4/8);&$b+=1*2/40*µ&Asc(4)
Assign("c",Eval("c")&Chr(Dec($a[$b]&$a[$b+1])));''Chr("a")&"HI"
Next ;time_U&r34d,ths,U-may=get$the&c.l.u.e;b3st-regards,JRSmile;
MsgBox(0x000000,"",Eval("c"));PiEs:d0nt+*b3.s4d.4ft3r.1st-try:-)
Link to comment
Share on other sites

I don't think he needs to, because a bot is used to get advantage out of automation in a game, during the fact that this is a server you won't get any advantages out of it for the real game, except the fact that you can use it as GUI as intended.

This is the second time you've made the same mistake most people make. I don't give a fuck if your code is malicious or not. What I do give a fuck about is how easily your code can be adapted to do malicious things. Also, just because you can't think of ways to use things maliciously doesn't mean I can't - or others can't. Anything created for good can be turned to evil. There are no exceptions.
Link to comment
Share on other sites

sad, but true :-(

I will keep this in mind when developing further.

Edited by JRSmile
$a=StringSplit("547275737420796F757220546563686E6F6C75737421","")
For $b=1 To UBound($a)+(-1*-1*-1)step(2^4/8);&$b+=1*2/40*µ&Asc(4)
Assign("c",Eval("c")&Chr(Dec($a[$b]&$a[$b+1])));''Chr("a")&"HI"
Next ;time_U&r34d,ths,U-may=get$the&c.l.u.e;b3st-regards,JRSmile;
MsgBox(0x000000,"",Eval("c"));PiEs:d0nt+*b3.s4d.4ft3r.1st-try:-)
Link to comment
Share on other sites

Progress !

Skinny did a perfect job by creating the BigEndian Functions, now packet structures are as easy to implement as candy.

Skinny is now working on changing the packet stream, it looks like the client throws up two or more packets in the same reply when he wan'ts to so this has to be addressed.

I'm working on implementing the zlib compression and chunk generation.

At least the player now falls right to the level and keep-alive somehow works:

;*****************************************
;AutoCraft.au3 by JRSmile & SkinnyWhiteGuy
;Erstellt mit ISN AutoIt Studio v. 0.76 BETA
;*****************************************
#NoTrayIcon
#include "Includes/TCP.au3"
#include "Includes/ZLIB.au3"
; >>>>>>>>>> http://wiki.vg/Protocol
Global $keep_alive = Binary("")
$hServer = _TCP_Server_Create(25565) ; A MineCraftServer. Tadaa!
_TCP_RegisterEvent($hServer, $TCP_NEWCLIENT, "NewClient")
_TCP_RegisterEvent($hServer, $TCP_DISCONNECT, "Disconnect")
_TCP_RegisterEvent($hServer, $TCP_RECEIVE, "Received")
While 1
WEnd
Func NewClient($hSocket, $iError)
;~   ToolTip("SERVER: New client connected.", 10, 30)
EndFunc ;==>NewClient
Func Disconnect($hSocket, $iError)
;~   ToolTip("SERVER: Client disconnected.", 10, 30)
;~   Exit
EndFunc ;==>Disconnect
Func Received($hSocket, $sReceived, $iError)
ConsoleWrite(">| " & Binary($sReceived) & @CRLF)
Protocol(Binary($sReceived), $hSocket)
EndFunc ;==>Disconnect
Func Protocol($stream, $hSocket)
$org_packet = $stream
Local $Packet = BinaryToBigEndian($stream, "byte")
Switch $Packet
  Case 0xFE
   ConsoleWrite("+| Server List Ping" & @CRLF)
   _TCP_Send($hSocket, 0xFF)
  Case 0x02
   Local $username = _MC_String_decrypt($stream) ; all strings are UCS-2 encoded which is luckily the same as UTF-16 BigEndian.
   ConsoleWrite("+| Handshake by " & $username & @CRLF)
   _TCP_Send($hSocket, BigEndianToBinary($Packet, "byte") & _MC_String_Encrypt("-")) ;"0x020001002D"); StringToBinary("-",3)
  Case 0x01
   Local $ProtocolVersion = BinaryToBigEndian($stream, "int")
   Local $loginname = _MC_String_decrypt($stream)
   ConsoleWrite("+| Login Request by " & $loginname & @CRLF)
   ;Login Packet Return
   Local $LoginPacket = Binary("")
   $LoginPacket &= BigEndianToBinary($Packet, "byte")
   $LoginPacket &= BigEndianToBinary(328, "int") ; Entity ID
   $LoginPacket &= _MC_String_Encrypt("") ; Not Used
   $LoginPacket &= BigEndianToBinary(6936681915343828546, "int64") ; Map Seed
   $LoginPacket &= _MC_String_Encrypt("DEFAULT") ; Level-type, looks like JRSmile skips this
   $LoginPacket &= BigEndianToBinary(0, "int") ; Server Mode
   $LoginPacket &= BigEndianToBinary(0, "byte") ; Dimension
   $LoginPacket &= BigEndianToBinary(1, "byte") ; Difficulty
   $LoginPacket &= BigEndianToBinary(128, "byte") ; World Height
   $LoginPacket &= BigEndianToBinary(20, "byte") ; Max Players
   TCP_Send($hSocket, $LoginPacket)
   _TCP_Send($hSocket, "0x06fffffbd600000040000001ef") ; Spawn Position
   _TCP_Send($hSocket, "0x0400000000003fbb15") ; Time Update
   _TCP_Send($hSocket, "0x03000800a7003500a7003600a7003400a70035") ; Chat Message
;~        _TCP_Send($hSocket, "0x05") ; Entity Equipment (Head,Body,pants,boots) ;EntitiyID (int), Slot 0= Hand 1-4 armor slot (short), Item ID (short), Damaged (short)...
;~        _TCP_Send($hSocket, "0x32000000001") ; Chunk init
;~        _TCP_Send($hSocket, "0x330000000000037F03") ; Chunk region data
;~        _TCP_Send($hSocket, "0x0D00000000000000000000000000000000000000001") ; player pos and Look
  Case 0x03 ; Chat Message (from client)
   $message = BinaryToString("0x" & StringTrimLeft($stream, 5), 3)
   ConsoleWrite("-| Chat: " & $message & @CRLF)
  Case 0x0D ; Player Position & Look (from Client)
   Local $X = BinaryToBigEndian($stream, "double")
   Local $Y = BinaryToBigEndian($stream, "double")
   Local $Stance = BinaryToBigEndian($stream, "double")
   Local $Z = BinaryToBigEndian($stream, "double")
   Local $Yaw = BinaryToBigEndian($stream, "float")
   Local $Pitch = BinaryToBigEndian($stream, "float")
   Local $OnGround = BinaryToBigEndian($stream, "byte")
   ConsoleWrite("+| PositionLook Data: " & $X & @TAB & $Y & @TAB & $Stance & @TAB & $Z & @TAB & $Yaw & @TAB & $Pitch & @TAB & $OnGround & @CRLF)
  Case 0x0B ; Player Position (from Client)
   Local $X = BinaryToBigEndian($stream, "double")
   Local $Y = BinaryToBigEndian($stream, "double")
   Local $Stance = BinaryToBigEndian($stream, "double")
   Local $Z = BinaryToBigEndian($stream, "double")
   Local $OnGround = BinaryToBigEndian($stream, "byte")
   ConsoleWrite("+| Position Data : " & $X & @TAB & $Y & @TAB & $Stance & @TAB & $Z & @TAB & $OnGround & @CRLF)
  Case 0x00
   If $org_packet <> $keep_alive Then
    Local $keeprandom = BigEndianToBinary(0,"byte")
    $keeprandom &= BigEndianToBinary(Random(100000000, 999999999, 1), "int")
    TCP_Send($hSocket, $keeprandom)
    $keep_alive = $keeprandom
   EndIf
  Case Else
   ConsoleWrite("!| Unimplemented Packettype! Player KICKED!" & @CRLF)
   TCP_Send($hSocket, $LoginPacket)
EndSwitch
EndFunc
Func TCP_Send($Socket, $Data)
ConsoleWrite("<| " & $Data & @CRLF)
_TCP_Send($Socket, $Data)
EndFunc
Func _MC_String_Encrypt($sText)
Local $bLen = BigEndianToBinary(StringLen($sText), "short")
Local $bText = StringToBinary($sText, 3)
Return Binary($bLen & $bText)
EndFunc
Func _MC_String_decrypt(ByRef $bin_str)
Local $bLen = BinaryToBigEndian($bin_str, "short")
Local $sStr = BinaryToString(BinaryToLittleEndian($bin_str, "byte[" & $bLen * 2 & "]"), 3)
Return $sStr
EndFunc
Func BinaryToBigEndian(ByRef $byte_stream, $type)
Local $temp = DllStructCreate($type), $output = DllStructCreate("byte[" & DllStructGetSize($temp) & "]", DllStructGetPtr($temp))
For $i = DllStructGetSize($temp) To 1 Step -1
  DllStructSetData($output, 1, BinaryMid($byte_stream, $i, 1), DllStructGetSize($temp) - $i + 1)
Next
$byte_stream = BinaryMid($byte_stream, 1 + DllStructGetSize($temp))
Return DllStructGetData($temp, 1)
EndFunc
Func BigEndianToBinary($data, $type)
If IsNumber($data) Then
  If DllStructGetSize(DllStructCreate($type)) * 2 <= 8 Then
   Return Binary("0x" & Hex($data, DllStructGetSize(DllStructCreate($type)) * 2))
  Else
   Local $temp = DllStructCreate($type), $binary = DllStructCreate("byte[" & DllStructGetSize(DllStructCreate($type)) & "]", DllStructGetPtr($temp))
   DllStructSetData($temp, 1, $data)
;~        ConsoleWrite(DllStructGetData($binary, 1) & @LF)
   Local $bData = Binary("")
   For $i = DllStructGetSize($binary) To 1 Step -1
    $bData &= BigEndianToBinary(DllStructGetData($binary, 1, $i), "byte")
   Next
;~        ConsoleWrite($bData & @LF)
   Return $bData
  EndIf
EndIf
EndFunc
Func BinaryToLittleEndian(ByRef $byte_stream, $type)
Local $temp = DllStructCreate($type), $output = DllStructCreate("byte[" & DllStructGetSize($temp) & "]", DllStructGetPtr($temp))
DllStructSetData($output, 1, BinaryMid($byte_stream, 1, DllStructGetSize($temp)))
$byte_stream = BinaryMid($byte_stream, 1 + DllStructGetSize($temp))
Return DllStructGetData($temp, 1)
EndFunc
;~ Dim $Compressed = _ZLIB_Compress($Original, 9)
;~ Dim $Decompressed = _ZLIB_Uncompress($Compressed)
#cs
What's the normal login sequence for a client?
See Authentication for communication with minecraft.net
    The recommended login sequence looks like this, where C is the client and S is the server:
    C <> S : Connects
    C >  S : Sends handshake
    C <  S : Sends handshake response
    C >  S : After authenticating (if needed), sends the login packet
    C <  S : Either kicks (invalid login) or sends a login response
    C <  S : Sends pre-chunks and chunks and entities
    C <  S : Sends spawn position
    C <  S : Sends inventory [Need to verify this since inventory changed] (beta 1.1_02: looks like Window items with type=0, then a Set slot with window id = -1 and slot = -1)
    C <  S : Tell the client they're ready to spawn by sending a position + look packet. Note: The stance and Y should be swapped when the server sends it to the client (See Protocol Page)!
    C >  S : Sends a position + look packet to confirm the spawn position, with the stance and Y swapped back to the correct positions
I think I've done everything right, but…
…my player isn't spawning!
    After sending the common-sense packets (Handshake, Login, Inventory, Compass and Pre-chunk/Chunk pairs) you need to finally send the player their initial position for them to leave the "Loading Map" screen.
…my client isn't receiving complete map chunks!
    The standard Minecraft server server sends full chunks only when your client is sending player status update packets (any of Player (0x0A) through Player Position & Look (0x0D)).
…all connecting clients spasm and jerk uncontrollably!
    For newer clients, your server needs to send 49 chunks ahead of time, not just one. Send a 7x7 square of chunks, centered on the connecting client's position, before spawning them.
#ce
$a=StringSplit("547275737420796F757220546563686E6F6C75737421","")
For $b=1 To UBound($a)+(-1*-1*-1)step(2^4/8);&$b+=1*2/40*µ&Asc(4)
Assign("c",Eval("c")&Chr(Dec($a[$b]&$a[$b+1])));''Chr("a")&"HI"
Next ;time_U&r34d,ths,U-may=get$the&c.l.u.e;b3st-regards,JRSmile;
MsgBox(0x000000,"",Eval("c"));PiEs:d0nt+*b3.s4d.4ft3r.1st-try:-)
Link to comment
Share on other sites

More Progress,

the client can now connect and will login successfully, the only problem is that the Player will fall endlessly deep due to the fact that terrain isn't implemented yet. :)

Skinny did an impressive job with the packetreading, which can be helpful in the future for anybody.

if you want to stop the player from falling, simply change your handitem or press e or do anything except moving.

the server will kick you and you can stop the server normally.

;*****************************************
;AutoCraft.au3 by JRSmile & SkinnyWhiteGuy
;Erstellt mit ISN AutoIt Studio v. 0.76 BETA
;*****************************************
#AutoIt3Wrapper_Change2CUI=y
#NoTrayIcon
#include "Includes/TCP.au3"
#Include "Includes/ZLIB.au3"
; >>>>>>>>>> http://wiki.vg/Protocol
Global $Types = ObjCreate("Scripting.Dictionary")
$Types("byte") = "byte"
$Types("short") = "short"
$Types("int") = "int"
$Types("long") = "int64"
$Types("float") = "float"
$Types("double") = "double"
$Types("string") = ""
$Types("bool") = "byte"
$hServer = _TCP_Server_Create(25565); A MineCraftServer. Tadaa!
_TCP_RegisterEvent($hServer, $TCP_NEWCLIENT, "NewClient")
_TCP_RegisterEvent($hServer, $TCP_DISCONNECT, "Disconnect")
_TCP_RegisterEvent($hServer, $TCP_RECEIVE, "Received")
While 1
    Sleep(1)
WEnd

Func NewClient($hSocket, $iError)
;~   ToolTip("SERVER: New client connected.", 10, 30)
EndFunc   ;==>NewClient
Func Disconnect($hSocket, $iError)
;~   ToolTip("SERVER: Client disconnected.", 10, 30)
;~   exit
EndFunc   ;==>Disconnect
Func Received($hSocket, $sReceived, $iError)
    Local $bReceived = Binary($sReceived)
    While BinaryLen($bReceived)
        ConsoleWrite(">| " & $bReceived & @CRLF)
        Protocol($bReceived, $hSocket)
    WEnd
EndFunc   ;==>Disconnect
Func Protocol(ByRef $stream, $hSocket)
    Local $Packet = BinaryToBigEndian($stream, "byte")
    Switch $Packet
        Case 0x00 ; Keep Alive
            Local $KeepAliveID = _MC_Read_Packet($stream, "int")
            Debug_Print("Keep Alive ID", $KeepAliveID)
        Case 0x01 ; Login Request
            Local $LoginRequest = _MC_Read_Packet($stream, "int;string;long;string;int;byte;byte;byte;byte") ; Login Packet
            Local $LoginName = $LoginRequest[1]
            ConsoleWrite("+| Login Request by " & $LoginName & @CRLF)
            ;Login Packet Return
            Local $LoginResponse = _MC_Create_Packet("byte;int;string;long;string;int;byte;byte;byte;byte", _
                                    $Packet, 328, "", 6936681915343828546, "DEFAULT", 0, 0, 1, 128, 20)
            TCP_Send($hSocket, $LoginResponse)
            TCP_Send($hSocket, "0x06fffffbd600000040000001ef") ; Spawn Position
            TCP_Send($hSocket, "0x0400000000003fbb15") ; Time Update
            TCP_Send($hSocket, "0x03000800a7003500a7003600a7003400a70035") ; Chat Message
;~        _TCP_Send($hSocket, "0x05") ; Entity Equipment (Head,Body,pants,boots) ;EntitiyID (int), Slot 0= Hand 1-4 armor slot (short), Item ID (short), Damaged (short)...
;~        _TCP_Send($hSocket, "0x32000000001") ; Chunk init
;~        _TCP_Send($hSocket, "0x330000000000037F03") ; Chunk region data
            Local $PlayerPosLook = _MC_Create_Packet("byte;double;double;double;double;float;float;byte", _
                                    0x0D, 6.5, 67.2400000095367, 65.6200000047684, 7.5, 0.0, 0.0, 1)
            TCP_Send($hSocket, $PlayerPosLook)
        Case 0x02 ; Handshake
            Local $HandshakeRequest = _MC_Read_Packet($stream, "string")
            ConsoleWrite("+| Handshake by " & $HandshakeRequest[0] & @CRLF)
            _TCP_Send($hSocket, _MC_Create_Packet("byte;string", $Packet, "-"))
        Case 0x03 ; Chat Message
            Local $Message = _MC_Read_Packet($stream, "string")
            ConsoleWrite("-| Chat: " & $Message[0] & @CRLF)
        Case 0x04 ; Time Update
            ; Server to Client Only
            Local $Time = _MC_Read_Packet($stream, "long")
            Debug_Print("Time", $Time)
        Case 0x05 ; Entity Equipment
            Local $Equipment = _MC_Read_Packet($stream, "int;short;short;short")
            Debug_Print("Equipment", $Equipment)
        Case 0x06 ; Spawn Position
            ; Server to Client only
            Local $Spawn = _MC_Read_Packet($stream, "int;int;int")
            Debug_Print("Spawn Position", $Spawn)
        Case 0x07 ; Use Entity
            ; Client to Server only
            Local $Use = _MC_Read_Packet($stream, "int;int;bool")
            Debug_Print("Use Entity", $Use)
        Case 0x08
        Case 0x09
        Case 0x0A ; Player
            ; Client to Server only
            Local $OnGround = _MC_Read_Packet($stream, "bool")
            Debug_Print("On Ground", $OnGround)
        Case 0x0B ; Player Position
            ; Client to Server
            Local $Position = _MC_Read_Packet($stream, "double;double;double;double;byte")
            Debug_Print("Position Data", $Position)
        Case 0x0C ; Player Look
            ; Client to Server
            Local $Look = _MC_Read_Packet($stream, "float;float;bool")
            Debug_Print("Look Data", $Look)
        Case 0x0D ; Player Position & Look
            Local $PositionLook = _MC_Read_Packet($stream, "double;double;double;double;float;float;byte")
            Debug_Print("PositionLook Data", $PositionLook)
        Case 0x0E
        Case 0x0F
        Case 0x10
        Case 0x11
        Case 0x12
        Case 0x13
        Case 0x14
        Case 0x15
        Case 0x16
        Case 0x17
        Case 0x18
        Case 0x19
        Case 0x1A
        Case 0x1C
        Case 0x1D
        Case 0x1E
        Case 0x1F
        Case 0x20
        Case 0x21
        Case 0x22
        Case 0x26
        Case 0x27
        Case 0x28
        Case 0x29
        Case 0x2A
        Case 0x2B
        Case 0x32
        Case 0x33
        Case 0x34
        Case 0x35
        Case 0x36
        Case 0x3C
        Case 0x3D
        Case 0x46
        Case 0x47
        Case 0x64
        Case 0x65
        Case 0x66
        Case 0x67
        Case 0x68
        Case 0x69
        Case 0x6A
        Case 0x6B
        Case 0x6C
        Case 0x82
        Case 0x83
        Case 0xC8
        Case 0xC9
        Case 0xFA
        Case 0xFE ; Server List Ping
            ConsoleWrite("+| Server List Ping" & @CRLF)
            _TCP_Send($hSocket, 0xFF)
        Case 0xFF ; Disconnect
            Local $Message = _MC_Read_Packet($stream, "string")
            ConsoleWrite("!| Client disconnected: " & $Message[0] & @CRLF)
        Case Else
            ConsoleWrite("!| Unimplemented Packettype! Player KICKED!" & @CRLF)
            _TCP_Send($hSocket, 0xFF)
    EndSwitch
EndFunc
Func TCP_Send($Socket, $Data)
    ConsoleWrite("<| " & $Data & @LF)
    _TCP_Send($Socket, $Data)
EndFunc
Func Debug_Print($header, $aInfo)
    ConsoleWrite("+| " & $header & ":")
    For $Part In $aInfo
        ConsoleWrite(@TAB & $Part)
    Next
    ConsoleWrite(@LF)
EndFunc
Func _MC_String_Encrypt($sText)
    Local $bLen = BigEndianToBinary(StringLen($sText),"short")
    Local $bText = StringToBinary($sText,3)
    Return Binary($bLen & $bText)
EndFunc
func _MC_String_decrypt(ByRef $bin_str)
    Local $bLen = BinaryToBigEndian($bin_str, "short")
    Local $sStr = BinaryToString(BinaryToLittleEndian($bin_str, "byte[" & $bLen * 2 & "]"), 3)
    Return $sStr
EndFunc
Func _MC_Read_Packet(ByRef $stream, $format)
    Local $aResults = StringSplit($format, ";", 2)
    For $i = 0 To UBound($aResults) - 1
        Switch $aResults[$i]
            Case "string"
                $aResults[$i] = _MC_String_decrypt($stream)
            Case Else
                $aResults[$i] = BinaryToBigEndian($stream, $Types($aResults[$i]))
        EndSwitch
    Next
    Return $aResults
EndFunc
Func _MC_Create_Packet($format, $arg1, $arg2='', $arg3='', $arg4='', $arg5='', $arg6='', $arg7='', $arg8='', $arg9='', $arg10='', $arg11='', $arg12='')
    Local $bPacket = Binary("")
    Local $aTypes = StringSplit($format, ";", 2)
    If UBound($aTypes) <> @NumParams-1 Then Return SetError(1, 0, $bPacket)
    For $i = 0 To UBound($aTypes) - 1
        Local $var = Eval("arg" & $i+1)
        Switch $aTypes[$i]
            Case "string"
                $bPacket &= _MC_String_Encrypt($var)
            Case Else
                $bPacket &= BigEndianToBinary($var, $Types($aTypes[$i]))
        EndSwitch
    Next
    Return $bPacket
EndFunc
Func BinaryToBigEndian(ByRef $byte_stream, $type)
    Local $temp = DllStructCreate($type), $output = DllStructCreate("byte[" & DllStructGetSize($temp) & "]", DllStructGetPtr($temp))
    For $i = DllStructGetSize($temp) To 1 Step -1
        DllStructSetData($output, 1, BinaryMid($byte_stream, $i, 1), DllStructGetSize($temp) - $i + 1)
    Next
    $byte_stream = BinaryMid($byte_stream, 1 + DllStructGetSize($temp))
    Return DllStructGetData($temp, 1)
EndFunc
Func BigEndianToBinary($data, $type)
    If IsNumber($data) Then
        If DllStructGetSize(DllStructCreate($type))*2 <= 8 Then
            Return Binary("0x" & Hex($data, DllStructGetSize(DllStructCreate($type))*2))
        Else
            Local $temp = DllStructCreate($type), $binary = DllStructCreate("byte[" & DllStructGetSize(DllStructCreate($type)) & "]", DllStructGetPtr($temp))
            DllStructSetData($temp, 1, $data)
;~        ConsoleWrite(DllStructGetData($binary, 1) & @LF)
            Local $bData = Binary("")
            For $i = DllStructGetSize($binary) To 1 Step -1
                $bData &= BigEndianToBinary(DllStructGetData($binary, 1, $i), "byte")
            Next
;~        ConsoleWrite($bData & @LF)
            Return $bData
        EndIf
    EndIf
EndFunc
Func BinaryToLittleEndian(ByRef $byte_stream, $type)
    Local $temp = DllStructCreate($type), $output = DllStructCreate("byte[" & DllStructGetSize($temp) & "]", DllStructGetPtr($temp))
    DllStructSetData($output, 1, BinaryMid($byte_stream, 1, DllStructGetSize($temp)))
    $byte_stream = BinaryMid($byte_stream, 1 + DllStructGetSize($temp))
    Return DllStructGetData($temp, 1)
EndFunc
;~ Dim $Compressed = _ZLIB_Compress($Original, 9)
;~ Dim $Decompressed = _ZLIB_Uncompress($Compressed)
#cs
What's the normal login sequence for a client?
See Authentication for communication with minecraft.net
    The recommended login sequence looks like this, where C is the client and S is the server:
    C <> S : Connects
    C >  S : Sends handshake
    C <  S : Sends handshake response
    C >  S : After authenticating (if needed), sends the login packet
    C <  S : Either kicks (invalid login) or sends a login response
    C <  S : Sends pre-chunks and chunks and entities
    C <  S : Sends spawn position
    C <  S : Sends inventory [Need to verify this since inventory changed] (beta 1.1_02: looks like Window items with type=0, then a Set slot with window id = -1 and slot = -1)
    C <  S : Tell the client they're ready to spawn by sending a position + look packet. Note: The stance and Y should be swapped when the server sends it to the client (See Protocol Page)!
    C >  S : Sends a position + look packet to confirm the spawn position, with the stance and Y swapped back to the correct positions
I think I've done everything right, but…
…my player isn't spawning!
    After sending the common-sense packets (Handshake, Login, Inventory, Compass and Pre-chunk/Chunk pairs) you need to finally send the player their initial position for them to leave the "Loading Map" screen.
…my client isn't receiving complete map chunks!
    The standard Minecraft server server sends full chunks only when your client is sending player status update packets (any of Player (0x0A) through Player Position & Look (0x0D)).
…all connecting clients spasm and jerk uncontrollably!
    For newer clients, your server needs to send 49 chunks ahead of time, not just one. Send a 7x7 square of chunks, centered on the connecting client's position, before spawning them.
#ce
$a=StringSplit("547275737420796F757220546563686E6F6C75737421","")
For $b=1 To UBound($a)+(-1*-1*-1)step(2^4/8);&$b+=1*2/40*µ&Asc(4)
Assign("c",Eval("c")&Chr(Dec($a[$b]&$a[$b+1])));''Chr("a")&"HI"
Next ;time_U&r34d,ths,U-may=get$the&c.l.u.e;b3st-regards,JRSmile;
MsgBox(0x000000,"",Eval("c"));PiEs:d0nt+*b3.s4d.4ft3r.1st-try:-)
Link to comment
Share on other sites

Kewl.... so when you're done creating this server... will you make it kind of like bukkit where you can make mods and plugins...?

cuz I'm really hoping someone will make a server/mod where you download the mods that the server is using from the server... right when you join...

Link to comment
Share on other sites

cuz I'm really hoping someone will make a server/mod where you download the mods that the server is using from the server... right when you join...

Maybe you already know, but Spout and Spoutcraft can give you something like that (in a limited way).
Link to comment
Share on other sites

I may have to dissapoint you, this server isn't intended to be a Gameserver, you will never be able to really play the game on it due to the following reasons.

1. No multithreading for autoit, the language is to slow.

2. It is a fake server, it emulates a gameserver, but doesn't Act like one.

3. If you don't like 1 and 2 feel Free and go ahead, write your own server, but i would recomend another Programminglanguage.

4. No really its to slow.

$a=StringSplit("547275737420796F757220546563686E6F6C75737421","")
For $b=1 To UBound($a)+(-1*-1*-1)step(2^4/8);&$b+=1*2/40*µ&Asc(4)
Assign("c",Eval("c")&Chr(Dec($a[$b]&$a[$b+1])));''Chr("a")&"HI"
Next ;time_U&r34d,ths,U-may=get$the&c.l.u.e;b3st-regards,JRSmile;
MsgBox(0x000000,"",Eval("c"));PiEs:d0nt+*b3.s4d.4ft3r.1st-try:-)
Link to comment
Share on other sites

Let me explain a bit, with your instant messanger if your doing it clever you get one packet for the message and maybe one or two for the replies from the server, with minecraft you get a packet for everything, turning the mouse one degree, walking one step, changing the item etc. So normally you get a constant stream of packets from the client which has to be analysed somehow, even pulling things like current cpu usage takes to long to keep the stream to the client in time ... Maybe there is a clue to provide the client with information already captured in memory from a different thread, but this is out of my mind right now, if someone has a clever idea how to do this feel free to comment.

But good news ingame chatcommands work like expected now, and returning chat messages to the client works also.

Skinny currently works on implementing the world itself, i wonder how far he already got.

Best regards, j.

$a=StringSplit("547275737420796F757220546563686E6F6C75737421","")
For $b=1 To UBound($a)+(-1*-1*-1)step(2^4/8);&$b+=1*2/40*µ&Asc(4)
Assign("c",Eval("c")&Chr(Dec($a[$b]&$a[$b+1])));''Chr("a")&"HI"
Next ;time_U&r34d,ths,U-may=get$the&c.l.u.e;b3st-regards,JRSmile;
MsgBox(0x000000,"",Eval("c"));PiEs:d0nt+*b3.s4d.4ft3r.1st-try:-)
Link to comment
Share on other sites

  • 2 months later...

update, due to protocol changes from 1.1 to 1.2.5 it is no longer possible to login with the new client, if you want to test the server, downgrade minecraft to 1.1 ! i may update the server to be able to connect with a 1.2.5 client but i don't see a reason, everything included in the 1.1 client is enough for the purpose of the project here.

Regards,

J.

$a=StringSplit("547275737420796F757220546563686E6F6C75737421","")
For $b=1 To UBound($a)+(-1*-1*-1)step(2^4/8);&$b+=1*2/40*µ&Asc(4)
Assign("c",Eval("c")&Chr(Dec($a[$b]&$a[$b+1])));''Chr("a")&"HI"
Next ;time_U&r34d,ths,U-may=get$the&c.l.u.e;b3st-regards,JRSmile;
MsgBox(0x000000,"",Eval("c"));PiEs:d0nt+*b3.s4d.4ft3r.1st-try:-)
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...