Openkore.com

OpenKore Forums
It is currently 22 Nov 2017, 10:40

All times are UTC - 5 hours [ DST ]





Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 2 posts ] 
Author Message
 Post subject: Poseidon bRO
PostPosted: 04 Apr 2016, 15:40 
Offline
Noob
Noob

Joined: 11 Mar 2012, 22:16
Posts: 6
Sorry my bad English.
I'm having trouble doing poseidonserver respond to gg sends the query more does not respond after that the openkore disconnects could give me a way of how to get all the help and welcome, I thank you.

QueryServer
Quote:
###########################################################
# 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 Poseidon::Client;
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;
use Time::HiRes qw(time sleep);
use Globals qw(%config %rpackets);
use Digest::MD5 qw(md5_hex);

my $CLASS = "Poseidon::QueryServer";

use constant REQUEST_TIMEOUT => 50;

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

if ($args->{username}) {
print "[PoseidonServer]-> Received query from bot client (" . $args->{username} . ")\n";
} else {
print "[PoseidonServer]-> Received query from bot client " . $client->getIndex() . "\n";
}

my %request = (
packet => $args->{packet},
client => $client,
username=>$args->{args}{username} = md5_hex($config{username}),
qstate => 'received',
#request_time => time
);

my $msg = $args->{packet};
my $length = unpack("v",substr($msg,2,2));

# 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 logData {
my ($type, $user, $packet, $time) = @_;
open LOG_FILE, ">>logs/gg_".$user.".log" or die $!;
print LOG_FILE sprintf("%s %s %s\n", $user, unpack("H*", $packet), $time);
close LOG_FILE;
}


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


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"};

my $clients = $server->clients();

for (my $x = 0; $x < @{$queue}; $x++) {
if ($queue->[$x]{qstate} eq 'request') {
# push queue to ROclient
print "[PoseidonServer]-> Querying Ragnarok Online client [" . time . "]...\n";
#print "[PoseidonServer]-> User: ". $queue->[0]{username} ."...\n";
my $query = $server->query($queue->[$x]);
if ($query eq 'nox') {
$queue->[$x]{client}->close();
splice(@{$queue}, $x, 1);
#shift @{$queue};
} else {
$queue->[$x]{roClient} = $query;
$queue->[$x]{qstate} = 'requested';
$queue->[$x]{request_time} = time;
}
} elsif (
($queue->[$x]{qstate} eq 'requested') && (time > ($queue->[$x]{request_time} + REQUEST_TIMEOUT) )
) {
print sprintf("Request from %s timed out \n", $queue->[$x]{username});
$queue->[$x]{client}->close() if $queue->[$x]{client};
splice(@{$queue}, $x, 1) if $queue->[$x];

} elsif ($clients->[$queue->[$x]{roClient}]{'query_state'} eq 'replied') {
# receive response packet from client
if ($queue->[$x]{client}) {
my ($data, %args);

$args{packet} = Poseidon::RagnarokServer::readResponse($clients->[$queue->[$x]{roClient}]);
$data = serialize("Poseidon Reply", \%args);
print sprintf("Reply took %s seconds \n", (time - $queue->[$x]{req_time}));
logData("R", $queue->[$x]{username}, $args{packet}, (time - $queue->[$x]{req_time}));

$queue->[$x]{client}->send($data);
$queue->[$x]{client}->close();
print "[PoseidonServer]-> Sent result to client : " . $queue->[$x]{client}->getIndex() . "\n";

splice(@{$queue}, $x, 1);
}
}
}
}

1;

RagnarokServer
Quote:
###########################################################
# 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
$client->send($msg);
# Don't allow other packet's (like Sync) to get to RO server.

} elsif ($switch eq '09D0') { # new bRO gameGuard packet response
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} || 124; #defaults to 106

# 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 v x4 x4' if $blocksize == 140;
$packstring = 'a4 V9 v V2 v14 Z24 C8 v Z16 v x4' if $blocksize == 136;
$packstring = 'a4 V9 v V2 v14 Z24 C8 v Z16 v' if $blocksize == 132;
$packstring = 'a4 V9 v V2 v14 Z24 C8 v Z16' if $blocksize == 128;
$packstring = 'a4 V9 v V2 v14 Z24 C8 v Z12' if $blocksize == 124;
$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;


Attachments:
Receive_bro.pm [3.37 KiB]
Downloaded 60 times
Send-bro.pm [2.21 KiB]
Downloaded 54 times
recvpackets.txt [53.58 KiB]
Downloaded 51 times
Top
 Profile  
 
 Post subject: Re: Poseidon bRO
PostPosted: 04 Apr 2016, 17:00 
Offline
Noob
Noob

Joined: 11 Mar 2012, 22:16
Posts: 6
Image


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 2 posts ] 

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