目录

Keira3 Internals

This is a collection of notes aiming to explain the internals of Keira3 for development purposes.

If you just want to use Keira3, you don't need any of the following. If you want to modify Keira3, for example to improve it or to add new features, you may find this page useful.

Main technologies

Keira3 is built upon the following open source web technologies:

Testing

We use test automation in Keira3 in our development cycle. For every PR/commit, our CI automatically runs a lot of automated tests.

More specifically, we have:

Why test automation?

Because every time you modify your app, you never know if you are breaking any existing functionality unless you manually test everything again and again.

When you have automated tests in place, you are still not 100% sure about not breaking existing stuff, but at least they can give you some assurance.

Files structure

Relevant directories:

Architecture design and fundamentals

Keira3 code is structured using OOP with techniques like inheritance and generic types to maximise code reuse.

Inside the directory src/app/shared/abstract there is a collection of abstract classes that are meant to be extended by the concrete Angular Components and Services which will implement the Keira3 features.

If you are not familiar with the terminology used so far, please check the above hyperlinks before proceeding.

Keira3 is **modular**, you can see it as a collection of features and shared utilities that are organised into Angular Modules.

Keira3 terminology and conventions

Typically, Keira3 features are caraterised by the following elements.

Table types

All the definitions of the AzerothCore DB tables are defined in Keira3 inside src/app/shared/types.

If you want to create a new editor, you have to first create its definition there.

The Main Entity

For example Creature is a main entity. Whether you want to modify a vendor (npc_vendor) or a loot of a creature (creature_loot_template), you still have to select (or create) a Creature.

There is always a table (and so also an Editor) for the Main Entity. For creatures it's creature_template.

You can't have a vendor, loot, etc… without having a creature first. In other words, you can't have an npc_vendor row without linking it to an existing entry of creature_template.

Another example could be: you can't have a row in quest_template_addon without linking it to an existing row of quest_template. Because quest_template is the Main Entity of the Quest editors.

Editor

An Editor is typically linked to a table. For example, the CreatureTrainer editor allows you to edit the npc_trainer table.

There are 2 main types of Editors in Keira3:

Single-row editors

They are the editors of tables containing ONE row for each entity.

For example, the table creature_template_addon can have only ONE row for each creature. You can never have 2 rows pointing to the same creature in this table.

Every row is uniquely identified by a primary key, that is the ID of the selected entity. Typically in the DB they are called id, ID, entry, Entry, etc… yes, they are completely inconsistent, but that's what we inherited from MaNGOS/TrinityCore. In Keira3 we call it just entityIdField.

Multi-row editors

They are the editors containing MULTIPLE rows for each entity.

For example, the table npc_vendor can have multiple rows that belongs to the same Creature. Every row of npc_vendor represents a specific Item that is sold by a specific Creature. And a Creature can sell 0, 1 or many items. Then every Creature can have 0, 1 or many rows in the npc_vendor table. Makes sense right?

Every row has 2 primary keys, typically (but not always) called id and guid. In Keira3 we always call them entityIdField and entitySecondIdField. The entityIdField is the ID of the selected entity.

Back to the example of npc_vendor:

Editor's Component and Service

Every Editor in Keira3 has its own Component and Service counterparts, where:

In order to maximise code reuse, the following abstract classes have been created:

Handler

Handlers are services responsible for holding statuses such as:

Group of editors that refer to the same main entity should share one Handler. For example, all Creature Editors refer to the CreatureHandlerService, all Quest Editors refer to the QuestHandlerService, and so on…

All Handlers classes extend the HandlerService abstract class.

Selectors

There are several kinds of selectors which allow the user to easily select a value for a given field.

Selectors are typically available to the user by clicking on the button with three dots:

image

There are three main types of selectors, listed below.

SingleValueSelectorBtnComponent

The SingleValueSelectorBtnComponent is a reusable component which can be used to allow the user to select a single value from a list of values, for a given field.

Let's check for example the exp field of creature_template, allowing to specify ONE value:

0 - Classic
1 - TBC
2 - WOTLK

All you have to do to implement such selector is first definying the list values by creating an array of Option:

image

All the options are located in src/app/shared/constants/options so you just need to create a new file like the above.

You then need to import the array of options, in this case EXPANSIONS, in the .ts file of your component and declare it as PUBLIC READONLY in order to make it available for the component's template:

image

Now you can use it in the .html template of the component by adding the keira-single-value-selector-btn html element and passing the following properties:

image

This is the result:

<img src=“https://user-images.githubusercontent.com/75517/118694803-c1794280-b80c-11eb-9099-00758983ca2e.png” width=300>

<img src=“https://user-images.githubusercontent.com/75517/118694841-cf2ec800-b80c-11eb-8719-b770a7fd0c98.png” width=500>

FlagsSelectorBtnComponent

The FlagsSelectorBtnComponent is another very useful reusable component which allows the user to compose a value from a set of flags (bitmask), for a given field. If terms like bits, bitmask, flags, etc.. sounds weird to you, we recommend to read this page to fully understand how flag values work.

Let's see, for example, how the field dynamicflags of creature_template is implemented.

First you need to define the the list of (bit) values by creating an array of Flag:

image

All the flag values are located in src/app/shared/constants/flags so you can create a new file there, for example dynamic-flags.ts in our case.

Basically you need to define what's the meaning of every single bit. Don't forge that bits typically start from zero.

Then you need to import the DYNAMIC_FLAGS array in the component's .ts file and make it available for its .html template by declaring it PUBLIC READONLY:

image

Now you just need to use it in the html by adding the keira-flags-selector-btn component there:

image

The attributes for this component are:

This is the result:

<img src=“https://user-images.githubusercontent.com/75517/118697264-685ede00-b80f-11eb-9609-6b4af903bcdc.png” width=300>

image

Other selectors

There are other selectors that allow the user to select values by doing a search either in the DB or in the DBC contained in the sqlite integrated in Keira3.

You can find their implementations in src/app/shared/modules/selectors as well as examples of usage around the app.

image

Example: the item-selector.

image

You can use it whenever an Item ID is needed:

image