Упрощение работы с xKore 2

Разработка новых функций.

Модератор: 4epT

Аватара пользователя
piroJOKE
Модератор
Сообщения: 8205
Зарегистрирован: Сб ноя 04, 2006 2:20 am
Сервер RO:: localhost
Откуда: Molvania

Упрощение работы с xKore 2

Сообщение piroJOKE »

Да, я в курсе что xKore 2 не работает (или работает но очень криво).
Однако давайте временно возомним себе, что он отменно работает, и офигенно нас типо радует. :twisted:

Однако, есть одно неудобство. При создании каждого нового подключения надо заботиться о портах, править xml-ку (или даже grf), в общим заниматься всякой тупой возней.

А между тем, было бы неплохо создать какую-то программу-сервер, которая брала бы на себя функцию аккаун- и чар- серверов, а затем переадресовывала бы нас к собственно работающей ОпенКоре. Это бы дало возможность использовать меню "выбор сервиса" для выбора из бегающих чаров. Логинимся из клиента с любым логином и паролем, а дальше... пример-эскиз на картинке ниже.

На этом этапе чар сервер фактически сообщает клиенту адрес:порт для подключения, так вот, он и будет сообщать localhost:порт; причем порт и имена чаров сообщат нашей гига-логон-программе работающие с включенным xKore 2 режимом экземпляры ОК. Т.е., теоретически - никаких сложностей, это вполне возможно.

Понятно, что никто этого делать не будет, поэтому пост остаеццо чиста для истории.
Вложения
эскиз
эскиз
megalogon_xkore2.png (5.83 КБ) 3454 просмотра
Use brain against brain, ai against ai... · как правильно задавать вопросы · faq · download
EternalHarvest
Разработчик
Сообщения: 819
Зарегистрирован: Пн окт 27, 2008 9:49 pm

Сообщение EternalHarvest »

src/Base/Ragnarok/CharServer.pm

Код: Выделить всё

- my $session = $self->{sessionStore}->get($sessionID);

+ my $session = {accountID => $accountID, sessionID => $sessionID, sessionID2 => $sessionID2, sex => $gender};
+ $self->{sessionStore}->add ($session);
+ $session->{state} = 'About to select character';
plugins/trident.pl

Код: Выделить всё

package tridentPlugin;
use strict;

use constant PRESENCE_TIMEOUT => 15;

use Globals;
use Log qw(message);
use Plugins;

Plugins::register('tridentPlugin', 'Trident Server Plugin', \&onUnload);

my ($lastPresence);
my $hooks = Plugins::addHooks(['mainLoop_pre', \&onAi, undef]);
sub onUnload { Plugins::delHooks($hooks); }

sub onAi {
	if ($lastPresence + PRESENCE_TIMEOUT < time) { 
		if ($char and $bus and $bus->getState () == Bus::Client::CONNECTED ()) {
			$bus->send ('Trident/Presence', {
				id => $char->{ID},
				title => $config{tridentTitle} || ("$char->{name}"),
				online => $char->{lv},
				host => $Network::XKore2::charServer->{BS_host},
				port => $Network::XKore2::charServer->{BS_port},
				sex => $char->{sex},
				timeout => PRESENCE_TIMEOUT,
			});
		}
		$lastPresence = time;
	}
}

1;
trident.pl

Код: Выделить всё

#!/usr/bin/env perl
use strict;

use constant CONTROL_FOLDER => 'control/trident';
use constant TABLES_FOLDER => 'tables';
use constant BUS_AGENT => 'Trident';
use constant SLEEP_TIME => 0.01;
use constant CHECK_TIMEOUT => 5;
use constant CHECK_TIMEOUT_PLAY => 5;

use FindBin qw($RealBin);
use lib "$RealBin";
use lib "$RealBin/src";
use lib "$RealBin/src/deps";
use Time::HiRes qw(time sleep);
use Encode;

use Base::Ragnarok::SessionStore;
use Bus::Client;
use Bus::Handlers;
use FileParsers;
use Settings;

our (%sys, %config, %rpackets, %masterServers, $masterServer);
my ($accountServer, $sessionStore);
my ($bus, $busMessageHandler);

sub initialize {
	printLine ("Starting Trident...");
	
	# load OpenKore settings
	Settings::setControlFolders (CONTROL_FOLDER);
	Settings::setTablesFolders (TABLES_FOLDER);
	Settings::addControlFile (Settings::getConfigFilename (),
		loader => [\&parseConfigFile, \%config], autoSearch => 0);
	Settings::addTableFile (Settings::getRecvPacketsFilename (),
		loader => [\&parseDataFile2, \%rpackets], autoSearch => 0);
	Settings::addTableFile ('servers.txt', loader => [\&parseSectionedFile, \%masterServers]);
	Settings::loadSysConfig ();
	my $progressHandler = sub {
		printLine ("Loading ".(shift)."...");
	};
	Settings::loadAll ($progressHandler);
	
	unless ($masterServer = $masterServers{$config{master}}) {
		printLine ("Check your masterServer!");
		die;
	}
	
	if (Settings::setRecvPacketsName ($masterServer->{recvpackets})) {
		my (undef, undef, $basename) = File::Spec->splitpath(Settings::getRecvPacketsFilename());
		Settings::loadByRegexp ($basename, $progressHandler);
	}
	
	printLine ("Starting account server...");
	$sessionStore = new Base::Ragnarok::SessionStore ();
	$accountServer = new Trident::AccountServer (
		host => $config{trident_listenIp},
		port => $config{trident_listenPort} || 6900,
		serverType => $masterServer->{serverType},
		rpackets => \%rpackets,
		charServer => new Trident::DummyCharServer ({title => 'Dummy', dummy => 1}),
		sessionStore => $sessionStore
	);
	
	printLine ("Initializing bus...");
	my $busHost = $sys{bus_server_host};
	my $busPort = $sys{bus_server_port};
	$busHost = undef if $busHost eq '';
	$busPort = undef if $busPort eq '';
	$bus = new Bus::Client(host => $busHost, port => $busPort, userAgent => BUS_AGENT);
	$busMessageHandler = new Bus::Handlers ($bus);
	$bus->onMessageReceived->add (undef, \&onBusMessage);
	
	# generate xml file for Ragnarok client
	makeXml ();
	printLine ("Trident.xml generated in OpenKore folder.");
	printLine ("Copy it to RO client's data folder and run 'ragexe 1rag1 /account:Trident.xml'.");
	
	printLine ("-" x 79);
}

sub iterate {
	my $i = 0;
	while ($i < scalar @{$accountServer->{charServers}}) {
		if (${$accountServer->{charServers}}[$i]{dummy}
		|| ${$accountServer->{charServers}}[$i]{seen}
		+ ${$accountServer->{charServers}}[$i]{timeout} + CHECK_TIMEOUT_PLAY < time) {
			unless (${$accountServer->{charServers}}[$i]{dummy}) {
				printLine ("Gone: ${$accountServer->{charServers}[$i]}{title}");
			}
			splice (@{$accountServer->{charServers}}, $i, 1);
		} else {
			$i++;
		}
	}
}

sub makeXml {
	open my $f, '>Trident.xml';
	print $f '<?xml version="1.0" encoding="euc-kr" ?>

<clientinfo>
	<servicetype>russia</servicetype>
	<servertype>primary</servertype>
	<hideaccountlist></hideaccountlist>
	<extendedslot></extendedslot>

	<connection>
		<display>Trident</display>
		<desc>None</desc>
		<address>'.$accountServer->getHost ().'</address>
		<port>'.$accountServer->getPort ().'</port>
		<version>'.$masterServer->{version}.'</version>
		<registrationweb>http://openkore.com/</registrationweb>
	</connection>
</clientinfo>';
	
	close $f;
}

sub onBusMessage {
	my (undef, undef, $msg) = @_;
	if ($msg->{messageID} eq 'Trident/Presence') {
		# client's server selection screen doesn't display utf8?
		$msg->{args}{title} = encode ('cp1251', $msg->{args}{title});
		
		for (my $i = 0; $i < scalar @{$accountServer->{charServers}}; $i++) {
			if (${$accountServer->{charServers}}[$i]{id} eq $msg->{args}{id}) {
				printLine ("Still alive: $msg->{args}{title}\@$msg->{args}{host}:$msg->{args}{port} ($i)");
				copyProperties (${$accountServer->{charServers}}[$i], $msg->{args});
				${$accountServer->{charServers}}[$i]{seen} = time;
				return;
			}
		}
		
		printLine ("New client: $msg->{args}{title}\@$msg->{args}{host}:$msg->{args}{port} (".scalar @{$accountServer->{charServers}}.")");
		push @{$accountServer->{charServers}}, new Trident::DummyCharServer ($msg->{args});
	}
}

sub copyProperties {
	my ($target, $source) = @_;
	foreach (keys %$source) {
		$target->{$_} = $source->{$_};
	}
}

sub printLine () {
	no warnings;
	print shift . "\n";
}

sub __start {
	initialize ();
	while (1) {
		iterate ();
		$bus->iterate () if $bus;
		$accountServer->iterate () if $accountServer;
		
		sleep SLEEP_TIME;
	}
}

__start() unless defined $ENV{INTERPRETER};

{
	package Trident::DummyCharServer;
	use strict;
	
	sub new {
		my ($class, $self) = @_; $self->{seen} = time; return bless $self => $class;
	}
	
	sub getHost { return shift->{host} }
	sub getPort { return shift->{port} }
	sub getName { return shift->{title} }
	sub getPlayersCount {return shift->{online} }
}

{
	package Trident::AccountServer;
	use strict;
	use Base::Ragnarok::AccountServer; use base qw/Base::Ragnarok::AccountServer/;
	
	sub login {
		my ($self, $session, $username, $password) = @_;
		
		$session->{sex} = $username =~ /female/i ? 0 : 1;
		
		if ($main::config{trident_password} and $main::config{trident_password} ne $password) {
			return Base::Ragnarok::AccountServer::PASSWORD_INCORRECT;
		} else {
			return Base::Ragnarok::AccountServer::LOGIN_SUCCESS;
		}
	}
}
control/trident/config.txt

Код: Выделить всё

master Russia - rRO
trident_listenIp 127.0.0.1
trident_listenPort 6999
trident_password
control/trident/sys.txt

Код: Выделить всё

bus_server_host 
bus_server_port 
Боты - config.txt

Код: Выделить всё

XKore 2
Боты - sys.txt

Код: Выделить всё

bus 1
bus_server_host 
bus_server_port
Запускаем trident.pl (боты могут уже бегать)
Если запускаем первый раз - копируем сгенерированный Trident.xml в папку data клиента РО
Запускаем ragexe 1rag1 /account:Trident.xml
Вводим логин female, чтоб чары получились женского пола, любой другой логин для мужского
Вводим пароль, указанный в trident_password, или любой пароль если там ничего не указано

http://bayimg.com/image/faljfaabk.jpg

http://bayimg.com/image/faljhaabk.jpg

http://bayimg.com/image/faljiaabk.jpg
Ответить