AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Netzwerke Delphi Query an Gameserver
Thema durchsuchen
Ansicht
Themen-Optionen

Query an Gameserver

Ein Thema von Flodding · begonnen am 18. Feb 2015 · letzter Beitrag vom 1. Nov 2015
Antwort Antwort
Seite 4 von 12   « Erste     234 56     Letzte »    
Flodding

Registriert seit: 26. Dez 2007
Ort: Kiel
121 Beiträge
 
Turbo Delphi für Win32
 
#31

AW: Query an Gameserver

  Alt 22. Feb 2015, 13:18
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.
Flo
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#32

AW: Query an Gameserver

  Alt 22. Feb 2015, 14:17
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
http://docwiki.embarcadero.com/RADSt...Der_Typ_Single

Dann könnte man das hier bauen
Delphi-Quellcode:
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}
Jetzt gibt es in Delphi auch so nette Sachen wie Delphi-Referenz durchsuchenTStream und der kann Delphi-Referenz durchsuchenTStream.WriteData und (viel Spanier hier) Delphi-Referenz durchsuchenTStream.ReadData.

Du bekommst ja eine Handvoll Bytes und die kann man in einen Delphi-Referenz durchsuchenTBytesStream packen und dann liest man ganz gemütlich die Daten heraus.

Hier mal ein kleines Beispiel zum Starten:
Delphi-Quellcode:
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;
Wie du sehen kannst, vermeide ich auf Teufel komm raus, irgendwo im Quelltext mit Magic Values zu arbeiten.

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.
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#33

AW: Query an Gameserver

  Alt 22. Feb 2015, 14:35
Bist du dir auch sicher, dass [$8A, $84] auch wirklich $8A84 bedeuten oder evtl. eher $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
http://de.wikipedia.org/wiki/Byte-Re...-Endian-Format

und dann bedeutet diese Bytefolge [$8A, $84] eben genau $848A entspricht was dezimal dann tatsächlich 33930 entspricht. Nur im Speicher sind die Bytes eben in umgekehrter Reihenfolge abgelegt.

Darauf achten musst du nicht, wenn du diese Werte (wie in meinem Beitrag zuvor gezeigt) direkt aus dem Stream liest (lese einfach eine SmallInt , bzw. Int16 )
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
BadenPower

Registriert seit: 17. Jun 2009
616 Beiträge
 
#34

AW: Query an Gameserver

  Alt 22. Feb 2015, 15:27
Die ID : 8A84 sollte umgewandelt 33930 ergeben. Tut es aber nicht egal in was ich umwandel. HextoStr gibt Kryptisches, HextoInt gibt eine falsche Zahl: 35460.
Das sagt mir, dass Du nie versucht hast 33930 in ein Hex umzuwandeln, denn dann hättest Du gesehen , dass 33930 ToHex-> 848A ist.

Na, fällt Dir etwas auf?

und dann bedeutet diese Bytefolge [$8A, $84] eben genau $848A entspricht was dezimal dann tatsächlich 33930 entspricht. Nur im Speicher sind die Bytes eben in umgekehrter Reihenfolge abgelegt.
Vielleicht fällt es ihm jetzt auf, wenn er das 2. mal mit der Nase darauf gestoßen wird.
Programmieren ist die Kunst aus Nullen und Einsen etwas sinnvollen zu gestalten.
Der bessere Künstler ist allerdings der Anwender, denn dieser findet Fehler, welche sich der Programmierer nicht vorstellen konnte.
  Mit Zitat antworten Zitat
Flodding

Registriert seit: 26. Dez 2007
Ort: Kiel
121 Beiträge
 
Turbo Delphi für Win32
 
#35

AW: Query an Gameserver

  Alt 22. Feb 2015, 19:39
Vielleicht fällt es ihm jetzt auf, wenn er das 2. mal mit der Nase darauf gestoßen wird.
Ja ist es jetzt.
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

Soviel zum Offtopic!

Delphi kennt TBytes bei mir nicht.
procedure Foo( AResponse : TBytes ); 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.
Flo
  Mit Zitat antworten Zitat
BadenPower

Registriert seit: 17. Jun 2009
616 Beiträge
 
#36

AW: Query an Gameserver

  Alt 22. Feb 2015, 20:19
Man schaue sich "8A84" und "848A" nur mal an.
Ich ICH ich

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.


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.
Das war nicht meine Absicht, zeigt mir aber, wie so oft, dass Antworten leider von den Fragestellern nicht richtig angeschaut werden.

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.
Programmieren ist die Kunst aus Nullen und Einsen etwas sinnvollen zu gestalten.
Der bessere Künstler ist allerdings der Anwender, denn dieser findet Fehler, welche sich der Programmierer nicht vorstellen konnte.
  Mit Zitat antworten Zitat
Flodding

Registriert seit: 26. Dez 2007
Ort: Kiel
121 Beiträge
 
Turbo Delphi für Win32
 
#37

AW: Query an Gameserver

  Alt 22. Feb 2015, 20:47
Schnipsel abgeändert:
Delphi-Quellcode:
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;
1.) [Pascal Fehler] Unit4.pas(125): E2026 Konstantenausdruck erwartet
2.) Nicht deklarierter Bezeichner 'WorkOnSimpleResponse' / 'WorkOnMultiPacketResponse'

Zitat:
Man sieht sofort den Unterschied, da es in der Muttersprache geschrieben steht.
Entschuldige, dass ich Delphi nicht wie meine Muttersprache beherrsche.

Zitat:
Wir können Dir auch das Programm komplett schreiben, aber wo wäre da der Lerneffekt.
@ BadenPower

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

MFG
Flo
  Mit Zitat antworten Zitat
Benutzerbild von BUG
BUG

Registriert seit: 4. Dez 2003
Ort: Cottbus
2.094 Beiträge
 
#38

AW: Query an Gameserver

  Alt 23. Feb 2015, 00:55
Entschuldige, dass ich Delphi nicht wie meine Muttersprache beherrsche.
Das ist auch nicht schlimm ... Sprachen und Bibliotheken kommen und gehen. Aber als Entwickler/Programmierer ist man zu einem großem Teil Problemlöser. Deine Fragen deuten darauf hin, dass in deinem Entwickler-Werkzeugkasten noch ein paar wichtige Werkzeuge fehlen. Daher also der ganze "Belehrungskram"

Zu den Fehlern:
  1. Ich würde mutmaßen, dass deine Delphiversion nicht mit den typisierten Konstanten im Case zurechtkommt. Probiere es mal ohne die Typen oder benutze stattdessen if-then-else-if...
  2. Diese beiden Funktionen bekommen den "Rest" des Streams und sollten von dir selbst geschrieben werden.
Der Code von Sir Rufo ist eben nur ein Beispiel wie man so etwas angehen kann.
  Mit Zitat antworten Zitat
Flodding

Registriert seit: 26. Dez 2007
Ort: Kiel
121 Beiträge
 
Turbo Delphi für Win32
 
#39

AW: Query an Gameserver

  Alt 24. Feb 2015, 12:34
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:
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) = 'FFFFFFFFthen
      begin
       buff_delemitted := buff_delemitted + 'FFFFFFFF;';
      end;
    if IntToHex(y[0], 2) + IntToHex(y[0], 1) + IntToHex(y[2], 2) + IntToHex(y[3], 2) = 'FFFFFFFEthen
      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) = '00then
      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;
Danke nochmal für die Hilfe bisher an alle die geholfen haben.
Flo
  Mit Zitat antworten Zitat
BadenPower

Registriert seit: 17. Jun 2009
616 Beiträge
 
#40

AW: Query an Gameserver

  Alt 24. Feb 2015, 13:36
Prüfe nach udp.Active:= true; (besser wäre udp.Open; ), ob die Verbindung überhaupt hergestellt werden konnte.

Delphi-Quellcode:
udp.Open;

if (udp.Connected) then
 begin
  x[0]:= $FF;
  x[1]:= $FF;
  //...
  udp.SendBuf(x,sizeof(x));

  //...

 end;
Programmieren ist die Kunst aus Nullen und Einsen etwas sinnvollen zu gestalten.
Der bessere Künstler ist allerdings der Anwender, denn dieser findet Fehler, welche sich der Programmierer nicht vorstellen konnte.
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 4 von 12   « Erste     234 56     Letzte »    

 

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 23:16 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz