Adding log propagation and location change.

This commit is contained in:
Sergiotarxz 2023-06-18 20:29:42 +02:00
parent e2a5c3d235
commit dd944416b7
12 changed files with 273 additions and 117 deletions

View File

@ -9,19 +9,20 @@ my $build = Module::Build->new(
dist_author => 'Sergio Iglesias <contact@owlcode.tech>', dist_author => 'Sergio Iglesias <contact@owlcode.tech>',
dist_abstract => 'Juego de L3TDE.', dist_abstract => 'Juego de L3TDE.',
requires => { requires => {
'Mojolicious' => 0, 'Mojolicious' => 0,
'Moo' => 0, 'Moo' => 0,
'Params::ValidationCompiler' => 0, 'Params::ValidationCompiler' => 0,
'Types::Standard' => 0, 'Types::Standard' => 0,
'Crypt::URandom' => 0, 'Crypt::URandom' => 0,
'Crypt::Bcrypt' => 0, 'Crypt::Bcrypt' => 0,
'DBIx::Class' => 0, 'DBIx::Class' => 0,
'DBIx::Class::DeploymentHandler' => 0, 'DBIx::Class::DeploymentHandler' => 0,
'UUID::URandom' => 0, 'UUID::URandom' => 0,
'Module::Pluggable' => 0, 'Module::Pluggable' => 0,
'Redis' => 0, 'Mojo::Redis' => 0,
'List::AllUtils' => 0, 'List::AllUtils' => 0,
'DateTime::Format::Pg' => 0, 'DateTime::Format::Pg' => 0,
'DateTime::Format::ISO8601::Format' => 0,
}, },
); );
$build->create_build_script; $build->create_build_script;

View File

@ -39,6 +39,7 @@ export default function Game (props: GameProps): JSX.Element {
const [currentLocation, setCurrentLocation] = React.useState<Location | null>(null) const [currentLocation, setCurrentLocation] = React.useState<Location | null>(null)
const [connectedLocations, setConnectedLocations] = React.useState<Location[] | null>(null) const [connectedLocations, setConnectedLocations] = React.useState<Location[] | null>(null)
const [logLines, setLogLines] = React.useState<LogLine[] | null>(null) const [logLines, setLogLines] = React.useState<LogLine[] | null>(null)
const [error, setError] = React.useState<string | null>(null)
if (websocket === null) { if (websocket === null) {
window.setTimeout(() => { window.setTimeout(() => {
const locationProtocol = window.location.protocol const locationProtocol = window.location.protocol
@ -58,7 +59,9 @@ export default function Game (props: GameProps): JSX.Element {
window.clearInterval(interval) window.clearInterval(interval)
}, 10000) }, 10000)
} }
const inputPackets = new InputPackets(setTeamPJs, setCurrentLocation, setConnectedLocations, setLogLines) const inputPackets = new InputPackets(setTeamPJs,
setCurrentLocation, setConnectedLocations,
logLines, setLogLines, setError)
webSocket.onmessage = (event) => { webSocket.onmessage = (event) => {
const packet = JSON.parse(event.data) const packet = JSON.parse(event.data)
inputPackets.handle(packet) inputPackets.handle(packet)
@ -74,7 +77,8 @@ export default function Game (props: GameProps): JSX.Element {
<UpperPanel teamPJs={teamPJs} <UpperPanel teamPJs={teamPJs}
currentLocation={currentLocation} currentLocation={currentLocation}
connectedLocations={connectedLocations} connectedLocations={connectedLocations}
logLines={logLines}/> logLines={logLines}
websocket={websocket}/>
<BottomPanel/> <BottomPanel/>
</> </>
) )

View File

@ -3,12 +3,14 @@ import type { Location } from '@lastres/location'
import type { PJ } from '@lastres/pj' import type { PJ } from '@lastres/pj'
import type { LogLine } from '@lastres/log-line' import type { LogLine } from '@lastres/log-line'
import PJListItem from '@lastres/components/pj-list-item' import PJListItem from '@lastres/components/pj-list-item'
import MoveToPacket from '@lastres/output-packet/move-to'
interface UpperPanelProps { interface UpperPanelProps {
connectedLocations: Location[] | null connectedLocations: Location[] | null
teamPJs: PJ[] | null teamPJs: PJ[] | null
currentLocation: Location | null currentLocation: Location | null
logLines: LogLine[] | null logLines: LogLine[] | null
websocket: WebSocket | null
} }
interface Style { interface Style {
@ -21,6 +23,7 @@ export default function UpperPanel (props: UpperPanelProps): JSX.Element {
const teamPJs = props.teamPJs const teamPJs = props.teamPJs
const currentLocation = props.currentLocation const currentLocation = props.currentLocation
const logLines = props.logLines const logLines = props.logLines
const websocket = props.websocket
if (!(teamPJs !== null && currentLocation !== null && connectedLocations !== null)) { if (!(teamPJs !== null && currentLocation !== null && connectedLocations !== null)) {
return ( return (
<> <>
@ -28,14 +31,26 @@ export default function UpperPanel (props: UpperPanelProps): JSX.Element {
</> </>
) )
} }
function onClickLocation (item: Location): void {
const moveToPacket = new MoveToPacket(item)
if (websocket !== null) {
moveToPacket.send(websocket)
}
}
function generateLog (): React.ReactNode { function generateLog (): React.ReactNode {
if (logLines === null || logLines.length < 1) { if (logLines === null || logLines.length < 1) {
return ( return (
<>No log</> <>No log</>
) )
} }
return logLines.reverse().map((item, i) => { return logLines.sort(function (a: LogLine, b: LogLine): number {
return <> const aDate = Date.parse(a.date)
const bDate = Date.parse(b.date)
return aDate - bDate
}).map((item, i) => {
return <span key={i}>
<b>{item.date}</b> { <b>{item.date}</b> {
item.content.map((item, i) => { item.content.map((item, i) => {
const style: Style = {} const style: Style = {}
@ -48,7 +63,7 @@ export default function UpperPanel (props: UpperPanelProps): JSX.Element {
return <span key={i} style={style}>{item.text}</span> return <span key={i} style={style}>{item.text}</span>
}) })
} <br/> } <br/>
</> </span>
}) })
} }
return ( return (
@ -74,7 +89,9 @@ export default function UpperPanel (props: UpperPanelProps): JSX.Element {
{ {
connectedLocations.map((item, i) => { connectedLocations.map((item, i) => {
return <li key={i}> return <li key={i}>
<a href="#">{item.area.name}/{item.location.name}</a> <a href="#" onClick={() => {
onClickLocation(item)
}}>{item.area.name}/{item.location.name}</a>
</li> </li>
}) })
} }

View File

@ -4,30 +4,42 @@ import type InputPacket from '@lastres/input-packet'
import type { LogLine } from '@lastres/log-line' import type { LogLine } from '@lastres/log-line'
import InputPacketInfo from '@lastres/input-packet/info' import InputPacketInfo from '@lastres/input-packet/info'
import InputPacketPong from '@lastres/input-packet/pong' import InputPacketPong from '@lastres/input-packet/pong'
type SetTeamPJs = (set: PJ[] | null) => void type SetTeamPJs = (set: PJ[] | null) => void
type SetCurrentLocation = (set: Location | null) => void type SetCurrentLocation = (set: Location | null) => void
type SetConnectedLocations = (set: Location[] | null) => void type SetConnectedLocations = (set: Location[] | null) => void
type DispatchHash = Record<string, any> type DispatchHash = Record<string, any>
type SetLogLines = (set: LogLine[] | null) => void type SetLogLinesCallback = (set: LogLine[] | null) => LogLine[]
type SetLogLines = (set: LogLine[] | SetLogLinesCallback | null) => void
type SetError = (set: string | null) => void
interface Packet { interface Packet {
command: string command: string
data: any data: any
} }
type LogHash = Record<string, LogLine>
export default class InputPackets { export default class InputPackets {
setTeamPJs: SetTeamPJs setTeamPJs: SetTeamPJs
setCurrentLocation: SetCurrentLocation setCurrentLocation: SetCurrentLocation
setConnectedLocations: SetConnectedLocations setConnectedLocations: SetConnectedLocations
setLogLines: SetLogLines setLogLines: SetLogLines
logLines: LogLine[] | null
cachedHash: DispatchHash | null = null cachedHash: DispatchHash | null = null
cachedArray: InputPacket[] | null = null cachedArray: InputPacket[] | null = null
setError: SetError
constructor (setTeamPJs: SetTeamPJs, constructor (setTeamPJs: SetTeamPJs,
setCurrentLocation: SetCurrentLocation, setCurrentLocation: SetCurrentLocation,
setConnectedLocations: SetConnectedLocations, setConnectedLocations: SetConnectedLocations,
setLogLines: SetLogLines) { logLines: LogLine[] | null,
setLogLines: SetLogLines,
setError: SetError) {
this.setTeamPJs = setTeamPJs this.setTeamPJs = setTeamPJs
this.setCurrentLocation = setCurrentLocation this.setCurrentLocation = setCurrentLocation
this.setConnectedLocations = setConnectedLocations this.setConnectedLocations = setConnectedLocations
this.logLines = logLines
this.setLogLines = setLogLines this.setLogLines = setLogLines
this.setError = setError
} }
handle (packet: Packet): void { handle (packet: Packet): void {
@ -42,10 +54,38 @@ export default class InputPackets {
const infoPacket = new InputPacketInfo() const infoPacket = new InputPacketInfo()
const pongPacket = new InputPacketPong() const pongPacket = new InputPacketPong()
infoPacket.onReceive((data) => { infoPacket.onReceive((data) => {
this.setTeamPJs(data.team_pjs) if (data.error !== undefined) {
this.setConnectedLocations(data.location_data.connected_places) this.setError(data.error)
this.setCurrentLocation(data.location_data.current) return
this.setLogLines(data.set_log) }
if (data.team_pjs !== undefined) {
this.setTeamPJs(data.team_pjs)
}
if (data.location_data?.connected_places !== undefined) {
this.setConnectedLocations(data.location_data.connected_places)
}
if (data.location_data?.current !== undefined) {
this.setCurrentLocation(data.location_data.current)
}
if (data.set_log !== undefined) {
this.setLogLines(data.set_log)
}
if (data.append_log !== undefined) {
const logHash: LogHash = {}
this.setLogLines((logLines: LogLine[] | null): LogLine[] => {
if (logLines !== null) {
for (const item of logLines) {
logHash[item.uuid] = item
}
logHash[data.append_log.uuid] = data.append_log
const outputLog: LogLine[] = Object.keys(logHash).map((item, i): LogLine => {
return logHash[item]
})
return outputLog
}
return []
})
}
}) })
this.cachedArray = [infoPacket, pongPacket] this.cachedArray = [infoPacket, pongPacket]
} }

View File

@ -1,11 +1,10 @@
export default abstract class OutputPacket { export default abstract class OutputPacket {
send(ws: WebSocket): void { send (ws: WebSocket): void {
const data = this.data();
ws.send(JSON.stringify({ ws.send(JSON.stringify({
command: this.command(), command: this.command(),
data: this.data(), data: this.data()
})) }))
} }
abstract data(): any abstract data (): any
abstract command(): string abstract command (): string
} }

View File

@ -11,7 +11,7 @@ use Data::Dumper;
use Moo; use Moo;
use JSON; use JSON qw/to_json from_json/;
use LasTres::Flags; use LasTres::Flags;
use LasTres::Redis; use LasTres::Redis;
@ -29,22 +29,22 @@ sub identifier {
sub handle ( $self, $ws, $session, $data ) { sub handle ( $self, $ws, $session, $data ) {
if ( ref $data ne 'HASH' ) { if ( ref $data ne 'HASH' ) {
return $ws->send( return $ws->send(
encode_json( { error => "Data should be a hashref." } ) ); to_json( { error => "Data should be a hashref." } ) );
} }
my $pj_uuid = $data->{pj_uuid}; my $pj_uuid = $data->{pj_uuid};
if ( !defined $pj_uuid ) { if ( !defined $pj_uuid ) {
return $ws->send( encode_json( { error => "No pj sent." } ) ); return $ws->send( to_json( { error => "No pj sent." } ) );
} }
my @pjs = $result_set_pjs->search( { uuid => $pj_uuid } ); my @pjs = $result_set_pjs->search( { uuid => $pj_uuid } );
if ( !scalar @pjs ) { if ( !scalar @pjs ) {
return $ws->send( return $ws->send(
encode_json( { error => 'This pj does not exists' } ) ); to_json( { error => 'This pj does not exists' } ) );
} }
my $pj = $pjs[0]; my $pj = $pjs[0];
my $user = $session->{user}; my $user = $session->{user};
if ( $pj->owner->uuid ne $user->uuid ) { if ( $pj->owner->uuid ne $user->uuid ) {
return $ws->send( return $ws->send(
encode_json( { error => 'You are not the owner of this pj.' } ) ); to_json( { error => 'You are not the owner of this pj.' } ) );
} }
$session->{pj} = $pj; $session->{pj} = $pj;
my $team = $pj->team; my $team = $pj->team;
@ -83,20 +83,34 @@ sub handle ( $self, $ws, $session, $data ) {
clear => $JSON::true, clear => $JSON::true,
); );
$info_packet_to_send->send($ws); $info_packet_to_send->send($ws);
require LasTres::Redis;
my $redis = LasTres::Redis->new;
say $redis->pj_subscription($pj);
$redis->subscribe($redis->pj_subscription($pj), my $save = sub($message, $topic, $topics) {
return $self->_on_redis_event($ws, $session, $message, $topic, $topics);
});
$session->{redis} = $redis;
}
sub _on_redis_event($self, $ws, $session, $message, $topic, $topics) {
say 'Receiving Redis event ' . $topic;
my $data = from_json($message);
my $pj = $session->{pj};
if ($data->{command} eq 'append-log') {
my $info_packet_to_send =
LasTres::Controller::Websocket::OutputPacket::Info->new(
append_log => $data->{log}
);
$info_packet_to_send->send($ws);
}
} }
sub _get_connected_places ( $self, $pj ) { sub _get_connected_places ( $self, $pj ) {
my $team = $pj->team; my $team = $pj->team;
my $location = $team->location; my $location = $team->location;
my $connected_places = []; my $connected_places = $location->get_available_locations_to_move_to($pj);
if ( $location->can('connected_places') ) {
@$connected_places = ( @{ $team->location->connected_places } );
}
@$connected_places =
( @$connected_places, @{ $location->parent->children } );
@$connected_places =
grep { $_->identifier ne $location->identifier } @$connected_places;
@$connected_places = map { $_->hash } @$connected_places; @$connected_places = map { $_->hash } @$connected_places;
return $connected_places; return $connected_places;
} }

View File

@ -13,50 +13,45 @@ use Moo;
with 'LasTres::Controller::Websocket::OutputPacket'; with 'LasTres::Controller::Websocket::OutputPacket';
has clear => ( has clear => ( is => 'rw', );
is => 'rw',
);
has team_pjs => ( has team_pjs => ( is => 'rw', );
is => 'rw',
);
has location_data => ( has location_data => ( is => 'rw', );
is => 'rw',
);
has set_log => ( has set_log => ( is => 'rw', );
is => 'rw', has append_log => ( is => 'rw' );
);
sub identifier { sub identifier {
return 'info'; return 'info';
} }
sub data($self) { sub data ($self) {
my $clear = $self->clear; my $clear = $self->clear;
my $team_pjs = $self->team_pjs; my $team_pjs = $self->team_pjs;
my $location_data = $self->location_data; my $location_data = $self->location_data;
my $set_log = $self->set_log; my $set_log = $self->set_log;
my $append_log = $self->append_log;
return { return {
( (
(defined $clear) ( defined $clear ) ? ( clear => $clear )
? (clear => $clear)
: () : ()
), ),
( (
(defined $team_pjs) ( defined $team_pjs ) ? ( team_pjs => $team_pjs )
? (team_pjs => $team_pjs)
: () : ()
), ),
( (
(defined $location_data) ( defined $location_data ) ? ( location_data => $location_data )
? (location_data => $location_data)
: () : ()
), ),
( (
(defined $set_log) ( defined $set_log ) ? ( set_log => [ map { $_->hash } @$set_log ] )
? (set_log => [map { $_->hash } @$set_log]) : ()
),
(
( defined $append_log )
? ( append_log => $append_log )
: () : ()
) )
}; };

View File

@ -10,77 +10,131 @@ use feature 'signatures';
use LasTres::Planets; use LasTres::Planets;
use Moo::Role; use Moo::Role;
use JSON qw/to_json/;
requires qw/identifier name description parent actions npcs/; requires qw/identifier name description parent actions npcs/;
my $planets = LasTres::Planets->new; my $planets = LasTres::Planets->new;
sub show_intro($self, $pj) { sub show_intro ( $self, $pj ) {
$pj->append_log_line([ $pj->append_log_line(
{ text => 'Estas en ' }, [
{ color => 'red', text => $self->parent->name }, { text => 'Estas en ' },
{ text => '/' }, { color => 'red', text => $self->parent->name },
{ color => 'green', text => $self->name }, { text => '/' },
]); { color => 'green', text => $self->name },
$pj->append_log_line([ ]
{ text => $pj->location->description }, );
]); $pj->append_log_line( [ { text => $pj->location->description }, ] );
} }
sub get($planet_id, $super_area_id, $area_id, $location_id) { sub notify_arrival($self, $team) {
for my $pj ($team->members) {
$self->show_intro($pj);
}
}
sub place_team($self, $team) {
$team->location($self);
$team->update;
$self->notify_arrival($team);
}
sub to_json_array ($self) {
my $hash = $self->hash;
return to_json(
[
$hash->{planet}{identifier}, $hash->{super_area}{identifier},
$hash->{area}{identifier}, $hash->{location}{identifier}
]
);
}
sub is_connected_by_move ( $self, $otherLocation, $pj = undef ) {
if ( !defined $otherLocation ) {
die '$otherLocation must be defined in is_connected.';
}
my $json_array_other_location = $otherLocation->to_json_array;
if ( grep { $_->to_json_array eq $json_array_other_location }
@{ $self->get_available_locations_to_move_to($pj) } )
{
return 1;
}
return 0;
}
sub get_available_locations_to_move_to ( $self, $pj ) {
my $team = $pj->team;
my $location = $team->location;
my $connected_places = [];
if ( $location->can('connected_places') ) {
@$connected_places = ( @{ $team->location->connected_places } );
}
@$connected_places =
( @$connected_places, @{ $location->parent->children } );
@$connected_places =
grep { $_->identifier ne $location->identifier } @$connected_places;
return $connected_places;
}
sub get ( $planet_id, $super_area_id, $area_id, $location_id ) {
my $planet = $planets->hash->{$planet_id}; my $planet = $planets->hash->{$planet_id};
if (!defined $planet) { if ( !defined $planet ) {
die "No such planet $planet_id."; die "No such planet $planet_id.";
} }
my $super_area = $planet->super_areas->{$super_area_id}; my $super_area = $planet->super_areas->{$super_area_id};
if (!defined $super_area) { if ( !defined $super_area ) {
die "No such super_area $super_area_id in planet $planet_id."; die "No such super_area $super_area_id in planet $planet_id.";
} }
my $area = $super_area->areas->{$area_id}; my $area = $super_area->areas->{$area_id};
if (!defined $area) { if ( !defined $area ) {
die "No such area $area_id in super_area $super_area_id in planet $planet_id."; die
"No such area $area_id in super_area $super_area_id in planet $planet_id.";
} }
my $location = $area->locations->{$location_id}; my $location = $area->locations->{$location_id};
if (!defined $location) { if ( !defined $location ) {
die "No such location $location_id in area $area_id in super_area $super_area_id in planet $planet_id."; die
"No such location $location_id in area $area_id in super_area $super_area_id in planet $planet_id.";
} }
return $location; return $location;
} }
sub hash($self) { sub hash ($self) {
my $location = $self; my $location = $self;
if (!Moo::Role::does_role($location, 'LasTres::Location')) { if ( !Moo::Role::does_role( $location, 'LasTres::Location' ) ) {
die "$location does not implement LasTres::Location."; die "$location does not implement LasTres::Location.";
} }
my $area = $location->parent; my $area = $location->parent;
if (!Moo::Role::does_role($area, 'LasTres::Area')) { if ( !Moo::Role::does_role( $area, 'LasTres::Area' ) ) {
die "$area does not implement LasTres::Area."; die "$area does not implement LasTres::Area.";
} }
my $super_area = $area->parent; my $super_area = $area->parent;
if (!Moo::Role::does_role($super_area, 'LasTres::SuperArea')) { if ( !Moo::Role::does_role( $super_area, 'LasTres::SuperArea' ) ) {
die "$super_area does not implement LasTres::SuperArea."; die "$super_area does not implement LasTres::SuperArea.";
} }
my $planet = $super_area->parent; my $planet = $super_area->parent;
if (!Moo::Role::does_role($planet, 'LasTres::Planet')) { if ( !Moo::Role::does_role( $planet, 'LasTres::Planet' ) ) {
die "$planet does not implement LasTres::Planet."; die "$planet does not implement LasTres::Planet.";
} }
return { return {
planet => { planet => {
name => $planet->name, name => $planet->name,
identifier => $planet->identifier, identifier => $planet->identifier,
}, },
super_area => { super_area => {
name => $super_area->name, name => $super_area->name,
identifier => $super_area->identifier, identifier => $super_area->identifier,
}, },
area => { area => {
name => $area->name, name => $area->name,
identifier => $area->identifier, identifier => $area->identifier,
}, },
location => { location => {
name => $location->name, name => $location->name,
identifier => $location->identifier, identifier => $location->identifier,
}, },
} };
} }
1; 1;

View File

@ -7,24 +7,37 @@ use warnings;
use feature 'signatures'; use feature 'signatures';
use parent 'Redis'; use parent 'Mojo::Redis';
use LasTres::Schema; use LasTres::Schema;
our $VERSION = $LasTres::Schema::VERSION; our $VERSION = $LasTres::Schema::VERSION;
{ {
my $cached_redis;
sub new { sub new {
my $self;
my $class = shift; my $class = shift;
if (!defined $cached_redis) { if (!defined $self) {
$cached_redis = $class->SUPER::new(@_); $self = $class->SUPER::new(@_);
} }
return $cached_redis; return $self;
} }
} }
sub prefix { sub prefix {
return "LasTres::Redis::$VERSION"; return "LasTres::Redis::$VERSION";
} }
sub subscribe($self, $topic, $callback) {
$self->pubsub->listen($topic, sub($self, $message, $topic) {
$callback->($message, $topic, [$topic]);
});
}
sub publish($self, $topic, $message) {
$self->pubsub->notify($topic, $message);
}
sub pj_subscription($class, $pj) {
return prefix() . '::Subscriptions::PJ::' . $pj->uuid;
}
1; 1;

View File

@ -251,6 +251,8 @@ sub last_50_log ($self) {
sub append_log_line ( $self, $content ) { sub append_log_line ( $self, $content ) {
require LasTres::Schema; require LasTres::Schema;
require LasTres::Redis;
my $redis = LasTres::Redis->new;
if ( ref $content ne 'ARRAY' ) { if ( ref $content ne 'ARRAY' ) {
die 'Bad log content, not a arrayref.'; die 'Bad log content, not a arrayref.';
} }
@ -281,13 +283,19 @@ sub append_log_line ( $self, $content ) {
} }
} }
my $uuid = create_uuid_string; my $uuid = create_uuid_string;
LasTres::Schema->Schema->resultset('PJLog') my $log =
LasTres::Schema->Schema->resultset('PJLog')
->new( ->new(
{ uuid => $uuid, owner => $self->uuid, content => to_json($content) } ) { uuid => $uuid, owner => $self->uuid, content => to_json($content) } );
->insert; $log->insert;
$log = $log->get_from_storage;
say 'Sending redis event '. $redis->pj_subscription($self);
$redis->publish( $redis->pj_subscription($self),
to_json( { command => 'append-log', log => $log->hash } ) );
} }
sub location($self) { sub location ($self) {
return $self->team->location; return $self->team->location;
} }
@ -299,12 +307,12 @@ sub set_flag ( $self, $name ) {
require LasTres::Schema; require LasTres::Schema;
my $schema = LasTres::Schema->Schema; my $schema = LasTres::Schema->Schema;
my $result_set_flags = $schema->resultset('PJFlag'); my $result_set_flags = $schema->resultset('PJFlag');
my $flag = $result_set_flags->new({name => $name, owner => $self->uuid}) my $flag = $result_set_flags->new( { name => $name, owner => $self->uuid } )
->update_or_insert; ->update_or_insert;
} }
sub get_flag ( $self, $name ) { sub get_flag ( $self, $name ) {
my @flags = $self->flags->search({name => $name}); my @flags = $self->flags->search( { name => $name } );
if ( scalar @flags ) { if ( scalar @flags ) {
return 1; return 1;
} }
@ -314,5 +322,4 @@ sub get_flag ( $self, $name ) {
sub clear_flag ( $self, $name ) { sub clear_flag ( $self, $name ) {
$self->flags->search( name => $name )->delete; $self->flags->search( name => $name )->delete;
} }
1; 1;

View File

@ -11,6 +11,7 @@ use parent 'DBIx::Class::Core';
use Data::Dumper; use Data::Dumper;
use JSON qw/from_json/; use JSON qw/from_json/;
use DateTime::Format::ISO8601::Format;
use Moo; use Moo;
@ -48,10 +49,11 @@ __PACKAGE__->set_primary_key('uuid');
__PACKAGE__->belongs_to( 'owner', 'LasTres::Schema::Result::PJ' ); __PACKAGE__->belongs_to( 'owner', 'LasTres::Schema::Result::PJ' );
sub hash ($self) { sub hash ($self) {
my $iso_formatter = DateTime::Format::ISO8601::Format->new(second_precision => 3);
return { return {
uuid => $self->uuid, uuid => $self->uuid,
content => $self->content, content => $self->content,
date => $self->date, date => $iso_formatter->format_datetime($self->date)
}; };
} }

View File

@ -96,7 +96,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
\************************************/ \************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ Game)\n/* harmony export */ });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _lastres_components_upper_panel__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @lastres/components/upper-panel */ \"./js-src/components/upper-panel.tsx\");\n/* harmony import */ var _lastres_components_bottom_panel__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @lastres/components/bottom-panel */ \"./js-src/components/bottom-panel.tsx\");\n/* harmony import */ var _lastres_components_pj_selection_menu__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @lastres/components/pj-selection-menu */ \"./js-src/components/pj-selection-menu.tsx\");\n/* harmony import */ var _lastres_output_packet_init__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @lastres/output-packet/init */ \"./js-src/output-packet/init.ts\");\n/* harmony import */ var _lastres_output_packet_ping__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @lastres/output-packet/ping */ \"./js-src/output-packet/ping.ts\");\n/* harmony import */ var _lastres_input_packets__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @lastres/input-packets */ \"./js-src/input-packets.ts\");\n\n\n\n\n\n\n\nfunction Game(props) {\n const selectedPJ = props.selectedPJ;\n if (selectedPJ === null) {\n return (react__WEBPACK_IMPORTED_MODULE_0__.createElement(react__WEBPACK_IMPORTED_MODULE_0__.Fragment, null,\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(_lastres_components_pj_selection_menu__WEBPACK_IMPORTED_MODULE_3__[\"default\"], { setSelectedPJ: props.setSelectedPJ, userWantsToCreatePJ: props.userWantsToCreatePJ, setUserWantsToCreatePJ: props.setUserWantsToCreatePJ, error: props.error, setError: props.setError })));\n }\n const [websocket, setWebsocket] = react__WEBPACK_IMPORTED_MODULE_0__.useState(null);\n const [teamPJs, setTeamPJs] = react__WEBPACK_IMPORTED_MODULE_0__.useState(null);\n const [currentLocation, setCurrentLocation] = react__WEBPACK_IMPORTED_MODULE_0__.useState(null);\n const [connectedLocations, setConnectedLocations] = react__WEBPACK_IMPORTED_MODULE_0__.useState(null);\n const [logLines, setLogLines] = react__WEBPACK_IMPORTED_MODULE_0__.useState(null);\n if (websocket === null) {\n window.setTimeout(() => {\n const locationProtocol = window.location.protocol;\n if (locationProtocol == null) {\n return;\n }\n const protocol = locationProtocol.match(/https:/) != null ? 'wss' : 'ws';\n const webSocket = new WebSocket(`${protocol}://${window.location.host}/ws`);\n webSocket.onopen = () => {\n new _lastres_output_packet_init__WEBPACK_IMPORTED_MODULE_4__[\"default\"](selectedPJ.uuid).send(webSocket);\n let interval = 0;\n interval = window.setInterval(() => {\n if (webSocket.readyState === WebSocket.OPEN) {\n new _lastres_output_packet_ping__WEBPACK_IMPORTED_MODULE_5__[\"default\"]().send(webSocket);\n return;\n }\n window.clearInterval(interval);\n }, 10000);\n };\n const inputPackets = new _lastres_input_packets__WEBPACK_IMPORTED_MODULE_6__[\"default\"](setTeamPJs, setCurrentLocation, setConnectedLocations, setLogLines);\n webSocket.onmessage = (event) => {\n const packet = JSON.parse(event.data);\n inputPackets.handle(packet);\n };\n webSocket.onerror = (event) => {\n console.log(event);\n };\n setWebsocket(webSocket);\n }, 1);\n }\n return (react__WEBPACK_IMPORTED_MODULE_0__.createElement(react__WEBPACK_IMPORTED_MODULE_0__.Fragment, null,\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(_lastres_components_upper_panel__WEBPACK_IMPORTED_MODULE_1__[\"default\"], { teamPJs: teamPJs, currentLocation: currentLocation, connectedLocations: connectedLocations, logLines: logLines }),\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(_lastres_components_bottom_panel__WEBPACK_IMPORTED_MODULE_2__[\"default\"], null)));\n}\n\n\n//# sourceURL=webpack://LasTres/./js-src/components/game.tsx?"); eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ Game)\n/* harmony export */ });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _lastres_components_upper_panel__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @lastres/components/upper-panel */ \"./js-src/components/upper-panel.tsx\");\n/* harmony import */ var _lastres_components_bottom_panel__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @lastres/components/bottom-panel */ \"./js-src/components/bottom-panel.tsx\");\n/* harmony import */ var _lastres_components_pj_selection_menu__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @lastres/components/pj-selection-menu */ \"./js-src/components/pj-selection-menu.tsx\");\n/* harmony import */ var _lastres_output_packet_init__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @lastres/output-packet/init */ \"./js-src/output-packet/init.ts\");\n/* harmony import */ var _lastres_output_packet_ping__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @lastres/output-packet/ping */ \"./js-src/output-packet/ping.ts\");\n/* harmony import */ var _lastres_input_packets__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @lastres/input-packets */ \"./js-src/input-packets.ts\");\n\n\n\n\n\n\n\nfunction Game(props) {\n const selectedPJ = props.selectedPJ;\n if (selectedPJ === null) {\n return (react__WEBPACK_IMPORTED_MODULE_0__.createElement(react__WEBPACK_IMPORTED_MODULE_0__.Fragment, null,\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(_lastres_components_pj_selection_menu__WEBPACK_IMPORTED_MODULE_3__[\"default\"], { setSelectedPJ: props.setSelectedPJ, userWantsToCreatePJ: props.userWantsToCreatePJ, setUserWantsToCreatePJ: props.setUserWantsToCreatePJ, error: props.error, setError: props.setError })));\n }\n const [websocket, setWebsocket] = react__WEBPACK_IMPORTED_MODULE_0__.useState(null);\n const [teamPJs, setTeamPJs] = react__WEBPACK_IMPORTED_MODULE_0__.useState(null);\n const [currentLocation, setCurrentLocation] = react__WEBPACK_IMPORTED_MODULE_0__.useState(null);\n const [connectedLocations, setConnectedLocations] = react__WEBPACK_IMPORTED_MODULE_0__.useState(null);\n const [logLines, setLogLines] = react__WEBPACK_IMPORTED_MODULE_0__.useState(null);\n const [error, setError] = react__WEBPACK_IMPORTED_MODULE_0__.useState(null);\n if (websocket === null) {\n window.setTimeout(() => {\n const locationProtocol = window.location.protocol;\n if (locationProtocol == null) {\n return;\n }\n const protocol = locationProtocol.match(/https:/) != null ? 'wss' : 'ws';\n const webSocket = new WebSocket(`${protocol}://${window.location.host}/ws`);\n webSocket.onopen = () => {\n new _lastres_output_packet_init__WEBPACK_IMPORTED_MODULE_4__[\"default\"](selectedPJ.uuid).send(webSocket);\n let interval = 0;\n interval = window.setInterval(() => {\n if (webSocket.readyState === WebSocket.OPEN) {\n new _lastres_output_packet_ping__WEBPACK_IMPORTED_MODULE_5__[\"default\"]().send(webSocket);\n return;\n }\n window.clearInterval(interval);\n }, 10000);\n };\n const inputPackets = new _lastres_input_packets__WEBPACK_IMPORTED_MODULE_6__[\"default\"](setTeamPJs, setCurrentLocation, setConnectedLocations, logLines, setLogLines, setError);\n webSocket.onmessage = (event) => {\n const packet = JSON.parse(event.data);\n inputPackets.handle(packet);\n };\n webSocket.onerror = (event) => {\n console.log(event);\n };\n setWebsocket(webSocket);\n }, 1);\n }\n return (react__WEBPACK_IMPORTED_MODULE_0__.createElement(react__WEBPACK_IMPORTED_MODULE_0__.Fragment, null,\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(_lastres_components_upper_panel__WEBPACK_IMPORTED_MODULE_1__[\"default\"], { teamPJs: teamPJs, currentLocation: currentLocation, connectedLocations: connectedLocations, logLines: logLines, websocket: websocket }),\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(_lastres_components_bottom_panel__WEBPACK_IMPORTED_MODULE_2__[\"default\"], null)));\n}\n\n\n//# sourceURL=webpack://LasTres/./js-src/components/game.tsx?");
/***/ }), /***/ }),
@ -186,7 +186,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
\*******************************************/ \*******************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ UpperPanel)\n/* harmony export */ });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _lastres_components_pj_list_item__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @lastres/components/pj-list-item */ \"./js-src/components/pj-list-item.tsx\");\n\n\nfunction UpperPanel(props) {\n const connectedLocations = props.connectedLocations;\n const teamPJs = props.teamPJs;\n const currentLocation = props.currentLocation;\n const logLines = props.logLines;\n if (!(teamPJs !== null && currentLocation !== null && connectedLocations !== null)) {\n return (react__WEBPACK_IMPORTED_MODULE_0__.createElement(react__WEBPACK_IMPORTED_MODULE_0__.Fragment, null,\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"p\", null, \"Esperando datos...\")));\n }\n function generateLog() {\n if (logLines === null || logLines.length < 1) {\n return (react__WEBPACK_IMPORTED_MODULE_0__.createElement(react__WEBPACK_IMPORTED_MODULE_0__.Fragment, null, \"No log\"));\n }\n return logLines.reverse().map((item, i) => {\n return react__WEBPACK_IMPORTED_MODULE_0__.createElement(react__WEBPACK_IMPORTED_MODULE_0__.Fragment, null,\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"b\", null, item.date),\n \" \",\n item.content.map((item, i) => {\n const style = {};\n if (item.color !== undefined) {\n style.color = item.color;\n }\n if (item.background !== undefined) {\n style.background = item.background;\n }\n return react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"span\", { key: i, style: style }, item.text);\n }),\n \" \",\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"br\", null));\n });\n }\n return (react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"div\", { className: \"presentation\" },\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"div\", { className: \"presentation-item\" }, teamPJs.map((item, i) => {\n return react__WEBPACK_IMPORTED_MODULE_0__.createElement(_lastres_components_pj_list_item__WEBPACK_IMPORTED_MODULE_1__[\"default\"], { key: i, pj: item });\n })),\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"div\", { className: \"presentation-item\" },\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"code\", null,\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"pre\", null, generateLog()))),\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"div\", { className: \"presentation-item\" },\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"p\", null,\n \"Est\\u00E1s en \",\n currentLocation.area.name,\n \"/\",\n currentLocation.location.name,\n \".\"),\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"p\", null, \"Puedes ir a:\"),\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"ul\", null, connectedLocations.map((item, i) => {\n return react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"li\", { key: i },\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"a\", { href: \"#\" },\n item.area.name,\n \"/\",\n item.location.name));\n })))));\n}\n\n\n//# sourceURL=webpack://LasTres/./js-src/components/upper-panel.tsx?"); eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ UpperPanel)\n/* harmony export */ });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"./node_modules/react/index.js\");\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);\n/* harmony import */ var _lastres_components_pj_list_item__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @lastres/components/pj-list-item */ \"./js-src/components/pj-list-item.tsx\");\n/* harmony import */ var _lastres_output_packet_move_to__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @lastres/output-packet/move-to */ \"./js-src/output-packet/move-to.ts\");\n\n\n\nfunction UpperPanel(props) {\n const connectedLocations = props.connectedLocations;\n const teamPJs = props.teamPJs;\n const currentLocation = props.currentLocation;\n const logLines = props.logLines;\n const websocket = props.websocket;\n if (!(teamPJs !== null && currentLocation !== null && connectedLocations !== null)) {\n return (react__WEBPACK_IMPORTED_MODULE_0__.createElement(react__WEBPACK_IMPORTED_MODULE_0__.Fragment, null,\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"p\", null, \"Esperando datos...\")));\n }\n function onClickLocation(item) {\n const moveToPacket = new _lastres_output_packet_move_to__WEBPACK_IMPORTED_MODULE_2__[\"default\"](item);\n if (websocket !== null) {\n moveToPacket.send(websocket);\n }\n }\n function generateLog() {\n if (logLines === null || logLines.length < 1) {\n return (react__WEBPACK_IMPORTED_MODULE_0__.createElement(react__WEBPACK_IMPORTED_MODULE_0__.Fragment, null, \"No log\"));\n }\n return logLines.sort(function (a, b) {\n const aDate = Date.parse(a.date);\n const bDate = Date.parse(b.date);\n return aDate - bDate;\n }).map((item, i) => {\n return react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"span\", { key: i },\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"b\", null, item.date),\n \" \",\n item.content.map((item, i) => {\n const style = {};\n if (item.color !== undefined) {\n style.color = item.color;\n }\n if (item.background !== undefined) {\n style.background = item.background;\n }\n return react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"span\", { key: i, style: style }, item.text);\n }),\n \" \",\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"br\", null));\n });\n }\n return (react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"div\", { className: \"presentation\" },\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"div\", { className: \"presentation-item\" }, teamPJs.map((item, i) => {\n return react__WEBPACK_IMPORTED_MODULE_0__.createElement(_lastres_components_pj_list_item__WEBPACK_IMPORTED_MODULE_1__[\"default\"], { key: i, pj: item });\n })),\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"div\", { className: \"presentation-item\" },\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"code\", null,\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"pre\", null, generateLog()))),\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"div\", { className: \"presentation-item\" },\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"p\", null,\n \"Est\\u00E1s en \",\n currentLocation.area.name,\n \"/\",\n currentLocation.location.name,\n \".\"),\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"p\", null, \"Puedes ir a:\"),\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"ul\", null, connectedLocations.map((item, i) => {\n return react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"li\", { key: i },\n react__WEBPACK_IMPORTED_MODULE_0__.createElement(\"a\", { href: \"#\", onClick: () => {\n onClickLocation(item);\n } },\n item.area.name,\n \"/\",\n item.location.name));\n })))));\n}\n\n\n//# sourceURL=webpack://LasTres/./js-src/components/upper-panel.tsx?");
/***/ }), /***/ }),
@ -236,7 +236,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
\*********************************/ \*********************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ InputPackets)\n/* harmony export */ });\n/* harmony import */ var _lastres_input_packet_info__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @lastres/input-packet/info */ \"./js-src/input-packet/info.ts\");\n/* harmony import */ var _lastres_input_packet_pong__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @lastres/input-packet/pong */ \"./js-src/input-packet/pong.ts\");\n\n\nclass InputPackets {\n constructor(setTeamPJs, setCurrentLocation, setConnectedLocations, setLogLines) {\n this.cachedHash = null;\n this.cachedArray = null;\n this.setTeamPJs = setTeamPJs;\n this.setCurrentLocation = setCurrentLocation;\n this.setConnectedLocations = setConnectedLocations;\n this.setLogLines = setLogLines;\n }\n handle(packet) {\n const hash = this.hashAvailablePackets();\n const identifier = packet.command;\n const inputPacket = hash[identifier];\n inputPacket.recv(packet);\n }\n listAvailablePackets() {\n if (this.cachedArray === null) {\n const infoPacket = new _lastres_input_packet_info__WEBPACK_IMPORTED_MODULE_0__[\"default\"]();\n const pongPacket = new _lastres_input_packet_pong__WEBPACK_IMPORTED_MODULE_1__[\"default\"]();\n infoPacket.onReceive((data) => {\n this.setTeamPJs(data.team_pjs);\n this.setConnectedLocations(data.location_data.connected_places);\n this.setCurrentLocation(data.location_data.current);\n this.setLogLines(data.set_log);\n });\n this.cachedArray = [infoPacket, pongPacket];\n }\n return this.cachedArray;\n }\n hashAvailablePackets() {\n if (this.cachedHash === null) {\n this.cachedHash = {};\n for (const inputPacket of this.listAvailablePackets()) {\n this.cachedHash[inputPacket.identifier()] = inputPacket;\n }\n }\n return this.cachedHash;\n }\n}\n\n\n//# sourceURL=webpack://LasTres/./js-src/input-packets.ts?"); eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ InputPackets)\n/* harmony export */ });\n/* harmony import */ var _lastres_input_packet_info__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @lastres/input-packet/info */ \"./js-src/input-packet/info.ts\");\n/* harmony import */ var _lastres_input_packet_pong__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @lastres/input-packet/pong */ \"./js-src/input-packet/pong.ts\");\n\n\nclass InputPackets {\n constructor(setTeamPJs, setCurrentLocation, setConnectedLocations, logLines, setLogLines, setError) {\n this.cachedHash = null;\n this.cachedArray = null;\n this.setTeamPJs = setTeamPJs;\n this.setCurrentLocation = setCurrentLocation;\n this.setConnectedLocations = setConnectedLocations;\n this.logLines = logLines;\n this.setLogLines = setLogLines;\n this.setError = setError;\n }\n handle(packet) {\n const hash = this.hashAvailablePackets();\n const identifier = packet.command;\n const inputPacket = hash[identifier];\n inputPacket.recv(packet);\n }\n listAvailablePackets() {\n if (this.cachedArray === null) {\n const infoPacket = new _lastres_input_packet_info__WEBPACK_IMPORTED_MODULE_0__[\"default\"]();\n const pongPacket = new _lastres_input_packet_pong__WEBPACK_IMPORTED_MODULE_1__[\"default\"]();\n infoPacket.onReceive((data) => {\n if (data.error !== undefined) {\n this.setError(data.error);\n return;\n }\n if (data.team_pjs !== undefined) {\n this.setTeamPJs(data.team_pjs);\n }\n if (data.location_data?.connected_places !== undefined) {\n this.setConnectedLocations(data.location_data.connected_places);\n }\n if (data.location_data?.current !== undefined) {\n this.setCurrentLocation(data.location_data.current);\n }\n if (data.set_log !== undefined) {\n this.setLogLines(data.set_log);\n }\n if (data.append_log !== undefined) {\n const logHash = {};\n this.setLogLines((logLines) => {\n if (logLines !== null) {\n for (const item of logLines) {\n logHash[item.uuid] = item;\n }\n logHash[data.append_log.uuid] = data.append_log;\n const outputLog = Object.keys(logHash).map((item, i) => {\n return logHash[item];\n });\n return outputLog;\n }\n return [];\n });\n }\n });\n this.cachedArray = [infoPacket, pongPacket];\n }\n return this.cachedArray;\n }\n hashAvailablePackets() {\n if (this.cachedHash === null) {\n this.cachedHash = {};\n for (const inputPacket of this.listAvailablePackets()) {\n this.cachedHash[inputPacket.identifier()] = inputPacket;\n }\n }\n return this.cachedHash;\n }\n}\n\n\n//# sourceURL=webpack://LasTres/./js-src/input-packets.ts?");
/***/ }), /***/ }),
@ -256,7 +256,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
\*********************************/ \*********************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ OutputPacket)\n/* harmony export */ });\nclass OutputPacket {\n send(ws) {\n const data = this.data();\n ws.send(JSON.stringify({\n command: this.command(),\n data: this.data(),\n }));\n }\n}\n\n\n//# sourceURL=webpack://LasTres/./js-src/output-packet.ts?"); eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ OutputPacket)\n/* harmony export */ });\nclass OutputPacket {\n send(ws) {\n ws.send(JSON.stringify({\n command: this.command(),\n data: this.data()\n }));\n }\n}\n\n\n//# sourceURL=webpack://LasTres/./js-src/output-packet.ts?");
/***/ }), /***/ }),
@ -270,6 +270,16 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac
/***/ }), /***/ }),
/***/ "./js-src/output-packet/move-to.ts":
/*!*****************************************!*\
!*** ./js-src/output-packet/move-to.ts ***!
\*****************************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ MoveToPacket)\n/* harmony export */ });\n/* harmony import */ var _lastres_output_packet__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @lastres/output-packet */ \"./js-src/output-packet.ts\");\n\nclass MoveToPacket extends _lastres_output_packet__WEBPACK_IMPORTED_MODULE_0__[\"default\"] {\n constructor(location) {\n super();\n this.location = location;\n }\n command() {\n return 'move_to';\n }\n data() {\n return {\n location: this.location.location.identifier,\n area: this.location.area.identifier,\n super_area: this.location.super_area.identifier,\n planet: this.location.planet.identifier\n };\n }\n}\n\n\n//# sourceURL=webpack://LasTres/./js-src/output-packet/move-to.ts?");
/***/ }),
/***/ "./js-src/output-packet/ping.ts": /***/ "./js-src/output-packet/ping.ts":
/*!**************************************!*\ /*!**************************************!*\
!*** ./js-src/output-packet/ping.ts ***! !*** ./js-src/output-packet/ping.ts ***!