Games::IL2Device::Link - A simple class for talking to IL2 clients.


Games-IL2Device-Link documentation Contained in the Games-IL2Device-Link distribution.

Index


Code Index:

NAME

Top

Games::IL2Device::Link - A simple class for talking to IL2 clients.

SYNOPSIS

Top

    use Games::IL2Device::Link;

    # Create a new connection to a IL2 client
    $mydl = Games::IL2Device::Link->new('127.0.0.1', 10001, ( TIMEOUT => 5)); 

    # Get value of key 52 (overload)
    $mydl->get(52);
    # reply method returns the result from last query
    print "G-load: ". $mydl->reply->{52} ."\n";

    # Toggle navigation lights.
    $mydl->set(411) or warn "411 failed!";

    # You can ask for several values at once with get
    $mydl->get(60,62,64,70,72,80,74);
    $reply = $mydl->reply;
    foreach (keys %$reply) { print "got: $reply->{$_}\n"; }







DESCRIPTION

Top

This class provides an interface to connect to a devicelink on a IL2 Forgotten Battles client (=> 2.01). The interface hosts a set of key values which can be set or get - reference to these values can be found in 'DeviceLink.txt' located in the IL2 Forgotten Battles install folder. To activate the devicelink feature in IL2 Forgotten Battles you need to add a section in the 'conf.ini' file:

BUGS

Top

The set() method currently only works with one key/pair value per call. Set values only works if you send them last to the server. Get values with parameters can only be sent one at each call. Get values with indexed replies are not parsed, you will have to remember in what order you called each object.

AUTHOR

Top

Mathias Jansson <matja[at]cpan.org>

COPYRIGHT

Top

SEE ALSO

Top

Games::IL2Device::Constants perl(1).


Games-IL2Device-Link documentation Contained in the Games-IL2Device-Link distribution.

package Games::IL2Device::Link;

use strict;
use warnings;
use IO::Socket qw(:DEFAULT :crlf);
use Carp;

use vars qw($VERSION);
our $VERSION = '0.02';

our %EXPORT_TAGS = ( 'all' => [ qw(
) ] );

our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );

our @EXPORT = qw(
);



# Methods

sub new {
  my $devlink = shift;
  my $class =  ref($devlink) || $devlink;
  my $self = {
	      ADDR => undef,
	      PORT => undef,
	      TIMEOUT => 30,
	      DEBUG => 0
	     };
  bless ($self, $class);
  $self->_init(@_);
  $self->il2connect if (defined($self->addr) && defined($self->port));
  return $self;
}



sub _init {
  my $self = shift;
  $self->{ADDR} = shift;
  $self->{PORT} = shift;
  if ( @_ ) {
    my %extra = @_;
    @$self{keys %extra} = values %extra;
  }
}



sub addr {
  my $self = shift;
  if (@_) {
    $self->{ADDR} = shift;
  }
  return $self->{ADDR};

}



sub port {
  my $self = shift;
  if (@_) {
    $self->{PORT} = shift;
  }
  return $self->{PORT};

}



sub reply {
  my $self = shift;
  return  $self->{'REPLY'};
}



sub il2connect {
  my $self = shift;
  
  if ( defined($self->addr) && defined($self->port) ) {
    
    $self->{SOCK} = IO::Socket::INET->new(PeerAddr => $self->addr,
					  PeerPort => $self->port,
					  Type => SOCK_DGRAM,
					  Proto => 'udp') or 
					    warn "il2connect() socket creation failed: $!";
    return 1;
  } else {
    carp "il2connect(): Nowhere to connect!";
    return 0;
  }
}


sub il2disconnect {
  my $self = shift;
  $self->{SOCK} = undef;
}


sub _send {
  my $self = shift;
  local $, = $CRLF;
  my $bs = 0;
  
  if ( defined( $self->{SOCK} ) ) {
    $bs = $self->{SOCK}->print("$self->{PACKET}$CRLF");
    warn "_send() failed to send data: $!" if $bs <= 0;
    print "_send(): sent; $self->{PACKET}\n" if $self->{DEBUG} && $bs;
  } else {
    carp "_send(): No socket defined, are you connected?";
  }
  return $bs;
}
  
  
  
sub _receive {
  my $self = shift;
  local $/ = $LF;
  my $recv_size = ( length(scalar "$self->{PACKET}$CRLF") * 4);
  my $buffer = undef;
  $self->{DATA} = undef;
  
  if ( defined($self->{SOCK}) ) {
    if ( $recv_size > 0 ) {
      $SIG{ALRM} = sub { die "timeout" };
      
      eval {
	alarm($self->{TIMEOUT});
	$self->{SOCK}->recv($buffer, $recv_size);
	$self->{DATA} = $buffer;
	alarm(0);
      };
      if ($@) {
	if ($@ =~ /timeout/) {
	  warn "_receive(): timeout while reading $!";
	} else {
	  alarm(0);
	  die;
	}
      }
      
    }
  } else {
    carp "_receive(): No socket defined, are you connected?";
    return undef;
  }
  print "_receive(): got: $self->{DATA}\n" if $self->{DEBUG};

  return $self->{DATA};
}


sub creategetpacket {
  my $self = shift;
  $self->{PACKET} = "R";
  foreach ( @_ ) {
    $self->{PACKET} .= "/$_";
  }
  $self->{PACKET} .= "/";
  print "creategetpacket(): created; $self->{PACKET}\n" if $self->{DEBUG};
  return $self->{PACKET};
}



sub createsetpacket {
  my $self = shift;
  my ($key, $value) = @_;
  if ( defined ($value) ) {
    $self->{PACKET} = "R/" . $key . "\\" . $value;
  } else {
    $self->{PACKET} = "R/" . $key . "\\";
  }
  print "createsetpacket(): created; $self->{PACKET}\n" if $self->{DEBUG};
  return $self->{PACKET};
}



sub set {
  my $self = shift;
  my $packet = $self->createsetpacket(@_);
  my $result = $self->_send($packet);
  return $result;
}



sub get {
  my $self = shift;
  my $data = undef;
  my $packet = $self->creategetpacket(@_);
  my $result = $self->_send($packet);
  if ( defined($result) ) {
    $data = $self->_receive();
    if ( defined( $data ) ) {
      $self->parsedata();
    } else {
      return 0;
    }
  } else {
    return 0;
  }
  return 1;
}



sub parsedata {
  my $self = shift;
  my %pdata;
  my $key = undef; 
  my $value = undef;
  foreach (split /\//, $self->{DATA}) {
    chomp;
    next if /^A/;
    if ( /^(\d+)\\/ ) { 
      $key = $1; 
    }
    if ( /[\\\d]*\\(.+)$/ ) {
      $value = $1 
    }
    $pdata{$key} = $value if defined $key;
    print "parsedata(): key; $key value; $value\n" if $self->{DEBUG};
  }
  $self->{REPLY} = \%pdata;
}



sub DESTROY {
  my $self = shift;
  carp "Closing connection" if $self->{DEBUG};
  $self->{SOCK} = undef;
}


1;
__END__