![]() |
AW: Query an Gameserver
ja das habe ich natürlich probiert...
von SIGNED INT to HEX funktionierts ja auch. aber von HEX to SIGNED INT häng ich. ich bekomms nur in INT gewandelt und das gibt dann den falschen wert. |
AW: Query an Gameserver
Es ist erheblich einfacher als du denkst, aber du musst eben etwas umdenken :)
Zunächst einmal schaust du dir die Datentypen an, die Valve da vorgibt und suchst dir die passenden Delphi-Typen dazu heraus ![]() Dann könnte man das hier bauen
Delphi-Quellcode:
Jetzt gibt es in Delphi auch so nette Sachen wie
type
TValveByte = Byte; {8 bit character or unsigned integer} TValveShort = SmallInt; {16 bit signed integer} TValveLong = Integer; {32 bit signed integer} TValveFloat = Single; {32 bit floating point} TValveLongLong = Cardinal; {64 bit unsigned integer} ![]() ![]() ![]() Du bekommst ja eine Handvoll Bytes und die kann man in einen ![]() Hier mal ein kleines Beispiel zum Starten:
Delphi-Quellcode:
Wie du sehen kannst, vermeide ich auf Teufel komm raus, irgendwo im Quelltext mit Magic Values zu arbeiten.
const
SIMPLE_RESPONSE_HEADER : TValveLong = $FFFFFFFF; MULTIPACKET_RESPONSE_HEADER : TValveLong = $FFFFFFFE; procedure Foo( AResponse : TBytes ); var LResponseStream : TStream; LHeader : TValveLong; begin LResponseStream := TBytesStream.Create( AResponse ); try LResponseStream.ReadData( LHeader ); // Wir lesen den 4-Byte Header case LHeader of SIMPLE_RESPONSE_HEADER : WorkOnSimpleResponse( LResponseStream ); MULTIPACKET_RESPONSE_HEADER : WorkOnMultiPacketResponse( LResponseStream ); else raise Exception.CreateFmt( 'Unknown Header Value %8.8x', [LHeader] ); end; finally LResponseStream.Free; end; end; Wenn irgendein Wert eine bestimmte Bedeutung hat, dann definiert man sich einen Konstante und verwendet diese Konstante im Quelltext. Dann bleibt das auch immer schön lesbar. |
AW: Query an Gameserver
Bist du dir auch sicher, dass
Delphi-Quellcode:
auch wirklich
[$8A, $84]
Delphi-Quellcode:
bedeuten oder evtl. eher
$8A84
Delphi-Quellcode:
?
$848A
In der Valve-Dokumentation wird ganz eindeutig von All types are little endian gesprochen, was wiederum bedeutet, dass du dir diese Seite anschauen solltest ![]() und dann bedeutet diese Bytefolge
Delphi-Quellcode:
eben genau
[$8A, $84]
Delphi-Quellcode:
entspricht was dezimal dann tatsächlich
$848A
Delphi-Quellcode:
entspricht. Nur im Speicher sind die Bytes eben in umgekehrter Reihenfolge abgelegt.
33930
Darauf achten musst du nicht, wenn du diese Werte (wie in meinem Beitrag zuvor gezeigt) direkt aus dem Stream liest (lese einfach eine
Delphi-Quellcode:
, bzw.
SmallInt
Delphi-Quellcode:
)
Int16
|
AW: Query an Gameserver
Zitat:
Zitat:
|
AW: Query an Gameserver
Zitat:
Aber ich muss dazu sagen, dass es kaum möglich ist, diskreter darauf hinzuweisen. Man schaue sich "8A84" und "848A" nur mal an. Ich möchte nicht unhöflich klingen, aber man hätte mich einfach direkt drauf hinweisen können OHNE zu warten und sich dann lustig drüber zu machen. Ich bin sehr dankbar für die Hilfe die mir hier angeboten wird und interpretiere sie auch nicht als lästiges Rumgedruckse oder Ähnliches. Indirekt / eloquent jemanden zu beleidigen ist trotzdem nicht die feine Art und ich bitte dies in Zukunft zu unterlassen. Sicher hätte ich dem preventieren können wenn ich wie der Fuchs aufgepasst hätte. Wir stempeln das als meinen Fehler ab :thumb: Soviel zum Offtopic! Delphi kennt TBytes bei mir nicht.
Delphi-Quellcode:
Des Weiteren verstehe ich am Beispiel noch nicht so ganz, wie ich unbekannten Inhalt erkennen soll. Das mit dem Header war ja nun leicht weil er bekannt ist.
procedure Foo( AResponse : TBytes );
|
AW: Query an Gameserver
Zitat:
Man sieht sofort den Unterschied, da es in der Muttersprache geschrieben steht. "8A84" und "848A" Man sieht sofort den Unterschied, wenn man sich mit der Sprache beschäftigt, also hier sich die hexadezimale Schreibweise zu Eigen gemacht hat. Und diese Schreibweise kommt in der Computerwelt an jeder Stelle um die Ecke. Zitat:
Wir können Dir auch das Programm komplett schreiben, aber wo wäre da der Lerneffekt. Wenn Du also das nächste mal mit einer Antwort etwas nicht anfangen kannst, dann frage doch nochmals nach, dann sehen wir auch, ob Du es verstanden hast oder nicht. |
AW: Query an Gameserver
Schnipsel abgeändert:
Delphi-Quellcode:
1.) [Pascal Fehler] Unit4.pas(125): E2026 Konstantenausdruck erwartet
type
TBytes = Array of Byte; TValveByte = Byte; {8 bit character or unsigned integer} TValveShort = SmallInt; {16 bit signed integer} TValveLong = Integer; {32 bit signed integer} TValveFloat = Single; {32 bit floating point} TValveLongLong = Cardinal; {64 bit unsigned integer} const SIMPLE_RESPONSE_HEADER : TValveLong = $FFFFFFFF; MULTIPACKET_RESPONSE_HEADER : TValveLong = $FFFFFFFE; procedure Foo(AResponse : Array of Byte); var LResponseStream : TStream; LHeader : TValveLong; begin LResponseStream := TMemoryStream.Create(); LResponseStream.Write(AResponse, Sizeof(AResponse)); try LResponseStream.Read( LHeader, sizeof(LHeader) ); // Wir lesen den 4-Byte Header case LHeader of SIMPLE_RESPONSE_HEADER : ShowMessage('Simple Header'); <--- Fehler 1 // WorkOnSimpleResponse( LResponseStream ); <--- Fehler 2 MULTIPACKET_RESPONSE_HEADER : ShowMessage('Multi Header'); <--- Fehler 1 // WorkOnMultiPacketResponse( LResponseStream ); <--- Fehler 2 else raise Exception.CreateFmt( 'Unknown Header Value %8.8x', [LHeader] ); end; finally LResponseStream.Free; end; end; 2.) Nicht deklarierter Bezeichner 'WorkOnSimpleResponse' / 'WorkOnMultiPacketResponse' Zitat:
Zitat:
War das ein Angebot, wenn ich auf den Lerneffekt verzichte? Im Ernst jetzt mal... ich weis, dass ihr oft mit Kindern zu tun habt, die einfach nur schnell alles fertig haben wollen und sich nicht für den sogenannten Lerneffekt interessieren. Ich möchte mir verbieten, dass du mich mit jenen auf eine Stufe stellst, denn ich habe schon in einem der ersten Posts erwähnt, dass ich nichts fertiges möchte. Andererseits möchte ich auch kein 3 Jahres-Kurs belegen müssen um noch dieses Jahr an mein Ziel zu kommen. Ich erwarte von niemandem, dass er mir fertigen Code generiert, den ich nur noch CopyPasten muss um dann so zu tun als wenn ich der tollste bin weil es ja irgendwie läuft. Da habe ich doch nicht im Geringsten etwas von, wenn ich einmal etwas ändern muss. Ich kam hierher in der Hoffnung, dass mir auf einfache Art erklärt wird, was ich tun muss um ein paar Informationen von einem Gameserver zu bekommen. Und ich habe nicht ansatzweise damit gerechnet, auch nur diesen MONAT damit fertig zu werden. Das ich alleine mit dem WORT "Gameserver" in eine Schublade gesteckt werden würde, war mir schon VOR der Thread-Erstellung klar. Ich bitte dich nun, dich diesem Thema fernzuhalten, wenn du keine produktiven weiterführenden Informationen zur Verfügung stellen möchtest oder kannst. Ich werde dir nicht Mehr Offtopic antworten :thumb: MFG |
AW: Query an Gameserver
Zitat:
Zu den Fehlern:
|
AW: Query an Gameserver
Ich habe es jetzt gelöst bekommen, dass alles ausgelesen wird, auch wenn noch keine Map geladen ist oder keine Spieler vorhanden sind. Problem war ja dass dann "00" ausgegeben wird und sich das Array dann verschiebt. Sicherlich ist es unschön, aber es funktioniert. Für Verbesserungsvorschläge bin ich gerne offen.
Einziges Problem ist jetzt folgendes: Der Server startet 4 Mal am Tag neu. um 06:00, 12:00, 18:00 und 00:00 Uhr. Wenn man zu diesen Zeitpunkten den Query ausführt, hängt sich das Programm auf. Hier der Code:
Delphi-Quellcode:
Danke nochmal für die Hilfe bisher an alle die geholfen haben.
procedure TForm4.Button1Click(Sender: TObject);
var A: TStringList; udp: TUdpSocket; x: array[0..25] of byte; y: array[0..1400] of byte; i: integer; buff_delemitted: string; startbit: integer; endbitbit: integer; stringcounter: integer; begin memo1.Clear; udp := TUdpSocket.Create(Self); udp.RemoteHost:= edit1.Text; udp.RemotePort:= edit2.Text; udp.Active:= true; x[0]:= $FF; x[1]:= $FF; x[2]:= $FF; x[3]:= $FF; x[4]:= $54; x[5]:= $53; x[6]:= $6F; x[7]:= $75; x[8]:= $72; x[9]:= $63; x[10]:= $65; x[11]:= $20; x[12]:= $45; x[13]:= $6E; x[14]:= $67; x[15]:= $69; x[16]:= $6E; x[17]:= $65; x[18]:= $20; x[19]:= $51; x[20]:= $75; x[21]:= $65; x[22]:= $72; x[23]:= $79; x[24]:= $00; udp.SendBuf(x,sizeof(x)); udp.ReceiveBuf(y,sizeof(y)); udp.Active := false; for i := 4 to sizeof(y) - 1 do begin // Header Lesen if (i = 3) then begin if IntToHex(y[0], 2) + IntToHex(y[0], 1) + IntToHex(y[2], 2) + IntToHex(y[3], 2) = 'FFFFFFFF' then begin buff_delemitted := buff_delemitted + 'FFFFFFFF;'; end; if IntToHex(y[0], 2) + IntToHex(y[0], 1) + IntToHex(y[2], 2) + IntToHex(y[3], 2) = 'FFFFFFFE' then begin buff_delemitted := buff_delemitted + 'FFFFFFFE;'; end; end // Antwort else if (IntToHex(y[i], 2) = '49') then begin buff_delemitted := buff_delemitted + IntToHex(y[i], 2) + ';' end // Protokoll else if i = 5 then begin buff_delemitted := buff_delemitted + IntToHex(y[i], 2) + ';' end // Strings aufteilen nach 00 else if (IntToHex(y[i], 2) = '00') then begin stringcounter := stringcounter +1; // Erste 4 Strings aufteilen if stringcounter < 5 then buff_delemitted := buff_delemitted + IntToHex(y[i], 2) + ';'; // Game ID Player und Max Player -> 0 Player keine Ausgabe "00" und würde Array verschieben if stringcounter = 5 then begin if IntToHex(y[i+2], 2) = '00' then buff_delemitted := buff_delemitted + IntToHex(y[i], 2) else buff_delemitted := buff_delemitted + IntToHex(y[i], 2) + ';'; end; // Restliche Strings werden korrekt getrennt if stringcounter > 5 then buff_delemitted := buff_delemitted + IntToHex(y[i], 2) + ';'; end else begin buff_delemitted := buff_delemitted + IntToHex(y[i], 2) end; Application.ProcessMessages; end; // HEX in Memo anzeigen zur Kontrolle Memo1.Text := buff_delemitted; A := TStringList.Create; try Split(';', buff_delemitted, A) ; server_header := HexStrToString(a[0]); server_protocol := inttostr(hextoint(a[1])); server_protocol := IntToStr(HexToInt(a[1])); server_name := HexStrToString(a[2]); server_map := HexStrToString(a[3]); server_folder := HexStrToString(a[4]); server_game := HexStrToString(a[5]); server_ID := inttostr(hextoint(a[6][3] + a[6][4] + a[6][1] + a[6][2])); server_players := inttostr(hextoint(a[6][5] + a[6][6])); server_max_players := inttostr(hextoint(a[6][7] + a[6][8])); server_bots := inttostr(hextoint(a[6][9] + a[6][10])); server_type := HexStrToString(a[7][1] + a[7][2]); server_environment := HexStrToString(a[7][3] + a[7][4]); server_visibility := inttostr(hextoint(a[7][5] + a[7][6])); server_VAC := inttostr(hextoint(a[8])); server_version := inttostr(hextoint(a[11][3] + a[6][4] + a[6][1] + a[6][2])); server_ExtraDataFlag := ''; server_EDF_port := ''; server_EDF_steamID := ''; server_EDF_keywords := ''; server_EDF_gameID := ''; lblServerHeader.Caption := server_header; lblServerProtocol.Caption := server_protocol; lblServerName.Caption := server_name; lblServerMap.Caption := server_map; lblServerFolder.Caption := server_folder; lblServerGame.Caption := server_game; lblServerID.Caption := server_id; lblServerPlayers.Caption := server_players; lblServerMaxPlayers.Caption := server_max_players; lblServerBots.Caption := server_bots; lblServerType.Caption := server_type; lblServerEnvironment.Caption := server_environment; lblServerVisibility.Caption := server_visibility; lblServerVAC.Caption := server_VAC; lblServerVersion.Caption := server_version; finally A.Free; end; end; |
AW: Query an Gameserver
Prüfe nach
Delphi-Quellcode:
(besser wäre
udp.Active:= true;
Delphi-Quellcode:
), ob die Verbindung überhaupt hergestellt werden konnte.
udp.Open;
Delphi-Quellcode:
udp.Open;
if (udp.Connected) then begin x[0]:= $FF; x[1]:= $FF; //... udp.SendBuf(x,sizeof(x)); //... end; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 16:10 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz