LasTres/GUIDE_TO_THE_CODE.md

5.4 KiB

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:

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:

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:

$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:

$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:

$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?