Adding initial support for conquering nodes.
This commit is contained in:
parent
16888b9fdb
commit
389f325618
@ -24,6 +24,7 @@ import NewNodeUI from '@burguillosinfo/conquer/interface/new-node'
|
||||
import NewTeamUI from '@burguillosinfo/conquer/interface/new-team'
|
||||
import WebSocket from '@burguillosinfo/conquer/websocket'
|
||||
import JsonSerializer from '@burguillosinfo/conquer/serializer';
|
||||
import ConquerUser from '@burguillosinfo/conquer/user'
|
||||
|
||||
type StylesInterface = Record<string, Style>
|
||||
|
||||
@ -433,13 +434,21 @@ export default class Conquer {
|
||||
if (this.currentPositionFeature === null) {
|
||||
return
|
||||
}
|
||||
const user = await ConquerUser.getSelfUser()
|
||||
let color = 'white';
|
||||
if (user !== null) {
|
||||
const team = await user.getTeam();
|
||||
if (team !== null) {
|
||||
color = team.getColor();
|
||||
}
|
||||
}
|
||||
const styles: StylesInterface = {
|
||||
currentPositionFeature: new Style({
|
||||
image: new CircleStyle({
|
||||
radius: 14,
|
||||
fill: new Fill({color: 'white'}),
|
||||
fill: new Fill({color: color}),
|
||||
stroke: new Stroke({
|
||||
color: 'blue',
|
||||
color: 'beige',
|
||||
width: 2,
|
||||
})
|
||||
})
|
||||
@ -447,7 +456,7 @@ export default class Conquer {
|
||||
};
|
||||
const features = [this.currentPositionFeature]
|
||||
for (const key in this.getServerNodes()) {
|
||||
styles[key] = this.getServerNodes()[key].getStyle()
|
||||
styles[key] = await this.getServerNodes()[key].getStyle()
|
||||
features.push(this.getServerNodes()[key].getFeature())
|
||||
}
|
||||
const vectorLayer = new VectorLayer<VectorSource>({
|
||||
|
@ -63,6 +63,7 @@ export default class NodeView extends AbstractTopBarInterface {
|
||||
+ (this.node.isNear()
|
||||
? 'Estas cerca y puedes interactuar con este sitio.'
|
||||
: 'Estás demasiado lejos para hacer nada aquí.');
|
||||
this.populateTeamData();
|
||||
if (this.node.isNear()) {
|
||||
await this.runIfNear();
|
||||
}
|
||||
@ -70,22 +71,87 @@ export default class NodeView extends AbstractTopBarInterface {
|
||||
mainNode.classList.remove('conquer-display-none')
|
||||
}
|
||||
|
||||
private async populateTeamData() {
|
||||
const element = document.createElement('p');
|
||||
const team = await this.node.getTeam();
|
||||
(() => {
|
||||
if (team === null) {
|
||||
element.innerText = 'El nodo no pertenece a ningún equipo todavía.';
|
||||
return;
|
||||
}
|
||||
const spanText = document.createElement('span');
|
||||
spanText.innerText = 'Equipo: ';
|
||||
element.append(spanText);
|
||||
const spanCircle = document.createElement('span');
|
||||
spanCircle.classList.add('conquer-team-circle');
|
||||
spanCircle.style.backgroundColor = team.getColor();
|
||||
element.append(spanCircle);
|
||||
const spanTeamName = document.createElement('span');
|
||||
spanTeamName.style.color = team.getColor();
|
||||
spanTeamName.innerText = ' ' + team.getName();
|
||||
element.append(spanTeamName);
|
||||
})();
|
||||
this.getView().append(element);
|
||||
}
|
||||
|
||||
private async runIfNear(): Promise<void> {
|
||||
const team = await this.user.getTeam();
|
||||
if (team === null) {
|
||||
const userTeam = await this.user.getTeam();
|
||||
const nodeTeam = await this.node.getTeam();
|
||||
if (userTeam === null) {
|
||||
const paragraphNoTeam = document.createElement('p');
|
||||
paragraphNoTeam.innerText = 'Parece que no has seleccionado equipo aun,'
|
||||
+ ' pulsa el botón de seleccionar equipo para comenzar tu aventura,'
|
||||
+ ' si quieres cambiar de equipo en el futuro puedes hacerlo sin problemas.';
|
||||
this.getView().append(paragraphNoTeam);
|
||||
}
|
||||
|
||||
const selectTeamButton = document.createElement('button');
|
||||
selectTeamButton.innerText = 'Seleccionar equipo';
|
||||
selectTeamButton.addEventListener('click', () => {
|
||||
this.runCallbacks('open-select-team');
|
||||
this.runCallbacks('close');
|
||||
});
|
||||
|
||||
this.getView().append(selectTeamButton);
|
||||
if (await this.isOpposingNode()) {
|
||||
const conquerForTeamButton = document.createElement('button');
|
||||
conquerForTeamButton.innerText = 'Conquistar';
|
||||
conquerForTeamButton.addEventListener('click', () => {
|
||||
this.conquerThisNodeForTeam();
|
||||
});
|
||||
this.getView().append(conquerForTeamButton);
|
||||
}
|
||||
}
|
||||
|
||||
private async conquerThisNodeForTeam() {
|
||||
const urlNode = new URL('/conquer/node/' + this.node.getUUID() + '/try-conquer',
|
||||
window.location.protocol + '//'
|
||||
+ window.location.hostname + ':'
|
||||
+ window.location.port)
|
||||
const response = await fetch(urlNode, {
|
||||
method: 'POST',
|
||||
});
|
||||
this.runCallbacks('update-nodes');
|
||||
this.runCallbacks('close');
|
||||
}
|
||||
|
||||
private async isOpposingNode(): Promise<boolean> {
|
||||
const userTeam = await this.user.getTeam();
|
||||
const nodeTeam = await this.node.getTeam();
|
||||
if (userTeam === null) {
|
||||
return false;
|
||||
}
|
||||
if (nodeTeam === null) {
|
||||
return true;
|
||||
}
|
||||
if (nodeTeam.getUUID() !== userTeam.getUUID()) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private async isNodeFree(): Promise<boolean> {
|
||||
return await this.node.getTeam() === null;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ import InterfaceManager from '@burguillosinfo/conquer/interface-manager'
|
||||
import NodeView from '@burguillosinfo/conquer/interface/node-view'
|
||||
import JsonSerializer from '@burguillosinfo/conquer/serializer';
|
||||
import SelectTeamUI from '@burguillosinfo/conquer/interface/select-team';
|
||||
import ConquerTeam from '@burguillosinfo/conquer/team';
|
||||
|
||||
@JsonObject()
|
||||
export default class MapNode {
|
||||
@ -24,9 +25,18 @@ export default class MapNode {
|
||||
@JsonProperty() private description: string,
|
||||
@JsonProperty() private kind: string,
|
||||
@JsonProperty() private is_near: boolean,
|
||||
@JsonProperty() private team: string,
|
||||
) {
|
||||
}
|
||||
|
||||
public async getTeam(): Promise<ConquerTeam | null> {
|
||||
if (this.team === null) {
|
||||
return null;
|
||||
}
|
||||
return ConquerTeam.getTeam(this.team);
|
||||
}
|
||||
|
||||
|
||||
public async fetch(): Promise<MapNode> {
|
||||
const urlNode = new URL('/conquer/node/' + this.uuid, window.location.protocol + '//' + window.location.hostname + ':' + window.location.port)
|
||||
const response = await fetch(urlNode);
|
||||
@ -125,11 +135,16 @@ export default class MapNode {
|
||||
return this.feature;
|
||||
}
|
||||
|
||||
public getStyle(): Style {
|
||||
public async getStyle(): Promise<Style> {
|
||||
const team = await this.getTeam();
|
||||
let color = 'white';
|
||||
if (team !== null) {
|
||||
color = team.getColor();
|
||||
}
|
||||
return new Style({
|
||||
image: new CircleStyle({
|
||||
radius: 14,
|
||||
fill: new Fill({color: 'white'}),
|
||||
fill: new Fill({color: color}),
|
||||
stroke: new Stroke({
|
||||
color: 'gray',
|
||||
width: 2,
|
||||
|
@ -101,6 +101,7 @@ sub startup ($self) {
|
||||
$r->put('/conquer/node')->to('ConquerNode#create');
|
||||
$r->get('/conquer/node/near')->to('ConquerNode#nearbyNodes');
|
||||
$r->get('/conquer/node/<uuid>')->to('ConquerNode#get');
|
||||
$r->post('/conquer/node/<uuid>/try-conquer')->to('ConquerNode#tryConquer');
|
||||
$r->get('/conquer/user')->to('UserConquer#get_self');
|
||||
$r->post('/conquer/user/login')->to('UserConquer#login');
|
||||
$r->get('/conquer/tile/<zoom>/<x>/<y>.png')->to('ConquerTile#tile');
|
||||
|
@ -32,6 +32,33 @@ sub get($self) {
|
||||
}
|
||||
return $self->render(json => $node->serialize());
|
||||
}
|
||||
|
||||
sub tryConquer($self) {
|
||||
my $user = $self->current_user;
|
||||
my $schema = BurguillosInfo::Schema->Schema->resultset('ConquerNode');
|
||||
if (!defined $user) {
|
||||
return $self->render(status => 401, json => {
|
||||
error => 'You must be logged to conquer a node.',
|
||||
});
|
||||
}
|
||||
if (!defined $user->team) {
|
||||
return $self->render(status => 400, json => {
|
||||
error => 'You must belong to a team to conquer a node.',
|
||||
});
|
||||
}
|
||||
my $uuid = $self->param('uuid');
|
||||
my ($node) = $schema->search({uuid => $uuid});
|
||||
if (!defined $node) {
|
||||
return $self->render(status => 404, json => {
|
||||
error => 'No existe ese nodo.',
|
||||
});
|
||||
}
|
||||
$node->team($user->team);
|
||||
$node->update;
|
||||
$self->render(json => {
|
||||
ok => $JSON::true,
|
||||
});
|
||||
}
|
||||
|
||||
sub create ($self) {
|
||||
my $user = $self->current_user;
|
||||
|
@ -37,29 +37,39 @@ __PACKAGE__->add_columns(
|
||||
data_type => 'geometry',
|
||||
is_nullable => 0,
|
||||
},
|
||||
team => {
|
||||
data_type => 'uuid',
|
||||
is_nullable => 1,
|
||||
},
|
||||
);
|
||||
|
||||
sub coordinate_2($self) {
|
||||
sub coordinate_2 ($self) {
|
||||
require BurguillosInfo::Schema;
|
||||
my $resultset = BurguillosInfo::Schema->Schema->resultset('ConquerNode');
|
||||
my ($new_self) = $resultset->search({uuid => $self->uuid}, {
|
||||
'+select' => {
|
||||
ST_Y => { ST_Centroid => 'geometry' },
|
||||
-as => 'coordinate_2',
|
||||
my ($new_self) = $resultset->search(
|
||||
{ uuid => $self->uuid },
|
||||
{
|
||||
'+select' => {
|
||||
ST_Y => { ST_Centroid => 'geometry' },
|
||||
-as => 'coordinate_2',
|
||||
}
|
||||
}
|
||||
});
|
||||
);
|
||||
return $new_self->get_column('coordinate_2');
|
||||
}
|
||||
|
||||
sub coordinate_1($self) {
|
||||
sub coordinate_1 ($self) {
|
||||
require BurguillosInfo::Schema;
|
||||
my $resultset = BurguillosInfo::Schema->Schema->resultset('ConquerNode');
|
||||
my ($new_self) = $resultset->search({uuid => $self->uuid}, {
|
||||
'+select' => {
|
||||
ST_X => { ST_Centroid => 'geometry' },
|
||||
-as => 'coordinate_1',
|
||||
my ($new_self) = $resultset->search(
|
||||
{ uuid => $self->uuid },
|
||||
{
|
||||
'+select' => {
|
||||
ST_X => { ST_Centroid => 'geometry' },
|
||||
-as => 'coordinate_1',
|
||||
}
|
||||
}
|
||||
});
|
||||
);
|
||||
return $new_self->get_column('coordinate_1');
|
||||
}
|
||||
|
||||
@ -74,6 +84,7 @@ sub serialize ( $self, $player = undef ) {
|
||||
coordinate_1 => $self->coordinate_1,
|
||||
coordinate_2 => $self->coordinate_2,
|
||||
is_near => $self->is_near($player),
|
||||
team => $self->team,
|
||||
};
|
||||
return $return;
|
||||
}
|
||||
@ -82,22 +93,29 @@ sub is_near ( $self, $player ) {
|
||||
if ( !defined $player ) {
|
||||
return $JSON::false;
|
||||
}
|
||||
|
||||
# Meters
|
||||
if ($self->get_distance_to_player($player) < 100) {
|
||||
if ( $self->get_distance_to_player($player) < 100 ) {
|
||||
return $JSON::true;
|
||||
}
|
||||
return $JSON::false;
|
||||
}
|
||||
|
||||
sub get_distance_to_player ($self, $player) {
|
||||
sub get_distance_to_player ( $self, $player ) {
|
||||
my $longitude_player = $player->last_coordinate_1;
|
||||
my $latitude_player = $player->last_coordinate_2;
|
||||
my $longitude_node = $self->coordinate_1;
|
||||
my $latitude_node = $self->coordinate_2;
|
||||
my $gis = GIS::Distance->new;
|
||||
my $latitude_player = $player->last_coordinate_2;
|
||||
my $longitude_node = $self->coordinate_1;
|
||||
my $latitude_node = $self->coordinate_2;
|
||||
my $gis = GIS::Distance->new;
|
||||
|
||||
# Setting distance to meters.
|
||||
my $distance = $gis->distance_metal( $latitude_node, $longitude_node, $latitude_player, $longitude_player) * 1000;
|
||||
my $distance = $gis->distance_metal(
|
||||
$latitude_node, $longitude_node,
|
||||
$latitude_player, $longitude_player
|
||||
) * 1000;
|
||||
}
|
||||
|
||||
__PACKAGE__->set_primary_key('uuid');
|
||||
__PACKAGE__->belongs_to( 'team_object',
|
||||
'BurguillosInfo::Schema::Result::ConquerTeam', 'team' );
|
||||
1;
|
||||
|
@ -39,6 +39,7 @@ __PACKAGE__->add_columns(
|
||||
|
||||
__PACKAGE__->set_primary_key('uuid');
|
||||
__PACKAGE__->has_many( players => 'BurguillosInfo::Schema::Result::ConquerUser', 'team');
|
||||
__PACKAGE__->has_many( nodes => 'BurguillosInfo::Schema::Result::ConquerNode', 'team');
|
||||
|
||||
sub serialize ($self) {
|
||||
$self = $self->get_from_storage();
|
||||
|
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user