steam-condenser 1.1.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (62) hide show
  1. data/Gemfile.lock +30 -0
  2. data/LICENSE +1 -1
  3. data/README.md +4 -3
  4. data/lib/steam-condenser/version.rb +2 -2
  5. data/lib/steam/community/alien_swarm/alien_swarm_mission.rb +24 -22
  6. data/lib/steam/community/alien_swarm/alien_swarm_stats.rb +66 -65
  7. data/lib/steam/community/alien_swarm/alien_swarm_weapon.rb +6 -6
  8. data/lib/steam/community/app_news.rb +2 -2
  9. data/lib/steam/community/css/css_map.rb +4 -4
  10. data/lib/steam/community/css/css_stats.rb +43 -43
  11. data/lib/steam/community/css/css_weapon.rb +5 -5
  12. data/lib/steam/community/defense_grid/defense_grid_stats.rb +36 -35
  13. data/lib/steam/community/dods/dods_class.rb +14 -14
  14. data/lib/steam/community/dods/dods_stats.rb +5 -4
  15. data/lib/steam/community/dods/dods_weapon.rb +6 -6
  16. data/lib/steam/community/game_achievement.rb +38 -31
  17. data/lib/steam/community/game_inventory.rb +6 -6
  18. data/lib/steam/community/game_leaderboard.rb +34 -32
  19. data/lib/steam/community/game_leaderboard_entry.rb +6 -6
  20. data/lib/steam/community/game_stats.rb +39 -65
  21. data/lib/steam/community/game_weapon.rb +2 -2
  22. data/lib/steam/community/l4d/abstract_l4d_stats.rb +54 -49
  23. data/lib/steam/community/l4d/abstract_l4d_weapon.rb +7 -6
  24. data/lib/steam/community/l4d/l4d2_map.rb +10 -10
  25. data/lib/steam/community/l4d/l4d2_stats.rb +33 -33
  26. data/lib/steam/community/l4d/l4d2_weapon.rb +8 -7
  27. data/lib/steam/community/l4d/l4d_explosive.rb +5 -4
  28. data/lib/steam/community/l4d/l4d_map.rb +8 -7
  29. data/lib/steam/community/l4d/l4d_stats.rb +7 -7
  30. data/lib/steam/community/l4d/l4d_weapon.rb +5 -4
  31. data/lib/steam/community/portal2/portal2_stats.rb +3 -3
  32. data/lib/steam/community/steam_game.rb +106 -16
  33. data/lib/steam/community/steam_group.rb +51 -40
  34. data/lib/steam/community/steam_id.rb +119 -87
  35. data/lib/steam/community/tf2/tf2_class.rb +14 -14
  36. data/lib/steam/community/tf2/tf2_class_factory.rb +2 -2
  37. data/lib/steam/community/tf2/tf2_engineer.rb +5 -7
  38. data/lib/steam/community/tf2/tf2_golden_wrench.rb +1 -1
  39. data/lib/steam/community/tf2/tf2_medic.rb +4 -6
  40. data/lib/steam/community/tf2/tf2_sniper.rb +3 -5
  41. data/lib/steam/community/tf2/tf2_spy.rb +10 -6
  42. data/lib/steam/community/tf2/tf2_stats.rb +15 -7
  43. data/lib/steam/community/web_api.rb +15 -1
  44. data/lib/steam/community/xml_data.rb +17 -0
  45. data/lib/steam/servers/game_server.rb +4 -4
  46. data/lib/steam/servers/master_server.rb +2 -2
  47. data/lib/steam/servers/source_server.rb +0 -2
  48. data/lib/steam/sockets/goldsrc_socket.rb +2 -2
  49. data/lib/steam/steam_player.rb +2 -2
  50. data/steam-condenser.gemspec +3 -2
  51. data/test/helper.rb +10 -2
  52. data/test/steam/communtiy/test_steam_group.rb +4 -4
  53. data/test/steam/communtiy/test_steam_id.rb +28 -2
  54. data/test/steam/communtiy/test_web_api.rb +2 -2
  55. data/test/steam/packets/test_steam_packet.rb +37 -0
  56. data/test/steam/servers/test_game_server.rb +296 -308
  57. data/test/steam/servers/test_goldsrc_server.rb +59 -59
  58. data/test/steam/servers/test_master_server.rb +131 -131
  59. data/test/steam/servers/test_server.rb +72 -72
  60. data/test/steam/servers/test_source_server.rb +126 -140
  61. data/test/steam/sockets/test_master_server_socket.rb +1 -0
  62. metadata +39 -19
@@ -1,17 +1,16 @@
1
1
  # This code is free software; you can redistribute it and/or modify it under
2
2
  # the terms of the new BSD License.
3
3
  #
4
- # Copyright (c) 2008-2011, Sebastian Staudt
4
+ # Copyright (c) 2008-2012, Sebastian Staudt
5
5
 
6
6
  require 'cgi'
7
- require 'open-uri'
8
- require 'rexml/document'
9
7
 
10
8
  require 'errors/steam_condenser_error'
11
9
  require 'steam/community/cacheable'
12
10
  require 'steam/community/game_stats'
13
11
  require 'steam/community/steam_game'
14
12
  require 'steam/community/steam_group'
13
+ require 'steam/community/xml_data'
15
14
 
16
15
  # The SteamId class represents a Steam Community profile (also called Steam ID)
17
16
  #
@@ -21,6 +20,8 @@ class SteamId
21
20
  include Cacheable
22
21
  cacheable_with_ids :custom_url, :steam_id64
23
22
 
23
+ include XMLData
24
+
24
25
  # Returns the custom URL of this Steam ID
25
26
  #
26
27
  # The custom URL is a user specified unique string that can be used instead
@@ -126,6 +127,11 @@ class SteamId
126
127
  # @return [String] This user's summary
127
128
  attr_reader :summary
128
129
 
130
+ # Returns this user's ban state in Steam's trading system
131
+ #
132
+ # @return [String] This user's trading ban state
133
+ attr_reader :trade_ban_state
134
+
129
135
  # Returns the visibility state of this Steam ID
130
136
  #
131
137
  # @return [Fixnum] This Steam ID's visibility State
@@ -138,7 +144,7 @@ class SteamId
138
144
  # Community
139
145
  # @raise [SteamCondenserError] if the community ID is to small
140
146
  # @return [String] The converted SteamID, like `STEAM_0:0:12345`
141
- def self.convert_community_id_to_steam_id(community_id)
147
+ def self.community_id_to_steam_id(community_id)
142
148
  steam_id1 = community_id % 2
143
149
  steam_id2 = community_id - 76561197960265728
144
150
 
@@ -159,7 +165,7 @@ class SteamId
159
165
  # @raise [SteamCondenserError] if the SteamID doesn't have the correct
160
166
  # format
161
167
  # @return [Fixnum] The converted 64bit numeric SteamID
162
- def self.convert_steam_id_to_community_id(steam_id)
168
+ def self.steam_id_to_community_id(steam_id)
163
169
  if steam_id == 'STEAM_ID_LAN' || steam_id == 'BOT'
164
170
  raise SteamCondenserError, "Cannot convert SteamID \"#{steam_id}\" to a community ID."
165
171
  elsif steam_id.match(/^STEAM_[0-1]:[0-1]:[0-9]+$/).nil?
@@ -171,6 +177,11 @@ class SteamId
171
177
  steam_id[1] + steam_id[2] * 2 + 76561197960265728
172
178
  end
173
179
 
180
+ class << self
181
+ alias_method :convert_community_id_to_steam_id, :community_id_to_steam_id
182
+ alias_method :convert_steam_id_to_community_id, :steam_id_to_community_id
183
+ end
184
+
174
185
  # Creates a new `SteamId` instance using a SteamID as used on servers
175
186
  #
176
187
  # The SteamID from the server is converted into a 64bit numeric SteamID first
@@ -192,19 +203,23 @@ class SteamId
192
203
  # @param [Boolean] fetch if `true` the Steam ID's data is loaded into the
193
204
  # object
194
205
  def initialize(id, fetch = true)
195
- begin
196
- if id.is_a? Numeric
197
- @steam_id64 = id
198
- else
199
- @custom_url = id.downcase
200
- end
201
-
202
- super(fetch)
203
- rescue REXML::ParseException
204
- raise SteamCondenserError, 'SteamID could not be loaded.'
206
+ if id.is_a? Numeric
207
+ @steam_id64 = id
208
+ else
209
+ @custom_url = id.downcase
205
210
  end
211
+
212
+ super fetch
206
213
  end
207
214
 
215
+ # Returns whether the owner of this SteamID is VAC banned
216
+ #
217
+ # @return [Boolean] `true` if the user has been banned by VAC
218
+ def banned?
219
+ @vac_banned
220
+ end
221
+ alias_method :is_banned?, :banned?
222
+
208
223
  # Returns the base URL for this Steam ID
209
224
  #
210
225
  # This URL is different for Steam IDs having a custom URL.
@@ -212,9 +227,9 @@ class SteamId
212
227
  # @return [String] The base URL for this SteamID
213
228
  def base_url
214
229
  if @custom_url.nil?
215
- "http://steamcommunity.com/profiles/#{@steam_id64}"
230
+ "http://steamcommunity.com/profiles/#@steam_id64"
216
231
  else
217
- "http://steamcommunity.com/id/#{@custom_url}"
232
+ "http://steamcommunity.com/id/#@custom_url"
218
233
  end
219
234
  end
220
235
 
@@ -225,68 +240,70 @@ class SteamId
225
240
  # when it is private
226
241
  # @see Cacheable#fetch
227
242
  def fetch
228
- profile_url = open(base_url + '?xml=1', {:proxy => true})
229
- profile = REXML::Document.new(profile_url.read).root
243
+ begin
244
+ profile = parse "#{base_url}?xml=1"
230
245
 
231
- unless REXML::XPath.first(profile, 'error').nil?
232
- raise SteamCondenserError, profile.elements['error'].text
233
- end
246
+ if profile.key? 'error'
247
+ raise SteamCondenserError, profile['error']
248
+ end
234
249
 
235
- unless REXML::XPath.first(profile, 'privacyMessage').nil?
236
- raise SteamCondenserError, profile.elements['privacyMessage'].text
237
- end
238
-
239
- begin
240
- @nickname = CGI.unescapeHTML profile.elements['steamID'].text
241
- @steam_id64 = profile.elements['steamID64'].text.to_i
242
- @vac_banned = (profile.elements['vacBanned'].text == 1)
243
-
244
- @image_url = profile.elements['avatarIcon'].text[0..-5]
245
- @online_state = profile.elements['onlineState'].text
246
- @privacy_state = profile.elements['privacyState'].text
247
- @state_message = profile.elements['stateMessage'].text
248
- @visibility_state = profile.elements['visibilityState'].text.to_i
249
-
250
- if @privacy_state == 'public'
251
- @custom_url = profile.elements['customURL'].text.downcase
252
- @custom_url = nil if @custom_url.empty?
253
-
254
- unless REXML::XPath.first(profile, 'favoriteGame').nil?
255
- @favorite_game = profile.elements['favoriteGame/name'].text
256
- @favorite_game_hours_played = profile.elements['favoriteGame/hoursPlayed2wk'].text
250
+ if profile.key? 'privacyMessage'
251
+ raise SteamCondenserError, profile['privacyMessage']
252
+ end
253
+
254
+ @nickname = CGI.unescapeHTML profile['steamID']
255
+ @steam_id64 = profile['steamID64'].to_i
256
+ @limited = (profile['isLimitedAccount'].to_i == 1)
257
+ @trade_ban_state = profile['tradeBanState']
258
+ @vac_banned = (profile['vacBanned'].to_i == 1)
259
+
260
+ @image_url = profile['avatarIcon'][0..-5]
261
+ @online_state = profile['onlineState']
262
+ @privacy_state = profile['privacyState']
263
+ @state_message = profile['stateMessage']
264
+ @visibility_state = profile['visibilityState'].to_i
265
+
266
+ if public?
267
+ @custom_url = profile['customURL'].downcase
268
+ @custom_url = nil if @custom_url.empty?
269
+
270
+ if profile.key? 'favoriteGame'
271
+ @favorite_game = profile['favoriteGame']['name']
272
+ @favorite_game_hours_played = profile['favoriteGame']['hoursPlayed2wk']
257
273
  end
258
274
 
259
- @head_line = CGI.unescapeHTML profile.elements['headline'].text
260
- @hours_played = profile.elements['hoursPlayed2Wk'].text.to_f
261
- @location = profile.elements['location'].text
262
- @member_since = Time.parse(profile.elements['memberSince'].text)
263
- @real_name = CGI.unescapeHTML profile.elements['realname'].text
264
- @steam_rating = profile.elements['steamRating'].text.to_f
265
- @summary = CGI.unescapeHTML profile.elements['summary'].text
275
+ @head_line = CGI.unescapeHTML profile['headline'] || ''
276
+ @hours_played = profile['hoursPlayed2Wk'].to_f
277
+ @location = profile['location']
278
+ @member_since = Time.parse profile['memberSince']
279
+ @real_name = CGI.unescapeHTML profile['realname'] || ''
280
+ @steam_rating = profile['steamRating'].to_f
281
+ @summary = CGI.unescapeHTML profile['summary'] || ''
266
282
 
267
283
  @most_played_games = {}
268
- unless REXML::XPath.first(profile, 'mostPlayedGames').nil?
269
- profile.elements.each('mostPlayedGames/mostPlayedGame') do |most_played_game|
270
- @most_played_games[most_played_game.elements['gameName'].text] = most_played_game.elements['hoursPlayed'].text.to_f
284
+ if profile.key? 'mostPlayedGames'
285
+ [profile['mostPlayedGames']['mostPlayedGame']].flatten.each do |most_played_game|
286
+ @most_played_games[most_played_game['gameName']] = most_played_game['hoursPlayed'].to_f
271
287
  end
272
288
  end
273
289
 
274
290
  @groups = []
275
- unless REXML::XPath.first(profile, 'groups').nil?
276
- profile.elements.each('groups/group') do |group|
277
- @groups << SteamGroup.new(group.elements['groupID64'].text.to_i, false)
291
+ if profile.key? 'groups'
292
+ [profile['groups']['group']].flatten.each do |group|
293
+ @groups << SteamGroup.new(group['groupID64'].to_i, false)
278
294
  end
279
295
  end
280
296
 
281
297
  @links = {}
282
- unless REXML::XPath.first(profile, 'weblinks').nil?
283
- profile.elements.each('weblinks/weblink') do |link|
284
- @links[CGI.unescapeHTML link.elements['title'].text] = link.elements['link'].text
298
+ if profile.key? 'weblinks'
299
+ [profile['weblinks']['weblink']].flatten.each do |link|
300
+ @links[CGI.unescapeHTML link['title']] = link['link']
285
301
  end
286
302
  end
287
303
  end
288
304
  rescue
289
- raise SteamCondenserError, 'XML data could not be parsed.'
305
+ raise $! if $!.is_a? SteamCondenserError
306
+ raise SteamCondenserError, 'XML data could not be parsed.', $!.backtrace
290
307
  end
291
308
 
292
309
  super
@@ -300,12 +317,10 @@ class SteamId
300
317
  # @see #friends
301
318
  # @see #initialize
302
319
  def fetch_friends
303
- url = "#{base_url}/friends?xml=1"
304
-
305
320
  @friends = []
306
- friends_data = REXML::Document.new(open(url, {:proxy => true}).read).root
307
- friends_data.elements.each('friends/friend') do |friend|
308
- @friends << SteamId.new(friend.text.to_i, false)
321
+ friends_data = parse "#{base_url}/friends?xml=1"
322
+ friends_data['friends']['friend'].each do |friend|
323
+ @friends << SteamId.new(friend.to_i, false)
309
324
  end
310
325
  end
311
326
 
@@ -317,22 +332,21 @@ class SteamId
317
332
  #
318
333
  # @see #games
319
334
  def fetch_games
320
- url = "#{base_url}/games?xml=1"
321
-
322
335
  @games = {}
323
336
  @playtimes = {}
324
- games_data = REXML::Document.new(open(url, {:proxy => true}).read).root
325
- games_data.elements.each('games/game') do |game_data|
326
- game = SteamGame.new(game_data)
327
- @games[game.app_id] = game
337
+ games_data = parse "#{base_url}/games?xml=1"
338
+ [games_data['games']['game']].flatten.each do |game_data|
339
+ app_id = game_data['appID'].to_i
340
+ game = SteamGame.new app_id, game_data
341
+ @games[app_id] = game
328
342
  recent = total = 0
329
- unless game_data.elements['hoursLast2Weeks'].nil?
330
- recent = game_data.elements['hoursLast2Weeks'].text.to_f
343
+ if game_data.key? 'hoursLast2Weeks'
344
+ recent = game_data['hoursLast2Weeks'].to_f
331
345
  end
332
- unless game_data.elements['hoursOnRecord'].nil?
333
- total = game_data.elements['hoursOnRecord'].text.to_f
346
+ if game_data.key? 'hoursOnRecord'
347
+ total = game_data['hoursOnRecord'].to_f
334
348
  end
335
- @playtimes[game.app_id] = [(recent * 60).to_i, (total * 60).to_i]
349
+ @playtimes[app_id] = [(recent * 60).to_i, (total * 60).to_i]
336
350
  end
337
351
 
338
352
  true
@@ -393,28 +407,31 @@ class SteamId
393
407
  #
394
408
  # @return [String] The URL of the icon-sized avatar
395
409
  def icon_url
396
- "#{@image_url}.jpg"
410
+ "#@image_url.jpg"
397
411
  end
398
412
 
399
- # Returns whether the owner of this SteamID is VAC banned
413
+ # Returns a unique identifier for this Steam ID
400
414
  #
401
- # @return [Boolean] `true` if the user has been banned by VAC
402
- def is_banned?
403
- @vac_banned
415
+ # This is either the 64bit numeric SteamID or custom URL
416
+ #
417
+ # @return [Fixnum, String] The 64bit numeric SteamID or the custom URL
418
+ def id
419
+ @custom_url.nil? ? @steam_id64 : @custom_url
404
420
  end
405
421
 
406
422
  # Returns whether the owner of this SteamId is playing a game
407
423
  #
408
424
  # @return [Boolean] `true` if the user is in-game
409
- def is_in_game?
425
+ def in_game?
410
426
  @online_state == 'in-game'
411
427
  end
428
+ alias_method :is_in_game?, :in_game?
412
429
 
413
- # Returns whether the owner of this SteamID is currently logged into Steam
430
+ # Returns whether this Steam account is limited
414
431
  #
415
- # @return [Boolean] `true` if the user is online
416
- def is_online?
417
- @online_state != 'offline'
432
+ # @return [Boolean] `true` if this account is limited
433
+ def limited?
434
+ @limited
418
435
  end
419
436
 
420
437
  # Returns the URL of the medium-sized version of this user's avatar
@@ -424,6 +441,21 @@ class SteamId
424
441
  "#{@image_url}_medium.jpg"
425
442
  end
426
443
 
444
+ # Returns whether the owner of this SteamID is currently logged into Steam
445
+ #
446
+ # @return [Boolean] `true` if the user is online
447
+ def online?
448
+ @online_state != 'offline'
449
+ end
450
+ alias_method :is_online?, :online?
451
+
452
+ # Returns whether this Steam ID is publicly accessible
453
+ #
454
+ # @return [Boolean] `true` if this Steam ID is public
455
+ def public?
456
+ @privacy_state == 'public'
457
+ end
458
+
427
459
  # Returns the time in minutes this user has played this game in the last two
428
460
  # weeks
429
461
  #
@@ -8,7 +8,7 @@ require 'steam/community/game_class'
8
8
  # Represents the stats for a Team Fortress 2 class for a specific user
9
9
  #
10
10
  # @author Sebastian Staudt
11
- module TF2Class
11
+ class TF2Class
12
12
 
13
13
  include GameClass
14
14
 
@@ -73,20 +73,20 @@ module TF2Class
73
73
 
74
74
  # Creates a new TF2 class instance based on the assigned XML data
75
75
  #
76
- # @param [REXML::Element] class_data The XML data for this class
76
+ # @param [Hash<String, Object>] class_data The XML data for this class
77
77
  def initialize(class_data)
78
- @name = class_data.elements['className'].text
79
- @max_buildings_destroyed = class_data.elements['ibuildingsdestroyed'].text.to_i
80
- @max_captures = class_data.elements['ipointcaptures'].text.to_i
81
- @max_damage = class_data.elements['idamagedealt'].text.to_i
82
- @max_defenses = class_data.elements['ipointdefenses'].text.to_i
83
- @max_dominations = class_data.elements['idominations'].text.to_i
84
- @max_kill_assists = class_data.elements['ikillassists'].text.to_i
85
- @max_kills = class_data.elements['inumberofkills'].text.to_i
86
- @max_revenges = class_data.elements['irevenge'].text.to_i
87
- @max_score = class_data.elements['ipointsscored'].text.to_i
88
- @max_time_alive = class_data.elements['iplaytime'].text.to_i
89
- @play_time = class_data.elements['playtimeSeconds'].text.to_i
78
+ @name = class_data['className']
79
+ @max_buildings_destroyed = class_data['ibuildingsdestroyed'].to_i
80
+ @max_captures = class_data['ipointcaptures'].to_i
81
+ @max_damage = class_data['idamagedealt'].to_i
82
+ @max_defenses = class_data['ipointdefenses'].to_i
83
+ @max_dominations = class_data['idominations'].to_i
84
+ @max_kill_assists = class_data['ikillassists'].to_i
85
+ @max_kills = class_data['inumberofkills'].to_i
86
+ @max_revenges = class_data['irevenge'].to_i
87
+ @max_score = class_data['ipointsscored'].to_i
88
+ @max_time_alive = class_data['iplaytime'].to_i
89
+ @play_time = class_data['playtimeSeconds'].to_i
90
90
  end
91
91
 
92
92
  end
@@ -20,10 +20,10 @@ module TF2ClassFactory
20
20
  # This returns an instance of `TF2Class` or its subclasses `TF2Engineer`,
21
21
  # `TF2Medic`, `TF2Sniper` or `TF2Spy` depending on the given XML data.
22
22
  #
23
- # @param [REXML::Element] class_data The XML data for the class
23
+ # @param [Hash<String, Object>] class_data The XML data for the class
24
24
  # @return [TF2Class] The statistics for the given class data
25
25
  def self.tf2_class(class_data)
26
- case class_data.elements['className'].text
26
+ case class_data['className']
27
27
  when 'Engineer' then
28
28
  return TF2Engineer.new(class_data)
29
29
  when 'Medic' then
@@ -9,9 +9,7 @@ require 'steam/community/tf2/tf2_class'
9
9
  # user
10
10
  #
11
11
  # @author Sebastian Staudt
12
- class TF2Engineer
13
-
14
- include TF2Class
12
+ class TF2Engineer < TF2Class
15
13
 
16
14
  # Returns the maximum number of buildings built by the player in a single
17
15
  # life as an Engineer
@@ -33,13 +31,13 @@ class TF2Engineer
33
31
 
34
32
  # Creates a new instance of the Engineer class based on the given XML data
35
33
  #
36
- # @param [REXML::Element] class_data The XML data for this Engineer
34
+ # @param [Hash<String, Object>] class_data The XML data for this Engineer
37
35
  def initialize(class_data)
38
36
  super class_data
39
37
 
40
- @max_buildings_built = class_data.elements['ibuildingsbuilt'].text.to_i
41
- @max_teleports = class_data.elements['inumteleports'].text.to_i
42
- @max_sentry_kills = class_data.elements['isentrykills'].text.to_i
38
+ @max_buildings_built = class_data['ibuildingsbuilt'].to_i
39
+ @max_teleports = class_data['inumteleports'].to_i
40
+ @max_sentry_kills = class_data['isentrykills'].to_i
43
41
  end
44
42
 
45
43
  end
@@ -46,7 +46,7 @@ class TF2GoldenWrench
46
46
  if @@golden_wrenches.nil?
47
47
  @@golden_wrenches = []
48
48
 
49
- data = MultiJson.decode(WebApi.json('ITFItems_440', 'GetGoldenWrenches', 2), { :symbolize_keys => true })
49
+ data = MultiJson.load(WebApi.json('ITFItems_440', 'GetGoldenWrenches', 2), { :symbolize_keys => true })
50
50
  data[:results][:wrenches].each do |wrench_data|
51
51
  @@golden_wrenches << TF2GoldenWrench.new(wrench_data)
52
52
  end
@@ -8,9 +8,7 @@ require 'steam/community/tf2/tf2_class'
8
8
  # Represents the stats for the Team Fortress 2 Medic class for a specific user
9
9
  #
10
10
  # @author Sebastian Staudt
11
- class TF2Medic
12
-
13
- include TF2Class
11
+ class TF2Medic < TF2Class
14
12
 
15
13
  # Returns the maximum health healed for teammates by the player in a
16
14
  # single life as a Medic
@@ -26,12 +24,12 @@ class TF2Medic
26
24
 
27
25
  # Creates a new instance of the Medic class based on the given XML data
28
26
  #
29
- # @param [REXML::Element] class_data The XML data for this Medic
27
+ # @param [Hash<String, Object>] class_data The XML data for this Medic
30
28
  def initialize(class_data)
31
29
  super class_data
32
30
 
33
- @max_health_healed = class_data.elements['ihealthpointshealed'].text.to_i
34
- @max_ubercharges = class_data.elements['inuminvulnerable'].text.to_i
31
+ @max_health_healed = class_data['ihealthpointshealed'].to_i
32
+ @max_ubercharges = class_data['inuminvulnerable'].to_i
35
33
  end
36
34
 
37
35
  end