Half-Life Server Qry Script

  • Hab vor 2 Wochen angefangen ein Script zu schreiben, welches Daten eines HL1 (+ Mods) Server ausliest und diese ausgibt.

    Screen:
    [Blockierte Grafik: http://img-up.net/img/Clipboard0RjGl.jpg]


    Code:

    Spoiler anzeigen
    [autoit]


    #include <String.au3>
    #include <GUIConstants.au3>
    #include <ie.au3>
    ;#NoTrayIcon

    [/autoit] [autoit][/autoit] [autoit]

    Dim $A2S_INFO = _HexToString("FFFFFFFF") & "TSource Engine Query" & _HexToString("00")
    Dim $A2S_SERVERQUERY_GETCHALLENGE = _HexToString("FFFFFFFF57")
    Dim $A2S_RULES = _HexToString("FFFFFFFF56")
    Dim $A2S_PLAYER = _HexToString("FFFFFFFF55")

    [/autoit] [autoit][/autoit] [autoit]

    global $s_ip
    global $s_port
    global $data
    global $rServerInfo[7]
    global $ServerMap
    global $ServerName
    global $ServerIsPass
    global $ServerPing
    global $ServerPlayers
    global $ServerSlots
    global $ServerPassword
    global $defaultstatus = "Ready"
    global $Ping
    global $abfrage = 0
    global $i = 0
    global $challenge

    [/autoit] [autoit][/autoit] [autoit]

    ; GUI!

    [/autoit] [autoit][/autoit] [autoit]

    $g_main = GUICreate("Server Query Tool by Sascha - [WIP]", 386, 250, 272, 161)
    $e_ip = GUICtrlCreateInput("83.142.80.79:27040", 56, 16, 161, 21)
    ;$e_port = GUICtrlCreateInput("27040", 216, 16, 73, 21)
    $l_ipport = GUICtrlCreateLabel("IP/Port:", 8, 16, 41, 17)
    $b_go = GUICtrlCreateButton("Go", 296, 16, 81, 17, 0)
    $gr_infos = GUICtrlCreateGroup("Infos", 8, 48, 369, 137)
    $l_servername = GUICtrlCreateLabel("Servername:", 16, 72, 64, 17)
    $l_servername_e = GUICtrlCreateLabel("", 88, 72, 284, 20)
    $l_map = GUICtrlCreateLabel("Map:", 16, 88, 28, 17)
    $l_map_e = GUICtrlCreateLabel("", 88, 88, 284, 20)
    $l_player = GUICtrlCreateLabel("Player:", 16, 104, 36, 17)
    $l_player_e = GUICtrlCreateLabel("", 88, 104, 284, 20)
    $l_ping = GUICtrlCreateLabel("Ping:", 16, 120, 28, 17)
    $l_ping_e = GUICtrlCreateLabel("", 88, 120, 284, 20)
    $l_password = GUICtrlCreateLabel("Password: ", 16, 136, 56, 17)
    $l_password_e = GUICtrlCreateLabel("", 88, 136, 284, 20)
    $b_connect = GUICtrlCreateButton("Connect", 104, 192, 169, 17, $BS_CENTER)
    $l_statusbar = GUICtrlCreateLabel($defaultstatus, 2, 232, 382, 16, $SS_SUNKEN)
    GUISetState(@SW_SHOW)

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    While 1

    ; status

    If ProcessExists("hl.exe") Then
    sleep(50)
    $test = GUICtrlSetData($l_statusbar,"Counter-Strike started - HF & GL")
    Else
    sleep(50)
    GUICtrlSetData($l_statusbar,$defaultstatus)
    EndIf


    $nMsg = GUIGetMsg()
    Switch $nMsg

    Case $GUI_EVENT_CLOSE
    UDPShutdown()
    Exit

    Case $b_go

    GUICtrlSetData($b_go,"Refresh")

    If $abfrage = 0 Then
    GUICtrlSetData($l_statusbar,"Sende " & $A2S_INFO & " an " & $rServerInfo[6]) ;status
    Else
    _refresh()
    GUICtrlSetData($l_statusbar,"Refreshing...") ; status
    EndIf

    $Address = StringSplit(GUICtrlRead($e_ip), ":")
    $s_ip = $Address[1]
    $s_port = $Address[2]

    sleep(1000)

    _getdata()
    _getchallenge()
    _getrules()
    _getplayers()
    GUICtrlSetData($l_servername_e,$ServerName)
    sleep(80)
    GUICtrlSetData($l_map_e,$ServerMap)
    sleep(80)
    GUICtrlSetData($l_player_e,$ServerPlayers & "/" & $ServerSlots)
    sleep(80)
    GUICtrlSetData($l_ping_e,$ServerPing)
    sleep(80)
    GUICtrlSetData($l_password_e,$ServerIsPass)
    GUICtrlSetData($l_statusbar,$defaultstatus) ;status
    $abfrage = 1

    [/autoit] [autoit][/autoit] [autoit]

    Case $b_connect
    GUICtrlSetData($l_statusbar,"Checking Password...") ;status
    If $ServerIsPass = "Yes" Then
    $ServerPassword = InputBox("","Enter password")
    GUICtrlSetData($l_statusbar,"Starting...")
    $connect = _IECreate("steam://connect/" & $rServerInfo[6] & "/" & $ServerPassword,"",0)
    Sleep(1000)
    _IEQuit($connect)
    Else
    GUICtrlSetData($l_statusbar,"Starting...")
    $connect = _IECreate("steam://connect/" & $rServerInfo[6],"",0)
    Sleep(1000)
    _IEQuit($connect)
    EndIf
    EndSwitch
    WEnd

    [/autoit] [autoit][/autoit] [autoit]

    ;#######################
    ; FUNKTIONEN!
    ;#######################

    [/autoit] [autoit][/autoit] [autoit]

    Func _refresh()
    $ServerName = ""
    $ServerMap = ""
    $ServerPing = ""
    $ServerIsPass = ""
    $ServerSlots = ""
    $ServerPlayers = ""
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    func _getchallenge()
    UDPStartup()
    $socketc = UDPOpen($s_ip,$s_port)
    UDPSend($socketc,$A2S_SERVERQUERY_GETCHALLENGE)
    $getchallenge = UDPRecv($socketc,999999)
    $challenge = BinaryToString($getchallenge)
    $challenge = StringTrimLeft($challenge, 4)
    ;MsgBox(0,"",$challenge)
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    func _getrules()
    UDPStartup()
    $socket = UDPOpen($s_ip,$s_port)
    UDPSend($socket,$A2S_RULES & $challenge)
    $rules = UDPRecv($socket, 99999)
    $Serverrules = BinaryToString($rules)
    ;MsgBox(0,"",$Serverrules)
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    func _getplayers()
    UDPStartup()
    $socket = UDPOpen($s_ip,$s_port)
    UDPSend($socket, $A2S_PLAYER & $challenge)
    $player = UDPRecv($socket,99999)
    $ServerPlayerInfos = BinaryToString($player)
    ;MsgBox(0,"",$ServerPlayerInfos)
    EndFunc

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    func _getdata()
    UDPStartup()
    $socket = UDPOpen($s_ip,$s_port)
    UDPSend($socket,$A2S_INFO)
    $incoming = UDPRecv($socket,9999999)
    $data = BinaryToString($incoming)


    ; status begin
    If $incoming > 0 Then
    GUICtrlSetData($l_statusbar,"Daten erhalten")
    Else
    GUICtrlSetData($l_statusbar,"Fehler beim Empfangen")
    EndIf

    sleep(1000)
    GUICtrlSetData($l_statusbar,$defaultstatus)
    ; status end


    If stringleft($data,4) == _HexToString("FFFFFFFF") Then
    $data = StringTrimLeft($data, 5)
    ; IP & Port verschwinden lassen
    Do
    $data = StringTrimLeft($data, 1)
    Until StringLeft($data, 1) = Chr(0)
    $data = StringTrimLeft($data, 1)

    ; Servernamen holen

    Do
    $ServerName = $ServerName & StringLeft($Data, 1)
    $Data = StringTrimLeft($Data, 1)
    Until StringLeft($Data, 1) = Chr(0)
    $Data = StringTrimLeft($Data, 1)

    ; Map holen

    Do
    $ServerMap = $ServerMap & StringLeft($Data, 1)
    $Data = StringTrimLeft($Data, 1)
    Until StringLeft($Data, 1) = Chr(0)
    $Data = StringTrimLeft($Data, 1)

    ; Game verschwinden lassen

    Do
    $Data = StringTrimLeft($Data, 1)
    Until StringLeft($Data, 1) = Chr(0)
    $Data = StringTrimLeft($Data, 1)

    ; Info loswerden ~~

    Do
    $Data = StringTrimLeft($Data, 1)
    Until StringLeft($Data, 1) = Chr(0)
    $Data = StringTrimLeft($Data, 1)

    ; Serverpw holn

    $ServerPlayers = Asc(StringLeft($Data, 1))
    $Data = StringTrimLeft($Data, 1)

    ; Slotanzahl

    $ServerSlots = Asc(StringLeft($Data, 1))
    $Data = StringTrimLeft($Data, 4)

    ; Serverpasswortabfrage

    $ServerIsPass = Asc(StringLeft($Data, 1))
    If String($ServerIsPass) = "1" Then
    $ServerIsPass = "Yes"
    Else
    $ServerIsPass = "No"
    EndIf

    ; Server anpingen

    If Ping($s_ip) <> 0 Then
    $ServerPing = Ping($s_ip)
    Else
    $ServerPing = "Time out"
    EndIf


    ; alles in einen Array schreiben

    $rServerInfo[0] = $ServerName
    $rServerInfo[1] = $ServerMap
    $rServerInfo[2] = $ServerPlayers
    $rServerInfo[3] = $ServerSlots
    $rServerInfo[4] = $ServerIsPass
    $rServerInfo[5] = $ServerPing
    $rServerInfo[6] = $s_ip & ":" & $s_port
    EndIf
    EndFunc

    [/autoit]


    Todo:

    - UDP Packet Rules zerlegen (Gott, is das ne kack Arbeit mit AutoIt...)
    - UDP Packet Playerstats zerlegen
    - Rules + Playerstats im GUI ausgeben
    - Favouriten Liste für Server
    - Code säubern


    Edit: 20 Hits, keine Antwort :(

    2 Mal editiert, zuletzt von Sn0opy (25. Juni 2007 um 08:28)

    • Offizieller Beitrag
    Zitat

    Edit: 20 Hits, keine Antwort

    Vielleicht gehts anderen auch, wie mir. Ich weiß nicht was ein Half-Life Server ist. Also guck ich mir dein Skript an.
    Jetzt weiß ich zwar noch immer nicht, was ein Half-Life Server ist, sehe aber das es irgendwas mit CounterStrike zu tun hat und somit ist es für mich nicht mehr interessant. ;)

  • Mich wundert es doch schon sehr, da 1. niemand dann mal nach "Half-Life" bei Google sucht, da es so ziehmlich einer der größten Shooter weltweit ist und Counter-Strike das ganze erstrecht bekannt gemacht hat und 2. Half-Life Server = Counter-Strike Server. Half-Life ist das Spiel und CS die Mod. Man kann mit dem Tool, wie bereits beschrieben, Informationen vom Server holen. Aber Naja, wenn das niemanden interessiert :X

  • naja liegt vielleicht daran, dass die meisten schon allseeingeye HLSW oder Steam nehmen -.- naja bin nicht so der CS-Spieler und deswegen sind für mich nur insgesamt 3 Gameserver wichtig

  • bam, n1 das du dir mal die mühe gemacht hast die ganzen upd qrys rauszusuchen uns so bla
    hab eh mal so nen kleinen smarten cs starter geschrieben und da hab ich über sowas auch nachgedacht, server informationen während dem joinen anzuzeigen, hab ich aber schnell wieder aufgegeben ^^

  • Die Qrys rauszusuchen und zu senden ist das kleinste Problem, da diese auf http://developer.valvesoftware.com zu finden sind. Musst dann eben etwas umdenken, WAS du an den Server sendest, bzw. in welchem Format.

    Das größte Problem dabei ist eben immer, dass man die Strings richtig zerteilt und das wird das Schwierige bei Strings, wo jedes Leerzeichen ein "." ist und wenn da nun sowas wie

    .cl_allowupload.1.mp_startmoney.800.

    kommt, wird das doch etwas dämlich ...

  • Was heisst hier HLSW find ich garnich gut für Server settings, da man da immer aus dem Spiel raus muss, ein Commandmenu für rcon is das viel besser, aber ich denke, dass wollter er auch garnich mit seinem Skript erstellen, sondern er wollte einfach ein kleines Tool schreiben, wo man Server States bekommt...

    und das is gut gelunegn - es ist im Gegensatz zu HLSW nämlich schön schlank und nich so überladen

    Ich würde trotzdem noch kewl finden, wenn es einen Button für "Erweitere Infos" gibt wo dann halt noch paar mehr States gelistet werden


    Walle

    Flensburg ist wie Payback - wenn man 18 Punkte hat bekommt man ein Fahrrad.

  • Das is klar, das will ich auch noch einbauen :D Aber schau dir mal an, was ich vom Server zurückbekomme, da ich das ganze nämlich noch zerteilen muss, um es richtig asuzugeben:

    Code
    _tutor_look_angle.._tutor_look_distance.200._tutor_message_character_display_tim
    e_coefficient.0.07._tutor_message_minimum_display_time.1._tutor_message_repeats.
    5._tutor_view_distance.1000.

    Das ist nun nur ein kleiner Ausschnitt daraus. Das Ganze muss am Ende dann aber so aussehen:

    _tutor_look_angle
    _tutor_look_distance 200
    _tutor_message_character_display_time_coefficient 0.07
    _tutor_message_minimum_display_time 1
    _tutor_message_repeats 5
    _tutor_view_distance 1000

    Da gibts schon mehrere Probleme:

    1. Jedes Leerzeichen zwischen Befehl und Wert werden durch einen Punkt getrennt. Nach dem Wert kommt wieder ein Befehl, um das ganze vom nächsten Befehl zu trennen.

    2. Dezimalzahlen werden in Counter-Strike nicht mit einem Komma getrennt (?), sondern mit einem Punkt, wie man bei _tutor_message_char... sehen kann. Da wäre nun das Problem, dass er zu früh auf den nächsten Befehl springt.

    In PHP kann man in diesem Falle einfach unterscheiden und sagen, dass das eine nen Byte ist, das andere nen String usw. das geht in AutoIt meines Wissens nach nicht.

    http://developer.valvesoftware.com/wiki/Server_Queries#Reply_format_2


    Hier läuft das Script von nem Freund. Er hat das ganze in PHP geschrieben

    http://erpel.dl.am/

    Einmal editiert, zuletzt von Sn0opy (25. Juni 2007 um 16:16)

    • Offizieller Beitrag

    Hi,
    ich hab dir mal ein Skript zum Aufbröseln der Servernachricht erstellt:

    Spoiler anzeigen
    [autoit]

    #include <array.au3>
    Dim $str = '_tutor_look_angle.._tutor_look_distance.200._tutor_message_character_display_tim' & _
    'e_coefficient.0.07._tutor_message_minimum_display_time.1._tutor_message_repeats.' & _
    '5._tutor_view_distance.1000.'
    Dim $arNum[10] = ['0','1','2','3','4','5','6','7','8','9'], $strOut = '', $arOut

    [/autoit] [autoit][/autoit] [autoit]

    $str = StringStripWS(StringReplace($str, '.', ' '),3)
    $arChars = StringSplit($str, '')
    If IsArray($arChars) Then
    For $i = 1 To $arChars[0]
    If ( $arChars[$i] = ' ' ) Then
    If ( _ArraySearch($arNum, $arChars[$i-1]) <> -1 ) Then ; Zeichen davor eine Ziffer ?
    If ( _ArraySearch($arNum, $arChars[$i+1]) <> -1 ) Then _; Zeichen danach eine Ziffer ?
    $arChars[$i] = '.'
    EndIf
    EndIf
    $strOut &= $arChars[$i]
    Next
    ;~ ConsoleWrite($strOut)
    EndIf
    $arOut = StringSplit($strOut, ' _', 1)
    For $i = 1 To $arOut[0]
    If StringLeft($arOut[$i], 1) <> '_' Then $arOut[$i] = '_' & $arOut[$i]
    Next
    _ArrayDisplay($arOut)

    [/autoit]