## How is the code organized?

### Database

The most important file to talk with the database is `lib/LasTres/Schema.pm`
this file defines the database version in the following line:

```perl
our $VERSION = 10;
```

Every time you modify one of the files in `lib/LasTres/Schema/Result/` to
add a new field or change an existing field you are going to increment
this variable plus one and prepare a migration and upgrade your local
database.

The exact instructions to do this varies a lot depending of your setup,
you should check the relevant documentation in `CONTRIBUTING.md` or `DOCKER.md`
depending of what of those ways you choose.

To interface with the database in a method or subroutine you retrieve a
ResultSet from the Schema, this is done in this way:

```perl
my $teams_resultset = LasTres::Schema->Schema->resultset('Team');
my @teams = $teams_resultset->search(uuid = $uuid);
```

I suggest you to take a look to the relevant code to see how common operations
with the database are done.


### Modifying web endpoints.

The complete list of available endpoints is defined in `lib/LasTres.pm`.

Those look like this:

```perl
$r->post('/player/register')->to('Player#register');
```

You can search the dispatch classes (Player in this example) under `lib/LasTres/Controller/`, the files ending in `.pm` children of this directory are the recognized dispatch classes.

### Websocket how-to.

Only a web endpoint listens to server websockets, but you can do many different
things with websockets, that is achieved by packets.

When developing LasTres we wanted to avoid having to reinvent the wheel for every
input or output packet that is why we made interfaces that define what
a class defining a packet should look like.

This interfaces are `lib/LasTres/Controller/Websocket/InputPacket.pm` and `lib/LasTres/Controller/Websocket/OutputPacket.pm`.

A class that pretends to be a Input or Output packet must comply with three basic rules:

* The first one is that it must implement the pertinent interface, for example:

`with 'LasTres::Controller::Websocket::InputPacket';`

Of course to comply with this rule you will have to implement every method in `requires`.

* The second one is that a input packet class should be located into `lib/LasTres/Controller/Websocket/InputPacket/` and a output packet into `lib/LasTres/Controller/Websocket/OutputPacket/`.

* The third one is that the identifier of your packet must be unique among the packets of its kind input/output.

### Pubsub

Something happened in a player websocket input packet or in the event loop and now every player in their team or location must be notified or their on screen information should be updated.

What can we do? Easy, thanks to Redis pubsub implementation we can execute an action into the event loop that contains the player websocket and we can send them the information required.

Currently the code handling Redis pubsub packets is defined into `lib/LasTres/Controller/Websocket/InputPacket/Init.pm`, this is not ideal because Redis amerit its own
packet structure, but it is technical debt and won't be addressed in this stage of development until it becomes a problem.

To publish a redis event you can do it like this:

```perl
$redis->publish( $redis->pj_subscription($pj),
    to_json( { command => 'update-team-sprites' } ) );
```

But please do not do it outside `lib/LasTres/Schema/Result/PJ.pm`, this code is
difficult to copy-paste and memorize when you can only write once for the PJ and
then simply call something similar to:

```perl
$pj->update_team_sprites;
```

And call it a day.

### Planets, SuperArea, Area and Location.

To create or edit new maps you should do it in this way.

Check the files `lib/LasTres/Planet.pm`, `lib/LasTres/SuperArea.pm`, `lib/LasTres/Area.pm`, `lib/LasTres/Location.pm`.

These are the interfaces that you should implement.

Where? Well the answer is that these interfaces should be represented in a tree in this way:

```
lib/LasTres/Planet/MyPlanet.pm
lib/LasTres/Planet/MyPlanet/MySuperArea.pm
lib/LasTres/Planet/MyPlanet/MySuperArea/MyArea.pm
lib/LasTres/Planet/MyPlanet/MySuperArea/MyArea/MyLocation.pm
```

You must use Module::Pluggable to search for the children when implementing the
interfaces, you should look into a existent structure of the kind of the
one you are trying to implement.

### What does this library do?

You can ask if you find a library outside or inside LasTres that is not documented or
you simply do not understand, if the library is not prefixed by `LasTres::` it is
really probable that good documentation exists in metacpan for your doubts so take
a look there if you can.

### Comments in extendable and implementable code.

If you look into a class or interface that you are supposed to extend or implement
you should get some comments about how and when you should override or implement methods.

These comments have no really any warrant and you should check what implementors
do anyway, if you find incomplete or outdated documentation would be nice that
you fix it for the following passing there.


### Tests.

Tests? What Tests? I wanted to get something functional fast and I did not care
about tests, I hope that this technical debt gets resolved at some point in
the future.

The fixer could be you!! Writting unit tests is a great way to understand more
about the codebase and become a valuable contributor.

Testing is not only boring by itself but also makes your future life more boring
with less bug to take care about. Isn't it great?
