minestat 3.0.0 → 3.0.1
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/ChangeLog.md +6 -0
- data/ReadMe.md +9 -5
- data/example.rb +1 -1
- data/lib/minestat.rb +84 -54
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e8a29b7c1a834e40e6a63b451abc0cd67018ca48b8efcdcd04a6ca365390cec0
|
4
|
+
data.tar.gz: 609d3ed8ccfdff65d6c317b25066012eeafb7e206dd347923088fe4108588add
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5b27f9e97df7fc7f2f38d0d18ae1f4c14015845ca0590cc8a33d269642697d41001c130ba36b6c7e0c39a5e39020b28b64bc02b78333ecfd1c3047a430d43555
|
7
|
+
data.tar.gz: f7e487a9a821c8b2aa83b8120c55eeb08b7229797bf6f62aff18937c4875db238ad88e3b6be08e6948303b79f74494d5ae60725fb9917d58729535d57aa33175
|
data/ChangeLog.md
CHANGED
@@ -1,5 +1,11 @@
|
|
1
|
+
## 3.0.1 (February 5, 2023)
|
2
|
+
- Added configurable DNS SRV resolution
|
3
|
+
- Added request type that attempts all SLP protocols
|
4
|
+
- Improved debug messages
|
5
|
+
|
1
6
|
## 3.0.0 (January 31, 2023)
|
2
7
|
- Added UT3/GS4 query support
|
8
|
+
- Added debug mode
|
3
9
|
- Refactored code
|
4
10
|
- Added YARD documentation
|
5
11
|
|
data/ReadMe.md
CHANGED
@@ -18,7 +18,7 @@ To install the gem: `gem install minestat`
|
|
18
18
|
```ruby
|
19
19
|
require 'minestat'
|
20
20
|
|
21
|
-
ms = MineStat.new("
|
21
|
+
ms = MineStat.new("frag.land")
|
22
22
|
puts "Minecraft server status of #{ms.address} on port #{ms.port}:"
|
23
23
|
if ms.online
|
24
24
|
puts "Server is online running version #{ms.version} with #{ms.current_players} out of #{ms.max_players} players."
|
@@ -36,24 +36,28 @@ end
|
|
36
36
|
|
37
37
|
To simply connect to an address:
|
38
38
|
```ruby
|
39
|
-
ms = MineStat.new("
|
39
|
+
ms = MineStat.new("frag.land")
|
40
40
|
```
|
41
41
|
Connect to an address on a certain TCP or UDP port:
|
42
42
|
```ruby
|
43
|
-
ms = MineStat.new("
|
43
|
+
ms = MineStat.new("frag.land", 25565)
|
44
44
|
```
|
45
45
|
Same as above example and additionally includes a timeout in seconds:
|
46
46
|
```ruby
|
47
|
-
ms = MineStat.new("
|
47
|
+
ms = MineStat.new("frag.land", 25565, 3)
|
48
48
|
```
|
49
49
|
Same as above example and additionally includes an explicit protocol to use:
|
50
50
|
```ruby
|
51
|
-
ms = MineStat.new("
|
51
|
+
ms = MineStat.new("frag.land", 25565, 3, MineStat::Request::QUERY)
|
52
52
|
```
|
53
53
|
Connect to a Bedrock server and enable debug mode:
|
54
54
|
```ruby
|
55
55
|
ms = MineStat.new("minecraft.frag.land", 19132, 3, MineStat::Request::BEDROCK, true)
|
56
56
|
```
|
57
|
+
Attempt all SLP protocols, disable debug mode, and disable DNS SRV resolution:
|
58
|
+
```ruby
|
59
|
+
ms = MineStat.new("minecraft.frag.land", 25565, 3, MineStat::Request::SLP, false, false)
|
60
|
+
```
|
57
61
|
|
58
62
|
### Support
|
59
63
|
* Discord: https://discord.frag.land
|
data/example.rb
CHANGED
@@ -2,7 +2,7 @@ require 'minestat'
|
|
2
2
|
|
3
3
|
# Below is an example using the MineStat class.
|
4
4
|
# If server is offline, other instance members will be nil.
|
5
|
-
ms = MineStat.new("
|
5
|
+
ms = MineStat.new("frag.land")
|
6
6
|
# Bedrock/Pocket Edition explicit query example with debug enabled
|
7
7
|
#ms = MineStat.new("minecraft.frag.land", 19132, 5, MineStat::Request::BEDROCK, true)
|
8
8
|
puts "Minecraft server status of #{ms.address} on port #{ms.port}:"
|
data/lib/minestat.rb
CHANGED
@@ -27,7 +27,7 @@ require 'timeout'
|
|
27
27
|
# Provides a Ruby interface for polling the status of Minecraft servers
|
28
28
|
class MineStat
|
29
29
|
# MineStat version
|
30
|
-
VERSION = "3.0.
|
30
|
+
VERSION = "3.0.1"
|
31
31
|
|
32
32
|
# Number of values expected from server
|
33
33
|
NUM_FIELDS = 6
|
@@ -116,6 +116,10 @@ class MineStat
|
|
116
116
|
|
117
117
|
# Unreal Tournament 3/GameSpy 4 query
|
118
118
|
QUERY = 5
|
119
|
+
|
120
|
+
# SLP only
|
121
|
+
# @since 3.0.1
|
122
|
+
SLP = 6
|
119
123
|
end
|
120
124
|
|
121
125
|
# Instantiates a MineStat object and polls the specified server for information
|
@@ -126,59 +130,60 @@ class MineStat
|
|
126
130
|
# @param debug [Boolean] Enable or disable error output
|
127
131
|
# @return [MineStat] A MineStat object
|
128
132
|
# @example Simply connect to an address
|
129
|
-
# ms = MineStat.new("
|
133
|
+
# ms = MineStat.new("frag.land")
|
130
134
|
# @example Connect to an address on a certain TCP or UDP port
|
131
|
-
# ms = MineStat.new("
|
135
|
+
# ms = MineStat.new("frag.land", 25565)
|
132
136
|
# @example Same as above example and additionally includes a timeout in seconds
|
133
|
-
# ms = MineStat.new("
|
137
|
+
# ms = MineStat.new("frag.land", 25565, 3)
|
134
138
|
# @example Same as above example and additionally includes an explicit protocol to use
|
135
|
-
# ms = MineStat.new("
|
139
|
+
# ms = MineStat.new("frag.land", 25565, 3, MineStat::Request::QUERY)
|
136
140
|
# @example Connect to a Bedrock server and enable debug mode
|
137
141
|
# ms = MineStat.new("minecraft.frag.land", 19132, 3, MineStat::Request::BEDROCK, true)
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
@
|
142
|
-
@
|
143
|
-
@
|
144
|
-
@
|
145
|
-
@
|
146
|
-
@
|
147
|
-
@
|
148
|
-
@
|
149
|
-
@
|
150
|
-
@
|
151
|
-
@
|
152
|
-
@
|
153
|
-
@
|
154
|
-
@
|
155
|
-
@
|
156
|
-
@
|
157
|
-
@
|
158
|
-
@
|
159
|
-
@
|
160
|
-
@
|
142
|
+
# @example Attempt all SLP protocols, disable debug mode, and disable DNS SRV resolution
|
143
|
+
# ms = MineStat.new("minecraft.frag.land", 25565, 3, MineStat::Request::SLP, false, false)
|
144
|
+
def initialize(address, port = DEFAULT_TCP_PORT, timeout = DEFAULT_TIMEOUT, request_type = Request::NONE, debug = false, srv_enabled = true)
|
145
|
+
@address = address # address of server
|
146
|
+
@port = port # TCP/UDP port of server
|
147
|
+
@srv_address # server address from DNS SRV record
|
148
|
+
@srv_port # server TCP port from DNS SRV record
|
149
|
+
@online # online or offline?
|
150
|
+
@version # server version
|
151
|
+
@mode # game mode (Bedrock/Pocket Edition only)
|
152
|
+
@motd # message of the day
|
153
|
+
@stripped_motd # message of the day without formatting
|
154
|
+
@current_players # current number of players online
|
155
|
+
@max_players # maximum player capacity
|
156
|
+
@player_list # list of players (UT3/GS4 query only)
|
157
|
+
@plugin_list # list of plugins (UT3/GS4 query only)
|
158
|
+
@protocol # protocol level
|
159
|
+
@json_data # JSON data for 1.7 queries
|
160
|
+
@favicon_b64 # base64-encoded favicon possibly contained in JSON 1.7 responses
|
161
|
+
@favicon # decoded favicon data
|
162
|
+
@latency # ping time to server in milliseconds
|
163
|
+
@timeout = timeout # TCP/UDP timeout
|
164
|
+
@server # server socket
|
165
|
+
@request_type # protocol version
|
166
|
+
@connection_status # status of connection ("Success", "Fail", "Timeout", or "Unknown")
|
167
|
+
@try_all = false # try all protocols?
|
168
|
+
@debug = debug # debug mode
|
169
|
+
@srv_enabled = srv_enabled # enable SRV resolution?
|
161
170
|
|
162
171
|
@try_all = true if request_type == Request::NONE
|
163
|
-
resolve_srv(
|
172
|
+
resolve_srv() if @srv_enabled
|
164
173
|
set_connection_status(attempt_protocols(request_type))
|
165
174
|
end
|
166
175
|
|
167
|
-
# Attempts to resolve SRV records
|
168
|
-
# @param address [String] Minecraft server address
|
169
|
-
# @param port [Integer] Minecraft server TCP or UDP port
|
176
|
+
# Attempts to resolve DNS SRV records
|
170
177
|
# @return [Boolean] Whether or not SRV resolution was successful
|
171
178
|
# @since 2.3.0
|
172
|
-
def resolve_srv(
|
179
|
+
def resolve_srv()
|
173
180
|
begin
|
174
181
|
resolver = Resolv::DNS.new
|
175
182
|
res = resolver.getresource("_minecraft._tcp.#{@address}", Resolv::DNS::Resource::IN::SRV)
|
176
|
-
@
|
177
|
-
@
|
178
|
-
rescue => exception
|
179
|
-
$stderr.puts exception if @debug
|
180
|
-
@address = address
|
181
|
-
@port = port
|
183
|
+
@srv_address = res.target.to_s # SRV target
|
184
|
+
@srv_port = res.port.to_i # SRV port
|
185
|
+
rescue => exception # primarily catch Resolv::ResolvError and revert if unable to resolve SRV record(s)
|
186
|
+
$stderr.puts "resolve_srv(): #{exception}" if @debug
|
182
187
|
return false
|
183
188
|
end
|
184
189
|
return true
|
@@ -222,6 +227,7 @@ class MineStat
|
|
222
227
|
unless retval == Retval::CONNFAIL
|
223
228
|
retval = json_request()
|
224
229
|
end
|
230
|
+
return retval if request_type == Request::SLP
|
225
231
|
# Bedrock/Pocket Edition
|
226
232
|
unless @online || retval == Retval::SUCCESS
|
227
233
|
retval = bedrock_request()
|
@@ -275,13 +281,18 @@ class MineStat
|
|
275
281
|
@server.connect(@address, @port)
|
276
282
|
else
|
277
283
|
start_time = Time.now
|
278
|
-
|
284
|
+
if @srv_enabled
|
285
|
+
@server = TCPSocket.new(@srv_address, @srv_port)
|
286
|
+
else
|
287
|
+
@server = TCPSocket.new(@address, @port)
|
288
|
+
end
|
279
289
|
end
|
280
290
|
@latency = ((Time.now - start_time) * 1000).round
|
281
291
|
rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH
|
292
|
+
$stderr.puts "connect(): Host unreachable or connection refused" if @debug
|
282
293
|
return Retval::CONNFAIL
|
283
294
|
rescue => exception
|
284
|
-
$stderr.puts exception if @debug
|
295
|
+
$stderr.puts "connect(): #{exception}" if @debug
|
285
296
|
return Retval::UNKNOWN
|
286
297
|
end
|
287
298
|
return Retval::SUCCESS
|
@@ -322,7 +333,7 @@ class MineStat
|
|
322
333
|
end
|
323
334
|
end
|
324
335
|
rescue => exception
|
325
|
-
$stderr.puts exception if @debug
|
336
|
+
$stderr.puts "check_response(): #{exception}" if @debug
|
326
337
|
return nil, Retval::UNKNOWN
|
327
338
|
end
|
328
339
|
retval = Retval::UNKNOWN if data == nil || data.empty?
|
@@ -347,7 +358,7 @@ class MineStat
|
|
347
358
|
if server_info != nil && server_info.length >= NUM_FIELDS_BETA
|
348
359
|
@version = ">=1.8b/1.3" # since server does not return version, set it
|
349
360
|
@motd = server_info[0]
|
350
|
-
strip_motd
|
361
|
+
strip_motd()
|
351
362
|
@current_players = server_info[1].to_i
|
352
363
|
@max_players = server_info[2].to_i
|
353
364
|
@online = true
|
@@ -360,7 +371,7 @@ class MineStat
|
|
360
371
|
@version = "#{server_info[3]} #{server_info[7]} (#{server_info[0]})"
|
361
372
|
@mode = server_info[8]
|
362
373
|
@motd = server_info[1]
|
363
|
-
strip_motd
|
374
|
+
strip_motd()
|
364
375
|
@current_players = server_info[4].to_i
|
365
376
|
@max_players = server_info[5].to_i
|
366
377
|
@online = true
|
@@ -373,7 +384,7 @@ class MineStat
|
|
373
384
|
server_info = Hash[*server_info[0].split(delimiter).flatten(1)]
|
374
385
|
@version = server_info["version"]
|
375
386
|
@motd = server_info["hostname"]
|
376
|
-
strip_motd
|
387
|
+
strip_motd()
|
377
388
|
@current_players = server_info["numplayers"].to_i
|
378
389
|
@max_players = server_info["maxplayers"].to_i
|
379
390
|
unless server_info["plugins"].nil? || server_info["plugins"].empty?
|
@@ -392,7 +403,7 @@ class MineStat
|
|
392
403
|
@protocol = server_info[1].to_i # contains the protocol version (51 for 1.9 or 78 for 1.6.4 for example)
|
393
404
|
@version = server_info[2]
|
394
405
|
@motd = server_info[3]
|
395
|
-
strip_motd
|
406
|
+
strip_motd()
|
396
407
|
@current_players = server_info[4].to_i
|
397
408
|
@max_players = server_info[5].to_i
|
398
409
|
@online = true
|
@@ -429,9 +440,10 @@ class MineStat
|
|
429
440
|
retval = parse_data("\u00A7", true) # section symbol
|
430
441
|
end
|
431
442
|
rescue Timeout::Error
|
443
|
+
$stderr.puts "beta_request(): Connection timed out" if @debug
|
432
444
|
return Retval::TIMEOUT
|
433
445
|
rescue => exception
|
434
|
-
$stderr.puts exception if @debug
|
446
|
+
$stderr.puts "beta_request(): #{exception}" if @debug
|
435
447
|
return Retval::UNKNOWN
|
436
448
|
end
|
437
449
|
if retval == Retval::SUCCESS
|
@@ -474,9 +486,10 @@ class MineStat
|
|
474
486
|
retval = parse_data("\x00") # null
|
475
487
|
end
|
476
488
|
rescue Timeout::Error
|
489
|
+
$stderr.puts "legacy_request(): Connection timed out" if @debug
|
477
490
|
return Retval::TIMEOUT
|
478
491
|
rescue => exception
|
479
|
-
$stderr.puts exception if @debug
|
492
|
+
$stderr.puts "legacy_request(): #{exception}" if @debug
|
480
493
|
return Retval::UNKNOWN
|
481
494
|
end
|
482
495
|
if retval == Retval::SUCCESS
|
@@ -535,9 +548,10 @@ class MineStat
|
|
535
548
|
retval = parse_data("\x00") # null
|
536
549
|
end
|
537
550
|
rescue Timeout::Error
|
551
|
+
$stderr.puts "extended_legacy_request(): Connection timed out" if @debug
|
538
552
|
return Retval::TIMEOUT
|
539
553
|
rescue => exception
|
540
|
-
$stderr.puts exception if @debug
|
554
|
+
$stderr.puts "extended_legacy_request(): #{exception}" if @debug
|
541
555
|
return Retval::UNKNOWN
|
542
556
|
end
|
543
557
|
if retval == Retval::SUCCESS
|
@@ -596,7 +610,7 @@ class MineStat
|
|
596
610
|
@protocol = json_data['version']['protocol'].to_i
|
597
611
|
@version = json_data['version']['name']
|
598
612
|
@motd = json_data['description']
|
599
|
-
strip_motd
|
613
|
+
strip_motd()
|
600
614
|
@current_players = json_data['players']['online'].to_i
|
601
615
|
@max_players = json_data['players']['max'].to_i
|
602
616
|
@favicon_b64 = json_data['favicon']
|
@@ -611,11 +625,13 @@ class MineStat
|
|
611
625
|
end
|
612
626
|
end
|
613
627
|
rescue Timeout::Error
|
628
|
+
$stderr.puts "json_request(): Connection timed out" if @debug
|
614
629
|
return Retval::TIMEOUT
|
615
630
|
rescue JSON::ParserError
|
631
|
+
$stderr.puts "json_request(): JSON parse error" if @debug
|
616
632
|
return Retval::UNKNOWN
|
617
633
|
rescue => exception
|
618
|
-
$stderr.puts exception if @debug
|
634
|
+
$stderr.puts "json_request(): #{exception}" if @debug
|
619
635
|
return Retval::UNKNOWN
|
620
636
|
end
|
621
637
|
if retval == Retval::SUCCESS
|
@@ -640,7 +656,7 @@ class MineStat
|
|
640
656
|
break if json_data.length >= json_len
|
641
657
|
end
|
642
658
|
rescue => exception
|
643
|
-
$stderr.puts exception if @debug
|
659
|
+
$stderr.puts "recv_json(): #{exception}" if @debug
|
644
660
|
end
|
645
661
|
return json_data
|
646
662
|
end
|
@@ -711,9 +727,10 @@ class MineStat
|
|
711
727
|
retval = parse_data("\x3B") # semicolon
|
712
728
|
end
|
713
729
|
rescue Timeout::Error
|
730
|
+
$stderr.puts "bedrock_request(): Connection timed out" if @debug
|
714
731
|
return Retval::TIMEOUT
|
715
732
|
rescue => exception
|
716
|
-
$stderr.puts exception if @debug
|
733
|
+
$stderr.puts "bedrock_request(): #{exception}" if @debug
|
717
734
|
return Retval::UNKNOWN
|
718
735
|
end
|
719
736
|
if retval == Retval::SUCCESS
|
@@ -777,9 +794,10 @@ class MineStat
|
|
777
794
|
retval = parse_data("\x00") # null
|
778
795
|
end
|
779
796
|
rescue Timeout::Error
|
797
|
+
$stderr.puts "query_request(): Connection timed out" if @debug
|
780
798
|
return Retval::TIMEOUT
|
781
799
|
rescue => exception
|
782
|
-
$stderr.puts exception if @debug
|
800
|
+
$stderr.puts "query_request(): #{exception}" if @debug
|
783
801
|
return Retval::UNKNOWN
|
784
802
|
end
|
785
803
|
if retval == Retval::SUCCESS
|
@@ -795,6 +813,14 @@ class MineStat
|
|
795
813
|
# Port (TCP or UDP) of the Minecraft server
|
796
814
|
attr_reader :port
|
797
815
|
|
816
|
+
# Address of the Minecraft server from a DNS SRV record
|
817
|
+
# @since 3.0.1
|
818
|
+
attr_reader :srv_address
|
819
|
+
|
820
|
+
# TCP port of the Minecraft server from a DNS SRV record
|
821
|
+
# @since 3.0.1
|
822
|
+
attr_reader :srv_port
|
823
|
+
|
798
824
|
# Whether or not the Minecraft server is online
|
799
825
|
attr_reader :online
|
800
826
|
|
@@ -872,4 +898,8 @@ class MineStat
|
|
872
898
|
# Whether or not debug mode is enabled
|
873
899
|
# @since 3.0.0
|
874
900
|
attr_reader :debug
|
901
|
+
|
902
|
+
# Whether or not DNS SRV resolution is enabled
|
903
|
+
# @since 3.0.1
|
904
|
+
attr_reader :srv_enabled
|
875
905
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: minestat
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.0.
|
4
|
+
version: 3.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Lloyd Dilley
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-02-
|
11
|
+
date: 2023-02-06 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: MineStat polls Minecraft server data such as version, motd, current players,
|
14
14
|
and max players.
|