Résolu Creation d'un fog sous l'eau mais le fog ne change pas
-
Bonjour,
Je suis nouveau dans le développement de mod (j’ai une expérience préalable en plugin, mais les mods offrent une plus grande possibilité de customisation pour mon serveur :beaming_face_with_smiling_eyes: )
Je suis en train de développer actuellement un mod aquatique qui a pour but de changer le fog quand le joueur est sous l’eau.
Pour ce faire, j’ai trouver ce post : https://www.minecraftforum.net/forums/mapping-and-modding-java-edition/minecraft-mods/modification-development/2345547-how-to-change-fog-color
Qui ramène vers ce code sur github : https://github.com/lawremi/PerFabricaAdAstra/blob/master/src/main/java/org/pfaa/chemica/client/fluid/FogHandler.javaEn m’inspirant un peut du code github j’ai réussi à pondre ce code :
public class FogCreation { public static FogCreation instance = new FogCreation(); private FogCreation() { } private boolean isUnderWater(Entity entity) { return entity.getEntityWorld().getBlockState(new BlockPos(entity.getPosition().getX(), entity.getPosition().getY() + 1, entity.getPosition().getZ())).getMaterial().isLiquid(); } @SubscribeEvent @SideOnly(Side.CLIENT) public void onFogColors(EntityViewRenderEvent.FogColors event) { Entity entity = event.getEntity(); System.out.println(isUnderWater(entity)); if (isUnderWater(entity)) { event.setRed(0); event.setBlue(155); event.setGreen(50); } } @SubscribeEvent @SideOnly(Side.CLIENT) public void onFogDensity(EntityViewRenderEvent.FogDensity event) { if (isUnderWater(event.getEntity())) { event.setDensity(0.5F); event.setCanceled(true); } } }
Le problème est que le fog vient de façon random quand je suis sous l’eau (au lieu de venir instantanément quand je rentre dans l’eau):
J’arrive sous l’eau, je bouge un peut puis au bout d’un moment random passé sous l’eau, le fog que j’ai setup aparait, puis disparait bien quand je sors de l’eau.Je pensais que mon bug venait de la fonction “isUnderWater”, mais avec le print a la ligne 18, j’ai remarqué que “true” est spammer dans la console donc mon changement de fog arrive bien pourtant rien ne se passe à l’écrant
Voici comment je register mon fog event:
// register fog MinecraftForge.EVENT_BUS.register(FogCreation.instance);
En éspérant que quelqu’un pourrait m’aider avec ça.
-
Après mon post j’ai essayer un nouvel axe de recherche:
Je me suis dit que vu que minecraft a un peut le même Event, du coup ma théorie est que ça doit être une question de priorité:
Mon Event est appellé à un certain moment, et celui de minecraft est appeler également, donc minecraft vient “override” mes couleurs car est appelée après, et donc, c’est pour ça que de façon random ma couleur apparait parfois et parfois non.J’ai donc essayer de changer la priorité de mes événements:
Je les ai tous les deux passer en HIGHEST puis en LOWEST, pourtant ça ne marche toujours pas (je crois même qu’en changeant la prioritée, mon fog n’apparait pas du tout). -
Bonsoir,
N’ayant plus d’espace de travail 1.12.2 sous la main je ne peux pas regarder de mon côté, en revanche je peux te proposer la piste suivante :
Utilises ton IDE pour chercher où l’événementEntityViewRenderEvent.FogColors
est déclenché et regarde ce que fais ensuite le code de base de Minecraft.Cela te permettra de vérifier ta théorie.
Le système de priorité ne permet que de passé avant ou après les autres fonctions écoutant sur le même événements, donc avant ou après les autres mods utilisant l’événement, et non après le code de Minecraft, qui n’utilise pas l’événement. -
@robin4002
Bonjour,Merci beaucoup, je n’ai pas le reflexe d’aller regarder les sources x)
Du coup pour comprendre ce qui ce passe, j’ai lancer mon debugger en allant plus loins que ce que j’ai l’habitude de faire (normallement je m’arrete a mon code et je skip les sources code en me disant qu’ils ne peuvent pas avoir de bug).
Mais en allant plus loin dans l’éxécution je me suis rendu compte de plusieurs problèmes avec mon code:
Déjà la valeur attendu pour le RGB est flottante, donc il faut une valeur entre 0 et 1. Mais après avoir fix ça, j’ai toujours eu le même problème (exactement pareil).
Du coup en m’enfonçant d’avantage dans les fin fond de forge, je me suis rendu compte qu’après l’appel de l’event, dans la classe EntityRenderer, il y a le alpha qui aparait et est à 0.
Donc j’ai remarquer mon soucis:
En reprenant le code: https://github.com/lawremi/PerFabricaAdAstra/blob/master/src/main/java/org/pfaa/chemica/client/fluid/FogHandler.java
J’ai pas mis le truc à la ligne 42 (GL11.glFogi(GL11.GL_FOG_MODE, GL11.GL_EXP);)
J’avais pas compris ce qu’est GL11 si quelqu’un pourrait m’expliquer ^^
Mais il faut le mettre sinon mon fog n’apparait pas.
Mais je peux pas mettre en résolu, car j’ai un nouveau bug :
Lorsque l’utilisateur entre dans l’eau et sort rapidement, parfois (très rarement), la densité de mon fog reste et il y’a un fog blanc moche qui apparait et qui reste tout le temps
Je pense que quand il sort de l’eau il faudrait que je remette le truc de GL11 correctement, mais je ne sais pas comment faire il y’a plein de constantes bizard dans la classe source (je veux juste faire mon fog moi :crying_face: )
Voici mon code après les différents fix:
public class FogCreation { public static FogCreation instance = new FogCreation(); private FogCreation() { } private boolean isUnderWater(Entity entity) { return entity.getEntityWorld().getBlockState(new BlockPos(entity.getPosition().getX(), entity.getPosition().getY() + 1, entity.getPosition().getZ())).getMaterial().isLiquid(); } @SubscribeEvent @SideOnly(Side.CLIENT) public void onFogColors(EntityViewRenderEvent.FogColors event) { Entity entity = event.getEntity(); if (isUnderWater(entity)) { event.setRed(0f); event.setBlue(0f); event.setGreen(0.5f); } } @SubscribeEvent @SideOnly(Side.CLIENT) public void onFogDensity(EntityViewRenderEvent.FogDensity event) { if (isUnderWater(event.getEntity())) { event.setDensity(0.5F); GL11.glFogi(GL11.GL_FOG_MODE, GL11.GL_EXP); event.setCanceled(true); } } }
Si quelqu’un pourrait m’aider à fix le bug du fog blanc sa serait cool
Edit: Après quelques nouveaux tests, je me suis rendu compte que le fog blanc moche apparait que quand je sort de l’eau lentement.
-
GL11 c’est une classe de la bibliothèque LWJGL qui est un wrapper pour OpenGL en Java.
Et OpenGL est un API qui permet d’envoyer des ordres à la carte graphique.Par contre je ne sais pas comment régler ton problème
Espérons que d’autres personnes, expérimenté sur la question passent par là ! -
@robin4002 D’accord, merci
-
Salut, je pense avoir repéré les erreurs dans ta classe, je les ai corrigé et je me suis permis d’apporter quelques optimisations :
public final class FogCreation { public static FogCreation instance = new FogCreation(); private FogCreation() { } private boolean isUnderWater(Entity entity, float partialTicks) { return ActiveRenderInfo.getBlockStateAtEntityViewpoint(entity.world, entity, partialTicks).getMaterial() == Material.WATER; } @SubscribeEvent @SideOnly(Side.CLIENT) public void onFogColors(EntityViewRenderEvent.FogColors event) { if(this.isUnderWater(event.getEntity(), (float)event.getRenderPartialTicks())) { event.setRed(0.0F); event.setGreen(0.5F); event.setBlue(0.0F); } } @SubscribeEvent @SideOnly(Side.CLIENT) public void onFogDensity(EntityViewRenderEvent.FogDensity event) { if(this.isUnderWater(event.getEntity(), (float)event.getRenderPartialTicks())) { event.setDensity(0.5F); GlStateManager.glFogi(GL11.GL_FOG_MODE, GL11.GL_EXP); } } }
N’hésite pas à revenir si ça ne marche pas, la 1.12.2 c’est un peu vieux et ça fait longtemps que je n’en ai pas fait.
-
@twiguinou Bonjour,
Merci beaucoup de ta réponse, le fog marche parfaitement !
Juste j’essaye actuelement de comprendre ton code et j’aurrais quelque questions si ça ne te dérange pas d’y répondre ou de m’aiguiller vers quelque chose qui m’aidera à comprendre ^^
Je regarde la fonction “getBlockStateAtEntityViewpoint”, après avoir vu le code source, j’ai compris que sa permet d’obtenir l’état d’un block pile au niveau des yeux de l’entité. Mais j’ai deux questions :
- Comment t’arrive à sortir cette fonction ? J’ai l’impression qu’elle est un peut cacher au fin fond de l’API forge et en plus elle n’est pas documenter
- Elle a un argument sombre qui est un float (il est nommer p_186703_2_) comment tu as compris qu’il fallait y mettre “event.getRenderPartialTicks()” et a quoi correspond le event.getRenderPartialTicks() (il n’y a rien d’écrit à ce propos dans la documentation).
Aussi pour le GlStateManager:
- Comment t’a fait pour la sortir également alors qu’il y’a pas de doc et c’est encore plus perdu dans forge que la fonction du dessus xd
- A quoi correspond cette classe ?
- Pourquoi l’utiliser au lieu de GL11 ?
Voilà, je suis désoler d’avoir autant de questions mais actuellement, pour moi, tu as fait de la magie noire xd
-
Bien-sûr ! tu peux essayer de dénicher toutes les fonctionnalités de Minecraft en fouillant tout simplement le code source :
- La classe ActiveRenderInfo est la source du rendu dans le jeu, elle enregistre et distribue les informations sur la position de la caméra et offre quelques méthodes pour en modifier le contenu.
- Ce que l’on appelle les partial ticks dans Forge c’est ce qui permet de synchroniser le rendu client avec le jeu, sans quoi le rendu serait désynchronisé avec ce qui ce passe réellement sur le serveur.
- La classe GlStateManager n’a pas vraiment d’intérêt si tu utilises la fonction glFogi mais elle enregistre, tout comme la classe d’avant, quelques informations sur les types de rendu, l’état général d’OpenGL…
-
@twiguinou D’accord, merci je passe en résolut
-
Bonjour,
Je viens de trouver un nouveau problème liée à ce code
La densité ne change pas.
Pour que la densité change, il faudrait changer le code de la fonction de fog:
@SubscribeEvent @SideOnly(Side.CLIENT) public void onFogDensity(EntityViewRenderEvent.FogDensity event) { if(this.isUnderWater(event.getEntity(), (float)event.getRenderPartialTicks())) { event.setDensity(density); GlStateManager.glFogi(GL11.GL_FOG_MODE, GL11.GL_EXP); event.setCanceled(true); changed = true; } else if (changed) { changed = false; event.setDensity(0.0f); event.setCanceled(true); } }
Avec des event.setCanceled(true) pour que la densite du fog de base de minecraft ne remplace pas mon fog.
J’ai rajouter une variable “changed” pour que lorsqu’il sort de l’eau le fog se remette a la normal. Sa permet d’éviter de call le “reset” à chaque fois, je ne sais pas si c’est une solution qui est la meilleur mais cette magouille fonctionne asser bien ^^