File Coverage

blib/lib/Games/AssaultCube/ServerQuery/Response.pm
Criterion Covered Total %
statement 1 3 33.3
branch n/a
condition n/a
subroutine 1 1 100.0
pod n/a
total 2 4 50.0


line stmt bran cond sub pod time code
1             # Declare our package
2             package Games::AssaultCube::ServerQuery::Response;
3              
4             # import the Moose stuff
5 1     1   2280 use Moose;
  0            
  0            
6             use MooseX::StrictConstructor;
7              
8             # Initialize our version
9             use vars qw( $VERSION );
10             $VERSION = '0.04';
11              
12             # get some utility stuff
13             use Games::AssaultCube::Utils qw( parse_pingresponse default_port getpongflag stripcolors );
14              
15             # This is a bit "weird" but very convenient, ha!
16             with 'Games::AssaultCube::Log::Line::Base::GameMode';
17              
18             # TODO improve validation for everything here, ha!
19              
20             has 'server' => (
21             isa => 'Str',
22             is => 'ro',
23             required => 1,
24             );
25              
26             has 'port' => (
27             isa => 'Int',
28             is => 'ro',
29             required => 1,
30             );
31              
32             has 'pingtime' => (
33             isa => 'Int',
34             is => 'ro',
35             required => 1,
36             );
37              
38             has 'query' => (
39             isa => 'Int',
40             is => 'ro',
41             required => 1,
42             );
43              
44             has 'protocol' => (
45             isa => 'Int',
46             is => 'ro',
47             required => 1,
48             );
49              
50             has 'players' => (
51             isa => 'Int',
52             is => 'ro',
53             required => 1,
54             );
55              
56             has 'minutes_left' => (
57             isa => 'Int',
58             is => 'ro',
59             required => 1,
60             );
61              
62             has 'map' => (
63             isa => 'Str',
64             is => 'ro',
65             required => 1,
66             );
67              
68             has 'desc' => (
69             isa => 'Str',
70             is => 'ro',
71             required => 1,
72             );
73              
74             has 'desc_nocolor' => (
75             isa => 'Str',
76             is => 'ro',
77             lazy => 1,
78             default => sub {
79             my $self = shift;
80             return stripcolors( $self->desc );
81             },
82             );
83              
84             has 'max_players' => (
85             isa => 'Int',
86             is => 'ro',
87             required => 1,
88             );
89              
90             has 'pong' => (
91             isa => 'Int',
92             is => 'ro',
93             default => 0,
94             );
95              
96             has 'pong_name' => (
97             isa => 'Str',
98             is => 'ro',
99             lazy => 1,
100             default => sub {
101             my $self = shift;
102             return getpongflag( $self->pong );
103             },
104             );
105              
106             has 'player_list' => (
107             isa => 'ArrayRef[Str]',
108             is => 'ro',
109             default => sub { [] },
110             );
111              
112             has 'is_full' => (
113             isa => 'Bool',
114             is => 'ro',
115             lazy => 1,
116             default => sub {
117             my $self = shift;
118             if ( $self->players == $self->max_players ) {
119             return 1;
120             } else {
121             return 0;
122             }
123             },
124             );
125              
126             has 'datagram' => (
127             isa => 'Str',
128             is => 'ro',
129             required => 1,
130             );
131              
132             has 'tohash' => (
133             isa => 'HashRef',
134             is => 'ro',
135             lazy => 1,
136             default => sub {
137             my $self = shift;
138             my $data = {};
139              
140             foreach my $attr ( qw( timestamp gamemode server port pingtime protocol players minutes_left map desc max_players ) ) {
141             $data->{ $attr } = $self->$attr();
142             }
143              
144             # extra data
145             if ( scalar @{ $self->player_list } ) {
146             $data->{player_list} = [ @{ $self->player_list } ];
147             } else {
148             $data->{player_list} = [];
149             }
150              
151             return $data;
152             },
153             );
154              
155             has 'timestamp' => (
156             isa => 'Int',
157             is => 'ro',
158             default => sub {
159             scalar time();
160             },
161             );
162              
163             sub BUILDARGS {
164             my $class = shift;
165              
166             # Normally, we would be created by Games::AssaultCube::ServerQuery and contain 2 args
167             if ( @_ == 2 && ref $_[0] ) {
168             if ( ref( $_[0] ) eq 'Games::AssaultCube::ServerQuery' ) {
169             # call the parse method
170             return {
171             server => $_[0]->server,
172             port => $_[0]->port,
173             datagram => $_[1],
174             %{ parse_pingresponse( $_[1] ) },
175             };
176             } elsif ( ref( $_[0] ) eq 'POE::Component::AssaultCube::ServerQuery' ) {
177             # parse it a bit differently
178             return {
179             server => $_[1]->{addr},
180             port => $_[1]->{port},
181             datagram => $_[1]->{payload}->[0],
182             %{ parse_pingresponse( $_[1]->{payload}->[0] ) },
183             };
184             } else {
185             die "unknown arguments";
186             }
187             } else {
188             return $class->SUPER::BUILDARGS(@_);
189             }
190             }
191              
192             # from Moose::Manual::BestPractices
193             no Moose;
194             __PACKAGE__->meta->make_immutable;
195              
196             1;
197             __END__
198              
199             =for stopwords CTF TDM desc gamemode pingtime pingmode pongflag pongflags tohash pong timestamp
200              
201             =head1 NAME
202              
203             Games::AssaultCube::ServerQuery::Response - Holds the various data from a ServerQuery response
204              
205             =head1 SYNOPSIS
206              
207             use Games::AssaultCube::ServerQuery;
208             my $query = Games::AssaultCube::ServerQuery->new( 'my.server.com' );
209             #my $query = Games::AssaultCube::ServerQuery->new( 'my.server.com', 12345 );
210             #my $query = Games::AssaultCube::ServerQuery->new({ server => 'foo.com', port => 12345, timeout => 5 });
211             my $response = $query->run;
212             if ( defined $response ) {
213             print "Server is running with " . $response->players . " players\n";
214             } else {
215             print "Server is not responding!\n";
216             }
217              
218             =head1 ABSTRACT
219              
220             This module holds the various data from a ServerQuery response.
221              
222             =head1 DESCRIPTION
223              
224             This module holds the response data from an AssaultCube ServerQuery. Normally you will not use this class
225             directly, but via the L<Games::AssaultCube::ServerQuery> class.
226              
227             =head2 Attributes
228              
229             You can get the various data by fetching the attribute. Valid attributes are:
230              
231             =head3 server
232              
233             The server hostname/ip
234              
235             =head3 port
236              
237             The server port
238              
239             WARNING: AssaultCube uses $port+1 for the query port. Please do not do pass $port+1 to the constructor,
240             we do it internally. Maybe in the future AC will use $port+2 or another system, so let us deal with it :)
241              
242             =head3 pingtime
243              
244             The AssaultCube-specific pingtime counter
245              
246             =head3 query
247              
248             The AssaultCube-specific query number we used to PING the server
249              
250             =head3 protocol
251              
252             The AssaultCube server protocol version
253              
254             =head3 gamemode
255              
256             The numeric AssaultCube gamemode ( look at L<Games::AssaultCube::Utils> for more info )
257              
258             P.S. It's better to use the gamemode_fullname or gamemode_name accessors
259              
260             =head3 gamemode_name
261              
262             The gamemode name ( CTF, TDM, etc )
263              
264             =head3 gamemode_fullname
265              
266             The full gamemode name ( "capture the flag", "team one shot one kill", etc )
267              
268             =head3 players
269              
270             The number of players currently on the server
271              
272             =head3 minutes_left
273              
274             The number of minutes left on the server
275              
276             =head3 map
277              
278             The map that's running on the server
279              
280             =head3 desc
281              
282             The description of the server
283              
284             =head3 desc_nocolor
285              
286             The description of the server, with any AssaultCube-specific colors removed
287              
288             =head3 max_players
289              
290             The maximum number of players this server can accept
291              
292             =head3 pong
293              
294             The AssaultCube-specific pongflags number
295              
296             P.S. It's better to use the pong_name accessor
297              
298             =head3 pong_name
299              
300             The AssaultCube-specific pongflag name
301              
302             =head3 player_list
303              
304             An arrayref of players on the server
305              
306             P.S. Don't forget to enable get_players in the constructor to L<Games::AssaultCube::ServerQuery>, it
307             defaults to an empty arrayref.
308              
309             =head3 is_full
310              
311             Returns a boolean value whether the server is full or not
312              
313             =head3 datagram
314              
315             The actual packet we received from the server
316              
317             =head3 tohash
318              
319             A convenience accessor returning "vital" data in a hashref for easy usage
320              
321             =head3 timestamp
322              
323             The UNIX timestamp when this response object was generated
324              
325             =head1 AUTHOR
326              
327             Apocalypse E<lt>apocal@cpan.orgE<gt>
328              
329             Props goes to Getty and the BS clan for the support!
330              
331             This project is sponsored by L<http://cubestats.net>
332              
333             =head1 COPYRIGHT AND LICENSE
334              
335             Copyright 2009 by Apocalypse
336              
337             This library is free software; you can redistribute it and/or modify
338             it under the same terms as Perl itself.
339              
340             =cut