steam-condenser 0.12.0 → 0.13.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.
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