steam-condenser 0.13.1 → 0.14.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. data/lib/exceptions/packet_format_exception.rb +12 -5
  2. data/lib/exceptions/rcon_ban_exception.rb +11 -3
  3. data/lib/exceptions/rcon_no_auth_exception.rb +10 -3
  4. data/lib/exceptions/steam_condenser_exception.rb +8 -5
  5. data/lib/exceptions/timeout_exception.rb +13 -3
  6. data/lib/exceptions/web_api_exception.rb +31 -23
  7. data/lib/steam-condenser.rb +9 -3
  8. data/lib/steam-condenser/community.rb +8 -1
  9. data/lib/steam-condenser/servers.rb +7 -1
  10. data/lib/steam-condenser/version.rb +2 -1
  11. data/lib/steam/community/cacheable.rb +4 -4
  12. data/lib/steam/community/game_inventory.rb +119 -0
  13. data/lib/steam/community/game_item.rb +38 -0
  14. data/lib/steam/community/game_stats.rb +10 -4
  15. data/lib/steam/community/portal2/portal2_inventory.rb +21 -0
  16. data/lib/steam/community/portal2/portal2_item.rb +35 -0
  17. data/lib/steam/community/portal2/portal2_stats.rb +28 -0
  18. data/lib/steam/community/tf2/tf2_inventory.rb +7 -37
  19. data/lib/steam/community/tf2/tf2_item.rb +8 -79
  20. data/lib/steam/community/tf2/tf2_stats.rb +10 -13
  21. data/lib/steam/community/web_api.rb +1 -0
  22. data/lib/steam/packets/a2m_get_servers_batch2_packet.rb +37 -4
  23. data/lib/steam/packets/a2s_info_packet.rb +10 -5
  24. data/lib/steam/packets/a2s_player_packet.rb +16 -6
  25. data/lib/steam/packets/a2s_rules_packet.rb +16 -4
  26. data/lib/steam/packets/a2s_serverquery_getchallenge_packet.rb +11 -5
  27. data/lib/steam/packets/c2m_checkmd5_packet.rb +10 -4
  28. data/lib/steam/packets/m2a_server_batch_packet.rb +19 -3
  29. data/lib/steam/packets/m2c_isvalidmd5_packet.rb +14 -5
  30. data/lib/steam/packets/m2s_requestrestart_packet.rb +14 -4
  31. data/lib/steam/packets/rcon/rcon_auth_request.rb +15 -3
  32. data/lib/steam/packets/rcon/rcon_auth_response.rb +17 -3
  33. data/lib/steam/packets/rcon/rcon_exec_request.rb +15 -3
  34. data/lib/steam/packets/rcon/rcon_exec_response.rb +20 -3
  35. data/lib/steam/packets/rcon/rcon_goldsrc_request.rb +18 -3
  36. data/lib/steam/packets/rcon/rcon_goldsrc_response.rb +17 -3
  37. data/lib/steam/packets/rcon/rcon_packet.rb +31 -3
  38. data/lib/steam/packets/rcon/rcon_packet_factory.rb +15 -5
  39. data/lib/steam/packets/rcon/rcon_terminator.rb +14 -5
  40. data/lib/steam/packets/request_with_challenge.rb +10 -5
  41. data/lib/steam/packets/s2a_info2_packet.rb +14 -5
  42. data/lib/steam/packets/s2a_info_base_packet.rb +16 -6
  43. data/lib/steam/packets/s2a_info_detailed_packet.rb +15 -8
  44. data/lib/steam/packets/s2a_logstring_packet.rb +11 -5
  45. data/lib/steam/packets/s2a_player_packet.rb +14 -6
  46. data/lib/steam/packets/s2a_rules_packet.rb +15 -5
  47. data/lib/steam/packets/s2c_challenge_packet.rb +17 -6
  48. data/lib/steam/packets/s2m_heartbeat2_packet.rb +18 -4
  49. data/lib/steam/packets/steam_packet.rb +14 -5
  50. data/lib/steam/packets/steam_packet_factory.rb +25 -2
  51. data/lib/steam/servers/game_server.rb +154 -25
  52. data/lib/steam/servers/goldsrc_server.rb +35 -3
  53. data/lib/steam/servers/master_server.rb +77 -23
  54. data/lib/steam/servers/server.rb +42 -3
  55. data/lib/steam/servers/source_server.rb +35 -11
  56. data/lib/stringio_additions.rb +48 -3
  57. data/test/query_tests.rb +4 -4
  58. metadata +11 -6
@@ -5,16 +5,25 @@
5
5
 
6
6
  require 'steam/packets/rcon/rcon_packet'
7
7
 
8
- # This class is used to determine the end of a RCON response from Source
9
- # servers. Packets of this type are sent after the actual RCON command and the
10
- # empty response packet from the server will indicate the end of the response.
8
+ # This packet class represents a special SERVERDATA_RESPONSE_VALUE packet which
9
+ # is sent to the server
10
+ #
11
+ # It is used to determine the end of a RCON response from Source servers.
12
+ # Packets of this type are sent after the actual RCON command and the empty
13
+ # response packet from the server will indicate the end of the response.
14
+ #
15
+ # @author Sebastian Staudt
16
+ # @see SourceServer#rcon_exec
11
17
  class RCONTerminator
12
18
 
13
19
  include RCONPacket
14
20
 
15
- # Creates a new RCONTerminator instance for the given request ID
21
+ # Creates a new RCON terminator packet instance for the given request ID
22
+ #
23
+ # @param [Fixnum] request_id The request ID for the current RCON
24
+ # communication
16
25
  def initialize(request_id)
17
- super request_id, RCONPacket::SERVERDATA_RESPONSE_VALUE, nil
26
+ super request_id, SERVERDATA_RESPONSE_VALUE, nil
18
27
  end
19
28
 
20
29
  end
@@ -1,12 +1,17 @@
1
- # This code is free software; you can redistribute it and/or modify it under the
2
- # terms of the new BSD License.
1
+ # This code is free software; you can redistribute it and/or modify it under
2
+ # the terms of the new BSD License.
3
3
  #
4
- # Copyright (c) 2008-2010, Sebastian Staudt
4
+ # Copyright (c) 2008-2011, Sebastian Staudt
5
5
 
6
- # This module implements a to_s method for request packets which send a challenge number
6
+ # This module implements a method to generate raw packet data used by request
7
+ # packets which send a challenge number
8
+ #
9
+ # @author Sebastian Staudt
7
10
  module RequestWithChallenge
8
11
 
9
- # Returns a packed version of the request
12
+ # Returns the raw data representing this packet
13
+ #
14
+ # @return string A string containing the raw data of this request packet
10
15
  def to_s
11
16
  [0xFF, 0xFF, 0xFF, 0xFF, @header_data, @content_data.string.to_i].pack('c5l')
12
17
  end
@@ -1,17 +1,26 @@
1
- # This code is free software; you can redistribute it and/or modify it under the
2
- # terms of the new BSD License.
1
+ # This code is free software; you can redistribute it and/or modify it under
2
+ # the terms of the new BSD License.
3
3
  #
4
4
  # Copyright (c) 2008-2011, Sebastian Staudt
5
5
 
6
6
  require 'steam/packets/s2a_info_base_packet'
7
7
 
8
- # The S2A_INFO2_Packet class represents the response to a A2S_INFO request sent
9
- # to a Source server.
8
+ # This class represents a S2A_INFO_DETAILED response packet sent by a Source or
9
+ # GoldSrc server
10
+ #
11
+ # Out-of-date (before 10/24/2008) GoldSrc servers use an older format (see
12
+ # {S2A_INFO_DETAILED_Packet}).
13
+ #
14
+ # @author Sebastian Staudt
15
+ # @see GameServer#update_server_info
10
16
  class S2A_INFO2_Packet
11
17
 
12
18
  include S2A_INFO_BasePacket
13
19
 
14
- # Creates a S2A_INFO2 response object based on the data received.
20
+ # Creates a new S2A_INFO2 response object based on the given data
21
+ #
22
+ # @param [String] data The raw packet data replied from the server
23
+ # @see S2A_INFO_BasePacket#generate_info_hash
15
24
  def initialize(data)
16
25
  super S2A_INFO2_HEADER, data
17
26
 
@@ -1,19 +1,29 @@
1
- # This code is free software; you can redistribute it and/or modify it under the
2
- # terms of the new BSD License.
1
+ # This code is free software; you can redistribute it and/or modify it under
2
+ # the terms of the new BSD License.
3
3
  #
4
- # Copyright (c) 2008-2010, Sebastian Staudt
4
+ # Copyright (c) 2008-2011, Sebastian Staudt
5
5
 
6
6
  require 'steam/packets/steam_packet'
7
7
 
8
- # The S2A_INFO_BasePacket class represents the response to a A2S_INFO
9
- # request send to the server.
8
+ # This module implements methods to generate and access server information from
9
+ # S2A_INFO_DETAILED and S2A_INFO2 response packets
10
+ #
11
+ # @author Sebastian Staudt
12
+ # @see S2A_INFO_DETAILED_Packet
13
+ # @see S2A_INFO2_Packet
10
14
  module S2A_INFO_BasePacket
11
15
 
12
16
  include SteamPacket
13
17
 
18
+ # Returns the information provided by the server
19
+ #
20
+ # @return [Hash<String, Object>] The information provided by the server
14
21
  attr_reader :info_hash
15
22
 
16
- # Returns the hash containing information on the server
23
+ protected
24
+
25
+ # Generates a hash of server properties from the instance variables of the
26
+ # including packet object
17
27
  def generate_info_hash
18
28
  @info_hash = Hash[
19
29
  *instance_variables.map { |var|
@@ -1,19 +1,26 @@
1
- # This code is free software; you can redistribute it and/or modify it under the
2
- # terms of the new BSD License.
1
+ # This code is free software; you can redistribute it and/or modify it under
2
+ # the terms of the new BSD License.
3
3
  #
4
- # Copyright (c) 2008-2010, Sebastian Staudt
4
+ # Copyright (c) 2008-2011 Sebastian Staudt
5
5
 
6
6
  require "steam/packets/s2a_info_base_packet"
7
7
 
8
- # The S2A_INFO_DETAILED_Packet class represents the response to a A2S_INFO
9
- # request send to a GoldSrc server.
10
- # This is deprecated by 10/24/2008 for GoldSrc servers. They use the same
11
- # format as Source servers (S2A_INFO2) now.
8
+ # This class represents a S2A_INFO_DETAILED response packet sent by a GoldSrc
9
+ # server
10
+ #
11
+ # This is deprecated by 10/24/2008. GoldSrc servers use the same format as
12
+ # Source servers now (see {S2A_INFO2_Packet}).
13
+ #
14
+ # @author Sebastian Staudt
15
+ # @see GameServer#update_server_info
12
16
  class S2A_INFO_DETAILED_Packet
13
17
 
14
18
  include S2A_INFO_BasePacket
15
19
 
16
- # Creates a S2A_INFO_DETAILED response object based on the data received.
20
+ # Creates a new S2A_INFO_DETAILED response object based on the given data
21
+ #
22
+ # @param [String] data The raw packet data replied from the server
23
+ # @see S2A_INFO_BasePacket#generate_info_hash
17
24
  def initialize(data)
18
25
  super S2A_INFO_DETAILED_HEADER, data
19
26
 
@@ -1,19 +1,25 @@
1
- # This code is free software; you can redistribute it and/or modify it under the
2
- # terms of the new BSD License.
1
+ # This code is free software; you can redistribute it and/or modify it under
2
+ # the terms of the new BSD License.
3
3
  #
4
4
  # Copyright (c) 2011, Sebastian Staudt
5
5
 
6
6
  require 'steam/packets/steam_packet'
7
7
 
8
- # The S2A_LOGSTRING packet type is used to transfer log messages.
8
+ # This class represents a S2A_LOGSTRING packet used to transfer log messages
9
+ #
10
+ # @author Sebastian Staudt
9
11
  class S2A_LOGSTRING_Packet
10
12
 
11
13
  include SteamPacket
12
14
 
13
- # The log message contained in this packet
15
+ # Returns the log message contained in this packet
16
+ #
17
+ # @return [String] The log message
14
18
  attr_reader :message
15
19
 
16
- # Creates a new log message packet
20
+ # Creates a new S2A_LOGSTRING object based on the given data
21
+ #
22
+ # @param [String] data The raw packet data sent by the server
17
23
  def initialize(data)
18
24
  super S2A_LOGSTRING_HEADER, data
19
25
 
@@ -1,25 +1,33 @@
1
- # This code is free software; you can redistribute it and/or modify it under the
2
- # terms of the new BSD License.
1
+ # This code is free software; you can redistribute it and/or modify it under
2
+ # the terms of the new BSD License.
3
3
  #
4
4
  # Copyright (c) 2008-2011, Sebastian Staudt
5
5
 
6
6
  require 'steam/packets/steam_packet'
7
7
 
8
- # The S2A_PLAYER_Packet class represents the response to a A2S_PLAYER
9
- # request send to the server.
8
+ # This class represents a S2A_PLAYER response sent by a game server
9
+ #
10
+ # It is used to transfer a list of players currently playing on the server.
11
+ #
12
+ # @author Sebastian Staudt
13
+ # @see GameServer#update_player_info
10
14
  class S2A_PLAYER_Packet
11
15
 
12
16
  include SteamPacket
13
17
 
18
+ # Returns the list of active players provided by the server
19
+ #
20
+ # @return [Hash<String, SteamPlayer>] All active players on the server
14
21
  attr_reader :player_hash
15
22
 
16
- # Creates a S2A_PLAYER response object based on the data received.
23
+ # Creates a new S2A_PLAYER response object based on the given data
24
+ #
25
+ # @param [String] content_data The raw packet data sent by the server
17
26
  def initialize(content_data)
18
27
  raise Exception.new('Wrong formatted S2A_PLAYER packet.') if content_data.nil?
19
28
 
20
29
  super S2A_PLAYER_HEADER, content_data
21
30
 
22
- # Ignore player count
23
31
  @content_data.byte
24
32
  @player_hash = {}
25
33
 
@@ -1,19 +1,29 @@
1
- # This code is free software; you can redistribute it and/or modify it under the
2
- # terms of the new BSD License.
1
+ # This code is free software; you can redistribute it and/or modify it under
2
+ # the terms of the new BSD License.
3
3
  #
4
4
  # Copyright (c) 2008-2011, Sebastian Staudt
5
5
 
6
6
  require 'steam/packets/steam_packet'
7
7
 
8
- # The S2A_RULES_Packet class represents the response to a A2S_RULES
9
- # request send to the server.
8
+ # This class represents a S2A_RULES response sent by a game server
9
+ #
10
+ # It is used to transfer a list of server rules (a.k.a. CVARs) with their
11
+ # active values.
12
+ #
13
+ # @author Sebastian Staudt
14
+ # @see GameServer#update_rules_info
10
15
  class S2A_RULES_Packet
11
16
 
12
17
  include SteamPacket
13
18
 
19
+ # Returns the list of server rules (a.k.a. CVars) with the current values
20
+ #
21
+ # @return [Hash<String, String>] A list of server rules
14
22
  attr_reader :rules_hash
15
23
 
16
- # Creates a S2A_RULES response object based on the data received.
24
+ # Creates a new S2A_RULES response object based on the given data
25
+ #
26
+ # @param [String] content_data The raw packet data sent by the server
17
27
  def initialize(content_data)
18
28
  raise Exception.new('Wrong formatted S2A_RULES response packet.') if content_data.nil?
19
29
 
@@ -1,22 +1,33 @@
1
- # This code is free software; you can redistribute it and/or modify it under the
2
- # terms of the new BSD License.
1
+ # This code is free software; you can redistribute it and/or modify it under
2
+ # the terms of the new BSD License.
3
3
  #
4
4
  # Copyright (c) 2008-2011, Sebastian Staudt
5
5
 
6
6
  require 'steam/packets/steam_packet'
7
7
 
8
- # The S2C_CHALLENGE_Packet class represents the response
9
- # to a A2S_SERVERQUERY_GETCHALLENGE request send to the server.
8
+ # This packet class represents a S2C_CHALLENGE response replied by a game
9
+ # server
10
+ #
11
+ # It is used to provide a challenge number to a client requesting information
12
+ # from the game server.
13
+ #
14
+ # @author Sebastian Staudt
15
+ # @see GameServer#update_challenge_number
10
16
  class S2C_CHALLENGE_Packet
11
17
 
12
18
  include SteamPacket
13
19
 
14
- # Creates a S2C_CHALLENGE response object based on the data received.
20
+ # Creates a new S2C_CHALLENGE response object based on the given data
21
+ #
22
+ # @param [String] challenge_number The raw packet data replied from the
23
+ # server
15
24
  def initialize(challenge_number)
16
25
  super S2C_CHALLENGE_HEADER, challenge_number
17
26
  end
18
27
 
19
- # Returns the challenge number received from the server
28
+ # Returns the challenge number received from the game server
29
+ #
30
+ # @return [Fixnum] The challenge number provided by the game server
20
31
  def challenge_number
21
32
  @content_data.rewind
22
33
  @content_data.long
@@ -5,12 +5,19 @@
5
5
 
6
6
  require 'steam/packets/steam_packet'
7
7
 
8
- # The S2M_HEARTBEAT2 packet type is used to signal a game servers availability
9
- # and status to the master servers.
8
+ # This class represents a S2M_HEARTBEAT2 packet sent by game servers to master
9
+ # servers
10
+ #
11
+ # It is used to signal the game server's availability and status to the master
12
+ # servers.
13
+ #
14
+ # @author Sebastian Staudt
15
+ # @see MasterServer#send_heartbeat
10
16
  class S2M_HEARTBEAT2_Packet
11
17
 
12
18
  include SteamPacket
13
19
 
20
+ # Default data to send with a S2M_HEARTBEAT2 packet
14
21
  DEFAULT_DATA = {
15
22
  :appid => 320,
16
23
  :bots => 0,
@@ -34,7 +41,12 @@ class S2M_HEARTBEAT2_Packet
34
41
  :version => '1.0.0.0'
35
42
  }
36
43
 
37
- # Creates a new heartbeat packet to send to a master server
44
+ # Creates a new S2M_HEARTBEAT2 packet object based on the given data
45
+ #
46
+ # @param [Hash<Symbol, Object>] data The data to send with the heartbeat. The
47
+ # data contents are merge with the values from {DEFAULT_DATA}.
48
+ # @raise [SteamCondenserException] when the required challenge number is
49
+ # missing
38
50
  def initialize(data = {})
39
51
  data = DEFAULT_DATA.merge data
40
52
 
@@ -49,7 +61,9 @@ class S2M_HEARTBEAT2_Packet
49
61
  super S2M_HEARTBEAT2_HEADER, bytes
50
62
  end
51
63
 
52
- # Returns a byte array representation of the packet data
64
+ # Returns the raw data representing this packet
65
+ #
66
+ # @return [String] A string containing the raw data of this request packet
53
67
  def to_s
54
68
  [@header_data, @content_data.string].pack('ca*')
55
69
  end
@@ -1,11 +1,15 @@
1
- # This code is free software; you can redistribute it and/or modify it under the
2
- # terms of the new BSD License.
1
+ # This code is free software; you can redistribute it and/or modify it under
2
+ # the terms of the new BSD License.
3
3
  #
4
4
  # Copyright (c) 2008-2011, Sebastian Staudt
5
5
 
6
6
  require 'stringio_additions'
7
7
 
8
- # This class represents a packet used by the Source query protocol
8
+ # This module implements the basic functionality used by most of the packets
9
+ # used in communication with master, Source or GoldSrc servers.
10
+ #
11
+ # @author Sebastian Staudt
12
+ # @see SteamPacketFactory
9
13
  module SteamPacket
10
14
 
11
15
  A2M_GET_SERVERS_BATCH2_HEADER = 0x31
@@ -29,13 +33,18 @@ module SteamPacket
29
33
  S2C_CHALLENGE_HEADER = 0x41
30
34
  S2M_HEARTBEAT2_HEADER = 0x30
31
35
 
32
- # Creates a new SteamPacket object with given header and content data
36
+ # Creates a new packet object based on the given data
37
+ #
38
+ # @param [Fixnum] header_data The packet header
39
+ # @param [String] content_data The raw data of the packet
33
40
  def initialize(header_data, content_data = '')
34
41
  @content_data = StringIO.new content_data.to_s
35
42
  @header_data = header_data
36
43
  end
37
44
 
38
- # Returns a packed string representing the packet's data
45
+ # Returns the raw data representing this packet
46
+ #
47
+ # @return [String] A string containing the raw data of this request packet
39
48
  def to_s
40
49
  [0xFF, 0xFF, 0xFF, 0xFF, @header_data, @content_data.string].pack('c5a*')
41
50
  end
@@ -1,5 +1,5 @@
1
- # This code is free software; you can redistribute it and/or modify it under the
2
- # terms of the new BSD License.
1
+ # This code is free software; you can redistribute it and/or modify it under
2
+ # the terms of the new BSD License.
3
3
  #
4
4
  # Copyright (c) 2008-2011, Sebastian Staudt
5
5
 
@@ -20,9 +20,19 @@ require 'steam/packets/m2s_requestrestart_packet'
20
20
  require 'steam/packets/s2a_logstring_packet'
21
21
  require 'steam/packets/rcon/rcon_goldsrc_response'
22
22
 
23
+ # This module provides functionality to handle raw packet data, including
24
+ # data split into several UDP / TCP packets and BZIP2 compressed data. It's the
25
+ # main utility to transform data bytes into packet objects.
26
+ #
27
+ # @author Sebastian Staudt
28
+ # @see SteamPacket
23
29
  module SteamPacketFactory
24
30
 
25
31
  # Creates a new packet object based on the header byte of the given raw data
32
+ #
33
+ # @param [String] raw_data The raw data of the packet
34
+ # @raise [SteamCondenserException] if the packet header is not recognized
35
+ # @return [SteamPacket] The packet object generated from the packet data
26
36
  def self.packet_from_data(raw_data)
27
37
  header = raw_data[0].ord
28
38
  data = raw_data[1..-1]
@@ -65,6 +75,19 @@ module SteamPacketFactory
65
75
  end
66
76
  end
67
77
 
78
+ # Reassembles the data of a split and/or compressed packet into a single
79
+ # packet object
80
+ #
81
+ # @param [Array<String>] split_packets An array of packet data
82
+ # @param [true, false] is_compressed whether the data of this packet is
83
+ # compressed
84
+ # @param [Fixnum] packet_checksum The CRC32 checksum of the decompressed
85
+ # packet data
86
+ # @raise [SteamCondenserException] if the bz2 gem is not installed
87
+ # @raise [PacketFormatException] if the calculated CRC32 checksum does not
88
+ # match the expected value
89
+ # @return [SteamPacket] The reassembled packet
90
+ # @see packet_from_data
68
91
  def self.reassemble_packet(split_packets, is_compressed = false, packet_checksum = 0)
69
92
  packet_data = split_packets.join ''
70
93
 
@@ -1,5 +1,5 @@
1
- # This code is free software; you can redistribute it and/or modify it under the
2
- # terms of the new BSD License.
1
+ # This code is free software; you can redistribute it and/or modify it under
2
+ # the terms of the new BSD License.
3
3
  #
4
4
  # Copyright (c) 2008-2011, Sebastian Staudt
5
5
 
@@ -15,6 +15,11 @@ require 'steam/packets/s2a_rules_packet'
15
15
  require 'steam/packets/s2c_challenge_packet'
16
16
  require 'steam/servers/server'
17
17
 
18
+ # This module is included by classes representing different game server
19
+ # implementations and provides the basic functionality to communicate with
20
+ # them using the common query protocol
21
+ #
22
+ # @author Sebastian Staudt
18
23
  module GameServer
19
24
 
20
25
  include Server
@@ -24,7 +29,11 @@ module GameServer
24
29
  REQUEST_PLAYER = 2
25
30
  REQUEST_RULES = 3
26
31
 
27
- # Parses the player attribute names supplied by +rcon status+
32
+ # Parses the player attribute names supplied by `rcon status`
33
+ #
34
+ # @param [String] status_header The header line provided by `rcon status`
35
+ # @return [Array<Symbol>] Split player attribute names
36
+ # @see .split_player_status
28
37
  def self.player_status_attributes(status_header)
29
38
  status_header.split.map do |attribute|
30
39
  case attribute
@@ -38,7 +47,13 @@ module GameServer
38
47
  end
39
48
  end
40
49
 
41
- # Splits the player status obtained with +rcon status+
50
+ # Splits the player status obtained with `rcon status`
51
+ #
52
+ # @param [Array<Symbol>] attributes The attribute names
53
+ # @param [String] player_status The status line of a single player
54
+ # @return [Hash<Symbol, String>] The attributes with the corresponding values
55
+ # for this player
56
+ # @see .player_status_attributes
42
57
  def self.split_player_status(attributes, player_status)
43
58
  player_status.sub! /^\d+ +/, '' if attributes.first != :userid
44
59
 
@@ -68,66 +83,119 @@ module GameServer
68
83
 
69
84
  # Creates a new instance of a game server object
70
85
  #
71
- # The port defaults to 27015 for game servers
86
+ # @param [String] address Either an IP address, a DNS name or one of them
87
+ # combined with the port number. If a port number is given, e.g.
88
+ # 'server.example.com:27016' it will override the second argument.
89
+ # @param [Fixnum] port The port the server is listening on
90
+ # @raise [SteamCondenserException] if an host name cannot be resolved
72
91
  def initialize(address, port = 27015)
73
92
  super
74
93
  end
75
94
 
76
95
  # Returns the last measured response time of this server
77
96
  #
78
- # If there's no data, update_ping is called to measure the current response
79
- # time of the server.
97
+ # If the latency hasn't been measured yet, it is done when calling this
98
+ # method for the first time.
80
99
  #
81
- # Whenever you want to get a new value for the ping time call update_ping.
100
+ # If this information is vital to you, be sure to call {#update_ping}
101
+ # regularly to stay up-to-date.
102
+ #
103
+ # @return [Fixnum] The latency of this server in milliseconds
104
+ # @see #update_ping
82
105
  def ping
83
106
  update_ping if @ping.nil?
84
107
  @ping
85
108
  end
86
109
 
87
- # Returns an array of the player's currently playing on this server.
110
+ # Returns a list of players currently playing on this server
88
111
  #
89
- # If there's no data, update_player_info is called to get the current list of
90
- # players.
112
+ # If the players haven't been fetched yet, it is done when calling this
113
+ # method for the first time.
91
114
  #
92
115
  # As the players and their scores change quite often be sure to update this
93
- # list regularly by calling update_player_info.
116
+ # list regularly by calling {#update_players} if you rely on this
117
+ # information.
118
+ #
119
+ # @param [String] rcon_password The RCON password of this server may be
120
+ # provided to gather more detailed information on the players, like
121
+ # STEAM_IDs.
122
+ # @return [Hash] The players on this server
123
+ # @see update_players
94
124
  def players(rcon_password = nil)
95
- update_player_info(rcon_password) if @player_hash.nil?
125
+ update_players(rcon_password) if @player_hash.nil?
96
126
  @player_hash
97
127
  end
98
128
 
129
+ # Authenticates the connection for RCON communication with the server
130
+ #
131
+ # @abstract Must be be implemented by including classes to handle the
132
+ # authentication
133
+ # @param [String] password The RCON password of the server
134
+ # @return [Boolean] whether the authentication was successful
135
+ # @see #rcon_exec
136
+ def rcon_auth(password)
137
+ end
138
+
99
139
  def rcon_authenticated?
100
140
  @rcon_authenticated
101
141
  end
102
142
 
103
- # Returns a hash of the settings applied on the server. These settings are
104
- # also called rules.
105
- # The hash has the format of +rule_name+ => +rule_value+
143
+ # Remotely executes a command on the server via RCON
106
144
  #
107
- # If there's no data, update_rules_info is called to get the current list of
145
+ # @abstract Must be be implemented by including classes to handle the command
146
+ # execution
147
+ # @param [String] command The command to execute on the server
148
+ # @return [String] The output of the executed command
149
+ # @see #rcon_auth
150
+ def rcon_exec(command)
151
+ end
152
+
153
+ # Returns the settings applied on the server. These settings are also called
108
154
  # rules.
109
155
  #
156
+ # If the rules haven't been fetched yet, it is done when calling this method
157
+ # for the first time.
158
+ #
110
159
  # As the rules usually don't change often, there's almost no need to update
111
160
  # this hash. But if you need to, you can achieve this by calling
112
- # update_rules_info.
161
+ # {#update_rules}.
162
+ #
163
+ # @return [Hash<String, String>] The currently active server rules
164
+ # @see #update_rules
113
165
  def rules
114
- update_rules_info if @rules_hash.nil?
166
+ update_rules if @rules_hash.nil?
115
167
  @rules_hash
116
168
  end
117
169
 
118
170
  # Returns a hash with basic information on the server.
119
171
  #
120
- # If there's no data, update_server_info is called to get up-to-date
121
- # information.
172
+ # If the server information haven't been fetched yet, it is done when
173
+ # calling this method for the first time.
122
174
  #
123
175
  # The server information usually only changes on map change and when players
124
176
  # join or leave. As the latter changes can be monitored by calling
125
- # update_player_info, there's no need to call update_server_info very often.
177
+ # {#update_players}, there's no need to call {#update_server_info} very
178
+ # often.
179
+ #
180
+ # @return [Hash] Server attributes with their values
181
+ # @see #update_server_info
126
182
  def server_info
127
183
  update_server_info if @info_hash.nil?
128
184
  @info_hash
129
185
  end
130
186
 
187
+ # Sends the specified request to the server and handles the returned response
188
+ #
189
+ # Depending on the given request type this will fill the various data
190
+ # attributes of the server object.
191
+ #
192
+ # @param [Fixnum] request_type The type of request to send to the server
193
+ # @param [Boolean] repeat_on_failure Whether the request should be repeated,
194
+ # if the replied packet isn't expected. This is useful to handle
195
+ # missing challenge numbers, which will be automatically filled in,
196
+ # although not requested explicitly.
197
+ # @raise [SteamCondenserException] if either the request type or the response
198
+ # packet is not known
131
199
  def handle_response_for_request(request_type, repeat_on_failure = true)
132
200
  begin
133
201
  case request_type
@@ -171,13 +239,30 @@ module GameServer
171
239
  end
172
240
  end
173
241
 
242
+ # Initializes this server object with basic information
243
+ #
244
+ # @see #update_challenge_number
245
+ # @see #update_ping
246
+ # @see #update_server_info
174
247
  def init
175
248
  update_ping
176
249
  update_server_info
177
250
  update_challenge_number
178
251
  end
179
252
 
180
- def update_player_info(rcon_password = nil)
253
+ # Sends a A2S_PLAYERS request to the server and updates the players' data for
254
+ # this server
255
+ #
256
+ # As the players and their scores change quite often be sure to update this
257
+ # list regularly by calling this method if you rely on this
258
+ # information.
259
+ #
260
+ # @param [String] rcon_password The RCON password of this server may be
261
+ # provided to gather more detailed information on the players, like
262
+ # STEAM_IDs.
263
+ # @see #handle_response_for_request
264
+ # @see #players
265
+ def update_players(rcon_password = nil)
181
266
  handle_response_for_request GameServer::REQUEST_PLAYER
182
267
 
183
268
  unless rcon_password.nil? || @player_hash.nil? || @player_hash.empty?
@@ -198,18 +283,52 @@ module GameServer
198
283
  end
199
284
  end
200
285
 
201
- def update_rules_info
286
+ # Sends a A2S_RULES request to the server and updates the rules of this
287
+ # server
288
+ #
289
+ # As the rules usually don't change often, there's almost no need to update
290
+ # this hash. But if you need to, you can achieve this by calling this method.
291
+ #
292
+ # @see #handle_response_for_request
293
+ # @see #rules
294
+ def update_rules
202
295
  handle_response_for_request GameServer::REQUEST_RULES
203
296
  end
204
297
 
298
+ # Sends a A2S_INFO request to the server and updates this server's basic
299
+ # information
300
+ #
301
+ # The server information usually only changes on map change and when players
302
+ # join or leave. As the latter changes can be monitored by calling
303
+ # {#update_players}, there's no need to call this method very often.
304
+ #
305
+ # @see #handle_response_for_request
306
+ # @see #server_info
205
307
  def update_server_info
206
308
  handle_response_for_request GameServer::REQUEST_INFO
207
309
  end
208
310
 
311
+ # Sends a A2S_SERVERQUERY_GETCHALLENGE request to the server and updates the
312
+ # challenge number used to communicate with this server
313
+ #
314
+ # There's usually no need to call this method explicitly, because
315
+ # {#handle_response_for_request} will automatically get the challenge number
316
+ # when the server assigns a new one.
317
+ #
318
+ # @see #handle_response_for_request
319
+ # @see #init
209
320
  def update_challenge_number
210
321
  handle_response_for_request GameServer::REQUEST_CHALLENGE
211
322
  end
212
323
 
324
+ # Sends a A2S_INFO request to the server and measures the time needed for the
325
+ # reply
326
+ #
327
+ # If this information is vital to you, be sure to call this method regularly
328
+ # to stay up-to-date.
329
+ #
330
+ # @return [Fixnum] The latency of this server in milliseconds
331
+ # @see #ping
213
332
  def update_ping
214
333
  send_request A2S_INFO_Packet.new
215
334
  start_time = Time.now
@@ -218,6 +337,10 @@ module GameServer
218
337
  @ping = (end_time - start_time) * 1000
219
338
  end
220
339
 
340
+ # Returns a human-readable text representation of the server
341
+ #
342
+ # @return [String] Available information about the server in a human-readable
343
+ # format
221
344
  def to_s
222
345
  return_string = ''
223
346
 
@@ -250,11 +373,17 @@ module GameServer
250
373
 
251
374
  protected
252
375
 
376
+ # Receives a response from the server
377
+ #
378
+ # @return [SteamPacket] The response packet replied by the server
253
379
  def reply
254
380
  @socket.reply
255
381
  end
256
382
 
257
- def send_request packet
383
+ # Sends a request packet to the server
384
+ #
385
+ # @param [SteamPacket] packet The request packet to send to the server
386
+ def send_request(packet)
258
387
  @socket.send packet
259
388
  end
260
389