Skip to content

Commit 01703da

Browse files
committed
Move contributing stuff from README to CONTRIBUTING.
1 parent 5f3175b commit 01703da

2 files changed

Lines changed: 157 additions & 155 deletions

File tree

CONTRIBUTING.md

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
2+
# ModOrganizer 2 - Basic Games - How to Contribute?
3+
4+
## How to add a new game?
5+
6+
You can create a plugin by providing a python class in the `games` folder.
7+
8+
**Note:** If your game plugin does not load properly, you should set the log level
9+
to debug and look at the `mo_interface.log` file.
10+
11+
You need to create a class that inherits `BasicGame` and put it in a `game_XX.py` in `games`.
12+
Below is an example for The Witcher 3 (see also [games/game_witcher3.py](games/game_witcher3.py)):
13+
14+
```python
15+
from PyQt6.QtCore import QDir
16+
from ..basic_game import BasicGame
17+
18+
19+
class Witcher3Game(BasicGame):
20+
21+
Name = "Witcher 3 Support Plugin"
22+
Author = "Holt59"
23+
Version = "1.0.0a"
24+
25+
GameName = "The Witcher 3"
26+
GameShortName = "witcher3"
27+
GameBinary = "bin/x64/witcher3.exe"
28+
GameDataPath = "Mods"
29+
GameSaveExtension = "sav"
30+
GameSteamId = 292030
31+
32+
def savesDirectory(self):
33+
return QDir(self.documentsDirectory().absoluteFilePath("gamesaves"))
34+
```
35+
36+
`BasicGame` inherits `IPluginGame` so you can override methods if you need to.
37+
Each attribute you provide corresponds to a method (e.g., `Version` corresponds
38+
to the `version` method, see the table below). If you override the method, you do
39+
not have to provide the attribute:
40+
41+
```python
42+
from PyQt6.QtCore import QDir
43+
from ..basic_game import BasicGame
44+
45+
import mobase
46+
47+
48+
class Witcher3Game(BasicGame):
49+
50+
Name = "Witcher 3 Support Plugin"
51+
Author = "Holt59"
52+
53+
GameName = "The Witcher 3"
54+
GameShortName = "witcher3"
55+
GameBinary = "bin/x64/witcher3.exe"
56+
GameDataPath = "Mods"
57+
GameSaveExtension = "sav"
58+
GameSteamId = 292030
59+
60+
def version(self):
61+
# Don't forget to import mobase!
62+
return mobase.VersionInfo(1, 0, 0, mobase.ReleaseType.final)
63+
64+
def savesDirectory(self):
65+
return QDir(self.documentsDirectory().absoluteFilePath("gamesaves"))
66+
```
67+
68+
### List of valid keys
69+
70+
| Name | Description | `IPluginGame` method | Python |
71+
|------|-------------|----------------------|--------|
72+
| Name | Name of the plugin | `name` | `str` |
73+
| Author | Author of the plugin | `author` | `str` |
74+
| Version | Version of the plugin | `version` | `str` or `mobase.VersionInfo` |
75+
| Description| Description (Optional) | `description` | `str` |
76+
| GameName | Name of the game, as displayed by MO2 | `gameName` | `str` |
77+
| GameShortName | Short name of the game | `gameShortName` | `str` |
78+
| GameNexusName| Nexus name of the game (Optional, default to `GameShortName`) | `gameNexusName` | `str` |
79+
| GameValidShortNames | Other valid short names (Optional) | `validShortNames` | `List[str]` or comma-separated list of values |
80+
| GameNexusId | Nexus ID of the game (Optional) | `nexusGameID` | `str` or `int` |
81+
| GameBinary | Name of the game executable, relative to the game path | `binaryName` | `str` |
82+
| GameLauncher | Name of the game launcher, relative to the game path (Optional) | `getLauncherName` | `str` |
83+
| GameDataPath | Name of the folder containing mods, relative to game folder| `dataDirectory` | |
84+
| GameDocumentsDirectory | Documents directory (Optional) | `documentsDirectory` | `str` or `QDir` |
85+
| GameIniFiles | Config files in documents, for profile specific config (Optional) | `iniFiles` | `str` or `List[str]` |
86+
| GameSavesDirectory | Directory containing saves (Optional, default to `GameDocumentsDirectory`) | `savesDirectory` | `str` or `QDir` |
87+
| GameSaveExtension | Save file extension (Optional) `savegameExtension` | `str` |
88+
| GameSteamId | Steam ID of the game (Optional) | `steamAPPId` | `List[str]` or `str` or `int` |
89+
| GameGogId | GOG ID of the game (Optional) | `gogAPPId` | `List[str]` or `str` or `int` |
90+
| GameOriginManifestIds | Origin Manifest ID of the game (Optional) | `originManifestIds` | `List[str]` or `str` |
91+
| GameOriginWatcherExecutables | Executables to watch for Origin DRM (Optional) | `originWatcherExecutables` | `List[str]` or `str` |
92+
| GameEpicId | Epic ID (`AppName`) of the game (Optional) | `epicAPPId` | `List[str]` or `str` |
93+
| GameEaDesktopId | EA Desktop ID of the game (Optional) | `eaDesktopContentId` | `List[str]` or `str` or `int` |
94+
95+
You can use the following variables for `str`:
96+
97+
- `%DOCUMENTS%` will be replaced by the standard *Documents* folder.
98+
- `%GAME_PATH%` will be replaced by the path to the game folder.
99+
- `%GAME_DOCUMENTS%` will be replaced by the value of `GameDocumentsDirectory`.
100+
101+
## Extra features
102+
103+
The meta-plugin provides some useful extra feature:
104+
105+
1. **Automatic Steam, GOG, Origin, Epic Games and EA Desktop detection:** If you provide
106+
Steam, GOG, Origin or Epic IDs for the game (via `GameSteamId`, `GameGogId`,
107+
`GameOriginManifestIds`, `GameEpicId` or `GameEaDesktopId`), the game will be listed
108+
in the list of available games when creating a new MO2 instance (if the game is
109+
installed via Steam, GOG, Origin, Epic Games / Legendary or EA Desktop).
110+
2. **Basic save game preview / metadata** (Python): If you can easily obtain a picture
111+
(file) and/or metadata (like from json) for any saves, you can provide basic save-game
112+
preview by using the `BasicGameSaveGameInfo`. See
113+
[games/game_witcher3.py](games/game_witcher3.py) and
114+
[games/game_bladeandsorcery.py](games/game_bladeandsorcery.py) for more details.
115+
3. **Basic local save games** (Python): profile specific save games, as in [games/game_valheim.py](games/game_valheim.py).
116+
4. **Basic mod data checker** (Python):
117+
Check and fix different mod archive layouts for an automatic installation with the proper
118+
file structure, using simple (glob) patterns via `BasicModDataChecker`.
119+
See [games/game_valheim.py](games/game_valheim.py) and [game_subnautica.py](games/game_subnautica.py) for an example.
120+
121+
Game IDs can be found here:
122+
123+
- For Steam on [Steam Database](https://steamdb.info/)
124+
- For GOG on [GOG Database](https://www.gogdb.org/)
125+
- For Origin from `C:\ProgramData\Origin\LocalContent` (.mfst files)
126+
- For Epic Games (`AppName`) from:
127+
- `C:\ProgramData\Epic\EpicGamesLauncher\Data\Manifests\` (.item files)
128+
- or `C:\ProgramData\Epic\EpicGamesLauncher\UnrealEngineLauncher\LauncherInstalled.dat`
129+
- or [Unofficial EGS ID DB](https://erri120.github.io/egs-db/)
130+
- For Legendary (alt. Epic launcher) via command `legendary list-games`
131+
or from: `%USERPROFILE%\.config\legendary\installed.json`
132+
- For EA Desktop from `<EA Games install location>\<game title>\__Installer\installerdata.xml`
133+
134+
## Contribute
135+
136+
We recommend using a dedicated Python environment to write a new basic game plugins.
137+
138+
1. Install the required version of Python - Currently Python 3.12 (MO2 2.5).
139+
2. Remove the repository at `${MO2_INSTALL}/plugins/basic_games`.
140+
3. Clone this repository at the location of the old plugin (
141+
`${MO2_INSTALL}/plugins/basic_games`).
142+
4. Place yourself inside the cloned folder and:
143+
144+
```bash
145+
# create a virtual environment (recommended)
146+
py -3.12 -m venv .\venv
147+
.\venv\scripts\Activate.ps1
148+
149+
# "install" poetry and the development package
150+
pip install poetry
151+
poetry install
152+
```

README.md

Lines changed: 5 additions & 155 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,10 @@ providing a very simple python class.
1313

1414
## How to install?
1515

16-
Download the archive for your MO2 version and extract it directly into your MO2 `plugins` folder.
17-
18-
- Mod Organizer **2.3.2**: [Download](https://github.com/ModOrganizer2/modorganizer-basic_games/releases/download/v0.0.3/basic_games-0.0.3.zip)
19-
and extract in your `plugins/` folder (see below).
20-
- Mod Organizer **2.4**: Basic games is included in Mod Organizer 2.4.
21-
- If you want to use new game plugins that have not been included in the
22-
release, [download the latest archive](https://github.com/ModOrganizer2/modorganizer-basic_games/archive/master.zip) and extract the files
23-
in the existing `basic_games` folder, overwriting existing files.
16+
Basic games is included in Mod Organizer 2.4, if you want to use new game plugins that
17+
have not been included in the release,
18+
[download the latest archive](https://github.com/ModOrganizer2/modorganizer-basic_games/archive/master.zip)
19+
and extract the files in the existing `basic_games` folder, overwriting existing files.
2420

2521
**Important:** Extract the *folder* in your `plugins` folder, not the individual files. Your
2622
`plugins` folder should look like this:
@@ -88,150 +84,4 @@ You can rename `modorganizer-basic_games-xxx` to whatever you want (e.g., `basic
8884

8985
## How to add a new game?
9086

91-
You can create a plugin by providing a python class in the `games` folder.
92-
93-
**Note:** If your game plugin does not load properly, you should set the log level
94-
to debug and look at the `mo_interface.log` file.
95-
96-
You need to create a class that inherits `BasicGame` and put it in a `game_XX.py` in `games`.
97-
Below is an example for The Witcher 3 (see also [games/game_witcher3.py](games/game_witcher3.py)):
98-
99-
```python
100-
from PyQt6.QtCore import QDir
101-
from ..basic_game import BasicGame
102-
103-
104-
class Witcher3Game(BasicGame):
105-
106-
Name = "Witcher 3 Support Plugin"
107-
Author = "Holt59"
108-
Version = "1.0.0a"
109-
110-
GameName = "The Witcher 3"
111-
GameShortName = "witcher3"
112-
GameBinary = "bin/x64/witcher3.exe"
113-
GameDataPath = "Mods"
114-
GameSaveExtension = "sav"
115-
GameSteamId = 292030
116-
117-
def savesDirectory(self):
118-
return QDir(self.documentsDirectory().absoluteFilePath("gamesaves"))
119-
```
120-
121-
`BasicGame` inherits `IPluginGame` so you can override methods if you need to.
122-
Each attribute you provide corresponds to a method (e.g., `Version` corresponds
123-
to the `version` method, see the table below). If you override the method, you do
124-
not have to provide the attribute:
125-
126-
```python
127-
from PyQt6.QtCore import QDir
128-
from ..basic_game import BasicGame
129-
130-
import mobase
131-
132-
133-
class Witcher3Game(BasicGame):
134-
135-
Name = "Witcher 3 Support Plugin"
136-
Author = "Holt59"
137-
138-
GameName = "The Witcher 3"
139-
GameShortName = "witcher3"
140-
GameBinary = "bin/x64/witcher3.exe"
141-
GameDataPath = "Mods"
142-
GameSaveExtension = "sav"
143-
GameSteamId = 292030
144-
145-
def version(self):
146-
# Don't forget to import mobase!
147-
return mobase.VersionInfo(1, 0, 0, mobase.ReleaseType.final)
148-
149-
def savesDirectory(self):
150-
return QDir(self.documentsDirectory().absoluteFilePath("gamesaves"))
151-
```
152-
153-
### List of valid keys
154-
155-
| Name | Description | `IPluginGame` method | Python |
156-
|------|-------------|----------------------|--------|
157-
| Name | Name of the plugin | `name` | `str` |
158-
| Author | Author of the plugin | `author` | `str` |
159-
| Version | Version of the plugin | `version` | `str` or `mobase.VersionInfo` |
160-
| Description| Description (Optional) | `description` | `str` |
161-
| GameName | Name of the game, as displayed by MO2 | `gameName` | `str` |
162-
| GameShortName | Short name of the game | `gameShortName` | `str` |
163-
| GameNexusName| Nexus name of the game (Optional, default to `GameShortName`) | `gameNexusName` | `str` |
164-
| GameValidShortNames | Other valid short names (Optional) | `validShortNames` | `List[str]` or comma-separated list of values |
165-
| GameNexusId | Nexus ID of the game (Optional) | `nexusGameID` | `str` or `int` |
166-
| GameBinary | Name of the game executable, relative to the game path | `binaryName` | `str` |
167-
| GameLauncher | Name of the game launcher, relative to the game path (Optional) | `getLauncherName` | `str` |
168-
| GameDataPath | Name of the folder containing mods, relative to game folder| `dataDirectory` | |
169-
| GameDocumentsDirectory | Documents directory (Optional) | `documentsDirectory` | `str` or `QDir` |
170-
| GameIniFiles | Config files in documents, for profile specific config (Optional) | `iniFiles` | `str` or `List[str]` |
171-
| GameSavesDirectory | Directory containing saves (Optional, default to `GameDocumentsDirectory`) | `savesDirectory` | `str` or `QDir` |
172-
| GameSaveExtension | Save file extension (Optional) `savegameExtension` | `str` |
173-
| GameSteamId | Steam ID of the game (Optional) | `steamAPPId` | `List[str]` or `str` or `int` |
174-
| GameGogId | GOG ID of the game (Optional) | `gogAPPId` | `List[str]` or `str` or `int` |
175-
| GameOriginManifestIds | Origin Manifest ID of the game (Optional) | `originManifestIds` | `List[str]` or `str` |
176-
| GameOriginWatcherExecutables | Executables to watch for Origin DRM (Optional) | `originWatcherExecutables` | `List[str]` or `str` |
177-
| GameEpicId | Epic ID (`AppName`) of the game (Optional) | `epicAPPId` | `List[str]` or `str` |
178-
| GameEaDesktopId | EA Desktop ID of the game (Optional) | `eaDesktopContentId` | `List[str]` or `str` or `int` |
179-
180-
You can use the following variables for `str`:
181-
182-
- `%DOCUMENTS%` will be replaced by the standard *Documents* folder.
183-
- `%GAME_PATH%` will be replaced by the path to the game folder.
184-
- `%GAME_DOCUMENTS%` will be replaced by the value of `GameDocumentsDirectory`.
185-
186-
## Extra features
187-
188-
The meta-plugin provides some useful extra feature:
189-
190-
1. **Automatic Steam, GOG, Origin, Epic Games and EA Desktop detection:** If you provide
191-
Steam, GOG, Origin or Epic IDs for the game (via `GameSteamId`, `GameGogId`,
192-
`GameOriginManifestIds`, `GameEpicId` or `GameEaDesktopId`), the game will be listed
193-
in the list of available games when creating a new MO2 instance (if the game is
194-
installed via Steam, GOG, Origin, Epic Games / Legendary or EA Desktop).
195-
2. **Basic save game preview / metadata** (Python): If you can easily obtain a picture
196-
(file) and/or metadata (like from json) for any saves, you can provide basic save-game
197-
preview by using the `BasicGameSaveGameInfo`. See
198-
[games/game_witcher3.py](games/game_witcher3.py) and
199-
[games/game_bladeandsorcery.py](games/game_bladeandsorcery.py) for more details.
200-
3. **Basic local save games** (Python): profile specific save games, as in [games/game_valheim.py](games/game_valheim.py).
201-
4. **Basic mod data checker** (Python):
202-
Check and fix different mod archive layouts for an automatic installation with the proper
203-
file structure, using simple (glob) patterns via `BasicModDataChecker`.
204-
See [games/game_valheim.py](games/game_valheim.py) and [game_subnautica.py](games/game_subnautica.py) for an example.
205-
206-
Game IDs can be found here:
207-
208-
- For Steam on [Steam Database](https://steamdb.info/)
209-
- For GOG on [GOG Database](https://www.gogdb.org/)
210-
- For Origin from `C:\ProgramData\Origin\LocalContent` (.mfst files)
211-
- For Epic Games (`AppName`) from:
212-
- `C:\ProgramData\Epic\EpicGamesLauncher\Data\Manifests\` (.item files)
213-
- or `C:\ProgramData\Epic\EpicGamesLauncher\UnrealEngineLauncher\LauncherInstalled.dat`
214-
- or [Unofficial EGS ID DB](https://erri120.github.io/egs-db/)
215-
- For Legendary (alt. Epic launcher) via command `legendary list-games`
216-
or from: `%USERPROFILE%\.config\legendary\installed.json`
217-
- For EA Desktop from `<EA Games install location>\<game title>\__Installer\installerdata.xml`
218-
219-
## Contribute
220-
221-
We recommend using a dedicated Python environment to write a new basic game plugins.
222-
223-
1. Install the required version of Python --- Currently Python 3.11 (MO2 2.5).
224-
2. Remove the repository at `${MO2_INSTALL}/plugins/basic_games`.
225-
3. Clone this repository at the location of the old plugin (
226-
`${MO2_INSTALL}/plugins/basic_games`).
227-
4. Place yourself inside the cloned folder and:
228-
229-
```bash
230-
# create a virtual environment (recommended)
231-
py -3.11 -m venv .\venv
232-
.\venv\scripts\Activate.ps1
233-
234-
# "install" poetry and the development package
235-
pip install poetry
236-
poetry install
237-
```
87+
See [CONTRIBUTING](./CONTRIBUTING.md).

0 commit comments

Comments
 (0)