Openkore.com

OpenKore Forums
It is currently 24 Sep 2018, 13:04

All times are UTC - 5 hours [ DST ]





Post new topic Reply to topic  [ 38 posts ]  Go to page 1, 2, 3, 4  Next
Author Message
 Post subject: Request GG Problem Poseidon
PostPosted: 09 Mar 2016, 12:30 
Offline
Noob
Noob

Joined: 01 Apr 2015, 16:41
Posts: 11
[EN]
I have a problem for this period.
Has week that responds regular week has not answered the request gg.
I have tried ways of trying to solve it did not get more success and I do not have knowledge at the time to understand why answers some weeks and not others.
What I noticed and that during the week answers I can log in poseidon apprentice and select the character and change trainee.
In the week that no answers I can not change char, simply does not return the selection screen characters.
Sending the prints this week that he is not responding as you can see the Poseidon is usually linked to openkore only can not send back a response this week.
I'll put the weekly update files and also my RagnarokServer, QueryServer files.
For me that for the operation are needed to add more 09D0 package I is not seeing something.
So who can give me a light on the way forward would be grateful.

[PT-BR]
Estou com um problema por periodo.
Tem semana que responde normal tem semana que não responde o request gg.
Eu já procurei formas de tentar resolver isso mais não obtive exito e não possuo conhecimento no momento para entender por que responde algumas semanas e outras não.
O que percebi e que durante a semana que responde eu posso logar no aprendiz do poseidon e selecionar o char e trocar de aprendiz.
Já na semana que não responde eu não consigo trocar de char, simplismente não volta a tela de selecão de personagens.
Mandando as prints dessa semana que não está respondendo como pode perceber o poseidon está ligado normalmente ao openkore só que não consegue enviar de volta a resposta nessa semana.
Vou colocar os arquivos da atualização semanal também e meus arquivos RagnarokServer, QueryServer.
Para mim que para o funcionamento so precisava adicionar o pacote 09D0 mais devo não está percebendo algo. Então quem puder me dar uma luz no caminho a seguir ficaria grato.

Image
Image
Image


Attachments:
recvpackets08-03.txt [15.83 KiB]
Downloaded 229 times
Sendbro08-03.pm [2.18 KiB]
Downloaded 207 times
Receivebro 08-03.pm [3.37 KiB]
Downloaded 191 times


Last edited by Break on 09 Mar 2016, 12:56, edited 2 times in total.
Top
 Profile  
 
 Post subject: Re: Request GG Problem Poseidon
PostPosted: 09 Mar 2016, 12:42 
Offline
Noob
Noob

Joined: 01 Apr 2015, 16:41
Posts: 11
QueryServer
Code:
###########################################################
# Poseidon server - OpenKore communication channel
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# Copyright (c) 2005-2006 OpenKore Development Team
###########################################################
package Poseidon::QueryServer;

use strict;
use Scalar::Util;
use Base::Server;
use Bus::MessageParser;
use Bus::Messages qw(serialize);
use Poseidon::RagnarokServer;
use base qw(Base::Server);
use Plugins;

my $CLASS = "Poseidon::QueryServer";


# struct Request {
#     Bytes packet;
#     Base::Server::Client client;
# }

##
# Poseidon::QueryServer->new(String port, String host, Poseidon::RagnarokServer ROServer)
# port: The port to start this server on.
# host: The host to bind this server to.
# ROServer: The RagnarokServer object to send GameGuard queries to.
# Require: defined($port) && defined($ROServer)
#
# Create a new Poseidon::QueryServer object.
sub new {
   my ($class, $port, $host, $roServer) = @_;
   my $self = $class->SUPER::new($port, $host);

   # Invariant: server isa 'Poseidon::RagnarokServer'
   $self->{"$CLASS server"} = $roServer;

   # Array<Request> queue
   #
   # The GameGuard query packets queue.
   #
   # Invariant: defined(queue)
   $self->{"$CLASS queue"} = [];

   return $self;
}

##
# void $QueryServer->process(Base::Server::Client client, String ID, Hash* args)
#
# Push an OpenKore GameGuard query to the queue.
sub process {
   my ($self, $client, $ID, $args) = @_;

   if ($ID ne "Poseidon Query") {
      $client->close();
      return;
   }
   
   print "[PoseidonServer]-> Received query from bot client " . $client->getIndex() . "\n";

   my %request = (
      packet => $args->{packet},
      client => $client
   );

   # perform client authentication here
   Plugins::callHook('Poseidon/server_authenticate', {
      args_hash => $args,
   });

   # note: the authentication plugin must set auth_failed to true if it doesn't
   # want the Poseidon server to respond to the query
   return if ($args->{auth_failed});

   Scalar::Util::weaken($request{client});
   push @{$self->{"$CLASS queue"}}, \%request;
#   my $packet = substr($ipcArgs->{packet}, 0, 18);
}


##################################################


sub onClientNew {
   my ($self, $client, $index) = @_;
   $client->{"$CLASS parser"} = new Bus::MessageParser();
   print "[PoseidonServer]-> New Bot Client Connected : " . $client->getIndex() . "\n";
}

sub onClientExit {
   my ($self, $client, $index) = @_;
   print "[PoseidonServer]-> Bot Client Disconnected : " . $client->getIndex() . "\n";
}

sub onClientData
{
   my ($self, $client, $msg) = @_;
   my ($ID, $args);

   my $parser = $client->{"$CLASS parser"};
   
   $parser->add($msg);
   
   while ($args = $parser->readNext(\$ID))
   {
      $self->process($client, $ID, $args);
   }
}

sub iterate {
   my ($self) = @_;
   my ($server, $queue);

   $self->SUPER::iterate();
   $server = $self->{"$CLASS server"};
   $queue = $self->{"$CLASS queue"};

   if ($server->getState() eq 'requested')
   {
      # Send the response to the client.
      if (@{$queue} > 0 && $queue->[0]{client}) {
         my ($data, %args);

         $args{packet} = $server->readResponse();
         $data = serialize("Poseidon Reply", \%args);
         $queue->[0]{client}->send($data);
         $queue->[0]{client}->close();
         print "[PoseidonServer]-> Sent result to client : " . $queue->[0]{client}->getIndex() . "\n";
      }
      shift @{$queue};

   } elsif (@{$queue} > 0 && $server->getState() eq 'ready') {
      print "[PoseidonServer]-> Querying Ragnarok Online client [" . time . "]...\n";
      $server->query($queue->[0]{packet});
   }
}

1;



RagnarokServer
Code:
###########################################################
# Poseidon server - Ragnarok Online server emulator
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# Copyright (c) 2005-2006 OpenKore Development Team
###########################################################
# This class emulates a Ragnarok Online server.
# The RO client connects to this server. This server
# periodically sends a GameGuard query to the RO client,
# and saves the RO client's response.
###########################################################

# TODO:
# 1) make use of unpack strings to pack our packets depending on serverType
# 2) make plugin like connection algorithms for each serverType or 1 main algo on which serverTypes have hooks

package Poseidon::RagnarokServer;

use strict;
use Base::Server;
use base qw(Base::Server);
use Misc;
use Utils qw(binSize getCoordString timeOut getHex getTickCount);
use Poseidon::Config;
use FileParsers;
use Math::BigInt;

my %clientdata;

# Decryption Keys
my $enc_val1 = 0;
my $enc_val2 = 0;
my $enc_val3 = 0;
my $state    = 0;

sub new {
   my ($class, @args) = @_;
   my $self = $class->SUPER::new(@args);

   # int challengeNum
   #
   # The number of times that the RO client has sent a
   # GameGuard challenge packet.
   #
   # Invariant: challengeNum >= 0
   $self->{challengeNum} = 0;

   # Bytes response
   #
   # A response for the last GameGuard query.
   $self->{response} = undef;

   # Invariant: state ne ''
   $self->{state} = 'ready';
   
   # added servertypes support
   if (-e 'servertypes.txt') {
      parseSectionedFile('servertypes.txt', \%{$self->{type}});
   } else {
      parseSectionedFile('src/Poseidon/servertypes.txt', \%{$self->{type}});
   }
   
   if (!$self->{type}->{$config{server_type}}) {
      die "Invalid serverType specified. Please check your poseidon config file.\n";
   } else {
      print "Building RagnarokServer with serverType $config{server_type}...\n";
   }

   return $self;
}

##
# $RagnarokServer->query(Bytes packet)
# packet: The raw GameGuard query packet.
# Require: defined($packet) && $self->getState() eq 'ready'
# Ensure: $self->getState() eq 'requesting'
#
# Send a GameGuard query to the RO client.
sub query
{
   my ($self, $packet) = @_;
   my $clients = $self->clients();

   for (my $i = 0; $i < @{$clients}; $i++) {
      if ($clients->[$i]) {
         if ($clients->[$i]{connectedToMap}) {
                      $clients->[$i]->send($packet);
                      $self->{state} = 'requesting';
                      return;
         }
      }
   }
   
   print "[RagnarokServer]-> Error: no Ragnarok Online client connected.\n";
}

##
# String $RagnarokServer->getState()
#
# Get the state of this RagnarokServer object.
# The result can be one of:
# 'ready' - The RO client is ready to handle another GameGuard query.
# 'requesting' - The query has been sent to the RO client, but it hasn't responded yet.
# 'requested' - The RO client has responded to the last GameGuard query.
# 'not connected' - The RO client hasn't connected to this server yet.
sub getState {
   my ($self) = @_;
   my $clients = $self->clients();

   if ($self->{state} eq 'requested') {
      return 'requested';
   } elsif (binSize($clients) == 0) {
      return 'not connected';
   } else {
      return $self->{state};
   }
}

##
# Bytes $RagnarokServer->readResponse()
# Require: $self->getState() eq 'requested'
# Ensure: defined(result) && $self->getState() eq 'ready'
#
# Read the response for the last GameGuard query.
sub readResponse {
   my $resp = $_[0]->{response};
   $_[0]->{response} = undef;
   $_[0]->{state} = 'ready';
   return $resp;
}


#####################################################

sub onClientNew
{
   my ($self, $client, $index) = @_;

   if ( $state == 0 )
   {
      # Initialize Decryption
      $enc_val1 = 0;
      $enc_val2 = 0;
      $enc_val3 = 0;
   } else { $state = 0; }
   
   $self->{challengeNum} = 0;
   
   print "[RagnarokServer]-> Ragnarok Online client ($index) connected.\n";   
}

sub onClientExit
{
   my ($self, $client, $index) = @_;
   
   $self->{challengeNum} = 0;
   
   print "[RagnarokServer]-> Ragnarok Online client ($index) disconnected.\n";
}

## constants
my $accountID = pack("a4", "acct");
my $posX = 53;
my $posY = 113;

## Globals
my $charID = pack("a4", "char");
my $sessionID = pack("a4", "sess");
my $sessionID2 = pack("C4", 0xff);
my $npcID1 = pack("a4", "npc1");
my $npcID0 = pack("a4", "npc2");
my $monsterID = pack("a4", "mon1");
my $itemID = pack("a4", "itm1");

sub DecryptMessageID
{
   my ($MID) = @_;
   
   # Checking if Decryption is Activated
   if ($enc_val1 != 0 && $enc_val2 != 0 && $enc_val3 != 0)
   {
      # Saving Last Informations for Debug Log
      my $oldMID = $MID;
      my $oldKey = ($enc_val1 >> 16) & 0x7FFF;
      
      # Calculating the Next Decryption Key
      $enc_val1 = $enc_val1->bmul($enc_val3)->badd($enc_val2) & 0xFFFFFFFF;
   
      # Xoring the Message ID [657BE2h] [0x6E0A]
      $MID = ($MID ^ (($enc_val1 >> 16) & 0x7FFF));

      # Debug Log
      # print sprintf("Decrypted MID : [%04X]->[%04X] / KEY : [0x%04X]->[0x%04X]\n", $oldMID, $MID, $oldKey, ($enc_val1 >> 16) & 0x7FFF);
   }
   
   return $MID;
}

sub onClientData {
   my ($self, $client, $msg, $index) = @_;

   my $packet_id = DecryptMessageID(unpack("v",$msg));
   my $switch = sprintf("%04X", $packet_id);
   
   # Parsing Packet
   ParsePacket($self, $client, $msg, $index, $packet_id, $switch);
}

sub ParsePacket
{
   my ($self, $client, $msg, $index, $packet_id, $switch) = @_;

   #my $packed_switch = quotemeta substr($msg, 0, 2);
   my $packed_switch = $packet_id;
   
   ### These variables control the account information ###
   my $host = $self->getHost();
   my $port = pack("v", $self->getPort());
   $host = '127.0.0.1' if ($host eq 'localhost');
   my @ipElements = split /\./, $host;
   
   # Note:
   # The switch packets are pRO specific and assumes the use of secureLogin 1. It may or may not work with other
   # countries' clients (except probably oRO). The best way to support other clients would be: use a barebones
   # eAthena or Freya as the emulator, or figure out the correct packet switches and include them in the
   # if..elsif..else blocks.

   if (($switch eq '01DB') || ($switch eq '0204')) { # client sends login packet 0204 packet thanks to elhazard

      # '01DC' => ['secure_login_key', 'x2 a*', [qw(secure_key)]],
      my $data = pack("C*", 0xdc, 0x01, 0x14) . pack("x17");
      $client->send($data);

      # save servers.txt info
      my $code = substr($msg, 2);
      if (length($msg) == 2) {
         $clientdata{$index}{secureLogin_type} = 0;
      } elsif (length($msg) == 20) {
         if ($code eq pack("C*", 0x04, 0x02, 0x7B, 0x8A, 0xA8, 0x90, 0x2F, 0xD8, 0xE8, 0x30, 0xF8, 0xA5, 0x25, 0x7A, 0x0D, 0x3B, 0xCE, 0x52)) {
            $clientdata{$index}{secureLogin_type} = 1;
         } elsif ($code eq pack("C*", 0x04, 0x02, 0x27, 0x6A, 0x2C, 0xCE, 0xAF, 0x88, 0x01, 0x87, 0xCB, 0xB1, 0xFC, 0xD5, 0x90, 0xC4, 0xED, 0xD2)) {
            $clientdata{$index}{secureLogin_type} = 2;
         } elsif ($code eq pack("C*", 0x04, 0x02, 0x42, 0x00, 0xB0, 0xCA, 0x10, 0x49, 0x3D, 0x89, 0x49, 0x42, 0x82, 0x57, 0xB1, 0x68, 0x5B, 0x85)) {
            $clientdata{$index}{secureLogin_type} = 3;
         } elsif ($code eq ("C*", 0x04, 0x02, 0x22, 0x37, 0xD7, 0xFC, 0x8E, 0x9B, 0x05, 0x79, 0x60, 0xAE, 0x02, 0x33, 0x6D, 0x0D, 0x82, 0xC6)) {
            $clientdata{$index}{secureLogin_type} = 4;
         } elsif ($code eq pack("C*", 0x04, 0x02, 0xc7, 0x0A, 0x94, 0xC2, 0x7A, 0xCC, 0x38, 0x9A, 0x47, 0xF5, 0x54, 0x39, 0x7C, 0xA4, 0xD0, 0x39)) {
            $clientdata{$index}{secureLogin_type} = 5;
         }
      } else {
         $clientdata{$index}{secureLogin_requestCode} = getHex($code);
      }

   } elsif (($switch eq '01DD') || ($switch eq '01FA') || ($switch eq '0064') || ($switch eq '0060') || ($switch eq '0277') || ($switch eq '02B0')) { # 0064 packet thanks to abt123

#      my $data = pack("C*", 0xAD, 0x02, 0x00, 0x00, 0x1E, 0x0A, 0x00, 0x00);
#      $client->send($data);
      my $sex = 1;
      my $serverName = pack("a20", "Poseidon server"); # server name should be less than or equal to 20 characters
      my $serverUsers = pack("V", @{$self->clients()} - 1);
      # '0069' => ['account_server_info', 'x2 a4 a4 a4 x30 C1 a*',
      #          [qw(sessionID accountID sessionID2 accountSex serverInfo)]],
      my $data;
      if ($switch eq '01FA') {
         $data = pack("C*", 0x69, 0x00, 0x53, 0x00) .
            $sessionID . $accountID . $sessionID2 .
            pack("x30") . pack("C1", $sex) . pack("x4") .
            pack("C*", $ipElements[0], $ipElements[1], $ipElements[2], $ipElements[3]) .
            $port .   $serverName . $serverUsers . pack("x2");
      } else {
         $data = pack("C*", 0x69, 0x00, 0x4F, 0x00) .
            $sessionID . $accountID . $sessionID2 .
            pack("x30") . pack("C1", $sex) .
            pack("C*", $ipElements[0], $ipElements[1], $ipElements[2], $ipElements[3]) .
            $port .   $serverName . $serverUsers . pack("x2");
      }

      $client->send($data);

      # save servers.txt info
      $clientdata{$index}{version} = unpack("V", substr($msg, 2, 4));
      $clientdata{$index}{master_version} = unpack("C", substr($msg, length($msg) - 1, 1));
      if ($switch eq '01DD') {
         $clientdata{$index}{secureLogin} = 1;
         undef $clientdata{$index}{secureLogin_account};
      } elsif ($switch eq '01FA') {
         $clientdata{$index}{secureLogin} = 3;
         $clientdata{$index}{secureLogin_account} = unpack("C", substr($msg, 47, 1));
      } else {
         undef $clientdata{$index}{secureLogin};
         undef $clientdata{$index}{secureLogin_type};
         undef $clientdata{$index}{secureLogin_account};
         undef $clientdata{$index}{secureLogin_requestCode};
      }
      if (($switch ne '01DD') && ($switch ne '01FA') && ($switch ne '0064')) {
         $clientdata{$index}{masterLogin_packet} = $switch;
      } else {
         undef $clientdata{$index}{masterLogin_packet};
      }

      if($switch eq '02B0') {   # kRO uses 02B2 as masterLogin packet when we have <langtype>0</langtype> in the clientinfo.xml
                        # if other servers do use this packet too that will be a problem.
         $clientdata{$index}{kRO} = 1;
      }

   } elsif (($switch eq '0065') || ($switch eq '0275') || ($msg =~ /^$packed_switch$accountID$sessionID$sessionID2\x0\x0.$/)) { # client sends server choice packet

      # Character List
      SendCharacterList($self, $client, $msg, $index);

      # save servers.txt info
      if ($switch ne '0065') {
         $clientdata{$index}{gameLogin_packet} = $switch;
      } else {
         undef $clientdata{$index}{gameLogin_packet};
      }

   } elsif ($switch eq '0066') { # client sends character choice packet

      # If Using Packet Encrypted Client
      if ( $self->{type}->{$config{server_type}}->{decrypt_mid_keys} )
      {
         # Enable Decryption
         my @enc_values = split(/\s+/, $self->{type}->{$config{server_type}}->{decrypt_mid_keys});
         ($enc_val1, $enc_val2, $enc_val3) = (Math::BigInt->new(@enc_values[0]), Math::BigInt->new(@enc_values[1]), Math::BigInt->new(@enc_values[2]));
      }
      
      # State
      $state = 1;

      $clientdata{$index}{mode} = unpack('C1', substr($msg, 2, 1));

      # '0071' => ['received_character_ID_and_Map', 'a4 Z16 a4 v1', [qw(charID mapName mapIP mapPort)]],
      my $mapName = pack("a16", "moc_prydb1.gat");
      my $data = pack("C*", 0x71, 0x00) . $charID . $mapName .
         pack("C*", $ipElements[0], $ipElements[1], $ipElements[2], $ipElements[3]) . $port;
      
      $client->send($data);
      
   } elsif ($switch eq  $self->{type}->{$config{server_type}}->{maploginPacket} &&
      (length($msg) == 19) &&
      (substr($msg, 2, 4) eq $accountID) &&
      (substr($msg, 6, 4) eq $charID) &&
      (substr($msg, 10, 4) eq $sessionID)
      ) { # client sends the maplogin packet

      SendMapLogin($self, $client, $msg, $index);
      # save servers.txt info
      $clientdata{$index}{serverType} = 0;

   } elsif ($switch eq '0072' &&
      (length($msg) == 19) &&
      (substr($msg, 2, 4) eq $accountID) &&
      (substr($msg, 6, 4) eq $charID) &&
      (substr($msg, 10, 4) eq $sessionID)
      ) { # client sends the maplogin packet

      SendMapLogin($self, $client, $msg, $index);
      # save servers.txt info
      $clientdata{$index}{serverType} = 0;

   } elsif ($switch eq '009B' &&
      (length($msg) == 32) &&
      (substr($msg, 3, 4) eq $accountID) &&
      (substr($msg, 12, 4) eq $charID) &&
      (substr($msg, 23, 4) eq $sessionID)
      ) { # client sends the maplogin packet

      SendMapLogin($self, $client, $msg, $index);
      # save servers.txt info
      $clientdata{$index}{serverType} = 3;

   } elsif ($switch eq '00F5' &&
      (length($msg) == 29) &&
      (substr($msg, 5, 4) eq $accountID) &&
      (substr($msg, 14, 4) eq $charID) &&
      (substr($msg, 20, 4) eq $sessionID)
      ) { # client sends the maplogin packet

      SendMapLogin($self, $client, $msg, $index);
      # save servers.txt info
      $clientdata{$index}{serverType} = 4;

   } elsif ($switch eq '009B' &&
      (length($msg) == 32) &&
      (substr($msg, 9, 4) eq $accountID) &&
      (substr($msg, 15, 4) eq $charID) &&
      (substr($msg, 23, 4) eq $sessionID)
      ) { # client sends the maplogin packet

      SendMapLogin($self, $client, $msg, $index);
      # save servers.txt info
      $clientdata{$index}{serverType} = 5;

   } elsif ($switch eq '0072' &&
      (length($msg) == 29) &&
      (substr($msg, 3, 4) eq $accountID) &&
      (substr($msg, 10, 4) eq $charID) &&
      (substr($msg, 20, 4) eq $sessionID)
      ) { # client sends the maplogin packet

      SendMapLogin($self, $client, $msg, $index);
      # save servers.txt info
      $clientdata{$index}{serverType} = 6;

   } elsif ($switch eq '0072' &&
      (length($msg) == 34) &&
      (substr($msg, 7, 4) eq $accountID) &&
      (substr($msg, 15, 4) eq $charID) &&
      (substr($msg, 25, 4) eq $sessionID)
      ) { # client sends the maplogin packet

      SendMapLogin($self, $client, $msg, $index);
      # save servers.txt info
      $clientdata{$index}{serverType} = 7;

   } elsif ($switch eq '009B' &&
      (length($msg) == 26) &&
      (substr($msg, 4, 4) eq $accountID) &&
      (substr($msg, 9, 4) eq $charID) &&
      (substr($msg, 17, 4) eq $sessionID)
      ) { # client sends the maplogin packet

      SendMapLogin($self, $client, $msg, $index);
      # save servers.txt info
      $clientdata{$index}{serverType} = 8;

   } elsif ($switch eq '009B' &&
      (length($msg) == 37) &&
      (substr($msg, 9, 4) eq $accountID) &&
      (substr($msg, 21, 4) eq $charID) &&
      (substr($msg, 28, 4) eq $sessionID)
      ) { # client sends the maplogin packet

      SendMapLogin($self, $client, $msg, $index);
      # save servers.txt info
      $clientdata{$index}{serverType} = 9;

   } elsif ($switch eq '0072' &&
      (length($msg) == 26) &&
      (substr($msg, 4, 4) eq $accountID) &&
      (substr($msg, 9, 4) eq $charID) &&
      (substr($msg, 17, 4) eq $sessionID)
      ) { # client sends the maplogin packet

      SendMapLogin($self, $client, $msg, $index);
      # save servers.txt info
      $clientdata{$index}{serverType} = 10;

   } elsif ($switch eq '0072' &&
      (length($msg) == 29) &&
      (substr($msg, 5, 4) eq $accountID) &&
      (substr($msg, 14, 4) eq $charID) &&
      (substr($msg, 20, 4) eq $sessionID)
      ) { # client sends the maplogin packet

      SendMapLogin($self, $client, $msg, $index);
      # save servers.txt info
      $clientdata{$index}{serverType} = 11;

   } elsif ($switch eq '0094' &&
      (length($msg) == 30) &&
      (substr($msg, 12, 4) eq $accountID) &&
      (substr($msg, 2, 4) eq $charID) &&
      (substr($msg, 6, 4) eq $sessionID)
      ) { # client sends the maplogin packet

      SendMapLogin($self, $client, $msg, $index);
      # save servers.txt info
      $clientdata{$index}{serverType} = 12;

   } elsif ($switch eq '0072' &&
      (length($msg) == 29) &&
      (substr($msg, 5, 4) eq $accountID) &&
      (substr($msg, 14, 4) eq $charID) &&
      (substr($msg, 20, 4) eq $sessionID)
      ) { # client sends the maplogin packet

      SendMapLogin($self, $client, $msg, $index);
      # save servers.txt info
      $clientdata{$index}{serverType} = "1 or 2";

   } elsif (($switch eq '0436' || $switch eq '022D') &&
      (length($msg) == 19) &&
      (substr($msg, 2, 4) eq $accountID) &&
      (substr($msg, 6, 4) eq $charID) &&
      (substr($msg, 10, 4) eq $sessionID)
      ) { # client sends the maplogin packet

      $client->send(pack("v a4", 0x0283, $accountID));
      # mapLogin packet
      $client->send(pack("H536", "eb0206ad09222b56c0050500000f012c010100000000000900000001004e565f42415349430000000000000000080000000f0000000030000000000000000000010054465f444f55424c4500000000000000090000000f0000000131000000000000000000010054465f4d495353000000000000000000070000000f0000000132000100000000000a00010054465f535445414c0000000000000000080000000f0000000133000400000000000a00010054465f484944494e4700000000000000090000000f0000000034000100000000000c00020054465f504f49534f4e00000000000000090000000f0000000135001000000000000a00090054465f4445544f5849465900000000000b0000000f000000008e00040000000100030001004e565f464952535441494400000000000b0000000f00000000d701df145a000200000000d701df145a0003000000003a010100d701df145a0002f13200003a010100b0001900d06b0000b0001800b2110000b102080000000000b202080000000000b0002a003f000000b0002b0000000000b0002e002d000000b000300000000000d9070039020000000000000000000000000000000000000000000000000000233000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"));
      $client->{connectedToMap} = 1;

   } elsif ($msg =~ /^$packed_switch/
      && $msg =~ /$accountID/
      && $msg =~ /$charID/
      && $msg =~ /$sessionID/) { # client sends the maplogin packet (unknown)

      print "Received unsupported map login packet $switch.\n";
      visualDump($msg, "$switch");

      SendMapLogin($self, $client, $msg, $index);
      # save servers.txt info
      undef $clientdata{$index}{serverType};
      #$clientdata{$index}{sendMapLogin} = $msg;

   } elsif ($switch eq '007D') { # client sends the map loaded packet
      my $data;

      # Temporary Hack to Initialized Crypted Client
      if ( $self->{type}->{$config{server_type}}->{decrypt_mid_keys} )
      {
         for ( my $i = 0 ; $i < 64 ; $i++ )
         {
            $client->send(pack("C C", 0x70, 0x08));
            
            # Forcedly Calculating the Next Decryption Key
            $enc_val1 = $enc_val1->bmul($enc_val3)->badd($enc_val2) & 0xFFFFFFFF;   
         }
      }      
      
      PerformMapLoadedTasks($self, $client, $msg, $index);
   } elsif (
      ( ( ($switch eq '007E') || ($switch eq '035F') ) && (($clientdata{$index}{serverType} == 0) || ($clientdata{$index}{serverType} == 1) || ($clientdata{$index}{serverType} == 2) || ($clientdata{$index}{serverType} == 6) || ($clientdata{$index}{serverType} == 7) || ($clientdata{$index}{serverType} == 10) || ($clientdata{$index}{serverType} == 11))) ||
      (($switch eq '0089') && (($clientdata{$index}{serverType} == 3) || ($clientdata{$index}{serverType} == 5) || ($clientdata{$index}{serverType} == 8) || ($clientdata{$index}{serverType} == 9))) ||
      (($switch eq '0116') && ($clientdata{$index}{serverType} == 4)) ||
      (($switch eq '00A7') && ($clientdata{$index}{serverType} == 12))
      ) { # client sends sync packet
      my $data = pack("C*", 0x7F, 0x00) . pack("V", getTickCount);
      $client->send($data);

      ### Check if packet 0228 got tangled up with the sync packet
      if (uc(unpack("H2", substr($msg, 7, 1))) . uc(unpack("H2", substr($msg, 6, 1))) eq '0228') {
         # queue the response (thanks abt123)
         $self->{response} = pack("v", $packet_id) . substr($msg, 8, length($msg)-2);
         $self->{state} = 'requested';
      }

   } elsif ($switch eq '00B2') { # quit to character select screen
         
      SendGoToCharSelection($self, $client, $msg, $index);
         
      # Disable Decryption
      $enc_val1 = 0;
      $enc_val2 = 0;
      $enc_val3 = 0;         
         
   } elsif ($switch eq '0187') { # accountid sync (what does this do anyway?)
      $client->send($msg);

   } elsif ($switch eq '018A') { # client sends quit packet
      
      SendQuitGame($self, $client, $msg, $index);

   } elsif ($switch eq '0228') { # client sends game guard sync
      # Queue the response
      # Don't allow other packet's (like Sync) to get to RO server.
      my $length = unpack("v",substr($msg,2,2));
      if ($length > 0) {
         $self->{response} = pack("v", $packet_id) . substr($msg,2,$length);
      } else {
         $self->{response} = pack("v", $packet_id);
      };
      $self->{state} = 'requested';
   
   } elsif ($switch eq '02A7') { # client sends hShield response
      # Queue the response
      $self->{response} = $msg;
      $self->{state} = 'requested';

   } elsif ($switch eq '0258') { # client sent gameguard's challenge request
      # Reply with "gameguard_grant" instead of a 0227 packet. Normally, the server would
      # send a 0227 gameguard challenge to the client, then the client will send the
      # proper 0228 response. Only after that will the server send 0259 to allow the
      # client to continue the login sequence. Since this is just a fake server,
      # there is no need to go through all that and we can do a shortcut.
      if ($self->{challengeNum} == 0) {
         print "Received GameGuard sync request. Client allowed to login account server.\n";
         $client->send(pack("C*", 0x59, 0x02, 0x01));
      } else {
         print "Received GameGuard sync request. Client allowed to login char/map server.\n";
         $client->send(pack("C*", 0x59, 0x02, 0x02));
      }
      $self->{challengeNum}++;
   } else {
      if ($switch eq '0090' || ($msg =~ /\x90\x0($npcID1|$npcID0)/)) { # npc talk
         undef $clientdata{$index}{npc_talk_code};
         if ($msg =~ /\x90\x0$npcID1/) {
            # Show the kafra image
            SendNpcImageShow($self, $client, $msg, $index, "kafra_04.bmp", 0x02);
            # Show the messages
            SendNPCTalk($self, $client, $msg, $index, $npcID1, "[Kafra]");
            SendNPCTalk($self, $client, $msg, $index, $npcID1, "Welcome to Kafra Corp. We will stay with you wherever you go.");
            SendNPCTalkContinue($self, $client, $msg, $index, $npcID1);
         } else {
            SendNPCTalk($self, $client, $msg, $index, $npcID0, "[Hakore]");
            SendNPCTalk($self, $client, $msg, $index, $npcID0, "Hello! I was examining your RO client's login packets while you were connecting to Poseidon.");
            SendNPCTalkContinue($self, $client, $msg, $index, $npcID0);
         }

      } elsif ($switch eq '00B8') { # npc talk response

         my $npcID = substr($msg, 2, 4);
         my $response = unpack("C1", substr($msg, 6, 1));
         if ($npcID eq $npcID0) {
            if ($response == 1) {
               # Check server info
               SendNPCTalk($self, $client, $msg, $index, $npcID, "[Hakore]");
               SendNPCTalk($self, $client, $msg, $index, $npcID, "Your RO client uses the following server details:");
               SendNPCTalk($self, $client, $msg, $index, $npcID, "^2222DDversion: $clientdata{$index}{version}");
               SendNPCTalk($self, $client, $msg, $index, $npcID, "master_version: $clientdata{$index}{master_version}");
               SendNPCTalk($self, $client, $msg, $index, "serverType: " . ((defined $clientdata{$index}{serverType}) ? $clientdata{$index}{serverType} : 'Unknown'));
               if ($clientdata{$index}{secureLogin}) {
                  SendNPCTalk($self, $client, $msg, $index, $npcID, "secureLogin: $clientdata{$index}{secureLogin}");
                  if ($clientdata{$index}{secureLogin_requestCode}) {
                     SendNPCTalk($self, $client, $msg, $index, $npcID, $npcID, "secureLogin_requestCode: $clientdata{$index}{secureLogin_requestCode}");
                  } elsif (defined $clientdata{$index}{secureLogin_type}) {
                     SendNPCTalk($self, $client, $msg, $index, $npcID, "secureLogin_type: $clientdata{$index}{secureLogin_type}");
                  }
                  if ($clientdata{$index}{secureLogin_account}) {
                     SendNPCTalk($self, $client, $msg, $index, $npcID, "secureLogin_account: $clientdata{$index}{secureLogin_account}");
                  }
               }
               if ($clientdata{$index}{masterLogin_packet}) {
                  SendNPCTalk($self, $client, $msg, $index, $npcID, "masterLogin_packet: $clientdata{$index}{masterLogin_packet}");
               }
               if ($clientdata{$index}{gameLogin_packet}) {
                  SendNPCTalk($self, $client, $msg, $index, $npcID, "gameLogin_packet: $clientdata{$index}{gameLogin_packet}");
               }
               SendNPCTalkContinue($self, $client, $msg, $index, $npcID);
               
               if (defined $clientdata{$index}{serverType}) {
                  $clientdata{$index}{npc_talk_code} = 3;
               } else {
                  $clientdata{$index}{npc_talk_code} = 2.5;
               }

            } elsif ($response == 2) {
               # Use storage
               SendNPCTalk($self, $client, $msg, $index, $npcID, "[Hakore]");
               SendNPCTalk($self, $client, $msg, $index, $npcID, "Thank you for the visit. Go and multiply!");
               SendNpcTalkClose($self, $client, $msg, $index, $npcID);
            }

         } elsif ($npcID eq $npcID1) {
            if ($response == 1) {
               # Use storage
               my $data;
               $data .= pack("C2 v1", 0xF0, 0x01, 40) .
                  pack("v2 C2 v1 x10", 3, 501, 0, 1, 16) .
                  pack("v2 C2 v1 x10", 4, 909, 3, 1, 144);
               $data .= pack("v3", 0xF2, 2, 300);
               SendNpcImageShow($self, $client, $msg, $index, "kafra_04.bmp", 0xFF);
               SendNpcTalkClose($self, $client, $msg, $index, $npcID);
               $client->send($data);

            } elsif ($response == 2) {
               # Use storage
               SendNPCTalk($self, $client, $msg, $index, $npcID, "[Kafra]");
               SendNPCTalk($self, $client, $msg, $index, $npcID, "We Kafra Corp. always try to serve you the best.");
               SendNPCTalk($self, $client, $msg, $index, $npcID, "Please come again.");
               SendNpcTalkClose($self, $client, $msg, $index, $npcID);
            }
         }

      } elsif ($switch eq '00B9') { # npc talk continue
         my $npcID = substr($msg, 2, 4);
         if ($npcID eq $npcID0) {
            if ($clientdata{$index}{npc_talk_code} == 2) {
               # Show NPC response list
               SendNpcTalkResponses($self, $client, $msg, $index, $npcID, "Yes, please:No, thanks:");
               $clientdata{$index}{npc_talk_code} = 3;

            } else {
               SendNPCTalk($self, $client, $msg, $index, $npcID, "[Hakore]");
               if (!$clientdata{$index}{npc_talk_code}) {
                  if (!defined $clientdata{$index}{serverType}) {
                     SendNPCTalk($self, $client, $msg, $index, $npcID, "However, I regret that Openkore may not currently support your server.");
                  } elsif ($clientdata{$index}{serverType} == 7 || $clientdata{$index}{serverType} == 12) {
                     SendNPCTalk($self, $client, $msg, $index, $npcID, "However, I regret that Openkore does not yet fully support your server this time.");
                  } else {
                     SendNPCTalk($self, $client, $msg, $index, $npcID, "Based on my examination, I think Openkore supports your server.");
                     SendNPCTalk($self, $client, $msg, $index, $npcID, "I can tell you the possible server details you can use to make Openkore to connect to your server.");
                  }
                  SendNPCTalkContinue($self, $client, $msg, $index, $npcID);
                  $clientdata{$index}{npc_talk_code} = 1;

               } elsif ($clientdata{$index}{npc_talk_code} == 1) {
                  if ((!defined $clientdata{$index}{serverType}) || ($clientdata{$index}{serverType} == 7)) {
                     SendNPCTalk($self, $client, $msg, $index, $npcID, "Would you still like to hear the details?");
                  } else {
                     SendNPCTalk($self, $client, $msg, $index, $npcID, "Would you like to hear the details?");
                  }
                  SendNPCTalkContinue($self, $client, $msg, $index, $npcID);
                  $clientdata{$index}{npc_talk_code} = 2;
            
               } elsif ($clientdata{$index}{npc_talk_code} == 2.5) {
                  if (!defined $clientdata{$index}{serverType}) {
                     SendNPCTalk($self, $client, $msg, $index, $npcID, "As you can see, I can't find a matching serverType for your server.");
                     SendNPCTalk($self, $client, $msg, $index, $npcID, "Please make a trial-and-error using all available serverTypes, one of them might be able to work.");
                  } elsif ($clientdata{$index}{serverType} == 7 || $clientdata{$index}{serverType} == 12) {
                     SendNPCTalk($self, $client, $msg, $index, $npcID, "Like I said, your server is not yet fully supported by Openkore.");
                     SendNPCTalk($self, $client, $msg, $index, $npcID, "You can login to the server and do most basic tasks, but you cannot attack, sit or stand, or use skills.");
                  }
                  SendNPCTalkContinue($self, $client, $msg, $index, $npcID);
                  $clientdata{$index}{npc_talk_code} = 4;

               } elsif ($clientdata{$index}{npc_talk_code} == 3) {
                  SendNPCTalk($self, $client, $msg, $index, $npcID, "The values of ^2222DDip^000000 and ^2222DDport^000000 can be found on your client's (s)clientinfo.xml.");
                  SendNPCTalkContinue($self, $client, $msg, $index, $npcID);
                  $clientdata{$index}{npc_talk_code} = 4;

               } elsif ($clientdata{$index}{npc_talk_code} == 4) {
                  if (!defined $clientdata{$index}{serverType}) {
                     SendNPCTalk($self, $client, $msg, $index, $npcID, "If none of the serverTypes work, please inform the developers about this so we can support your server in future releases of Openkore.");
                     SendNPCTalk($self, $client, $msg, $index, $npcID, "Please visit ^2222DDhttp://forums.openkore.com/^000000");
                     SendNPCTalk($self, $client, $msg, $index, $npcID, "Thank you.");
                  } else {
                     if (($clientdata{$index}{serverType} == 7)
                        || ($clientdata{$index}{serverType} == 8)
                        || ($clientdata{$index}{serverType} == 9)
                        || ($clientdata{$index}{serverType} == 10)
                        || ($clientdata{$index}{serverType} == 11)
                        || ($clientdata{$index}{serverType} == 12)
                        || ($clientdata{$index}{masterLogin_packet})
                        || ($clientdata{$index}{gameLogin_packet})
                     ) {
                        SendNPCTalk($self, $client, $msg, $index, $npcID, "Please note that you can only connect to your server using Openkore SVN.");
                     } else {
                        SendNPCTalk($self, $client, $msg, $index, $npcID, "Openkore v.1.6.6 or later will work on your server.");
                     }
                     SendNPCTalk($self, $client, $msg, $index, $npcID, "For more info, please visit ^2222DDhttp://www.openkore.com/^000000");
                     SendNPCTalk($self, $client, $msg, $index, $npcID, "Good luck!");
                  }
                  SendNpcTalkClose($self, $client, $msg, $index, $npcID);
               }
            }

         } elsif ($npcID eq $npcID1) {
            # Show kafra response list
            SendNpcTalkResponses($self, $client, $msg, $index, $npcID, "Use Storage:Cancel:");
         }

      } elsif ($switch eq '0146') { # talk cancel
         my $npcID = substr($msg, 2, 4);
         if ($npcID eq $npcID1) {
            SendNpcImageShow($self, $client, $msg, $index, "kafra_04.bmp", 0xFF);
         }

      } elsif ($clientdata{$index}{mode}) {

         if (($switch eq '00F7' || $switch eq '0193') && (length($msg) == 2)) { # storage close
            my $data = pack("v1", 0xF8);
            $client->send($data);

         } elsif ($switch eq '00BF') { # emoticon
            my ($client, $code) = @_;
            my $data = pack("v1 a4", 0xC0, $accountID) . substr($msg, 2, 1);
            $clientdata{$index}{emoticonTime} = time;
            $client->send($data);

         } else {
            print "\nReceived packet $switch:\n";
            visualDump($msg, "$switch");

            # Just provide feedback in the RO Client about the unhandled packet
            # '008E' => ['self_chat', 'x2 Z*', [qw(message)]],
            my $data = pack("v2 a31", 0x8E, 35, "Sent packet $switch (" . length($msg) . " bytes).");
            if (timeOut($clientdata{$index}{emoticonTime}, 1.8)) {
               $clientdata{$index}{emoticonTime} = time;
               $data .= pack("v1 a4 C1", 0xC0, $accountID, 1);
            }

            # These following packets should reset the item inventory.
            # If you drop something from your inventory and the server didn't respond,
            # you will not be able to drop the item for the second test
            # This, however, does not cover item_use. YOu would have to relog
            # to test another item_use packet.
            #$data .= pack("v3", 0xAF, 3, 0);
            #$data .= pack("v3", 0xAF, 4, 0);

            # There are no other send packet that contains NPC ids as the last four byte
            # other than the talk and sendGetPlayerInfo packets.
            # Since most possible talk packets are handled above, we can assume that this is
            # a sendGetPlayerInfo packet.
            # Note that we have an NPC that is not named initially to allow a
            # sendGetPlayerInfo packet to be captured.)
            # '0095' => ['actor_info', 'a4 Z24', [qw(ID name)]],
            my $ID = substr($msg, length($msg) - 4, 4);
            if ($ID eq $npcID0) {
               $data .= pack("v1 a4 a24", 0x95, $npcID0, "Server Details Guide");
            } elsif ($ID eq $npcID1) {
               $data .= pack("v1 a4 a24", 0x95, $npcID1, "Kafra");
            }

            $client->send($data);
         }
      }
   }
}

# PACKET SENDING S->C

sub SendCharacterList
{
   my ($self, $client, $msg, $index) = @_;
   
   # Log
   print "Requested Char List (Standard)\n";
   
   # Wanted Block Size
   my $blocksize = $self->{type}->{$config{server_type}}->{charBlockSize} || 116; #defaults to 116

   # Packet Len, Total Characters and Total Slots
   my $totalchars = 2;
   my $totalslots = 12;
   my $len = $blocksize * $totalchars;
   
   # Character Block Pack String
   my $packstring = '';

   $packstring = 'a4 V9 v V2 v14 Z24 C8 v Z16 V x4 x4 x4' if $blocksize == 144;
   $packstring = 'a4 V9 v V2 v14 Z24 C8 v Z16 x4 x4' if $blocksize == 136;
   $packstring = 'a4 V9 v V2 v14 Z24 C8 v Z16 x4' if $blocksize == 132;
   $packstring = 'a4 V9 v V2 v14 Z24 C8 v Z16' if $blocksize == 128;
   $packstring = 'a4 V9 v V2 v14 Z24 C6 v2 x4' if $blocksize == 116;
   $packstring = 'a4 V9 v V2 v14 Z24 C6 v2' if $blocksize == 112;
   $packstring = 'a4 V9 v17 Z24 C6 v2' if $blocksize == 108;
   $packstring = 'a4 V9 v17 Z24 C6 v' if $blocksize == 106;
   
   # Unknown CharBlockSize
   if ( length($packstring) == 0 ) { print "Unknown CharBlockSize : $blocksize\n"; return; }
   
   # Character Block Format
   my($cID,$exp,$zeny,$jobExp,$jobLevel,$opt1,$opt2,$option,$stance,$manner,$statpt,$hp,$maxHp,$sp,$maxSp,$walkspeed,$jobId,$hairstyle,$weapon,$level,$skillpt,$headLow,$shield,$headTop,$headMid,$hairColor,$clothesColor,$name,$str,$agi,$vit,$int,$dex,$luk,$slot,$rename) = 0;

   # Preparing Begin of Character List Packet
   my $data;
   if ($self->{type}->{$config{server_type}}->{charListPacket} eq '0x82d') {
      $data = $accountID . pack("v2 C5 a20", 0x82d, $len + 29,$totalchars,0,0,0,$totalchars,-0); # 29 = v2 C5 a20 size for bRO
   } else {
      $data = $accountID . pack("v v C3", 0x6b, $len + 7, $totalslots, -1, -1);
   }
   
   # Character Block
   my $block;
   
   # Filling Character 1 Block
   $cID = $charID;   $hp = 10000; $maxHp = 10000; $sp = 10000; $maxSp = 10000; $hairstyle = 1; $level = 99; $headTop = 0; $hairColor = 6;
   $name = "Poseidon"; $str = 1; $agi = 1; $vit = 1; $int = 1; $dex = 1; $luk = 1;   $exp = 1; $zeny = 1; $jobExp = 1; $jobLevel = 50; $slot = 0; $rename = 0;
   
   # Preparing Character 1 Block
   $block = pack($packstring,$cID,$exp,$zeny,$jobExp,$jobLevel,$opt1,$opt2,$option,$stance,$manner,$statpt,$hp,$maxHp,$sp,$maxSp,$walkspeed,$jobId,$hairstyle,$weapon,$level,$skillpt,$headLow,$shield,$headTop,$headMid,$hairColor,$clothesColor,$name,$str,$agi,$vit,$int,$dex,$luk,$slot,$rename);

   # Attaching Block
   $data .= $block;
   
   # Filling Character 2 Block
   $cID = $charID;   $hp = 10000; $maxHp = 10000; $sp = 10000; $maxSp = 10000; $hairstyle = 1; $level = 99; $headTop = 0; $hairColor = 6;
   $name = "Poseidon Dev"; $str = 1; $agi = 1; $vit = 1; $int = 1; $dex = 1; $luk = 1;   $exp = 1; $zeny = 1; $jobExp = 1; $jobLevel = 50; $slot = 1; $rename = 0;
   
   # Preparing Character 2 Block
   $block = pack($packstring,$cID,$exp,$zeny,$jobExp,$jobLevel,$opt1,$opt2,$option,$stance,$manner,$statpt,$hp,$maxHp,$sp,$maxSp,$walkspeed,$jobId,$hairstyle,$weapon,$level,$skillpt,$headLow,$shield,$headTop,$headMid,$hairColor,$clothesColor,$name,$str,$agi,$vit,$int,$dex,$luk,$slot,$rename);      
   
   # Attaching Block
   $data .= $block;      
   
   # Measuring Size of Block
   print "Wanted CharBlockSize : $blocksize\n";      
   print "Built CharBlockSize : " . length($block) . "\n";

   $client->send($data);
}

sub SendMapLogin {
   my ($self, $client, $msg, $index) = @_;

   # '0073' => ['map_loaded','x4 a3',[qw(coords)]]
   my $data;
   
   if ( $config{server_type} !~ /^bRO/ ) { $data .= $accountID; } #<- This is Server Type Based !!
   $data .= pack("C*", 0x73, 0x00) . pack("V", getTickCount) . getCoordString($posX, $posY, 1) . pack("C*", 0x05, 0x05);

   if ($clientdata{$index}{mode}) {
      $data .= pack("C2 v1", 0x0F, 0x01, 226) .
         # skillID targetType level sp range skillName
         pack("v2 x2 v3 a24 C1", 1, 0, 9, 0, 1, "NV_BASIC" . chr(0) . "GetMapInfo" . chr(0x0A), 0) .
         pack("v2 x2 v3 a24 C1", 24, 4, 1, 10, 10, "AL_RUWACH", 0) . # self skill test
         pack("v2 x2 v3 a24 C1", 25, 2, 1, 10, 9, "AL_PNEUMA", 0) . # location skill test
         pack("v2 x2 v3 a24 C1", 26, 4, 2, 9, 1, "AL_TELEPORT", 0) . # self skill test
         pack("v2 x2 v3 a24 C1", 27, 2, 4, 26, 9, "AL_WARP", 0) . # location skill test
         pack("v2 x2 v3 a24 C1", 28, 16, 10, 40, 9, "AL_HEAL", 0); # target skill test
   }
   
   $client->send($data);
   
   $client->{connectedToMap} = 1;   
}

sub SendGoToCharSelection
{
   my ($self, $client, $msg, $index) = @_;
   
   # Log   
   print "Requested Char Selection Screen\n";   
   
   $client->send(pack("v v", 0xB3, 1));
}

sub SendQuitGame
{
   my ($self, $client, $msg, $index) = @_;
   
   # Log
   print "Requested Quit Game...\n";
   
   $client->send(pack("v v", 0x18B, 0));   
}

sub SendLookTo
{
   my ($self, $client, $msg, $index, $ID, $to) = @_;
   
   # Make Poseidon look to front
   $client->send(pack('v1 a4 C1 x1 C1', 0x9C, $ID, 0, $to));
}

sub SendUnitInfo      
{
   my ($self, $client, $msg, $index, $ID, $name) = @_;
   
   # Let's not wait for the client to ask for the unit info
   # '0095' => ['actor_info', 'a4 Z24', [qw(ID name)]],
   $client->send(pack("v1 a4 a24", 0x95, $ID, $name));
}

sub SendSystemChatMessage
{
   my ($self, $client, $msg, $index, $message) = @_;
   
   # '009A' => ['system_chat', 'v Z*', [qw(len message)]],
   $client->send(pack("v2 a32", 0x9A, 36, $message));
}

sub SendShowNPC
{
   my ($self, $client, $msg, $index, $obj_type, $GID, $SpriteID, $X, $Y, $MobName) = @_;
   
   # Packet Structure
   my ($object_type,$NPCID,$walk_speed,$opt1,$opt2,$option,$type,$hair_style,$weapon,$lowhead,$shield,$tophead,$midhead,$hair_color,$clothes_color,$head_dir,$guildID,$emblemID,$manner,$opt3,$stance,$sex,$xSize,$ySize,$lv,$font,$name) = 0;

   # Building NPC Data
   $object_type = $obj_type;
   $NPCID = $GID;
   $walk_speed = 0x1BD;
   $type = $SpriteID;
   $lv = 1;
   $name = $MobName;
   
   # '0856' => ['actor_exists', 'v C a4 v3 V v11 a4 a2 v V C2 a3 C3 v2 Z*', [qw(len object_type ID walk_speed opt1 opt2 option type hair_style weapon shield lowhead tophead midhead hair_color clothes_color head_dir costume guildID emblemID manner opt3 stance sex coords xSize ySize lv font name)]], # -1 # spawning provided by try71023
   my $dbuf;
   if ( $config{server_type} !~ /^bRO/ ) { $dbuf .= pack("C", $object_type); } #<- This is Server Type Based !!
   $dbuf .= pack("a4 v3 V v11 a4 a2 v V C2",$NPCID,$walk_speed,$opt1,$opt2,$option,$type,$hair_style,$weapon,$lowhead,$shield,$tophead,$midhead,$hair_color,$clothes_color,$head_dir,$guildID,$emblemID,$manner,$opt3,$stance,$sex);
   $dbuf .= getCoordString($X, $Y, 1);
   $dbuf .= pack("C2 v2",$xSize,$ySize,$lv,$font);
   $dbuf .= pack("Z" . length($name),$name);
   my $opcode;
   if ( $config{server_type} !~ /^bRO/ ) { $opcode = 0x858; } #<- This is Server Type Based !!
   $client->send(pack("v v",$opcode,length($dbuf) + 4) . $dbuf);
}

sub SendShowItemOnGround
{
   my ($self, $client, $msg, $index, $ID, $SpriteID, $X, $Y) = @_;
   
   # '009D' => ['item_exists', 'a4 v1 x1 v3', [qw(ID type x y amount)]]
   $client->send(pack("v1 a4 v1 x1 v3 x2", 0x9D, $ID, $SpriteID, $posX + 1, $posY - 1, 1));   
}

sub SendNPCTalk
{
   my ($self, $client, $msg, $index, $npcID, $message) = @_;
   
   # '00B4' => ['npc_talk', 'v a4 Z*', [qw(len ID msg)]]
   my $dbuf = pack("a" . length($message), $message);
   $client->send(pack("v2 a4", 0xB4, (length($dbuf) + 8), $npcID) . $dbuf);
}

sub SendNPCTalkContinue
{
   my ($self, $client, $msg, $index, $npcID) = @_;
   
   # '00B5' => ['npc_talk_continue', 'a4', [qw(ID)]]
   $client->send(pack("v a4", 0xB5, $npcID));
}

sub SendNpcTalkClose
{
   my ($self, $client, $msg, $index, $npcID) = @_;
   
   # '00B6' => ['npc_talk_close', 'a4', [qw(ID)]]
   $client->send(pack("v a4", 0xB6, $npcID));   
}

sub SendNpcTalkResponses
{
   my ($self, $client, $msg, $index, $npcID, $message) = @_;
   
   # '00B7' => ['npc_talk', 'v a4 Z*', [qw(len ID msg)]]
   my $dbuf = pack("a" . length($message), $message);
   $client->send(pack("v2 a4", 0xB7, (length($dbuf) + 8), $npcID) . $dbuf);   
}

sub SendNpcImageShow
{
   my ($self, $client, $msg, $index, $image, $type) = @_;

   # Type = 0xFF = Hide Image
   # Type = 0x02 = Show Image
   # '01B3' => ['npc_image', 'Z64 C', [qw(npc_image type)]]
   $client->send(pack("v a64 C1", 0x1B3, $image, $type));
}

# SERVER TASKS

sub PerformMapLoadedTasks
{
   my ($self, $client, $msg, $index) = @_;
   
   # Looking to Front
   SendLookTo($self, $client, $msg, $index, $accountID, 4);
   
   # Let's not wait for the client to ask for the unit info
   SendUnitInfo($self, $client, $msg, $index, $accountID, 'Poseidon' . (($clientdata{$index}{mode} ? ' Dev' : '')));
   
   # Global Announce
   SendSystemChatMessage($self, $client, $msg, $index, "Welcome to the Poseidon Server !");

   # Show an NPC
   SendShowNPC($self, $client, $msg, $index, 1, $npcID0, 86, $posX + 3, $posY + 4, "Server Details Guide");
   SendLookTo($self, $client, $msg, $index, $npcID0, 3);
   SendUnitInfo($self, $client, $msg, $index, $npcID0, "Server Details Guide");

   # Dev Mode (Char Slot 1)
   if ($clientdata{$index}{mode})
   {
      # Show an NPC (Kafra)
      SendShowNPC($self, $client, $msg, $index, 1, $npcID1, 114, $posX + 5, $posY + 3, "Kafra NPC");
      SendLookTo($self, $client, $msg, $index, $npcID1, 4);
      SendUnitInfo($self, $client, $msg, $index, $npcID1, "Kafra NPC");         
      
      # Show a monster
      SendShowNPC($self, $client, $msg, $index, 5, $monsterID, 1002, $posX - 2, $posY - 1, "Poring");
      SendLookTo($self, $client, $msg, $index, $monsterID, 3);
      SendUnitInfo($self, $client, $msg, $index, $monsterID, "Poring");
      
      # Show an item on ground
      SendShowItemOnGround($self, $client, $msg, $index, $itemID, 512, $posX + 1, $posY - 1);
   }
}

1;





Last edited by Break on 08 Apr 2016, 13:20, edited 1 time in total.

Top
 Profile  
 
 Post subject: Re: Request GG Problem Poseidon
PostPosted: 10 Mar 2016, 00:37 
Offline
Noob
Noob

Joined: 07 Jun 2010, 17:47
Posts: 3
Ola,
Tenta alterar as keys no servertype

decrypt_mid_keys 0x708a594d 0x24461949 0x5e660a4b # K M A

Voce esta conseguindo logar mais de um bot por poseidon??


Top
 Profile  
 
 Post subject: Re: Request GG Problem Poseidon
PostPosted: 10 Mar 2016, 00:39 
Offline
Noob
Noob

Joined: 07 Jun 2010, 17:47
Posts: 3
Ola,

Modifica a key no servertype decrypt_mid_keys 0x708a594d 0x24461949 0x5e660a4b # K M A

Esta conseguindo rodar mais de um bot por poseidon?


Top
 Profile  
 
 Post subject: Re: Request GG Problem Poseidon
PostPosted: 10 Mar 2016, 17:36 
Offline
Noob
Noob

Joined: 01 Apr 2015, 16:41
Posts: 11
Ja utilizo essas keys.
No momento não estou rodando nenhum pois o poseidon não responde. rsrs
Mais quando responde só rodo 1 kore tbm por poseidon.
Quero mais rodar para por lojinha devido a não tomar dcs.


Top
 Profile  
 
 Post subject: Re: Request GG Problem Poseidon
PostPosted: 10 Mar 2016, 21:00 
Offline
Noob
Noob

Joined: 07 Jun 2010, 17:47
Posts: 3
Realmente ele é mais estável que o xKore 2.
Eu vou nao estou conseguindo obter resposta do GG tambem, a request nao volta pro openkore.

Tentei usar seu QueryServer.pm mas parece que precisa de alguns arquivos e pastas extras, certo?

Vou testar por aqui, se obtiver algo êxito, posto.

Parece que o pessoal do bRO deu uma abandonada no Poseidon, todo mundo usando xKore.


Top
 Profile  
 
 Post subject: Re: Request GG Problem Poseidon
PostPosted: 11 Mar 2016, 10:55 
Offline
Noob
Noob

Joined: 11 Mar 2016, 10:52
Posts: 6
Eu tenho muito interesse em usar o poseidon, mas nao tenho os arquivos para fazer isso. Um de vocês dois poderia me mandar PM pra me ajudar ? Eu entendo bastante de redes, trabalho com isso, queria começar a usar pra ver se consigo concertar o problema de 1 poseidon por boy.

Abs.,


Top
 Profile  
 
 Post subject: Re: Request GG Problem Poseidon
PostPosted: 12 Mar 2016, 13:00 
Offline
Noob
Noob

Joined: 01 Apr 2015, 16:41
Posts: 11
Os arquivos são esses o QueryServe e o RagnarokServer.
E add a key semanal no Serves.txt


Top
 Profile  
 
 Post subject: Re: Request GG Problem Poseidon
PostPosted: 21 Mar 2016, 13:26 
Offline
Noob
Noob

Joined: 11 Mar 2016, 10:52
Posts: 6
Break wrote:
Os arquivos são esses o QueryServe e o RagnarokServer.
E add a key semanal no Serves.txt


Peguei os 3 arquivos dessa ultima semana.
Agora como consigo achar a key pra atualizar o servertype.txt ?

Abs.,


Top
 Profile  
 
 Post subject: Re: Request GG Problem Poseidon
PostPosted: 22 Mar 2016, 10:56 
Offline
Noob
Noob

Joined: 11 Mar 2016, 10:52
Posts: 6
Clou wrote:
Break wrote:
Os arquivos são esses o QueryServe e o RagnarokServer.
E add a key semanal no Serves.txt


Peguei os 3 arquivos dessa ultima semana.
Agora como consigo achar a key pra atualizar o servertype.txt ?

Abs.,


Na verdade, alguem poderia me mandar o servertype.txt ??


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 38 posts ]  Go to page 1, 2, 3, 4  Next

All times are UTC - 5 hours [ DST ]


Who is online

Users browsing this forum: No registered users and 1 guest


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group