Get player count JSON
41 replies If you're stuck with pure CS2D Lua (not LuaJIT) then your only option is to use
reqhttp requesting to UnrealSoftware server as
Avo said.
However, if you have atleast JIT and LuaSocket, then you can create your own UDP socket then parse the response as shown in https://github.com/Austinb/GameQ/blob/v3/src/GameQ/Protocols/Cs2d.php#L189
1. Send "\x01\x00\xFB\x01" to the server
2. Server will send you back "\x01\x00\xFB\x01" followed by any data that's according to the link above.


However, if you have atleast JIT and LuaSocket, then you can create your own UDP socket then parse the response as shown in https://github.com/Austinb/GameQ/blob/v3/src/GameQ/Protocols/Cs2d.php#L189
1. Send "\x01\x00\xFB\x01" to the server
2. Server will send you back "\x01\x00\xFB\x01" followed by any data that's according to the link above.


So can I use your LuaJIT dedicated server? And how would I get that socket thing?
Is death truly a bad thing? If it is, then why do we all get to experience it? And... Why does it take so long? - What is the meaning of death?
If you can handle the consequence like slight script difference and stability (although from my testing server running with it for 1 week, it's stable). Then to use socket:
Avo has written:
Mami Tomoe has written:
You might want to see
[Lua 5.1] LuaSocket 3.0 x86 Windows/Linux/MacOS (6).


Okay and how do I download a file with Lua?
socket.http
doesn't seem to exist.You might want to see


edited 1×, last 07.05.20 01:22:14 pm


So I need LuaJIT to use that socket thing?
Is death truly a bad thing? If it is, then why do we all get to experience it? And... Why does it take so long? - What is the meaning of death?
@
Mami Tomoe: You are doing something that you don't know how to complete it successfully, Just copying and pasting them. You won't be success if you keep going this way my man. Ask everything about it that you don't know, Search on Google, Then you'll finally understand how actually it does work, Afterall you can make it on your own


This is my learning process.
Is death truly a bad thing? If it is, then why do we all get to experience it? And... Why does it take so long? - What is the meaning of death?

The recommended approach would be to get the server details directly from the server via UDP.
@

Or one would need to figure it out with wireshark, tcpdump, etc?
---

Oh, I was not aware of existence of reqhttp function! That's the way to go if you want to ask /serverinfo.php for data in the most simple manner (not the fastest tho).
Trust me, I'm an engineer |
DC approved
Super extra mod for CS2D (64), yeah!



Okay well I just need simple instructions on how to use Lua to get info from another server.
Such as:
Get LuaJIT
Install socket thingy
Use req hook to do x things
etc
Such as:
Get LuaJIT
Install socket thingy
Use req hook to do x things
etc
Is death truly a bad thing? If it is, then why do we all get to experience it? And... Why does it take so long? - What is the meaning of death?
Why are you still asking for LuaJIT, LuaSocket while there is
dgram
in nodeJS, You can use nodeJS itself to request data, You don't need to install anything if you use my way. LuaSocket does the same thing as mine even if I compare them mine is simpler. It requests data from the server to the client directly. If you want to use it, Just run the code I've posted yesterday then you're done that's all you have to do. Well, how do I use nodeJS?
Is death truly a bad thing? If it is, then why do we all get to experience it? And... Why does it take so long? - What is the meaning of death?

Why are you still asking for LuaJIT, LuaSocket while there is
dgram
in nodeJS, You can use nodeJS itself to request data, You don't need to install anything if you use my way. LuaSocket does the same thing as mine even if I compare them mine is simpler. It requests data from the server to the client directly. If you want to use it, Just run the code I've posted yesterday then you're done that's all you have to do.@


@
Mami Tomoe Are you using pure lua or CS2D


CS2D Lua, I want to have a server specifically for doing file downloading and stuff
If you want a simple approach, you can use something like this
Code:
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
local reqID
addhook("httpdata", "httpdata")
function httpadata(requestID, state, data)
if requestID == reqID and state == 1 then
-- Now "data" has the HTTP data as Avo said before, see below.
-- Do your processing to the data here to retrieve what you need.
end
end
-- Somewhere
reqID = reqhttp("unrealsoftware.de", "/inc_pub/serverinfo.php?i="..server_ip.."&p="..server_port.."&g=0")
addhook("httpdata", "httpdata")
function httpadata(requestID, state, data)
if requestID == reqID and state == 1 then
-- Now "data" has the HTTP data as Avo said before, see below.
-- Do your processing to the data here to retrieve what you need.
end
end
-- Somewhere
reqID = reqhttp("unrealsoftware.de", "/inc_pub/serverinfo.php?i="..server_ip.."&p="..server_port.."&g=0")

I made a little investigation of http://www.unrealsoftware.de/usgn.php?s=cs2d and find out that you can make a GET call to
For example:
returned
It's not JSON, but I guess you can use parse it and make use of that. It's simple HTML with table tags.
Parameters of a call:
Code:
www.unrealsoftware.de/inc_pub/serverinfo.php
For example:
Code:
http://www.unrealsoftware.de/inc_pub/serverinfo.php?i=85.25.143.56&p=36955&g=0&123
returned
Code:
(visible content only, HTML tags omitted)Name: [Q][GamersCentral.de][Public]
Map: de_dust2
Players: 2 / 32 (Bots: 0)
Password: None
U.S.G.N. only: Off
Fog of War: On
Friendly Fire: Off
Lua: Uses Lua Scripts!
Game Mode: Standard
Map: de_dust2
Players: 2 / 32 (Bots: 0)
Password: None
U.S.G.N. only: Off
Fog of War: On
Friendly Fire: Off
Lua: Uses Lua Scripts!
Game Mode: Standard
It's not JSON, but I guess you can use parse it and make use of that. It's simple HTML with table tags.
Parameters of a call:
Code:
http://www.unrealsoftware.de/inc_pub/serverinfo.php?i=<IP>&p=<PORT>&g=<GAME ID, 0 for CS2D>&<SOME RANDOM NUMBER>
Edit: For anyone stumble upon this solution, this no longer works under CS2D as UnrealSoftware sites now enforces HSTS!
edited 1×, last 27.06.20 01:46:23 pm


MikuAuahDark has written:
Edit: it seems that random number is optional.
That random number is not optional, it's used to prevent the GET request from being cached.
What is the right way to use the cached number then?
Is death truly a bad thing? If it is, then why do we all get to experience it? And... Why does it take so long? - What is the meaning of death?
@
Gaios: Is using the same one every time bad?

Is death truly a bad thing? If it is, then why do we all get to experience it? And... Why does it take so long? - What is the meaning of death?
Using the same number every time is equal to not using it at all. It won't prevent caching.
The best value would be a unix timestamp of the current time.
(not sure why I used a random number when I implemented that stuff years ago. It's an "ok" approach but of course there's still a chance that you get the same number twice, rendering the anti caching mechanism usless)
The best value would be a unix timestamp of the current time.
(not sure why I used a random number when I implemented that stuff years ago. It's an "ok" approach but of course there's still a chance that you get the same number twice, rendering the anti caching mechanism usless)
edited 1×, last 08.05.20 05:30:42 pm
Does the number have a limit? Like is it int, long, or what?
Is death truly a bad thing? If it is, then why do we all get to experience it? And... Why does it take so long? - What is the meaning of death?
No it does not have any limit. In fact it's entirely ignored by the script which is called. Its only purpose is to alter the URL to prevent browsers from caching the call.
It's probably not even an entirely valid request string syntax (not sure, didn't check the URI RFCs). Normally you would have to put a variable name at that point. The script doesn't care though because the value is not relevant.
So instead of appending
Btw: I would appreciate if you could just host the PHP stuff on your own server. That would perform better anyway (for you). Of course the requirement would be to run a webserver with PHP.
This is the code I'm using.
Pasted together and stripped some things like a caching mechanism. I hope it works anyway.
Please don't judge me. This is some ooold shit.
It's probably not even an entirely valid request string syntax (not sure, didn't check the URI RFCs). Normally you would have to put a variable name at that point. The script doesn't care though because the value is not relevant.
So instead of appending
&123
you could also append something like &t=12345678912345679
. Makes no difference.Btw: I would appreciate if you could just host the PHP stuff on your own server. That would perform better anyway (for you). Of course the requirement would be to run a webserver with PHP.
This is the code I'm using.
Pasted together and stripped some things like a caching mechanism. I hope it works anyway.
Please don't judge me. This is some ooold shit.
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
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
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
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
<?php
/*
Quick & dirty library to read/extract BlitzMax compatible data types from raw input data (files/UDP).
Globals:
- $d: holds the data to read (d for Data)
- $dOS: read offset in bytes (dOS for Data OffSet)
- the normal functions manipulate $d (which is slow), they do not use $dOS
- the fast functions use $dOS to keep track of the read offset, they do not manipulate $d (faster)
*/
function readLine(){
global $d;
$line='';
do {
$char=ord(substr($d,0,1));
$line.=chr($char);
$d=substr($d,1);
} while ($char!=13);
$d=substr($d,1);
return substr($line,0,strlen($line)-1);
}
function readString(){
global $d;
$length=ord(substr($d,0,1));
$string=substr($d,1,$length);
$d=substr($d,$length+1);
return $string;
}
function readByte(){
global $d;
$byte=ord(substr($d,0,1));
$d=substr($d,1);
return $byte;
}
function readShort(){
global $d;
$short=substr($d,0,2);
$d=substr($d,2);
$r=unpack('S',$short);
return $r[1];
}
function readInt(){
global $d;
$int=substr($d,0,4);
$d=substr($d,4);
$r=unpack('l',$int);
return $r[1];
}
function readFloat(){
global $d;
$float=ord(substr($d,0,4));
$d=substr($d,4);
$r=unpack('f',$float);
return $r[1];
}
// Fast versions using an offset ($dOS) instead of manipulating $d
function readLineFast(){
global $d;
global $dOS;
$line='';
do {
$char=ord(substr($d,$dOS,1));
$line.=chr($char);
$dOS++;
} while ($char!=13);
$dOS++;
return substr($line,0,strlen($line)-1);
}
function readStringFast(){
global $d;
global $dOS;
$length=ord(substr($d,$dOS,1));
$string=substr($d,$dOS+1,$length);
$dOS+=($length+1);
return $string;
}
function readByteFast(){
global $d;
global $dOS;
$byte=ord(substr($d,$dOS,1));
$dOS++;
return $byte;
}
function readShortFast(){
global $d;
global $dOS;
$short=substr($d,$dOS,2);
$dOS+=2;
$r=unpack('S',$short);
return $r[1];
}
function readIntFast(){
global $d;
global $dOS;
$int=substr($d,$dOS,4);
$dOS+=4;
$r=unpack('l',$int);
return $r[1];
}
function readFloatFast(){
global $d;
global $dOS;
$float=ord(substr($d,$dOS,4));
$dOS+=4;
$r=unpack('f',$float);
return $r[1];
}
function utf8_htmlentities($t,$q=ENT_COMPAT,$char='UTF-8',$denc=TRUE){
return htmlentities($t,$q,$char,$denc);
}
// Send request with specified payload data
function sendRequest($data){
global $fp;
global $d;
// Use cached data
if (isset($d)) {
return;
}
// Send Request
fwrite($fp, $data);
// Set Timeout
stream_set_timeout($fp, 5);
// Read Data (try to read up to 256 bytes)
$d = fread($fp, 256);
// Meta data implies timeout
$md = stream_get_meta_data($fp);
if ($md['timed_out'] == 1){
die('timeout');
}
// Empty package implies timeout
if (ord(substr($d, 0, 1)) == 0){
die('timeout');
}
}
//-------------------------------------------------------------------------
// Validate IP
if (!filter_var($_GET['i'], FILTER_VALIDATE_IP)) {
die('bad IP (format)');
}
if (strpos($_GET['i'], '127') === 0) {
die('bad IP (local)');
}
$_GET['p'] = (int)$_GET['p'];
if ($_GET['p'] < 1 || $_GET['p'] > 65535) {
die('bad port');
}
// Connect (with 5 secs timeout)
if (!isset($d)) {
$fp = @fsockopen('udp://'.$_GET['i'], $_GET['p'], $errno, $errstr, 5);
}
if (isset($d) || $fp) {
switch ((int)$_GET['g']){
// Game 0 - CS2D
case 0:
sendRequest(chr(1).chr(0).chr(251).chr(1)); //Send Request
// Read UDP packet header
$b0=readByte();
$b1=readByte();
$b2=readByte();
$b3=readByte();
if ($b0==0) {
echo('timeout');
break;
}
// Check if header is valid
if ($b0==1 && $b1==0 && $b2=251 && $b3==1){
//Get Data
$mode=readByte(); //Mode Bit Flags
$name=readString(); //Server Name
$map=readString(); //Map
$players=min(readByte(),32); //Players
$players_max=min(readByte(),32); //Players Max
if ($mode & 32){ $gmi=readByte(); }else{ $gmi=0; } //Game Mode
$bots=readByte();
// Print General Data
echo '<table>';
echo '<tr><td>Name:</td><td>',utf8_htmlentities($name),'</td></tr>';
echo '<tr><td>Map:</td><td>',utf8_htmlentities($map),'</td></tr>';
echo '<tr><td>Players:</td><td>',$players,' / ',$players_max,' (Bots: ',$bots,')</td></tr>';
// Print Mode Flag Stuff
if ($mode & 1){ $t='Password protected!'; }else{ $t='None'; } echo '<tr><td>Password:</td><td>',$t,'</td></tr>';
if ($mode & 2){ $t='On'; }else{ $t='Off'; } echo '<tr><td>U.S.G.N. only:</td><td>',$t,'</td></tr>';
if ($mode & 4){ $t='On'; }else{ $t='Off'; } echo '<tr><td>Fog of War:</td><td>',$t,'</td></tr>';
if ($mode & 8){ $t='On'; }else{ $t='Off'; } echo '<tr><td>Friendly Fire:</td><td>',$t,'</td></tr>';
if ($mode & 64){ $t='Uses Lua Scripts!'; }else{ $t='None'; } echo '<tr><td>Lua:</td><td>',$t,'</td></tr>';
// Print Game Mode
switch ($gmi){
case 0: $gm='Standard'; break;
case 1: $gm='Deathmatch'; break;
case 2: $gm='Team Deathmatch'; break;
case 3: $gm='Construction'; break;
case 4: $gm='Zombies'; break;
default: $gm='Unknown ('.$gmi.')';
}
echo '<tr><td>Game Mode:</td><td>',$gm,'</td></tr>';
echo '</table>';
}else{
echo 'unexpected server reply (',$b0,',',$b1,',',$b2,',',$b3,') - expected (1,0,251,1)';
}
break;
// Game 1 - Carnage Contest
case 1:
// NOT RELEVANT 4 U BOY!
break;
// Unknown
default:
echo 'unknown request';
}
// Close socket
if (isset($fp)) {
fclose($fp);
} else {
echo '<br /><span style="font-size:9px; color:#AAA">(cached values, new every 10 sec)</span>';
}
}else{
echo 'failed to open socket to server! please try again later!';
}
/*
Quick & dirty library to read/extract BlitzMax compatible data types from raw input data (files/UDP).
Globals:
- $d: holds the data to read (d for Data)
- $dOS: read offset in bytes (dOS for Data OffSet)
- the normal functions manipulate $d (which is slow), they do not use $dOS
- the fast functions use $dOS to keep track of the read offset, they do not manipulate $d (faster)
*/
function readLine(){
global $d;
$line='';
do {
$char=ord(substr($d,0,1));
$line.=chr($char);
$d=substr($d,1);
} while ($char!=13);
$d=substr($d,1);
return substr($line,0,strlen($line)-1);
}
function readString(){
global $d;
$length=ord(substr($d,0,1));
$string=substr($d,1,$length);
$d=substr($d,$length+1);
return $string;
}
function readByte(){
global $d;
$byte=ord(substr($d,0,1));
$d=substr($d,1);
return $byte;
}
function readShort(){
global $d;
$short=substr($d,0,2);
$d=substr($d,2);
$r=unpack('S',$short);
return $r[1];
}
function readInt(){
global $d;
$int=substr($d,0,4);
$d=substr($d,4);
$r=unpack('l',$int);
return $r[1];
}
function readFloat(){
global $d;
$float=ord(substr($d,0,4));
$d=substr($d,4);
$r=unpack('f',$float);
return $r[1];
}
// Fast versions using an offset ($dOS) instead of manipulating $d
function readLineFast(){
global $d;
global $dOS;
$line='';
do {
$char=ord(substr($d,$dOS,1));
$line.=chr($char);
$dOS++;
} while ($char!=13);
$dOS++;
return substr($line,0,strlen($line)-1);
}
function readStringFast(){
global $d;
global $dOS;
$length=ord(substr($d,$dOS,1));
$string=substr($d,$dOS+1,$length);
$dOS+=($length+1);
return $string;
}
function readByteFast(){
global $d;
global $dOS;
$byte=ord(substr($d,$dOS,1));
$dOS++;
return $byte;
}
function readShortFast(){
global $d;
global $dOS;
$short=substr($d,$dOS,2);
$dOS+=2;
$r=unpack('S',$short);
return $r[1];
}
function readIntFast(){
global $d;
global $dOS;
$int=substr($d,$dOS,4);
$dOS+=4;
$r=unpack('l',$int);
return $r[1];
}
function readFloatFast(){
global $d;
global $dOS;
$float=ord(substr($d,$dOS,4));
$dOS+=4;
$r=unpack('f',$float);
return $r[1];
}
function utf8_htmlentities($t,$q=ENT_COMPAT,$char='UTF-8',$denc=TRUE){
return htmlentities($t,$q,$char,$denc);
}
// Send request with specified payload data
function sendRequest($data){
global $fp;
global $d;
// Use cached data
if (isset($d)) {
return;
}
// Send Request
fwrite($fp, $data);
// Set Timeout
stream_set_timeout($fp, 5);
// Read Data (try to read up to 256 bytes)
$d = fread($fp, 256);
// Meta data implies timeout
$md = stream_get_meta_data($fp);
if ($md['timed_out'] == 1){
die('timeout');
}
// Empty package implies timeout
if (ord(substr($d, 0, 1)) == 0){
die('timeout');
}
}
//-------------------------------------------------------------------------
// Validate IP
if (!filter_var($_GET['i'], FILTER_VALIDATE_IP)) {
die('bad IP (format)');
}
if (strpos($_GET['i'], '127') === 0) {
die('bad IP (local)');
}
$_GET['p'] = (int)$_GET['p'];
if ($_GET['p'] < 1 || $_GET['p'] > 65535) {
die('bad port');
}
// Connect (with 5 secs timeout)
if (!isset($d)) {
$fp = @fsockopen('udp://'.$_GET['i'], $_GET['p'], $errno, $errstr, 5);
}
if (isset($d) || $fp) {
switch ((int)$_GET['g']){
// Game 0 - CS2D
case 0:
sendRequest(chr(1).chr(0).chr(251).chr(1)); //Send Request
// Read UDP packet header
$b0=readByte();
$b1=readByte();
$b2=readByte();
$b3=readByte();
if ($b0==0) {
echo('timeout');
break;
}
// Check if header is valid
if ($b0==1 && $b1==0 && $b2=251 && $b3==1){
//Get Data
$mode=readByte(); //Mode Bit Flags
$name=readString(); //Server Name
$map=readString(); //Map
$players=min(readByte(),32); //Players
$players_max=min(readByte(),32); //Players Max
if ($mode & 32){ $gmi=readByte(); }else{ $gmi=0; } //Game Mode
$bots=readByte();
// Print General Data
echo '<table>';
echo '<tr><td>Name:</td><td>',utf8_htmlentities($name),'</td></tr>';
echo '<tr><td>Map:</td><td>',utf8_htmlentities($map),'</td></tr>';
echo '<tr><td>Players:</td><td>',$players,' / ',$players_max,' (Bots: ',$bots,')</td></tr>';
// Print Mode Flag Stuff
if ($mode & 1){ $t='Password protected!'; }else{ $t='None'; } echo '<tr><td>Password:</td><td>',$t,'</td></tr>';
if ($mode & 2){ $t='On'; }else{ $t='Off'; } echo '<tr><td>U.S.G.N. only:</td><td>',$t,'</td></tr>';
if ($mode & 4){ $t='On'; }else{ $t='Off'; } echo '<tr><td>Fog of War:</td><td>',$t,'</td></tr>';
if ($mode & 8){ $t='On'; }else{ $t='Off'; } echo '<tr><td>Friendly Fire:</td><td>',$t,'</td></tr>';
if ($mode & 64){ $t='Uses Lua Scripts!'; }else{ $t='None'; } echo '<tr><td>Lua:</td><td>',$t,'</td></tr>';
// Print Game Mode
switch ($gmi){
case 0: $gm='Standard'; break;
case 1: $gm='Deathmatch'; break;
case 2: $gm='Team Deathmatch'; break;
case 3: $gm='Construction'; break;
case 4: $gm='Zombies'; break;
default: $gm='Unknown ('.$gmi.')';
}
echo '<tr><td>Game Mode:</td><td>',$gm,'</td></tr>';
echo '</table>';
}else{
echo 'unexpected server reply (',$b0,',',$b1,',',$b2,',',$b3,') - expected (1,0,251,1)';
}
break;
// Game 1 - Carnage Contest
case 1:
// NOT RELEVANT 4 U BOY!
break;
// Unknown
default:
echo 'unknown request';
}
// Close socket
if (isset($fp)) {
fclose($fp);
} else {
echo '<br /><span style="font-size:9px; color:#AAA">(cached values, new every 10 sec)</span>';
}
}else{
echo 'failed to open socket to server! please try again later!';
}
edited 3×, last 08.05.20 05:48:49 pm
I'd love to just connect directly to the server but I don't know anything web related, all the programming I do is non-web stuff sadly...
Is death truly a bad thing? If it is, then why do we all get to experience it? And... Why does it take so long? - What is the meaning of death?
@
Mami Tomoe: try it, then. It's totally worth it to know how network-related stuff works in general. All of these things such as TCP, UDP, sockets, HTTP, REST etc.

Trust me, I'm an engineer |
DC approved
Super extra mod for CS2D (64), yeah!


