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 1 von 2  1 2      
Flodding

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

AW: Query an Gameserver

  Alt 24. Feb 2015, 11: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
 
#2

AW: Query an Gameserver

  Alt 24. Feb 2015, 12: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
Flodding

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

AW: Query an Gameserver

  Alt 24. Feb 2015, 12:55
ja das hat super funktioniert

Schlussendlich benötige ich doch noch eine bessere Variante um die Einzelnen Stellen der Antwort auszulesen. So, wie man die Informationen von einem Gameserver per Query abfragen kann, kann man auch die globale serverliste beim Masterserver per Query abfragen. dieses Script habe ich ebenfalls in PHP vorliegen.
Hier ein Link zum Script das die Serverliste anzeigt (Laden dauert etwas):
http://last-templers.de/a2epoch/serverlist.php
Nicht alle Server in der Liste funktionieren.

Problem besteht in den letzten Bytes, die angeben ob der Server Passwortgeschützt ist und ob VAC aktiviert ist.

Code:
Bei Servern OHNE Passwort (647700;00;) funktioniert mein Code.
Bei Servern MIT Passwort (64770100;) funktioniert mein code natürlich nicht, da die letzten Strings des Array dann verschoben werden.
Ich kann das auch mit einer IF ELSE Abfrage lösen, aber irgendwie scheint mir das ganze ziemlich "dreckig" programmiert.
Die einen mögen jetzt sagen: "Funktioniert doch, lass es so" .

Andererseits verstehe ich die Funktion von Sir Rufo nicht so ganz. Ehrlich gesagt garnicht.

Klar ist schon, dass er nur den Header ausliest und überprüft ob die Antwort Gesplittet ist oder nicht. Ich stocke schon an dem punkt, wie ich die ersten 4 Strings, die ja variable Längen haben, auslesen oder definieren soll.

Das mit dem TMemoryStream hatte ich schon probiert. Da kam bei mir nur Gemurkse bei raus.
Da blicke ich nicht durch.
Flo
  Mit Zitat antworten Zitat
Benutzerbild von Neutral General
Neutral General

Registriert seit: 16. Jan 2004
Ort: Bendorf
5.219 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#4

AW: Query an Gameserver

  Alt 24. Feb 2015, 13:14
Ein kleines Beispiel:

Delphi-Quellcode:
var
  mem: TMemoryStream;
  intVar, intVarLesen: Integer;
  boolVar, boolVarLesen: Boolean;
begin
  boolVar := true;
  intVar := 123;
 
  mem := TMemoryStream.Create;
  try
    // Integer schreiben
    mem.Write(intVar, SizeOf(Integer));
    // Boolean schreiben
    mem.Write(boolVar, SizeOf(Boolean));
    
    // Vor dem auslesen den Stream an den Anfang positionieren
    mem.Position := 0;

    // Daten in gleicher Reihenfolge auslesen wie sie eingelesen wurden
    mem.Read(intVarLesen, SizeOf(Integer));
    mem.Read(boolVarLesen, SizeOf(Integer));
  finally
    mem.Free;
  end;
end;
Was du wahrscheinlich machen könntest wär sowas wie:

Delphi-Quellcode:
var
  PreHeader: Array[0..3] of Byte;
  Header: Byte;
  Protocol: Byte;
  tmpChar: AnsiChar;
  ServerName: AnsiString;
begin
  mem.SetSize({größe des Antwortpakets});
  udp1.ReceiveBuf(mem.Memory^, mem.Size);
  
  mem.Position := 0;

  mem.Read(PreHeader[0], SizeOf(PreHeader)); // FF FF FF FF
  mem.Read(Header, SizeOf(Byte));
  mem.Read(Protocol, SizeOf(Byte));

  // Aus folgenden kann/sollte man ne Funktion machen
  ServerName:= '';
  repeat
    mem.Read(tmpChar, SizeOf(AnsiChar));
    if (tmpChar <> #0) then
      ServerName:= ServerName + tmpChar;
  until tmpChar = #0;

  // usw..
end;
Michael
"Programmers talk about software development on weekends, vacations, and over meals not because they lack imagination,
but because their imagination reveals worlds that others cannot see."
  Mit Zitat antworten Zitat
Flodding

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

AW: Query an Gameserver

  Alt 24. Feb 2015, 13:43
Das Funktionierende war auf die Verbindungsproblematik bezogen. Dies funktioniert jetzt schon soweit, dass wenn der Server nicht erreichbar ist, einfach nichts ausgewertet wird. Ändere ich den Queryport aber auf den Spielport zB, dann hängts immernoch.

Delphi-Quellcode:
  ServerName:= '';
  repeat
    mem.Read(tmpChar, SizeOf(AnsiChar));
    if (tmpChar <> #0) then
      ServerName:= ServerName + tmpChar;
  until tmpChar = #0;
da würde spätestens unten bei den Bytes nach den Strings dann wieder die Problematik aufkommen:

Mit Passwort: 8A 84 01 40 00 64 77 01 00

8A84 = Version
01 = Spieler aktuell
40 = Spieler max.
00 = Bots
64 = Typ
77 = Environment
01 = Passwort
00 = VAC status

Ohne Passwort: 8A 84 01 40 00 64 77 00

8A84 = Version
01 = Spieler aktuell
40 = Spieler max.
00 = Bots
64 = Typ
77 = Environment
--> PASSWORT FEHLT
00 = VAC status

Ebenso verhällt es sich bei den aktuellen Spielern auf dem Server. die werden auch als 00 gesendet und somit würden sie dann nur als "stop" für den Stream behandelt werden.
Flo
  Mit Zitat antworten Zitat
Benutzerbild von p80286
p80286

Registriert seit: 28. Apr 2008
Ort: Stolberg (Rhl)
6.659 Beiträge
 
FreePascal / Lazarus
 
#6

AW: Query an Gameserver

  Alt 24. Feb 2015, 14:01
Ich hab mal aus Deinem HexDump ein Beispiel heraus gefischt:
Code:
8A84 
00 
00 
00 - Bots
00 - Typ
00 - Enviroment
00 - Passwortkenner(?)
00 - VAC status?
00 
00 
00 
C4
Ist der Passwortkenner jetzt nicht gesetzt (x00) oder fehlt er? Und wenn Ja, dan gibt es also mind. 2 verschiedene Satztypen?


Gruß
K-H
Programme gehorchen nicht Deinen Absichten sondern Deinen Anweisungen
R.E.D retired error detector
  Mit Zitat antworten Zitat
Flodding

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

AW: Query an Gameserver

  Alt 24. Feb 2015, 14:23
Wenn man das so betrachtet, dann macht das mit dem Zerlegen und dem ";" und dem Array am Ende keinen Sinn mehr.

Dann wäre es ja sinnvoller im oberen Teil einfach die ersten 4 variablen Strings zu lesen mit den 00en, danach die Bytes direkt an ihrer Position auszuwerten. Dann ist es egal ob 00 dort steht oder 0000 denn dann stehen die ersten 00 für 0 Spieler und die zweiten zB für 0 Bots.
Flo
  Mit Zitat antworten Zitat
BadenPower

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

AW: Query an Gameserver

  Alt 24. Feb 2015, 16:29
Ändere ich den Queryport aber auf den Spielport zB, dann hängts immernoch.
Zeig' mal her, was Du bereits geschafft hast, damit wir einmal einen Überblick erhalten.

Dann sind notwendige Änderungen und Verbesserungsvorschläge leichter zu beschreiben.

So ist es manchmal mehr oder weniger ein Rätselraten.
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
 
#9

AW: Query an Gameserver

  Alt 24. Feb 2015, 16:35
Möchtest du dass ich das Projekt hochlade? Oder soll ich gesammten Code Posten?
Flo
  Mit Zitat antworten Zitat
BadenPower

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

AW: Query an Gameserver

  Alt 24. Feb 2015, 19:07
Ändere ich den Queryport aber auf den Spielport zB, dann hängts immernoch.
In der Button2Click fehlt die Abfrage ob Connected.


und in der GetInfo

Delphi-Quellcode:
if (form4.udp1.Connected) then
form4.Udp1.SendBuf(request, SizeOf(TInfoRequest));
form4.Udp1.ReceiveBuf(buffer, SizeOf(buffer));
i := 0;
fehlt das begin-end. So wie Du es hier machst wird nur der Versuch unterbunden SendBuf auszuführen.

Aber die Zeilen danach werden immer ausgeführt, egal ob Connected 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
Antwort Antwort
Seite 1 von 2  1 2      

 

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:45 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