Skip to content

Commit 52f4e79

Browse files
* Begin port * Update to beta 10 (Les-Moddeurs-Francais#60) * Update to beta 13 * Begin port * Try to rename current version (I want to die) * Oh yes sir, It's working ! * Verification of pages and links
1 parent 519deaf commit 52f4e79

35 files changed

+1810
-9
lines changed

docs/bases/installation.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ tags: [bases]
77

88
# Installation de la workspace
99

10-
- Installez Java 16 Development Kit (JDK) en suivant l'un de ces 3 liens : **[Oracle](https://www.oracle.com/java/technologies/javase-jdk16-downloads.html)** OU **[Zulu](https://www.azul.com/downloads/?version=java-16-sts&package=jdk-fx)** OU **[Adoptium](https://adoptium.net/?variant=openjdk16&jvmVariant=hotspot)**. Minecraft et MinecraftForge depuis la 1.17 sont compilés sous Java 16.
10+
- Installez Java 17 Development Kit (JDK) en suivant l'un de ces 3 liens : **[Oracle](https://www.oracle.com/java/technologies/javase-jdk16-downloads.html)** OU **[Zulu](https://www.azul.com/downloads/?version=java-16-sts&package=jdk-fx)** OU **[Adoptium](https://adoptium.net/?variant=openjdk16&jvmVariant=hotspot)**. Minecraft et MinecraftForge depuis la 1.18 sont compilés sous Java 17.
1111
- Installez le Mod Development Kit (MDK) en suivant ce [lien](https://files.minecraftforge.net/).
1212
- Extrayez tous les fichiers et dossiers contenus dans le dossier compressé dans un nouveau dossier (ceci sera votre dossier de mod).
1313
- Selon votre IDE:

docs/register/deferred.md

-3
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,10 @@ Quelques explications :
3838
- SCHEDULES
3939
- ACTIVITIES
4040
- WORLD_CARVERS
41-
- SURFACE_BUILDERS
4241
- FEATURES
43-
- DECORATORS
4442
- CHUNK_STATUS
4543
- STRUCTURE_FEATURES
4644
- BLOCK_STATE_PROVIDER_TYPES
47-
- BLOCK_PLACER_TYPES
4845
- FOLIAGE_PLACER_TYPES
4946
- TREE_DECORATOR_TYPES
5047
- BIOMES

docusaurus.config.js

+26-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,19 @@
11
const lightCodeTheme = require('prism-react-renderer/themes/github');
22
const darkCodeTheme = require('prism-react-renderer/themes/dracula');
3+
const versions = require('./versions.json');
4+
5+
function getNextVersionName() {
6+
const expectedPrefix = '1.1';
7+
8+
const lastReleasedVersion = versions[0];
9+
if (!lastReleasedVersion.includes(expectedPrefix)) {
10+
throw new Error(
11+
'this code is only meant to be used during the 2.0 beta phase.',
12+
);
13+
}
14+
const version = parseInt(lastReleasedVersion.replace(expectedPrefix, ''), 10);
15+
return `${expectedPrefix}${version + 1}`;
16+
}
317

418
/** @type {import('@docusaurus/types').DocusaurusConfig} */
519
module.exports = {
@@ -28,6 +42,11 @@ module.exports = {
2842
label: 'Documentation',
2943
},
3044
{to: '/news', label: 'News', position: 'left'},
45+
{
46+
type: 'docsVersionDropdown',
47+
position: 'right',
48+
dropdownActiveClassDisabled: true,
49+
},
3150
{
3251
href: 'https://github.com/Les-Moddeurs-Francais/Forge-Doc',
3352
label: 'GitHub',
@@ -118,13 +137,19 @@ module.exports = {
118137
},
119138
presets: [
120139
[
121-
'@docusaurus/preset-classic',
140+
'classic',
122141
{
123142
docs: {
124143
sidebarPath: require.resolve('./sidebars.js'),
125144
editUrl:
126145
'https://github.com/Les-Moddeurs-Francais/Forge-Doc/edit/master',
127146
showLastUpdateAuthor: true,
147+
lastVersion: 'current',
148+
versions: {
149+
current: {
150+
label: `${getNextVersionName()}`,
151+
},
152+
},
128153
},
129154
blog: {
130155
blogTitle: 'News',

i18n/fr/docusaurus-plugin-content-docs/current.json

-4
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,4 @@
11
{
2-
"version.label": {
3-
"message": "Next",
4-
"description": "The label for version current"
5-
},
62
"sidebar.tutorialSidebar.category.Bases": {
73
"message": "Bases",
84
"description": "The label for category Bases in sidebar tutorialSidebar"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"label": "Avancé",
3+
"link": {
4+
"type": "generated-index",
5+
"title": "Avancé",
6+
"description": "Tous ce qu'il y a à savoir sur les sujets avancé de l'API MinecraftrtForge.",
7+
"slug": "/category/advanced"
8+
},
9+
"position": 13
10+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
---
2+
sidebar_position: 1
3+
title: Access Transformer
4+
description: Comment utiliser les access transformers ?
5+
tags: [avancé]
6+
---
7+
8+
Les `access transformers` (ou AT) permettent de modifier l'accessibilité et la visibilité des variables, méthodes et classes des librairies (retirer le `final`, changer l'attribut `private` en `public`, etc...).
9+
10+
## Ajout du fichier pour les AT's
11+
Pour spécifier à ForgeGradle que le mod utilisera les access transformers, vous devez ajouter cette ligne dans le build.gradle (la catégorie `minecraft` est normalement déjà présente dans votre fichier) :
12+
```
13+
minecraft {
14+
accessTransformer = file('src/main/resources/META-INF/accesstransformer.cfg')
15+
}
16+
```
17+
18+
Après cela, vous devrez créer un fichier `accesstransformer.cfg` au niveau du chemin spécifié.
19+
20+
Pour appliquer les `access trasnformers` après une modification du fichier, vous devrez rafraichir le projet gradle.
21+
22+
## Commentaires
23+
24+
Tous les textes succédant un `#` avant la fin de la ligne seront transcrits comme des commentaires et ne seront pas pris en compte.
25+
26+
## Les modifieurs d'accès
27+
28+
Les modificateurs d'accès spécifient vers quelle nouvelle visibilité la cible donnée sera transformée. Par ordre décroissant de visibilité :
29+
- `public` - visible pour toutes les classes à l'intérieur et à l'extérieur de son package
30+
- `protected` - visible uniquement pour les classes à l'intérieur du package et les sous-classes
31+
- `default` - visible uniquement pour les classes à l'intérieur du package
32+
- `private` - visible uniquement à l'intérieur de la classe
33+
34+
Le modificateur spécial +f et -f peut être ajouté aux modificateurs mentionnés plus haut afin d'ajouter ou de supprimer l'attribut `final`.
35+
36+
## Obtenir les access transformers
37+
38+
Pour obtenir les access transformers, vous pouvez rejoindre le [discord](https://discord.gg/UvedJ9m) de Forge, vous rendre dans le channel bot-commands et utiliser ces 3 commandes (ceci concerne les mappings officiels) :
39+
- `!mojf` suivi du nom de la variable (et cela peut être précédé du nom de la classe suivie d'un point pour plus de précisions, ex : `Block.harvestLevel`) pour obtenir la ligne d'access transformer correspondante.
40+
- `!mojm` suivi du nom de la fonction (et cela peut être précédé du nom de la classe suivie d'un point pour plus de précisions, ex : `Block.asBlock`) pour obtenir la ligne d'access transformer correspondante.
41+
- `!mojc` suivi du nom de la classe pour obtenir la ligne d'access transformer correspondante.
42+
43+
## Exemples
44+
45+
```
46+
# Définis la visibilité de la méthode en public
47+
public net.minecraft.data.loot.BlockLoot m_124254_(Lnet/minecraft/world/level/block/Block;Lnet/minecraft/world/item/Item;)Lnet/minecraft/world/level/storage/loot/LootTable$Builder; # createStemDrops
48+
49+
# Définis la visibilité de la variable en protected
50+
protected net.minecraft.client.gui.Gui f_168670_ # LINE_HEIGHT
51+
52+
# Définis la visibilité de la classe en protected
53+
protected net.minecraft.client.gui.screens.MenuScreens
54+
```
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,238 @@
1+
---
2+
sidebar_position: 2
3+
title: Dist Executor
4+
description: Comment utiliser les dist executors ?
5+
tags: [avancé]
6+
---
7+
8+
## Introduction
9+
Le système de `Dist Executor` est une API efficace fournie par **FML** située dans le projet `fmlcore` permettant de gérer le code ne devant s'exécuter que sur une `Dist` particulière. Ce système a été ajouté en remplacement du système de `SidedProxy`, présent lors des anciennes versions de **Forge** (1.12.2 et avant).
10+
11+
12+
## C'est quoi une `Dist` ?
13+
Une `Dist` représente sur quel "côté", sur quel distribution de Minecraft doit s'exécuter ce code. Ces distributions sont représentées dans l'énumération `net.minecraftforge.api.distmarker.Dist`. Aujourd'hui, il existe 2 distributions :
14+
- `CLIENT` : La distribution du client. Il s'agit du client avec lequel les joueurs jouent. Il gère la partie rendu/graphique du jeu.
15+
- `DEDICATED_SERVER` : La distribution du serveur dédié. Il s'agit de la distribution réservée aux serveurs. Il gère le monde ainsi que quelques éléments logiques, et communique avec le client via le réseau. Il ne contient aucun élément visuel du jeu.
16+
17+
:::caution
18+
La distribution `DEDICATED_SERVER` n'est pas utilisée lors de l'exécution du serveur intégré lancé en solo.
19+
:::
20+
21+
22+
## L'annotation `@OnlyIn`
23+
L'annotation `@OnlyIn` permet d'indiquer à **FML** de charger ou non le membre annoté en fonction de la `Dist` spécifiée en paramètre. Tout comme l'énumération `Dist`, elle se situe dans le package `net.minecraftforge.api.distmarker`. Elle peut-être utilisée sur les classes, les champs, les méthodes, les constructeurs, les packages et les annotations. Pour information, cette annotation est traitée dans la classe `RuntimeDistCleaner` du projet `fmlloader`. L'annotation `@OnlyIns` ne sera pas traité dans ce tutoriel.
24+
25+
Si on tente d'appeler un membre depuis une autre `Dist`, le membre sera considéré comme inexistant et des erreurs comme `NoSuchFieldError`, `NoSuchMethodError` ou encore `ClassNotFoundException` peuvent survenir en fonction du type du membre.
26+
27+
Par exemple :
28+
```java
29+
package fr.lmf.distexecutor;
30+
31+
import net.minecraftforge.api.distmarker.Dist;
32+
import net.minecraftforge.api.distmarker.OnlyIn;
33+
34+
@OnlyIn(Dist.CLIENT)
35+
public class OnlyClientClass {
36+
37+
private Object aField;
38+
39+
public void aMethod() {
40+
// do something
41+
}
42+
}
43+
```
44+
45+
La classe ne sera chargée que sur le client. Si elle est appelée sur le serveur, une erreur sera propagée.
46+
47+
En revanche, une même classe par exemple peut contenir des membres reliés à des `Dist`s différentes.
48+
Exemple :
49+
```java
50+
package fr.lmf.distexecutor;
51+
52+
import net.minecraftforge.api.distmarker.Dist;
53+
import net.minecraftforge.api.distmarker.OnlyIn;
54+
55+
public class SimpleClass {
56+
57+
@OnlyIn(Dist.CLIENT)
58+
private Object aField;
59+
60+
@OnlyIn(Dist.DEDICATED_SERVER)
61+
public void aMethod() {
62+
// do something
63+
}
64+
}
65+
```
66+
67+
Ici, la classe sera chargée, quelque soit la distribution, mais le field `aField` sera inexistant sur serveur et de même pour la méthode `aMethod` sur le client. Si nous exécutons `System.out.println(this.aField);` dans la méthode `aMethod`, le jeu plantera.
68+
69+
70+
## La classe `DistExecutor`
71+
Maintenant, vous aimeriez peut-être savoir comment appeler une classe, une méthode ou quoi que ce soit en fonction de la `Dist` pour éviter les erreurs évoquées plus haut ?
72+
Utiliser la reflection pour voir si la classe `net.minecraft.client.Minecraft` (uniquement présente sur le client) existe serait une solution ; hélas les limitations de **FML** nous en empêche : une erreur est propagée et ferme le jeu automatiquement avant même que nouis puissons exécuter du code. De toute façon, ce n'est pas la méthode propre et recommandée que nous recommande **Forge**.
73+
74+
La classe `DistExecutor` entre maintenant en jeu. Elle se situe dans le package `net.minecraftforge.fml` du projet `fmlcore`. Elle possède quelques méthodes statiques utilitaires qui peuvent répondr à notre problématique.
75+
Nous nous intéresserons pour le moment qu'aux méthodes `(un)safeRunForDist` et `(un)safeRunWhenOn`. Libre à vous de lire la JavaDoc disponible dans la classe pour connaître l'utilité de chaque méthode. Veillez à ne pas utiliser - du moins le moins possible - les méthodes annotées avec l'annotation `@Deprecated`.
76+
77+
:::caution
78+
Les méthodes `unsafe` n'exécutent pas certaines vérifications que les méthodes `safe` appliquent à l'exécution du jeu. Nonobstant, ces vérifications ne sont pas appliquées en production, quand vous lancer le jeu depuis un launcher par exemple. Vous pouvez donc avoir un plantage en lançant le jeu depuis un environnement de développement, et pas en lançant votre jeu de manière classique. Enfin, les méthodes `unsafe` ne peuvent prévenir de certaines erreurs comme les `ClassCastException`.
79+
:::
80+
81+
### La méthode `(un)safeRunForDist`
82+
La méthode `(un)safeRunForDist` permet de retourner une instance de la classe demandée en paramètre en fonction de la `Dist`. Par exemple, un système de "proxy" est facilement reproductible grâce à cette méthode :
83+
```java
84+
package fr.lmf.distexecutor;
85+
86+
public interface SidedManager {
87+
void init();
88+
}
89+
```
90+
91+
Cette interface va nous permettre de définir un membre commun entre nos `Manager`s : un pour le client, et l'autre pour le serveur. Voici un exemple d'implémentation pour le client :
92+
```java
93+
package fr.lmf.distexecutor.client;
94+
95+
import fr.lmf.distexecutor.SidedManager;
96+
import net.minecraftforge.api.distmarker.Dist;
97+
import net.minecraftforge.api.distmarker.OnlyIn;
98+
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
99+
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
100+
101+
@OnlyIn(Dist.CLIENT)
102+
public class ClientManager implements SidedManager {
103+
104+
@Override
105+
public void init() {
106+
FMLJavaModLoadingContext.get().getModEventBus().addListener(this::clientSetup);
107+
}
108+
109+
public void clientSetup(FMLClientSetupEvent event) {
110+
// do something at client startup
111+
}
112+
}
113+
```
114+
En voici une autre pour le serveur :
115+
```java
116+
package fr.lmf.distexecutor.server;
117+
118+
import fr.lmf.distexecutor.SidedManager;
119+
import net.minecraftforge.api.distmarker.Dist;
120+
import net.minecraftforge.api.distmarker.OnlyIn;
121+
import net.minecraftforge.common.MinecraftForge;
122+
import net.minecraftforge.eventbus.api.SubscribeEvent;
123+
import net.minecraftforge.fmlserverevents.FMLServerStartedEvent;
124+
125+
@OnlyIn(Dist.DEDICATED_SERVER)
126+
public class ServerManager implements SidedManager
127+
{
128+
@Override
129+
public void init() {
130+
MinecraftForge.EVENT_BUS.register(this);
131+
}
132+
133+
@SubscribeEvent
134+
public void onServerStart(FMLServerStartedEvent event) {
135+
// do something at server startup
136+
}
137+
}
138+
```
139+
Enfin, il faudra exécuter la bonne méthode `init` au démarrage du mod. La méthode `(un)safeRunForDist` prend 2 paramètres à signature identiques : un [`Supplier`](https://docs.oracle.com/en/java/javase/16/docs/api/java.base/java/util/function/Supplier.html) d'un `(Safe)Supplier` de votre classe cible (ici `ClientManager` ou `ServerManager`). Un `SafeSupplier` est une interface fournie par **FML** étandant `Supplier` et `SafeReferent`. Un `SafeReferent` est une interface elle aussi fournie par **FML** qui va subir des vérifications et propager une erreur si il n'est pas jugé "safe". Les méthodes `unsafe` ne demandent pas de `SafeSupplier`, remplacé par un `Supplier` classique.
140+
141+
```java
142+
package fr.lmf.distexecutor;
143+
144+
import fr.lmf.distexecutor.client.ClientManager;
145+
import fr.lmf.distexecutor.server.ServerManager;
146+
import net.minecraftforge.fml.DistExecutor;
147+
import net.minecraftforge.fml.common.Mod;
148+
149+
@Mod("distexecutorexample")
150+
public class DistExecutorMod {
151+
152+
// some fields and constants
153+
154+
public DistExecutorMod() {
155+
// do something
156+
var manager = DistExecutor.unsafeRunForDist(() -> ClientManager::new, () -> ServerManager::new);
157+
manager.init();
158+
// do something
159+
}
160+
161+
// other methods
162+
}
163+
```
164+
165+
:::tip
166+
Notez l'utilisation du mot-clé `var`, introduit dans **Java** depuis la version 10. Il détectera automatiquement le type commun de nos deux classes, ici `SidedManager`. Nous avons donc accès aux méthodes dans cette classe, soit `init` dans le cadre de l'exemple, libre à vous d'en rajouter autant que vous voulez pour les usages de votre choix.
167+
:::
168+
169+
### La méthode `(un)safeRunWhenOn`
170+
Voici une seconde méthode qui fonctionne un peu différemment, rassurez vous, vous n'avez pas besoin de tout recommencer, gardez vos classes `ClientManager` et `ServerManager`, vous allez en avoir besoin.
171+
172+
La méthode `(un)safeRunWhenOn` fonctionne différemment, déjà, elle ne prend pas un ensemble de `Supplier`, mais une `Dist` en premier paramètre et un `Supplier` d'un objet `(Safe)Runnable` (en fonction de si vous utilisez la méthode safe ou unsafe). Si la `Dist` fournie en paramètre correspond à la distribution actuelle, le code contenu dans l'objet `(Safe)Runnable` sera exécuté. Par exemple, voici un code qui affichera dans la console "Bonjour depuis le client" sur le client et "Bonjour depuis le serveur" sur le serveur :
173+
174+
```java
175+
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> System.out.println("Bonjour depuis le client"));
176+
DistExecutor.unsafeRunWhenOn(Dist.DEDICATED_SERVER, () -> () -> System.out.println("Bonjour depuis le serveur"));
177+
```
178+
179+
Jusqu'ici, nos deux `Manager`s avait la même méthode en commun, appelée au même moment. En revanche, vous aimeriez pouvoir être plus libre dans l'utilisation de vos `Manager`s en ajoutant des méthodes indépendantes et pouvant être appelées un peu partout comme pouvoir démarrer une base de donnée depuis le serveur, ou alors ouvrir un écran depuis le client...
180+
181+
On considère une méthode `foo(String)` dans `ClientManager` et une méthode `bar(int)` dans `ServerManager`. Effectivement, polymorphisme et héritage ici ne seront pas utiles. Une solution est de déclarer 2 fields publiques et statiques (ou alors privé, avec un accesseur), un pour le `ClientManager` et l'autre pour le `ServerManager`, de les initialiser chacun à l'aide de la méthode `(un)safeRunWhenOn`. Puis ensuite de les appeler quand bon vous semble dans une classe elle-même annotée `@OnlyIn` avec la `Dist` correspondante, ou bien en utilisant à nouveau la méthode `(un)safeRunWhenOn`.
182+
183+
Vous pouvez également profiter de l'interface `SidedManager` créée plus tôt pour donner un accès sûr aux méthodes communes et publiques des deux `Manager`s :
184+
```java
185+
package fr.lmf.distexecutor;
186+
187+
import fr.lmf.distexecutor.SidedManager;
188+
import fr.lmf.distexecutor.client.ClientManager;
189+
import fr.lmf.distexecutor.server.ServerManager;
190+
import net.minecraftforge.api.distmarker.Dist;
191+
import net.minecraftforge.api.distmarker.OnlyIn;
192+
import net.minecraftforge.fml.DistExecutor;
193+
import net.minecraftforge.fml.common.Mod;
194+
195+
@Mod("distexecutorexample")
196+
public class DistExecutorMod {
197+
198+
@OnlyIn(Dist.CLIENT)
199+
private static ClientManager clientManager;
200+
201+
@OnlyIn(Dist.DEDICATED_SERVER)
202+
private static ServerManager serverManager;
203+
204+
private static SidedManager currentManager;
205+
206+
public DistExecutorMod() {
207+
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> {
208+
clientManager = new ClientManager();
209+
clientManager.foo("foobar");
210+
});
211+
DistExecutor.unsafeRunWhenOn(Dist.DEDICATED_SERVER, () -> () -> {
212+
serverManager = new ServerManager();
213+
serverManager.bar(0);
214+
});
215+
currentManager = DistExecutor.unsafeRunForDist(() -> DistExecutorMod::getClientManager, () -> DistExecutorMod::getServerManager);
216+
currentManager.init();
217+
}
218+
219+
@OnlyIn(Dist.CLIENT)
220+
public static ClientManager getClientManager() {
221+
return clientManager;
222+
}
223+
224+
@OnlyIn(Dist.DEDICATED_SERVER)
225+
public static ServerManager getServerManager() {
226+
return serverManager;
227+
}
228+
229+
public static SidedManager getCurrentManager() {
230+
return currentManager;
231+
}
232+
}
233+
```
234+
235+
## Conclusion
236+
Vous savez maintenant vous servir de l'annotation `@OnlyIn` et de la classe `DistExecutor`. Vous êtes au courant des erreurs qui peuvent survenir si vous utilisez de manière incorrecte ces classes et que vous appelez de manière non vérifiée des membres présent sur une seule distribution du client.
237+
238+
Ce n'est pas une notion évidente, c'est pour ça que j'ai essayé d'être le plus clair et concis et de donner quelques exemples et quelques tips. Toutefois il existe évidemment d'autres manières d'utiliser ces outils pratique. Ne vous découragez pas au moindre plantage et faites attention à ce que vous appelez.

0 commit comments

Comments
 (0)