1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-11-23 22:37:55 +02:00

Added markdownlint to Github CI

- Markdown will now be validated as part of Github CI
- Applied auto-fix to most common issues (mostly whitespace related)
- Fixed manually some of more complex cases

Some valid markdownlint rules are currently disabled, to avoid failing
CI, can be enabled in future
This commit is contained in:
Ivan Savenko
2024-11-30 20:20:15 +00:00
parent d4b2ec5b0b
commit 74a4a10f48
78 changed files with 2192 additions and 1360 deletions

View File

@@ -6,12 +6,13 @@ There are two types of AI: adventure and battle.
**Battle AIs** are responsible for fighting, i.e. moving stacks on the battlefield
We have 3 battle AIs so far:
* BattleAI - strongest
* StupidAI - for neutrals, should be simple so that experienced players can abuse it
* Empty AI - should do nothing at all. If needed another battle AI can be introduced.
Each battle AI consist of a few classes, but the main class, kind of entry point usually has the same name as the package itself. In BattleAI it is the BattleAI class. It implements some battle specific interface, do not remember. Main method there is activeStack(battle::Unit* stack). It is invoked by the system when it's time to move your stack. The thing you use to interact with the game and receive the gamestate is usually referenced in the code as cb. CPlayerSpecificCallback it should be. It has a lot of methods and can do anything. For instance it has battleGetUnitsIf(), which returns all units on the battlefield matching some lambda condition.
Each side in a battle is represented by an CArmedInstance object. CHeroInstance and CGDwelling, CGMonster and more are subclasses of CArmedInstance. CArmedInstance contains a set of stacks. When the battle starts, these stacks are converted to battle stacks. Usually Battle AIs reference them using the interface battle::Unit *.
Each battle AI consist of a few classes, but the main class, kind of entry point usually has the same name as the package itself. In BattleAI it is the BattleAI class. It implements some battle specific interface, do not remember. Main method there is activeStack(battle::Unit*stack). It is invoked by the system when it's time to move your stack. The thing you use to interact with the game and receive the gamestate is usually referenced in the code as cb. CPlayerSpecificCallback it should be. It has a lot of methods and can do anything. For instance it has battleGetUnitsIf(), which returns all units on the battlefield matching some lambda condition.
Each side in a battle is represented by an CArmedInstance object. CHeroInstance and CGDwelling, CGMonster and more are subclasses of CArmedInstance. CArmedInstance contains a set of stacks. When the battle starts, these stacks are converted to battle stacks. Usually Battle AIs reference them using the interface battle::Unit*.
Units have bonuses. Nearly everything aspect of a unit is configured in the form of bonuses. Attack, defense, health, retaliation, shooter or not, initial count of shots and so on.
When you call unit->getAttack() it summarizes all these bonuses and returns the resulting value.
@@ -38,17 +39,20 @@ BattleAI itself handles all the rest and issues actual commands
Adventure AI responsible for moving heroes on map, gathering things, developing town. Main idea is to gather all possible tasks on map, prioritize them and select the best one for each heroes. Initially was a fork of VCAI
### Parts
Gateway - a callback for server used to invoke AI actions when server thinks it is time to do something. Through this callback AI is informed about various events like hero level up, tile revialed, blocking dialogs and so on. In order to do this Gaateway implements specific interface. The interface is exactly the same for human and AI
Another important actor for server interaction is CCallback * cb. This one is used to retrieve gamestate information and ask server to do things like hero moving, spell casting and so on. Each AI has own instance of Gateway and it is a root object which holds all AI state. Gateway has an event method yourTurn which invokes makeTurn in another thread. The last passes control to Nullkiller engine.
Nullkiller engine - place where actual AI logic is organized. It contains a main loop for gathering and prioritizing things. Its algorithm:
* reset AI state, it avoids keeping some memory about the game in general to reduce amount of things serialized into savefile state. The only serialized things are in nullkiller->memory. This helps reducing save incompatibility. It should be mostly enough for AI to analyze data avaialble in CCallback
* main loop, loop iteration is called a pass
** update AI state, some state is lazy and updates once per day to avoid performance hit, some state is recalculated each loop iteration. At this stage analysers and pathfidner work
**update AI state, some state is lazy and updates once per day to avoid performance hit, some state is recalculated each loop iteration. At this stage analysers and pathfidner work
** gathering goals, prioritizing and decomposing them
** execute selected best goals
Analyzer - a module gathering data from CCallback *. Its goal to make some statistics and avoid making any significant decissions.
* HeroAnalyser - decides upong which hero suits better to be main (army carrier and fighter) and which is better to be a scout (gathering unguarded resources, exploring)
* BuildAnalyzer - prepares information on what we can build in our towns, and what resources we need to do this
* DangerHitMapAnalyser - checks if enemy hero can rich each tile, how fast and what is their army strangth
@@ -61,9 +65,11 @@ Analyzer - a module gathering data from CCallback *. Its goal to make some stati
* PriorityEvaluator - gathers information on task rewards, evaluates their priority using Fuzzy Light library (fuzzy logic)
### Goals
Units of activity in AI. Can be AbstractGoal, Task, Marker and Behavior
Task - simple thing which can be done right away in order to gain some reward. Or a composition of simple things in case if more than one action is needed to gain the reward.
* AdventureSpellCast - town portal, water walk, air walk, summon boat
* BuildBoat - builds a boat in a specific shipyard
* BuildThis - builds a building in a specified town
@@ -78,6 +84,7 @@ Task - simple thing which can be done right away in order to gain some reward. O
* StayAtTown - stay at town for the rest of the day (to regain mana)
Behavior - a core game activity
* CaptureObjectsBehavior - generally it is about visiting map objects which give reward. It can capture any object, even those which are behind monsters and so on. But due to performance considerations it is not allowed to handle monsters and quests now.
* ClusterBehavior - uses information of ObjectClusterizer to unblock objects hidden behind various blockers. It kills guards, completes quests, captures garrisons.
* BuildingBehavior - develops our towns
@@ -89,6 +96,7 @@ Behavior - a core game activity
* DefenceBehavior - defend towns by eliminating treatening heroes or hiding in town garrison
AbstractGoal - some goals can not be completed because it is not clear how to do this. They express desire to do something, not exact plan. DeepDecomposer is used to refine such goals until they are turned into such plan or discarded. Some examples:
* CaptureObject - you need to visit some object (flag a shipyard for instance) but do not know how
* CompleteQuest - you need to bypass bordergate or borderguard or questguard but do not know how
AbstractGoal usually comes in form of composition with some elementar task blocked by abstract objective. For instance CaptureObject(Shipyard), ExecuteHeroChain(visit x, build boat, visit enemy town). When such composition is decomposed it can turn into either a pair of herochains or into another abstract composition if path to shipyard is also blocked with something.

View File

@@ -6,8 +6,8 @@ The bonus system of VCMI is a set of mechanisms that make handling of different
Each bonus originates from some node in the bonus system, and may have propagator and limiter objects attached to it. Bonuses are shared around as follows:
1. Bonuses with propagator are propagated to "matching" descendants in the red DAG - which descendants match is determined by the propagator. Bonuses without a propagator will not be propagated.
2. Bonuses without limiters are inherited by all descendants in the black DAG. If limiters are present, they can restrict inheritance to certain nodes.
1. Bonuses with propagator are propagated to "matching" descendants in the red DAG - which descendants match is determined by the propagator. Bonuses without a propagator will not be propagated.
2. Bonuses without limiters are inherited by all descendants in the black DAG. If limiters are present, they can restrict inheritance to certain nodes.
Inheritance is the default means of sharing bonuses. A typical example is an artefact granting a bonus to attack/defense stat, which is inherited by the hero wearing it, and then by creatures in the hero's army.
A common limiter is by creature - e.g. the hero Eric has a specialty that grants bonuses to attack, defense and speed, but only to griffins.
@@ -15,9 +15,9 @@ Propagation is used when bonuses need to be shared in a different direction than
### Technical Details
- Propagation is done by copying bonuses to the target nodes. This happens when bonuses are added.
- Inheritance is done on-the-fly when needed, by traversing the black DAG. Results are cached to improve performance.
- Whenever a node changes (e.g. bonus added), a global counter gets increased which is used to check whether cached results are still current.
- Propagation is done by copying bonuses to the target nodes. This happens when bonuses are added.
- Inheritance is done on-the-fly when needed, by traversing the black DAG. Results are cached to improve performance.
- Whenever a node changes (e.g. bonus added), a global counter gets increased which is used to check whether cached results are still current.
## Operations on the graph
@@ -26,6 +26,7 @@ There are two basic types of operations that can be performed on the graph:
### Adding a new node
When node is attached to a new black parent (the only possibility - adding parent is the same as adding a child to it), the propagation system is triggered and works as follows:
- For the attached node and its all red ancestors
- For every bonus
- Call propagator giving the new descendant - then attach appropriately bonuses to the red descendant of attached node (or the node itself).
@@ -54,7 +55,7 @@ Updaters are objects attached to bonuses. They can modify a bonus (typically by
The following example shows an artifact providing a bonus based on the level of the hero that wears it:
```javascript
```jsonc
"core:greaterGnollsFlail":
{
"text" : { "description" : "This mighty flail increases the attack of all gnolls under the hero's command by twice the hero's level." },

View File

@@ -1,26 +1,26 @@
# Building Android
The following instructions apply to **v1.2 and later**. For earlier versions the best documentation is https://github.com/vcmi/vcmi-android/blob/master/building.txt (and reading scripts in that repo), however very limited to no support will be provided from our side if you wish to go down that rabbit hole.
The following instructions apply to **v1.2 and later**. For earlier versions the best documentation is <https://github.com/vcmi/vcmi-android/blob/master/building.txt> (and reading scripts in that repo), however very limited to no support will be provided from our side if you wish to go down that rabbit hole.
*Note*: building has been tested only on Linux and macOS. It may or may not work on Windows out of the box.
## Requirements
1. CMake 3.20+: download from your package manager or from https://cmake.org/download/
1. CMake 3.20+: download from your package manager or from <https://cmake.org/download/>
2. JDK 11, not necessarily from Oracle
3. Android command line tools or Android Studio for your OS: https://developer.android.com/studio/
3. Android command line tools or Android Studio for your OS: <https://developer.android.com/studio/>
4. Android NDK version **r25c (25.2.9519653)**, there're multiple ways to obtain it:
- install with Android Studio
- install with `sdkmanager` command line tool
- download from https://developer.android.com/ndk/downloads
- download from <https://developer.android.com/ndk/downloads>
- download with Conan, see [#NDK and Conan](#ndk-and-conan)
5. Optional:
- Ninja: download from your package manager or from https://github.com/ninja-build/ninja/releases
- Ccache: download from your package manager or from https://github.com/ccache/ccache/releases
- Ninja: download from your package manager or from <https://github.com/ninja-build/ninja/releases>
- Ccache: download from your package manager or from <https://github.com/ccache/ccache/releases>
## Obtaining source code
Clone https://github.com/vcmi/vcmi with submodules. Example for command line:
Clone <https://github.com/vcmi/vcmi> with submodules. Example for command line:
```
git clone --recurse-submodules https://github.com/vcmi/vcmi.git
@@ -31,6 +31,7 @@ git clone --recurse-submodules https://github.com/vcmi/vcmi.git
We use Conan package manager to build/consume dependencies, find detailed usage instructions [here](./Conan.md). Note that the link points to the state of the current branch, for the latest release check the same document in the [master branch](https://github.com/vcmi/vcmi/blob/master/docs/developers/Сonan.md).
On the step where you need to replace **PROFILE**, choose:
- `android-32` to build for 32-bit architecture (armeabi-v7a)
- `android-64` to build for 64-bit architecture (aarch64-v8a)
@@ -38,7 +39,7 @@ On the step where you need to replace **PROFILE**, choose:
Conan must be aware of the NDK location when you execute `conan install`. There're multiple ways to achieve that as written in the [Conan docs](https://docs.conan.io/1/integrations/cross_platform/android.html):
- the easiest is to download NDK from Conan (option 1 in the docs), then all the magic happens automatically. On the step where you need to replace **PROFILE**, choose _android-**X**-ndk_ where _**X**_ is either `32` or `64`.
- the easiest is to download NDK from Conan (option 1 in the docs), then all the magic happens automatically. On the step where you need to replace **PROFILE**, choose *android-**X**-ndk* where ***X*** is either `32` or `64`.
- to use an already installed NDK, you can simply pass it on the command line to `conan install`: (note that this will work only when consuming the pre-built binaries)
```

View File

@@ -11,15 +11,15 @@ Older distributions and compilers might work, but they aren't tested by Github C
To compile, the following packages (and their development counterparts) are needed to build:
- CMake
- SDL2 with devel packages: mixer, image, ttf
- zlib and zlib-devel
- Boost C++ libraries v1.48+: program-options, filesystem, system, thread, locale
- Recommended, if you want to build launcher or map editor: Qt 5, widget and network modules
- Recommended, FFmpeg libraries, if you want to watch in-game videos: libavformat and libswscale. Their name could be libavformat-devel and libswscale-devel, or ffmpeg-libs-devel or similar names.
- Optional:
- if you want to build scripting modules: LuaJIT
- to speed up recompilation: Ccache
- CMake
- SDL2 with devel packages: mixer, image, ttf
- zlib and zlib-devel
- Boost C++ libraries v1.48+: program-options, filesystem, system, thread, locale
- Recommended, if you want to build launcher or map editor: Qt 5, widget and network modules
- Recommended, FFmpeg libraries, if you want to watch in-game videos: libavformat and libswscale. Their name could be libavformat-devel and libswscale-devel, or ffmpeg-libs-devel or similar names.
- Optional:
- if you want to build scripting modules: LuaJIT
- to speed up recompilation: Ccache
### On Debian-based systems (e.g. Ubuntu)
@@ -41,7 +41,7 @@ NOTE: `fuzzylite-devel` package is no longer available in recent version of Fedo
On Arch-based distributions, there is a development package available for VCMI on the AUR.
It can be found at https://aur.archlinux.org/packages/vcmi-git/
It can be found at <https://aur.archlinux.org/packages/vcmi-git/>
Information about building packages from the Arch User Repository (AUR) can be found at the Arch wiki.
@@ -109,9 +109,9 @@ This will generate `vcmiclient`, `vcmiserver`, `vcmilauncher` as well as .so lib
### RPM package
The first step is to prepare a RPM build environment. On Fedora systems you can follow this guide: http://fedoraproject.org/wiki/How_to_create_an_RPM_package#SPEC_file_overview
The first step is to prepare a RPM build environment. On Fedora systems you can follow this guide: <http://fedoraproject.org/wiki/How_to_create_an_RPM_package#SPEC_file_overview>
0. Enable RPMFusion free repo to access to ffmpeg libs:
1. Enable RPMFusion free repo to access to ffmpeg libs:
```sh
sudo dnf install https://download1.rpmfusion.org/free/fedora/rpmfusion-free-release-$(rpm -E %fedora).noarch.rpm
@@ -120,33 +120,34 @@ sudo dnf install https://download1.rpmfusion.org/free/fedora/rpmfusion-free-rele
> [!NOTE]
> The stock ffmpeg from Fedora repo is no good as it lacks a lots of codecs
1. Perform a git clone from a tagged branch for the right Fedora version from https://github.com/rpmfusion/vcmi; for example for Fedora 38: <pre>git clone -b f38 --single-branch https://github.com/rpmfusion/vcmi.git</pre>
2. Perform a git clone from a tagged branch for the right Fedora version from <https://github.com/rpmfusion/vcmi>; for example for Fedora 38: <pre>git clone -b f38 --single-branch https://github.com/rpmfusion/vcmi.git</pre>
2. Copy all files to ~/rpmbuild/SPECS with command: <pre>cp vcmi/* ~/rpmbuild/SPECS</pre>
3. Copy all files to ~/rpmbuild/SPECS with command: <pre>cp vcmi/* ~/rpmbuild/SPECS</pre>
3. Fetch all sources by using spectool:
4. Fetch all sources by using spectool:
```sh
sudo dnf install rpmdevtools
spectool -g -R ~/rpmbuild/SPECS/vcmi.spec
```
4. Fetch all dependencies required to build the RPM:
5. Fetch all dependencies required to build the RPM:
```sh
sudo dnf install dnf-plugins-core
sudo dnf builddep ~/rpmbuild/SPECS/vcmi.spec
```
4. Go to ~/rpmbuild/SPECS and open terminal in this folder and type:
6. Go to ~/rpmbuild/SPECS and open terminal in this folder and type:
```sh
rpmbuild -ba ~/rpmbuild/SPECS/vcmi.spec
```
5. Generated RPM is in folder ~/rpmbuild/RPMS
7. Generated RPM is in folder ~/rpmbuild/RPMS
If you want to package the generated RPM above for different processor architectures and operating systems you can use the tool mock.
Moreover, it is necessary to install mock-rpmfusion_free due to the packages ffmpeg-devel and ffmpeg-libs which aren't available in the standard RPM repositories(at least for Fedora). Go to ~/rpmbuild/SRPMS in terminal and type:
Moreover, it is necessary to install mock-rpmfusion_free due to the packages ffmpeg-devel and ffmpeg-libs which aren't available in the standard RPM repositories(at least for Fedora). Go to ~/rpmbuild/SRPMS in terminal and type:
```sh
mock -r fedora-38-aarch64-rpmfusion_free path_to_source_RPM

View File

@@ -12,8 +12,8 @@ Windows builds can be made in more than one way and with more than one tool. Thi
- CMake [download link](https://cmake.org/download/). During install after accepting license agreement make sure to check "Add CMake to the system PATH for all users".
- To unpack pre-build Vcpkg: [7-zip](http://www.7-zip.org/download.html)
- Optional:
- To create installer: [NSIS](http://nsis.sourceforge.net/Main_Page)
- To speed up recompilation: [CCache](https://github.com/ccache/ccache/releases)
- To create installer: [NSIS](http://nsis.sourceforge.net/Main_Page)
- To speed up recompilation: [CCache](https://github.com/ccache/ccache/releases)
### Choose an installation directory
@@ -21,12 +21,14 @@ Create a directory for VCMI development, eg. `C:\VCMI` We will call this directo
Warning! Replace `%VCMI_DIR%` with path you've chosen for VCMI installation in the following commands.
It is recommended to avoid non-ascii characters in the path to your working folders. The folder should not be write-protected by system.
It is recommended to avoid non-ascii characters in the path to your working folders. The folder should not be write-protected by system.
Good locations:
- `C:\VCMI`
Bad locations:
- `C:\Users\Michał\VCMI (non-ascii character)`
- `C:\Program Files (x86)\VCMI (write protection)`
@@ -38,13 +40,14 @@ You have two options: to use pre-built libraries or build your own. We strongly
#### Download and unpack archive
Vcpkg Archives are available at our GitHub: https://github.com/vcmi/vcmi-deps-windows/releases
Vcpkg Archives are available at our GitHub: <https://github.com/vcmi/vcmi-deps-windows/releases>
- Download latest version available.
EG: v1.6 assets - [vcpkg-export-x64-windows-v143.7z](https://github.com/vcmi/vcmi-deps-windows/releases/download/v1.6/vcpkg-export-x64-windows-v143.7z)
- Extract archive by right clicking on it and choosing "7-zip -> Extract Here".
#### Move dependencies to target directory
Once extracted, a `vcpkg` directory will appear with `installed` and `scripts` subfolders inside.
Move extracted `vcpkg` directory into your `%VCMI_DIR%`
@@ -57,19 +60,19 @@ Be aware that building Vcpkg might take a lot of time depend on your CPU model a
#### Clone vcpkg
1. open SourceTree
2. File -\> Clone
3. select **<https://github.com/microsoft/vcpkg/>** as source
4. select **%VCMI_DIR%/vcpkg** as destination
5. click **Clone**
1. open SourceTree
2. File -\> Clone
3. select **<https://github.com/microsoft/vcpkg/>** as source
4. select **%VCMI_DIR%/vcpkg** as destination
5. click **Clone**
From command line use:
git clone https://github.com/microsoft/vcpkg.git %VCMI_DIR%/vcpkg
`git clone https://github.com/microsoft/vcpkg.git %VCMI_DIR%/vcpkg`
#### Build vcpkg and dependencies
- Run
- Run
`%VCMI_DIR%/vcpkg/bootstrap-vcpkg.bat`
- For 32-bit build run:
`%VCMI_DIR%/vcpkg/vcpkg.exe install tbb:x64-windows fuzzylite:x64-windows sdl2:x64-windows sdl2-image:x64-windows sdl2-ttf:x64-windows sdl2-mixer[mpg123]:x64-windows boost:x64-windows qt5-base:x64-windows ffmpeg:x64-windows luajit:x64-windows`
@@ -85,6 +88,7 @@ Extract `ccache` to a folder of your choosing, add the folder to the `PATH` envi
## Build VCMI
#### From GIT GUI
- Open SourceTree
- File -> Clone
- select `https://github.com/vcmi/vcmi/` as source
@@ -94,26 +98,30 @@ Extract `ccache` to a folder of your choosing, add the folder to the `PATH` envi
- click Clone
#### From command line
- `git clone --recursive https://github.com/vcmi/vcmi.git %VCMI_DIR%/source`
### Generate solution for VCMI
- Create `%VCMI_DIR%/build` folder
- Open a command line prompt at `%VCMI_DIR%/build`
- Execute `cd %VCMI_DIR%/build`
- Execute `cd %VCMI_DIR%/build`
- Create solution (Visual Studio 2022 64-bit) `cmake %VCMI_DIR%/source -DCMAKE_TOOLCHAIN_FILE=%VCMI_DIR%/vcpkg/scripts/buildsystems/vcpkg.cmake -G "Visual Studio 17 2022" -A x64`
### Compile VCMI with Visual Studio
- Open `%VCMI_DIR%/build/VCMI.sln` in Visual Studio
- Select `Release` build type in the combobox
- If you want to use ccache:
- Select `Manage Configurations...` in the combobox
- Specify the following CMake variable: `ENABLE_CCACHE=ON`
- See the [Visual Studio documentation](https://learn.microsoft.com/en-us/cpp/build/customize-cmake-settings?view=msvc-170#cmake-variables-and-cache) for details
- Select `Manage Configurations...` in the combobox
- Specify the following CMake variable: `ENABLE_CCACHE=ON`
- See the [Visual Studio documentation](https://learn.microsoft.com/en-us/cpp/build/customize-cmake-settings?view=msvc-170#cmake-variables-and-cache) for details
- Right click on `BUILD_ALL` project. This `BUILD_ALL` project should be in `CMakePredefinedTargets` tree in Solution Explorer.
- VCMI will be built in `%VCMI_DIR%/build/bin` folder!
### Compile VCMI with MinGW via MSYS2
- Install MSYS2 from https://www.msys2.org/
- Install MSYS2 from <https://www.msys2.org/>
- Start the `MSYS MinGW x64`-shell
- Install dependencies: `pacman -S mingw-w64-x86_64-SDL2 mingw-w64-x86_64-SDL2_image mingw-w64-x86_64-SDL2_mixer mingw-w64-x86_64-SDL2_ttf mingw-w64-x86_64-boost mingw-w64-x86_64-gcc mingw-w64-x86_64-ninja mingw-w64-x86_64-qt5-static mingw-w64-x86_64-qt5-tools mingw-w64-x86_64-tbb`
- Generate and build solution from VCMI-root dir: `cmake --preset windows-mingw-release && cmake --build --preset windows-mingw-release`
@@ -134,8 +142,10 @@ Vcpkg might be very unstable due to limited popularity and fact of using bleedin
Pre-built version we provide is always manually tested with all supported versions of MSVC for both Release and Debug builds and all known quirks are listed below.
#$# Build is successful but can not start new game
### Build is successful but can not start new game
Make sure you have:
* Installed Heroes III from disk or using GOG installer
* Copied `Data`, `Maps` and `Mp3` folders from Heroes III to: `%USERPROFILE%\Documents\My Games\vcmi\`

View File

@@ -6,7 +6,8 @@
2. Xcode: <https://developer.apple.com/xcode/>
3. CMake 3.21+: `brew install --cask cmake` or get from <https://cmake.org/download/>
4. Optional:
- CCache to speed up recompilation: `brew install ccache`
- CCache to speed up recompilation: `brew install ccache`
## Obtaining source code

View File

@@ -91,7 +91,7 @@ Open `VCMI.xcodeproj` from the build directory, select `vcmiclient` scheme and h
## Packaging project into DMG file
After building, run `cpack` from the build directory. If using Xcode generator, also pass `-C `<configuration name> with the same configuration that you used to build the project.
After building, run `cpack` from the build directory. If using Xcode generator, also pass `-C`<configuration name> with the same configuration that you used to build the project.
If you use Conan, it's expected that you use **conan-generated** directory at step 4 of [Conan package manager](Conan.md).

View File

@@ -1,23 +1,21 @@
# CMake options
* `-D CMAKE_BUILD_TYPE=Debug`
* Enables debug info and disables optimizations
* Enables debug info and disables optimizations
* `-D CMAKE_EXPORT_COMPILE_COMMANDS=ON`
* Creates `compile_commands.json` for [clangd](https://clangd.llvm.org/) language server.
For clangd to find the JSON, create a file named `.clangd` with this content
```
CompileFlags:
CompilationDatabase: build
```
and place it here:
```
.
├── vcmi -> contains sources and is under git control
├── build -> contains build output, makefiles, object files,...
└── .clangd
```
* Creates `compile_commands.json` for [clangd](https://clangd.llvm.org/) language server. For clangd to find the JSON, create a file named `.clangd` with this content
```
CompileFlags:
CompilationDatabase: build
```
and place it here:
```
.
├── vcmi -> contains sources and is under git control
├── build -> contains build output, makefiles, object files,...
└── .clangd
```
* `-D ENABLE_CCACHE:BOOL=ON`
* Speeds up recompilation
* Speeds up recompilation
* `-G Ninja`
* Use Ninja build system instead of Make, which speeds up the build and doesn't require a `-j` flag
* Use Ninja build system instead of Make, which speeds up the build and doesn't require a `-j` flag

View File

@@ -29,9 +29,10 @@ Most of VCMI configuration files uses Json format and located in "config" direct
### Main purposes of client
Client is responsible for:
- displaying state of game to human player
- capturing player's actions and sending requests to server
- displaying changes in state of game indicated by server
- displaying state of game to human player
- capturing player's actions and sending requests to server
- displaying changes in state of game indicated by server
### Rendering of graphics
@@ -44,9 +45,9 @@ In rendering, Interface object system is quite helpful. Its base is CIntObject c
Server is responsible for:
- maintaining state of the game
- handling requests from all clients participating in game
- informing all clients about changes in state of the game that are
- maintaining state of the game
- handling requests from all clients participating in game
- informing all clients about changes in state of the game that are
visible to them
## Lib
@@ -59,11 +60,11 @@ iOS platform pioneered single process build, where server is a static library an
Lib contains code responsible for:
- handling most of Heroes III files (.lod, .txt setting files)
- storing information common to server and client like state of the game
- managing armies, buildings, artifacts, spells, bonuses and other game objects
- handling general game mechanics and related actions (only adventure map objects; it's an unwanted remnant of past development - all game mechanics should be handled by the server)
- networking and serialization
- handling most of Heroes III files (.lod, .txt setting files)
- storing information common to server and client like state of the game
- managing armies, buildings, artifacts, spells, bonuses and other game objects
- handling general game mechanics and related actions (only adventure map objects; it's an unwanted remnant of past development - all game mechanics should be handled by the server)
- networking and serialization
#### Serialization
@@ -94,7 +95,6 @@ Forward declarations of the lib in headers of other parts of the project need to
`<other forward declarations>`
`<classes>`
##### New project part
If you're creating new project part, place `VCMI_LIB_USING_NAMESPACE` in its `StdInc.h` to be able to use lib classes without explicit namespace in implementation files. Example: <https://github.com/vcmi/vcmi/blob/develop/launcher/StdInc.h>
@@ -121,4 +121,4 @@ VCMI includes [FuzzyLite](http://code.google.com/p/fuzzy-lite/) library to make
### Duels
### ERM parser
### ERM parser

View File

@@ -4,7 +4,7 @@
VCMI implementation bases on C++17 standard. Any feature is acceptable as long as it's will pass build on our CI, but there is list below on what is already being used.
Any compiler supporting C++17 should work, but this has not been thoroughly tested. You can find information about extensions and compiler support at http://en.cppreference.com/w/cpp/compiler_support
Any compiler supporting C++17 should work, but this has not been thoroughly tested. You can find information about extensions and compiler support at <http://en.cppreference.com/w/cpp/compiler_support>
## Style Guidelines
@@ -20,7 +20,7 @@ Inside a code block put the opening brace on the next line after the current sta
Good:
``` cpp
```cpp
if(a)
{
code();
@@ -30,7 +30,7 @@ if(a)
Bad:
``` cpp
```cpp
if(a) {
code();
code();
@@ -41,14 +41,14 @@ Avoid using unnecessary open/close braces, vertical space is usually limited:
Good:
``` cpp
```cpp
if(a)
code();
```
Bad:
``` cpp
```cpp
if(a) {
code();
}
@@ -58,7 +58,7 @@ Unless there are either multiple hierarchical conditions being used or that the
Good:
``` cpp
```cpp
if(a)
{
if(b)
@@ -68,7 +68,7 @@ if(a)
Bad:
``` cpp
```cpp
if(a)
if(b)
code();
@@ -78,7 +78,7 @@ If there are brackets inside the body, outside brackets are required.
Good:
``` cpp
```cpp
if(a)
{
for(auto elem : list)
@@ -90,7 +90,7 @@ if(a)
Bad:
``` cpp
```cpp
if(a)
for(auto elem : list)
{
@@ -102,7 +102,7 @@ If "else" branch has brackets then "if" should also have brackets even if it is
Good:
``` cpp
```cpp
if(a)
{
code();
@@ -118,7 +118,7 @@ else
Bad:
``` cpp
```cpp
if(a)
code();
else
@@ -134,7 +134,7 @@ If you intentionally want to avoid usage of "else if" and keep if body indent ma
Good:
``` cpp
```cpp
if(a)
{
code();
@@ -148,7 +148,7 @@ else
Bad:
``` cpp
```cpp
if(a)
code();
else
@@ -160,7 +160,7 @@ When defining a method, use a new line for the brace, like this:
Good:
``` cpp
```cpp
void method()
{
}
@@ -168,7 +168,7 @@ void method()
Bad:
``` cpp
```cpp
void Method() {
}
```
@@ -179,14 +179,14 @@ Use white space in expressions liberally, except in the presence of parenthesis.
**Good:**
``` cpp
```cpp
if(a + 5 > method(blah('a') + 4))
foo += 24;
```
**Bad:**
``` cpp
```cpp
if(a+5>method(blah('a')+4))
foo+=24;
```
@@ -199,13 +199,13 @@ Use a space before and after the address or pointer character in a pointer decla
Good:
``` cpp
```cpp
CIntObject * images[100];
```
Bad:
``` cpp
```cpp
CIntObject* images[100]; or
CIntObject *images[100];
```
@@ -214,14 +214,14 @@ Do not use spaces before parentheses.
Good:
``` cpp
```cpp
if(a)
code();
```
Bad:
``` cpp
```cpp
if (a)
code();
```
@@ -230,7 +230,7 @@ Do not use extra spaces around conditions inside parentheses.
Good:
``` cpp
```cpp
if(a && b)
code();
@@ -240,7 +240,7 @@ if(a && (b || c))
Bad:
``` cpp
```cpp
if( a && b )
code();
@@ -252,14 +252,14 @@ Do not use more than one space between operators.
Good:
``` cpp
```cpp
if((a && b) || (c + 1 == d))
code();
```
Bad:
``` cpp
```cpp
if((a && b) || (c + 1 == d))
code();
@@ -273,14 +273,14 @@ When allocating objects, don't use parentheses for creating stack-based objects
Good:
``` cpp
```cpp
std::vector<int> v;
CGBoat btn = new CGBoat();
```
Bad:
``` cpp
```cpp
std::vector<int> v(); // shouldn't compile anyway
CGBoat btn = new CGBoat;
```
@@ -289,14 +289,14 @@ Avoid overuse of parentheses:
Good:
``` cpp
```cpp
if(a && (b + 1))
return c == d;
```
Bad:
``` cpp
```cpp
if((a && (b + 1)))
return (c == d);
```
@@ -305,7 +305,7 @@ if((a && (b + 1)))
Base class list must be on same line with class name.
``` cpp
```cpp
class CClass : public CClassBaseOne, public CClassBaseOne
{
int id;
@@ -321,7 +321,7 @@ When 'private:', 'public:' and other labels are not on the line after opening br
Good:
``` cpp
```cpp
class CClass
{
int id;
@@ -333,7 +333,7 @@ public:
Bad:
``` cpp
```cpp
class CClass
{
int id;
@@ -344,7 +344,7 @@ public:
Good:
``` cpp
```cpp
class CClass
{
protected:
@@ -357,7 +357,7 @@ public:
Bad:
``` cpp
```cpp
class CClass
{
@@ -373,7 +373,7 @@ public:
Constructor member and base class initialization must be on new line, indented with tab with leading colon.
``` cpp
```cpp
CClass::CClass()
: CClassBaseOne(true, nullptr), id(0), bool parameters(false)
{
@@ -387,7 +387,7 @@ Switch statements have the case at the same indentation as the switch.
Good:
``` cpp
```cpp
switch(alignment)
{
case EAlignment::EVIL:
@@ -407,7 +407,7 @@ default:
Bad:
``` cpp
```cpp
switch(alignment)
{
case EAlignment::EVIL:
@@ -447,7 +447,7 @@ break;
Good:
``` cpp
```cpp
auto lambda = [this, a, &b](int3 & tile, int index) -> bool
{
do_that();
@@ -456,7 +456,7 @@ auto lambda = [this, a, &b](int3 & tile, int index) -> bool
Bad:
``` cpp
```cpp
auto lambda = [this,a,&b](int3 & tile, int index)->bool{do_that();};
```
@@ -464,7 +464,7 @@ Empty parameter list is required even if function takes no arguments.
Good:
``` cpp
```cpp
auto lambda = []()
{
do_that();
@@ -473,7 +473,7 @@ auto lambda = []()
Bad:
``` cpp
```cpp
auto lambda = []
{
do_that();
@@ -484,7 +484,7 @@ Do not use inline lambda expressions inside if-else, for and other conditions.
Good:
``` cpp
```cpp
auto lambda = []()
{
do_that();
@@ -497,7 +497,7 @@ if(lambda)
Bad:
``` cpp
```cpp
if([]()
{
do_that();
@@ -511,7 +511,7 @@ Do not pass inline lambda expressions as parameter unless it's the last paramete
Good:
``` cpp
```cpp
auto lambda = []()
{
do_that();
@@ -521,7 +521,7 @@ obj->someMethod(lambda, true);
Bad:
``` cpp
```cpp
obj->someMethod([]()
{
do_that();
@@ -530,7 +530,7 @@ obj->someMethod([]()
Good:
``` cpp
```cpp
obj->someMethod(true, []()
{
do_that();
@@ -543,7 +543,7 @@ Serialization of each element must be on it's own line since this make debugging
Good:
``` cpp
```cpp
template <typename Handler> void serialize(Handler & h, const int version)
{
h & identifier;
@@ -555,7 +555,7 @@ template <typename Handler> void serialize(Handler & h, const int version)
Bad:
``` cpp
```cpp
template <typename Handler> void serialize(Handler & h, const int version)
{
h & identifier & description & name & dependencies;
@@ -566,7 +566,7 @@ Save backward compatibility code is exception when extra brackets are always use
Good:
``` cpp
```cpp
template <typename Handler> void serialize(Handler & h, const int version)
{
h & identifier;
@@ -586,7 +586,7 @@ template <typename Handler> void serialize(Handler & h, const int version)
Bad:
``` cpp
```cpp
template <typename Handler> void serialize(Handler & h, const int version)
{
h & identifier;
@@ -604,7 +604,7 @@ template <typename Handler> void serialize(Handler & h, const int version)
For any new files, please paste the following info block at the very top of the source file:
``` cpp
```cpp
/*
* Name_of_File.h, part of VCMI engine
*
@@ -622,13 +622,13 @@ The above notice have to be included both in header and source files (.h/.cpp).
For any header or source file code must be in following order:
1. Licensing information
2. pragma once preprocessor directive
3. include directives
4. Forward declarations
5. All other code
1. Licensing information
2. pragma once preprocessor directive
3. include directives
4. Forward declarations
5. All other code
``` cpp
```cpp
/*
* Name_of_File.h, part of VCMI engine
*
@@ -652,7 +652,7 @@ If you comment on the same line with code there must be one single space between
Good:
``` cpp
```cpp
if(a)
{
code(); //Do something
@@ -665,7 +665,7 @@ else // Do something.
Bad:
``` cpp
```cpp
if(a)
{
code();//Do something
@@ -680,7 +680,7 @@ If you add single-line comment on own line slashes must have same indent as code
Good:
``` cpp
```cpp
// Do something
if(a)
{
@@ -692,7 +692,7 @@ if(a)
Bad:
``` cpp
```cpp
// Do something
if(a)
{
@@ -706,7 +706,7 @@ Avoid comments inside multi-line if-else conditions. If your conditions are too
Good:
``` cpp
```cpp
bool isMyHeroAlive = a && b || (c + 1 > 15);
bool canMyHeroMove = myTurn && hero.movePoints > 0;
if(isMyHeroAlive && canMyHeroMove)
@@ -717,7 +717,7 @@ if(isMyHeroAlive && canMyHeroMove)
Bad:
``` cpp
```cpp
if((a && b || (c + 1 > 15)) //Check if hero still alive
&& myTurn && hero.movePoints > 0) //Check if hero can move
{
@@ -727,7 +727,7 @@ if((a && b || (c + 1 > 15)) //Check if hero still alive
You should write a comment before the class definition which describes shortly the class. 1-2 sentences are enough. Methods and class data members should be commented if they aren't self-describing only. Getters/Setters, simple methods where the purpose is clear or similar methods shouldn't be commented, because vertical space is usually limited. The style of documentation comments should be the three slashes-style: ///.
``` cpp
```cpp
/// Returns true if a debug/trace log message will be logged, false if not.
/// Useful if performance is important and concatenating the log message is a expensive task.
bool isDebugEnabled() const;
@@ -738,7 +738,7 @@ The above example doesn't follow a strict scheme on how to comment a method. It
If you need a more detailed description for a method you can use such style:
``` cpp
```cpp
/// <A short one line description>
///
/// <Longer description>
@@ -749,7 +749,7 @@ If you need a more detailed description for a method you can use such style:
/// @return Description of the return value
```
A good essay about writing comments: http://ardalis.com/when-to-comment-your-code
A good essay about writing comments: <http://ardalis.com/when-to-comment-your-code>
### Casing
@@ -775,7 +775,7 @@ Outdated. There is separate entry for [Logging API](Logging_API.md)
If you want to trace the control flow of VCMI, then you should use the macro LOG_TRACE or LOG_TRACE_PARAMS. The first one prints a message when the function is entered or leaved. The name of the function will also be logged. In addition to this the second macro, let's you specify parameters which you want to print. You should print traces with parameters like this:
``` cpp
```cpp
LOG_TRACE_PARAMS(logGlobal, "hero '%s', spellId '%d', pos '%s'.", hero, spellId, pos);
```
@@ -797,14 +797,14 @@ Do not use uncommon abbreviations for class, method, parameter and global object
Bad:
``` cpp
```cpp
CArt * getRandomArt(...)
class CIntObject
```
Good:
``` cpp
```cpp
CArtifact * getRandomArtifact(...)
class CInterfaceObject
```
@@ -827,7 +827,7 @@ The header StdInc.h should be included in every compilation unit. It has to be i
Do not declare enumerations in global namespace. It is better to use strongly typed enum or to wrap them in class or namespace to avoid polluting global namespace:
``` cpp
```cpp
enum class EAlignment
{
GOOD,
@@ -848,7 +848,7 @@ namespace EAlignment
If the comment duplicates the name of commented member, it's better if it wouldn't exist at all. It just increases maintenance cost. Bad:
``` cpp
```cpp
size_t getHeroesCount(); //gets count of heroes (surprise?)
```
@@ -862,16 +862,16 @@ Don't return const objects or primitive types from functions -- it's pointless.
Bad:
``` cpp
```cpp
const std::vector<CGObjectInstance *> guardingCreatures(int3 pos) const;
```
Good:
``` cpp
```cpp
std::vector<const CGObjectInstance *> guardingCreatures(int3 pos) const;
```
## Sources
[Mono project coding guidelines](http://www.mono-project.com/Coding_Guidelines)
[Mono project coding guidelines](http://www.mono-project.com/Coding_Guidelines)

View File

@@ -27,7 +27,7 @@ The following platforms are supported and known to work, others might require ch
- **Windows**: libraries are built with x86_64-mingw-w64-gcc version 10 (which is available in repositories of Ubuntu 22.04)
- **Android**: libraries are built with NDK r25c (25.2.9519653)
2. Download the binaries archive and unpack it to `~/.conan` directory from https://github.com/vcmi/vcmi-dependencies/releases/latest
2. Download the binaries archive and unpack it to `~/.conan` directory from <https://github.com/vcmi/vcmi-dependencies/releases/latest>
- macOS: pick **dependencies-mac-intel.txz** if you have Intel Mac, otherwise - **dependencies-mac-arm.txz**
- iOS: pick ***dependencies-ios.txz***
@@ -65,7 +65,7 @@ If you use `--build=never` and this command fails, then it means that you can't
VCMI "recipe" also has some options that you can specify. For example, if you don't care about game videos, you can disable FFmpeg dependency by passing `-o with_ffmpeg=False`. If you only want to make release build, you can use `GENERATE_ONLY_BUILT_CONFIG=1` environment variable to skip generating files for other configurations (our CI does this).
_Note_: you can find full reference of this command [in the official documentation](https://docs.conan.io/1/reference/commands/consumer/install.html) or by executing `conan help install`.
*Note*: you can find full reference of this command [in the official documentation](https://docs.conan.io/1/reference/commands/consumer/install.html) or by executing `conan help install`.
### Using our prebuilt binaries for macOS/iOS
@@ -86,7 +86,7 @@ This subsection describes platform specifics to build libraries from source prop
#### Building for macOS/iOS
- To build Locale module of Boost in versions >= 1.81, you must use `compiler.cppstd=11` Conan setting (our profiles already contain it). To use it with another profile, either add this setting to your _host_ profile or pass `-s compiler.cppstd=11` on the command line.
- To build Locale module of Boost in versions >= 1.81, you must use `compiler.cppstd=11` Conan setting (our profiles already contain it). To use it with another profile, either add this setting to your *host* profile or pass `-s compiler.cppstd=11` on the command line.
- If you wish to build dependencies against system libraries (like our prebuilt ones do), follow [below instructions](#using-recipes-for-system-libraries) executing `conan create` for all directories. Don't forget to pass `-o with_apple_system_libs=True` to `conan install` afterwards.
#### Building for Android
@@ -105,11 +105,11 @@ After applying patch(es):
2. Run `make`
3. Copy file `qtbase/jar/QtAndroid.jar` from the build directory to the **package directory**, e.g. `~/.conan/data/qt/5.15.14/_/_/package/SOME_HASH/jar`.
_Note_: if you plan to build Qt from source again, then you don't need to perform the above _After applying patch(es)_ steps after building.
*Note*: if you plan to build Qt from source again, then you don't need to perform the above *After applying patch(es)* steps after building.
##### Using recipes for system libraries
1. Clone/download https://github.com/kambala-decapitator/conan-system-libs
1. Clone/download <https://github.com/kambala-decapitator/conan-system-libs>
2. Execute `conan create PACKAGE vcmi/CHANNEL`, where `PACKAGE` is a directory path in that repository and `CHANNEL` is **apple** for macOS/iOS and **android** for Android. Do it for each library you need.
3. Now you can execute `conan install` to build all dependencies.

View File

@@ -6,7 +6,7 @@ Qt Creator is the recommended IDE for VCMI development on Linux distributions, b
- Almost no manual configuration when used with CMake. Project configuration is read from CMake text files,
- Easy to setup and use with multiple different compiler toolchains: GCC, Visual Studio, Clang
You can install Qt Creator from repository, but better to stick to latest version from Qt website: https://www.qt.io/download-qt-installer-oss
You can install Qt Creator from repository, but better to stick to latest version from Qt website: <https://www.qt.io/download-qt-installer-oss>
## Configuration
@@ -21,4 +21,4 @@ The build dir should be set to something like /trunk/build for the debug build a
There is a problem with QtCreator when debugging both vcmiclient and vcmiserver. If you debug the vcmiclient, start a game, attach the vcmiserver process to the gdb debugger(Debug \> Start Debugging \> Attach to Running External Application...) then breakpoints which are set for vcmiserver will be ignored. This looks like a bug, in any case it's not intuitively. Two workarounds are available luckily:
1. Run vcmiclient (no debug mode), then attach server process to the debugger
2. Open two instances of QtCreator and debug vcmiserver and vcmiclient separately(it works!)
2. Open two instances of QtCreator and debug vcmiserver and vcmiclient separately(it works!)

View File

@@ -2,14 +2,14 @@
## Features
- A logger belongs to a "domain", this enables us to change log level settings more selectively
- The log format can be customized
- The color of a log entry can be customized based on logger domain and logger level
- Logger settings can be changed in the settings.json file
- No std::endl at the end of a log entry required
- Thread-safe
- Macros for tracing the application flow
- Provides stream-like and function-like logging
- A logger belongs to a "domain", this enables us to change log level settings more selectively
- The log format can be customized
- The color of a log entry can be customized based on logger domain and logger level
- Logger settings can be changed in the settings.json file
- No std::endl at the end of a log entry required
- Thread-safe
- Macros for tracing the application flow
- Provides stream-like and function-like logging
## Class diagram
@@ -17,14 +17,14 @@
Some notes:
- There are two methods `configure` and `configureDefault` of the class `CBasicLogConfigurator` to initialize and setup the logging system. The latter one setups default logging and isn't dependent on VCMI's filesystem, whereas the first one setups logging based on the user's settings which can be configured in the settings.json.
- The methods `isDebugEnabled` and `isTraceEnabled` return true if a log record of level debug respectively trace will be logged. This can be useful if composing the log message is a expensive task and performance is important.
- There are two methods `configure` and `configureDefault` of the class `CBasicLogConfigurator` to initialize and setup the logging system. The latter one setups default logging and isn't dependent on VCMI's filesystem, whereas the first one setups logging based on the user's settings which can be configured in the settings.json.
- The methods `isDebugEnabled` and `isTraceEnabled` return true if a log record of level debug respectively trace will be logged. This can be useful if composing the log message is a expensive task and performance is important.
## Usage
### Setup settings.json
``` javascript
``` jsonc
{
"logging" : {
"console" : {
@@ -87,6 +87,7 @@ global -\> info
### How to get a logger
There exist only one logger object per domain. A logger object cannot be copied. You can get access to a logger object by using the globally defined ones like `logGlobal` or `logAi`, etc... or by getting one manually:
```cpp
Logger * logger = CLogger::getLogger(CLoggerDomain("rmg"));
```
@@ -104,22 +105,22 @@ Don't include a '\n' or std::endl at the end of your log message, a new line wil
The following list shows several log levels from the highest one to the lowest one:
- error -\> for errors, e.g. if resource is not available, if a initialization fault has occurred, if a exception has been thrown (can result in program termination)
- warn -\> for warnings, e.g. if sth. is wrong, but the program can continue execution "normally"
- info -\> informational messages, e.g. Filesystem initialized, Map loaded, Server started, etc...
- debug -\> for debugging, e.g. hero moved to (12,3,0), direction 3', 'following artifacts influence X: .. or pattern detected at pos (10,15,0), p-nr. 30, flip 1, repl. 'D'
- trace -\> for logging the control flow, the execution progress or fine-grained events, e.g. hero movement completed, entering CMapEditManager::updateTerrainViews: posx '10', posy '5', width '10', height '10', mapLevel '0',...
- error -\> for errors, e.g. if resource is not available, if a initialization fault has occurred, if a exception has been thrown (can result in program termination)
- warn -\> for warnings, e.g. if sth. is wrong, but the program can continue execution "normally"
- info -\> informational messages, e.g. Filesystem initialized, Map loaded, Server started, etc...
- debug -\> for debugging, e.g. hero moved to (12,3,0), direction 3', 'following artifacts influence X: .. or pattern detected at pos (10,15,0), p-nr. 30, flip 1, repl. 'D'
- trace -\> for logging the control flow, the execution progress or fine-grained events, e.g. hero movement completed, entering CMapEditManager::updateTerrainViews: posx '10', posy '5', width '10', height '10', mapLevel '0',...
The following colors are available for console output:
- default
- green
- red
- magenta
- yellow
- white
- gray
- teal
- default
- green
- red
- magenta
- yellow
- white
- gray
- teal
### How to trace execution
@@ -143,10 +144,10 @@ The program execution can be traced by using the macros TRACE_BEGIN, TRACE_END a
A domain is a specific part of the software. In VCMI there exist several domains:
- network
- ai
- bonus
- network
- network
- ai
- bonus
- network
In addition to these domains, there exist always a super domain called "global". Sub-domains can be created with "ai.battle" or "ai.adventure" for example. The dot between the "ai" and "battle" is important and notes the parent-child relationship of those two domains. A few examples how the log level will be inherited:

View File

@@ -2,7 +2,7 @@
## Configuration
``` javascript
``` jsonc
{
//general purpose script, Lua or ERM, runs on server
"myScript":
@@ -87,75 +87,75 @@ VCMI uses LuaJIT, which is Lua 5.1 API, see [upstream documentation](https://www
Following libraries are supported
- base
- table
- string
- math
- bit
- base
- table
- string
- math
- bit
## ERM
### Features
- no strict limit on function/variable numbers (technical limit 32 bit integer except 0))
- TODO semi compare
- DONE macros
- no strict limit on function/variable numbers (technical limit 32 bit integer except 0))
- TODO semi compare
- DONE macros
### Bugs
- TODO Broken XOR support (clashes with \`X\` option)
- TODO Broken XOR support (clashes with \`X\` option)
### Triggers
- TODO **!?AE** Equip/Unequip artifact
- WIP **!?BA** when any battle occurs
- WIP **!?BF** when a battlefield is prepared for a battle
- TODO **!?BG** at every action taken by any stack or by the hero
- TODO **!?BR** at every turn of a battle
- *!?CM (client only) click the mouse button.*
- TODO **!?CO** Commander triggers
- TODO **!?DL** Custom dialogs
- DONE **!?FU** function
- TODO **!?GE** "global" event
- TODO **!?GM** Saving/Loading
- TODO **!?HE** when the hero \# is attacked by an enemy hero or
- TODO **!?AE** Equip/Unequip artifact
- WIP **!?BA** when any battle occurs
- WIP **!?BF** when a battlefield is prepared for a battle
- TODO **!?BG** at every action taken by any stack or by the hero
- TODO **!?BR** at every turn of a battle
- *!?CM (client only) click the mouse button.*
- TODO **!?CO** Commander triggers
- TODO **!?DL** Custom dialogs
- DONE **!?FU** function
- TODO **!?GE** "global" event
- TODO **!?GM** Saving/Loading
- TODO **!?HE** when the hero \# is attacked by an enemy hero or
visited by an allied hero
- TODO **!?HL** hero gains a level
- TODO **!?HM** every step a hero \# takes
- *!?IP Multiplayer support.*
- TODO **!?LE** (!$LE) An Event on the map
- WIP **!?MF** stack taking physical damage(before an action)
- TODO **!?MG** casting on the adventure map
- *!?MM scroll text during a battle*
- TODO **!?MR** Magic resistance
- TODO **!?MW** Wandering Monsters
- WIP **!?OB** (!$OB) visiting objects
- DONE **!?PI** Post Instruction.
- TODO **!?SN** Sound and ERA extensions
- *!?TH town hall*
- TODO **!?TL** Real-Time Timer
- TODO **!?TM** timed events
- TODO **!?HL** hero gains a level
- TODO **!?HM** every step a hero \# takes
- *!?IP Multiplayer support.*
- TODO **!?LE** (!$LE) An Event on the map
- WIP **!?MF** stack taking physical damage(before an action)
- TODO **!?MG** casting on the adventure map
- *!?MM scroll text during a battle*
- TODO **!?MR** Magic resistance
- TODO **!?MW** Wandering Monsters
- WIP **!?OB** (!$OB) visiting objects
- DONE **!?PI** Post Instruction.
- TODO **!?SN** Sound and ERA extensions
- *!?TH town hall*
- TODO **!?TL** Real-Time Timer
- TODO **!?TM** timed events
### Receivers
#### VCMI
- **!!MC:S@varName@** - declare new "normal" variable (technically
- **!!MC:S@varName@** - declare new "normal" variable (technically
v-var with string key)
- TODO Identifier resolver
- WIP Bonus system
- TODO Identifier resolver
- WIP Bonus system
#### ERA
- DONE !!if !!el !!en
- TODO !!br !!co
- TODO !!SN:X
- DONE !!if !!el !!en
- TODO !!br !!co
- TODO !!SN:X
#### WoG
- TODO !!AR Артефакт (ресурс) в определенной позиции
- TODO !!BA Битва
- !!BA:A$ return 1 for battle evaluation
- !!BA:A$ return 1 for battle evaluation
- TODO !!BF Препятствия на поле боя
- TODO !!BG Действий монстров в бою
- TODO !!BH Действия героя в бою
@@ -201,4 +201,4 @@ Following libraries are supported
- *!#VC Контроль переменных*
- WIP !!VR Установка переменных
### Persistence
### Persistence

View File

@@ -5,12 +5,14 @@
For implementation details see files located at `lib/network` directory.
VCMI uses connection using TCP to communicate with server, even in single-player games. However, even though TCP is stream-based protocol, VCMI uses atomic messages for communication. Each message is a serialized stream of bytes, preceded by 4-byte message size:
```
int32_t messageSize;
byte messagePayload[messageSize];
```
Networking can be used by:
- game client (vcmiclient / VCMI_Client.exe). Actual application that player interacts with directly using UI.
- match server (vcmiserver / VCMI_Server.exe / part of game client). This app controls game logic and coordinates multiplayer games.
- lobby server (vcmilobby). This app provides access to global lobby through which players can play game over Internet.
@@ -28,11 +30,13 @@ For gameplay, VCMI serializes data into a binary stream. See [Serialization](Ser
## Global lobby communication
For implementation details see:
- game client: `client/globalLobby/GlobalLobbyClient.h
- match server: `server/GlobalLobbyProcessor.h
- lobby server: `client/globalLobby/GlobalLobbyClient.h
In case of global lobby, message payload uses plaintext json format - utf-8 encoded string:
```
int32_t messageSize;
char jsonString[messageSize];
@@ -43,6 +47,7 @@ Every message must be a struct (json object) that contains "type" field. Unlike
### Communication flow
Notes:
- invalid message, such as corrupted json format or failure to validate message will result in no reply from server
- in addition to specified messages, match server will send `operationFailed` message on failure to apply player request
@@ -51,7 +56,8 @@ Notes:
- client -> lobby: `clientRegister`
- lobby -> client: `accountCreated`
#### Login
#### Login
- client -> lobby: `clientLogin`
- lobby -> client: `loginSuccess`
- lobby -> client: `chatHistory`
@@ -59,10 +65,12 @@ Notes:
- lobby -> client: `activeGameRooms`
#### Chat Message
- client -> lobby: `sendChatMessage`
- lobby -> every client: `chatMessage`
#### New Game Room
- client starts match server instance
- match -> lobby: `serverLogin`
- lobby -> match: `loginSuccess`
@@ -73,19 +81,23 @@ Notes:
- lobby -> every client: `activeGameRooms`
#### Joining a game room
See [#Proxy mode](proxy-mode)
#### Leaving a game room
- client closes connection to match server
- match -> lobby: `leaveGameRoom`
#### Sending an invite:
#### Sending an invite
- client -> lobby: `sendInvite`
- lobby -> target client: `inviteReceived`
Note: there is no dedicated procedure to accept an invite. Instead, invited player will use same flow as when joining public game room
#### Logout
- client closes connection
- lobby -> every client: `activeAccounts`
@@ -94,6 +106,7 @@ Note: there is no dedicated procedure to accept an invite. Instead, invited play
In order to connect players located behind NAT, VCMI lobby can operate in "proxy" mode. In this mode, connection will be act as proxy and will transmit gameplay data from client to a match server, without any data processing on lobby server.
Currently, process to establish connection using proxy mode is:
- Player attempt to join open game room using `joinGameRoom` message
- Lobby server validates requests and on success - notifies match server about new player in lobby using control connection
- Match server receives request, establishes new connection to game lobby, sends `serverProxyLogin` message to lobby server and immediately transfers this connection to VCMIServer class to use as connection for gameplay communication
@@ -101,4 +114,4 @@ Currently, process to establish connection using proxy mode is:
- Game client receives message and establishes own side of proxy connection - connects to lobby, sends `clientProxyLogin` message and transfers to ServerHandler class to use as connection for gameplay communication
- Lobby server accepts new connection and moves it into a proxy mode - all packages that will be received by one side of this connection will be re-sent to another side without any processing.
Once the game is over (or if one side disconnects) lobby server will close another side of the connection and erase proxy connection
Once the game is over (or if one side disconnects) lobby server will close another side of the connection and erase proxy connection

View File

@@ -74,4 +74,4 @@ For every zone, a few random obstacle sets are selected. [Details](https://githu
### Filling space
Tiles which need to be `blocked` but are not `used` are filled with obstacles. Largest obstacles which cover the most tiles are picked first, other than that they are chosen randomly.
Tiles which need to be `blocked` but are not `used` are filled with obstacles. Largest obstacles which cover the most tiles are picked first, other than that they are chosen randomly.

View File

@@ -140,7 +140,7 @@ CLoadFile/CSaveFile classes allow to read data to file and store data to file. T
#### Networking
See [Networking](Networking.md)
See [Networking](Networking.md)
### Additional features
@@ -259,4 +259,4 @@ Foo *loadedA, *loadedB;
The feature recognizes pointers by addresses. Therefore it allows mixing pointers to base and derived classes. However, it does not allow serializing classes with multiple inheritance using a "non-first" base (other bases have a certain address offset from the actual object).
Pointer cycles are properly handled. This feature makes sense for savegames and is turned on for them.
Pointer cycles are properly handled. This feature makes sense for savegames and is turned on for them.