| Autor |
Beitrag |
manu
      
Beiträge: 21
|
Verfasst: So 25.05.03 22:36
Hi,
mich beschäftig schon seit ein paar Tagen ein kleines Problem. Da ich gerade dabei bin, mich in Delphi einzuarbeiten hab ich mich dazu entschlossen ein kleines Quake3-Tool zu schreiben um dabei ein wenig zu lernen. Das klappt auch alles wunderbar doch jetzt hänge ich fest und weiß nicht mehr weiter. Ich möchte gerne, das mein Programm von einem Quake3-Server ein paar Informationen abfragt. Für die Commands usw. hab ich auch schon eine Art Tutorial gefunden: ftp.idsoftware.com/i...ake3/docs/server.txt
Doch da das für Java ist hat mir das nicht wirklich weitergeholfen. Dann hab ich noch weiter gesucht und habe ein Tutorial gefunden wie man das ganze mit PHP macht. Ich hab den Code mal so weit wie möglich gekürzt und dabei kam folgendes raus:
Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19:
| <?php
$ip = "127.0.0.1"; $port = 27960;
$hlserver_con = fsockopen("udp://".$ip, $port); fwrite($hlserver_con, sprintf('%c%c%c%c%s%c', 0xFF, 0xFF, 0xFF, 0xFF, "getstatus", 0x00));
$server_data = fread($hlserver_con, 4); $status = socket_get_status($hlserver_con); $bytes = $status["unread_bytes"];
$server_data = fread($hlserver_con, $bytes);
fclose($hlserver_con);
echo $server_data;
?> |
Das läuft also so ab:
1. Mit dem Server verbinden
2. 4 x 1 byte mit dem wert 255+getstatus+byte mit dem wert 0 schicken
3. Antwort empfangen und die 4 ersten Bytes abschneiden (ist ne unwichtige int-Zahl)
4. Restliche Antwort als String empfangen
5. Verbindung trennen
Der String sieht dann ungefähr so aus:
statusResponse
\dmflags\0\fraglimit\10\timelimit\0\sv_hostname\manu\......
Ich hab mir auch schon den Thread zu BF1942 angesehen, aber bei BF ist das ja anscheinemd leichter, da man nur einen einfachen String senden muss. Bei Quake besteht die Querry aber aus 4 Bytes und einem String und nochmal einem Byte. Meine Frage: Wie krieg ich die Abfrage mit idUDPClient hin?
mfg manu
|
|
BungeeBug
      
Beiträge: 901
|
Verfasst: So 25.05.03 22:43
Hi,
wie es geht haste doch schon geschrieben
Du sendest erst das was du bei 2 beschreiben hast. Den String empängst du im OnRead Ereigniss deines Clients ... dann musste nur noch mit Copy(), Pos() und wie sie alles heissen, den empfangenen String phrasen ... und so wie ich das da sehen kann is das ganze ja sehr selbst erklärent
MfG BungeeBug
|
|
cirrus
      
Beiträge: 49
|
Verfasst: Mo 26.05.03 01:08
falsch, der idUDPClient empfängt die Daten mit einer der Receive Methoden, zur GameServer-Abfrage machst du es dann prinzipiell so:
Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15:
| ... var recBuffer: String; udpClient: TidUDPClient; begin udp:=tidudpclient.create(nil) udp.Port:=DEIN PORT; udp.Host:='DEINE SERVER IP'; udp.ReceiveTimeout:=500; udp.Active:=true; udp.Send('ÿÿÿÿgetstatus'); //q3 Query Command schicken recBuffer:=udp.ReceiveString; ...... {Parsing der Serverantwort} end. |
Detailierte Infos über Game Server Queries und Source Code in Delphi findest du auf www.kquery.com/ oder demnächst auch auf meiner page
Schreibe allerdings einen Launcher für CounterStrike.
gruss
cirrus
_________________ Wenn die Nacht am tiefsten ist der Tag am nächsten
|
|
manu 
      
Beiträge: 21
|
Verfasst: Mo 26.05.03 11:03
Danke an euch zwei für die schnellen Antworten, werde jetzt nochmal alles genau durchtesten und probieren. :D
@ BungeeBug
Mein Problem war halt dass ich ned wusste wie ich diese 4 bytes senden soll. Hab halt ned daran gedacht die einfach mit ÿ's zu machen.
mfg manu
|
|
manu 
      
Beiträge: 21
|
Verfasst: Fr 30.05.03 23:10
Titel: Neues Problem beim Broadcast Empfang
Ok, mein Problem von oben ist jetzt gelöst es funktioniert alles wunderbar. Doch jetzt häng ich an einem neuen Problem fest. Mein Programm soll ja alle verfügbaren LAN-Server auflisten, also habe ich einfach eine Broadcast Message an alle Rechner im Netz geschickt. Nur wie kann ich dann die Antworten der Server im LAN empfangen? Beim idUDPClient gibt es ja kein OnRead-Ereigniss wie beim Server. Theoretisch müsste man ja eigentlich alle Antworten in einer Schleife abfragen. Ich hab nur kein Plan wie ich das jetzt machen soll, vieleicht weiß ja einer von Euch weiter?
mfg manu
|
|
cirrus
      
Beiträge: 49
|
Verfasst: Sa 31.05.03 01:52
versuch es mit dem tidudpserver. damit kannst du broadcasts senden und alle gesendeten daten im OnUPDRead Ereignis verarbeiten. bin mir allerdings nicht sicher ob das klappt, ist aber einen versuch wert.
mfg cirrus
_________________ Wenn die Nacht am tiefsten ist der Tag am nächsten
|
|
manu 
      
Beiträge: 21
|
Verfasst: So 01.06.03 12:20
Ich habs schon flüchtig mit der Server-Komponente versucht, da hats ned geklappt, aber wenn du sonst keinen anderen Weg weist werd ich da mal weiter rumexperimentieren. :D
mfg manu
|
|
cirrus
      
Beiträge: 49
|
Verfasst: So 01.06.03 12:58
Eine Lan server auflistung habe ich selbst auch noch nicht gecodet, hier ein guter artikel: Hier
_________________ Wenn die Nacht am tiefsten ist der Tag am nächsten
|
|
manu 
      
Beiträge: 21
|
Verfasst: Mo 02.06.03 13:46
Ok jetzt klappt alles :D
Hab einfach in einer Schleife solange mit dem Client per ReciveString empfangen bis keine Daten mehr kommen.
Die der Link oben hat mir zwar nicht direkt weitergeholfen, aber war trotzdem nützlich.
mfg manu
|
|
CGerdon
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Mo 16.06.03 18:02
mhhh...gibts ein tool für Quake 3 wo man nur die Server IP eingeben muss und er zeigt dann die Infos (gametyp und so). Für UT gibts ja hier ein Beispiel: www.kquery.com/devel...index2.php?article=4
|
|
manu 
      
Beiträge: 21
|
Verfasst: Mo 16.06.03 19:48
Ein fertiges Tool kenne ich nicht, aber ist ja kein Problem sowas mit Delphi zu machen. Oben steht ja bereits der Code. Wenn Bedarf besteht kann ich dir gern auch nochmal ein ausführlicheres Beispiel dazu schreiben.
mfg manu
|
|
CGerdon
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Mo 16.06.03 19:53
Eine Ausführlich Anleitung wäre super  Bin nähmlich noch ziemlich newbie in Sachen Delphi 
|
|
manu 
      
Beiträge: 21
|
Verfasst: Mo 16.06.03 21:12
Ich hab das ganze als Delphi 7 Projekt abgespeichert, gezippt und hier hochgeladen. Den kompletten Quellcode mach ich am besten hier auch noch rein:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92:
| unit Unit1;
interface
uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, IdBaseComponent, IdComponent, IdUDPBase, IdUDPClient;
type TForm1 = class(TForm) ed_host: TEdit; ed_port: TEdit; la_host: TLabel; la_port: TLabel; cb_string: TCheckBox; bu_abfragen: TButton; Client: TIdUDPClient; procedure bu_abfragenClick(Sender: TObject); procedure ed_portKeyPress(Sender: TObject; var Key: Char); private { Private-Deklarationen } public { Public-Deklarationen } end;
var Form1: TForm1;
implementation
{$R *.dfm}
function wertholen(var str: string; const wertname: string): string; var startpos, endpos: integer; var tmp: string; begin tmp:= copy(str,0,Length(str)); startpos:= (pos(wertname+'\',tmp)+Length(wertname+'\')); endpos:= Length(tmp); tmp:= copy(tmp,startpos,endpos); endpos:= (pos('\',tmp)-1); if pos('\',tmp)=0 then endpos:= Length(tmp); result:= copy(tmp,0,endpos); end;
procedure TForm1.bu_abfragenClick(Sender: TObject); var str: string; startticks, endticks: integer; begin if (ed_host.Text<>'') and (ed_port.Text<>'') then begin Client.ReceiveTimeout:= 500; Client.Host:= ed_host.Text; Client.Port:= StrToInt(ed_port.Text); Client.Active:= True; startticks:= GetTickCount; Client.Send('ÿÿÿÿgetinfo'); str:= Client.ReceiveString; endticks:= GetTickCount; Client.Active:= False; if str<>'' then begin if cb_string.Checked then begin showmessage(str); end else begin showmessage( 'Serveradresse: '+ed_host.Text+':'+ed_port.Text+#13+ 'Servername: '+wertholen(str,'\sv_hostname')+#13+ 'Aktuelle Map: '+wertholen(str,'\mapname')+#13+ 'Spieler: '+wertholen(str,'\clients')+'/'+wertholen(str,'sv_maxclients')+#13+ 'Ping: '+IntToStr(endticks-startticks)+' ms'+#13+ 'Gametype: '+wertholen(str,'\gametype')+#13+ 'Protocol Version:: '+wertholen(str,'\protocol')+#13+ 'Punkbuster: '+wertholen(str,'\punkbuster')+#13+ 'Pure Server: '+wertholen(str,'\pure') ) end; end else showmessage('Leider wurde kein server gefunden!'); end else showmessage('Bitte IP und Port eingeben!'); end;
procedure TForm1.ed_portKeyPress(Sender: TObject; var Key: Char); begin if not (key in [#8, #9, #48 .. #57]) then key:=#0; end;
end. |
Um das Ganze zum laufen zu bringen brauchst du außerdem noch Indy 9, das gibts hier. Einfach runterladen, entpacken, die Fulld7.bat ausführen und in Delphi bei Komponenten / Packages installieren / Hinzufügen die Datei "pfadzuindy\d7\dclIndy70.bpl" hinzufügen. dann kannst du die Datei Project1.dpr aus meinem Archiv in Delphi öffnen, ändern und kompilieren.
Statt dem ÿÿÿÿgetinfo kannst du auch ÿÿÿÿgetstatus nehmen, dann bekommst du noch mehr Infos vom Server.
Falls noch Fragen offen sind einfach hier posten!
mfg manu
|
|
CGerdon
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Mo 16.06.03 21:19
WOW, klasse!!!  Ich werd mal morgen versuchen, dass so umzuschreiben, dass der richtige Gametyp angezeigt wird, (im moment 1,2,3 usw statt Free For All, CTF, usw.) Ich denke das schaffe ich so! Vielen vielen Dank nochmal! 
|
|
CGerdon
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Mo 16.06.03 21:45
ich habe doch noch ne Frage: Ich möchte, dass die Infos nicht als Message sondern in einzelnen Edit Felder kommt:
ed_servername.text:='Servername: '+wertholen(str,'\sv_hostname')+#13+ klappt aber nich 
|
|
manu 
      
Beiträge: 21
|
Verfasst: Di 17.06.03 14:28
Das musst du so machen:
Quelltext 1:
| ed_servername.text:= 'Servername: '+wertholen(str,'\sv_hostname'); |
Das +#13+ ist nur dafür da, dass es in der Showmessage-Box einen Zeilenumbruch gibt.  Auch nicht vergessen dafst du dass nach jeder Anweisung ein abschließendes ; folgen muss.
Das 'Servername: ' würde ich aber ned im Edit-Feld anzeigen sondern per Label davor. (So wie oben bei der Hostadresse)
Ansonsten sage ich gern geschehen, wenn ich dir damit weiterhelfen konnte. Wenn du fertig bist kannst du es ja auch mal hochladen oder mir per Mail schicken!
mfg manu
|
|
CGerdon
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Di 17.06.03 14:32
jo, sobald ich fertig bin lad ich die exe und den Source Code hoch 
|
|
|