=head1 NAME

Minecraft::RCON - RCON remote console communication with Minecraft servers

=head1 VERSION

Version 1.04

=head1 SYNOPSIS

    use Minecraft::RCON;

    my $rcon = Minecraft::RCON->new( { password => 'secret' } );

    eval { $rcon->connect };
    die "Connection failed: $@" if $@;

    my $response;
    eval { $response = $rcon->command('help') };
    say $@ ? "Error: $@" : "Response: $response";

    $rcon->disconnect;

=head1 DESCRIPTION

C<Minecraft::RCON> provides a nice object interface for talking to Mojang AB's
game Minecraft. Intended for use with their multiplayer servers, specifically
I<your> multiplayer server, as you will need the correct RCON password, and
RCON must be enabled on said server.

=head1 CONSTRUCTOR

=head2 new( %options )

Create a new RCON object. Note we do not connect automatically; see
C<connect()> for that. The properties and their defaults are shown below:

    my $rcon = Minecraft::RCON->new({
        address         => '127.0.0.1',
        port            => 25575,
        password        => '',
        color_mode      => 'strip',
        error_mode      => 'error',
    });

We will C<carp()> but not die in the event that any unknown options are
provided.

=over 4

=item address

The hostname or IP address to connect to.

=item port

The TCP port number to connect to.

=item password

The plaintext password used to authenticate. This password must match the
C<rcon.password=> line in the F<server.properties> file for your server.

=item color_mode

The color mode controls how C<Minecraft::RCON> handles color codes sent back
by the Minecraft server. It must be one of C<strip>, C<convert>, or C<ignore>.
constants. See C<color_mode()> for more information.

=back

=head1 METHODS

=head2 connect

    eval { $rcon->connect }; # $@ will be set on error

Attempt to connect to the configured address and port, and issue the
configured password for authentication.

If already connected, returns C<undef> (nothing to be done).

This method will C<croak> if the connection fails for any reason.
Otherwise, returns a true value.

=head2 connected

    say "We are connected!" if $rcon->connected;

Returns true if we have a connected socket, false otherwise. Note that we have
no way to tell if there is a misbehaving Minecraft server on the other
side of that socket, so it is entirely possible for this command (or
C<connect()>) to succeed, but C<command()> calls to fail.

=head2 disconnect

    $rcon->disconnect;

Disconnects from the server by closing the socket. Always succeeds.

=head2 command( $command, [ $color_mode ] )

    my $response = $rcon->command("data get block $x $y $z");
    my $ansi = $rcon->command('list', 'convert');

Sends the C<$command> to the Minecraft server, and synchronously waits for the
response. This method is capable of handling fragmented responses (spread over
several response packets), and will concatenate them all before returning the
result.

The resulting server response will have its color codes stripped, converted,
or ignored, according to the current C<color_mode()> setting, unless a
C<$color_mode> is given, which will override the current setting for this
command only.

=head2 color_mode( $color_mode, [ $code ] )

    $rcon->color_mode('strip');

When a command response is received, the color codes it contains can be
stripped, converted to ANSI, or left alone, depending on this setting.

C<$color_mode> is optional, unless C<$code> is also specified.
The valid modes are as follows:

=over 10

=item strip

Strip any color codes, returning the plaintext.

=item convert

Convert any color codes to the equivalent ANSI escape sequences, suitable for
display in a terminal.

=item ignore

Ignore color codes, returning the full command response verbatim.

=back

The current mode will be returned.

If C<$code> is specified and is a C<CODE> ref, C<color_mode()> will apply the
new color mode, run C<$code-E<gt>()>, and then restore the original color
mode. This is useful when you use one color mode most of the time, but have
sections of code requiring a different mode:

Example usage:

    # Color mode is 'convert'
    $rcon->color_mode(strip => sub {
        my $plaintext = $rcon->command('...');
    });

But see also C<command($cmd, $mode)> for running single commands with
another color mode.


=head2 color_convert( $string, [ $color_mode ] )

    my $response = $rcon->command('list');
    my ($strip, $ansi) = map { $rcon->color_convert($response, $_) }
        qw<strip convert>;

This method is used internally by C<command()> to convert command responses as
configured in the object. However, C<color_convert()> itself may be useful in
some applications where a stripped version of the response may be needed for
parsing, while an ANSI version may be desired for display to a terminal, for
example, without having to run the command itself (with possible side-effects)
a second time. For C<color_convert()> to do anything meaningful, your object's
C<color_mode> should be set to C<ignore>.

=head1 ERROR HANDLING

This module C<croak>s (see L<Carp>) for almost all errors.
When an error does not affect control flow, we will C<carp> instead.

Thus, C<command()> and C<connect()>, at minimum, should be wrapped in block
C<eval>:

    eval { $result = $rcon->command('list'); };
    warn "I don't know who is online because: $@" if $@;

If a little extra syntactic sugar is desired, you can use an exception handler
like L<Try::Tiny> instead:

    use Try::Tiny;

    try {
        $result = $rcon->command('list');
    } catch {
        warn "I don't know who is online because: $_";
    }

=head1 DEPRECATED METHODS

The following methods have been deprecated. They will issue a warning to
STDOUT when called, and will be removed in a future release.

=head2 convert_color ( $enable )

If C<$enable> is a true value, change the color mode to C<convert>.
Returns 1 if the current color mode is C<convert>, undef otherwise.

B<Deprecated.> Use C<color_mode('convert')> instead.

=head2 strip_color

If C<$enable> is a true value, change the color mode to C<strip>.
Returns 1 if the current color mode is C<strip>, undef otherwise.

B<Deprecated.> Use C<color_mode('strip')> instead.

=head1 SUPPORT

=over 4

=item L<https://github.com/rjt-pl/Minecraft-RCON.git>: Source code repository

=item L<https://github.com/rjt-pl/Minecraft-RCON/issues>: Bug reports and feature requests

=back

=head1 SEE ALSO

=over 4

=item L<Net::RCON::Minecraft> for an alternative API

=item L<Terminal::ANSIColor>, L<IO::Socket::INET>

=item L<https://developer.valvesoftware.com/wiki/Source_RCON_Protocol>

=item L<https://wiki.vg/RCON>

=back

=head1 AFFILIATION WITH MOJANG

I<Note from original author, Fredrik Vold:>

I am in no way affiliated with Mojang or the development of Minecraft.
I'm simply a fan of their work, and a server admin myself.  I needed
some RCON magic for my servers website, and there was no perl module.

It is important that everyone using this module understands that if
Mojang changes the way RCON works, I won't be notified any sooner than
anyone else, and I have no special avenue of connection with them.

=head1 LICENSE

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

L<http://dev.perl.org/licenses/artistic.html>

=head1 AUTHORS

=over 4

=item B<Ryan Thompson> C<E<lt>rjt@cpan.orgE<gt>>

Addition of unit test suite, fragmentation support, and other improvements.


=item B<Fredrik Vold> C<E<lt>fredrik@webkonsept.comE<gt>>

Original (0.1.x) author.

No copyright claimed, no rights reserved.

You are absolutely free to do as you wish with this code, but mentioning me in
your comments or whatever would be nice.

Minecraft is a trademark of Mojang AB. Name used in accordance with my
interpretation of L<http://www.minecraft.net/terms>, to the best of my
knowledge.

=back
