About the bus system

Forum closed. All further discussion to be discussed at https://github.com/OpenKore/

Moderator: Moderators

Message
Author
ryanblonna3
Human
Human
Posts: 30
Joined: 29 Jul 2010, 11:53
Noob?: No

About the bus system

#1 Post by ryanblonna3 »

Hi, I just found out about this powerful feature (the bus system), but I do not quite understand how to use it after having read about it in the OK manual. In what file do you write code utilizing the bus system, and where does this file go? This was not clear to me; perhaps I need to make a plugin and use it there? Thanks for any input...

EternalHarvest
Developers
Developers
Posts: 1798
Joined: 05 Dec 2008, 05:42
Noob?: Yes

Re: About the bus system

#2 Post by EternalHarvest »

ryanblonna3 wrote:perhaps I need to make a plugin and use it there?
Probably, as Bus doesn't do anything useful by itself and just provides utility.

ryanblonna3
Human
Human
Posts: 30
Joined: 29 Jul 2010, 11:53
Noob?: No

Re: About the bus system

#3 Post by ryanblonna3 »

Ah, so if I can utilize it through a plugin, then I should be able to use it via the macro plugin.

By any chance, is there any development going on concerning the use of the Bus system in the 'follow' algorithms? I noticed that when there is a lot of lag, OK's follow algorithm causes the bot to go berserk and walk in seemingly random directions. This could be avoided if the algorithms were implemented using the Bus system, no? Just a side comment :-)

EternalHarvest
Developers
Developers
Posts: 1798
Joined: 05 Dec 2008, 05:42
Noob?: Yes

Re: About the bus system

#4 Post by EternalHarvest »

ryanblonna3 wrote:This could be avoided if the algorithms were implemented using the Bus system, no?
Yea, that could be implemented as sharing coordinates via Bus and something similar to AI::ai_partyfollow (which is for following party members).

I've tried to make a working example, so there it is (not optimized as it doesn't need processFollow's own tries to find and it seems to have logic problems when master is finally found. The only really useful feature so far that it can find faraway non-party members):

Code: Select all

package busgps;

use strict;
use Bus::Client;
use Globals;
use Log qw(message error);
use Translation qw(T TF);
use Utils;

use constant DOMAIN => 'busgps';
use constant BUS_MESSAGE_ID => 'busgps';
use constant TIMEOUT => 5;
use constant ACTOR_FIELDS => qw(
	ID name nameID jobID type sex zeny walk_speed
	lv lv_job hp hp_max sp sp_max exp exp_max exp_job exp_job_max weight weight_max
);

# ideally, actors in $Globals::playersList and in this list should be the same object
# but that requires more tweaking (for example Network::Receive::ServerType0::actor_display)
my $gps_players_list = new ActorList('Actor::Player');
my %gps_client_to_player;

my %broadcast_timeout = (timeout => TIMEOUT);

my $hooks = Plugins::addHooks(
	['initialized', \&initialized, undef],
	['mainLoop_pre', \&main, undef],
	['AI_post', \&ai, undef],
);
my $commands = Commands::register (
	['busgps', 'Display data shared via Bus', \&command],
);
my $bus_message_received;

Plugins::register("busgps", "Sharing data via Bus", sub {
	Plugins::delHooks($hooks);
	Commands::unregister($commands);
	$bus->onMessageReceived->remove($bus_message_received) if $bus_message_received;
});

sub initialized {
	$bus_message_received = $bus->onMessageReceived->add(undef, \&bus_message_received);
}

sub main {
	if (timeOut(\%broadcast_timeout)) {
		if ($char && $field && $bus->getState == Bus::Client::CONNECTED) {
			my %args;
			
			$args{master_ip} = $masterServer->{ip};
			@args{qw(pos_x pos_y map), ACTOR_FIELDS} = (@{$char->{pos}}{qw(x y)}, $field->name, @{$char}{+ACTOR_FIELDS});
			
			$bus->send(BUS_MESSAGE_ID, \%args);
		}
		
		$broadcast_timeout{time} = time;
	}
}

sub ai {
	# from AI::ai_partyfollow
	if ($config{follow} && defined (my $followIndex = AI::findAction('follow'))) {
		my $args = AI::args($followIndex);
		if (
			!exists $args->{following} && !exists $args->{ai_follow_lost}
			&& !AI::inQueue(qw(storageAuto storageGet sellAuto buyAuto))
			&& (my $actor = List::Util::first { $_->{name} eq $config{followTarget} } @{$gps_players_list->getItems})
		) {
			if (
				exists $ai_v{master} && distance($actor->{pos}, $ai_v{master}) > 15
				or $actor->{map} != $ai_v{master}{map}
				or (timeOut($ai_v{master}{time}, 15) && distance($actor->{pos}, $char->{pos_to}) > $config{followDistanceMax})
			) {
				$ai_v{master} = {x => $actor->{pos}{x}, y => $actor->{pos}{y}, map => $actor->{map}, time => time};
				
				my ($master_map, undef) = Field::nameToBaseName(undef, $actor->{map});
				if ($master_map ne $field->baseName) {
					message TF("Calculating route to find master: %s\n", $master_map), 'follow';
				} elsif (distance($actor->{pos}, $char->{pos_to}) > $config{followDistanceMax} ) {
					message TF("Calculating route to find master: %s (%s,%s)\n", $master_map, @{$actor->{pos}}{qw(x y)}), 'follow';
				} else {
					return;
				}
				
				AI::clear(qw(move route mapRoute));
				AI::ai_route($master_map, @{$actor->{pos}}{qw(x y)}, distFromGoal => $config{followDistanceMin});
				
				if (defined ($followIndex = AI::findAction('follow'))) {
					$ai_seq_args[$followIndex]{ai_follow_lost_end}{timeout} = $timeout{ai_follow_lost_end}{timeout};
				}
			}
		}
	}
}

sub bus_message_received {
	my (undef, undef, $msg) = @_;
	
	if ($msg->{messageID} eq BUS_MESSAGE_ID && defined $msg->{args}{ID}) {
		if ($msg->{args}{master_ip} eq $masterServer->{ip}) {
			my $actor = $gps_players_list->getByID($msg->{args}{ID});
			my $mustAdd;
			unless (defined $actor) {
				$actor = new Actor::Player;
				$mustAdd = 1;
			}
			
			(@{$actor->{pos}}{qw(x y)}, @{$actor}{qw(map bus_clientID), ACTOR_FIELDS})
			= @{$msg->{args}}{qw(pos_x pos_y map FROM), ACTOR_FIELDS};
			
			if ($mustAdd) {
				$gps_players_list->add($actor);
				$gps_client_to_player{$actor->{bus_clientID}} = $actor->{ID};
				message TF("%s appeared on GPS at %s %d %d\n", $actor, $actor->{map}, @{$actor->{pos}}{qw(x y)}), DOMAIN;
			}
		}
	} elsif ($msg->{messageID} eq 'LEAVE' && defined $msg->{args}{clientID}) {
		if (exists $gps_client_to_player{$msg->{args}{clientID}}) {
			if (my $actor = $gps_players_list->getByID($gps_client_to_player{$msg->{args}{clientID}})) {
				message TF("%s disappeared from GPS at %s %d %d\n", $actor, $actor->{map}, @{$actor->{pos}}{qw(x y)}), DOMAIN;
				$gps_players_list->removeByID($gps_client_to_player{$msg->{args}{clientID}});
			}
			delete $gps_client_to_player{$msg->{args}{clientID}};
		}
	}
}

sub command {
	
}
Also it would be good to implement off-screen actor list independently so other features can fill it / depend on it too.

ryanblonna3
Human
Human
Posts: 30
Joined: 29 Jul 2010, 11:53
Noob?: No

Re: About the bus system

#5 Post by ryanblonna3 »

Great, so there is development going on in this area. :-) I have to study the code first, but this is a heck of a lot of useful code I can use, thanks!

Yeah, AI efficiency would definitely improve if it used less of the RO server to get/recieve/store data and utilized the Bus more. I think this would be specially true for those of us with little internet connectivity.

Thanks for the informative and detailed reply!

Shakti-lar
Noob
Noob
Posts: 8
Joined: 17 Jan 2015, 20:45
Noob?: Yes

Re: About the bus system

#6 Post by Shakti-lar »

hi, i just want to know,
is this busgps working?
what about newly added bus_userAgent function work?

Locked