Posted June 22, 20205 yr On 6/15/2020 at 5:22 AM, diesieben07 said: Implement IContainerFactory on your container factory, not ContainerType.IFactory. Then you get the PacketBuffer you wrote to when using NetworkHooks.openGui. Hi I am doing the same thing here (custom entity inventory) and I got lost when you said this. I didn't find any mention about (SiegeContainerFactory and SiegeScreenFactory) inside classes at first post My code is working except that client does not have itemstacks syncronized (it is empty). By the way, these are important parts of my mod Can anybody help me please? Thank you †GnR† Slash DeadPlayerContainer: package com.gnrdevand.inventoryplus.inventory; import com.gnrdevand.inventoryplus.entities.DeadPlayerEntity; import com.gnrdevand.inventoryplus.init.ContainerTypes; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerInventory; import net.minecraft.inventory.EquipmentSlotType; import net.minecraft.inventory.IInventory; import net.minecraft.inventory.container.Container; import net.minecraft.inventory.container.ContainerType; import net.minecraft.inventory.container.Slot; import net.minecraft.item.ItemStack; import net.minecraft.network.PacketBuffer; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import javax.annotation.Nullable; import java.awt.*; public class DeadPlayerContainer extends Container { private static final String[] ARMOR_SLOT_TEXTURES = new String[]{"item/empty_armor_slot_boots", "item/empty_armor_slot_leggings", "item/empty_armor_slot_chestplate", "item/empty_armor_slot_helmet"}; private static final EquipmentSlotType[] VALID_EQUIPMENT_SLOTS = new EquipmentSlotType[]{EquipmentSlotType.HEAD, EquipmentSlotType.CHEST, EquipmentSlotType.LEGS, EquipmentSlotType.FEET}; private final Point firstArmorSlot = new Point(8, 8); private final Point firstInvSlot = new Point(44, 9); private final Point firstPlayerArmorSlot = new Point(8, 98); private final Point firstPlayerInvSlot = new Point(44, 98); private final PlayerInventory playerInventory; private final DeadPlayerEntity deadPlayerEntity; private int ctSlotIndex; private int firstArmorSlotIndex; private int firstOffHandSlotIndex; private int firstMainSlotIndex; private int firstMainHandSlotIndex; private int firstPlayerArmorSlotIndex; private int firstPlayerOffHandPSlotIndex; private int firstPlayerMainPSlotIndex; private int firstPlayerMainHandSlotIndex; public DeadPlayerContainer(int containerId, PlayerInventory playerInv, PacketBuffer buffer) { this(containerId, playerInv, (DeadPlayerEntity) playerInv.player.world.getEntityByID(buffer.readInt())); } public DeadPlayerContainer(int containerIdIn, PlayerInventory playerInventoryIn, DeadPlayerEntity deadPlayerEntityIn) { super(ContainerTypes.DEAD_PLAYER_CONTAINER.get(), containerIdIn); this.deadPlayerEntity = deadPlayerEntityIn; this.playerInventory = playerInventoryIn; this.deadPlayerEntity.getMainInventory().openInventory(playerInventoryIn.player); this.deadPlayerEntity.getArmorInventory().openInventory(playerInventoryIn.player); this.deadPlayerEntity.getOffHandInventory().openInventory(playerInventoryIn.player); addContainerSlots(); addPlayerSlots(); } @Override public boolean canInteractWith(PlayerEntity playerIn) { return playerIn.getDistanceSq(deadPlayerEntity.posX, deadPlayerEntity.posY, deadPlayerEntity.posZ) <= 64D; } @Override public ItemStack transferStackInSlot(PlayerEntity playerIn, int index) { return super.transferStackInSlot(playerIn, index); } @Override public void onContainerClosed(PlayerEntity playerIn) { super.onContainerClosed(playerIn); this.deadPlayerEntity.getInventory().getInventories().forEach((s, invEnt) -> { invEnt.closeInventory(playerIn); }); } private void addContainerSlots() { ctSlotIndex = 0; // armor slots firstArmorSlotIndex = ctSlotIndex; for (int i = 0; i < 4; i++) { final EquipmentSlotType equipmentslottype = VALID_EQUIPMENT_SLOTS[i]; addSlot(new Slot( deadPlayerEntity.getArmorInventory(), ctSlotIndex, firstArmorSlot.x, firstArmorSlot.y + 18 * i){ @Override public int getSlotStackLimit() { return 1; } @Override public boolean isItemValid(ItemStack stack) { return stack.canEquip(equipmentslottype, playerInventory.player); } @Nullable @OnlyIn(Dist.CLIENT) @Override public String getSlotTexture() { return DeadPlayerContainer.ARMOR_SLOT_TEXTURES[equipmentslottype.getIndex()]; } }); ctSlotIndex++; } // off hand slot firstOffHandSlotIndex = ctSlotIndex; this.addSlot(new Slot(deadPlayerEntity.getOffHandInventory(), ctSlotIndex, firstArmorSlot.x + 18, firstArmorSlot.y + 18 * 3) { @Nullable @OnlyIn(Dist.CLIENT) public String getSlotTexture() { return "item/empty_armor_slot_shield"; } }); ctSlotIndex++; // main slots firstMainSlotIndex = ctSlotIndex; for (int row = 0; row < 3; row++) { for (int col = 0; col < 9; col++) { addSlot(new Slot(deadPlayerEntity.getMainInventory(), ctSlotIndex, firstInvSlot.x + col * 18, firstInvSlot.y + row * 18)); ctSlotIndex++; } } // main hand slots firstMainHandSlotIndex = ctSlotIndex; for (int i = 0; i < 9; i++) { addSlot(new Slot(deadPlayerEntity.getMainInventory(), ctSlotIndex, firstInvSlot.x + i * 18, firstInvSlot.y + 18 * 3)); ctSlotIndex++; } } private void addPlayerSlots() { // armor slots firstPlayerArmorSlotIndex = ctSlotIndex; for (int i = 0; i < 4; i++) { final EquipmentSlotType equipmentslottype = VALID_EQUIPMENT_SLOTS[i]; addSlot(new Slot( playerInventory, playerInventory.getSizeInventory() - 5 + 1, firstPlayerArmorSlot.x, firstPlayerArmorSlot.y + 18 * i){ @Override public int getSlotStackLimit() { return 1; } @Override public boolean isItemValid(ItemStack stack) { return stack.canEquip(equipmentslottype, playerInventory.player); } @Nullable @OnlyIn(Dist.CLIENT) @Override public String getSlotTexture() { return DeadPlayerContainer.ARMOR_SLOT_TEXTURES[equipmentslottype.getIndex()]; } }); ctSlotIndex++; } // off hand slot firstPlayerOffHandPSlotIndex = ctSlotIndex; this.addSlot(new Slot(playerInventory, playerInventory.getSizeInventory() - 1, firstPlayerArmorSlot.x + 18, firstPlayerArmorSlot.y + 18 * 3) { @Nullable @OnlyIn(Dist.CLIENT) public String getSlotTexture() { return "item/empty_armor_slot_shield"; } }); ctSlotIndex++; // main slots firstPlayerMainPSlotIndex = ctSlotIndex; for (int row = 0; row < 3; row++) { for (int col = 0; col < 9; col++) { addSlot(new Slot(playerInventory, col + (row + 1) * 9, firstPlayerInvSlot.x + col * 18, firstPlayerInvSlot.y + row * 18)); ctSlotIndex++; } } // main hand slots firstPlayerMainHandSlotIndex = ctSlotIndex; for (int i = 0; i < 9; i++) { addSlot(new Slot(playerInventory, i, firstPlayerInvSlot.x + i * 18, firstPlayerInvSlot.y + 18 * 3)); } } public DeadPlayerEntity getDeadPlayerEntity() { return this.deadPlayerEntity; } } ContainerTypes: package com.gnrdevand.inventoryplus.init; import com.gnrdevand.inventoryplus.InventoryPlus; import com.gnrdevand.inventoryplus.inventory.DeadPlayerContainer; import net.minecraft.inventory.container.ContainerType; import net.minecraftforge.common.extensions.IForgeContainerType; import net.minecraftforge.fml.RegistryObject; import net.minecraftforge.registries.DeferredRegister; import net.minecraftforge.registries.ForgeRegistries; public class ContainerTypes { public static final DeferredRegister<ContainerType<?>> CONTAINER_TYPES = new DeferredRegister<>(ForgeRegistries.CONTAINERS, InventoryPlus.MODID); public static final RegistryObject<ContainerType<DeadPlayerContainer>> DEAD_PLAYER_CONTAINER = CONTAINER_TYPES.register(InventoryPlus.MODID, () -> { return IForgeContainerType.create(DeadPlayerContainer::new); }); } MainMod: package com.gnrdevand.inventoryplus; import com.gnrdevand.inventoryplus.gui.DeadPlayerInventoryScreen; import com.gnrdevand.inventoryplus.init.ConfigHandler; import com.gnrdevand.inventoryplus.init.ContainerTypes; import com.gnrdevand.inventoryplus.network.Networking; import net.minecraft.client.gui.ScreenManager; import net.minecraft.client.settings.KeyBinding; import net.minecraft.client.util.InputMappings; import net.minecraftforge.eventbus.api.IEventBus; import net.minecraftforge.fml.ModLoadingContext; import net.minecraftforge.fml.client.registry.ClientRegistry; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.config.ModConfig; import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent; import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; import net.minecraftforge.fml.loading.FMLPaths; import java.util.logging.Logger; @Mod(InventoryPlus.MODID) public final class InventoryPlus { public static final String MODID = "inventoryplus"; public static final Logger LOGGER = Logger.getLogger(MODID); public InventoryPlus() { ModLoadingContext.get().registerConfig(ModConfig.Type.CLIENT, ConfigHandler.CLIENT_CONFIG); ModLoadingContext.get().registerConfig(ModConfig.Type.COMMON, ConfigHandler.COMMON_CONFIG); FMLJavaModLoadingContext.get().getModEventBus().addListener(this::setup); FMLJavaModLoadingContext.get().getModEventBus().addListener(this::clientRegistries); ConfigHandler.loadConfig(ConfigHandler.CLIENT_CONFIG, FMLPaths.CONFIGDIR.get().resolve(MODID + "-client.toml")); ConfigHandler.loadConfig(ConfigHandler.COMMON_CONFIG, FMLPaths.CONFIGDIR.get().resolve(MODID + "-common.toml")); ContainerTypes.CONTAINER_TYPES.register(FMLJavaModLoadingContext.get().getModEventBus()); } private void setup(final FMLCommonSetupEvent event) { Networking.registerMessages(); } private void clientRegistries(FMLClientSetupEvent event) { ScreenManager.registerFactory(ContainerTypes.DEAD_PLAYER_CONTAINER.get(), DeadPlayerInventoryScreen::new); } } I did not understand this part of MainMod class: (ContainerTypes.CONTAINER_TYPES.register(FMLJavaModLoadingContext.get().getModEventBus());) DeadPlayerInventoryScreen: package com.gnrdevand.inventoryplus.gui; import com.gnrdevand.gnrsharedlib.gui.controls.ButtonExt; import com.gnrdevand.inventoryplus.entities.DeadPlayerEntity; import com.gnrdevand.inventoryplus.inventory.DeadPlayerContainer; import com.gnrdevand.inventoryplus.lib.Resources; import com.mojang.blaze3d.platform.GlStateManager; import net.minecraft.client.gui.screen.inventory.ContainerScreen; import net.minecraft.entity.player.PlayerInventory; import net.minecraft.util.text.ITextComponent; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; @OnlyIn(Dist.CLIENT) public class DeadPlayerInventoryScreen extends ContainerScreen<DeadPlayerContainer> { private final PlayerInventory playerInventory; private final DeadPlayerEntity deadPlayerEntity; private float mousePosx; private float mousePosY; public DeadPlayerInventoryScreen(DeadPlayerContainer container, PlayerInventory playerInventoryIn, ITextComponent tileIn) { super(container, playerInventoryIn, tileIn); this.playerInventory = playerInventoryIn; this.deadPlayerEntity = container.getDeadPlayerEntity(); } @Override protected void init() { xSize = 211; ySize = 179; super.init(); String txt = Resources.getMsg("transfer"); addButton(new ButtonExt(this, guiLeft + xSize - 20 - font.getStringWidth(txt) - 6, guiTop + (18 * 4) + 6, font.getStringWidth(txt) + 20, 20, txt, btnClick -> { })); } @Override protected void drawGuiContainerBackgroundLayer(float partialTicks, int mouseX, int mouseY) { GlStateManager.color4f(1.0F, 1.0F, 1.0F, 1.0F); this.minecraft.getTextureManager().bindTexture(Resources.DEAD_PLAYER_GUI); int x = (this.width - this.xSize) / 2; int y = (this.height - this.ySize) / 2; this.blit(x, y, 0, 0, this.xSize, this.ySize); } @Override protected void drawGuiContainerForegroundLayer(int mouseX, int mouseY) { this.font.drawString(this.playerInventory.getDisplayName().getFormattedText(), 7, (18 * 4) + 6 + font.FONT_HEIGHT, 4210752); } @Override public void render(int mouseX, int mouseY, float partialTicks) { this.mousePosx = mouseX; this.mousePosY = mouseY; super.render(mouseX, mouseY, partialTicks); this.renderHoveredToolTip(mouseX, mouseY); } } DeadPlayerEntity: package com.gnrdevand.inventoryplus.entities; import com.gnrdevand.inventoryplus.init.ConfigHandler; import com.gnrdevand.inventoryplus.init.ModEntities; import com.gnrdevand.inventoryplus.inventory.DeadPlayerContainer; import net.minecraft.entity.CreatureEntity; import net.minecraft.entity.EntitySize; import net.minecraft.entity.EntityType; import net.minecraft.entity.Pose; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerInventory; import net.minecraft.entity.player.ServerPlayerEntity; import net.minecraft.inventory.EquipmentSlotType; import net.minecraft.inventory.container.Container; import net.minecraft.inventory.container.INamedContainerProvider; import net.minecraft.item.ItemStack; import net.minecraft.nbt.CompoundNBT; import net.minecraft.network.PacketBuffer; import net.minecraft.network.datasync.DataParameter; import net.minecraft.network.datasync.DataSerializers; import net.minecraft.network.datasync.EntityDataManager; import net.minecraft.util.DamageSource; import net.minecraft.util.Hand; import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.StringTextComponent; import net.minecraft.world.World; import net.minecraftforge.fml.network.NetworkHooks; import javax.annotation.Nullable; import java.util.function.Consumer; public class DeadPlayerEntity extends CreatureEntity { public static final String name = "dead_player_entity"; private static final DataParameter<Integer> DATA_BORN_TIME = EntityDataManager.createKey(DeadPlayerEntity.class, DataSerializers.VARINT); private static final DataParameter<String> DATA_CUSTOM_NAME = EntityDataManager.createKey(DeadPlayerEntity.class, DataSerializers.STRING); private final DeadPlayerEntityInventoryContainerProvider containerProvider; private int timeToDie; private String customName; private InventoryForEntities inventory; public enum eDeadPlayerInvTypes { ARMOR("armorInventory"), MAIN("mainInventory"), OFFHAND("offHandInventory"); private String type; eDeadPlayerInvTypes(String type) { this.type = type; } public String getType() { return this.type; } } public DeadPlayerEntity(EntityType<? extends CreatureEntity> type, World worldIn) { super((EntityType<? extends CreatureEntity>) ModEntities.DEAD_PLAYER_ENTITY, worldIn); this.timeToDie = 20 * 60 * ConfigHandler.CFG_DEAD_BODY_TIME.get(); // in minutes this.setInvulnerable(true); inventory = new InventoryForEntities(this); inventory.addInventory(eDeadPlayerInvTypes.MAIN.getType(), 9 * 4); // Player Inventory + Player quick inventory inventory.addInventory(eDeadPlayerInvTypes.ARMOR.getType(), 4); // Player Armor inventory.addInventory(eDeadPlayerInvTypes.OFFHAND.getType(), 1); // Player off hand item inventory.setMustDieOnPeacefull(false); inventory.setCanDropInventoryOnDeath(true); this.containerProvider = new DeadPlayerEntityInventoryContainerProvider(this); } public InventoryForEntities getInventory() { return this.inventory; } public InventoryEntity getArmorInventory() { return this.inventory.getInventory(eDeadPlayerInvTypes.ARMOR.getType()); } public InventoryEntity getOffHandInventory() { return this.inventory.getInventory(eDeadPlayerInvTypes.OFFHAND.getType()); } public InventoryEntity getMainInventory() { return this.inventory.getInventory(eDeadPlayerInvTypes.MAIN.getType()); } public long getTimeToDie() { return this.timeToDie; } public void setName(String name) { customName = name; this.dataManager.set(DATA_CUSTOM_NAME, customName); } public boolean copyPlayerInventory(PlayerEntity player) { boolean hasInv = false; for (int i = 0; i < player.inventory.armorInventory.size(); i++) { inventory.getInventory(eDeadPlayerInvTypes.ARMOR.getType()).addItem(player.inventory.armorInventory.get(i).copy()); if (!player.inventory.armorInventory.get(i).isEmpty()) hasInv = true; } inventory.getInventory(eDeadPlayerInvTypes.OFFHAND.getType()).addItem(player.inventory.offHandInventory.get(0).copy()); if (!player.inventory.offHandInventory.get(0).isEmpty()) hasInv = true; for (int i = 0; i < player.inventory.mainInventory.size(); i++) { inventory.getInventory(eDeadPlayerInvTypes.MAIN.getType()).addItem(player.inventory.mainInventory.get(i).copy()); if (!player.inventory.mainInventory.get(i).isEmpty()) hasInv = true; } return hasInv; } @Override protected void registerData() { super.registerData(); this.getDataManager().register(DATA_BORN_TIME, 0); this.getDataManager().register(DATA_CUSTOM_NAME, ""); } @Override public void writeAdditional(CompoundNBT compound) { super.writeAdditional(compound); compound.putInt("DATA_BORN_TIME", timeToDie); compound.putString("DATA_CUSTOM_NAME", customName); inventory.getInventories().forEach((name, invEnt) -> { compound.put(name, invEnt.writeToNBT()); }); } @Override public void readAdditional(CompoundNBT compound) { super.readAdditional(compound); timeToDie = compound.getInt("DATA_BORN_TIME"); customName = compound.getString("DATA_CUSTOM_NAME"); inventory.getInventories().forEach((name, invEnt) -> { invEnt.readFromNBT(compound.getList(name, 10)); }); } @Override public EntitySize getSize(Pose poseIn) { return EntitySize.fixed(1.8F, 0.2F); } @Override protected boolean isMovementBlocked() { return true; } @Override public boolean canBeSteered() { return false; } @Override public boolean canDespawn(double distanceToClosestPlayer) { return false; } @Override public void livingTick() { if (!ConfigHandler.CFG_USE_DEAD_BODY.get() && !world.isRemote) { this.setHealth(0); this.remove(); return; } super.livingTick(); //if (bornTime > 0) bornTime--; if (timeToDie <=0) { this.setHealth(0); this.onDeath(DamageSource.OUT_OF_WORLD); this.remove(); } else if (!world.isRemote) { int seconds = timeToDie / 20; this.setCustomName(new StringTextComponent(customName + " > " + String.format("%02d", (int) (seconds / 60)) + ":" + String.format("%02d", (int) (seconds % 60)))); } } @Override protected boolean processInteract(PlayerEntity player, Hand hand) { if (hand == Hand.MAIN_HAND && !player.world.isRemote && player instanceof ServerPlayerEntity) { NetworkHooks.openGui((ServerPlayerEntity) player, this.containerProvider, new Consumer<PacketBuffer>() { @Override public void accept(PacketBuffer buffer) { buffer.writeInt(getEntityId()); } }); return true; } return super.processInteract(player, hand); } @Override public void onDeath(DamageSource cause) { super.onDeath(cause); if (!world.isRemote) { inventory.getInventory(eDeadPlayerInvTypes.ARMOR.getType()).dropInventoryItems(); inventory.getInventory(eDeadPlayerInvTypes.OFFHAND.getType()).dropInventoryItems(); inventory.getInventory(eDeadPlayerInvTypes.MAIN.getType()).dropInventoryItems(); } } @Override public ItemStack getItemStackFromSlot(EquipmentSlotType slotIn) { if (slotIn == EquipmentSlotType.MAINHAND) { return this.inventory.getInventory(eDeadPlayerInvTypes.MAIN.getType()).getStackInSlot(0); } else if (slotIn == EquipmentSlotType.OFFHAND) { return this.inventory.getInventory(eDeadPlayerInvTypes.OFFHAND.getType()).getStackInSlot(0); } else { return slotIn.getSlotType() == EquipmentSlotType.Group.ARMOR ? this.inventory.getInventory(eDeadPlayerInvTypes.ARMOR.getType()).getStackInSlot(slotIn.getIndex()) : ItemStack.EMPTY; } } } class DeadPlayerEntityInventoryContainerProvider implements INamedContainerProvider { private final DeadPlayerEntity deadPlayerEntity; public DeadPlayerEntityInventoryContainerProvider(DeadPlayerEntity deadPlayerEntity) { this.deadPlayerEntity = deadPlayerEntity; } @Nullable @Override public Container createMenu(int containerId, PlayerInventory playerInv, PlayerEntity player) { return new DeadPlayerContainer(containerId, playerInv, this.deadPlayerEntity); } @Override public ITextComponent getDisplayName() { return deadPlayerEntity.getDisplayName(); } } Edited June 22, 20205 yr by GnRSlashSP Added full Container code (with slots creation) †GnR† Slash can one man truly make a difference?
June 22, 20205 yr Author 5 minutes ago, diesieben07 said: In the future please make your own thread instead of posting in some random thread that you think is mildly related. Sorry, I posted hede because I am trying to use exact the same code. Next time I'll create new topic 5 minutes ago, diesieben07 said: Your container does not add any slots. Not sure what you expected as a result other than it having no slots and thus not showing any items. Ok, all code is now there. Sorry 5 minutes ago, diesieben07 said: This does nothing. I know, but I don't know what I have to do inside it yet †GnR† Slash can one man truly make a difference?
June 22, 20205 yr Author Last question: Do you know if there is a repository that contains "entity with inventory" that I can use as a study? I confess that from forge 1.7.10 to 1.15 is very difficult for me, I can learn fast from examples. Thank you †GnR† Slash can one man truly make a difference?
June 23, 20205 yr Author I was looking at ItemStackHandler and the difference mine is too slight, ItemHandler is missing some features like listeners, clear inventory, isEmpty, MarkDirt. So, this is reasonable if it syncs with client for me automatically. I changed from "extends Inventory" to extends "ItemHandler" and now I cant add slots because new slot needs Inventory class. Let me see ... Did I get it right? If I implement correctly, will the inventory automatically sync without having to create custom network messages or ItemHandler is just a way to writeToNBT automatically? thanks †GnR† Slash can one man truly make a difference?
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.