The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

Games::AssaultCube::Log::Line - Parses an AssaultCube server log line

SYNOPSIS

        use Games::AssaultCube::Log::Line;
        open( my $fh, "<", "logfile.log" ) or die "Unable to open logfile: $!";
        while ( my $line = <$fh> ) {
                $line =~ s/(?:\n|\r)+//;
                next if ! length $line;
                my $log = Games::AssaultCube::Log::Line->new( $line );

                # play with the data
                print "LOG: " . $log->event . " happened\n";
        }
        close( $fh ) or die "Unable to close logfile: $!";

ABSTRACT

Parses an AssaultCube server log line

DESCRIPTION

This module takes an AssaultCube logfile line as parameter and converts this into an easily-accessed object. Please look at the subclasses for all possible event types. This is the factory which handles the "generic" stuff and the parsing. The returned object actually is a subclass which inherits from Games::AssaultCube::Log::Line::Base and contains the various accessors suited for that event type.

You would need to set up the "fluff" to read the logfile and feed lines into this parser as shown in the SYNOPSIS.

Constructor

The constructor for this class is the "new()" method. The constructor accepts only one argument, the log line to parse. The constructor will return an object or die() if the line is undef/zero-length.

Furthermore, you can supply an optional second argument: the subclass parser. It can be an object or a coderef. Please review the notes below, "Subclassing the parser".

It is important to remember that this class is simply a "factory" that parses the log line and hands the data off to the appropriate subclass. It is this subclass that is actually returned from the constructor. This means this class has no methods/subs/attributes attached to it and you should study the subclasses for details :)

Subclassing the parser

Since AssaultCube is open source, it is feasible for people to modify the server code to output other forms of logs. It makes sense for us to provide a way for others to make use of this code, and extend it to take their log format into account. What follows will be a description on how this is achieved.

In order to subclass the parser, all you need to do is provide either an object or a coderef to the constructor. It will be called before executing the normal parsing code contained in this class. If it's an object, the "parse()" method will be called on it; otherwise the coderef will be called.

The subclass can either return undef or a defined result. If it returns undef then we will continue with the normal code. If it was defined, then it will be returned directly to the caller, bypassing the parsing code. That way your subclass can return anything, from an object to a hashref to a simple "1". The implication of this is that your subclass will be called every time this class is instantiated. The arguments is simply the line to be parsed, just like the constructor of this class. From there your subclass can use the Games::AssaultCube::Log::Line::Base object if desired for it's events or anything else.

NOTE: Since the subclass would process every line, it is desirable to be very fast. It would be smart to design your log extensions so they are immediately detected by the subclass. A normal AssaultCube log line would look something like:

        Team RVSF:  9 players,   63 frags,    0 flags
        Status at 18-02-2009 10:02:56: 19 remote clients, 84.3 send, 5.2 rec (K/sec)
        [199.203.37.253] abcde fragged fghi

It would be extremely beneficial if your "extended" log format includes an easily-recognizable prefix. Some examples would be something like this:

        *LOG* Player "abcde" scored a 10-kill streak
        |EXTLOG| Server restarted
        == Player fghi captured the flag at 3:45 into the game

Then, your subclass's parse() method could check the first few characters of the line and immediately return before doing any extensive regex/split/code on it. Here's a sample parse() method for a subclass that uses the object style and the "==" extended log prefix:

        sub parse {
                my( $self, $line ) = @_;
                if ( substr( $line, 0, 2 ) ne '==' ) {
                        return;
                } else {
                        # Process our own extended log format
                        # Be sure to return a defined result!
                        return 1;
                }
        }

We assume that if you know enough to extend the AssaultCube sources and add your own logs, you know enough to not cause conflicts in the log formats :) Have fun playing around with AssaultCube!

AUTHOR

Apocalypse <apocal@cpan.org>

Torsten Raudssus <torsten@raudssus.de>

Props goes to the BS clan for the support!

This project is sponsored by http://cubestats.net

COPYRIGHT AND LICENSE

Copyright 2009 by Apocalypse

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.