[Delphi] CS details ontvangen, [beginners problem?

Pagina: 1
Acties:
  • 160 views sinds 30-01-2008
  • Reageer

  • Cheater
  • Registratie: Januari 2001
  • Laatst online: 23:34
Aan de hand van:
[topic=366476/1/25]

met deze quote wou ik even verder gaan:
Hmm ik heb me niet zo verdiept in Delphi, maar het idee is dat je erachter komt hoe lang de string is die je terugkrijgt (met VB is dat Len(string). En dat je de string van achteren naar voren met een 'for-loopje' gaat parsen. Als je met dat for-loopje een Chr(0) tegenkomt (dit is in VB een null-character) weet je dat het stukje info na dat character begint.
In VB kan je dan met de functie Mid(string,start,length) het stukje string eruit halen.
string = de string die je terugkrijgt van de server
start = (de positie waar het for loopje de chr(0) heeft gevonden) + 1
length = deze kan je weglaten omdat de functie toch niet verder kijkt dan het volgende null-character.
Een aan de hand van deze quote baseer ik m'n probleem:
Op dinsdag 01 januari 2002 22:13 schreef Stoel het volgende:

ik heb dit:
code:
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
procedure TForm1.Button1Click(Sender: TObject);
var
  MyStream: TMemoryStream;
  TmpStr: String;
  command:string;
Begin
  NMUDP1.ReportLevel := Status_Basic;
  NMUDP1.RemoteHost := Edit1.Text;
  NMUDP1.RemotePort := StrToInt(Edit2.Text);
  command := edit3.text+#13#10;
  TmpStr := command;
  MyStream := TMemoryStream.Create;
  try
    MyStream.Write(TmpStr[1], Length(command));
    NMUDP1.SendStream(MyStream);
  finally
    MyStream.Free;
  end;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  Memo1.Clear;
end;

procedure TForm1.NMUDP1Status(Sender: TComponent; status: String);
begin
  If StatusBar1 <> nil then
    StatusBar1.SimpleText := status;
end;

procedure TForm1.NMUDP1DataSend(Sender: TObject);
begin
  StatusBar1.SimpleText := 'Data Sent';
end;

procedure TForm1.NMUDP1InvalidHost(var handled: Boolean);
var
  TmpStr: String;
begin
  If InputQuery('Invalid Host!', 'Specify a new host:', TmpStr) then
  Begin
    NMUDP1.RemoteHost := TmpStr;
    Handled := TRUE;
  End;
end;

procedure TForm1.NMUDP1DataReceived(Sender: TComponent;
  NumberBytes: Integer; FromIP: String; Port: Integer);
var
  MyStream: TMemoryStream;
  TmpStr: String;
begin
  MyStream := TMemoryStream.Create;
  try
    NMUDP1.ReadStream(MyStream);
    SetLength(TmpStr,NumberBytes);
    MyStream.Read(TmpStr[1],NumberBytes);
    Memo1.Lines.Add(TmpStr);
  finally
    MyStream.Free;
  end;
end;

Nu geef ik het commando:

ÿÿÿÿdetails

Maar nu krijg ik alleen : ÿÿÿÿm213.239.57.46:27045 terug!!
De rest blijft ergens achter!!
Want ik moet nog de servername krijgen en mod type, os, enz enz!!
Hoe krijg ik dit nu voor elkaar??
Please help me, ik moet graag een goede documantatie van het cs protocol hebben, :)
Ik heb nu hetzelfde, en lang leve Gathering, ik zit met hetzelfde probleem... met de bovenste quote kan ik niet veel, omdat ik daar niet echt gespecialiseerd in ben. Alleen wat basic shit enzo. Maar kan iemand mij nou eens een constructie geven AAN DE HAND VAN BOVENSTAANDE QUOTE hoe ik dit loopje nou in elkaar moet zetten? Hoe ik dus kan achterhalen wanneer de spatie is gegeven.

Verwijderd

Probeer eens een pchar? scheelt 4 bytes

edit: Schrijf die #13#10 maar niet. Zul je zien krijg je alles terug! CR/LF ofwel "windows-enter"

  • whoami
  • Registratie: December 2000
  • Laatst online: 01:57
Ik versta uw probleem niet goed hoor. Kun je het misschien eens duidelijk verwoorden?

https://fgheysels.github.io/


  • Cheater
  • Registratie: Januari 2001
  • Laatst online: 23:34
Ik heb er dit ingepleurd:

for n := 1 to Length(TmpStr) do
if Copy(TmpStr, n, 1) = Char(0) then
begin
Label1.Caption := 'Spatie gedetecteerd';

end;


Dit werkt. Maar hoe kan ik nou de rest van de hele informatiezooi bekijken?

  • Tomatoman
  • Registratie: November 2000
  • Laatst online: 01:25

Tomatoman

Fulltime prutser

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
procedure TForm1.NMUDP1DataReceived(Sender: TComponent;
  NumberBytes: Integer; FromIP: String; Port: Integer);
var
  MyStream: TMemoryStream;
  TmpStr: String;
begin
  MyStream := TMemoryStream.Create;
  try
    NMUDP1.ReadStream(MyStream);
    SetLength(TmpStr,NumberBytes);
    MyStream.Read(TmpStr[1],NumberBytes);
    Memo1.Lines.Add(TmpStr);
  finally
    MyStream.Free;
  end;
end;

Je schrijft: Nu geef ik het commando: ÿÿÿÿdetails
Maar nu krijg ik alleen : ÿÿÿÿm213.239.57.46:27045 terug!!


Dat zijn dus 24 karakters, oftewel 24 bytes. Met de parameter NumberBytes geeft de procedure aan hoeveel bytes werkelijk zijn ontvangen. Ik gok dat dat er meer zijn dan 24.

Zet eens een breakpoint op de eerste regel onder MyStream.Read(TmpStr[1], NumberBytes); (eenmaal links in de marge van de regel klikken). Zodra je programma bij het breakpoint stopt, beweeg je de cursor over de tekst TmpStr in de code editor van Delphi. Je ziet dan in een tooltip (de hinttekst) de waarde van TmpStr verschijnen - een tekst met meer dan 24 karakters (NumberBytes om precies te zijn).

Met Lines.Add wordt alles tot het eerste null-karakter (#0) aan de Memo toegevoegd, de rest niet :(. Maar de rest is dus wel ontvangen! Daarom moeten we wat handwerk doen >:).
code:
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
procedure TForm1.NMUDP1DataReceived(Sender: TComponent;
  NumberBytes: Integer; FromIP: String; Port: Integer);
var
  MyStream: TMemoryStream;
  TmpStr: string;
  NullPos: Integer;
begin
  MyStream := TMemoryStream.Create;
  try
    NMUDP1.ReadStream(MyStream);
    SetLength(TmpStr,NumberBytes);
    MyStream.Read(TmpStr[1],NumberBytes); // data kopiëren naar TmpStr
    { Nu TmpStr in stukken knippen. Alles tot eerste #0 aan memo toevoegen en
    vervolgens aan de voorkant van TmpStr afknippen. Zo wordt TmpStr steeds
    korter aan de voorkant, totdat er niets meer over is. }
    while TmpStr <> '' do      // zolang er nog tekst over is ...
    begin
    NullPos := Pos(#0, TmpStr); // waar is de eerste #0?
    { Tekst aan memo toevoegen. Alles na eerste #0 wordt weggelaten. }
    Memo1.Lines.Add(TmpStr);
    if NullPos = 0 then
      TmpStr := ''        // klaar!
    else
      { TmpStr wordt nu gelijk aan alle tekst achter eerste #0. In feite wordt
        dus alles t/m #0 weggeknipt en wat er overblijft wordt de nieuwe
        waarde van TmpStr. Met Copy worden nooit méér karakters gekopieerd dan
        TmpStr lang is, dus de parameter NumberBytes kun je ook vervangen door
        zoiets als 100000, zolang het maar tenminste de lengte van (de oude)
        TmpStr is. }
      TmpStr := Copy(TmpStr, NullPos +1, NumberBytes);
    end;
  finally
    MyStream.Free;
  end;
end;

En nog bedankt voor je nieuwjaarswens :).

Een goede grap mag vrienden kosten.


  • Cheater
  • Registratie: Januari 2001
  • Laatst online: 23:34
Deze messages was TE laat, en niet goed na de bovenstaande geweldige post

  • Cheater
  • Registratie: Januari 2001
  • Laatst online: 23:34
in 1 woord: VET.
in 2 woorden: you're cool
in 5 woorden: je verdient m'n eeuwige dank

De informatie die ik nu krijg:
code:
1
2
3
4
5
6
7
8
9
ÿÿÿÿm213.206.78.236:27015
[ToD] War Arena
de_aztec
cstrike
CounterStrike
    ž-dlžžwww.counter-strike.net
ž
ž÷
ž

Wat zijn die gekke blokjes?

  • Tomatoman
  • Registratie: November 2000
  • Laatst online: 01:25

Tomatoman

Fulltime prutser

Nu er nog overheen springen . (voor mij het moeilijkste ?)
Hoe bedoel je?

[Edit] Laat maar, ook ik was te laat met mijn reactie.

Een goede grap mag vrienden kosten.


  • Cheater
  • Registratie: Januari 2001
  • Laatst online: 23:34
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
"details"
    (int32)         -1
    (byte)      ASCII 'm' ( S2A_INFO_DETAILED )
    (string)        net address of server
    (string)        name of the host / server
    (string)        name of the map
    (string)        game directory (i.e. valve/)
    (string)        Game description (e.g. "half-life multiplay")
    (byte)      active client count
    (byte)      maximum clients allowed
    (byte)      protocol version (currently 37)
    (byte)      type of server == 'l' for listen or 'd' for dedicated
    (byte)      os of server == 'w' for win32 or 'l' for linux
    (byte)      password on server == 1 or yes, 0, for no
    (byte)      is server running a mod? == 1 for yes, 0 for no

    IFF the server is running mod byte was 1:

    (string)        URL for mod's "info" website
    (string)        URL for mod's download ftp server
    (int32)     mod version #
    (int32)     mod download size ( in bytes, approx. )
    (byte)      is the mod a server side only mod?  1 == yes, 0 == no
    (byte)      does this server require you to have a custom client side .dll ( client.dll )?  1 == yes, 0 == no.

Met de commando details (en nog wat ervoor)
krijg je bovenstaande allemaal teruggestuurd.
Nou is mijn verklaring voor die blokjes dat dat de bytes zijn. die hierboven staan beschreven.
Wat kan ik daartegen doen?

De bedoeling is straks netjes alles in labels zetten.

  • Tomatoman
  • Registratie: November 2000
  • Laatst online: 01:25

Tomatoman

Fulltime prutser

Die gekke blokje zijn karakters die niet kunnen worden weergegeven met het geselecteerde lettertype. Meestal zijn dat karakters met een speciale betekenis. Zoek in Delphi Help maar eens naar 'Virtual Key Codes' voor meer uitleg. Je zult in de documentatie van het cs-protocol moeten opzoeken wat de precieze betekenis is.

Een goede grap mag vrienden kosten.


  • Tomatoman
  • Registratie: November 2000
  • Laatst online: 01:25

Tomatoman

Fulltime prutser

Daar gaat 'ie dan. Inmiddels heb ik de code kunnen testen met een serviceverbinding en de fouten eruit gehaald >:). Hij werkt alleen met het commando details, maar met het voorbeeld kun je zelf code voor andere commando's schrijven.
code:
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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, NMUDP, StdCtrls, ComCtrls;

type
  TForm1 = class(TForm)
    NMUDP1: TNMUDP;
    Edit1: TEdit;
    Edit2: TEdit;
    Edit3: TEdit;
    Button1: TButton;
    procedure NMUDP1DataReceived(Sender: TComponent; NumberBytes: Integer;
    FromIP: String; Port: Integer);
    procedure Button1Click(Sender: TObject);
  end;

type
  TDetails = packed record
    Version: Longint;        // -1 of +1
    M: Char;              // 'm'
    NetAddress: string;
    HostName: string;
    MapName: string;
    GameDir: string;
    GameDescription: string;
    ActiveClientCount: Byte;
    MaxClients: Byte;
    ProtocolVersion: Byte;  // 37
    ServerType: Char;        // 'l' voor listen of 'd' voor dedicated
    ServerOS: Char;      // 'w' voor win32 of 'l' voor linux
    Password: Boolean;
    case ModRunning: Boolean of
    False: ();
    True: (
      InfoURL: ShortString;
      FTPURL: ShortString;
      ModVersion: Longint;
      ModSize: Longint;
      ServerSideOnly: Boolean;
      ClientDLL: Boolean);
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

function DecodeStream(P: Pointer): TDetails;
var
  NullPos: Integer;
begin
  with Result do
  begin
    // pointer wijst naar Version
    Version := Cardinal(P^);
    if Version <> -1 then
    raise Exception.Create('verkeerde versie'); // afbreken met een fout
    Inc(Cardinal(P), SizeOf(Version)); // pointer voorbij Version verschuiven

    // pointer wijst nu naar M
    M := Char(P^);
    if M <> 'm' then
    raise Exception.Create('verkeerde commando'); // afbreken met een fout
    Inc(Cardinal(P), SizeOf(Version));

    NetAddress := PChar(P);     // null-terminated string (exclusief #0)
    NullPos := Length(PChar(P)) +1;    // waar is de eerste #0 (n-de karakter)?
    Inc(Cardinal(P), NullPos);     // pointer voorbij NetAddress verschuiven

    HostName := PChar(P);
    NullPos := Length(PChar(P)) +1;
    Inc(Cardinal(P), NullPos);

    MapName := PChar(P);
    NullPos := Length(PChar(P)) +1;
    Inc(Cardinal(P), NullPos);

    GameDir := PChar(P);
    NullPos := Length(PChar(P)) +1;
    Inc(Cardinal(P), NullPos);

    GameDescription := PChar(P);
    NullPos := Length(PChar(P)) +1;
    Inc(Cardinal(P), NullPos);

    ActiveClientCount := Byte(P^);
    Inc(Cardinal(P), SizeOf(ActiveClientCount));

    MaxClients := Byte(P^);
    Inc(Cardinal(P), SizeOf(MaxClients));

    ProtocolVersion := Byte(P^);
    Inc(Cardinal(P), SizeOf(ProtocolVersion));

    ServerType := Char(P^);
    Inc(Cardinal(P), SizeOf(ServerType));

    ServerOS := Char(P^);
    Inc(Cardinal(P), SizeOf(ServerOS));

    Password := Boolean(P^);
    Inc(Cardinal(P), SizeOf(Password));

    ModRunning := Boolean(P^);
    if ModRunning then
    begin
    Inc(Cardinal(P), SizeOf(ModRunning));

    InfoURL := PChar(P);
    NullPos := Length(PChar(P)) +1;
    Inc(Cardinal(P), NullPos);

    FTPURL := PChar(P);
    NullPos := Length(PChar(P)) +1;
    Inc(Cardinal(P), NullPos);

    ModVersion := Longint(P^);
    Inc(Cardinal(P), SizeOf(ProtocolVersion));

    ModSize := Longint(P^);
    Inc(Cardinal(P), SizeOf(ProtocolVersion));

    ServerSideOnly := Boolean(P^);
    Inc(Cardinal(P), SizeOf(ProtocolVersion));

    ClientDLL := Boolean(P^);
    end;
  end;
end;

procedure TForm1.NMUDP1DataReceived(Sender: TComponent;
  NumberBytes: Integer; FromIP: String; Port: Integer);
var
  MemStream: TMemoryStream;
  StreamPointer: Pointer;
  Details: TDetails;
begin
  MemStream := TMemoryStream.Create;
  try
    NMUDP1.ReadStream(MemStream);
    StreamPointer := MemStream.Memory;
    Details := DecodeStream(StreamPointer);

    { doe nu iets met Details - een voorbeeld }
    with Details do
    begin
    ShowMessage('Game-beschrijving: ' + GameDescription);
    if ModRunning then
      ShowMessage('website voor info: ' + InfoURL)
    else
      ShowMessage('Mod draait niet - geen website voor info beschikbaar');
    end;
  finally
    MemStream.Free;
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  MemStream: TMemoryStream;
  Command: string;
Begin
  NMUDP1.ReportLevel := Status_Basic;
  { voorbeeldinstellingen: RemoteHost = '66.88.59.170', RemotePort = 27015,
    Command = 'details' }
  NMUDP1.RemoteHost := Edit1.Text;
  NMUDP1.RemotePort := StrToInt(Edit2.Text);
  Command := #$FF + #$FF + #$FF + #$FF +  Edit3.Text + #0;
  MemStream := TMemoryStream.Create;
  try
    MemStream.Write(Command[1], Length(Command));
    NMUDP1.SendStream(MemStream);
  finally
    MemStream.Free;
  end;
end;

end.

Een goede grap mag vrienden kosten.


  • Cheater
  • Registratie: Januari 2001
  • Laatst online: 23:34
ActiveClientCount := Byte(P^);
Inc(Cardinal(P), SizeOf(ActiveClientCount));

toch wel 1 van de belangrijkere onderdelen:

Kan ik hier nu niets mee?

Het is Byte, wat ik niet in een Label.Caption kan zetten of in een memo. Want dan heeftie zogenaamd een string nodig. Wat moet ik hiermee aan?

  • jelmervos
  • Registratie: Oktober 2000
  • Niet online

jelmervos

Simple user

Byte is toch gewoon 0..255? Kun je die niet met IntToStr omzetten?

"The shell stopped unexpectedly and Explorer.exe was restarted."


  • Tomatoman
  • Registratie: November 2000
  • Laatst online: 01:25

Tomatoman

Fulltime prutser

ActiveClientCount is een getal, een byte. Natuurlijk zou je die TDetails record zodanig kunnen ombouwen dat ActiveClientCount een string is, maar daarmee leg je jezelf veel beperkingen op. Als je over een jaar die code in een ander projectje wilt gebruiken, denk je tegen die tijd:

1) Waarom is ActiveClientCount in godsnaam een string en geen getal? :?
2) Hoe maak ik er alsnog een getal van in die recordstructuur? :?

Grote kans dus dat je dan het wiel opnieuw moet uitvinden. In ieder geval zou je dan de functie DecodeStream moeten herschrijven. Zonde, want dat is nergens voor nodig als je het nu in één keer goed doet. Ik raad je dus aan dergelijke, ingewikkelde functies zo logisch mogelijk te houden, het bespaart je een hoop hoofdbrekens in de toekomst.

Overigens gaat conversie zoals jelmervos zegt heel eenvoudig:
Label1.Caption := IntToStr(Details.ActiveClientCount);
of nog mooier
Label1.Caption := Format('%d clients actief', [Details.ActiveClientCount]);

Enne, ik geef toe dat de code waarmee ik je heb opgezadeld, best intimiderend is. Maar ja, het was dan ook niet bepaald een beginnersprobleem ;).

Een goede grap mag vrienden kosten.


  • Cheater
  • Registratie: Januari 2001
  • Laatst online: 23:34
Ik stond gewoon verbaasd te kijken naar je kennis, en je hulp
Meestal blijven dit probleempjes in de onopgeloste problemen bak

  • Cheater
  • Registratie: Januari 2001
  • Laatst online: 23:34
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
"players"
    Server responds with the following packet:
    (int32)     -1
    (byte)      ASCII 'D' (players response, S2A_PLAYER)
    (byte)      active client count

    for each active client
        (byte)      client number / index
        (string)        player name
        (int32)     client's frag total
        (float32)       client's total time in-game

"rules"
    Server responds with the following packet:
    (int32)     -1
    (byte)      ASCII 'E' (rules response, S2A_RULES)
    (int16)     number of rules

    for each rule
        (string)        rule name
        (string)        rule value

Je krijgt hier het geval 'for each', zoals 'for each active client'.
Hoe los ik dat op? Het spelersaantal is een flucturerend getal.

  • Cheater
  • Registratie: Januari 2001
  • Laatst online: 23:34
code:
1
2
"ping"
    Server responds with a single byte code ASCII 'j'

En bij ping krijg ik altijd een ping van 106ms.
Hij refresh om de 1 seconde, maar al een hele lange tijd 106ms. En er zitten zo'n 15 mensen op de server, dus toeval lijkt het me niet.

  • Cheater
  • Registratie: Januari 2001
  • Laatst online: 23:34
^kick^

Verwijderd

Probeer eens een class te maken, waar je de gegevens van 'players' in kunt stoppen;

Een class werkt hier denk ik beter dan een record, omdat je een array van variabele lengte [lees TList] nodig hebt, die je moet creeeren en destroyen.

  • Cheater
  • Registratie: Januari 2001
  • Laatst online: 23:34
voor mij praat jij nu arabisch

Verwijderd

:) Wat was de vraag dan? Wat wil je doen met die "players" en "rules" gegevens?

Verwijderd

Op vrijdag 29 maart 2002 21:31 schreef DiFool het volgende:
:) Wat was de vraag dan? Wat wil je doen met die "players" en "rules" gegevens?
Nee hij bedoeld dat ie newbie is .. net als mij in delphi :P ;)

  • Cheater
  • Registratie: Januari 2001
  • Laatst online: 23:34
duz ik ben niet duidelijk genoeg met mij vraag?

  • jelmervos
  • Registratie: Oktober 2000
  • Niet online

jelmervos

Simple user

Op zaterdag 30 maart 2002 02:13 schreef Cheater het volgende:
duz ik ben niet duidelijk genoeg met mij vraag?
Nope :)

"The shell stopped unexpectedly and Explorer.exe was restarted."


  • Cheater
  • Registratie: Januari 2001
  • Laatst online: 23:34
Ik moet een soort While not EOF krijgen ofzoiets

bij Players
en ook bij Rulez. maar rulez heb ik al eens gezien, die's niet zo belangrijk, maar misschien wel handig, om wat preferences van de server te laten zien

Verwijderd

pseudo-code:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Version := [lees een int32];
{ Version moet -1 zijn }
Assert(Version = -1, 'Verkeerde versie');

B := [lees een byte];
{ B moet 'D' zijn }
Assert(B = 'D', 'Geen player response');

PlayerCount := [lees een byte]
for i := 0 to PlayerCount - 1 do
begin
  ClientNumber[i] := [lees een byte];
  PlayerName[i]   := [lees een string];
  FragTotal[i]    := [lees een int32];
  TotalTime[i]    := [lees een float32];
end;

Als je goed in de code van tomatoman kijkt, kun je wel bepalen hoe je []-code moet programmeren.

Je moet verder bedenken of je de waarden die je inleest wilt opslaan, of meteen op het scherm wilt afdrukken.

  • Cheater
  • Registratie: Januari 2001
  • Laatst online: 23:34
Meteen afdrukken, want ik heb er een refresh van 1 seconden opzitten.

Belast dit de server eigenlijk niet? Straks monitoren zo'n 10 mensen die server tegelijk.

  • Cheater
  • Registratie: Januari 2001
  • Laatst online: 23:34
Ik denk dat ik de Float32 fout heb. Ik heb er maar een LongInt neergezet, maar dit klopt denk ik niet. Het heeft iets met tijd te maken, dus that's why. Wat moet ik aan met Float32? ik heb de HELP van Delphi er ook op nageslagen, maar niet echt iets gevonden.

  • OxiMoron
  • Registratie: November 2001
  • Laatst online: 27-06 10:54
ik zoek ff....
code:
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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
Procedure Detailinput(Buff: Array of char;Size: Integer);
{
    Detail input procedure.
   Invoer:
   - Buff -> ingekomen packet
   - Size -> grote ingekomen packet
   Uitvoer:
   - De Details van de server in de ServerView
       - IP en poort (niet gebruikt)
    - Hostname
    - Huidige map
    - Gamedir (niet gebruikt)
    - Game
    - Aantal Connecties - Max aantal connecties
    - Protocol Versie (niet gebruikt)
    - Server type -> 'd' = dedicated 'l' = Listen
    - Server OS -> 'l' = Linux 'w' = win32
    - Password -> '0' = nee '1' = ja
    - Draait mod -> '0' = nee '1' = ja (niet gebruikt)
        - als ie 1 is dan: (niet gebruikt)
           - URL Mod's site (niet gebruikt)
        - URL mod's ftp (niet gebruikt)
        - Mod versie (niet gebruikt)
        - mod size in bytes (niet gebruikt)
        - server side only mod? -> '1' = ja '0' = nee (niet gebruikt)
        - eigen client.dll voor mod nodig? -> '1' = ja '0' = nee (niet gebruikt)
}
Var
     S: String;
    J: Integer;
    Z: TListItem;
begin
    S := '';
    J := 5;
    MainForm.ServerView.Items.Clear;
    While Buff[J] <> Char($00) do
    begin //Ip enzo
        S := S + Buff[J];
        Inc(J);
    end;
    //ip en poort
    //Showmessage(S);
    S := '';
    Inc(J);
    While Buff[J] <> Char($00) do
    begin //Hostname
        S := S + Buff[J];
        Inc(J);
    end;
    Z := MainForm.ServerView.Items.Add;
    Z.ImageIndex:=0;
    Z.Caption := 'Hostname';
    Z.SubItems.Add(S);
    S := '';
    Inc(J);
    While Buff[J] <> Char($00) do
    begin //map
        S := S + Buff[J];
        Inc(J);
    end;
    Z := MainForm.ServerView.Items.Add;
    Z.ImageIndex:=0;
    Z.Caption := 'Map';
    Z.SubItems.Add(S);
    S := '';
    Inc(J);
    While Buff[J] <> Char($00) do
    begin //Gamedir
        S := S + Buff[J];
        Inc(J);
    end;
    //niet belangrijk (nog)
    S := '';
    Inc(J);
    While Buff[J] <> Char($00) do
    begin //game
        S := S + Buff[J];
        Inc(J);
    end;
    Z := MainForm.ServerView.Items.Add;
    Z.ImageIndex:=0;
    Z.Caption := 'Game';
    Z.SubItems.Add(S);;
    S := '';
    Inc(J);
   //active connections - max. connections
     S := IntToStr(Ord(Buff[J]))+' - ' +IntToStr(Ord(Buff[J+1]));
    Z := MainForm.ServerView.Items.Add;
    Z.ImageIndex:=0;
    Z.Caption := 'Connecties';
    Z.SubItems.Add(S);
    S:= '';
    Inc(J,2);
    //Buff[J] = protocol version
    Inc(J);
    Z := MainForm.ServerView.Items.Add;
    Z.ImageIndex:=0;
    Z.Caption := 'Server type';
    If Buff[J] = 'd' then //dedicated server, anders Listen
        Z.Subitems.Add('Dedicated') else
      Z.Subitems.Add('Non-dedicated');
    Inc(J);
    Z := MainForm.ServerView.Items.Add;
    Z.ImageIndex:=0;
    Z.Caption := 'OS type';
    If Buff[J] = 'w' then //server draait in windows, anders linux
        Z.Subitems.Add('Win32') else
      Z.Subitems.Add('Linux');
    Inc(J);
    Z := MainForm.ServerView.Items.Add;
    Z.ImageIndex:=0;
    Z.Caption := 'Password';
    If Ord(Buff[J]) = 1 then //server heeft password, anders geen password
      Z.Subitems.Add('Yes') else
      Z.Subitems.Add('No');
end;

Procedure Playerinput(Buff: Array of char;Size: Integer);
{
    Player input procedure.
   Invoer:
   - Buff -> ingekomen packet
   - Size -> grote ingekomen packet
   Uitvoer:
   - De Details van de server in de PlayerView
    - Aantal clienten
    - Voor elke client:
        - client's nummer
    - client's naam
    - client's kill aantal
    - client's total time ingame
}
Var
    I,J: Integer;
   Li: LongInt;
   Z: TListItem;
   S: String;
   t: Double;
begin
    MainForm.PLayerView.Items.Clear;
   J := 6;
    for I := 1 to Ord(Buff[5]) do //tot Aantal clienten
   begin
       Z := MainForm.PlayerView.Items.Add;
         Z.ImageIndex:=0;
    //Id number
    If Length(IntToStr(Ord(Buff[J]))) = 1 then
             Z.Caption := '0'+IntToStr(Ord(Buff[J])) else
       Z.Caption := IntToStr(Ord(Buff[J]));
    //Naam
    S := '';
    Inc(J);
    While Buff[J] <> Char($00) do
    begin
        S := S + Buff[J];
       Inc(J);
    end;
        Z.SubItems.Add(S);
    //aantal kills
    Inc(J);
    Li := StrToInt('$'+IntToHex(Ord(Buff[J+3]),2) + IntToHex(Ord(Buff[J+2]),2) + IntToHex(Ord(Buff[J+1]),2) + IntToHex(Ord(Buff[J]),2));
    Inc(J,4);
    Z.SubItems.Add(IntToStr(Li) );
    //Connectie tijd
    S := '';
    t := PSingle(@Buff[J])^;
    if Length(FloatToStr(Trunc(t/3600))) = 1 then                                        //om het mooi recht te houden 0 toevoegen bij minder dan 10 uur
        S := S + '0';
    S := S + FloatToStr(Trunc(t/3600))+':';                                              //Reken het aantal uur uit
    t := t - (Trunc(t/3600)*3600);                                                           //trek die uren van het totaal af
    if Length(FloatToStr(Trunc(t/60))) = 1 then                                          //om het mooi recht te houden 0 toevoegen bij minder dan 10 minuten
        S := S + '0';
    S :=  S + FloatToStr(Trunc(t/60))+':';                                               //Reken het aantal minuten uit
    t := t - (Trunc(t/60)*60);                                                                  //trek die minuten van het totaal af
    if Length(FloatToStr(Trunc(t))) = 1 then                         //om het mooi recht te houden 0 toevoegen bij minder dan 10 seconden
        S := S + '0';
    S := S +  FloatToStr(Trunc(t));                                                         //Reken het aantal seconden uit
        Inc(J,4);
    Z.SubItems.Add(S);
    end;
end;

Dit heb ik ff uit m'n eigen programma gehaalt..
Hij zet alles vervolgens ook in een ListView, maar ik denk dat je alles er verder wel uit krijgt..

vooral het stukje om de connectie tijd te krijgen kan wel handig zijn ;)

Albert Einstein: A question that sometime drives me hazy: Am I or are the others crazy?


  • OxiMoron
  • Registratie: November 2001
  • Laatst online: 27-06 10:54
Btw.. de code kan vast wel iets handiger, maar dit heb ik 2 jaar terug geschreven toen ik net met Delphi begon.

Albert Einstein: A question that sometime drives me hazy: Am I or are the others crazy?


  • Cheater
  • Registratie: Januari 2001
  • Laatst online: 23:34
pffff. ik heb er 2 dagen naar zitten kijken, maar ik kom er niet uit.

Wat moet ik nou ???

Verwijderd

Gebruik Single ipv Float32; en post eens de code die je al hebt.

  • OxiMoron
  • Registratie: November 2001
  • Laatst online: 27-06 10:54
ehh ik doorloop de buffer en haal de waardes eruit..

je moet de buffer die je binnenkrijgt niet rechtstreeks in een memo ofzo proppen maar stukje voor stukje parsen :)

Albert Einstein: A question that sometime drives me hazy: Am I or are the others crazy?


  • Cheater
  • Registratie: Januari 2001
  • Laatst online: 23:34
I know , I know. dat deed ik ook, maar ik zat met die TIME.
Ik wil een TIJDveld in een variabel stoppen
Maar met welke manier moet ik die TIME variabel declareren.

That was the point! Effe SINGLE proberen

  • Cheater
  • Registratie: Januari 2001
  • Laatst online: 23:34
Voor als ik D als code terug krijg, heb ik dit:
code:
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
function DecodeStream(P: Pointer): TDetails;
var
  i: integer;
  NullPos: Integer;
begin
  with Result do
  begin
    // pointer wijst naar Version
    Version := Cardinal(P^);
    Inc(Cardinal(P), SizeOf(Version)); // pointer voorbij Version verschuiven

    // pointer wijst nu naar M
    M := Char(P^);
    if (M = 'm') then
    begin

  end else if (M = 'D') then
  begin
  ActiveClientCount := Byte(P^);
  Inc(Cardinal(P), SizeOf(ActiveClientCount));

  for i := 0 to ActiveClientCount - 1 do
  begin
    Clientnumber := Byte(P^);
    Inc(Cardinal(P), SizeOf(ClientNumber));

    PlayerName := Char(P);
    NullPos := Length(PChar(P)) +1;
    Inc(Cardinal(P), NullPos);

    FragsCount := Longint(P^);
    Inc(Cardinal(P), SizeOf(ProtocolVersion));

    TotalTime := LongInt(P^);     // TotalTime := Single(P^); ook al geprobeerd
  end;

Heb ik het een beetje goed gedaan? :?

Verwijderd

PlayerName := PChar(P);

Verder stop je de gegevens nu in een TDetails, terwijl je ze eigenlijk meteen wilt afdrukken.

Beter zou misschien zijn:
code:
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
procedure DecodeStream(P: Pointer; AStrings: TStrings);
var
  { Hier wat var declareren bv:
  Clientnumber: Byte;
  PlayerName: string;
  NullPos: Integer;
  FragsCount: LongInt;
  TotalTime: Single;
begin
  [..]
  for i := 0 to ActiveClientCount - 1 do
  begin
    Clientnumber := Byte(P^);
    Inc(Cardinal(P), SizeOf(ClientNumber));

    PlayerName := PChar(P);
    NullPos := Length(PChar(P)) + 1;
    Inc(Cardinal(P), NullPos);

    FragsCount := Longint(P^);
    Inc(Cardinal(P), SizeOf(FragsCount));

    TotalTime := Single(P^);
    Inc(Cardinal(P), SizeOf(TotalTime));

    { Voeg de gegevens toe aan AStrings }
    AStrings.Add(Format('%d %s %d %d', 
    [ClientNumber, PlayerName, FragsCount, Trunc(TotalTime)]));
  end;
end;

Dan kun je de volgende aanroep doen, als je een listbox op het scherm zet:
code:
1
  DecodeStream(StreamPointer, ListBox1.Items);

  • Cheater
  • Registratie: Januari 2001
  • Laatst online: 23:34
Dit declareer ik bovenaan:
code:
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
type
  TDetails = packed record
    Version: Longint;        // -1 of +1
    M: Char;              // 'm'
    NetAddress: string;
    HostName: string;
    MapName: string;
    GameDir: string;
    GameDescription: string;
    ActiveClientCount: Byte;
    MaxClients: Byte;
    ProtocolVersion: Byte;  // 37
    ServerType: Char;        // 'l' voor listen of 'd' voor dedicated
    ServerOS: Char;      // 'w' voor win32 of 'l' voor linux
    Password: Boolean;
    Clientnumber: Byte;
    PlayerName: string;
    FragsCount: Longint;
    TotalTime: Single;
    case ModRunning: Boolean of
    False: ();
    True: (
      InfoURL: ShortString;
      FTPURL: ShortString;
      ModVersion: Longint;
      ModSize: Longint;
      ServerSideOnly: Boolean;
      ClientDLL: Boolean);
     end;

Dit is m'n Function van DecodeStream
code:
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
93
94
95
96
97
98
99
100
101
102
103
function DecodeStream(P: Pointer): TDetails;
var
  i: integer;
  NullPos: Integer;
begin
  with Result do
  begin
    // pointer wijst naar Version
    Version := Cardinal(P^);
    Inc(Cardinal(P), SizeOf(Version)); // pointer voorbij Version verschuiven

    // pointer wijst nu naar M
    M := Char(P^);
    if (M = 'm') then
    begin
 {     raise Exception.Create('verkeerde commando'); // afbreken met een fout}
    Inc(Cardinal(P), SizeOf(Version));

    NetAddress := PChar(P);     // null-terminated string (exclusief #0)
    NullPos := Length(PChar(P)) +1;    // waar is de eerste #0 (n-de karakter)?
    Inc(Cardinal(P), NullPos);     // pointer voorbij NetAddress verschuiven

    HostName := PChar(P);
    NullPos := Length(PChar(P)) +1;
    Inc(Cardinal(P), NullPos);

    MapName := PChar(P);
    NullPos := Length(PChar(P)) +1;
    Inc(Cardinal(P), NullPos);

    GameDir := PChar(P);
    NullPos := Length(PChar(P)) +1;
    Inc(Cardinal(P), NullPos);

    GameDescription := PChar(P);
    NullPos := Length(PChar(P)) +1;
    Inc(Cardinal(P), NullPos);

    ActiveClientCount := Byte(P^);
    Inc(Cardinal(P), SizeOf(ActiveClientCount));

    MaxClients := Byte(P^);
    Inc(Cardinal(P), SizeOf(MaxClients));

    ProtocolVersion := Byte(P^);
    Inc(Cardinal(P), SizeOf(ProtocolVersion));

    ServerType := Char(P^);
    Inc(Cardinal(P), SizeOf(ServerType));

    ServerOS := Char(P^);
    Inc(Cardinal(P), SizeOf(ServerOS));

    Password := Boolean(P^);
    Inc(Cardinal(P), SizeOf(Password));

    ModRunning := Boolean(P^);
    if ModRunning then
    begin
    Inc(Cardinal(P), SizeOf(ModRunning));

    InfoURL := PChar(P);
    NullPos := Length(PChar(P)) +1;
    Inc(Cardinal(P), NullPos);

    FTPURL := PChar(P);
    NullPos := Length(PChar(P)) +1;
    Inc(Cardinal(P), NullPos);

    ModVersion := Longint(P^);
    Inc(Cardinal(P), SizeOf(ProtocolVersion));

    ModSize := Longint(P^);
    Inc(Cardinal(P), SizeOf(ProtocolVersion));

    ServerSideOnly := Boolean(P^);
    Inc(Cardinal(P), SizeOf(ProtocolVersion));

    ClientDLL := Boolean(P^);
    end; 
  end else if (M = 'D') then
  begin

  ActiveClientCount := Byte(P^);
  Inc(Cardinal(P), SizeOf(ActiveClientCount));

  for i := 0 to ActiveClientCount - 1 do
  begin
    Clientnumber := Byte(P^);
    Inc(Cardinal(P), SizeOf(ClientNumber));

    PlayerName := PChar(P);
    NullPos := Length(PChar(P)) +1;
    Inc(Cardinal(P), NullPos);

    FragsCount := Longint(P^);
    Inc(Cardinal(P), SizeOf(ProtocolVersion));

    TotalTime := Single(P^);
  end;
  end;
  end;
end;

Hieronder staat de code, voor als de NMUDP component iets ontvangt:
code:
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
procedure TForm1.NMUDP1DataReceived(Sender: TComponent;
  NumberBytes: Integer; FromIP: String; Port: Integer);
var
  MemStream: TMemoryStream;
  StreamPointer: Pointer;
  Details: TDetails;
begin
  MemStream := TMemoryStream.Create;
  try
    NMUDP1.ReadStream(MemStream);
    StreamPointer := MemStream.Memory;
    Details := DecodeStream(StreamPointer);

    { doe nu iets met Details - een voorbeeld }

    with Details do
    begin
    if (M = 'm') then
    begin
    Label30.Caption := 'Monitoring: tod.rentone.nl';
    Label38.Caption := 'Naam: ' + HostName;
    Label39.Caption := 'Game: ' + GameDescription;
    Label40.Caption := 'Map: ' + MapName;
    Label41.Caption := 'Aantal spelers op server: ' + IntToStr(ActiveClientCount);
    Label42.Caption := 'Maximum spelers: ' + IntToStr(MaxClients);
    ProgressBar3.Max := MaxClients;
    ProgressBar3.Position := ActiveClientCount;
    end;
    if (M = 'D') then
    begin
    Label4.Caption := PlayerName;
    Label47.Caption := 'PlayerName';
    end;
    end;
  finally
    MemStream.Free;
  end;

En hieronder staat een procedure van een knopje waarbij ik de details van de server opvraag:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
procedure TForm1.Button10Click(Sender: TObject);
  var
  MemStream: TMemoryStream;
  Command: string;
begin
  Ping11.DnsLookup('tod.rentone.nl');
  NMUDP1.ReportLevel := Status_Basic;
  NMUDP1.RemoteHost := 'tod.rentone.nl';
  NMUDP1.RemotePort := StrToInt('27015');
  Command := #$FF + #$FF + #$FF + #$FF +  'details' + #0;
  MemStream := TMemoryStream.Create;
  try
    MemStream.Write(Command[1], Length(Command));
    NMUDP1.SendStream(MemStream);
  finally
    MemStream.Free;
  end;
end;

En hieronder een procedure van een knopje waarbij ik de players opvraag van de server
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
procedure TForm1.Button6Click(Sender: TObject);

  var
  MemStream: TMemoryStream;
  Command: string;
  begin
  NMUDP1.ReportLevel := Status_Basic;
  NMUDP1.RemoteHost := 'tod.rentone.nl';
  NMUDP1.RemotePort := StrToInt('27015');

  Command := #$FF + #$FF + #$FF + #$FF +  'players' + #0;
  MemStream := TMemoryStream.Create;
  try
    MemStream.Write(Command[1], Length(Command));
    NMUDP1.SendStream(MemStream);
  finally
    MemStream.Free;
  end;
end;

Je mag dik gaan testen, maar ik krijg iedere keer een weirde foutmelding als ik op het knopje voor de 'players' klik. Geen echte DELPHI foutmelding, maar zoiets van, fatale uitzondering enzo, blabla. Geen informatie over de foutmelding stat hierin.

Wat moet ik nou doen om het werkend te maken.

Even erbij vermelden WAT ik nou eigenlijk ontvang als ik commando 'details' verstuur:
code:
1
2
3
4
5
6
7
8
9
10
"players"
    Server responds with the following packet:
    (int32)     -1
    (byte)      ASCII 'D' (players response, S2A_PLAYER)
    (byte)      active client count
    for each active client
        (byte)      client number / index
        (string)        player name
        (int32)     client's frag total
        (float32)       client's total time in-game

Dus, tja. (tussen de codes door staan normale berichten)

Verwijderd

Waar treedt de fout precies op? Bepaal dit met breakpoints.

Verder zie ik zo nog wat foutjes:
  • PlayerName moet van het type string zijn ipv PChar;
  • Na 'TotalTime := Single(P^)' moet je ook een inc doen, dus bv:
    code:
    1
    
    Inc(Cardinal(P), SizeOf(TotalTime));

  • Cheater
  • Registratie: Januari 2001
  • Laatst online: 23:34
Even serius...

MOET dat?
die laatste INC?

Want er komt toch niets meer erna?

  • Cheater
  • Registratie: Januari 2001
  • Laatst online: 23:34
Ik weet het niet zeker, maar volgens mij

Loopt hij hier de fout in:

MemStream.Free;

Verwijderd

Ik zie dat je nog meer fouten maakt bij het inlezen; misschien is het makkelijk om wat hulpfuncties te maken voor het inlezen bv:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function LeesString(var P: Pointer): string;
var
  NullPos: Integer;
begin
  // null-terminated string (exclusief #0)  
  Result := PChar(P);
  // waar is de eerste #0 (n-de karakter)?    
  NullPos := Length(PChar(P)) +1;    
  
  Inc(Cardinal(P), NullPos);      
end;

function LeesByte(var P: Pointer): Byte;
begin
  Result := Byte(P^);
  Inc(Cardinal(P), SizeOf(Byte));
end;

Verder nog LeesInteger, LeesChar, LeesSingle etc.

Het begin van DecodeStream wordt dan:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function DecodeStream(P: Pointer): TDetails;
var
  [..]
begin
  with Result do
  begin
    Version := LeesCardinal(P);

    M := LeesChar(P);
    
    if M = 'm' then
    begin
    NetAddress := LeesString(P);
    HostName := LeesString(P);
    [etc]

Verwijderd

Op donderdag 11 april 2002 18:16 schreef Cheater het volgende:
Even serius...

MOET dat?
die laatste INC?

Want er komt toch niets meer erna?
Begrijp je het principe van een for lus? Antwoord is dus, ja die laatste Inc moet want die lus kan meerdere keren uitgevoerd worden.

  • Cheater
  • Registratie: Januari 2001
  • Laatst online: 23:34
Ik ben erachter gekomen dat hij dit stukje niet uitvoert bij Datarecieved van de UDP :

if (M = 'D') then
begin
Label4.Caption := IntToStr(ActiveClientCount);
Label47.Caption := 'PlayerName';
end;

M is dus NIET 'D' (ook geen 'd' dat heb ik getest') maar in de manual (zie een paar post hierboven) staat dat ik 'D' toegestuurd zou moeten krijgen.

[BOVENSTAANDE SOURCE CODE EDITED !!!]
Updates:
PChar --> string
If Else constructie aangepast bij Datarecieved

Verwijderd

Ik heb ff snel een test progje geschreven en ik krijg dit terug:
code:
1
  255, 255, 255, 255, 68, 0

Dus een -1, een 'D' en een '0' [=active client count]

Klopt toch, of niet?

  • Cheater
  • Registratie: Januari 2001
  • Laatst online: 23:34
ja maar door middel van breakpoints komt hij niet bij de IF ELSE constructie van
code:
1
2
3
4
5
    if (M = 'D') or (M = 'd') then
    begin
    Label4.Caption := IntToStr(ActiveClientCount);
    Label47.Caption := 'PlayerName';
    end;

Verwijderd

Maar wat staat er dan in M? En wat zet hij in de andere variabelen van TDetails?

Dus zet een breakpoint op de eerste regel van de functie DecodeStream; Run het programma, wacht tot hij op die break-point stopt; loop er dan doorheen door op F8 te drukken. Kijk naar de variabele door met [CTRL] + [linkermuis] op een variabele in de programma-tekst te drukken, etc.

Zet eventueel Optimization uit via 'Project|Options|Compiler| Code generation|Optimization' zodat je beter naar de variabelen kunt kijken.

  • Cheater
  • Registratie: Januari 2001
  • Laatst online: 23:34
Als ik de for-loop weghaal, (dus dat hij de code uitvoert die hij over alle spelers zou moeten uitvoeren, maar 1 keer uitvoert) dan geeft hij geen foutmelding. Ik denk dat het bestand die met een UDP component is gekoppeld een oneindige bewerking uitvoert (dat heb ik bekeken, hij voert iets gewoon oneindig aantal keer uit, en ineens loopt hij in de fout.


Zonder de fout drukt hij wel iets af, en dan bekijk ik de ActiveClientCount. En die is dan:
ActiveClientCount = 68

Hoe komt dit?

edit:

Ik denk omdat ik nog op het versienummer stond of iets dergelijks. Als ik daar overheen stap krijg ik 13. Maar er zitten in het echt, GEEN spelers op.

Wat vergeet ik allemaal? Als je het protocol bekijkt. En kijk naar wat ik terugkrijg, als ik players stuur.

Hieronder de code zoals ik em nu heb:
[code]function DecodeStream(P: Pointer): TDetails;
var
i: integer;
NullPos: Integer;
begin
with Result do
begin
// pointer wijst naar Version
Version := Cardinal(P^);
Inc(Cardinal(P), SizeOf(Version)); // pointer voorbij Version verschuiven

// pointer wijst nu naar M
M := Char(P^);
if (M = 'm') then
begin
end;
end else if (M = 'D') then
begin
Inc(Cardinal(P), SizeOf(Version));

ActiveClientCount := Byte(P^);
Inc(Cardinal(P), SizeOf(ActiveClientCount));

{ for i := 0 to ActiveClientCount - 1 do
begin }
Clientnumber := Byte(P^);
Inc(Cardinal(P), SizeOf(ClientNumber));

PlayerName := PChar(P);
NullPos := Length(PChar(P)) +1;
Inc(Cardinal(P), NullPos);

FragsCount := Longint(P^);
Inc(Cardinal(P), SizeOf(FragsCount));

TotalTime := Single(P^);
Inc(Cardinal(P), SizeOf(TotalTime));
{ end; }
end;
end;
end;[/code]
Pagina: 1