MFF

    Minecraft Forge France
    • Récent
    • Mots-clés
    • Populaire
    • Utilisateurs
    • Groupes
    • Forge Events
      • Automatique
      • Foncé
      • Clair
    • S'inscrire
    • Se connecter

    Créer un item container (type backpack / sac à dos)

    Planifier Épinglé Verrouillé Déplacé Les interfaces (GUI) et les container
    1.7.10
    82 Messages 23 Publieurs 25.6k Vues 1 Watching
    Charger plus de messages
    • Du plus ancien au plus récent
    • Du plus récent au plus ancien
    • Les plus votés
    Répondre
    • Répondre à l'aide d'un nouveau sujet
    Se connecter pour répondre
    Ce sujet a été supprimé. Seuls les utilisateurs avec les droits d'administration peuvent le voir.
    • SCAREXS Hors-ligne
      SCAREX
      dernière édition par

      Envoi le crash report

      Site web contenant mes scripts : http://SCAREXgaming.github.io

      Pas de demandes de support par MP ni par skype SVP.
      Je n'accepte sur skype que l…

      1 réponse Dernière réponse Répondre Citer 0
      • L Hors-ligne
        Laserflip33
        dernière édition par

        Je te l’envoie dès que le serveur recrash

        [Server thread/ERROR] : This crash report has been saved to: /var/directory_serv/servmc_116233/./crash-reports/crash-2015-10-26_12.40.37-server.txt
        [Erreur Java] java.lang.Thread.run(Thread.java:722) [?:1.7.0]
        [Erreur Java] net.minecraft.server.MinecraftServer.run(MinecraftServer.java:646) [MinecraftServer.class:?]
        [Erreur Java] net.minecraft.server.MinecraftServer.func_71217_p(MinecraftServer.java:783) ~[MinecraftServer.class:?]
        [Erreur Java] net.minecraft.server.dedicated.DedicatedServer.func_71190_q(DedicatedServer.java:432) ~[lj.class:?]
        [Erreur Java] net.minecraft.server.MinecraftServer.func_71190_q(MinecraftServer.java:953) ~[MinecraftServer.class:?]
        [Erreur Java] net.minecraft.network.NetworkSystem.func_151269_c(NetworkSystem.java:166) ~s.class:?]
        [Erreur Java] net.minecraft.network.NetHandlerPlayServer.func_147231_a(NetHandlerPlayServer.java:969) ~x.class:?]
        [Erreur Java] net.minecraft.server.management.ServerConfigurationManager.disconnect(ServerConfigurationManager.java:419) ~[ld.class:?]
        [Erreur Java] net.minecraft.world.World.func_72900_e(World.java:1844) ~[afn.class:?]
        [Erreur Java] net.minecraft.entity.player.EntityPlayer.func_70106_y(EntityPlayer.java:1481) ~[xl.class:?]
        [Erreur Java] laserflip33.ordreduphenix.common.ContainerBourseMoke.func_75134_a(ContainerBourseMoke.java:96) ~[ContainerBourseMoke.class:?]
        [Erreur Java] laserflip33.ordreduphenix.common.ContainerBourseMoke.writeToNBT(ContainerBourseMoke.java:47) ~[ContainerBourseMoke.class:?]
        [12:40:37] [Server thread/ERROR] : Encountered an unexpected exception

        1 réponse Dernière réponse Répondre Citer 0
        • L Hors-ligne
          Laserflip33
          dernière édition par

          Et le code de la classe ContainerBourseMoke :

          package laserflip33.ordreduphenix.common;
          
          import net.minecraft.entity.player.EntityPlayer;
          import net.minecraft.entity.player.InventoryPlayer;
          import net.minecraft.inventory.Container;
          import net.minecraft.inventory.Slot;
          import net.minecraft.item.ItemStack;
          import net.minecraft.nbt.NBTTagCompound;
          
          public class ContainerBourseMoke extends Container
          {
          public InventoryBourseMoke invBackpack;
          public int rows;
          
          public ContainerBourseMoke(InventoryPlayer playerInv, InventoryBourseMoke inv) {
          this.invBackpack = inv;
          this.rows = inv.getSizeInventory() / 9;
          int i = (this.rows - 4) * 18;
          int j;
          int k;
          
          // Adding slots to the backpack
          for (j = 0; j < this.rows; ++j) {
          for (k = 0; k < 9; ++k) {
          this.addSlotToContainer(new SlotBourseMoke(inv, k + j * 9, 8 + k * 18, 18 + j * 18));
          }
          }
          
          // Adding player's slots
          for (j = 0; j < 3; ++j) {
          for (k = 0; k < 9; ++k) {
          this.addSlotToContainer(new Slot(playerInv, k + j * 9 + 9, 8 + k * 18, 103 + j * 18 + i));
          }
          }
          
          for (j = 0; j < 9; ++j) {
          this.addSlotToContainer(new Slot(playerInv, j, 8 + j * 18, 161 + i));
          }
          }
          
          @Override
          public boolean canInteractWith(EntityPlayer player) {
          return true;
          }
          
          public void writeToNBT(ItemStack stack) {
          if (!stack.hasTagCompound()) stack.setTagCompound(new NBTTagCompound());
          invBackpack.writeToNBT(stack.getTagCompound());
          }
          
          @Override
          public ItemStack transferStackInSlot(EntityPlayer player, int index) {
          ItemStack itemstack = null;
          Slot slot = (Slot) this.inventorySlots.get(index);
          
          if (slot != null && slot.getHasStack()) {
          ItemStack itemstack1 = slot.getStack();
          itemstack = itemstack1.copy();
          
          // Prevents backpack-ception (backpack inside backpack) with
          // shift-click
          if (itemstack.getItem() instanceof BourseMoke) return null;
          
          if (index < this.invBackpack.getSizeInventory()) {
          if (!this.mergeItemStack(itemstack1, this.invBackpack.getSizeInventory(), this.inventorySlots.size(), true)) return null;
          } else if (!this.mergeItemStack(itemstack1, 0, this.invBackpack.getSizeInventory(), false)) { return null; }
          
          if (itemstack1.stackSize == 0)
          slot.putStack((ItemStack) null);
          else
          slot.onSlotChanged();
          }
          
          return itemstack;
          }
          
          /**
          * @param buttonPressed
          *            left click, right click, wheel click, etc.
          * @param flag
          *            category (e.g.: hotbar keys)
          */
          @Override
          public ItemStack slotClick(int slotIndex, int buttonPressed, int flag, EntityPlayer player) {
          // Prevents from removing current backpack
          if (flag == 2 && buttonPressed == player.inventory.currentItem) return null;
          if (slotIndex - this.invBackpack.getSizeInventory() - 27 == player.inventory.currentItem) return null;
          return super.slotClick(slotIndex, buttonPressed, flag, player);
          }
          
          /**
          * Used to save content
          */
          @Override
          public void onContainerClosed(EntityPlayer player) {
          this.writeToNBT(player.getHeldItem());
          super.onContainerClosed(player);
          }
          }
          

          Et le crash report complet :

          –-- Minecraft Crash Report ----
          // I'm sorry, Dave.
          
          Time: 26/10/15 13:06
          Description: Exception in server tick loop
          
          java.lang.NullPointerException: Exception in server tick loop
          at laserflip33.ordreduphenix.common.ContainerBourseMoke.writeToNBT(ContainerBourseMoke.java:47)
          at laserflip33.ordreduphenix.common.ContainerBourseMoke.func_75134_a(ContainerBourseMoke.java:96)
          at net.minecraft.entity.player.EntityPlayer.func_70106_y(EntityPlayer.java:1481)
          at net.minecraft.world.World.func_72900_e(World.java:1844)
          at net.minecraft.server.management.ServerConfigurationManager.disconnect(ServerConfigurationManager.java:419)
          at net.minecraft.network.NetHandlerPlayServer.func_147231_a(NetHandlerPlayServer.java:969)
          at net.minecraft.network.NetworkSystem.func_151269_c(NetworkSystem.java:166)
          at net.minecraft.server.MinecraftServer.func_71190_q(MinecraftServer.java:953)
          at net.minecraft.server.dedicated.DedicatedServer.func_71190_q(DedicatedServer.java:432)
          at net.minecraft.server.MinecraftServer.func_71217_p(MinecraftServer.java:783)
          at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:646)
          at java.lang.Thread.run(Thread.java:722)
          
          A detailed walkthrough of the error, its code path and all known details is as follows:
          ---------------------------------------------------------------------------------------
          
          -- System Details --
          Details:
          Minecraft Version: 1.7.2
          Operating System: Linux (amd64) version 3.14-0.bpo.1-amd64
          Java Version: 1.7.0, Oracle Corporation
          Java VM Version: Java HotSpot(TM) 64-Bit Server VM (mixed mode), Oracle Corporation
          Memory: 366335336 bytes (349 MB) / 1116057600 bytes (1064 MB) up to 18407424000 bytes (17554 MB)
          JVM Flags: 21 total; -Xms512M -XX:PermSize=384m -XX:MaxPermSize=768m -XX:-UseConcMarkSweepGC -XX:+UseParNewGC -XX:+UseNUMA -XX:+CMSParallelRemarkEnabled -XX:+UseAdaptiveGCBoundary -XX:-UseGCOverheadLimit -XX:+UseBiasedLocking -XX:SurvivorRatio=8 -XX:TargetSurvivorRatio=90 -XX:MaxTenuringThreshold=15 -XX:UseSSE=3 -XX:+UseLargePages -XX:+UseFastAccessorMethods -XX:+UseStringCache -XX:+UseCompressedOops -XX:+OptimizeStringConcat -XX:+AggressiveOpts -XX:ParallelGCThreads=1
          AABB Pool Size: 7109 (398104 bytes; 0 MB) allocated, 6560 (367360 bytes; 0 MB) used
          IntCache: cache: 0, tcache: 0, allocated: 12, tallocated: 94
          FML: MCP v9.03 FML v7.2.217.1147 Minecraft Forge 10.12.2.1147 13 mods loaded, 13 mods active
          mcp{9.03} [Minecraft Coder Pack] (minecraft.jar) Unloaded->Constructed->Pre-initialized->Initialized->Post-initialized->Available->Available->Available->Available
          FML{7.2.217.1147} [Forge Mod Loader] (cauldron.jar) Unloaded->Constructed->Pre-initialized->Initialized->Post-initialized->Available->Available->Available->Available
          Forge{10.12.2.1147} [Minecraft Forge] (cauldron.jar) Unloaded->Constructed->Pre-initialized->Initialized->Post-initialized->Available->Available->Available->Available
          CustomSpawner{3.2.0.dev.R3} [DrZhark's CustomSpawner] (CustomMobSpawner 3.2.0-DEV-R3.zip) Unloaded->Constructed->Pre-initialized->Initialized->Post-initialized->Available->Available->Available->Available
          customnpcs{1.7.2-2} [CustomNpcs] (CustomNPCs_1.7.2.jar) Unloaded->Constructed->Pre-initialized->Initialized->Post-initialized->Available->Available->Available->Available
          MoCreatures{6.2.0.dev.R3} [DrZhark's Mo'Creatures Mod] (DrZharks MoCreatures Mod v6.2.0-DEV-R3.zip) Unloaded->Constructed->Pre-initialized->Initialized->Post-initialized->Available->Available->Available->Available
          ftfloocraft{1.7.10-0.3.1} [Floocraft] (Floocraft-1.7.10-0.3.1.jar) Unloaded->Constructed->Pre-initialized->Initialized->Post-initialized->Available->Available->Available->Available
          MineChess{1.3.7} [MineChess] (MineChess-Mod-1.7.2.zip) Unloaded->Constructed->Pre-initialized->Initialized->Post-initialized->Available->Available->Available->Available
          halloween{1.0.0} [Halloween] (ModHalloween.jar) Unloaded->Constructed->Pre-initialized->Initialized->Post-initialized->Available->Available->Available->Available
          ordreduphenix{1.0.0} [Ordre du Phenix] (ordreduphenix-1.0.jar) Unloaded->Constructed->Pre-initialized->Initialized->Post-initialized->Available->Available->Available->Available
          pottermod{0.2} [PotterMod] (Pottermod-0.2.jar) Unloaded->Constructed->Pre-initialized->Initialized->Post-initialized->Available->Available->Available->Available
          quidcraft{0.1} [Quidcraft] (Quidcraft-0.1(1.7.2).jar) Unloaded->Constructed->Pre-initialized->Initialized->Post-initialized->Available->Available->Available->Available
          witchery{0.20.4} [Witchery] (witchery-1.7.2-0.20.4.jar) Unloaded->Constructed->Pre-initialized->Initialized->Post-initialized->Available->Available->Available->Available
          Profiler Position: N/A (disabled)
          Vec3 Pool Size: 56493 (3163608 bytes; 3 MB) allocated, 6233 (349048 bytes; 0 MB) used
          Player Count: 5 / 50; [EntityPlayerMP['Xemox'/1437, l='MapOrdrePhenix', x=-2577,64, y=48,00, z=2512,38](Xemox at -2577.63824231431,48.0,2512.379903864352), EntityPlayerMP['unai64700'/2173, l='MapOrdrePhenix', x=-2583,59, y=54,50, z=2489,30](unai64700 at -2583.5871402555135,54.5,2489.300000011921), EntityPlayerMP['yas35400'/51794, l='MapOrdrePhenix', x=-2578,97, y=54,48, z=2478,82](yas35400 at -2578.969493942492,54.4807108763317,2478.8155894892357), EntityPlayerMP['Actiz'/8176, l='MapOrdrePhenix', x=-2811,37, y=40,00, z=1950,95](Actiz at -2811.3673737126605,40.0,1950.946107101118), EntityPlayerMP['EmmaCarena'/344622, l='MapOrdrePhenix', x=-2581,05, y=54,00, z=2440,25](EmmaCarena at -2581.0475033284024,54.0,2440.2492956906467)]
          Is Modded: Definitely; Server brand changed to 'cauldron,craftbukkit,mcpc,fml,forge'
          Type: Dedicated Server (map_server.txt)
          
          1 réponse Dernière réponse Répondre Citer 0
          • SCAREXS Hors-ligne
            SCAREX
            dernière édition par

            Je pense que ce qu’il se passe c’est que l’item en main du joueur disparaît ou alors le joueur change son slot utilisé, or ce n’est pas censé arriver, as-tu une idée de comment le joueur pourrait changer son slot utilisé ou déplacer l’ItemStack ?

            Site web contenant mes scripts : http://SCAREXgaming.github.io

            Pas de demandes de support par MP ni par skype SVP.
            Je n'accepte sur skype que l…

            1 réponse Dernière réponse Répondre Citer 0
            • L Hors-ligne
              Laserflip33
              dernière édition par

              @‘SCAREX’:

              Je pense que ce qu’il se passe c’est que l’item en main du joueur disparaît ou alors le joueur change son slot utilisé, or ce n’est pas censé arriver, as-tu une idée de comment le joueur pourrait changer son slot utilisé ou déplacer l’ItemStack ?

              J’ai vraiment aucune idée sur ce coup là… Par contre mon hypothèse est fausse : le crash ne survient pas lorsque deux sacs s’ouvrent. Je connais désormais la raison, certaines personnes s’amusent à ouvrir et fermer très rapidement leurs sacs. Après ça le serveur crash quasiment à coup sûr…

              1 réponse Dernière réponse Répondre Citer 0
              • SCAREXS Hors-ligne
                SCAREX
                dernière édition par

                Tu peux verifier à chaque tick si le joueur a toujours le sac en main et ne change pas de slot en cours, s’il change tu fermes le sac

                Site web contenant mes scripts : http://SCAREXgaming.github.io

                Pas de demandes de support par MP ni par skype SVP.
                Je n'accepte sur skype que l…

                1 réponse Dernière réponse Répondre Citer 0
                • robin4002R Hors-ligne
                  robin4002 Moddeurs confirmés Rédacteurs Administrateurs
                  dernière édition par

                  Il faut ajouter un null check pour corriger ce NPE.
                  Et dans le container dans la fonction canInteractWith il devrait avoir return player.getHeldItem() != null && player.getHeldItem().getItem() == ClassePrincipale.leSac; et non return true; 😉

                  1 réponse Dernière réponse Répondre Citer 0
                  • L Hors-ligne
                    Laserflip33
                    dernière édition par

                    Merci je teste cela. 😉

                    1 réponse Dernière réponse Répondre Citer 0
                    • Benjamin LoisonB Hors-ligne
                      Benjamin Loison
                      dernière édition par

                      Sac :

                      @Override
                      public ItemStack onItemRightClick(ItemStack stack, World world, EntityPlayer player) {
                      player.openGui(ModAltisCraft.instance, 1, world, (int) player.posX, (int) player.posY, (int) player.posZ);
                      return stack;
                      }
                      

                      Mod :

                      @Mod(modid="altiscraft.MODID", name="AltisCraft.fr", version="1.0.0")
                       public class ModAltisCraft
                       {
                         public static final String MODID = "altiscraft";
                         @Mod.Instance("altiscraft.MODID")
                         public static ModAltisCraft instance;
                         public static final int guiIDMenu = 0;
                         public static final int GuiSac = 1;
                      

                      Et le Gui ne s’ouvre pas de l’aide s’il vous plaît ? 😕

                      >! Développeur de Altis-Life (Arma III) sur Minecraft !
                      >! Site web     : https://lemnoslife.com

                      1 réponse Dernière réponse Répondre Citer 0
                      • SCAREXS Hors-ligne
                        SCAREX
                        dernière édition par

                        As-tu enregistré ton guiHandler ? Si oui, envoi ton guiHandler

                        Envoyé de mon SM-G920F en utilisant Tapatalk

                        Site web contenant mes scripts : http://SCAREXgaming.github.io

                        Pas de demandes de support par MP ni par skype SVP.
                        Je n'accepte sur skype que l…

                        1 réponse Dernière réponse Répondre Citer 0
                        • Benjamin LoisonB Hors-ligne
                          Benjamin Loison
                          dernière édition par

                          Mod :

                          @Mod.EventHandler
                          public void init(FMLInitializationEvent event) {
                          NetworkRegistry.INSTANCE.registerGuiHandler(instance, new GuiHandler());
                          }
                          

                          GuiHandler :

                          package fr.altiscraft.benjaminloison.gui;
                          
                          import cpw.mods.fml.common.network.IGuiHandler;
                          import fr.altiscraft.benjaminloison.common.ConteneurSac;
                          import fr.altiscraft.benjaminloison.common.InventaireSac;
                          import fr.altiscraft.benjaminloison.common.Sac;
                          import net.minecraft.entity.player.EntityPlayer;
                          import net.minecraft.world.World;
                          
                          public class GuiHandler implements IGuiHandler
                          {
                          @Override
                          public Object getServerGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z) {
                          switch (ID) {
                          case 0:
                          if (player.getHeldItem() == null || !(player.getHeldItem().getItem() instanceof Sac)) return null;
                          return new ConteneurSac(player.inventory, new InventaireSac(player.getHeldItem(), 54));
                          }
                          return null;
                          }
                          
                          @Override
                          public Object getClientGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z) {
                          switch (ID) {
                          case 0:
                          if (player.getHeldItem() == null || !(player.getHeldItem().getItem() instanceof Sac)) return null;
                          return new GuiSac(player.inventory, new InventaireSac(player.getHeldItem(), 54));
                          }
                          return null;
                          }
                          }
                          

                          >! Développeur de Altis-Life (Arma III) sur Minecraft !
                          >! Site web     : https://lemnoslife.com

                          1 réponse Dernière réponse Répondre Citer 0
                          • SCAREXS Hors-ligne
                            SCAREX
                            dernière édition par

                            Normal, tu demandes l’id 1 mais ton guiHandler c’est case 0

                            Envoyé de mon SM-G920F en utilisant Tapatalk

                            Site web contenant mes scripts : http://SCAREXgaming.github.io

                            Pas de demandes de support par MP ni par skype SVP.
                            Je n'accepte sur skype que l…

                            1 réponse Dernière réponse Répondre Citer 0
                            • Benjamin LoisonB Hors-ligne
                              Benjamin Loison
                              dernière édition par

                              player.openGui(ModAltisCraft.instance, 0, world, (int) player.posX, (int) player.posY, (int) player.posZ);
                              ``` ne change rien :/
                              et ```java
                              public static final int GuiSac = 0;
                              ``` non plus :/

                              >! Développeur de Altis-Life (Arma III) sur Minecraft !
                              >! Site web     : https://lemnoslife.com

                              1 réponse Dernière réponse Répondre Citer 0
                              • robin4002R Hors-ligne
                                robin4002 Moddeurs confirmés Rédacteurs Administrateurs
                                dernière édition par

                                  @Mod.Instance("altiscraft.MODID")
                                  public static ModAltisCraft instance;
                                

                                …
                                C’est soit :

                                  @Mod.Instance(ModAltisCraft.MODID)
                                  public static ModAltisCraft instance;
                                

                                soit

                                  @Mod.Instance("altiscraft")
                                  public static ModAltisCraft instance;
                                

                                Mais pas le mélange des deux …

                                1 réponse Dernière réponse Répondre Citer 0
                                • Benjamin LoisonB Hors-ligne
                                  Benjamin Loison
                                  dernière édition par

                                  Avec ça ```java
                                  @Mod.Instance(ModAltisCraft.MODID)
                                  public static ModAltisCraft instance;

                                  
                                  J'ai ce crash :
                                  
                                  java.lang.NullPointerException: Initializing game
                                  at cpw.mods.fml.common.network.NetworkRegistry.registerGuiHandler(NetworkRegistry.java:219)
                                  at fr.altiscraft.benjaminloison.common.ModAltisCraft.init(ModAltisCraft.java:574)
                                  
                                  Avec la ligne 574 :
                                  
                                  ```java
                                  NetworkRegistry.INSTANCE.registerGuiHandler(instance, new GuiHandler());
                                  

                                  Je comprends pas le NPE 😕

                                  >! Développeur de Altis-Life (Arma III) sur Minecraft !
                                  >! Site web     : https://lemnoslife.com

                                  1 réponse Dernière réponse Répondre Citer 0
                                  • robin4002R Hors-ligne
                                    robin4002 Moddeurs confirmés Rédacteurs Administrateurs
                                    dernière édition par

                                    Ah en fait cette ligne est fausse aussi :
                                    @Mod(modid=“altiscraft.MODID”, name=“AltisCraft.fr”, version=“1.0.0”)
                                    Du-coup les deux erreurs se compensaient …
                                    ça devrait être :
                                    @Mod(modid=ModAltisCraft.MODID, name=“AltisCraft.fr”, version=“1.0.0”)

                                    mais ça veut aussi dire que l’erreur ne vient pas de là.

                                    1 réponse Dernière réponse Répondre Citer 0
                                    • Benjamin LoisonB Hors-ligne
                                      Benjamin Loison
                                      dernière édition par

                                      C’est bon j’arrive à relancer le jeu mais ça n’ouvre toujours pas mon Sac 😕

                                      >! Développeur de Altis-Life (Arma III) sur Minecraft !
                                      >! Site web     : https://lemnoslife.com

                                      1 réponse Dernière réponse Répondre Citer 0
                                      • SCAREXS Hors-ligne
                                        SCAREX
                                        dernière édition par

                                        Renvoi toutes tes classes

                                        Envoyé de mon SM-G920F en utilisant Tapatalk

                                        Site web contenant mes scripts : http://SCAREXgaming.github.io

                                        Pas de demandes de support par MP ni par skype SVP.
                                        Je n'accepte sur skype que l…

                                        1 réponse Dernière réponse Répondre Citer 0
                                        • robin4002R Hors-ligne
                                          robin4002 Moddeurs confirmés Rédacteurs Administrateurs
                                          dernière édition par

                                          @‘robin4002’:

                                          mais ça veut aussi dire que l’erreur ne vient pas de là.

                                          je m’en doutais. Essayes de mettre des System.out.println par ci par là.

                                          1 réponse Dernière réponse Répondre Citer 0
                                          • Benjamin LoisonB Hors-ligne
                                            Benjamin Loison
                                            dernière édition par

                                            player.openGui(ModAltisCraft.instance, 0, world, (int) player.posX, (int) player.posY, (int) player.posZ);
                                            ``` Est censé lire ça ? ```java
                                            public static final int GuiSac = 0;
                                            ``` Non ?

                                            >! Développeur de Altis-Life (Arma III) sur Minecraft !
                                            >! Site web     : https://lemnoslife.com

                                            1 réponse Dernière réponse Répondre Citer 0
                                            • 1
                                            • 2
                                            • 3
                                            • 4
                                            • 5
                                            • 3 / 5
                                            • Premier message
                                              Dernier message
                                            Design by Woryk
                                            ContactMentions Légales

                                            MINECRAFT FORGE FRANCE © 2024

                                            Powered by NodeBB