steam-condenser 0.12.0 → 0.13.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. data/README.md +3 -1
  2. data/lib/exceptions/web_api_exception.rb +49 -0
  3. data/lib/steam/community/app_news.rb +69 -0
  4. data/lib/steam/community/game_achievement.rb +29 -0
  5. data/lib/steam/community/steam_id.rb +1 -1
  6. data/lib/steam/community/tf2/tf2_golden_wrench.rb +43 -0
  7. data/lib/steam/community/tf2/tf2_inventory.rb +51 -0
  8. data/lib/steam/community/tf2/tf2_item.rb +106 -0
  9. data/lib/steam/community/tf2/tf2_stats.rb +11 -0
  10. data/lib/steam/community/web_api.rb +96 -0
  11. data/lib/steam/packets/a2s_player_packet.rb +1 -1
  12. data/lib/steam/packets/a2s_rules_packet.rb +3 -3
  13. data/lib/steam/packets/c2m_checkmd5_packet.rb +24 -0
  14. data/lib/steam/packets/m2c_isvalidmd5_packet.rb +25 -0
  15. data/lib/steam/packets/m2s_requestrestart_packet.rb +24 -0
  16. data/lib/steam/packets/rcon/rcon_packet.rb +1 -1
  17. data/lib/steam/packets/rcon/rcon_packet_factory.rb +0 -1
  18. data/lib/steam/packets/rcon/rcon_terminator.rb +20 -0
  19. data/lib/steam/packets/s2a_info2_packet.rb +3 -3
  20. data/lib/steam/packets/s2a_logstring_packet.rb +24 -0
  21. data/lib/steam/packets/s2a_player_packet.rb +1 -1
  22. data/lib/steam/packets/s2a_rules_packet.rb +2 -2
  23. data/lib/steam/packets/s2c_challenge_packet.rb +2 -2
  24. data/lib/steam/packets/s2m_heartbeat2_packet.rb +57 -0
  25. data/lib/steam/packets/steam_packet.rb +6 -3
  26. data/lib/steam/packets/steam_packet_factory.rb +12 -9
  27. data/lib/steam/servers/game_server.rb +57 -16
  28. data/lib/steam/servers/goldsrc_server.rb +7 -12
  29. data/lib/steam/servers/master_server.rb +63 -15
  30. data/lib/steam/servers/server.rb +66 -0
  31. data/lib/steam/servers/source_server.rb +14 -20
  32. data/lib/steam/sockets/goldsrc_socket.rb +13 -9
  33. data/lib/steam/sockets/rcon_socket.rb +35 -24
  34. data/lib/steam/sockets/steam_socket.rb +27 -21
  35. data/lib/steam/steam_player.rb +30 -15
  36. data/lib/steam-condenser/community.rb +17 -16
  37. data/lib/steam-condenser/version.rb +2 -2
  38. metadata +39 -15
  39. data/lib/datagram_channel.rb +0 -67
  40. data/lib/socket_channel.rb +0 -55
  41. data/lib/steam/packets/a2a_ack_packet.rb +0 -24
  42. data/lib/steam/packets/a2a_ping_packet.rb +0 -19
data/README.md CHANGED
@@ -11,7 +11,8 @@ Currently it is implemented in Java, PHP and Ruby.
11
11
  * Ruby 1.8.6 or newer
12
12
 
13
13
  The following gems are required:
14
- * `bzip2-ruby` (for Source servers sending compressed responses)
14
+ * `bzip2-ruby (for Source servers sending compressed responses)
15
+ * `json` (for the Web API features)
15
16
 
16
17
  ## License
17
18
 
@@ -22,6 +23,7 @@ included LICENSE file.
22
23
  ## Credits
23
24
 
24
25
  * Sebastian Staudt -- koraktor(at)gmail.com
26
+ * DeFirence -- defirence(at)defirence.za.net
25
27
 
26
28
  ## See Also
27
29
 
@@ -0,0 +1,49 @@
1
+ # This code is free software; you can redistribute it and/or modify it under the
2
+ # terms of the new BSD License.
3
+ #
4
+ # Copyright (c) 2010, Sebastian Staudt
5
+
6
+ require 'exceptions/steam_condenser_exception'
7
+
8
+ # This exceptions is raised when a Steam Web API request or a related action
9
+ # fails. This can have various reasons.
10
+ class WebApiException < SteamCondenserException
11
+
12
+ # Creates a new WebApiException with an error message according to the given
13
+ # +cause+. If this cause is +:status_bad+ (which will origin from the Web API
14
+ # itself) or +:http_error+ the details about this failed request will be
15
+ # taken from +status_code+ and +status_message+.
16
+ #
17
+ # * +:http_errpr+: An error in the HTTP request itself will result in an
18
+ # exception with this reason.
19
+ # * +:invalid_key+: This occurs when trying to set a Web API key that isn't
20
+ # valid, i.e. a 128 bit integer in a hexadecimal string.
21
+ # * +:status_bad+: This is caused by a succesful request that fails for
22
+ # some Web API internal reason (e.g. a invalid argument).
23
+ # Details about this failed request will be taken from
24
+ # +status_code+ and +status_message+.
25
+ # * +:unauthorized+: This happens when a Steam Web API request is rejected as
26
+ # unauthorized. This most likely means that you did not
27
+ # specify a valid Web API key using +WebAPI.api_key=+. A
28
+ # Web API key can be obtained from
29
+ # http://steamcommunity.com/dev/apikey.
30
+ #
31
+ # Other undefined reasons will cause a generic error message.
32
+ def initialize(cause, status_code = nil, status_message = '')
33
+ case cause
34
+ when :http_error then
35
+ message = "The Web API request has failed due to an HTTP error: #{status_message} (status code: #{status_code})."
36
+ when :invalid_key then
37
+ message = 'This is not a valid Steam Web API key.'
38
+ when :status_bad then
39
+ message = "The Web API request failed with the following error: #{status_message} (status code: #{status_code})."
40
+ when :unauthorized then
41
+ message = 'Your Web API request has been rejected. You most likely did not specify a valid Web API key.'
42
+ else
43
+ message = 'An unexpected error occured while executing a Web API request.'
44
+ end
45
+
46
+ super message
47
+ end
48
+
49
+ end
@@ -0,0 +1,69 @@
1
+ # This code is free software; you can redistribute it and/or modify it under the
2
+ # terms of the new BSD License.
3
+ #
4
+ # Copyright (c) 2010, Sebastian Staudt
5
+
6
+ require 'json'
7
+
8
+ require 'steam/community/web_api'
9
+
10
+ # The AppNews class is a representation of Steam news and can be used to load
11
+ # current news about specific games
12
+ class AppNews
13
+
14
+ attr_reader :app_id, :author, :contents, :date, :feed_label, :feed_name,
15
+ :gid, :title, :url
16
+
17
+ # Loads the news for the given game with the given restrictions
18
+ #
19
+ # [+app_id+] The unique Steam Application ID of the game (e.g. +440+ for
20
+ # Team Fortress 2). See
21
+ # http://developer.valvesoftware.com/wiki/Steam_Application_IDs
22
+ # for all application IDs
23
+ # [+count+] The maximum number of news to load (default: 5). There's no
24
+ # reliable way to load all news. Use really a really great
25
+ # number instead
26
+ # [+max_length+] The maximum content length of the news (default: nil). If a
27
+ # maximum length is defined, the content of the news will only
28
+ # be at most +max_length+ characters long plus an ellipsis
29
+ def self.news_for_app(app_id, count = 5, max_length = nil)
30
+ params = { :appid => app_id, :count => count, :maxlength => max_length }
31
+ data = WebApi.json('ISteamNews', 'GetNewsForApp', 1, params)
32
+
33
+ news_items = []
34
+ JSON.parse(data, { :symbolize_names => true })[:appnews][:newsitems][:newsitem].each do |news_data|
35
+ news_items << AppNews.new(app_id, news_data)
36
+ end
37
+
38
+ news_items
39
+ end
40
+
41
+ # Returns whether this news items originates from a source other than Steam
42
+ # itself (e.g. an external blog)
43
+ def external?
44
+ @external
45
+ end
46
+
47
+ private
48
+
49
+ # Creates a new instance of an AppNews news item with the given data
50
+ #
51
+ # [+app_id+] The unique Steam Application ID of the game (e.g. +440+ for
52
+ # Team Fortress 2). See
53
+ # http://developer.valvesoftware.com/wiki/Steam_Application_IDs
54
+ # for all application IDs
55
+ # [+news_data+] The news data extracted from JSON
56
+ def initialize(app_id, news_data)
57
+ @app_id = app_id
58
+ @author = news_data[:autor]
59
+ @contents = news_data[:contents].strip
60
+ @data = Time.at(news_data[:date])
61
+ @external = news_data[:is_external_url]
62
+ @feed_label = news_data[:feedlabel]
63
+ @feed_name = news_data[:feedname]
64
+ @gid = news_data[:gid]
65
+ @title = news_data[:title]
66
+ @url = news_data[:url]
67
+ end
68
+
69
+ end
@@ -3,14 +3,43 @@
3
3
  #
4
4
  # Copyright (c) 2008-2010, Sebastian Staudt
5
5
 
6
+ require 'json'
7
+
8
+ require 'steam/community/web_api'
9
+
6
10
  # The GameAchievement class represents a specific achievement for a single game
7
11
  # and for a single user
8
12
  class GameAchievement
9
13
 
10
14
  attr_reader :app_id, :name, :steam_id64, :timestamp
11
15
 
16
+ # Loads the global unlock percentages of all achievements for the given game
17
+ #
18
+ # [+app_id+] The unique Steam Application ID of the game (e.g. +440+ for
19
+ # Team Fortress 2). See
20
+ # http://developer.valvesoftware.com/wiki/Steam_Application_IDs
21
+ # for all application IDs
22
+ def self.global_percentages(app_id)
23
+ percentages = {}
24
+
25
+ data = WebApi.json('ISteamUserStats', 'GetGlobalAchievementPercentagesForApp', 1, { :gameid => app_id })
26
+ JSON.parse(data, { :symbolize_names => true })[:achievementpercentages][:achievements][:achievement].each do |percentage|
27
+ percentages[percentage[:name].to_sym] = percentage[:percent]
28
+ end
29
+
30
+ percentages
31
+ end
32
+
12
33
  # Creates the achievement with the given name for the given user and game
13
34
  # and achievement data
35
+ #
36
+ # [+steam_id64+] The 64bit SteamID of the player this achievement
37
+ # belongs to
38
+ # [+app_id+] The unique Steam Application ID of the game (e.g.
39
+ # +440+ for Team Fortress 2). See
40
+ # http://developer.valvesoftware.com/wiki/Steam_Application_IDs
41
+ # for all application IDs
42
+ # [+achievement_data+] The achievement data extracted from JSON
14
43
  def initialize(steam_id64, app_id, achievement_data)
15
44
  @app_id = app_id
16
45
  @name = achievement_data.elements['name'].text
@@ -177,7 +177,7 @@ class SteamId
177
177
  if game.elements['globalStatsLink'].nil?
178
178
  @games[game_name] = false
179
179
  else
180
- friendly_name = game.elements['globalStatsLink'].text.match(/http:\/\/steamcommunity.com\/stats\/([0-9a-zA-Z:]+)\/achievements\//)[1]
180
+ friendly_name = game.elements['globalStatsLink'].text.match(/http:\/\/steamcommunity.com\/stats\/([^?\/]+)\/achievements\//)[1]
181
181
  @games[game_name] = friendly_name.downcase
182
182
  end
183
183
  end
@@ -0,0 +1,43 @@
1
+ # This code is free software; you can redistribute it and/or modify it under the
2
+ # terms of the new BSD License.
3
+ #
4
+ # Copyright (c) 2010, Sebastian Staudt
5
+
6
+ require 'json'
7
+ require 'steam/community/steam_id'
8
+ require 'steam/community/web_api'
9
+
10
+ # Represents the special Team Fortress 2 item Golden Wrench. It includes the
11
+ # ID of the item, the serial number of the wrench, a reference to the SteamId
12
+ # of the owner and the date this player crafted the wrench
13
+ class TF2GoldenWrench
14
+
15
+ attr_reader :date, :id, :number, :owner
16
+
17
+ @@golden_wrenches = nil
18
+
19
+ # Returns an array of all golden wrenches (as instances of TF2GoldenWrench)
20
+ def self.golden_wrenches
21
+ if @@golden_wrenches.nil?
22
+ @@golden_wrenches = []
23
+
24
+ data = JSON.parse(WebApi.json('ITFItems_440', 'GetGoldenWrenches'), { :symbolize_names => true })
25
+ data[:results][:wrenches][:wrench].each do |wrench_data|
26
+ @@golden_wrenches << TF2GoldenWrench.new(wrench_data)
27
+ end
28
+ end
29
+
30
+ @@golden_wrenches
31
+ end
32
+
33
+ private
34
+
35
+ # Creates a new instance of TF2GoldenWrench with the given data
36
+ def initialize(wrench_data)
37
+ @date = Time.at(wrench_data[:timestamp])
38
+ @id = wrench_data[:itemID]
39
+ @number = wrench_data[:wrenchNumber]
40
+ @owner = SteamId.new(wrench_data[:steamID], false)
41
+ end
42
+
43
+ end
@@ -0,0 +1,51 @@
1
+ # This code is free software; you can redistribute it and/or modify it under the
2
+ # terms of the new BSD License.
3
+ #
4
+ # Copyright (c) 2010, Sebastian Staudt
5
+
6
+ require 'steam/community/cacheable'
7
+ require 'steam/community/tf2/tf2_item'
8
+ require 'steam/community/web_api'
9
+
10
+ # Represents the inventory (aka. Backpack) of a Team Fortress 2 player
11
+ class TF2Inventory
12
+
13
+ include Cacheable
14
+ cacheable_with_ids :steam_id64
15
+
16
+ attr_reader :items, :steam_id64
17
+
18
+ # Creates a new inventory object for the given SteamID64. This calls update
19
+ # to fetch the data and create the TF2Item instances contained in this
20
+ # players backpack
21
+ def initialize(steam_id64, fetch_now = true)
22
+ @steam_id64 = steam_id64
23
+
24
+ super(fetch_now)
25
+ end
26
+
27
+ # Returns the item at the given position in the backpack. The positions range
28
+ # from 1 to 100 instead of the usual array indices (0 to 99).
29
+ def [](index)
30
+ @items[index - 1]
31
+ end
32
+
33
+ # Updates the contents of the backpack using Steam Web API
34
+ def fetch
35
+ result = WebApi.json!('ITFItems_440', 'GetPlayerItems', 1, { :SteamID => @steam_id64 })
36
+
37
+ @items = []
38
+ result[:items][:item].each do |item_data|
39
+ unless item_data.nil?
40
+ item = TF2Item.new(item_data)
41
+ @items[item.backpack_position - 1] = item
42
+ end
43
+ end
44
+ end
45
+
46
+ # Returns the number of items in the user's backpack
47
+ def size
48
+ @items.size
49
+ end
50
+
51
+ end
@@ -0,0 +1,106 @@
1
+ # This code is free software; you can redistribute it and/or modify it under the
2
+ # terms of the new BSD License.
3
+ #
4
+ # Copyright (c) 2010, Sebastian Staudt
5
+
6
+ require 'steam/community/web_api'
7
+
8
+ # Represents a Team Fortress 2 item
9
+ class TF2Item
10
+
11
+ CLASSES = [ :scout, :sniper, :soldier, :demoman, :medic, :heavy, :pyro, :spy ]
12
+
13
+ attr_reader :attributes, :backpack_position, :class, :count, :defindex, :id,
14
+ :level, :name, :quality, :slot, :type
15
+
16
+ @@attribute_schema = nil
17
+
18
+ @@item_schema = nil
19
+
20
+ @@schema_language = 'en'
21
+
22
+ # Returns the attribute schema
23
+ #
24
+ # The attribute schema is fetched first if not done already
25
+ def self.attribute_schema
26
+ update_schema if @@attribute_schema.nil?
27
+
28
+ @@attribute_schema
29
+ end
30
+
31
+ # Returns the item schema
32
+ #
33
+ # The item schema is fetched first if not done already
34
+ def self.item_schema
35
+ update_schema if @@item_schema.nil?
36
+
37
+ @@item_schema
38
+ end
39
+
40
+ # Sets the language the schema should be fetched in (default is: +'en'+)
41
+ def self.schema_language=(language)
42
+ @@schema_language = language
43
+ end
44
+
45
+ # Creates a new instance of a TF2Item with the given data
46
+ def initialize(item_data)
47
+ update_schema if @@item_schema.nil?
48
+
49
+ @defindex = item_data[:defindex]
50
+
51
+ @backpack_position = item_data[:inventory] & 0xffff
52
+ @class = @@item_schema[@defindex][:item_class]
53
+ @count = item_data[:quantity]
54
+ @id = item_data[:id]
55
+ @level = item_data[:level]
56
+ @name = @@item_schema[@defindex][:item_name]
57
+ @quality = @@qualities[item_data[:quality]]
58
+ @slot = @@item_schema[@defindex][:item_slot]
59
+ @type = @@item_schema[@defindex][:item_type_name]
60
+
61
+ @equipped = {}
62
+ CLASSES.each_index do |class_id|
63
+ @equipped[CLASSES[class_id]] = (item_data[:inventory] & (1 << 16 + class_id) != 0)
64
+ end
65
+
66
+ unless @@item_schema[@defindex][:attributes].nil?
67
+ @attributes = @@item_schema[@defindex][:attributes][:attribute]
68
+ end
69
+ end
70
+
71
+ # Returns the class symbols for each class this player has equipped this item
72
+ def classes_equipped?
73
+ @equipped.reject { |class_id, equipped| !equipped }
74
+ end
75
+
76
+ # Returns whether this item is equipped by this player at all
77
+ def equipped?
78
+ @equipped.has_value? true
79
+ end
80
+
81
+ protected
82
+
83
+ # Updates the item schema (this includes attributes and qualities) using the
84
+ # +GetSchema+ method of interface +ITFItems_440+
85
+ def update_schema
86
+ params = {}
87
+ params[:language] = @@schema_language unless @@schema_language.nil?
88
+ result = WebApi.json!('ITFItems_440', 'GetSchema', 1, params)
89
+
90
+ @@attribute_schema = {}
91
+ result[:attributes][:attribute].each do |attribute_data|
92
+ @@attribute_schema[attribute_data[:name]] = attribute_data
93
+ end
94
+
95
+ @@item_schema = []
96
+ result[:items][:item].each do |item_data|
97
+ @@item_schema[item_data[:defindex]] = item_data
98
+ end
99
+
100
+ @@qualities = []
101
+ result[:qualities].each do |quality, id|
102
+ @@qualities[id] = quality
103
+ end
104
+ end
105
+
106
+ end
@@ -5,6 +5,7 @@
5
5
 
6
6
  require 'steam/community/game_stats'
7
7
  require 'steam/community/tf2/tf2_class_factory'
8
+ require 'steam/community/tf2/tf2_inventory'
8
9
 
9
10
  # The TF2Stats class represents the game statistics for a single user in Team
10
11
  # Fortress 2
@@ -22,6 +23,16 @@ class TF2Stats < GameStats
22
23
  end
23
24
  end
24
25
 
26
+ # Returns the current Team Fortress 2 inventory (a.k.a. backpack) of this
27
+ # player
28
+ def inventory
29
+ if @inventory.nil?
30
+ @inventory = TF2Inventory.new(steam_id64)
31
+ end
32
+
33
+ @inventory
34
+ end
35
+
25
36
  # Returns a Hash of TF2Class for this user containing all Team Fortress 2
26
37
  # classes. If the classes haven't been parsed already, parsing is done now.
27
38
  def class_stats
@@ -0,0 +1,96 @@
1
+ # This code is free software; you can redistribute it and/or modify it under
2
+ # the terms of the new BSD License.
3
+ #
4
+ # Copyright (c) 2010, Sebastian Staudt
5
+
6
+ require 'json'
7
+ require 'open-uri'
8
+
9
+ require 'exceptions/web_api_exception'
10
+
11
+ # This adds support for Steam Web API to classes needing this functionality.
12
+ # The Web API requires you to register a domain with your Steam account to
13
+ # acquire an API key. See http://steamcommunity.com/dev for further details.
14
+ module WebApi
15
+
16
+ @@api_key = nil
17
+
18
+ # Returns the Steam Web API key
19
+ def self.api_key
20
+ @@api_key
21
+ end
22
+
23
+ # Sets the Steam Web API key.
24
+ #
25
+ # [+api_key+] The 128bit API key that has to be requested from
26
+ # http://steamcommunity.com/dev
27
+ def self.api_key=(api_key)
28
+ unless api_key.nil? || api_key.match(/^[0-9A-F]{32}$/)
29
+ raise WebApiException.new(:invalid_key)
30
+ end
31
+
32
+ @@api_key = api_key
33
+ end
34
+
35
+ # Fetches JSON data from Steam Web API using the specified interface, method
36
+ # and version. Additional parameters are supplied via HTTP GET.
37
+ # Data is returned as a JSON-encoded string.
38
+ #
39
+ # [+interface+] The Web API interface to call, e.g. +ISteamUser+
40
+ # [+method+] The Web API method to call, e.g. +GetPlayerSummaries+
41
+ # [+version+] The API method version to use (default: 1)
42
+ # [+params+] A Hash of additional parameters to supply via HTTP GET
43
+ def self.json(interface, method, version = 1, params = nil)
44
+ load(:json, interface, method, version, params)
45
+ end
46
+
47
+ # Fetches JSON data from Steam Web API using the specified interface, method
48
+ # and version. Additional parameters are supplied via HTTP GET.
49
+ # Data is returned as a Hash containing the JSON data.
50
+ #
51
+ # [+interface+] The Web API interface to call, e.g. +ISteamUser+
52
+ # [+method+] The Web API method to call, e.g. +GetPlayerSummaries+
53
+ # [+version+] The API method version to use (default: 1)
54
+ # [+params+] A Hash of additional parameters to supply via HTTP GET
55
+ def self.json!(interface, method, version = 1, params = nil)
56
+ data = json(interface, method, version, params)
57
+ result = JSON.parse(data, { :symbolize_names => true })[:result]
58
+
59
+ status = result[:status]
60
+ if status != 1
61
+ raise WebApiException.new(:status_bad, status, result[:statusDetail])
62
+ end
63
+
64
+ result
65
+ end
66
+
67
+ # Fetches data from Steam Web API using the specified interface, method and
68
+ # version. Additional parameters are supplied via HTTP GET.
69
+ # Data is returned as a String in the given format.
70
+ #
71
+ # [+format+] The format to load from the API ('json', 'vdf', or 'xml')
72
+ # [+interface+] The Web API interface to call, e.g. +ISteamUser+
73
+ # [+method+] The Web API method to call, e.g. +GetPlayerSummaries+
74
+ # [+version+] The API method version to use (default: 1)
75
+ # [+params+] A Hash of additional parameters to supply via HTTP GET
76
+ def self.load(format, interface, method, version = 1, params = nil)
77
+ version = version.to_s.rjust(4, '0')
78
+ url = "http://api.steampowered.com/#{interface}/#{method}/v#{version}/"
79
+ params = {} unless params.is_a?(Hash)
80
+ params[:format] = format
81
+ params[:key] = WebApi.api_key
82
+
83
+ unless params.nil? && params.empty?
84
+ url += '?' + params.map { |k,v| "#{k}=#{v}" }.join('&')
85
+ end
86
+
87
+ begin
88
+ open(url, { :proxy => true }).read
89
+ rescue OpenURI::HTTPError
90
+ status = $!.io.status[0]
91
+ raise WebApiException.new(:unauthorized) if status[0].to_i == 401
92
+ raise WebApiException.new(:http_error, status[0].to_i, status[1])
93
+ end
94
+ end
95
+
96
+ end
@@ -10,8 +10,8 @@ require 'steam/packets/steam_packet'
10
10
  # server.
11
11
  class A2S_PLAYER_Packet
12
12
 
13
- include RequestWithChallenge
14
13
  include SteamPacket
14
+ include RequestWithChallenge
15
15
 
16
16
  # Creates a new A2S_PLAYER request object including the challenge_number
17
17
  def initialize(challenge_number = -1)
@@ -1,16 +1,16 @@
1
1
  # This code is free software; you can redistribute it and/or modify it under the
2
2
  # 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/request_with_challenge'
7
7
  require 'steam/packets/steam_packet'
8
8
 
9
- # Creates a new A2A_RULES request object including the challenge_number
9
+ # Creates a new A2S_RULES request object including the challenge_number
10
10
  class A2S_RULES_Packet
11
11
 
12
- include RequestWithChallenge
13
12
  include SteamPacket
13
+ include RequestWithChallenge
14
14
 
15
15
  # Creates a new A2S_RULES request object including the challenge_number
16
16
  def initialize(challenge_number = -1)
@@ -0,0 +1,24 @@
1
+ # This code is free software; you can redistribute it and/or modify it under
2
+ # the terms of the new BSD License.
3
+ #
4
+ # Copyright (c) 2010-2011, Sebastian Staudt
5
+
6
+ require 'steam/packets/steam_packet'
7
+
8
+ # The C2M_CHECKMD5 packet type is used to initialize (challenge) master server
9
+ # communication.
10
+ class C2M_CHECKMD5_Packet
11
+
12
+ include SteamPacket
13
+
14
+ # Creates a new challenge request packet for master server communication
15
+ def initialize
16
+ super C2M_CHECKMD5_HEADER
17
+ end
18
+
19
+ # Returns a byte array representation of the packet data
20
+ def to_s
21
+ [@header_data, 0xFF].pack('c2')
22
+ end
23
+
24
+ end
@@ -0,0 +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.
3
+ #
4
+ # Copyright (c) 2011, Sebastian Staudt
5
+
6
+ require 'steam/packets/steam_packet'
7
+
8
+ # A packet of type M2S_ISVALIDMD5 is used by the master server to provide a
9
+ # challenge number to a game server
10
+ class M2C_ISVALIDMD5_Packet
11
+
12
+ include SteamPacket
13
+
14
+ # Returns the challenge number to use for master server communication
15
+ attr_reader :challenge
16
+
17
+ # Creates a new response packet with the data from the master server
18
+ def initialize(data)
19
+ super M2C_ISVALIDMD5_HEADER, data
20
+
21
+ @content_data.byte
22
+ @challenge = @content_data.long
23
+ end
24
+
25
+ end
@@ -0,0 +1,24 @@
1
+ # This code is free software; you can redistribute it and/or modify it under the
2
+ # terms of the new BSD License.
3
+ #
4
+ # Copyright (c) 2011, Sebastian Staudt
5
+
6
+ require 'steam/packets/steam_packet'
7
+
8
+ # The M2S_REQUESTRESTART packet type is used to by master servers to request a
9
+ # game server restart, e.g. when using outdated versions.
10
+ class M2S_REQUESTRESTART_Packet
11
+
12
+ include SteamPacket
13
+
14
+ # Returns the challenge number used for master server communication
15
+ attr_reader :challenge
16
+
17
+ # Creates a new server restart request packet sent by a master server
18
+ def initialize(data)
19
+ super C2M_CHECKMD5_HEADER, data
20
+
21
+ @challenge = @content_data.long
22
+ end
23
+
24
+ end
@@ -22,7 +22,7 @@ module RCONPacket
22
22
  @request_id = request_id
23
23
  end
24
24
 
25
- def bytes
25
+ def to_s
26
26
  [@content_data.length + 8, @request_id, @header_data, @content_data.string].pack('V3a*')
27
27
  end
28
28
 
@@ -16,7 +16,6 @@ module RCONPacketFactory
16
16
  def self.packet_from_data(raw_data)
17
17
  byte_buffer = StringIO.new raw_data
18
18
 
19
- byte_buffer.long
20
19
  request_id = byte_buffer.long
21
20
  header = byte_buffer.long
22
21
  data = byte_buffer.cstring
@@ -0,0 +1,20 @@
1
+ # This code is free software; you can redistribute it and/or modify it under
2
+ # the terms of the new BSD License.
3
+ #
4
+ # Copyright (c) 2011, Sebastian Staudt
5
+
6
+ require 'steam/packets/rcon/rcon_packet'
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.
11
+ class RCONTerminator
12
+
13
+ include RCONPacket
14
+
15
+ # Creates a new RCONTerminator instance for the given request ID
16
+ def initialize(request_id)
17
+ super request_id, RCONPacket::SERVERDATA_RESPONSE_VALUE, nil
18
+ end
19
+
20
+ end
@@ -1,12 +1,12 @@
1
1
  # This code is free software; you can redistribute it and/or modify it under the
2
2
  # 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_INFO2_Packet class represents the response to a A2A_INFO
9
- # request send to a Source server.
8
+ # The S2A_INFO2_Packet class represents the response to a A2S_INFO request sent
9
+ # to a Source server.
10
10
  class S2A_INFO2_Packet
11
11
 
12
12
  include S2A_INFO_BasePacket