pRO's Update! Login Pincode..(similar to bRO)

Philippines

Moderators: waferbaron, Moderators

Forum rules
This server is currently not maintained and tables folder (including connection info) is outdated. Read the wiki for instructions on how to update those information. Please contribute your updated info. Contact Cozzie to join the team as a regular server supporter.
Message
Author
vinceaar0n00
Noob
Noob
Posts: 12
Joined: 08 Aug 2014, 02:14
Noob?: Yes

Re: pRO's Update! Login Pincode..(similar to bRO)

#281 Post by vinceaar0n00 »

heres my servers.txt

tables/servers.txt

Code: Select all

[Philippines - pRO: Valkyrie]
ip 202.57.118.235
port 6900
master_version 15
version 1
secureLogin 1
secureLogin_type 0
secureLogin_requestCode
secureLogin_account 0
serverType pRO
patchserver wpatch.ragnarok.com.ph
patchpath /patch50
storageEncryptKey 0x050B6F79, 0x0202C179, 0x0E20120, 0x04FA43E3, 0x0179B6C8, 0x05973DF2, 0x07D8D6B, 0x08CB9ED9
serverEncoding Tagalog
charBlockSize 144
gameGuard 1
recvpackets recvpackets.txt
addTableFolders pRO
pinCode 1


Heres my pRO.pm

\src\Network\Receive\pRO.pm

Code: Select all

#########################################################################
#  OpenKore - Network subsystem
#  Copyright (c) 2006 OpenKore Team
#
#  This software is open source, licensed under the GNU General Public
#  License, version 2.
#  Basically, this means that you're allowed to modify and distribute
#  this software. However, if you distribute modified versions, you MUST
#  also distribute the source code.
#  See http://www.gnu.org/licenses/gpl.html for the full license.
#########################################################################
# pRO (Philippines)
# Servertype overview: http://wiki.openkore.com/index.php/ServerType
package Network::Receive::pRO;

use strict;
use base qw(Network::Receive::ServerType0);

use Globals;
use Log qw(message warning error debug);
use Translation;
use Misc;
use Utils qw(timeOut getFormattedDate);
use I18N qw(bytesToString stringToBytes);

use Time::HiRes qw(time);

sub new {
   my ($class) = @_;
   my $self = $class->SUPER::new(@_);
   my %packets = (
      #'006D' => ['character_creation_successful', 'a4 V9 v V2 v14 Z24 C6 v2', [qw(charID exp zeny exp_job lv_job opt1 opt2 option stance manner points_free hp hp_max sp sp_max walk_speed type hair_style weapon lv points_skill lowhead shield tophead midhead hair_color clothes_color name str agi vit int dex luk slot renameflag)]],
      '0097' => ['private_message', 'v Z24 V Z*', [qw(len privMsgUser flag privMsg)]], # -1
      #'082D' => ['received_characters_info', 'x2 C5 x20', [qw(normal_slot premium_slot billing_slot producible_slot valid_slot)]],
      #'099D' => ['received_characters', 'v a*', [qw(len charInfo)]],
   );

   foreach my $switch (keys %packets) {
      $self->{packet_list}{$switch} = $packets{$switch};
   }

   my %handlers = qw(
      received_characters 099D
      actor_exists 0856
      actor_connected 0857
      actor_moved 0858
      account_id 0283
   );
   $self->{packet_lut}{$_} = $handlers{$_} for keys %handlers;
   
   return $self;
}

=pod
sub received_characters_info {
   my ($self, $args) = @_;

   Scalar::Util::weaken(my $weak = $self);
   my $timeout = {timeout => 6, time => time};

   $self->{charSelectTimeoutHook} = Plugins::addHook('Network::serverConnect/special' => sub {
      if ($weak && timeOut($timeout)) {
         $weak->received_characters({charInfo => '', RAW_MSG_SIZE => 4});
      }
   });

   $self->{charSelectHook} = Plugins::addHook(charSelectScreen => sub {
      if ($weak) {
         Plugins::delHook(delete $weak->{charSelectTimeoutHook}) if $weak->{charSelectTimeoutHook};
      }
   });

   $timeout{charlogin}{time} = time;

   $self->received_characters($args);
}


sub received_characters {
   return if ($net->getState() == Network::IN_GAME);
   my ($self, $args) = @_;
   $net->setState(Network::CONNECTED_TO_LOGIN_SERVER);

   $charSvrSet{normal_slot} = $args->{normal_slot} if (exists $args->{normal_slot});
   $charSvrSet{premium_slot} = $args->{premium_slot} if (exists $args->{premium_slot});
   $charSvrSet{billing_slot} = $args->{billing_slot} if (exists $args->{billing_slot});
   $charSvrSet{producible_slot} = $args->{producible_slot} if (exists $args->{producible_slot});
   $charSvrSet{valid_slot} = $args->{valid_slot} if (exists $args->{valid_slot});

   undef $conState_tries;

   Plugins::callHook('parseMsg/recvChars', $args->{options});
   if ($args->{options} && exists $args->{options}{charServer}) {
      $charServer = $args->{options}{charServer};
   } else {
      $charServer = $net->serverPeerHost . ":" . $net->serverPeerPort;
   }

   # PACKET_HC_ACCEPT_ENTER2 contains no character info
   return unless exists $args->{charInfo};

   my $blockSize = $self->received_characters_blockSize();
   for (my $i = $args->{RAW_MSG_SIZE} % $blockSize; $i < $args->{RAW_MSG_SIZE}; $i += $blockSize) {
      #exp display bugfix - chobit andy 20030129
      my $unpack_string = $self->received_characters_unpackString;
      # TODO: What would be the $unknown ?
      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, $unknown, $mapname, $deleteDate) =
         unpack($unpack_string, substr($args->{RAW_MSG}, $i));
      $chars[$slot] = new Actor::You;

      # Re-use existing $char object instead of re-creating it.
      # Required because existing AI sequences (eg, route) keep a reference to $char.
      $chars[$slot] = $char if $char && $char->{ID} eq $accountID && $char->{charID} eq $cID;

      $chars[$slot]{ID} = $accountID;
      $chars[$slot]{charID} = $cID;
      $chars[$slot]{exp} = $exp;
      $chars[$slot]{zeny} = $zeny;
      $chars[$slot]{exp_job} = $jobExp;
      $chars[$slot]{lv_job} = $jobLevel;
      $chars[$slot]{hp} = $hp;
      $chars[$slot]{hp_max} = $maxHp;
      $chars[$slot]{sp} = $sp;
      $chars[$slot]{sp_max} = $maxSp;
      $chars[$slot]{jobID} = $jobId;
      $chars[$slot]{hair_style} = $hairstyle;
      $chars[$slot]{lv} = $level;
      $chars[$slot]{headgear}{low} = $headLow;
      $chars[$slot]{headgear}{top} = $headTop;
      $chars[$slot]{headgear}{mid} = $headMid;
      $chars[$slot]{hair_color} = $hairColor;
      $chars[$slot]{clothes_color} = $clothesColor;
      $chars[$slot]{name} = $name;
      $chars[$slot]{str} = $str;
      $chars[$slot]{agi} = $agi;
      $chars[$slot]{vit} = $vit;
      $chars[$slot]{int} = $int;
      $chars[$slot]{dex} = $dex;
      $chars[$slot]{luk} = $luk;
      $chars[$slot]{sex} = $accountSex2;

      $chars[$slot]{deleteDate} = getFormattedDate($deleteDate) if ($deleteDate);
      $chars[$slot]{nameID} = unpack("V", $chars[$slot]{ID});
      $chars[$slot]{name} = bytesToString($chars[$slot]{name});
   }

   my $nChars = 0;
   foreach (@chars) { $nChars++ if($_); }

   # FIXME better support for multiple received_characters packets
   if ($args->{switch} eq '099D' && $args->{RAW_MSG_SIZE} >= ($blockSize * 3)) {
      $net->setState(1.5);
      return;
   }

   message T("Received characters from Character Server\n"), "connection";

   if (charSelectScreen(1) == 1) {
         $firstLoginMap = 1;
         $startingzeny = $chars[$config{'char'}]{'zeny'} unless defined $startingzeny;
         $sentWelcomeMessage = 1;
   }
}
=cut

*parse_quest_update_mission_hunt = *Network::Receive::ServerType0::parse_quest_update_mission_hunt_v2;
*reconstruct_quest_update_mission_hunt = *Network::Receive::ServerType0::reconstruct_quest_update_mission_hunt_v2;

1;

heres my RagnarokServer.pm

src\Poseidon\RagnarokServer.pm

Code: Select all

###########################################################
# 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;

   print "Received packet: $switch\n";
   
   # 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("C*", 0x00, 0x00, 0x00, 0x00) . 
            pack("x26") . pack("C1", $sex);
            
            print "$data\n";


            $client->send($data);
            
            $data = 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, $switch);

      # 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' || ($switch eq '0360') ) ) && (($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' || $switch eq '09D0') { # 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}++;

   } elsif ($switch eq '09A1') {
      SendCharacterList($self, $client, $msg, $index, $switch);

   } elsif ($switch eq '08B8') {
      my $seed = 'seed';
      my $data = pack("C*", 0xB9, 0x08);
      $data .= pack("V a4 v", $seed, $accountID, 0);

      $client->send($data);

   } 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, $switch) = @_;
   
   # Log
   print "Requested Char List (Standard)\n";
   if ($switch eq '0065') {
      my $blocksize = $self->{type}->{$config{server_type}}->{charBlockSize} || 116; #defaults to 116
      my $totalslots = 12;
      my $data;
      
      $data = pack("V", getTickCount);
      
      $client->send($data);
      
      $data = pack("C*", 0x2D, 0x08);
      $data .= pack("C*", 0x1D, 0x00);
      $data .= pack("C*", 0x0C, 0x00, 0x00, 0x0C, 0x0C);
      $data .= pack("x20");

      print "$data\n";
      
      print "Wanted CharBlockSize : $blocksize\n";      
      #print "Built CharBlockSize : " . length($block) . "\n";

      $client->send($data);

      $data = pack("C3 x3", 0xA0, 0x09, 0x01);
      $client->send($data);

   } elsif ($switch eq '09A1') {
      # 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;
      $data = pack("C2 v", 0x9D, 0x09, $len+4);
=pod
      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);
      }
=cut
   
      # 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);

      #pinCode
      my $seed = 'seed';
      $data = pack("C*", 0xB9, 0x08);
      $data .= pack("V a4 v", $seed, $accountID, 1);

      $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 .= pack("C*", 0x83, 0x02) . $accountID; } #<- This is Server Type Based !!
   $data .= pack("C*", 0xEB, 0x02) . pack("V", getTickCount) . getCoordString($posX, $posY, 1) . pack("C*", 0x05, 0x05) . 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;


vinceaar0n00
Noob
Noob
Posts: 12
Joined: 08 Aug 2014, 02:14
Noob?: Yes

Re: pRO's Update! Login Pincode..(similar to bRO)

#282 Post by vinceaar0n00 »

heres my poseidon.txt
control/poseidon.txt

Code: Select all

# Ragnarok Server
# Here you'll define the IP Address and the Port where Poseidon
# will keep waiting for your ragnarok online client to connect.
ragnarokserver_ip=192.168.1.3
ragnarokserver_port=6900

# Query Server
# Here you'll define the IP Address and the Port where Poseidon
# will keep waiting for open kore to connect and send the GG/HS queries.
queryserver_ip=127.0.0.1
queryserver_port=24390

# Server Type
# Here you have to specify your current server type in order
# to the poseidon operate properly !
# The available server types for now are : Default, bRO_.* (check servertypes.txt)
# You should modify this if you're having problems with char list.
server_type=pRO

# Char Block Size
# Here you can specify the desired CharBlockSize your client requires
# The available block sizes are : 106, 108, 112, 116, 128, 132 and 136
CharBlockSize=144

make sure you have these lines in config.txt in control folder

Code: Select all

# Poseidon Settings (http://wiki.openkore.com/index.php/PoseidonServer)
# They must be the same as Query Server config in Poseidon.txt
poseidonServer 127.0.0.1
poseidonPort 24390


after i did these modifications i transfered my openkore folder to my virtual machine
modified the ip address of the machine depending on the gateway/ip of the router

my router's gateway is 192.168.1.1 so i used

Host pc
IP 192.168.1.2
Sub 255.255.255.0
Gatw 192.168.1.1

Virtual Pc
IP 192.168.1.3
Sub 255.255.255.0
Gatw 192.168.1.1
heres my servertypes.txt

src\Poseidon\servertypes.txt

Code: Select all

[Default]
decrypt_mid 0
charBlockSize 116
charListPacket 0x6b
maploginPacket 0000
[bRO_2012-09-19a]
decrypt_mid 1
decrypt_mid_keys 0x26977a6f 0x374e3b8e 0x4dba6c1e # K M A
charBlockSize 116
charListPacket 0x82d
maploginPacket 022D
[bRO_2012-09-26a]
decrypt_mid 1
decrypt_mid_keys 0x146f5964 0x76792070 0x1fa30c53 # K M A
charBlockSize 116
charListPacket 0x82d
maploginPacket 088E
[bRO_2012-10-03a]
decrypt_mid 1
decrypt_mid_keys 0x5c18014b 0x503e1282 0x6e6b29c1 # K M A
charBlockSize 116
charListPacket 0x82d
maploginPacket 0366
[tRO_2013-07-09a]
decrypt_mid 1
decrypt_mid_keys 0x6441767a 0x71020102 0x48c21f02 # K A M
charBlockSize 144
[pRO]
charBlockSize 144
heres my DirectConnection.pm
src\Network\DirectConnection.pm

Code: Select all

#########################################################################
#  OpenKore - Networking subsystem
#  This module contains functions for sending packets to the server.
#
#  This software is open source, licensed under the GNU General Public
#  License, version 2.
#  Basically, this means that you're allowed to modify and distribute
#  this software. However, if you distribute modified versions, you MUST
#  also distribute the source code.
#  See http://www.gnu.org/licenses/gpl.html for the full license.
#
#  $Revision: 7069 $
#  $Id: Network.pm 7069 2010-01-16 02:23:00Z klabmouse $
#
#########################################################################
##
# MODULE DESCRIPTION: Connection handling
#
# The Network module handles connections to the Ragnarok Online server.
# This module only handles connection issues, and nothing else. It doesn't do
# anything with the actual data. Network data handling is performed by
# the @MODULE(Network::Receive) and Network::Receive::ServerTypeX classes.
#
# The submodule @MODULE(Network::Send) contains functions for sending all
# kinds of messages to the RO server.
#
# Please also read <a href="http://wiki.openkore.com/index.php/Network_subsystem">the
# network subsystem overview.</a>
#
# This implementation establishes a direct connection to the RO server.
# Note that there are alternative implementations for this interface: @MODULE(Network::XKore),
# @MODULE(Network::XKore2) and @MODULE(Network::XKoreProxy)

package Network::DirectConnection;

use strict;
use Modules 'register';
use Exporter;
use base qw(Exporter);
use Time::HiRes qw(time);
use IO::Socket::INET;
use encoding 'utf8';
use Scalar::Util;
use File::Spec;

use Globals;
use Log qw(message warning error);
use Misc qw(chatLog);
use Network;
use Network::Send ();
use Plugins;
use Settings;
use Interface;
use Utils qw(dataWaiting timeOut);
use Utils::Exceptions;
use Translation;

##
# Network::DirectConnection->new([wrapper])
# wrapper: If this object is to be wrapped by another object which is interface-compatible
#          with the Network::DirectConnection class, then specify the wrapper object here. The message
#          sender will use this wrapper to send socket data. Internally, the reference to the wrapper
#          will be stored as a weak reference.
#
# Create a new Network::DirectConnection object. The connection is not yet established.
sub new {
	my ($class, $wrapper) = @_;
	my %self;

	$self{remote_socket} = new IO::Socket::INET;
	if ($wrapper) {
		$self{wrapper} = $wrapper;
		Scalar::Util::weaken($self{wrapper});
	}

	return bless \%self, $class;
}

##
# int $net->version()
#
# Returns the implementation number this object.
sub version {
	return 0;
}

sub DESTROY {
	my $self = shift;
	
	$self->serverDisconnect();
}


######################
## Server Functions ##
######################

##
# boolean $net->serverAliveServer()
#
# Check whether the connection to the server is alive.
sub serverAlive {
	return $_[0]->{remote_socket} && $_[0]->{remote_socket}->connected();
}

##
# String $net->serverPeerHost()
#
# If the connection to the server is alive, returns the host name of the server.
# Otherwise, returns undef.
sub serverPeerHost {
	return $_[0]->{remote_socket}->peerhost if ($_[0]->serverAlive);
	return undef;
}

##
# int $net->serverPeerPort()
#
# If the connection to the server is alive, returns the port number of the server.
# Otherwise, returns undef.
sub serverPeerPort {
	return $_[0]->{remote_socket}->peerport if ($_[0]->serverAlive);
	return undef;
}

##
# $net->serverConnect(String host, int port)
# host: the host name/IP of the RO server to connect to.
# port: the port number of the RO server to connect to.
#
# Establish a connection to a Ragnarok Online server.
#
# This function is used internally by $net->checkConnection() and should not be used directly.
sub serverConnect {
	my $self = shift;
	my $host = shift;
	my $port = shift;
	my $return = 0;

	Plugins::callHook('Network::connectTo', {
		socket => \$self->{remote_socket},
		return => \$return,
		host => $host,
		port => $port
	});
	return if ($return);

	message TF("Connecting (%s:%s)... ", $host, $port), "connection";
	$self->{remote_socket} = new IO::Socket::INET(
			LocalAddr	=> $config{bindIp} || undef,
			PeerAddr	=> $host,
			PeerPort	=> $port,
			Proto		=> 'tcp',
			Timeout		=> 4);
	($self->{remote_socket} && inet_aton($self->{remote_socket}->peerhost()) eq inet_aton($host)) ?
		message T("connected\n"), "connection" :
		error(TF("couldn't connect: %s (error code %d)\n", "$!", int($!)), "connection");
	if ($self->getState() != Network::NOT_CONNECTED) {
		$incomingMessages->nextMessageMightBeAccountID();
	}
}

##
# void $net->serverSend(Bytes data)
#
# If the connection to the server is alive, send data to the server.
# Otherwise, this method does nothing.
sub serverSend {
	my $self = shift;
	my $msg = shift;
	if ($self->serverAlive) {
		if (Plugins::hasHook("Network::serverSend/pre")) {
			Plugins::callHook("Network::serverSend/pre", { msg => \$msg });
		}
		if (defined $msg) {
			$self->{remote_socket}->send($msg);
			if (Plugins::hasHook("Network::serverSend")) {
				Plugins::callHook("Network::serverSend", { msg => $msg });
			}
		}
	}
}

##
# Bytes $net->serverRecv()
#
# Receive data from the RO server.
sub serverRecv {
	my $self = shift;
	my $msg;
	
	return undef unless (dataWaiting(\$self->{remote_socket}));
	
	$self->{remote_socket}->recv($msg, 1024 * 32);
	if (Plugins::hasHook("Network::serverRecv")) {
		Plugins::callHook("Network::serverRecv", { msg => \$msg });
	}
	if (!defined($msg) || length($msg) == 0) {
		# Connection from server closed.
		close($self->{remote_socket});
		return undef;
	}
	return $msg;
}

##
# Bytes $net->serverAddress()
#
# Return the server's raw address.
sub serverAddress {
	my ($self) = @_;
	return $self->{remote_socket}->sockaddr();
}

##
# $net->serverDisconnect()
#
# Disconnect from the current Ragnarok Online server.
#
# This function is used internally by $net->checkConnection() and should not be used directly.
sub serverDisconnect {
	my $self = shift;
	
	if ($self->serverAlive) {
		if ($incomingMessages && length(my $incoming = $incomingMessages->getBuffer)) {
				warning TF("Incoming data left in the buffer:\n");
				Misc::visualDump($incoming);
				
				if (defined(my $rplen = $incomingMessages->{rpackets}{my $switch = Network::MessageTokenizer::getMessageID($incoming)})) {
					my $inlen = do { no encoding 'utf8'; use bytes; length $incoming };
					if (($rplen->{length} > $inlen) || ($rplen->{minLength} > $inlen)) { # check for minLength too, if defined
						warning TF("Only %d bytes in the buffer, when %s's packet length is supposed to be %d (wrong recvpackets?)\n", $inlen, $switch, $rplen);
					}
				}
		}

		$messageSender->sendQuit() if ($self->getState() == Network::IN_GAME);

		message TF("Disconnecting (%s:%s)...", $self->{remote_socket}->peerhost(), 
			$self->{remote_socket}->peerport()), "connection";
		close($self->{remote_socket});
		!$self->serverAlive() ?
			message T("disconnected\n"), "connection" :
			error T("couldn't disconnect\n"), "connection";
	}
}

sub getState {
	return $conState;
}

sub setState {
	my ($self, $state) = @_;
	$conState = $state;
	Plugins::callHook('Network::stateChanged');
}


######################
## Client Functions ##
######################

##
# boolean $net->clientAlive()
#
# Check whether there are one or more clients connected to Kore.
sub clientAlive {
	my %args = (net => $_[0]);
	Plugins::callHook('Network::clientAlive', \%args);
	return $args{return};
}

##
# $net->clientSend(Bytes data)
#
# Make the RO client think that it has received $data.
sub clientSend {
	my ($self) = @_;
	if ($self->clientAlive && Plugins::hasHook('Network::clientSend')) {
		my %args = (net => $self, data => $_[1]);
		Plugins::callHook('Network::clientSend', \%args);
		return $args{return};
	} else {
		return undef;
	}
}

##
# Bytes $net->clientRecv()
#
# Receive data that the RO client wants to send to the RO server.
sub clientRecv {
	my ($self) = @_;
	if ($self->clientAlive) {
		my %args = (net => $_[0]);
		Plugins::callHook('Network::clientRecv', \%args);
		return $args{return};
	} else {
		return undef;
	}
}


#######################
## Utility Functions ##
#######################

#######################################
#######################################
# Check Connection
#######################################
#######################################

##
# $net->checkConnection()
#
# Handles any connection issues. Based on the current situation, this function may
# re-connect to the RO server, disconnect, do nothing, etc.
#
# This function is meant to be run in the Kore main loop.
sub checkConnection {
	my $self = shift;
	
	return if ($Settings::no_connect);

	if ($self->getState() == Network::NOT_CONNECTED && (!$self->{remote_socket} || !$self->{remote_socket}->connected) && timeOut($timeout_ex{'master'}) && !$conState_tries) {
		my $master = $masterServer = $masterServers{$config{master}};
		
		message T("Connecting to Account Server...\n"), "connection";
		$shopstarted = 1;
		$conState_tries++;
		$initSync = 1;
		$incomingMessages->clear();

		eval {
			my $wrapper = ($self->{wrapper}) ? $self->{wrapper} : $self;
			$packetParser = Network::Receive->create($wrapper, $masterServer->{serverType});
			$messageSender = Network::Send->create($wrapper, $masterServer->{serverType});
		};
		if ($@) {
			$interface->errorDialog("$@");
			$quit = 1;
			return;
		}
		$reconnectCount++;
		$self->serverConnect($master->{ip}, $master->{port});

		# call plugin's hook to determine if we can continue the work
		if ($self->serverAlive) {
			Plugins::callHook("Network::serverConnect/master");
			return if ($conState == 1.5);
		}

		# GameGuard support
		if ($self->serverAlive && $config{gameGuard} == 3) {
			my $msg = pack("C*", 0x58, 0x02);
			$net->serverSend($msg);
			message T("Requesting permission to logon on account server...\n");
			$conState = 1.2;
			
			# Saving Last Request Time (Logon) (GG/HS Query)
			$timeout{poseidon_wait_reply}{time} = time;			
			
			return;
		}

		if ($self->serverAlive && $master->{secureLogin} >= 1) {
			my $code;

			message T("Secure Login...\n"), "connection";
			undef $secureLoginKey;

			if ($master->{secureLogin_requestCode} ne '') {
				$code = $master->{secureLogin_requestCode};
			} elsif ($config{secureLogin_requestCode} ne '') {
				$code = $config{secureLogin_requestCode};
			}

			if ($code ne '') {
				$messageSender->sendToServer($messageSender->reconstruct({
					switch => 'client_hash',
					code => $code,
				}));
			} elsif ($master->{secureLogin_type}) {
				$messageSender->sendToServer($messageSender->reconstruct({
					switch => 'client_hash',
					type => $master->{secureLogin_type},
				}));
			}
			
			$messageSender->sendToServer($messageSender->reconstruct({
				switch => 'secure_login_key_request',
			}));

		} elsif ($self->serverAlive) {
			$messageSender->sendPreLoginCode($master->{preLoginCode}) if ($master->{preLoginCode});
			$messageSender->sendMasterLogin($config{'username'}, $config{'password'},
				$master->{master_version}, $master->{version});
		}

		$timeout{'master'}{'time'} = time;
	} elsif ($self->getState() == 1.2) {
	# Checking if we succesful received the Game Guard Confirmation (Should Happen Sooner)
		if ( time - $timeout{poseidon_wait_reply}{time} > ($timeout{poseidon_wait_reply}{timeout} || 15) )
		{
			message T("The Game Guard Authorization Request\n");
			message T("has timed out, please check your poseidon server !!\n");
			message TF("Address poseidon server: %s\n", $config{'poseidonServer'});
			message TF("Port poseidon: %s\n", $config{'poseidonPort'});
			$self->serverDisconnect;
			$self->setState(Network::NOT_CONNECTED);			
		}
	# we skipped some required connection operations while waiting for the server to allow as to login,
	# after we have successfully sent in the reply to the game guard challenge (using the poseidon server)
	# this conState will allow us to continue from where we left off.
	} elsif ($self->getState() == 1.3) {
		$conState = 1;
		my $master = $masterServer = $masterServers{$config{'master'}};
		if ($master->{secureLogin} >= 1) {
			my $code;

			message T("Secure Login...\n"), "connection";
			undef $secureLoginKey;

			if ($master->{secureLogin_requestCode} ne '') {
				$code = $master->{secureLogin_requestCode};
			} elsif ($config{secureLogin_requestCode} ne '') {
 				$code = $config{secureLogin_requestCode};
			}

			if ($code ne '') {
				$messageSender->sendToServer($messageSender->reconstruct({
					switch => 'client_hash',
					code => $code,
				}));
			} elsif ($master->{secureLogin_type}) {
				$messageSender->sendToServer($messageSender->reconstruct({
					switch => 'client_hash',
					type => $master->{secureLogin_type},
				}));
			}
			
			$messageSender->sendToServer($messageSender->reconstruct({
				switch => 'secure_login_key_request',
			}));

		} else {
			$messageSender->sendPreLoginCode($master->{preLoginCode}) if ($master->{preLoginCode});
			$messageSender->sendMasterLogin($config{'username'}, $config{'password'},
				$master->{master_version}, $master->{version});
		}

		$timeout{'master'}{'time'} = time;
		
	} elsif ($self->getState() == Network::NOT_CONNECTED) {
		if($masterServer->{secureLogin} >= 1 && $secureLoginKey ne "" && !timeOut($timeout{'master'}) && $conState_tries) {
			my $master = $masterServer;
			message T("Sending encoded password...\n"), "connection";
			$messageSender->sendMasterSecureLogin($config{'username'}, $config{'password'}, $secureLoginKey,
					$master->{version}, $master->{master_version},
					$master->{secureLogin}, $master->{secureLogin_account});
			undef $secureLoginKey;

		} elsif (timeOut($timeout{'master'}) && timeOut($timeout_ex{'master'})) {
			if ($config{dcOnMaxReconnections} && $config{dcOnMaxReconnections} <= $reconnectCount) {
				error T("Auto disconnecting on MaxReconnections!\n");
				chatLog("k", T("*** Exceeded the maximum number attempts to reconnect, auto disconnect! ***\n"));
				$quit = 1;
				return;
			}
			message TF("Timeout on Account Server, reconnecting. Wait %s seconds...\n", $timeout{'reconnect'}{'timeout'}), "connection";
			$timeout_ex{'master'}{'time'} = time;
			$timeout_ex{'master'}{'timeout'} = $timeout{'reconnect'}{'timeout'};
			$self->serverDisconnect;
			undef $conState_tries;
		}
	} elsif ($self->getState() == 1.5) {
		if (!$self->serverAlive) {
			$self->setState(Network::NOT_CONNECTED);
			undef $conState_tries;
			return;
		}
		
		# on this special stage, the plugin will know what to do next.
		Plugins::callHook("Network::serverConnect/special");
		
	} elsif ($self->getState() == Network::CONNECTED_TO_MASTER_SERVER) {
		if(!$self->serverAlive() && ($config{'server'} ne "" || $masterServer->{charServer_ip}) && !$conState_tries) {
			if ($config{pauseCharServer}) {
				message "Pausing for $config{pauseCharServer} second(s)...\n", "system";
				sleep $config{pauseCharServer};
			}
			my $master = $masterServer;
			message T("Connecting to Character Server...\n"), "connection";
			$conState_tries++;
			$captcha_state = 0;

			if ($master->{charServer_ip}) {
				$self->serverConnect($master->{charServer_ip}, $master->{charServer_port});
			} elsif ($servers[$config{'server'}]) {
				$self->serverConnect($servers[$config{'server'}]{'ip'}, $servers[$config{'server'}]{'port'});
			} else {
				error TF("Invalid server specified, server %s does not exist...\n", $config{server}), "connection";

				my @serverList;
				foreach my $server (@servers) {
					push @serverList, $server->{name};
				}
				my $ret = $interface->showMenu(
						T("Please select your login server."),
						\@serverList,
						title => T("Select Login Server"));
				if ($ret == -1) {
					quit();
				} else {
					main::configModify('server', $ret, 1);
					undef $conState_tries;
				}
				return;
			}

			# call plugin's hook to determine if we can continue the connection
			if ($self->serverAlive) {
				Plugins::callHook("Network::serverConnect/char");
				$reconnectCount = 0;
				return if ($conState == 1.5);
			}
			# TODO: the connect code needs a major rewrite =/
			unless($masterServer->{captcha}) {
				$messageSender->sendGameLogin($accountID, $sessionID, $sessionID2, $accountSex);
				$timeout{'gamelogin'}{'time'} = time;
			}
		} elsif($self->serverAlive() && $masterServer->{captcha}) {
			if ($captcha_state == 0) { # send initiate once, then wait for servers captcha_answer packet
				$messageSender->sendCaptchaInitiate();
				$captcha_state = -1;
			} elsif ($captcha_state == 1) { # captcha answer was correct, sent sendGameLogin once, then wait for servers 
				$messageSender->sendGameLogin($accountID, $sessionID, $sessionID2, $accountSex);
				$timeout{'gamelogin'}{'time'} = time;
				$captcha_state = -1;
			} else {
				return;
			}
		} elsif (timeOut($timeout{'gamelogin'}) && ($config{'server'} ne "" || $masterServer->{'charServer_ip'})) {
			error TF("Timeout on Character Server, reconnecting. Wait %s seconds...\n", $timeout{'reconnect'}{'timeout'}), "connection";
			$timeout_ex{'master'}{'time'} = time;
			$timeout_ex{'master'}{'timeout'} = $timeout{'reconnect'}{'timeout'};
			$self->serverDisconnect;
			undef $conState_tries;
			$self->setState(Network::NOT_CONNECTED);
		}
	} elsif ($self->getState() == Network::CONNECTED_TO_LOGIN_SERVER) {
		if(!$self->serverAlive() && $config{'char'} ne "" && !$conState_tries) {
			message T("Connecting to Character Select Server...\n"), "connection";
			$conState_tries++;
			$self->serverConnect($servers[$config{'server'}]{'ip'}, $servers[$config{'server'}]{'port'});

			# call plugin's hook to determine if we can continue the connection
			if ($self->serverAlive) {
				Plugins::callHook("Network::serverConnect/charselect");
				return if ($conState == 1.5);
			}
					
			$messageSender->sendCharLogin($config{'char'});
			$timeout{'charlogin'}{'time'} = time;

		} elsif (timeOut($timeout{'charlogin'}) && $config{'char'} ne "") {
			error T("Timeout on Character Select Server, reconnecting...\n"), "connection";
			$timeout_ex{'master'}{'time'} = time;
			$timeout_ex{'master'}{'timeout'} = $timeout{'reconnect'}{'timeout'};
			$self->serverDisconnect;
			$self->setState(Network::NOT_CONNECTED);
			undef $conState_tries;
		}
	} elsif ($self->getState() == Network::CONNECTED_TO_CHAR_SERVER) {
		if(!$self->serverAlive() && !$conState_tries) {
			if ($config{pauseMapServer}) {
				message "Pausing for $config{pauseMapServer} second(s)...\n", "system";
				sleep($config{pauseMapServer});
			}
			message T("Connecting to Map Server...\n"), "connection";
			$conState_tries++;
			main::initConnectVars();
			my $master = $masterServer;
			my ($ip, $port);
			if ($master->{private}) {
				$ip = $config{forceMapIP} || $master->{ip};
				$port = $map_port;
			} else {
				$ip = $master->{mapServer_ip} || $config{forceMapIP} || $map_ip;
				$port = $master->{mapServer_port} || $map_port;
			}
			$self->serverConnect($ip, $port);

			# call plugin's hook to determine if we can continue the connection
			if ($self->serverAlive) {
				Plugins::callHook("Network::serverConnect/mapserver");
				return if ($conState == 1.5);
			}

			$messageSender->sendMapLogin($accountID, $charID, $sessionID, $accountSex2);
			$timeout_ex{master}{time} = time;
			$timeout_ex{master}{timeout} = $timeout{reconnect}{timeout};
			$timeout{maplogin}{time} = time;

		} elsif (timeOut($timeout{maplogin})) {
			message T("Timeout on Map Server, connecting to Account Server...\n"), "connection";
			$timeout_ex{master}{timeout} = $timeout{reconnect}{timeout};
			$self->serverDisconnect;
			$self->setState(Network::NOT_CONNECTED);
			undef $conState_tries;
		}
	} elsif ($self->getState() == Network::IN_GAME) {
		if(!$self->serverAlive()) {
			Plugins::callHook('disconnected');
			if ($config{dcOnDisconnect}) {
				error T("Auto disconnecting on Disconnect!\n");
				chatLog("k", T("*** You disconnected, auto disconnect! ***\n"));
				$quit = 1;
			} else {
				message TF("Disconnected from Map Server, connecting to Account Server in %s seconds...\n", $timeout{reconnect}{timeout}), "connection";
				$timeout_ex{master}{time} = time;
				$timeout_ex{master}{timeout} = $timeout{reconnect}{timeout};
				$self->setState(Network::NOT_CONNECTED);
				undef $conState_tries;
			}

		} elsif (timeOut($timeout{play})) {
			error T("Timeout on Map Server, "), "connection";
			Plugins::callHook('disconnected');
			if ($config{dcOnDisconnect}) {
				error T("Auto disconnecting on Disconnect!\n");
				chatLog("k", T("*** You disconnected, auto disconnect! ***\n"));
				$quit = 1;
			} else {
				error TF("connecting to Account Server in %s seconds...\n", $timeout{reconnect}{timeout}), "connection";
				$timeout_ex{master}{time} = time;
				$timeout_ex{master}{timeout} = $timeout{reconnect}{timeout};
				$self->serverDisconnect;
				$self->setState(Network::NOT_CONNECTED);
				undef $conState_tries;
			}
		}
	}
}

return 1;







then i modified poseidon.xml
C:\Program Files\Level Up Games\Ragnarok Online\data\poseidon.xml

Code: Select all

<?xml version="1.0" encoding="euc-kr" ?> 
- <clientinfo>
<servicetype>philippine</servicetype> 
<servertype>primary</servertype> 
<passwordencrypt /> 
<extendedslot /> 
- <connection>
<display>Poseidon Server</display> 
<desc>None</desc> 
<address>192.168.1.3</address> 
<port>6900</port> 
<version>1</version> 
<registrationweb>http://www.openkore.com</registrationweb> 
</connection>
</clientinfo>

then made a batch file ro.bat
C:\Program Files\Level Up Games\Ragnarok Online\data\ro.bat

Code: Select all

f2pexe.exe 1rag1 5free5 /account:poseidon.xml
forgot gameguard should be set to 2 in config.txt

there you go.. not really a guide but it should do..
Last edited by vinceaar0n00 on 25 Aug 2014, 04:16, edited 1 time in total.

vinceaar0n00
Noob
Noob
Posts: 12
Joined: 08 Aug 2014, 02:14
Noob?: Yes

Re: pRO's Update! Login Pincode..(similar to bRO)

#283 Post by vinceaar0n00 »

i'd like to say thank you to the contributors and developers of these none of these codes are mine and you guys made it possible for me to bot again.. thanks alot... just wish i could use more than 1 bot per pc still trying to figure that out..

vhonn
Human
Human
Posts: 28
Joined: 03 Jun 2012, 11:50
Noob?: Yes

Re: pRO's Update! Login Pincode..(similar to bRO)

#284 Post by vhonn »

vinceaar0n00 wrote:i'd like to say thank you to the contributors and developers of these none of these codes are mine and you guys made it possible for me to bot again.. thanks alot... just wish i could use more than 1 bot per pc still trying to figure that out..
I cross checked my file we have the same except I have to edit poseidon.pl file to run, and edit pRO.pm file. I was able to run the poseidon, still having disconnection and Poseidon Client with the novice automatically closes, this time it takes longer than before.

Image

just right after the Poseidon Client closes then it gets disconnected.

Maybe I need to start from scratch with a fresh client.

vinceaar0n00
Noob
Noob
Posts: 12
Joined: 08 Aug 2014, 02:14
Noob?: Yes

Re: pRO's Update! Login Pincode..(similar to bRO)

#285 Post by vinceaar0n00 »

try downloading a fresh ro client. make sure no openkore poseidon is running on your host pc. try microsoft virtual pc.


btw my bot's been running for more than a day no dc so far.

zonda
Human
Human
Posts: 45
Joined: 12 Aug 2014, 21:15
Noob?: Yes

Re: pRO's Update! Login Pincode..(similar to bRO)

#286 Post by zonda »

I don't get disconnected when using Xkore 3. But if I just use poseidon, openkore doesnt seem to connect to poseidon, so it still get disconnected

vhonn
Human
Human
Posts: 28
Joined: 03 Jun 2012, 11:50
Noob?: Yes

Re: pRO's Update! Login Pincode..(similar to bRO)

#287 Post by vhonn »

vinceaar0n00 wrote:try downloading a fresh ro client. make sure no openkore poseidon is running on your host pc. try microsoft virtual pc.


btw my bot's been running for more than a day no dc so far.
You mean to say I cannot run the Bot Client and the Poseidon with the RO client (with 2 novices ) on the single machine at the same time? So I Need the BOT+Poseidon on my main computer and the RO Client (with 2 novices ) on a Virtual Machine? Basically speaking RO client will automatically close because the GG detects that there is a 3rd party software running in parallel with it. I think That make sense. Let me try running the RO client(poseidon server on VM) if it will not close most probably that is the reason.

vinceaar0n00
Noob
Noob
Posts: 12
Joined: 08 Aug 2014, 02:14
Noob?: Yes

Re: pRO's Update! Login Pincode..(similar to bRO)

#288 Post by vinceaar0n00 »

ro client on host/main pc and poseidon and openkore on vm.. thats what ive been trying to tell you from the start..
you wont be able to run poseidon or openkore with the ro client unless your able to run openkore and poseidon via perl without binaries..
only one bot per poseidon server.

iorinhoj
Noob
Noob
Posts: 4
Joined: 29 Jan 2013, 22:44
Noob?: Yes

Re: pRO's Update! Login Pincode..(similar to bRO)

#289 Post by iorinhoj »

anything new bout disconnecting prob? or should we start a new thread since this is for login pincode thread?

buririt
Noob
Noob
Posts: 4
Joined: 27 Sep 2012, 22:48
Noob?: No

Re: pRO's Update! Login Pincode..(similar to bRO)

#290 Post by buririt »

is there any update regarding running multiple bots in 1 PC???
wat happens if i run 2 or more bots using the poseidon method??

Post Reply