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 8 von 12   « Erste     678 910     Letzte »    
Flodding

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

AW: Query an Gameserver

  Alt 24. Feb 2015, 22:44
Hab den Fehler gefunden.
Move(buffer[i], response.PlayerName, SizeOf(response.PlayerName)); inc(i, SizeOf(response.PlayerName)); kann ja nicht gehen... wofür hab ich denn EXTRA ne GETSTRING Funktion geschenkt bekommen?
response.PlayerName := GetString(buffer, i); Muss es natürlich heissen.

Die Abfrage mit den Spielernamen funktioniert nun auch:
Delphi-Quellcode:
procedure Get_PLAYER_INFO;
var
  request: TInfoRequest;
  response: TPlayerResponse;
  buffer: TBufferArray;
  i: Integer;
  y: integer;
begin
  request.RequestHeader := -1;
  request.PacketHeader := 'U';
  request.Payload := 'FFFFFFFF'; // Von mir aus auch mit einer Konstante oder einem Ressourcestring

  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.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.Challenge, SizeOf(response.Challenge)); inc(i, SizeOf(response.Challenge));

  i := 0;

  request.Payload[0] := chr(buffer[5]);
  request.Payload[1] := chr(buffer[6]);
  request.Payload[2] := chr(buffer[7]);
  request.Payload[3] := chr(buffer[8]);
  form4.Udp1.SendBuf(request, SizeOf(TInfoRequest));
  form4.Udp1.ReceiveBuf(buffer, SizeOf(buffer));

  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.PlayerCount, SizeOf(response.PlayerCount)); inc(i, SizeOf(response.PlayerCount));

  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));
    form4.ListBox1.Items.Add(response.PlayerName);
    end;

  form4.lblServerHeader.Caption := chr(response.PacketHeader); // D = Antwort -> Playerinfos kommen

  end;
end;
Ja mir fehlen viele Grundlagen was dieses Thema angeht. Ich hatte ehrlich gesagt auch nicht damit gerechnet vor solch Problemen (aus meiner Sicht jetzt) zu stehen als ich meinen kleinen CommunityLauncher angefangen habe zu basteln. Grundsätzlich wollte ich auch NUR die aktuelle Anzahl der Spieler anzeigen lassen, aber es taten sich mit einmal alle Möglichkeiten auf und dadurch ist es erst so eskaliert (wenn dies dann das richtige Wort ist)

Bis jetzt habe ich immer nur kleinere Tools gebastelt die mit dann im Alltag Kleinigkeiten abnehmen oder Dateieinhalte ändern und sowas. Da brauchte ich solch Teufelszeug noch nie und dementsprechend gering sind meine Erfahrungen damit. Wobei ich sagen muss, dass ich in der Vergangenheit wohl auch eher umständlich Programmiert habe als effizient.
Ich habe es auch schon vorher erwähnt. Ich bin kein Professioneller Programmierer und werds leider auch niemals werden. Aber genau dafür gibt es solche Foren, wo Menschen die Wissen haben, es auch teilen können mit denen die es nicht haben oder noch nicht genug.

Trotzdem möchte ich mich hier nochmal bei jedem bedanken der an diesem Thema seinen Beitrag geleistet hat und hoffe, dass zukünftige Forumbesucher mit der selben Problematik es hierdurch leichter haben.

Am Ende bleibt ein Problem übrig...

Zitat:
Wenn der Server nicht erreichbar ist oder der falsche Port angegeben wird, hängt sich das Programm auf.
Wer dafür noch eine Lösung parat hat möge diese doch bitte mit uns teilen
Flo
  Mit Zitat antworten Zitat
BadenPower

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

AW: Query an Gameserver

  Alt 24. Feb 2015, 22:56
@BadenPower
Dann ist der auf der Valve Seite falsch deklariert. Dort ist ID als "short" gelistet, und ganz oben steht in den Typkonventionen: short = 16 bit signed integer
Ein 16 Bit ohne Vorzeichen kommt dort nichtmals vor.
Das habe ich auch gesehen und mich eigentlich gewundert.

Aber ich habe auch die Ausgabe von dem folgenden Link angeschaut:

http://last-templers.de/a2epoch/query/query.php

Dort wird die ID auch positiv als 33930 dargestellt.
Und eine negative ID macht in meinen Augen doch auch keinen Sinn. Daher bin ich eigentlich der Meinung, dass es ein "Word" sein müsste.
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
Benutzerbild von Sir Rufo
Sir Rufo

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

AW: Query an Gameserver

  Alt 24. Feb 2015, 23:20
Nein, was es ist ist eindeutig von Valve festgelegt: 16 bit signed integer

Was du daraus interpretierst ist und bleibt deine Sache. Du kannst ja auch die ID als HEX-Wert ausgeben, oder daraus ein Bild erzeugen, oder oder oder.
Es ist einfach eine eindeutige ID und das wichtigste ist, dass beim Austausch mit dem Rest der Welt, die korrekte Bytefolge zu dieser ID wieder zurückgegeben wird.

In der Schnittstelle würde ich das immer so belassen, wie es vorgegeben ist ...
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
 
#74

AW: Query an Gameserver

  Alt 25. Feb 2015, 10:04
Nein, was es ist ist eindeutig von Valve festgelegt: 16 bit signed integer
Es ist richtig, dass es Valve so hinterlegt hat.

Ist es aber auch richtig?

Ich wage daran zu zweifeln, da dort die "Steam Application ID" ausgegeben werden soll und diese beginnen bei 0. Und bei diesem Gameserver mit diesem Port, den uns Flodding genannt hat ist die AppId laut Steamdb.info nun mal 33930 und nicht -31606.
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
Benutzerbild von DeddyH
DeddyH

Registriert seit: 17. Sep 2006
Ort: Barchfeld
27.624 Beiträge
 
Delphi 12 Athens
 
#75

AW: Query an Gameserver

  Alt 25. Feb 2015, 10:17
Das ist doch lediglich eine Frage der Interpretation, 2 Byte bleiben 2 Byte.
Detlef
"Ich habe Angst vor dem Tag, an dem die Technologie unsere menschlichen Interaktionen übertrumpft. Die Welt wird eine Generation von Idioten bekommen." (Albert Einstein)
Dieser Tag ist längst gekommen
  Mit Zitat antworten Zitat
BadenPower

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

AW: Query an Gameserver

  Alt 25. Feb 2015, 11:19
Am Ende bleibt ein Problem übrig...

Zitat:
Wenn der Server nicht erreichbar ist oder der falsche Port angegeben wird, hängt sich das Programm auf.
Wer dafür noch eine Lösung parat hat möge diese doch bitte mit uns teilen
Ach da war ja noch etwas.

Delphi-Quellcode:
procedure TForm4.Get_A2S_INFO;
var
  Request: TInfoRequest;
  Response: TInfoResponse;
  Buffer: TBufferArray;
  I: Integer;
  CheckTime: TDateTime;
begin
  Request.RequestHeader := 'ÿÿÿÿ';
  Request.PacketHeader := 'T';
  Request.Payload := 'Source Engine Query';
  Request.Payload[19] := #0;

  Udp1.RemoteHost:= Edit1.Text;
  Udp1.RemotePort:= Edit2.Text;

  Udp1.Open;
  if (Udp1.Connected) then
   begin
    Udp1.SendBuf(Request, SizeOf(TInfoRequest));
    CheckTime := Now();
    Udp1.WaitForData(5000);
    if (SecondsBetween(Now(),CheckTime) <= 1) then
     begin
      Udp1.ReceiveBuf(Buffer, SizeOf(Buffer));

      I := 0;
      Move(Buffer[I], Response.ResponseHeader, SizeOf(Response.ResponseHeader));
      Inc(I, SizeOf(Response.ResponseHeader));

      //...

     end;

   end;

end;
Normalerweise sollte die Funktion WaitForData() true zurückgeben wenn der Server bereit ist. Da bei mir mit D2007 aber immer false geliefert wird, mache das wie oben gepostet.

Kann das einmal jemand prüfen, ob bei höheren Delphi-Versionen True zurückgegeben wird?

Wenn ja dann könnte man das Workaround in höheren Versionen weglassen.
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
 
#77

AW: Query an Gameserver

  Alt 25. Feb 2015, 11:20
EDIT: Frage nach der Antwort gepostet.

Hallo!

Immernoch die "nicht erreichbar" Problematik.

Mein aktueller Code um die Verbindung aufzubauen:
Delphi-Quellcode:
  form4.udp1.RemoteHost:= '5.45.97.44';
  form4.udp1.RemotePort:= '2301';
  form4.udp1.Open;

  if form4.udp1.Connected then
  begin

  form4.Udp1.SendBuf(request, SizeOf(TInfoRequest));
  form4.Udp1.ReceiveBuf(buffer, SizeOf(buffer));

  form4.udp1.WaitForData(1000);
  if Length(buffer)<1 then
  begin
   form4.udp1.Close;
   exit;
  end;
Wenn der Port korrekt ist, wird 1 Sekunde gewartet und dann der "buffer" gelesen.

Ist der Port aber kein QueryPort:
Delphi-Quellcode:
  form4.udp1.RemoteHost:= '5.45.97.44';
  form4.udp1.RemotePort:= '1111'; // Port geändert
  form4.udp1.Open;

  if form4.udp1.Connected then
  begin

  form4.Udp1.SendBuf(request, SizeOf(TInfoRequest));
  form4.Udp1.ReceiveBuf(buffer, SizeOf(buffer));

  form4.udp1.WaitForData(1000);
  if Length(buffer)<1 then
  begin
   form4.udp1.Close;
   exit;
  end;
Das Programm hängt sich auf.
Ich hab schon nachgelesen und scheinbar hängt es sich nicht wirklich auf, sondern lauscht weiterhin und wartet auf Antwort.

Ich bin auf diese Option gestoßen:
form4.udp1.BlockMode := bmNonBlocking Damit soll das angeblich funktionieren, jedoch bekomme ich dann immer die Meldung vom "OnError"-Event, dass keine Verbindung aufgebaut werden konnte.
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;
Irgendwelche Ideen?
Flo
  Mit Zitat antworten Zitat
Flodding

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

AW: Query an Gameserver

  Alt 25. Feb 2015, 11:38
Ich habe das OnError Event erstmal deaktiviert, weil der immer ausgelöst wurde wenn WaitForData zu lange gedauert hat.

Habs so ausprobiert jetzt:
Delphi-Quellcode:
  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));
  CheckTime := Now();
  form4.udp1.WaitForData(1000);

  if (SecondsBetween(Now(),CheckTime) <= 1) then
  begin
  form4.Udp1.ReceiveBuf(buffer, SizeOf(buffer));
  i := 0;
  ...
  ...
Bleibt immernoch hängen und wartet nicht nur 1 Sekunde.
Flo
  Mit Zitat antworten Zitat
Benutzerbild von BUG
BUG

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

AW: Query an Gameserver

  Alt 25. Feb 2015, 11:44
Da es mir Schmerzen verursacht, es immer wieder zu lesen: Es gibt keine UDP-Verbindung! UDP ist ein verbindungsloses Protokoll. Die Verbindung gibt es auf Anwendungsebene ... also das was du gerade programmierst.
Bezüglich des Fehlers: Guck dir mal den Errorcode an ... eventuell steht da nur so WSAEWOULDBLOCK drin.

Geändert von BUG (25. Feb 2015 um 11:53 Uhr)
  Mit Zitat antworten Zitat
BadenPower

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

AW: Query an Gameserver

  Alt 25. Feb 2015, 11:51
Ich habe das OnError Event erstmal deaktiviert, weil der immer ausgelöst wurde wenn WaitForData zu lange gedauert hat.

Habs so ausprobiert jetzt:
Delphi-Quellcode:
form4.udp1.WaitForData(1000);

  if (SecondsBetween(Now(),CheckTime) <= 1) then
  begin
  ...
Bleibt immernoch hängen und wartet nicht nur 1 Sekunde.
Warum hast Du nicht meine Werte übernommen.

Also

Delphi-Quellcode:
form4.udp1.WaitForData(5000);

  if (SecondsBetween(Now(),CheckTime) <= 1) then
  begin
  ...
Weil wenn der TimeOut nur 1 Sekunde (Wert 1000) sein soll, dann ist der Unterschied zwischen CheckTime und Now() in der If-Anweiung IMMER kleiner oder gleich 1 Sekunde.
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 8 von 12   « Erste     678 910     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 07:35 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