Desarrollo

From DDraceNetwork
Revision as of 03:23, 3 March 2023 by Yek (talk | contribs) (Created page with "Primero que todo, DDNet está codificado usando el lenguaje de programación C++, necesitarás estar bastante familiarizado con él, pero también puedes saber lo básico y aprender más con él.")

Este artículo pretende introducirte en el desarollo de DDNet, Al tratarse de un juego de código abierto, depende de las personas que contribuyen a él en su tiempo libre.


Tu entorno de desarrollo

Es extremadamente recomendable configurar algún entorno de Linux para empezar a programar en DDNet por las siguientes razones (a partir de ahora):

  • La mayoría de los colaboradores de DDNet utilizan Linux para contribuir.
  • Gestión de paquetes más simple, puedes instalar fácilmente todas las librerías necesarias y empezar a contribuir.
  • Este artículo aún no tiene versión para Windows y se centra en Linux.

Primero que todo, DDNet está codificado usando el lenguaje de programación C++, necesitarás estar bastante familiarizado con él, pero también puedes saber lo básico y aprender más con él.

Some useful resources to learn C++:

The source code of DDNet is managed using Git, a version control system, an essential tool to collaborate with multiple developers.

If you don't have git yet in your Linux distribution, make sure to install it, for example in most debian/ubuntu based distributions: sudo apt install git.


Getting the source code

The source code is located on Github, you can get the source code by cloning without the need of an account, but if you want to ever put your changes to the official source code you will need one.

If you are not familiar with git/github you can learn the basics here: Hello World - Github


Installing the dependencies

If you are on Linux, you can install all the needed dependencies by reading the README on the DDNet github page: https://github.com/ddnet/ddnet#dependencies-on-linux--macos

For Arch Linux:

sudo pacman -S --needed base-devel cmake curl freetype2 git glew gmock libnotify opusfile python sdl2 sqlite wavpack


Compiling DDNet

We use CMake to control the compilation process, if you have all the dependencies installed, it's as easy as following these commands (make sure you are on the DDNet folder):

mkdir build
cd build
cmake ..
make -j$(nproc)


General information

Here are some general bits of information:

  • Currently, the source code is compiled with the C++17 standard, but you will see that many parts of the code are more C-like since only mostly new code uses C++17 stuff.
  • std::string is rarely used, char arrays plus using system.h methods for handling them are the norm.
  • Most I/O code, formatting and printing is done using system.h provided methods.


The source code layout

Now that you can build DDNet you can begin editing it.


The src/base directory

Since DDNet is a cross-platform game, an abstraction layer over that is needed to make development easier, this directory contains many useful functions to handle that.


The src/engine directory

Here lies the game engine, it handles most stuff that is not gameplay related, such as graphics, sound, network, etc.


The src/game directory

All gameplay related code is here, separated into client and server.


Server side

This game uses its own Entity Component System, the main class to which all other entities derive from is CEntity located in src/game/server/entity.h.

These entities are managed by the game world located here src/game/server/gameworld.h

Some important entities are:

  • CCharacter: Represents a tee that is alive, it is instantiated when a tee spawns and deleted when it dies. For information about the player kept between deaths, see CPlayer.


Client side

The client side is made up of components, these are classes that inherit CComponent: These components can implement the virtual methods such as OnInit, OnMessage, etc. to provide their functionality.


Networking

The network protocol is mostly generated by python scripts that output C++ code, for example, datasrc/network.py defines all network packets.


Code conventions

The ongoing discussion on code conventions is located here: ddnet#2945

Currently, the following applies:


Indentation style

Allman style is used.

This style puts the brace associated with a control statement on the next line, indented to the same level as the control statement. Statements within the braces are indented to the next level.

while(x == y)
{
    Something();
    SomethingElse();
}
</div>

<div lang="en" dir="ltr" class="mw-content-ltr">
Finalthing();


Classes and Structs

Must be prefixed by C (for legacy reasons this is ignored for structs in some places, such as in graphics code) or I for interfaces.

Example:

class CCharacter : public CEntity
{
    // ...
}


Enums and constants

Should be screaming snake case, for example: MAX_PLAYERS

enum
{
	FAKETUNE_FREEZE = 1,
	FAKETUNE_SOLO = 2,
	FAKETUNE_NOJUMP = 4,
	FAKETUNE_NOCOLL = 8,
	FAKETUNE_NOHOOK = 16,
	FAKETUNE_JETPACK = 32,
	FAKETUNE_NOHAMMER = 64,
};


Variable naming

  • The names of variables contain 3 parts: qualifier, prefix and name.
  • Variable names should start with uppercase unless they are 1 char long without any prefix or qualifier, for example: i, x, y.
  • Variables can have more than 1 qualifier (or zero) and more than 1 prefix (or zero).

These are laid out like this: [qualifiers]_[prefixes][Name]


Qualifiers

  • m for member variables: m_MyVariable.
  • s for static variables: s_MyStaticVariable.
  • g for global variables with external linkage: gs_MyGlobalStaticVar.


Prefixes

  • p for pointers: pMyPointer, m_pCharacter, ppMyPointerToPointer.
  • a for arrays: aMyArray, aBuf.
  • fn for functions: pfnMyCallback, m_papfnMyPointerToArrayOfCallbacks.


Common snippets

Here is a list of code that you may frequently see across the codebase:


Formatting text

char aBuf[128];
str_format(aBuf, sizeof(aBuf), "number: %d", 2);


Iterating over all players

for(int i = 0; i < MAX_CLIENTS; i++)
{
    // Server-side
    CPlayer *pPlayer = GameServer()->m_apPlayers[i];
}


Printing to the game console

Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "wikiprint", "Hello from the ddnet wiki!");


Debug printing

int i = 2;
dbg_msg("wikiprint", "Hello from the ddnet wiki: %d", i);


External resources