steam-condenser 0.9.0 → 0.10.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.
- data/LICENSE +1 -1
- data/README.md +2 -0
- data/Rakefile +0 -2
- data/VERSION.yml +1 -1
- data/lib/abstract_class.rb +1 -3
- data/lib/exceptions/buffer_underflow_exception.rb +1 -3
- data/lib/exceptions/packet_format_exception.rb +1 -3
- data/lib/exceptions/rcon_no_auth_exception.rb +1 -3
- data/lib/exceptions/timeout_exception.rb +0 -2
- data/lib/steam/community/game_stats.rb +5 -3
- data/lib/steam/community/l4d/abstract_l4d_stats.rb +143 -0
- data/lib/steam/community/l4d/abstract_l4d_weapon.rb +26 -0
- data/lib/steam/community/l4d/l4d2_map.rb +65 -0
- data/lib/steam/community/l4d/l4d2_stats.rb +125 -0
- data/lib/steam/community/l4d/l4d2_weapon.rb +21 -0
- data/lib/steam/community/l4d/l4d_map.rb +2 -0
- data/lib/steam/community/l4d/l4d_stats.rb +5 -115
- data/lib/steam/community/l4d/l4d_weapon.rb +3 -7
- data/lib/steam/community/steam_id.rb +28 -19
- data/lib/steam/community/tf2/tf2_class_factory.rb +1 -3
- data/lib/steam/community/tf2/tf2_engineer.rb +2 -4
- data/lib/steam/community/tf2/tf2_medic.rb +1 -3
- data/lib/steam/community/tf2/tf2_sniper.rb +1 -3
- data/lib/steam/community/tf2/tf2_spy.rb +1 -3
- data/lib/steam/packets/a2a_ack_packet.rb +1 -3
- data/lib/steam/packets/a2a_ping_packet.rb +1 -3
- data/lib/steam/packets/a2m_get_servers_batch2_packet.rb +0 -2
- data/lib/steam/packets/a2s_info_packet.rb +0 -2
- data/lib/steam/packets/a2s_player_packet.rb +1 -3
- data/lib/steam/packets/a2s_rules_packet.rb +1 -3
- data/lib/steam/packets/a2s_serverquery_getchallenge_packet.rb +1 -3
- data/lib/steam/packets/m2a_server_batch_packet.rb +1 -3
- data/lib/steam/packets/rcon/rcon_auth_request.rb +1 -3
- data/lib/steam/packets/rcon/rcon_auth_response.rb +1 -3
- data/lib/steam/packets/rcon/rcon_exec_request.rb +1 -3
- data/lib/steam/packets/rcon/rcon_goldsrc_request.rb +1 -3
- data/lib/steam/packets/rcon/rcon_goldsrc_response.rb +1 -3
- data/lib/steam/packets/rcon/rcon_packet.rb +1 -3
- data/lib/steam/packets/rcon/rcon_packet_factory.rb +1 -3
- data/lib/steam/packets/request_with_challenge.rb +1 -3
- data/lib/steam/packets/s2a_info2_packet.rb +1 -3
- data/lib/steam/packets/s2a_info_base_packet.rb +2 -0
- data/lib/steam/packets/s2a_rules_packet.rb +1 -1
- data/lib/steam/packets/s2c_challenge_packet.rb +1 -3
- data/lib/steam/packets/steam_packet.rb +15 -16
- data/lib/steam/servers/master_server.rb +0 -2
- data/lib/steam/servers/source_server.rb +3 -1
- data/lib/steam-condenser.rb +2 -0
- metadata +21 -19
@@ -3,69 +3,17 @@
|
|
3
3
|
#
|
4
4
|
# Copyright (c) 2009, Sebastian Staudt
|
5
5
|
|
6
|
-
require 'steam/community/
|
6
|
+
require 'steam/community/l4d/abstract_l4d_stats'
|
7
7
|
require 'steam/community/l4d/l4d_explosive'
|
8
8
|
require 'steam/community/l4d/l4d_map'
|
9
9
|
require 'steam/community/l4d/l4d_weapon'
|
10
10
|
|
11
|
-
class L4DStats <
|
12
|
-
|
13
|
-
attr_reader :xml_data
|
11
|
+
class L4DStats < AbstractL4DStats
|
14
12
|
|
15
13
|
# Creates a L4DStats object by calling the super constructor with the game
|
16
|
-
# name "l4d"
|
14
|
+
# name "l4d".
|
17
15
|
def initialize(steam_id)
|
18
16
|
super steam_id, 'l4d'
|
19
|
-
|
20
|
-
if public?
|
21
|
-
@most_recent_game = {}
|
22
|
-
@most_recent_game['difficulty'] = @xml_data.elements['stats/mostrecentgame/difficulty'].text
|
23
|
-
@most_recent_game['escaped'] = (@xml_data.elements['stats/mostrecentgame/bEscaped'].text == 1)
|
24
|
-
@most_recent_game['movie'] = @xml_data.elements['stats/mostrecentgame/movie'].text
|
25
|
-
@most_recent_game['time_played'] = @xml_data.elements['stats/mostrecentgame/time'].text
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
# Returns a Hash of favorites for this user like weapons and character.
|
30
|
-
# If the favorites haven't been parsed already, parsing is done now.
|
31
|
-
def favorites
|
32
|
-
return unless public?
|
33
|
-
|
34
|
-
if @favorites.nil?
|
35
|
-
@favorites = {}
|
36
|
-
@favorites['campaign'] = @xml_data.elements['stats/favorites/campaign'].text
|
37
|
-
@favorites['campaign_percentage'] = @xml_data.elements['stats/favorites/campaignpct'].text.to_i
|
38
|
-
@favorites['character'] = @xml_data.elements['stats/favorites/character'].text
|
39
|
-
@favorites['character_percentage'] = @xml_data.elements['stats/favorites/characterpct'].text.to_i
|
40
|
-
@favorites['level1_weapon'] = @xml_data.elements['stats/favorites/weapon1'].text
|
41
|
-
@favorites['level1_weapon_percentage'] = @xml_data.elements['stats/favorites/weapon1pct'].text.to_i
|
42
|
-
@favorites['level2_weapon'] = @xml_data.elements['stats/favorites/weapon2'].text
|
43
|
-
@favorites['level2_weapon_percentage'] = @xml_data.elements['stats/favorites/weapon2pct'].text.to_i
|
44
|
-
end
|
45
|
-
|
46
|
-
@favorites
|
47
|
-
end
|
48
|
-
|
49
|
-
# Returns a Hash of lifetime statistics for this user like the time played.
|
50
|
-
# If the lifetime statistics haven't been parsed already, parsing is done now.
|
51
|
-
def lifetime_stats
|
52
|
-
return unless public?
|
53
|
-
|
54
|
-
if @lifetime_stats.nil?
|
55
|
-
@lifetime_stats = {}
|
56
|
-
@lifetime_stats['finales_survived'] = @xml_data.elements['stats/lifetime/finales'].text.to_i
|
57
|
-
@lifetime_stats['games_played'] = @xml_data.elements['stats/lifetime/gamesplayed'].text.to_i
|
58
|
-
@lifetime_stats['finales_survived_percentage'] = @lifetime_stats['finales_survived'].to_f / @lifetime_stats['games_played']
|
59
|
-
@lifetime_stats['infected_killed'] = @xml_data.elements['stats/lifetime/infectedkilled'].text.to_i
|
60
|
-
@lifetime_stats['kills_per_hour'] = @xml_data.elements['stats/lifetime/killsperhour'].text.to_f
|
61
|
-
@lifetime_stats['avg_kits_shared'] = @xml_data.elements['stats/lifetime/kitsshared'].text.to_f
|
62
|
-
@lifetime_stats['avg_kits_used'] = @xml_data.elements['stats/lifetime/kitsused'].text.to_f
|
63
|
-
@lifetime_stats['avg_pills_shared'] = @xml_data.elements['stats/lifetime/pillsshared'].text.to_f
|
64
|
-
@lifetime_stats['avg_pills_used'] = @xml_data.elements['stats/lifetime/pillsused'].text.to_f
|
65
|
-
@lifetime_stats['time_played'] = @xml_data.elements['stats/lifetime/timeplayed'].text
|
66
|
-
end
|
67
|
-
|
68
|
-
@lifetime_stats
|
69
17
|
end
|
70
18
|
|
71
19
|
# Returns a Hash of Survival statistics for this user like revived teammates.
|
@@ -74,13 +22,7 @@ class L4DStats < GameStats
|
|
74
22
|
return unless public?
|
75
23
|
|
76
24
|
if @survival_stats.nil?
|
77
|
-
|
78
|
-
@survival_stats['gold_medals'] = @xml_data.elements['stats/survival/goldmedals'].text.to_i
|
79
|
-
@survival_stats['silver_medals'] = @xml_data.elements['stats/survival/silvermedals'].text.to_i
|
80
|
-
@survival_stats['bronze_medals'] = @xml_data.elements['stats/survival/bronzemedals'].text.to_i
|
81
|
-
@survival_stats['rounds_played'] = @xml_data.elements['stats/survival/roundsplayed'].text.to_i
|
82
|
-
@survival_stats['best_time'] = @xml_data.elements['stats/survival/besttime'].text.to_f
|
83
|
-
|
25
|
+
super
|
84
26
|
@survival_stats['maps'] = {}
|
85
27
|
@xml_data.elements.each('stats/survival/maps/*') do |map_data|
|
86
28
|
@survival_stats['maps'][map_data.name] = L4DMap.new(map_data)
|
@@ -90,58 +32,6 @@ class L4DStats < GameStats
|
|
90
32
|
@survival_stats
|
91
33
|
end
|
92
34
|
|
93
|
-
# Returns a Hash of teamplay statistics for this user like revived teammates.
|
94
|
-
# If the teamplay statistics haven't been parsed already, parsing is done now.
|
95
|
-
def teamplay_stats
|
96
|
-
return unless public?
|
97
|
-
|
98
|
-
if @teamplay_stats.nil?
|
99
|
-
@teamplay_stats = {}
|
100
|
-
@teamplay_stats['revived'] = @xml_data.elements['stats/teamplay/revived'].text.to_i
|
101
|
-
@teamplay_stats['most_revived_difficulty'] = @xml_data.elements['stats/teamplay/reviveddiff'].text
|
102
|
-
@teamplay_stats['avg_revived'] = @xml_data.elements['stats/teamplay/revivedavg'].text.to_f
|
103
|
-
@teamplay_stats['avg_was_revived'] = @xml_data.elements['stats/teamplay/wasrevivedavg'].text.to_f
|
104
|
-
@teamplay_stats['protected'] = @xml_data.elements['stats/teamplay/protected'].text.to_i
|
105
|
-
@teamplay_stats['most_protected_difficulty'] = @xml_data.elements['stats/teamplay/protecteddiff'].text
|
106
|
-
@teamplay_stats['avg_protected'] = @xml_data.elements['stats/teamplay/protectedavg'].text.to_f
|
107
|
-
@teamplay_stats['avg_was_protected'] = @xml_data.elements['stats/teamplay/wasprotectedavg'].text.to_f
|
108
|
-
@teamplay_stats['friendly_fire_damage'] = @xml_data.elements['stats/teamplay/ffdamage'].text.to_i
|
109
|
-
@teamplay_stats['most_friendly_fire_difficulty'] = @xml_data.elements['stats/teamplay/ffdamagediff'].text
|
110
|
-
@teamplay_stats['avg_friendly_fire_damage'] = @xml_data.elements['stats/teamplay/ffdamageavg'].text.to_f
|
111
|
-
end
|
112
|
-
|
113
|
-
@teamplay_stats
|
114
|
-
end
|
115
|
-
|
116
|
-
# Returns a Hash of Versus statistics for this user like percentage of rounds
|
117
|
-
# won.
|
118
|
-
# If the Versus statistics haven't been parsed already, parsing is done now.
|
119
|
-
def versus_stats
|
120
|
-
return unless public?
|
121
|
-
|
122
|
-
if @versus_stats.nil?
|
123
|
-
@versus_stats = {}
|
124
|
-
@versus_stats['games_played'] = @xml_data.elements['stats/versus/gamesplayed'].text.to_i
|
125
|
-
@versus_stats['games_completed'] = @xml_data.elements['stats/versus/gamescompleted'].text.to_i
|
126
|
-
@versus_stats['finales_survived'] = @xml_data.elements['stats/versus/finales'].text.to_i
|
127
|
-
@versus_stats['finales_survived_percentage'] = @versus_stats['finales_survived'].to_f / @versus_stats['games_played']
|
128
|
-
@versus_stats['points'] = @xml_data.elements['stats/versus/points'].text.to_i
|
129
|
-
@versus_stats['most_points_infected'] = @xml_data.elements['stats/versus/pointsas'].text
|
130
|
-
@versus_stats['games_won'] = @xml_data.elements['stats/versus/gameswon'].text.to_i
|
131
|
-
@versus_stats['games_lost'] = @xml_data.elements['stats/versus/gameslost'].text.to_i
|
132
|
-
@versus_stats['highest_survivor_score'] = @xml_data.elements['stats/versus/survivorscore'].text.to_i
|
133
|
-
|
134
|
-
%w(boomer hunter smoker tank).each do |infected|
|
135
|
-
@versus_stats[infected] = {}
|
136
|
-
@versus_stats[infected]['special'] = @xml_data.elements["stats/versus/#{infected}special"].text.to_i
|
137
|
-
@versus_stats[infected]['most_damage'] = @xml_data.elements["stats/versus/#{infected}dmg"].text.to_i
|
138
|
-
@versus_stats[infected]['avg_lifespan'] = @xml_data.elements["stats/versus/#{infected}lifespan"].text.to_i
|
139
|
-
end
|
140
|
-
end
|
141
|
-
|
142
|
-
@versus_stats
|
143
|
-
end
|
144
|
-
|
145
35
|
# Returns a Hash of L4DWeapon for this user containing all Left4Dead weapons.
|
146
36
|
# If the weapons haven't been parsed already, parsing is done now.
|
147
37
|
def weapon_stats
|
@@ -150,7 +40,7 @@ class L4DStats < GameStats
|
|
150
40
|
if @weapon_stats.nil?
|
151
41
|
@weapon_stats = {}
|
152
42
|
@xml_data.elements.each('stats/weapons/*') do |weapon_data|
|
153
|
-
unless
|
43
|
+
unless %w{molotov pipes}.include? weapon_data.name
|
154
44
|
weapon = L4DWeapon.new(weapon_data)
|
155
45
|
else
|
156
46
|
weapon = L4DExplosive.new(weapon_data)
|
@@ -3,9 +3,9 @@
|
|
3
3
|
#
|
4
4
|
# Copyright (c) 2009, Sebastian Staudt
|
5
5
|
|
6
|
-
require 'steam/community/
|
6
|
+
require 'steam/community/l4d/abstract_l4d_weapon'
|
7
7
|
|
8
|
-
class L4DWeapon <
|
8
|
+
class L4DWeapon < AbstractL4DWeapon
|
9
9
|
|
10
10
|
attr_reader :accuracy, :headshots_percentage, :kill_percentage
|
11
11
|
|
@@ -13,11 +13,7 @@ class L4DWeapon < GameWeapon
|
|
13
13
|
def initialize(weapon_data)
|
14
14
|
super weapon_data
|
15
15
|
|
16
|
-
@
|
17
|
-
@headshots_percentage = weapon_data.elements['headshots'].text
|
18
|
-
@id = weapon_data.name
|
19
|
-
@kill_percentage = weapon_data.elements['killpct'].text
|
20
|
-
@shots = weapon_data.elements['shots'].text.to_i
|
16
|
+
@kill_percentage = weapon_data.elements['killpct'].text
|
21
17
|
end
|
22
18
|
|
23
19
|
end
|
@@ -1,7 +1,7 @@
|
|
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-
|
4
|
+
# Copyright (c) 2008-2010, Sebastian Staudt
|
5
5
|
|
6
6
|
require 'open-uri'
|
7
7
|
require 'rexml/document'
|
@@ -23,6 +23,21 @@ class SteamId
|
|
23
23
|
:real_name, :state_message, :steam_id64, :steam_rating,
|
24
24
|
:steam_rating_text, :summary, :vac_banned, :visibility_state
|
25
25
|
|
26
|
+
# Converts the 64bit SteamID +community_id+ as used and reported by the Steam
|
27
|
+
# Community to a SteamID reported by game servers
|
28
|
+
def self.convert_community_id_to_steam_id(community_id)
|
29
|
+
steam_id1 = community_id % 2
|
30
|
+
steam_id2 = community_id - 76561197960265728
|
31
|
+
|
32
|
+
unless steam_id2 > 0
|
33
|
+
raise SteamCondenserException.new("SteamID #{community_id} is too small.")
|
34
|
+
end
|
35
|
+
|
36
|
+
steam_id2 = (steam_id2 - steam_id1) / 2
|
37
|
+
|
38
|
+
"STEAM_0:#{steam_id1}:#{steam_id2}"
|
39
|
+
end
|
40
|
+
|
26
41
|
# Converts the SteamID +steam_id+ as reported by game servers to a 64bit
|
27
42
|
# SteamID
|
28
43
|
def self.convert_steam_id_to_community_id(steam_id)
|
@@ -79,6 +94,10 @@ class SteamId
|
|
79
94
|
raise SteamCondenserException.new(profile.elements['error'].text)
|
80
95
|
end
|
81
96
|
|
97
|
+
unless REXML::XPath.first(profile, 'privacyMessage').nil?
|
98
|
+
raise SteamCondenserException.new(profile.elements['privacyMessage'].text)
|
99
|
+
end
|
100
|
+
|
82
101
|
@image_url = profile.elements['avatarIcon'].text[0..-5]
|
83
102
|
@online_state = profile.elements['onlineState'].text
|
84
103
|
@privacy_state = profile.elements['privacyState'].text
|
@@ -91,6 +110,7 @@ class SteamId
|
|
91
110
|
# Only public profiles can be scanned for further information
|
92
111
|
if @privacy_state == 'public'
|
93
112
|
@custom_url = profile.elements['customURL'].text.downcase
|
113
|
+
@custom_url = nil if @custom_url.empty?
|
94
114
|
|
95
115
|
# The favorite game cannot be set since 10/10/2008, but old profiles
|
96
116
|
# still have this. May be removed in a future version.
|
@@ -147,28 +167,17 @@ class SteamId
|
|
147
167
|
|
148
168
|
# Fetches the games this user owns
|
149
169
|
def fetch_games
|
150
|
-
|
151
|
-
require 'hpricot'
|
152
|
-
|
153
|
-
url = "#{base_url}/games"
|
170
|
+
url = "#{base_url}/games?xml=1"
|
154
171
|
|
155
172
|
@games = {}
|
156
|
-
games_data =
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
stats = game.next_sibling
|
161
|
-
if stats.name == 'br'
|
173
|
+
games_data = REXML::Document.new(open(url, {:proxy => true}).read).root
|
174
|
+
games_data.elements.each('games/game') do |game|
|
175
|
+
game_name = game.elements['name'].text
|
176
|
+
if game.elements['globalStatsLink'].nil?
|
162
177
|
@games[game_name] = false
|
163
178
|
else
|
164
|
-
|
165
|
-
|
166
|
-
@games[game_name] = false
|
167
|
-
else
|
168
|
-
stats = stats.siblings_at(2)[0]
|
169
|
-
friendly_name = stats['href'].match(/http:\/\/steamcommunity.com\/stats\/([0-9a-zA-Z:]+)\/achievements\//)[1]
|
170
|
-
@games[game_name] = friendly_name.downcase
|
171
|
-
end
|
179
|
+
friendly_name = game.elements['globalStatsLink'].text.match(/http:\/\/steamcommunity.com\/stats\/([0-9a-zA-Z:]+)\/achievements\//)[1]
|
180
|
+
@games[game_name] = friendly_name.downcase
|
172
181
|
end
|
173
182
|
end
|
174
183
|
|
@@ -1,9 +1,7 @@
|
|
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, Sebastian Staudt
|
5
|
-
#
|
6
|
-
# $Id$
|
4
|
+
# Copyright (c) 2008-2009, Sebastian Staudt
|
7
5
|
|
8
6
|
require "abstract_class"
|
9
7
|
require "steam/community/tf2/tf2_class"
|
@@ -1,16 +1,14 @@
|
|
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, Sebastian Staudt
|
5
|
-
#
|
6
|
-
# $Id$
|
4
|
+
# Copyright (c) 2008-2009, Sebastian Staudt
|
7
5
|
|
8
6
|
require "steam/community/tf2/tf2_class"
|
9
7
|
|
10
8
|
# Represents the stats for the Team Fortress 2 engineer class for a specific
|
11
9
|
# user
|
12
10
|
class TF2Engineer < TF2Class
|
13
|
-
|
11
|
+
|
14
12
|
attr_reader :max_buildings_built, :max_teleports, :max_sentry_kills
|
15
13
|
|
16
14
|
# Creates a new instance of TF2Engineer based on the assigned XML data
|
@@ -1,9 +1,7 @@
|
|
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, Sebastian Staudt
|
5
|
-
#
|
6
|
-
# $Id$
|
4
|
+
# Copyright (c) 2008-2009, Sebastian Staudt
|
7
5
|
|
8
6
|
require "steam/community/tf2/tf2_class"
|
9
7
|
|
@@ -1,9 +1,7 @@
|
|
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, Sebastian Staudt
|
5
|
-
#
|
6
|
-
# $Id$
|
4
|
+
# Copyright (c) 2008-2009, Sebastian Staudt
|
7
5
|
|
8
6
|
require "steam/community/tf2/tf2_class"
|
9
7
|
|
@@ -1,9 +1,7 @@
|
|
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, Sebastian Staudt
|
5
|
-
#
|
6
|
-
# $Id$
|
4
|
+
# Copyright (c) 2008-2009, Sebastian Staudt
|
7
5
|
|
8
6
|
require "steam/community/tf2/tf2_class"
|
9
7
|
|
@@ -1,9 +1,7 @@
|
|
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, Sebastian Staudt
|
5
|
-
#
|
6
|
-
# $Id$
|
4
|
+
# Copyright (c) 2008-2009, Sebastian Staudt
|
7
5
|
|
8
6
|
require "steam/packets/request_with_challenge"
|
9
7
|
require "steam/packets/steam_packet"
|
@@ -1,9 +1,7 @@
|
|
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, Sebastian Staudt
|
5
|
-
#
|
6
|
-
# $Id$
|
4
|
+
# Copyright (c) 2008-2009, Sebastian Staudt
|
7
5
|
|
8
6
|
require "steam/packets/request_with_challenge"
|
9
7
|
require "steam/packets/steam_packet"
|
@@ -1,9 +1,7 @@
|
|
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, Sebastian Staudt
|
5
|
-
#
|
6
|
-
# $Id$
|
4
|
+
# Copyright (c) 2008-2009, Sebastian Staudt
|
7
5
|
|
8
6
|
require "steam/packets/rcon/rcon_packet"
|
9
7
|
|
@@ -1,9 +1,7 @@
|
|
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, Sebastian Staudt
|
5
|
-
#
|
6
|
-
# $Id$
|
4
|
+
# Copyright (c) 2008-2009, Sebastian Staudt
|
7
5
|
|
8
6
|
require "steam/packets/rcon/rcon_packet"
|
9
7
|
|
@@ -1,9 +1,7 @@
|
|
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, Sebastian Staudt
|
5
|
-
#
|
6
|
-
# $Id$
|
4
|
+
# Copyright (c) 2008-2009, Sebastian Staudt
|
7
5
|
|
8
6
|
require "steam/packets/rcon/rcon_packet"
|
9
7
|
|
@@ -1,9 +1,7 @@
|
|
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, Sebastian Staudt
|
5
|
-
#
|
6
|
-
# $Id$
|
4
|
+
# Copyright (c) 2008-2009, Sebastian Staudt
|
7
5
|
|
8
6
|
require "abstract_class"
|
9
7
|
require "steam/packets/steam_packet"
|
@@ -1,9 +1,7 @@
|
|
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, Sebastian Staudt
|
5
|
-
#
|
6
|
-
# $Id$
|
4
|
+
# Copyright (c) 2008-2009, Sebastian Staudt
|
7
5
|
|
8
6
|
require "abstract_class"
|
9
7
|
require "byte_buffer"
|
@@ -1,9 +1,7 @@
|
|
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, Sebastian Staudt
|
5
|
-
#
|
6
|
-
# $Id$
|
4
|
+
# Copyright (c) 2008-2009, Sebastian Staudt
|
7
5
|
|
8
6
|
# This module implements a to_s method for request packets which send a challenge number
|
9
7
|
module RequestWithChallenge
|
@@ -1,9 +1,7 @@
|
|
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, Sebastian Staudt
|
5
|
-
#
|
6
|
-
# $Id$
|
4
|
+
# Copyright (c) 2008-2009, Sebastian Staudt
|
7
5
|
|
8
6
|
require "steam/packets/s2a_info_base_packet"
|
9
7
|
|
@@ -1,48 +1,47 @@
|
|
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, Sebastian Staudt
|
5
|
-
#
|
6
|
-
# $Id$
|
4
|
+
# Copyright (c) 2008-2010, Sebastian Staudt
|
7
5
|
|
8
6
|
# This class represents a packet used by the Source query protocol
|
9
7
|
class SteamPacket
|
10
|
-
|
11
|
-
A2S_INFO_HEADER = 0x54
|
12
|
-
S2A_INFO2_HEADER = 0x49
|
13
|
-
A2A_PING_HEADER = 0x69
|
8
|
+
|
14
9
|
A2A_ACK_HEADER = 0x6A
|
10
|
+
A2A_PING_HEADER = 0x69
|
11
|
+
A2M_GET_SERVERS_BATCH2_HEADER = 0x31
|
12
|
+
A2S_INFO_HEADER = 0x54
|
15
13
|
A2S_PLAYER_HEADER = 0x55
|
16
|
-
S2A_PLAYER_HEADER = 0x44
|
17
14
|
A2S_RULES_HEADER = 0x56
|
18
|
-
S2A_RULES_HEADER = 0x45
|
19
15
|
A2S_SERVERQUERY_GETCHALLENGE_HEADER = 0x57
|
20
|
-
S2C_CHALLENGE_HEADER = 0x41
|
21
|
-
A2M_GET_SERVERS_BATCH2_HEADER = 0x31
|
22
16
|
M2A_SERVER_BATCH_HEADER = 0x66
|
23
|
-
S2C_CONNREJECT_HEADER = 0x39
|
24
17
|
RCON_GOLDSRC_CHALLENGE_HEADER = 0x63
|
25
18
|
RCON_GOLDSRC_NO_CHALLENGE_HEADER = 0x39
|
26
19
|
RCON_GOLDSRC_RESPONSE_HEADER = 0x6c
|
20
|
+
S2A_INFO_DETAILED_HEADER = 0x6D
|
21
|
+
S2A_INFO2_HEADER = 0x49
|
22
|
+
S2A_PLAYER_HEADER = 0x44
|
23
|
+
S2A_RULES_HEADER = 0x45
|
24
|
+
S2C_CONNREJECT_HEADER = 0x39
|
25
|
+
S2C_CHALLENGE_HEADER = 0x41
|
27
26
|
|
28
27
|
# Creates a new SteamPacket object with given header and content data
|
29
28
|
def initialize(header_data, content_data = "")
|
30
29
|
@content_data = ByteBuffer.new content_data
|
31
30
|
@header_data = header_data
|
32
31
|
end
|
33
|
-
|
32
|
+
|
34
33
|
# Returns a packed string representing the packet's data
|
35
34
|
#
|
36
35
|
# TODO Has to automatically split packets greater than 1400 bytes
|
37
36
|
def to_s
|
38
37
|
packet_data = [0xFF, 0xFF, 0xFF].pack("ccc")
|
39
|
-
|
38
|
+
|
40
39
|
unless @split_packet
|
41
40
|
packet_data << [0xFF].pack("c")
|
42
41
|
else
|
43
42
|
packet_data << [0xFE].pack("c")
|
44
43
|
end
|
45
|
-
|
44
|
+
|
46
45
|
return packet_data << [@header_data, @content_data.array].pack("ca*")
|
47
|
-
end
|
46
|
+
end
|
48
47
|
end
|
@@ -17,7 +17,9 @@ class SourceServer < GameServer
|
|
17
17
|
def self.split_player_status(player_status)
|
18
18
|
player_data = player_status.match(/# *(\d+) +"(.*)" +(.*)/).to_a[1..-1]
|
19
19
|
player_data[2] = player_data[2].split
|
20
|
-
player_data.flatten
|
20
|
+
player_data.flatten!
|
21
|
+
player_data.delete_at(3)
|
22
|
+
player_data
|
21
23
|
end
|
22
24
|
|
23
25
|
def initialize(ip_address, port_number = 27015)
|