-
Bonjour,
Concernant le point 2 pour sauvegarder les données en les liant au joueur, il faut passer par une capability : https://www.minecraftforgefrance.fr/topic/4817/les-capabilities?_=1579706317665
-
Oui, je le sais déjà, par contre merci pour le liens, cela m’aidera sans doute, mon inventaire est sauvegarder de cette manière :
package com.kporal.mcplus.items.kitbag; import net.minecraft.nbt.NBTBase; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.EnumFacing; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.capabilities.ICapabilityProvider; import net.minecraftforge.common.capabilities.ICapabilitySerializable; import net.minecraftforge.items.CapabilityItemHandler; import net.minecraftforge.items.ItemStackHandler; public class KitbagProvider implements ICapabilityProvider, ICapabilitySerializable<NBTTagCompound> { private final ItemStackHandler inventory; public KitbagProvider() { inventory = new ItemStackHandler( 117 ); // 107 to 117 } @Override public NBTTagCompound serializeNBT() { return inventory.serializeNBT(); } public void deserializeNBT( NBTTagCompound nbt ) { inventory.deserializeNBT( nbt ); } @Override public boolean hasCapability( Capability<?> capability, EnumFacing facing ) { if( capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY ) { return true; } return false; } @Override public <T> T getCapability( Capability<T> capability, EnumFacing facing ) { if( capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY ) { return (T) inventory; } return null; } }Et cela fonctionne bien, par contre la ou cela me pose souci c’est que ce n’est pas l’effet que je veux, je m’explique : actuellement l’inventaire en question est sauvegarder dans l’item, hors je veux que celui-ci soit sauvegarder comme si c’étais un enderchest ( que chaque item ouvre le même inventaire et non un inventaire unique lié à chaque item ), je crois savoir que l’enderchest est sauvegarder dans le joueur directement, de quel manière je pourrait reproduire cela ?
Genre : j’enregistre un NBTag au joueur ( par exemple lorsqu’il spawn / respawn en vérifiant si celui-ci existe déjà ou non ), puis dans mon item je charge le NBTag lié au joueur et non celui de l’item ? je en sais pas trop comment procéder même si je pense avoir une bonne idée de base. -
Tu attaches comment ta capability actuellement ?
-
Actuellement via mon item et je pense que c’est là mon souci, car au lieu d’attacher la capability au joueur puis d’y faire appel via l’item je fais sa :
package com.kporal.mcplus.items; import com.kporal.mcplus.Main; import com.kporal.mcplus.items.kitbag.KitbagProvider; import net.minecraft.creativetab.CreativeTabs; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.ActionResult; import net.minecraft.util.EnumActionResult; import net.minecraft.util.EnumHand; import net.minecraft.world.World; import net.minecraftforge.common.capabilities.ICapabilityProvider; public class BookMysteries extends Item { public BookMysteries() { this.setRegistryName( "bookmysteries" ); this.setTranslationKey( "bookmysteries" ); this.setCreativeTab( Main.mcptab ); this.setMaxStackSize( 1 ); } public ActionResult<ItemStack> onItemRightClick( World w, EntityPlayer p, EnumHand e ) { if( !w.isRemote ) { p.openGui( Main.instance, 0, w, e.ordinal(), -1, -1 ); } return new ActionResult<ItemStack>( EnumActionResult.PASS, p.getHeldItemMainhand() ); } public void onPlayerStoppedUsing( ItemStack stack, World worldIn, EntityLivingBase entityLiving, int timeLeft ) {} @Override public ICapabilityProvider initCapabilities( ItemStack item, NBTTagCompound nbt ) { if( item.getItem() == Main.bookmysteries ) { return new KitbagProvider(); } return null; } } -
Yep c’est ça, si tu veux le même comportement que l’ender chest il faut l’attacher au joueur.
-
Bon la possibilité qui me viens à l’esprit pour attacher la capability au joueur est d’utiliser les event PlayerEvent.Clone et EntityJoinWorldEvent, par contre après via l’item je ne sais pas comment procéder pour ouvrir la capability lié au joueur … et vue l’heure je verrais sa demain

-
Dans la fonction onItemRightClick tu as le joueur en argument, tu peux depuis ce dernier obtenir la capa :
if(p.hasCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null)) { KitbagProvider cap = event.player.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null);Et pour attacher la capability il fau utiliser
AttachCapabilitiesEvent<Entity>. -
Bon j’ai tenter de créer ma propre capability etc etc et … elle fonctionne ( si on peux dire ça ) mais le résultat est juste pas du tout celui attendu ! ( bref en gros j’ai merder quelque pars sans doute ) le souci étant que cela me fait modifier beaucoup de chose dans mes autres classes tout en implémentant le code nécessaire à la création de la capability, utilisant par défaut CapabilityItemHandler.ITEM_HANDLER_CAPABILITY pour l’inventaire de mon item, je me suis dis, pourquoi pas tenté de faire :
VoidStorageCapabilitypackage com.kporal.mcplus.capabilities; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.capabilities.CapabilityInject; import net.minecraftforge.items.CapabilityItemHandler; import net.minecraftforge.items.IItemHandler; public class VoidStorageCapability extends CapabilityItemHandler { @CapabilityInject(IItemHandler.class) public static Capability<IItemHandler> VOID_STORAGE_CAPABILITY = null; }VoidStorageProvider
package com.kporal.mcplus.capabilities; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.EnumFacing; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.capabilities.ICapabilityProvider; import net.minecraftforge.common.capabilities.ICapabilitySerializable; import net.minecraftforge.items.CapabilityItemHandler; import net.minecraftforge.items.ItemStackHandler; public class VoidStorageProvider implements ICapabilityProvider, ICapabilitySerializable<NBTTagCompound> { private final ItemStackHandler inventory; public VoidStorageProvider() { inventory = new ItemStackHandler( 117 ); } @Override public NBTTagCompound serializeNBT() { return inventory.serializeNBT(); } @Override public void deserializeNBT( NBTTagCompound nbt ) { inventory.deserializeNBT( nbt ); } @Override public boolean hasCapability( Capability<?> capability, EnumFacing facing ) { if( capability == VoidStorageCapability.VOID_STORAGE_CAPABILITY ) { return true; } return false; } @Override public <T> T getCapability( Capability<T> capability, EnumFacing facing ) { if( capability == VoidStorageCapability.VOID_STORAGE_CAPABILITY ) { return (T) inventory; } return null; } }BookMysteries
package com.kporal.mcplus.items; import com.kporal.mcplus.Main; import com.kporal.mcplus.capabilities.VoidStorageCapability; import com.kporal.mcplus.items.kitbag.KitbagProvider; import net.minecraft.creativetab.CreativeTabs; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.ActionResult; import net.minecraft.util.EnumActionResult; import net.minecraft.util.EnumHand; import net.minecraft.world.World; import net.minecraftforge.common.capabilities.ICapabilityProvider; import net.minecraftforge.items.CapabilityItemHandler; import net.minecraftforge.items.IItemHandler; public class BookMysteries extends Item { public BookMysteries() { this.setRegistryName( "bookmysteries" ); this.setTranslationKey( "bookmysteries" ); this.setCreativeTab( Main.mcptab ); this.setMaxStackSize( 1 ); } public ActionResult<ItemStack> onItemRightClick( World w, EntityPlayer p, EnumHand e ) { if( !w.isRemote ) { p.openGui( Main.instance, 0, w, e.ordinal(), -1, -1 ); if( p.hasCapability( VoidStorageCapability.VOID_STORAGE_CAPABILITY, null )) { IItemHandler cap = p.getCapability( VoidStorageCapability.VOID_STORAGE_CAPABILITY, null ); IItemHandler own = p.getHeldItemMainhand().getCapability( CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null ); for( int i = 0; i < own.getSlots(); i++ ) { own.insertItem( i, cap.getStackInSlot( i ), false ); } } } return new ActionResult<ItemStack>( EnumActionResult.PASS, p.getHeldItemMainhand() ); } public void onPlayerStoppedUsing( ItemStack stack, World worldIn, EntityLivingBase entityLiving, int timeLeft ) {} @Override public ICapabilityProvider initCapabilities( ItemStack item, NBTTagCompound nbt ) { return new KitbagProvider(); } }Alors le but est de créer une copie de l’inventaire de mon item ( au niveau code ) pour faciliter tous les échange que je ferais dessus via le Gui ( qui inclura le workbench et un furnace … ).
Bref Le résultat précédent est le même que celui que j’obtiens ici ( avec quelques erreurs en moins cependant ! ), en somme, j’ai une loop ( qui fais crash le jeux ) :at com.kporal.mcplus.items.kitbag.KitbagProvider.serializeNBT(KitbagProvider.java:23) at com.kporal.mcplus.items.kitbag.KitbagProvider.serializeNBT(KitbagProvider.java:1) at net.minecraftforge.common.capabilities.CapabilityDispatcher.serializeNBT(CapabilityDispatcher.java:123) at net.minecraft.item.ItemStack.writeToNBT(ItemStack.java:262)Mais je crois savoir ou est mon erreur …
-
Bon bah mon souci viens de là ( je suppose ) :
@SubscribeEvent public void addCapability( AttachCapabilitiesEvent<Entity> event ) { //System.out.println( "test debug coucou" ); if( event.getObject() instanceof EntityPlayer ) { //System.out.println( "test debug coucou playerentity" ); EntityPlayer p = ( EntityPlayer ) event.getObject(); if( !p.world.isRemote ) { if( !p.hasCapability( VoidStorageCapability.VOID_STORAGE_CAPABILITY, null )) { //p.getCapability( VoidStorageCapability.VOID_STORAGE_CAPABILITY, null ); //event.addCapability( new ResourceLocation( Main.MODID, "voidstorage" ), new VoidStorageProvider() ); System.out.println( Main.NAME + " :: Capability > voidstorage added for " + p.getName() ); } } } }Pourquoi ? bah simplement car mon 3e message de debug ne s’affiche “jamais” … donc forte chance que VoidStorageCapability.VOID_STORAGE_CAPABILITY doit posé problème, sauf que … je n’ai aucune erreur … j’ai simplement répliquer CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, qui s’enregistre lui même, donc là je suis perdu lol …
-
Perso je n’ai jamais mit de check dans cette event, j’ajoute la capa au joueur à chaque fois que l’event est appelé.
-
Ok, je vaid tester ça alors; ce qui devrais me donner :
@SubscribeEvent public void addCapability( AttachCapabilitiesEvent<Entity> event ) { if( event.getObject() instanceof EntityPlayer ) { event.addCapability( new ResourceLocation( Main.MODID, "voidstorage" ), new VoidStorageProvider() ); } }Par contre je ne suis aps certain concernant mon ResourceLocation, je vais tester cela.
-
Bon la capability est clairement instancier maintenant, du coup merci !
Par contre, je garde la loop qui fait crash le jeux et je suppose que cela viens d’ici mais … aucune certitude :public ActionResult<ItemStack> onItemRightClick( World w, EntityPlayer p, EnumHand e ) { if( !w.isRemote ) { p.openGui( Main.instance, 0, w, e.ordinal(), -1, -1 ); if( p.hasCapability( VoidStorageCapability.VOID_STORAGE_CAPABILITY, null )) { IItemHandler cap = p.getCapability( VoidStorageCapability.VOID_STORAGE_CAPABILITY, null ); IItemHandler own = p.getHeldItemMainhand().getCapability( CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null ); for( int i = 0; i < own.getSlots(); i++ ) { own.insertItem( i, cap.getStackInSlot( i ), false ); } } } return new ActionResult<ItemStack>( EnumActionResult.PASS, p.getHeldItemMainhand() ); } public void onPlayerStoppedUsing( ItemStack stack, World worldIn, EntityLivingBase entityLiving, int timeLeft ) {} @Override public ICapabilityProvider initCapabilities( ItemStack item, NBTTagCompound nbt ) { return new KitbagProvider(); }package com.kporal.mcplus.capabilities; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.EnumFacing; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.capabilities.ICapabilityProvider; import net.minecraftforge.common.capabilities.ICapabilitySerializable; import net.minecraftforge.items.CapabilityItemHandler; import net.minecraftforge.items.ItemStackHandler; public class VoidStorageProvider implements ICapabilityProvider, ICapabilitySerializable<NBTTagCompound> { private final ItemStackHandler voidStorageContainer; public VoidStorageProvider() { voidStorageContainer = new ItemStackHandler( 117 ); } @Override public NBTTagCompound serializeNBT() { return voidStorageContainer.serializeNBT(); } @Override public void deserializeNBT( NBTTagCompound nbt ) { voidStorageContainer.deserializeNBT( nbt ); } @Override public boolean hasCapability( Capability<?> capability, EnumFacing facing ) { if( capability == VoidStorageCapability.VOID_STORAGE_CAPABILITY ) { return true; } return false; } @Override public <T> T getCapability( Capability<T> capability, EnumFacing facing ) { if( capability == VoidStorageCapability.VOID_STORAGE_CAPABILITY ) { return (T) voidStorageContainer; } return null; } }package com.kporal.mcplus.items.kitbag; import net.minecraft.nbt.NBTBase; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.EnumFacing; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.capabilities.CapabilityInject; import net.minecraftforge.common.capabilities.ICapabilityProvider; import net.minecraftforge.common.capabilities.ICapabilitySerializable; import net.minecraftforge.items.CapabilityItemHandler; import net.minecraftforge.items.ItemStackHandler; public class KitbagProvider implements ICapabilityProvider, ICapabilitySerializable<NBTTagCompound> { private final ItemStackHandler inventory; public KitbagProvider() { inventory = new ItemStackHandler( 117 ); } @Override public NBTTagCompound serializeNBT() { return inventory.serializeNBT(); } @Override public void deserializeNBT( NBTTagCompound nbt ) { inventory.deserializeNBT( nbt ); } @Override public boolean hasCapability( Capability<?> capability, EnumFacing facing ) { if( capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY ) { return true; } return false; } @Override public <T> T getCapability( Capability<T> capability, EnumFacing facing ) { if( capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY ) { return (T) inventory; } return null; } }La loop étant uniquement composé de :
at net.minecraft.item.ItemStack.writeToNBT(ItemStack.java:262) at net.minecraftforge.items.ItemStackHandler.serializeNBT(ItemStackHandler.java:183) at com.kporal.mcplus.items.kitbag.KitbagProvider.serializeNBT(KitbagProvider.java:23) at com.kporal.mcplus.items.kitbag.KitbagProvider.serializeNBT(KitbagProvider.java:1)Mais … après relecture de moi même en écrivant, chaque Capability dois bien avoir sa propre interface ? car si oui la loop est normal vue que :
package com.kporal.mcplus.capabilities; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTBase; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; import net.minecraft.util.EnumFacing; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.capabilities.CapabilityInject; import net.minecraftforge.common.capabilities.CapabilityManager; import net.minecraftforge.items.CapabilityItemHandler; import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.IItemHandlerModifiable; import net.minecraftforge.items.ItemStackHandler; public class VoidStorageCapability extends CapabilityItemHandler { @CapabilityInject(IItemHandler.class) public static Capability<IItemHandler> VOID_STORAGE_CAPABILITY = null; public static void register() { CapabilityManager.INSTANCE.register(IItemHandler.class, new Capability.IStorage<IItemHandler>() { @Override public NBTBase writeNBT(Capability<IItemHandler> capability, IItemHandler instance, EnumFacing side) { NBTTagList nbtTagList = new NBTTagList(); int size = instance.getSlots(); for (int i = 0; i < size; i++) { ItemStack stack = instance.getStackInSlot(i); if (!stack.isEmpty()) { NBTTagCompound itemTag = new NBTTagCompound(); itemTag.setInteger("Slot", i); stack.writeToNBT(itemTag); nbtTagList.appendTag(itemTag); } } return nbtTagList; } @Override public void readNBT(Capability<IItemHandler> capability, IItemHandler instance, EnumFacing side, NBTBase base) { if (!(instance instanceof IItemHandlerModifiable)) throw new RuntimeException("IItemHandler instance does not implement IItemHandlerModifiable"); IItemHandlerModifiable itemHandlerModifiable = (IItemHandlerModifiable) instance; NBTTagList tagList = (NBTTagList) base; for (int i = 0; i < tagList.tagCount(); i++) { NBTTagCompound itemTags = tagList.getCompoundTagAt(i); int j = itemTags.getInteger("Slot"); if (j >= 0 && j < instance.getSlots()) { itemHandlerModifiable.setStackInSlot(j, new ItemStack(itemTags)); } } } }, ItemStackHandler::new); } }Ce qui expliquerais tout !
-
Ok ok j’ai faux sur toute la ligne, j’ai simplement modifier mon item en supprimant sont initCapabilities sans motifier le code restant et en utilisant simplement :
package com.kporal.mcplus.items.kitbag; import com.kporal.mcplus.capabilities.VoidStorageCapability; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.inventory.IInventory; import net.minecraft.world.World; import net.minecraftforge.fml.common.network.IGuiHandler; import net.minecraftforge.items.CapabilityItemHandler; import net.minecraftforge.items.IItemHandler; public class KitbagGuiHandler implements IGuiHandler { @Override public Object getServerGuiElement( int ID, EntityPlayer p, World w, int x, int y, int z ) { //return new KitbagContainer( (IItemHandler) p.getHeldItemMainhand().getCapability( CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null ), p ); return new KitbagContainer(( IItemHandler ) p.getCapability( VoidStorageCapability.VOID_STORAGE_CAPABILITY, null ), p ); } @Override public Object getClientGuiElement( int ID, EntityPlayer p, World w, int x, int y, int z ) { //return new KitbagGui( (IItemHandler) p.getHeldItemMainhand().getCapability( CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null ), p ); return new KitbagGui(( IItemHandler ) p.getCapability( VoidStorageCapability.VOID_STORAGE_CAPABILITY, null ), p ); } }Je n’ai plus de crash, ni de loop, par contre je suis bien censé ouvrir VoidStorageCapability.VOID_STORAGE_CAPABILITY mais … il me duplique l’inventaire du joueur et non le voidStorageContainer = new ItemStackHandler( 117 );, des idées d’où j’ai faux ?
-
Tu peux envoyer la classe KitbagContainer ?
-
KitbagContainer
package com.kporal.mcplus.items.kitbag; import com.kporal.mcplus.container.FuelFurnaceSlot; import com.kporal.mcplus.container.OutputFurnaceSlot; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.inventory.Container; import net.minecraft.inventory.IContainerListener; import net.minecraft.inventory.IInventory; import net.minecraft.inventory.InventoryCraftResult; import net.minecraft.inventory.InventoryCrafting; import net.minecraft.inventory.Slot; import net.minecraft.inventory.SlotCrafting; import net.minecraft.item.ItemStack; import net.minecraft.util.NonNullList; import net.minecraft.world.World; import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.SlotItemHandler; public class KitbagContainer extends Container { public EntityPlayer player; public World world; private int xPos = 5, yPos = 5, iid = 0, iRows = 8, iLines = 13, nSlots = iRows * iLines; public KitbagContainer( IItemHandler i, EntityPlayer p ) { player = p; world = p.world; // Container inventory :: 0 > 103 for( int y = 0; y < iRows; ++y ) { for( int x = 0; x < iLines; ++x ) { addSlotToContainer( new SlotItemHandler( i, iid, xPos + x * 18, yPos + y * 18 )); iid++; } } // Workbench slots :: 104 > 113 addSlotToContainer( new SlotItemHandler( i, iid, 167, 170 )); iid++; for (int y = 0; y < 3; ++y) { for (int x = 0; x < 3; ++x) { addSlotToContainer( new SlotItemHandler( i, iid, 185 + x * 18, 152 + y * 18 )); iid++; } } // Furnace slots :: 114 > 116 addSlotToContainer( new SlotItemHandler( i, iid, 221, 209 )); iid++; addSlotToContainer( new FuelFurnaceSlot( i, iid, 185, 209 )); iid++; addSlotToContainer( new OutputFurnaceSlot( p, i, iid, 167, 209 )); yPos = 152; // Player inventory for( int y = 0; y < 3; ++y ) { for( int x = 0; x < 9; ++x ) { addSlotToContainer( new Slot( p.inventory, x + y * 9 + 9, xPos + x * 18, yPos + y * 18 )); } } // Player hotbar for( int x = 0; x < 9; ++x ) { addSlotToContainer( new Slot( p.inventory, x, xPos + x * 18, 209 )); } } @Override public ItemStack transferStackInSlot( EntityPlayer playerIn, int index ) { ItemStack itemstack = ItemStack.EMPTY; Slot slot = inventorySlots.get(index); if( slot != null && slot.getHasStack() ) { ItemStack itemstack1 = slot.getStack(); itemstack = itemstack1.copy(); if( index == 104 ) { itemstack1.getItem().onCreated(itemstack1, world, playerIn); if( !this.mergeItemStack(itemstack1, 0, nSlots, false )) { return ItemStack.EMPTY; } slot.onSlotChange( itemstack1, itemstack ); } else if( index < nSlots ) { if( !mergeItemStack( itemstack1, nSlots, inventorySlots.size(), true )) { return ItemStack.EMPTY; } } else if( !mergeItemStack( itemstack1, 0, nSlots, false )) { return ItemStack.EMPTY; } if ( itemstack1.isEmpty() ) { slot.putStack( ItemStack.EMPTY ); } else { slot.onSlotChanged(); } if( itemstack1.getCount() == itemstack.getCount() ) { return ItemStack.EMPTY; } ItemStack itemstack2 = slot.onTake( playerIn, itemstack1 ); if( index == 104 ) { playerIn.dropItem( itemstack2, false ); } } return itemstack; } @Override public boolean canInteractWith( EntityPlayer p ) { return true; } } -
Ce qui donne en jeux :

-
Ok je reviens à la charge car j’ai … progressé ? ( hum lol ou pas ), j’ai supprimer tous le contenu superflu, utilisant ni plus ni moins que le code de base que j’utilisai pour instancier mon item, après des heures de test j’ai décider de modifier mon point de vue et donc de procéder comme ceci :
EventsHandler.java
@SubscribeEvent public void addCapability( AttachCapabilitiesEvent<Entity> event ) { if( event.getObject() instanceof EntityPlayer ) { event.addCapability( new ResourceLocation( Main.MODID, "voidStorage" ), new KitbagProvider() ); System.out.println( Main.NAME + " :: Capability > voidStorage added for ..." ); } }KitbagGuiHandler
package com.kporal.mcplus.items.kitbag; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.inventory.IInventory; import net.minecraft.world.World; import net.minecraftforge.fml.common.network.IGuiHandler; import net.minecraftforge.items.CapabilityItemHandler; import net.minecraftforge.items.IItemHandler; public class KitbagGuiHandler implements IGuiHandler { @Override public Object getServerGuiElement( int ID, EntityPlayer p, World w, int x, int y, int z ) { //return new KitbagContainer( (IItemHandler) p.getHeldItemMainhand().getCapability( CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null ), p ); IItemHandler iii = ( IItemHandler ) p.getCapability( CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null ); System.out.println( "MSDEBUG<SERVER> :: " + iii.getSlots() + " " + iii.toString() ); return new KitbagContainer(( IItemHandler ) p.getCapability( CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null ), p ); } @Override public Object getClientGuiElement( int ID, EntityPlayer p, World w, int x, int y, int z ) { //return new KitbagGui( (IItemHandler) p.getHeldItemMainhand().getCapability( CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null ), p ); IItemHandler iii = ( IItemHandler ) p.getCapability( CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null ); System.out.println( "MSDEBUG<CLIENT> :: " + iii.getSlots() + " " + iii.toString() ); return new KitbagGui(( IItemHandler ) p.getCapability( CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null ), p ); } }Je n’ai rien modifier d’autre, le reste du code pointe sur CapabilityItemHandler.ITEM_HANDLER_CAPABILITY car pourquoi créer une nouvelle capability alors que celle-ci est déjà toute prête !
BREF, point important :
[13:52:24] [Server thread/INFO] [STDOUT]: [com.kporal.mcplus.items.kitbag.KitbagGuiHandler:getServerGuiElement:17]: MSDEBUG<SERVER> :: 41 net.minecraftforge.items.wrapper.PlayerInvWrapper@42179e3b [13:52:24] [main/INFO] [STDOUT]: [com.kporal.mcplus.items.kitbag.KitbagGuiHandler:getClientGuiElement:25]: MSDEBUG<CLIENT> :: 41 net.minecraftforge.items.wrapper.PlayerInvWrapper@3ac9e8b8Euh oui, cela ne pointe pas du tout sur la capability mais sur le player inventory … … … !
Des idées ? -
Désoler pour le double post ! mais là … je viens simplement de Reset mon world ( encore une fois ) mais cette fois-ci en supprimant simplement mon AttachCapabilitiesEvent<Entity> et … il s’avère que le résultat est exactement le même, ce qui peux signifier que ma capability initiale n’est simplement à aucun moment attacher au joueur ! Je vais faire d’autres test pour voir ce qu’il se passe

-
ENFIN … ! Bon je poste l’intégralité de mon “kitbag” au cas ou que cela puisse aider quelqu’un !
KitbagCapability.java
package com.kporal.mcplus.items.kitbag; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTBase; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; import net.minecraft.util.EnumFacing; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.capabilities.CapabilityInject; import net.minecraftforge.common.capabilities.CapabilityManager; import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.IItemHandlerModifiable; import net.minecraftforge.items.ItemStackHandler; public class KitbagCapability { @CapabilityInject(KitbagHandler.class) public static Capability<KitbagHandler> VOIDSTORAGE_CAPABILITY = null; public static void register() { CapabilityManager.INSTANCE.register(KitbagHandler.class, new Capability.IStorage<KitbagHandler>() { @Override public NBTBase writeNBT(Capability<KitbagHandler> capability, KitbagHandler instance, EnumFacing side) { NBTTagList nbtTagList = new NBTTagList(); int size = instance.getSlots(); for (int i = 0; i < size; i++) { ItemStack stack = instance.getStackInSlot(i); if (!stack.isEmpty()) { NBTTagCompound itemTag = new NBTTagCompound(); itemTag.setInteger("Slot", i); stack.writeToNBT(itemTag); nbtTagList.appendTag(itemTag); } } return nbtTagList; } @Override public void readNBT(Capability<KitbagHandler> capability, KitbagHandler instance, EnumFacing side, NBTBase base) { if (!(instance instanceof IItemHandlerModifiable)) throw new RuntimeException("IItemHandler instance does not implement IItemHandlerModifiable"); IItemHandlerModifiable itemHandlerModifiable = (IItemHandlerModifiable) instance; NBTTagList tagList = (NBTTagList) base; for (int i = 0; i < tagList.tagCount(); i++) { NBTTagCompound itemTags = tagList.getCompoundTagAt(i); int j = itemTags.getInteger("Slot"); if (j >= 0 && j < instance.getSlots()) { itemHandlerModifiable.setStackInSlot(j, new ItemStack(itemTags)); } } } }, KitbagStackHandler::new); } }KitbagContainer.java
package com.kporal.mcplus.items.kitbag; import com.kporal.mcplus.container.FuelFurnaceSlot; import com.kporal.mcplus.container.OutputFurnaceSlot; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.inventory.Container; import net.minecraft.inventory.IContainerListener; import net.minecraft.inventory.IInventory; import net.minecraft.inventory.InventoryCraftResult; import net.minecraft.inventory.InventoryCrafting; import net.minecraft.inventory.Slot; import net.minecraft.inventory.SlotCrafting; import net.minecraft.item.ItemStack; import net.minecraft.util.NonNullList; import net.minecraft.world.World; import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.SlotItemHandler; public class KitbagContainer extends Container { private int xPos = 5, yPos = 5, iid = 0, iRows = 8, iLines = 13, nSlots = iRows * iLines; public KitbagContainer( IItemHandler i, EntityPlayer p ) { // Container inventory :: 0 > 103 for( int y = 0; y < iRows; ++y ) { for( int x = 0; x < iLines; ++x ) { addSlotToContainer( new SlotItemHandler( i, iid, xPos + x * 18, yPos + y * 18 )); iid++; } } // Workbench slots :: 104 > 113 addSlotToContainer( new SlotItemHandler( i, iid, 167, 170 )); iid++; for (int y = 0; y < 3; ++y) { for (int x = 0; x < 3; ++x) { addSlotToContainer( new SlotItemHandler( i, iid, 185 + x * 18, 152 + y * 18 )); iid++; } } // Furnace slots :: 114 > 116 addSlotToContainer( new SlotItemHandler( i, iid, 221, 209 )); iid++; addSlotToContainer( new FuelFurnaceSlot( i, iid, 185, 209 )); iid++; addSlotToContainer( new OutputFurnaceSlot( p, i, iid, 167, 209 )); yPos = 152; // Player inventory for( int y = 0; y < 3; ++y ) { for( int x = 0; x < 9; ++x ) { addSlotToContainer( new Slot( p.inventory, x + y * 9 + 9, xPos + x * 18, yPos + y * 18 )); } } // Player hotbar for( int x = 0; x < 9; ++x ) { addSlotToContainer( new Slot( p.inventory, x, xPos + x * 18, 209 )); } } @Override public ItemStack transferStackInSlot( EntityPlayer playerIn, int index ) { ItemStack itemstack = ItemStack.EMPTY; Slot slot = inventorySlots.get(index); if( slot != null && slot.getHasStack() ) { ItemStack itemstack1 = slot.getStack(); itemstack = itemstack1.copy(); if( index == 104 ) { itemstack1.getItem().onCreated(itemstack1, playerIn.world, playerIn); if( !this.mergeItemStack(itemstack1, 0, nSlots, false )) { return ItemStack.EMPTY; } slot.onSlotChange( itemstack1, itemstack ); } else if( index < nSlots ) { if( !mergeItemStack( itemstack1, nSlots, inventorySlots.size(), true )) { return ItemStack.EMPTY; } } else if( !mergeItemStack( itemstack1, 0, nSlots, false )) { return ItemStack.EMPTY; } if ( itemstack1.isEmpty() ) { slot.putStack( ItemStack.EMPTY ); } else { slot.onSlotChanged(); } if( itemstack1.getCount() == itemstack.getCount() ) { return ItemStack.EMPTY; } ItemStack itemstack2 = slot.onTake( playerIn, itemstack1 ); if( index == 104 ) { playerIn.dropItem( itemstack2, false ); } } return itemstack; } @Override public boolean canInteractWith( EntityPlayer p ) { return true; } }KitbagGui.java
package com.kporal.mcplus.items.kitbag; import com.kporal.mcplus.Main; import net.minecraft.client.gui.inventory.GuiContainer; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.inventory.IInventory; import net.minecraft.tileentity.TileEntityFurnace; import net.minecraft.util.ResourceLocation; import net.minecraftforge.items.IItemHandler; public class KitbagGui extends GuiContainer { private IItemHandler i; public KitbagGui( IItemHandler i, EntityPlayer p ) { super( new KitbagContainer( i, p )); this.xSize = 243; this.ySize = 230; this.i = i; } @Override protected void drawGuiContainerBackgroundLayer(float partialTicks, int mouseX, int mouseY) { GlStateManager.color( 1.0F, 1.0F, 1.0F, 1.0F ); this.mc.getTextureManager().bindTexture( new ResourceLocation( Main.MODID, "textures/gui/container/bookmysteries.png" ) ); this.drawTexturedModalRect( this.guiLeft, this.guiTop, 0, 0, this.xSize, this.ySize ); // GuiFurnace.class int w = (this.width - this.xSize) / 2; int h = (this.height - this.ySize) / 2; int k = 5; // this.getBurnLeftScaled(13); this.drawTexturedModalRect( w + 204, h + 221 - k, 0, 243 - k, 14, k + 1 ); int l = 12; // this.getCookProgressScaled( 15 ); this.drawTexturedModalRect( w + 203, h + 224 - 1, 14, 230, l + 1, 2 ); } }KitbagGuiHandler
package com.kporal.mcplus.items.kitbag; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.inventory.IInventory; import net.minecraft.world.World; import net.minecraftforge.fml.common.network.IGuiHandler; import net.minecraftforge.items.CapabilityItemHandler; import net.minecraftforge.items.IItemHandler; public class KitbagGuiHandler implements IGuiHandler { @Override public Object getServerGuiElement( int ID, EntityPlayer p, World w, int x, int y, int z ) { return new KitbagContainer(( IItemHandler ) p.getCapability( KitbagCapability.VOIDSTORAGE_CAPABILITY, null ), p ); } @Override public Object getClientGuiElement( int ID, EntityPlayer p, World w, int x, int y, int z ) { return new KitbagGui(( IItemHandler ) p.getCapability( KitbagCapability.VOIDSTORAGE_CAPABILITY, null ), p ); } }KitbagHandler.java
package com.kporal.mcplus.items.kitbag; import javax.annotation.Nonnull; import net.minecraft.inventory.IInventory; import net.minecraft.item.ItemStack; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.capability.IFluidHandler; public interface KitbagHandler { int getSlots(); @Nonnull ItemStack getStackInSlot(int slot); @Nonnull ItemStack insertItem(int slot, @Nonnull ItemStack stack, boolean simulate); @Nonnull ItemStack extractItem(int slot, int amount, boolean simulate); int getSlotLimit(int slot); default boolean isItemValid(int slot, @Nonnull ItemStack stack) { return true; } }KitbagProvider.java
package com.kporal.mcplus.items.kitbag; import net.minecraft.nbt.NBTBase; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.EnumFacing; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.capabilities.CapabilityInject; import net.minecraftforge.common.capabilities.ICapabilityProvider; import net.minecraftforge.common.capabilities.ICapabilitySerializable; import net.minecraftforge.items.CapabilityItemHandler; import net.minecraftforge.items.ItemStackHandler; public class KitbagProvider implements ICapabilityProvider, ICapabilitySerializable<NBTTagCompound> { private final KitbagStackHandler inventory; public KitbagProvider() { inventory = new KitbagStackHandler( 117 ); } @Override public NBTTagCompound serializeNBT() { return inventory.serializeNBT(); } @Override public void deserializeNBT( NBTTagCompound nbt ) { inventory.deserializeNBT( nbt ); } @Override public boolean hasCapability( Capability<?> capability, EnumFacing facing ) { if( capability == KitbagCapability.VOIDSTORAGE_CAPABILITY ) { return true; } return false; } @Override public <T> T getCapability( Capability<T> capability, EnumFacing facing ) { if( capability == KitbagCapability.VOIDSTORAGE_CAPABILITY ) { return (T) inventory; } return null; } }KitbagStackHandler.java
package com.kporal.mcplus.items.kitbag; import javax.annotation.Nonnull; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; import net.minecraft.util.NonNullList; import net.minecraftforge.common.util.Constants; import net.minecraftforge.common.util.INBTSerializable; import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.IItemHandlerModifiable; import net.minecraftforge.items.ItemHandlerHelper; public class KitbagStackHandler implements KitbagHandler, IItemHandlerModifiable, INBTSerializable<NBTTagCompound> { protected NonNullList<ItemStack> stacks; public KitbagStackHandler() { this(1); } public KitbagStackHandler(int size) { stacks = NonNullList.withSize(size, ItemStack.EMPTY); } public KitbagStackHandler(NonNullList<ItemStack> stacks) { this.stacks = stacks; } public void setSize(int size) { stacks = NonNullList.withSize(size, ItemStack.EMPTY); } @Override public void setStackInSlot(int slot, @Nonnull ItemStack stack) { validateSlotIndex(slot); this.stacks.set(slot, stack); onContentsChanged(slot); } @Override public int getSlots() { return stacks.size(); } @Override @Nonnull public ItemStack getStackInSlot(int slot) { validateSlotIndex(slot); return this.stacks.get(slot); } @Override @Nonnull public ItemStack insertItem(int slot, @Nonnull ItemStack stack, boolean simulate) { if (stack.isEmpty()) return ItemStack.EMPTY; validateSlotIndex(slot); ItemStack existing = this.stacks.get(slot); int limit = getStackLimit(slot, stack); if (!existing.isEmpty()) { if (!ItemHandlerHelper.canItemStacksStack(stack, existing)) return stack; limit -= existing.getCount(); } if (limit <= 0) return stack; boolean reachedLimit = stack.getCount() > limit; if (!simulate) { if (existing.isEmpty()) { this.stacks.set(slot, reachedLimit ? ItemHandlerHelper.copyStackWithSize(stack, limit) : stack); } else { existing.grow(reachedLimit ? limit : stack.getCount()); } onContentsChanged(slot); } return reachedLimit ? ItemHandlerHelper.copyStackWithSize(stack, stack.getCount()- limit) : ItemStack.EMPTY; } @Override @Nonnull public ItemStack extractItem(int slot, int amount, boolean simulate) { if (amount == 0) return ItemStack.EMPTY; validateSlotIndex(slot); ItemStack existing = this.stacks.get(slot); if (existing.isEmpty()) return ItemStack.EMPTY; int toExtract = Math.min(amount, existing.getMaxStackSize()); if (existing.getCount() <= toExtract) { if (!simulate) { this.stacks.set(slot, ItemStack.EMPTY); onContentsChanged(slot); } return existing; } else { if (!simulate) { this.stacks.set(slot, ItemHandlerHelper.copyStackWithSize(existing, existing.getCount() - toExtract)); onContentsChanged(slot); } return ItemHandlerHelper.copyStackWithSize(existing, toExtract); } } @Override public int getSlotLimit(int slot) { return 64; } protected int getStackLimit(int slot, @Nonnull ItemStack stack) { return Math.min(getSlotLimit(slot), stack.getMaxStackSize()); } @Override public boolean isItemValid(int slot, @Nonnull ItemStack stack) { return true; } @Override public NBTTagCompound serializeNBT() { NBTTagList nbtTagList = new NBTTagList(); for (int i = 0; i < stacks.size(); i++) { if (!stacks.get(i).isEmpty()) { NBTTagCompound itemTag = new NBTTagCompound(); itemTag.setInteger("Slot", i); stacks.get(i).writeToNBT(itemTag); nbtTagList.appendTag(itemTag); } } NBTTagCompound nbt = new NBTTagCompound(); nbt.setTag("Items", nbtTagList); nbt.setInteger("Size", stacks.size()); return nbt; } @Override public void deserializeNBT(NBTTagCompound nbt) { setSize(nbt.hasKey("Size", Constants.NBT.TAG_INT) ? nbt.getInteger("Size") : stacks.size()); NBTTagList tagList = nbt.getTagList("Items", Constants.NBT.TAG_COMPOUND); for (int i = 0; i < tagList.tagCount(); i++) { NBTTagCompound itemTags = tagList.getCompoundTagAt(i); int slot = itemTags.getInteger("Slot"); if (slot >= 0 && slot < stacks.size()) { stacks.set(slot, new ItemStack(itemTags)); } } onLoad(); } protected void validateSlotIndex(int slot) { if (slot < 0 || slot >= stacks.size()) throw new RuntimeException("Slot " + slot + " not in valid range - [0," + stacks.size() + ")"); } protected void onLoad() { } protected void onContentsChanged(int slot) { } }PS: J’ai simplement fais un gros copier coller de toute la capability CapabilityItemHandler.ITEM_HANDLER_CAPABILITY sans instancier celle-ci via l’item évidement.
Mais bref, le code est néanmoins incomplet mais il est fonctionnel. -
Fin du code : ( pour rendre le contenu permanent )
@SubscribeEvent public void cloneEvent( PlayerEvent.Clone e ) { if( e.isWasDeath() ) { KitbagHandler o = e.getOriginal().getCapability( KitbagCapability.VOIDSTORAGE_CAPABILITY, null ); KitbagHandler i = e.getEntityPlayer().getCapability( KitbagCapability.VOIDSTORAGE_CAPABILITY, null ); for( int k = 0; k < o.getSlots(); k++ ) { i.insertItem( k, o.getStackInSlot( k ), false ); } } } @SubscribeEvent public void addCapability( AttachCapabilitiesEvent<Entity> event ) { if( event.getObject() instanceof EntityPlayer ) { event.addCapability( new ResourceLocation( Main.MODID, "voidStorage" ), new KitbagProvider() ); } }