Delphi-PRAXiS
Seite 9 von 12   « Erste     789 1011     Letzte »    

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Netzwerke (https://www.delphipraxis.net/14-netzwerke/)
-   -   Delphi Query an Gameserver (https://www.delphipraxis.net/183987-query-gameserver.html)

Flodding 25. Feb 2015 10:57

AW: Query an Gameserver
 
Nachdem das OnError Event deaktiviert wurde, funktionierte dann auch "bmNonBlocking"

Der Workaround funktioniert zwar, aber die Abfragezeit ist mit 5 Sekunden etwas lang.
Delphi-Quellcode:
  form4.udp1.BlockMode := bmNonBlocking;
  form4.udp1.RemoteHost:= form4.edit1.Text;
  form4.udp1.RemotePort:= form4.edit2.Text;
  form4.udp1.Open;

  if form4.udp1.Connected then
  begin
  form4.Udp1.SendBuf(request, SizeOf(TInfoRequest));
  form4.udp1.WaitForData(250);
  form4.Udp1.ReceiveBuf(buffer, SizeOf(buffer));
  i := 0;
Dies funktioniert so ohne extra Zeitüberprüfung. Ob Queryport offen oder eben nicht.

BadenPower 25. Feb 2015 11:04

AW: Query an Gameserver
 
Zitat:

Zitat von Flodding (Beitrag 1291432)
Der Workaround funktioniert zwar, aber die Abfragezeit ist mit 5 Sekunden etwas lang.

Diese Zeit ist nur 5 Sekunden, wenn der Server oder Port nicht erreichbar ist. Ist er Erreichbar, dann rutscht es in Milisekunden durch.

Zitat:

Zitat von Flodding (Beitrag 1291432)
Nachdem das OnError Event deaktiviert wurde, funktionierte dann auch "bmNonBlocking"

wenn ich den UdpSocket auf "bmNonBlocking" stelle, dann blockiert er nie. Aber ich bekomme in diesem Modus keine Daten.

Flodding 25. Feb 2015 11:09

AW: Query an Gameserver
 
Dies hier funktioniert bei mir:
Delphi-Quellcode:
procedure Get_A2S_INFO;
var
  request: TInfoRequest;
  response: TInfoResponse;
  buffer: TBufferArray;
  i: Integer;
  CheckTime: TDateTime;
begin
  request.RequestHeader := -1;
  request.PacketHeader := 'T';
  request.Payload := 'Source Engine Query'; // Von mir aus auch mit einer Konstante oder einem Ressourcestring
  request.Payload[19] := #0;

  form4.udp1.BlockMode := bmNonBlocking;
  form4.udp1.RemoteHost:= form4.edit1.Text;
  form4.udp1.RemotePort:= form4.edit2.Text;
  form4.udp1.Open;

  if form4.udp1.Connected then
    begin
    form4.Udp1.SendBuf(request, SizeOf(TInfoRequest));
    form4.udp1.WaitForData(250);
    form4.Udp1.ReceiveBuf(buffer, SizeOf(buffer));
    i := 0;
    Move(buffer[i], response.ResponseHeader, SizeOf(response.ResponseHeader)); inc(i, SizeOf(response.ResponseHeader));
    Move(buffer[i], response.PacketHeader, SizeOf(response.PacketHeader)); inc(i, SizeOf(response.PacketHeader));
    Move(buffer[i], response.Protocol, SizeOf(response.Protocol)); inc(i, SizeOf(response.Protocol));

    if response.ResponseHeader = -1 then
      begin
      response.Name := GetString(buffer, i);
      response.Map := GetString(buffer, i);
      response.Folder := GetString(buffer, i);
      response.Game := GetString(buffer, i);
      Move(buffer[i], response.ID, SizeOf(response.ID)); inc(i, SizeOf(response.ID));
      Move(buffer[i], response.Players, SizeOf(response.Players)); inc(i, SizeOf(response.Players));
      Move(buffer[i], response.MaxPlayers, SizeOf(response.MaxPlayers)); inc(i, SizeOf(response.MaxPlayers));
      Move(buffer[i], response.Bots, SizeOf(response.Bots)); inc(i, SizeOf(response.Bots));
      Move(buffer[i], response.ServerType, SizeOf(response.ServerType)); inc(i, SizeOf(response.ServerType));
      Move(buffer[i], response.Environment, SizeOf(response.Environment)); inc(i, SizeOf(response.Environment));
      Move(buffer[i], response.Visibility, SizeOf(response.Visibility)); inc(i, SizeOf(response.Visibility));
      Move(buffer[i], response.VAC, SizeOf(response.VAC)); inc(i, SizeOf(response.VAC));
      response.Version := GetString(buffer, i);
      Move(buffer[i], response.EDF, SizeOf(response.EDF)); inc(i, SizeOf(response.EDF));
      Move(buffer[i], response.EDFPort, SizeOf(response.EDFPort)); inc(i, SizeOf(response.EDFPort));
      Move(buffer[i], response.EDFSteamID, SizeOf(response.EDFSteamID)); inc(i, SizeOf(response.EDFSteamID));
      Move(buffer[i], response.EDFSpecPort, SizeOf(response.EDFSpecPort)); inc(i, SizeOf(response.EDFSpecPort));
      //response.EDFSpecName := GetString(buffer, i);
      response.EDFKeywords := GetString(buffer, i);
      Move(buffer[i], response.EDFGameID, SizeOf(response.EDFGameID)); inc(i, SizeOf(response.EDFGameID));

      form4.lblServerHeader.Caption := chr(response.PacketHeader);
      form4.lblServerProtocol.Caption := IntToStr(response.Protocol);
      form4.lblServerName.Caption := response.Name;
      form4.lblServerMap.Caption := response.Map;
      form4.lblServerFolder.Caption := response.Folder;
      form4.lblServerGame.Caption := response.Game;
      form4.lblServerID.Caption := inttostr(response.ID);
      form4.lblServerPlayers.Caption := IntToStr(response.Players);
      form4.lblServerMaxPlayers.Caption := IntToStr(response.MaxPlayers);
      form4.lblServerBots.Caption := IntToStr(response.Bots);
      form4.lblServerType.Caption := chr(response.ServerType);
      form4.lblServerEnvironment.Caption := chr(response.Environment);
      form4.lblServerVisibility.Caption := inttostr(response.Visibility);
      form4.lblServerVAC.Caption := IntToStr(response.VAC);
      form4.lblServerVersion.Caption := response.Version;
      end
      else
      form4.lblServerName.Caption := 'Server nicht erreichbar';
  end;
end;
Das Error Event:
Delphi-Quellcode:
procedure TForm4.udp1Error(Sender: TObject; SocketError: Integer);
begin
//showmessage('Could not connect. The server you are trying to query might be down');
//udp1.Active:= false;
end;

Flodding 25. Feb 2015 14:32

AW: Query an Gameserver
 
Die Sekundenanzeige bei Der Playerinfo will auch nicht so ganz.

Delphi-Quellcode:
TPlayerResponse = record
  ResponseHeader: Integer;
  PacketHeader: Byte;
  Challenge: Integer;
  PlayerCount: Byte;
  PlayerIndex: Byte;
  PlayerName: String;
  PlayerScore: Integer;
  PlayerDuration: Integer;
end;
Delphi-Quellcode:
procedure Get_PLAYER_INFO;
var
  request: TInfoRequest;
  response: TPlayerResponse;
  buffer: TBufferArray;
  i: Integer;
  y: integer;
  PlayerList: TTreeNode;
begin
  request.RequestHeader := -1;
  request.PacketHeader := 'U';
  request.Payload := 'FFFFFFFF';

  Form1.udp1.BlockMode := bmNonBlocking;
  Form1.udp1.RemoteHost:= Form1.edit1.Text;
  Form1.udp1.RemotePort:= Form1.edit2.Text;
  Form1.udp1.Open;

  if (Form1.udp1.Connected) then
    begin
    Form1.Udp1.SendBuf(request, SizeOf(TInfoRequest));
    Form1.udp1.WaitForData(250);
    Form1.Udp1.ReceiveBuf(buffer, SizeOf(buffer));
    //Challenge aus Buffer lesen
    i := 0;
    Move(buffer[i], response.ResponseHeader, SizeOf(response.ResponseHeader)); inc(i, SizeOf(response.ResponseHeader));
    Move(buffer[i], response.PacketHeader, SizeOf(response.PacketHeader)); inc(i, SizeOf(response.PacketHeader));
    Move(buffer[i], response.Challenge, SizeOf(response.Challenge)); inc(i, SizeOf(response.Challenge));
    if chr(response.PacketHeader) = 'A' then
      begin
      //Challende in den PayLoad schreiben
      request.Payload[0] := chr(buffer[5]);
      request.Payload[1] := chr(buffer[6]);
      request.Payload[2] := chr(buffer[7]);
      request.Payload[3] := chr(buffer[8]);
      //A2S_PLAYER request mit Challenge senden
      Form1.Udp1.SendBuf(request, SizeOf(TInfoRequest));
      Form1.udp1.WaitForData(250);
      Form1.Udp1.ReceiveBuf(buffer, SizeOf(buffer));
      i := 0;
      Move(buffer[i], response.ResponseHeader, SizeOf(response.ResponseHeader)); inc(i, SizeOf(response.ResponseHeader));
      Move(buffer[i], response.PacketHeader, SizeOf(response.PacketHeader)); inc(i, SizeOf(response.PacketHeader));
      if chr(response.PacketHeader) = 'D' then
        begin
        Move(buffer[i], response.PlayerCount, SizeOf(response.PlayerCount)); inc(i, SizeOf(response.PlayerCount));
        Form1.TreeView1.Items.Clear;
        for y := 0 to response.PlayerCount - 1 do
          begin
          Move(buffer[i], response.PlayerIndex, SizeOf(response.PlayerIndex)); inc(i, SizeOf(response.PlayerIndex));
          response.PlayerName := GetString(buffer, i);
          Move(buffer[i], response.PlayerScore, SizeOf(response.PlayerScore)); inc(i, SizeOf(response.PlayerScore));
          Move(buffer[i], response.PlayerDuration, SizeOf(response.PlayerDuration)); inc(i, SizeOf(response.PlayerDuration));

          PlayerList := Form1.TreeView1.Items.Add(Nil, response.PlayerName);
          Form1.TreeView1.Items.AddChild(PlayerList, 'ID: ' + IntToStr(response.PlayerIndex));
          Form1.TreeView1.Items.AddChild(PlayerList, 'Kills: ' + IntToStr(response.PlayerScore));
          Form1.TreeView1.Items.AddChild(PlayerList, 'Seconds: ' + IntToStr(response.PlayerDuration));

          Application.ProcessMessages;
          end;
        end;
      end;
    end;
form1.TreeView1.FullExpand;
Form1.udp1.Active := false;
end;
Lese ich die Zeit flasch aus?

Neutral General 25. Feb 2015 14:39

AW: Query an Gameserver
 
Wie immer gilt: Dokumentation lesen hilft.

Data Type Comment
Duration float Time (in seconds) player has been connected to the server.

Flodding 25. Feb 2015 16:19

AW: Query an Gameserver
 
LongInt wäre da richtig oder?

http://www.delphibasics.co.uk/RTL.asp?Name=LongInt

Neutral General 25. Feb 2015 16:28

AW: Query an Gameserver
 
Float ist eine Fließkommazahl. Single wäre der entsprechende Datentyp in Delphi.

Flodding 25. Feb 2015 20:25

AW: Query an Gameserver
 
Ich versuche jetzt die Master-Serverliste abzufragen.

Ich bekomme sogar Antwort. :thumb:

Ich hab jetzt etliche Tests gemacht und rumprobiert, aber ich bekomme einfach keine vernünftige Liste mit servern die ich dann per Query abfragen könnte.

Delphi-Quellcode:
TServerListResponse = record
  ResponseHeader: Integer;
  PacketHeader: Word;
  First: Byte;               // Byte
  Secound: Byte;             // Byte
  Third: Byte;               // Byte
  Fourth: Byte;              // Byte
  Port: Word;                // Short
end;
Delphi-Quellcode:
procedure Get_SERVER_LIST;
var
  request: TInfoRequest;
  response: TServerListResponse;
  buffer: TBufferArray;
  i: Integer;
  y: integer;
begin
// Abfrage der Arma 2 OA Server

// Example
// 31 FF 30 2E 30 2E 30 2E 30 3A 30 00 5C 6E 61 70 70 5C 35 30 30 00

// Tests
//       1ÿ0.0.0.0:0\x00\gamedir\arma2arrowpc\x00
//       31 ff 30 2e 30 2e 30 2e 30 3a 30 5c 78 30 30 5c 67 61 6d 65 64 69 72 5c 61 72 6d 61 32 61 72 72 6f 77 70 63 5c 78 30 30
//      1ÿ0.0.0.0:0\x00\gamedir\arma2arrowpc\x00
//      31 ff 30 2e 30 2e 30 2e 30 3a 30 5c 30 30 5c 67 61 6d 65 64 69 72 5c 61 72 6d 61 32 61 72 72 6f 77 70 63 5c 30 30
//       1ÿ0.0.0.0:0\00\gamedir\arma2arrowpc\00
//       31 ff 30 2e 30 2e 30 2e 30 3a 30 5c 30 5c 67 61 6d 65 64 69 72 5c 61 72 6d 61 32 61 72 72 6f 77 70 63 5c 30
//      1ÿ0.0.0.0:000\gamedir\arma2arrowpc00
//      31 ff 30 2e 30 2e 30 2e 30 3a 30 30 30 5c 67 61 6d 65 64 69 72 5c 61 72 6d 61 32 61 72 72 6f 77 70 63 30 30
//       1ÿ0.0.0.0:0ß\gamedir\arma2arrowpcß
//       31 ff 30 2e 30 2e 30 2e 30 3a 30 df 5c 67 61 6d 65 64 69 72 5c 61 72 6d 61 32 61 72 72 6f 77 70 63 df
//      1ÿ0.0.0.0:00\gamedir\arma2arrowpc0
//      31 ff 30 2e 30 2e 30 2e 30 3a 30 30 5c 67 61 6d 65 64 69 72 5c 61 72 6d 61 32 61 72 72 6f 77 70 63 30

  request.Payload[0] := $31;
  request.Payload[1] := $FF;
  request.Payload[2] := $30;
  request.Payload[3] := $2E;
  request.Payload[4] := $30;
  request.Payload[5] := $2E;
  request.Payload[6] := $30;
  request.Payload[7] := $2E;
  request.Payload[8] := $30;
  request.Payload[9] := $3A;
  request.Payload[10] := $00;

  request.Payload[11] := $30;
  request.Payload[12] := $5C;
  request.Payload[13] := $67;
  request.Payload[14] := $61;
  request.Payload[15] := $6D;
  request.Payload[16] := $65;
  request.Payload[17] := $64;
  request.Payload[18] := $69;
  request.Payload[19] := $72;
  request.Payload[20] := $5C;
  request.Payload[21] := $61;
  request.Payload[22] := $72;
  request.Payload[23] := $6D;
  request.Payload[24] := $61;
  request.Payload[25] := $32;
  request.Payload[26] := $61;
  request.Payload[27] := $72;
  request.Payload[28] := $72;
  request.Payload[29] := $6F;
  request.Payload[30] := $77;
  request.Payload[31] := $70;
  request.Payload[32] := $63;
  request.Payload[33] := $00;

  Form1.udp1.BlockMode := bmNonBlocking;
  Form1.udp1.RemoteHost:= 'hl2master.steampowered.com';
  Form1.udp1.RemotePort:= '27011';
  Form1.udp1.Open;

  if (Form1.udp1.Connected) then
    begin
    Form1.Udp1.SendBuf(request.Payload, SizeOf(request.Payload));
    Form1.udp1.WaitForData(250);
    Form1.Udp1.ReceiveBuf(buffer, SizeOf(buffer));
    i := 0;
    Move(buffer[i], response.ResponseHeader, SizeOf(response.ResponseHeader)); inc(i, SizeOf(response.ResponseHeader));
    form1.ListBox1.Clear;
    for y := 0 to 255 do
      begin
      Move(buffer[i], response.First, SizeOf(response.First)); inc(i, SizeOf(response.First));
      Move(buffer[i], response.Secound, SizeOf(response.Secound)); inc(i, SizeOf(response.Secound));
      Move(buffer[i], response.Third, SizeOf(response.Third)); inc(i, SizeOf(response.Third));
      Move(buffer[i], response.Fourth, SizeOf(response.Fourth)); inc(i, SizeOf(response.Fourth));
      Move(buffer[i], response.Port, SizeOf(response.Port)); inc(i, SizeOf(response.Port));
      Form1.ListBox1.Items.Add(Inttostr(response.First) + '.' + Inttostr(response.Secound) + '.' + inttostr(response.Third) + '.' + inttostr(response.Fourth) + ':' + FloatToStr(response.Port));
      Application.ProcessMessages;
      end;

    end;

Form1.udp1.Active := false;
end;
Danke im Voraus diesmal :oops:

Sir Rufo 25. Feb 2015 20:42

AW: Query an Gameserver
 
Was wollen einem wohl diese Worte sagen:
Zitat:

The format is then a series of these server address blocks
und dann noch (weil die Frage bestimmt auch noch kommt)
Zitat:

The full requested IP list may not fit in 1 x packet. Subsequent packets must be requested by using the last received IP address and Port as the 'seed' in the next request.
Das erste Zitat veranlasst uns zu folgendem Konstrukt
Delphi-Quellcode:
TServerAddressBlock = record
  First: Byte; // Byte
  Second: Byte; // Byte
  Third: Byte; // Byte
  Fourth: Byte; // Byte
  Port: Word; // unsigned Short
end;

TServerAddresses = array of TServerAddressBlock;

TServerListResponse = record
  ResponseHeader: Integer;
  PacketHeader: Word;
  ServerAddresses : TServerAddresses;
end;

BadenPower 25. Feb 2015 20:54

AW: Query an Gameserver
 
Delphi-Quellcode:
  lRequest.Payload[9] := $3A;
  lRequest.Payload[10] := $00;
nach dem Doppelpunkt fehlt noch die 0 für den Port.


Alle Zeitangaben in WEZ +1. Es ist jetzt 23:57 Uhr.
Seite 9 von 12   « Erste     789 1011     Letzte »    

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