minestat 0.3.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/minestat.rb +56 -37
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9c241df5d1adebf63bf3fa8ff85a4066cf788b64ac160afddf99906f6d0ea1a3
|
4
|
+
data.tar.gz: c257c9b9640bb4bf961bdc80dfbebbcad829cfe5a56f90951bc724859ab389c7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: afb6c96adcac8c9bcea0bb88e1466ef9354d116345707c1f9fa901322996d412c8244a59c5facd724909d7f16375f5c3dcc098f40aef484ca8a9d18dff4936c4
|
7
|
+
data.tar.gz: c08c4a7f1099ed57094bedf7c4f3eed374eff7fa824be55a1962b3fa3831f6f2f088284ee0b58acc09c7285b33fea8892ed8abfbe5b757264876497c3ff637d0
|
data/lib/minestat.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
# minestat.rb - A Minecraft server status checker
|
2
|
-
# Copyright (C) 2014 Lloyd Dilley
|
2
|
+
# Copyright (C) 2014-2021 Lloyd Dilley
|
3
3
|
# http://www.dilley.me/
|
4
4
|
#
|
5
5
|
# This program is free software; you can redistribute it and/or modify
|
@@ -21,6 +21,7 @@ require 'socket'
|
|
21
21
|
require 'timeout'
|
22
22
|
|
23
23
|
class MineStat
|
24
|
+
VERSION = "2.0.0" # MineStat version
|
24
25
|
NUM_FIELDS = 6 # number of values expected from server
|
25
26
|
NUM_FIELDS_BETA = 3 # number of values expected from a 1.8b/1.3 server
|
26
27
|
MAX_VARINT_SIZE = 5 # maximum number of bytes a varint can be
|
@@ -34,7 +35,15 @@ class MineStat
|
|
34
35
|
UNKNOWN = -3
|
35
36
|
end
|
36
37
|
|
37
|
-
|
38
|
+
module Request
|
39
|
+
NONE = -1
|
40
|
+
BETA = 0
|
41
|
+
LEGACY = 1
|
42
|
+
EXTENDED = 2
|
43
|
+
JSON = 3
|
44
|
+
end
|
45
|
+
|
46
|
+
def initialize(address, port = DEFAULT_PORT, timeout = DEFAULT_TIMEOUT, request_type = Request::NONE)
|
38
47
|
@address = address # address of server
|
39
48
|
@port = port # TCP port of server
|
40
49
|
@online # online or offline?
|
@@ -47,29 +56,39 @@ class MineStat
|
|
47
56
|
@latency # ping time to server in milliseconds
|
48
57
|
@timeout = timeout # TCP timeout
|
49
58
|
@server # server socket
|
50
|
-
@
|
59
|
+
@request_type # SLP protocol version
|
51
60
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
61
|
+
case request_type
|
62
|
+
when Request::BETA
|
63
|
+
retval = beta_request()
|
64
|
+
when Request::LEGACY
|
65
|
+
retval = legacy_request()
|
66
|
+
when Request::EXTENDED
|
67
|
+
retval = extended_legacy_request()
|
68
|
+
when Request::JSON
|
69
|
+
retval = json_request()
|
70
|
+
else
|
71
|
+
# Attempt various SLP ping requests in a particular order. If the request
|
72
|
+
# succeeds or the connection fails, there is no reason to continue with
|
73
|
+
# subsequent requests. Attempts should continue in the event of a timeout
|
74
|
+
# however since it may be due to an issue during the handshake.
|
75
|
+
# Note: Newer server versions may still respond to older SLP requests.
|
76
|
+
# For example, 1.13.2 responds to 1.4/1.5 queries, but not 1.6 queries.
|
77
|
+
# SLP 1.4/1.5
|
78
|
+
retval = legacy_request()
|
79
|
+
# SLP 1.8b/1.3
|
80
|
+
unless retval == Retval::SUCCESS || retval == Retval::CONNFAIL
|
81
|
+
retval = beta_request()
|
82
|
+
end
|
83
|
+
# SLP 1.6
|
84
|
+
unless retval == Retval::SUCCESS || retval == Retval::CONNFAIL
|
85
|
+
retval = extended_legacy_request()
|
86
|
+
end
|
87
|
+
# SLP 1.7
|
88
|
+
unless retval == Retval::SUCCESS || retval == Retval::CONNFAIL
|
89
|
+
retval = json_request()
|
90
|
+
end
|
71
91
|
end
|
72
|
-
|
73
92
|
@online = false unless retval == Retval::SUCCESS
|
74
93
|
end
|
75
94
|
|
@@ -112,7 +131,7 @@ class MineStat
|
|
112
131
|
server_info = data.split(delimiter)
|
113
132
|
if is_beta
|
114
133
|
if server_info != nil && server_info.length >= NUM_FIELDS_BETA
|
115
|
-
@version = "1.8b/1.3" # since server does not return version, set it
|
134
|
+
@version = ">=1.8b/1.3" # since server does not return version, set it
|
116
135
|
@motd = server_info[0]
|
117
136
|
@current_players = server_info[1].to_i
|
118
137
|
@max_players = server_info[2].to_i
|
@@ -137,21 +156,21 @@ class MineStat
|
|
137
156
|
end
|
138
157
|
|
139
158
|
# 1.8b/1.3
|
140
|
-
# 1.8 beta through 1.3 servers communicate as follows for a ping
|
159
|
+
# 1.8 beta through 1.3 servers communicate as follows for a ping request:
|
141
160
|
# 1. Client sends \xFE (server list ping)
|
142
161
|
# 2. Server responds with:
|
143
162
|
# 2a. \xFF (kick packet)
|
144
163
|
# 2b. data length
|
145
164
|
# 2c. 3 fields delimited by \u00A7 (section symbol)
|
146
165
|
# The 3 fields, in order, are: message of the day, current players, and max players
|
147
|
-
def
|
166
|
+
def beta_request()
|
148
167
|
retval = nil
|
149
168
|
begin
|
150
169
|
Timeout::timeout(@timeout) do
|
151
170
|
retval = connect()
|
152
171
|
return retval unless retval == Retval::SUCCESS
|
153
172
|
# Perform handshake and acquire data
|
154
|
-
@
|
173
|
+
@request_type = "SLP 1.8b/1.3 (beta)"
|
155
174
|
@server.write("\xFE")
|
156
175
|
retval = parse_data("\u00A7", true) # section symbol
|
157
176
|
end
|
@@ -165,7 +184,7 @@ class MineStat
|
|
165
184
|
end
|
166
185
|
|
167
186
|
# 1.4/1.5
|
168
|
-
# 1.4 and 1.5 servers communicate as follows for a ping
|
187
|
+
# 1.4 and 1.5 servers communicate as follows for a ping request:
|
169
188
|
# 1. Client sends:
|
170
189
|
# 1a. \xFE (server list ping)
|
171
190
|
# 1b. \x01 (server list ping payload)
|
@@ -177,14 +196,14 @@ class MineStat
|
|
177
196
|
# server version, message of the day, current players, and max players
|
178
197
|
# The protocol version corresponds with the server version and can be the
|
179
198
|
# same for different server versions.
|
180
|
-
def
|
199
|
+
def legacy_request()
|
181
200
|
retval = nil
|
182
201
|
begin
|
183
202
|
Timeout::timeout(@timeout) do
|
184
203
|
retval = connect()
|
185
204
|
return retval unless retval == Retval::SUCCESS
|
186
205
|
# Perform handshake and acquire data
|
187
|
-
@
|
206
|
+
@request_type = "SLP 1.4/1.5 (legacy)"
|
188
207
|
@server.write("\xFE\x01")
|
189
208
|
retval = parse_data("\x00") # null
|
190
209
|
end
|
@@ -198,7 +217,7 @@ class MineStat
|
|
198
217
|
end
|
199
218
|
|
200
219
|
# 1.6
|
201
|
-
# 1.6 servers communicate as follows for a ping
|
220
|
+
# 1.6 servers communicate as follows for a ping request:
|
202
221
|
# 1. Client sends:
|
203
222
|
# 1a. \xFE (server list ping)
|
204
223
|
# 1b. \x01 (server list ping payload)
|
@@ -218,14 +237,14 @@ class MineStat
|
|
218
237
|
# server version, message of the day, current players, and max players
|
219
238
|
# The protocol version corresponds with the server version and can be the
|
220
239
|
# same for different server versions.
|
221
|
-
def
|
240
|
+
def extended_legacy_request()
|
222
241
|
retval = nil
|
223
242
|
begin
|
224
243
|
Timeout::timeout(@timeout) do
|
225
244
|
retval = connect()
|
226
245
|
return retval unless retval == Retval::SUCCESS
|
227
246
|
# Perform handshake and acquire data
|
228
|
-
@
|
247
|
+
@request_type = "SLP 1.6 (extended legacy)"
|
229
248
|
@server.write("\xFE\x01\xFA")
|
230
249
|
@server.write("\x00\x0B") # 11 (length of "MC|PingHost")
|
231
250
|
@server.write('MC|PingHost'.encode('UTF-16BE').force_encoding('ASCII-8BIT'))
|
@@ -246,7 +265,7 @@ class MineStat
|
|
246
265
|
end
|
247
266
|
|
248
267
|
# 1.7
|
249
|
-
# 1.7 to current servers communicate as follows for a ping
|
268
|
+
# 1.7 to current servers communicate as follows for a ping request:
|
250
269
|
# 1. Client sends:
|
251
270
|
# 1a. \x00 (handshake packet containing the fields specified below)
|
252
271
|
# 1b. \x00 (request)
|
@@ -261,14 +280,14 @@ class MineStat
|
|
261
280
|
# {'players': {'max': 20, 'online': 0},
|
262
281
|
# 'version': {'protocol': 404, 'name': '1.13.2'},
|
263
282
|
# 'description': {'text': 'A Minecraft Server'}}
|
264
|
-
def
|
283
|
+
def json_request()
|
265
284
|
retval = nil
|
266
285
|
begin
|
267
286
|
Timeout::timeout(@timeout) do
|
268
287
|
retval = connect()
|
269
288
|
return retval unless retval == Retval::SUCCESS
|
270
289
|
# Perform handshake
|
271
|
-
@
|
290
|
+
@request_type = "SLP 1.7 (JSON)"
|
272
291
|
payload = "\x00\x00"
|
273
292
|
payload += [@address.length].pack('c') << @address
|
274
293
|
payload += [@port].pack('n')
|
@@ -342,5 +361,5 @@ class MineStat
|
|
342
361
|
return vint
|
343
362
|
end
|
344
363
|
|
345
|
-
attr_reader :address, :port, :online, :version, :motd, :current_players, :max_players, :protocol, :json_data, :latency, :
|
364
|
+
attr_reader :address, :port, :online, :version, :motd, :current_players, :max_players, :protocol, :json_data, :latency, :request_type
|
346
365
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: minestat
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Lloyd Dilley
|
@@ -9,10 +9,10 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2021-03-03 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
14
|
description: MineStat polls Minecraft server data such as version, motd, current players,
|
15
|
-
and max players
|
15
|
+
and max players.
|
16
16
|
email:
|
17
17
|
- minecraft@frag.land
|
18
18
|
executables: []
|