Jump to content

[1.15.2] Custom Entity Container/Gui Not Interactable


OuiOuiCroissant

Recommended Posts

I am trying to create an entity with a gui that displays slots for their armor, mainhand, offhand, and a 10 slot inventory. Currently my gui will open when the entity is right-clicked by the player, but it is unfortunately NOT interactable.

 

Entity Super Class - SiegeEntity:

Spoiler

package com.siegemod.entities;

import com.siegemod.container.PeasantContainer;

import net.minecraft.entity.AgeableEntity;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.ILivingEntityData;
import net.minecraft.entity.SharedMonsterAttributes;
import net.minecraft.entity.SpawnReason;
import net.minecraft.entity.ai.goal.HurtByTargetGoal;
import net.minecraft.entity.ai.goal.LookAtGoal;
import net.minecraft.entity.ai.goal.LookRandomlyGoal;
import net.minecraft.entity.ai.goal.MoveThroughVillageGoal;
import net.minecraft.entity.ai.goal.MoveTowardsVillageGoal;
import net.minecraft.entity.ai.goal.SwimGoal;
import net.minecraft.entity.ai.goal.WaterAvoidingRandomWalkingGoal;
import net.minecraft.entity.merchant.villager.AbstractVillagerEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.entity.player.ServerPlayerEntity;
import net.minecraft.inventory.container.Container;
import net.minecraft.inventory.container.INamedContainerProvider;
import net.minecraft.item.ItemStack;
import net.minecraft.item.MerchantOffer;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.util.Hand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.world.DifficultyInstance;
import net.minecraft.world.IWorld;
import net.minecraft.world.World;
import net.minecraftforge.fml.network.NetworkHooks;

public abstract class SiegeEntity extends AbstractVillagerEntity {

    protected final double WALK_SPEED = 0.4D;
    // Convert to ItemHandler
    //private final Inventory PEASANT_INVENTORY = new Inventory(16);

    // 0 = wander, 1 = follow, 2 = locked follow, 3 = guard, 4 = locked guard.
    protected double stance = 0;
    protected PlayerEntity king;
    protected PlayerEntity[] allies;

    protected BlockPos bedPosition;
    protected BlockPos destination;
    protected ItemStack targetItem;

    public SiegeEntity(EntityType<? extends AbstractVillagerEntity> entityType, World worldIn, PlayerEntity kingIn) {
        super(entityType, worldIn);
        // this.king = kingIn;
    }

    @Override
    protected void registerGoals() {
        this.goalSelector.addGoal(0, new SwimGoal(this));
        // We're going to need a custom avoid entity goal
        // We're going to need a custom choose target goal
        this.goalSelector.addGoal(3, new MoveTowardsVillageGoal(this, WALK_SPEED));
        this.goalSelector.addGoal(3, new MoveThroughVillageGoal(this, WALK_SPEED, false, 4, () -> {
            return true;
        }));
        this.goalSelector.addGoal(6, new WaterAvoidingRandomWalkingGoal(this, WALK_SPEED));
        this.goalSelector.addGoal(7, new LookAtGoal(this, PlayerEntity.class, 6.0F));
        this.goalSelector.addGoal(8, new LookRandomlyGoal(this));

        this.targetSelector.addGoal(2, new HurtByTargetGoal(this));
    }

    @Override
    protected void registerAttributes() {
        super.registerAttributes();
        this.getAttribute(SharedMonsterAttributes.MAX_HEALTH).setBaseValue(20.0D);
        this.getAttribute(SharedMonsterAttributes.FOLLOW_RANGE).setBaseValue(64.0D);
        this.getAttribute(SharedMonsterAttributes.MOVEMENT_SPEED).setBaseValue(0.6F);

        this.getAttributes().registerAttribute(SharedMonsterAttributes.ATTACK_DAMAGE).setBaseValue(1.0D);

        this.getAttribute(SharedMonsterAttributes.ARMOR).setBaseValue(0.0D);
        this.getAttribute(SharedMonsterAttributes.ARMOR_TOUGHNESS).setBaseValue(0.0D);
        this.getAttribute(SharedMonsterAttributes.KNOCKBACK_RESISTANCE).setBaseValue(10.0F);
    }

    @Override
    public boolean attackEntityAsMob(Entity entityIn) {
        this.swingArm(getActiveHand());
        return super.attackEntityAsMob(entityIn);
    }

    public void livingTick() {
        this.updateArmSwingProgress();
        super.livingTick();
    }

    @Override
    public ILivingEntityData onInitialSpawn(IWorld worldIn, DifficultyInstance difficultyIn, SpawnReason reason, ILivingEntityData spawnDataIn, CompoundNBT dataTag) {
        // Temporary method of choosing king. Implement join kingdom feature in future.
        if (reason == SpawnReason.COMMAND) {
            this.king = world.getClosestPlayer(this.getPosX(), this.getPosY(), this.getPosZ(), 64, false);
        }
        return super.onInitialSpawn(worldIn, difficultyIn, reason, spawnDataIn, dataTag);
    }

    @Override
    public void writeAdditional(CompoundNBT compound) {
        super.writeAdditional(compound);
    }

    @Override
    public void readAdditional(CompoundNBT compound) {
        super.readAdditional(compound);
    }

    public PlayerEntity getKing() {
        return king;
    }

    @Override
    public AgeableEntity createChild(AgeableEntity ageable) {
        return null;
    }

    @Override
    protected void onVillagerTrade(MerchantOffer offer) {
    }

    @Override
    protected void populateTradeData() {
    }

    @Override
    public final boolean processInteract(PlayerEntity player, Hand hand) {
        if (hand == Hand.MAIN_HAND) {
            if (getKing() == null) {
                // Open join kingdom request screen.
                // OpenGui only accepts ServerPlayerEntity
                // Also works to ensure we are serverside
                System.out.println("king is null");
            } else if (player == getKing() && player instanceof ServerPlayerEntity) {
                System.out.println("king is " + player.toString());
                NetworkHooks.openGui((ServerPlayerEntity) player, new SiegeContainerProvider(this));
                return true;
            }
        }
        return super.processInteract(player, hand);
    }

    public static class SiegeContainerProvider implements INamedContainerProvider {

        private final SiegeEntity PEASANT;

        public SiegeContainerProvider(SiegeEntity peasantIn) {
            this.PEASANT = peasantIn;
        }

        @Override
        public Container createMenu(int containerId, PlayerInventory playerInv, PlayerEntity player) {
            return new PeasantContainer(player, PEASANT);
        }

        @Override
        public ITextComponent getDisplayName() {
            return PEASANT.getDisplayName();
        }
    }
}

Entity Class - PeasantEntity:

Spoiler

package com.siegemod.entities.friendly;

import com.siegemod.entities.SiegeEntity;
import com.siegemod.entities.enemy.EnemyEntity;

import net.minecraft.entity.EntityType;
import net.minecraft.entity.ai.goal.AvoidEntityGoal;
import net.minecraft.entity.merchant.villager.AbstractVillagerEntity;
import net.minecraft.entity.monster.ZombieEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.world.World;

public class PeasantEntity extends SiegeEntity {

    public PeasantEntity(EntityType<? extends AbstractVillagerEntity> entityType, World worldIn) {
        this(entityType, worldIn, null);
    }

    public PeasantEntity(EntityType<? extends AbstractVillagerEntity> entityType, World worldIn, PlayerEntity kingIn) {
        super(entityType, worldIn, kingIn);
    }

    @Override
    protected void registerGoals() {
        this.goalSelector.addGoal(2, new AvoidEntityGoal<>(this, EnemyEntity.class, 16.0F, WALK_SPEED, WALK_SPEED * 1.2D));
        this.goalSelector.addGoal(2, new AvoidEntityGoal<>(this, ZombieEntity.class, 16.0F, WALK_SPEED, WALK_SPEED * 1.2D));
    }
}

Container Class:

Spoiler

package com.siegemod.container;

import com.siegemod.entities.SiegeEntity;

import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.inventory.Inventory;
import net.minecraft.inventory.container.Container;
import net.minecraft.inventory.container.Slot;
import net.minecraft.item.ItemStack;
import net.minecraft.network.PacketBuffer;

public class PeasantContainer extends Container {

    public SiegeEntity peasant;
    public Inventory peasantInventory;

    public PeasantContainer(int containerId, PlayerInventory playerInv, PacketBuffer containerBuffer) {
        super(SiegeContainerTypes.PEASANT_CONTAINER.get(), containerId);
    }

    public PeasantContainer(PlayerEntity player, SiegeEntity peasantIn) {
        super(SiegeContainerTypes.PEASANT_CONTAINER.get(), 0);
        // replace with ItemHandler in future
        this.peasantInventory = new Inventory(16); //peasantInventory.getPeasantInventory.getInv();
        assertInventorySize(peasantInventory, 16);
        this.peasant = peasantIn;
        /*
        // Armor Inventory
        int armorInvYPos = 8;
        int sizePerSlot = 18;
        for (int column = 0; column < 4; ++column) {
            this.addSlot(new Slot(this.peasantInventory, 4, 8, armorInvYPos + (column * sizePerSlot)));
        }
        
        // MainHand
        this.addSlot(new Slot(this.peasantInventory, 4, 32, 62));
        
        // OffHand
        this.addSlot(new Slot(this.peasantInventory, 5, 32, 62));
        
        // Main Inventory
        int invXPos = 80;
        int invYPos = 8;
        int slotsInEachRow = 5;
        for (int row = 0; row < 5; ++row) {
            for (int column = 0; column < 4; ++column) {
                this.addSlot(new Slot(this.peasantInventory, row + column * slotsInEachRow + 6, invXPos + (column * sizePerSlot), invYPos + (row * sizePerSlot)));
            }
        }*/
        // Temporary layout
        //ARMOR
        this.addSlot(new Slot(this.peasantInventory, 0, 8, 8));
        this.addSlot(new Slot(this.peasantInventory, 1, 8, 26));
        this.addSlot(new Slot(this.peasantInventory, 2, 8, 44));
        this.addSlot(new Slot(this.peasantInventory, 3, 8, 62));
        //MAINHAND & OFFHAND
        this.addSlot(new Slot(this.peasantInventory, 4, 32, 62));
        this.addSlot(new Slot(this.peasantInventory, 5, 56, 62));
        //MAIN
        this.addSlot(new Slot(this.peasantInventory, 6, 80, 8));
        this.addSlot(new Slot(this.peasantInventory, 7, 98, 8));
        this.addSlot(new Slot(this.peasantInventory, 8, 116, 8));
        this.addSlot(new Slot(this.peasantInventory, 9, 134, 8));
        this.addSlot(new Slot(this.peasantInventory, 10, 152, 8));
        this.addSlot(new Slot(this.peasantInventory, 11, 80, 26));
        this.addSlot(new Slot(this.peasantInventory, 12, 98, 26));
        this.addSlot(new Slot(this.peasantInventory, 13, 116, 26));
        this.addSlot(new Slot(this.peasantInventory, 14, 134, 26));
        this.addSlot(new Slot(this.peasantInventory, 15, 152, 26));

        // Player Main Inventory
        for (int row = 0; row < 3; ++row) {
            for (int column = 0; column < 9; ++column) {
                this.addSlot(new Slot(player.inventory, column + row * 9 + 9, 8 + column * 18, 102 + row * 18 + -18));
            }
        }
        // Player Hotbar
        for (int row = 0; row < 9; ++row) {
            this.addSlot(new Slot(player.inventory, row, 8 + row * 18, 142));
        }
    }

    @Override
    public boolean canInteractWith(PlayerEntity playerIn) {
        return true;// peasant != null && playerIn.getDistance(peasant) <= PlayerEntity.REACH_DISTANCE.getDefaultValue() + 1;
    }

    public ItemStack transferStackInSlot(PlayerEntity playerIn, int index) {
        ItemStack itemstack = ItemStack.EMPTY;
        Slot slot = this.inventorySlots.get(index);
        if (slot != null && slot.getHasStack()) {
            ItemStack itemstack1 = slot.getStack();
            itemstack = itemstack1.copy();
            if (index < this.peasantInventory.getSizeInventory()) {
                if (!this.mergeItemStack(itemstack1, this.peasantInventory.getSizeInventory(), this.inventorySlots.size(), true)) {
                    return ItemStack.EMPTY;
                }
            } else if (!this.mergeItemStack(itemstack1, 0, this.peasantInventory.getSizeInventory(), false)) {
                return ItemStack.EMPTY;
            }

            if (itemstack1.isEmpty()) {
                slot.putStack(ItemStack.EMPTY);
            } else {
                slot.onSlotChanged();
            }
        }

        return itemstack;
    }

    public SiegeEntity getPeasant() {
        return this.peasant;
    }
}

Container Screen Class:

Spoiler

package com.siegemod.container;

import com.mojang.blaze3d.systems.RenderSystem;
import com.siegemod.SiegeMod;

import net.minecraft.client.gui.screen.inventory.ContainerScreen;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.text.ITextComponent;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;

@OnlyIn(Dist.CLIENT)
public class PeasantScreen extends ContainerScreen<PeasantContainer> {

    private static final ResourceLocation PEASANT_GUI = new ResourceLocation(SiegeMod.MODID, "gui/peasant_gui.png");

    public PeasantScreen(PeasantContainer screenContainer, PlayerInventory inv, ITextComponent titleIn) {
        super(screenContainer, inv, titleIn);
        this.guiLeft = 0;
        this.guiTop = 0;
        this.xSize = 176;
        this.ySize = 166;
    }

    @Override
    protected void init() {
        super.init();
    }

    @Override
    protected void drawGuiContainerBackgroundLayer(float partialTicks, int mouseX, int mouseY) {
        RenderSystem.color4f(1.0F, 1.0F, 1.0F, 1.0F);
        this.getMinecraft().getTextureManager().bindTexture(PEASANT_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
    public void render(int mouseX, int mouseY, float partialTicks) {
        this.renderBackground();
        super.render(mouseX, mouseY, partialTicks);
        this.renderHoveredToolTip(mouseX, mouseY);
    }
}

ContainerTypes Class:

Spoiler

package com.siegemod.container;

import com.siegemod.SiegeMod;

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 SiegeContainerTypes {

    public static final DeferredRegister<ContainerType<?>> CONTAINER_TYPES = new DeferredRegister<>(ForgeRegistries.CONTAINERS, SiegeMod.MODID);

    public static final RegistryObject<ContainerType<PeasantContainer>> PEASANT_CONTAINER = CONTAINER_TYPES.register(SiegeMod.MODID, () -> {
        return IForgeContainerType.create(PeasantContainer::new);
    });
}

ClientEventBusSubscriber:

Spoiler

package com.siegemod.util;

import com.siegemod.SiegeMod;
import com.siegemod.container.PeasantScreen;
import com.siegemod.container.SiegeContainerTypes;
import com.siegemod.entities.SiegeEntityTypes;
import com.siegemod.entities.render.PeasantRenderer;

import net.minecraft.client.gui.ScreenManager;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.client.registry.RenderingRegistry;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.Mod.EventBusSubscriber.Bus;
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;

@Mod.EventBusSubscriber(modid = SiegeMod.MODID, bus = Bus.MOD, value = Dist.CLIENT)
public class ClientEventBusSubscriber {

    @SubscribeEvent
    public static void clientSetup(FMLClientSetupEvent event) {

        ScreenManager.registerFactory(SiegeContainerTypes.PEASANT_CONTAINER.get(), PeasantScreen::new);

        RenderingRegistry.registerEntityRenderingHandler(SiegeEntityTypes.PEASANT.get(), PeasantRenderer::new);
    }
}

Main Class:

Spoiler

package com.siegemod;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import com.siegemod.container.SiegeContainerTypes;
import com.siegemod.entities.SiegeEntityTypes;

import net.minecraft.client.Minecraft;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
import net.minecraftforge.fml.event.server.FMLServerStartingEvent;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;

@Mod("siegemod")
public class SiegeMod {
    // this is what you'll use to output anything to the log (instead of sysout if
    // you like)
    public static final Logger LOGGER = LogManager.getLogger();
    public static final String MODID = "siegemod";
    public static SiegeMod instance;
    public static Minecraft mc = Minecraft.getInstance();

    public SiegeMod() {
        final IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus();

        instance = this;

        FMLJavaModLoadingContext.get().getModEventBus().addListener(this::setup);
        FMLJavaModLoadingContext.get().getModEventBus().addListener(this::doClientStuff);

        MinecraftForge.EVENT_BUS.register(this);

        SiegeEntityTypes.ENTITY_TYPES.register(modEventBus);
        SiegeContainerTypes.CONTAINER_TYPES.register(modEventBus);
    }

    private void setup(final FMLCommonSetupEvent event) {

    }

    private void doClientStuff(final FMLClientSetupEvent event) {

    }

    @SubscribeEvent
    public void onServerStarting(FMLServerStartingEvent event) {

    }

    // You can use EventBusSubscriber to automatically subscribe events on the
    // contained class (this is subscribing to the MOD
    // Event bus for receiving Registry Events)
    @Mod.EventBusSubscriber(bus = Mod.EventBusSubscriber.Bus.MOD)
    public static class RegistryEvents {
    }
}

I will be converting from Inventory to ItemHandler soon, but for now I just want the container to open.

 

--SOLUTION--

Main Entity Class:

Spoiler

package com.siegemod.entities;

import java.util.UUID;
import java.util.function.Consumer;

import com.siegemod.container.PeasantContainer;
import com.siegemod.container.PeasantInventory;

import net.minecraft.entity.AgeableEntity;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.ILivingEntityData;
import net.minecraft.entity.SharedMonsterAttributes;
import net.minecraft.entity.SpawnReason;
import net.minecraft.entity.ai.goal.HurtByTargetGoal;
import net.minecraft.entity.ai.goal.LookAtGoal;
import net.minecraft.entity.ai.goal.LookRandomlyGoal;
import net.minecraft.entity.ai.goal.MoveThroughVillageGoal;
import net.minecraft.entity.ai.goal.MoveTowardsTargetGoal;
import net.minecraft.entity.ai.goal.MoveTowardsVillageGoal;
import net.minecraft.entity.ai.goal.SwimGoal;
import net.minecraft.entity.merchant.villager.AbstractVillagerEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.entity.player.ServerPlayerEntity;
import net.minecraft.inventory.Inventory;
import net.minecraft.inventory.container.Container;
import net.minecraft.inventory.container.INamedContainerProvider;
import net.minecraft.item.ItemStack;
import net.minecraft.item.MerchantOffer;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.nbt.ListNBT;
import net.minecraft.network.PacketBuffer;
import net.minecraft.pathfinding.GroundPathNavigator;
import net.minecraft.util.Hand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.world.DifficultyInstance;
import net.minecraft.world.IWorld;
import net.minecraft.world.World;
import net.minecraftforge.fml.network.NetworkHooks;

public abstract class SiegeEntity extends AbstractVillagerEntity {
    private final PeasantInventory peasantInventory;
    private final SiegeEntityInventoryContainerProvider containerProvider;
    public SiegeEntity(EntityType<? extends AbstractVillagerEntity> entityType, World worldIn, PlayerEntity kingIn) {
        super(entityType, worldIn);
        this.peasantInventory = new PeasantInventory(new Inventory(16), this);
        this.containerProvider = new SiegeEntityInventoryContainerProvider(this);
    }
    @Override
    public final boolean processInteract(PlayerEntity player, Hand hand) {
        if (hand == Hand.MAIN_HAND && player instanceof ServerPlayerEntity && !world.isRemote) {
                SiegeEntity peasant = this;
                NetworkHooks.openGui((ServerPlayerEntity) player, this.containerProvider, new Consumer<PacketBuffer>() {
                    @Override
                    public void accept(PacketBuffer buffer) {
                        buffer.writeInt(peasant.getEntityId());
                    }
                });
                return true;
        }
        return super.processInteract(player, hand);
    }

    @Override
    public void writeAdditional(CompoundNBT compound) {
        super.writeAdditional(compound);
        ListNBT listnbt = new ListNBT();
        for (int i = 0; i < this.peasantInventory.getSlots(); ++i) {
            ItemStack itemstack = this.peasantInventory.getStackInSlot(i);
            if (!itemstack.isEmpty()) {
                listnbt.add(itemstack.write(new CompoundNBT()));
            }
        }
        compound.put("PeasantInventory", listnbt);
    }

    @Override
    public void readAdditional(CompoundNBT compound) {
        super.readAdditional(compound);

        ListNBT listnbt = compound.getList("PeasantInventory", 10);
        for (int i = 0; i < listnbt.size(); ++i) {
            ItemStack itemstack = ItemStack.read(listnbt.getCompound(i));
            if (!itemstack.isEmpty()) {
                this.peasantInventory.insertItem(i, itemstack, false);
            }
        }
    }

    public PeasantInventory getPeasantInventory() {
        return peasantInventory;
    }

    public class SiegeEntityInventoryContainerProvider implements INamedContainerProvider {

        private final SiegeEntity peasant;

        public SiegeEntityInventoryContainerProvider(SiegeEntity peasantIn) {
            this.peasant = peasantIn;
        }

        @Override
        public Container createMenu(int containerId, PlayerInventory playerInv, PlayerEntity player) {
            return new PeasantContainer(containerId, playerInv, this.peasant);
        }

        @Override
        public ITextComponent getDisplayName() {
            return peasant.getDisplayName();
        }
    }

ContainerFactory:

Spoiler

package com.siegemod.util;

import com.siegemod.container.PeasantContainer;

import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.inventory.container.Container;
import net.minecraft.network.PacketBuffer;
import net.minecraftforge.fml.network.IContainerFactory;

public class SiegeContainerFactory implements IContainerFactory<Container> {

    @Override
    public Container create(int windowId, PlayerInventory inv, PacketBuffer data) {
        return new PeasantContainer(windowId, inv, data);
    }
}

ScreenFactory:

Spoiler

package com.siegemod.util;

import com.siegemod.container.PeasantScreen;

import net.minecraft.client.gui.ScreenManager.IScreenFactory;
import net.minecraft.client.gui.screen.inventory.ContainerScreen;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.inventory.container.Container;
import net.minecraft.util.text.ITextComponent;

public class SiegeScreenFactory implements IScreenFactory<Container, ContainerScreen<Container>> {

    @Override
    public ContainerScreen<Container> create(Container container, PlayerInventory inv, ITextComponent ITextComponent) {
        return new PeasantScreen(container, inv, ITextComponent);
    }
}

Container Class:

Spoiler

package com.siegemod.container;

import com.mojang.datafixers.util.Pair;
import com.siegemod.entities.SiegeEntity;

import net.minecraft.enchantment.EnchantmentHelper;
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.PlayerContainer;
import net.minecraft.inventory.container.Slot;
import net.minecraft.item.ItemStack;
import net.minecraft.network.PacketBuffer;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;

public class PeasantContainer extends Container {

    public SiegeEntity peasant;
    public IInventory peasantInventory;

    public PeasantContainer(int containerId, PlayerInventory playerInv, PacketBuffer containerBuffer) {
        this(containerId, playerInv, (SiegeEntity) playerInv.player.world.getEntityByID(containerBuffer.readInt()));
    }

    public PeasantContainer(int containerId, PlayerInventory playerInv, SiegeEntity peasantIn) {
        super(SiegeContainerTypes.PEASANT_CONTAINER.get(), containerId);
        this.peasant = peasantIn;
        this.peasantInventory = peasant.getPeasantInventory().getInv();
        this.peasantInventory.openInventory(playerInv.player);

 

        // Entity Slots

 

        // Player Main Inventory
        for (int row = 0; row < 3; ++row)
            for (int column = 0; column < 9; ++column)
                this.addSlot(new Slot(playerInv, column + row * 9 + 9, 8 + column * 18, 102 + row * 18 + -18));

        // Player Hotbar
        for (int row = 0; row < 9; ++row) {
            this.addSlot(new Slot(playerInv, row, 8 + row * 18, 142));
        }
    }

    @Override
    public boolean canInteractWith(PlayerEntity playerIn) {
        return true;
    }

    @Override
    public ItemStack transferStackInSlot(PlayerEntity playerIn, int index) {
        ItemStack itemstack = ItemStack.EMPTY;
        Slot slot = this.inventorySlots.get(index);
        if (slot != null && slot.getHasStack()) {
            ItemStack itemstack1 = slot.getStack();
            itemstack = itemstack1.copy();
            if (index < this.peasantInventory.getSizeInventory()) {
                if (!this.mergeItemStack(itemstack1, this.peasantInventory.getSizeInventory(), this.inventorySlots.size(), true)) {
                    return ItemStack.EMPTY;
                }
            } else if (!this.mergeItemStack(itemstack1, 1, this.peasantInventory.getSizeInventory(), false)) {
                return ItemStack.EMPTY;
            }
            if (itemstack1.isEmpty()) {
                slot.putStack(ItemStack.EMPTY);
            } else {
                slot.onSlotChanged();
            }
        }
        return itemstack;
    }

    public SiegeEntity getPeasant() {
        return this.peasant;
    }
}

Screen Class:

Spoiler

package com.siegemod.container;

import com.mojang.blaze3d.systems.RenderSystem;
import com.siegemod.SiegeMod;
import com.siegemod.entities.SiegeEntity;

import net.minecraft.client.gui.screen.inventory.ContainerScreen;
import net.minecraft.client.gui.screen.inventory.InventoryScreen;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.inventory.container.Container;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.text.ITextComponent;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;

@OnlyIn(Dist.CLIENT)
public class PeasantScreen extends ContainerScreen<Container> {

    private static final ResourceLocation PEASANT_GUI = new ResourceLocation(SiegeMod.MODID, "gui/peasant_gui.png");

    private float mousePosx;
    private float mousePosY;

    private final SiegeEntity peasant;

    public PeasantScreen(Container screenContainer, PlayerInventory inv, ITextComponent titleIn) {
        super((PeasantContainer) screenContainer, inv, titleIn);
        this.peasant = ((PeasantContainer) screenContainer).getPeasant();
        this.guiLeft = 0;
        this.guiTop = 0;
        this.xSize = 176;
        this.ySize = 166;
    }

    @Override
    protected void drawGuiContainerBackgroundLayer(float partialTicks, int mouseX, int mouseY) {
        RenderSystem.color4f(1.0F, 1.0F, 1.0F, 1.0F);
        this.getMinecraft().getTextureManager().bindTexture(PEASANT_GUI);
        int i = (this.width - this.xSize) / 2;
        int j = (this.height - this.ySize) / 2;
        this.blit(i, j, 0, 0, this.xSize, this.ySize);
        InventoryScreen.drawEntityOnScreen(i + 52, j + 50, 22, (float) (i + 51) - this.mousePosx, (float) (j + 75 - 50) - this.mousePosY, this.peasant);
    }

    @Override
    public void render(int p_render_1_, int p_render_2_, float p_render_3_) {
        this.renderBackground();
        this.mousePosx = (float) p_render_1_;
        this.mousePosY = (float) p_render_2_;
        super.render(p_render_1_, p_render_2_, p_render_3_);
        this.renderHoveredToolTip(p_render_1_, p_render_2_);
    }
}

 

Edited by OuiOuiCroissant
Updated with solution
Link to comment
Share on other sites

Update!

I have discovered that I MUST use the required constructor:

Spoiler

public PeasantContainer(int containerId, PlayerInventory playerInv, PacketBuffer containerBuffer) {

However, I need both the Screen and Container classes to identify the entity they belong to.

 

I bet I can pass getEntityID through the PacketBuffer parameter of Container class. Do I make a new PacketBuffer in the createMenu method and give it Unpooled.buffer()?

Spoiler

        @Override
        public Container createMenu(int containerId, PlayerInventory playerInv, PlayerEntity player) {
            return new PeasantContainer(containerId, playerInv, new PacketBuffer(Unpooled.buffer().writeInt(PEASANT.getEntityId())));
        }

When I read it in the Container class it throws an IndexOutOfBoundsException. I will need to read up on how PacketBuffer works. I will update if I figure it out.

Spoiler

    public PeasantContainer(int containerId, PlayerInventory playerInv, PacketBuffer containerBuffer) {
        super(SiegeContainerTypes.PEASANT_CONTAINER.get(), containerId);
        this.peasant = (SiegeEntity) playerInv.player.world.getEntityByID(containerBuffer.readInt());

 

Link to comment
Share on other sites

IContainerFactory doesn't have a PacketBuffer field, it only exists as a parameter in its create() method. Where does an instance of PacketBuffer come from? Or should I create my own static instance in my container factory?

 

Implementing IContainerFactory on my container factory has me implement a create() method:

Spoiler

    @Override
    public Container create(int windowId, PlayerInventory inv, PacketBuffer data) {
        return null;
    }
}

But I cannot make a static instance of my container, right? And create() is not a static method so I can't call it from somewhere else. I have nothing to pass into widowId or playerInv from here either.

Spoiler

package com.siegemod.container;

import com.siegemod.SiegeMod;

import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.inventory.container.Container;
import net.minecraft.inventory.container.ContainerType;
import net.minecraft.network.PacketBuffer;
import net.minecraftforge.common.extensions.IForgeContainerType;
import net.minecraftforge.fml.RegistryObject;
import net.minecraftforge.fml.network.IContainerFactory;
import net.minecraftforge.registries.DeferredRegister;
import net.minecraftforge.registries.ForgeRegistries;

public class SiegeContainerTypes implements IContainerFactory<Container> {

    public static final DeferredRegister<ContainerType<?>> CONTAINER_TYPES = new DeferredRegister<>(ForgeRegistries.CONTAINERS, SiegeMod.MODID);

    public static final RegistryObject<ContainerType<PeasantContainer>> PEASANT_CONTAINER = CONTAINER_TYPES.register(SiegeMod.MODID, () -> {
        return IForgeContainerType.create(PeasantContainer::new);
    });

    @Override
    public Container create(int windowId, PlayerInventory inv, PacketBuffer data) {
        return null;
    }
}

 

Link to comment
Share on other sites

I just meant a static field to pass into NetworkHooks.openGui(ServerPlayerEntity, INamedContainerProvider, Consumer<PacketBuffer>) like so:

Spoiler

public static final PacketBuffer CONTAINER_PACKET = new PacketBuffer(Unpooled.buffer());

 

So far my container factory looks like:

Spoiler

package com.siegemod.util;

import com.siegemod.container.PeasantContainer;

import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.inventory.container.Container;
import net.minecraft.network.PacketBuffer;
import net.minecraftforge.fml.network.IContainerFactory;

public class SiegeContainerFactory implements IContainerFactory<Container> {

    @Override
    public Container create(int windowId, PlayerInventory inv, PacketBuffer data) {
        System.out.println("IContainerFactory#CREATE WAS RUN");
        return new PeasantContainer(windowId, inv, data);
    }
}

And I made a screen factory:

Spoiler

package com.siegemod.util;

import com.siegemod.container.PeasantScreen;

import net.minecraft.client.gui.ScreenManager.IScreenFactory;
import net.minecraft.client.gui.screen.inventory.ContainerScreen;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.inventory.container.Container;
import net.minecraft.util.text.ITextComponent;

public class SiegeScreenFactory implements IScreenFactory<Container, ContainerScreen<Container>> {

    @Override
    public ContainerScreen<Container> create(Container container, PlayerInventory inv, ITextComponent ITextComponent) {
        System.out.println("ScreenFactory#CREATE WAS RUN");
        return new PeasantScreen(container, inv, ITextComponent);
    }
}

Will both of these create() methods be run if I run NetworkHooks.openGui(ServerPlayerEntity, INamedContainerProvider, Consumer<PacketBuffer>) on the server side?

 

Thank you so much for your patience and help.

Link to comment
Share on other sites

Something I implement? As in I implement an interface? Or do you mean I create a new instance of PacketBuffer like so:

ContainerProvider:

Spoiler

    public class SiegeContainerProvider implements INamedContainerProvider {

        private final SiegeEntity peasant;

        public SiegeContainerProvider(SiegeEntity peasantIn) {
            this.peasant = peasantIn;
        }

        @Override
        public Container createMenu(int containerId, PlayerInventory playerInv, PlayerEntity player) {
            PacketBuffer containerPacket = new PacketBuffer(Unpooled.buffer());
            containerPacket.writeInt(peasant.getEntityId());
            return new PeasantContainer(containerId, playerInv, containerPacket);
        }

        @Override
        public ITextComponent getDisplayName() {
            return peasant.getDisplayName();
        }
    }

Here are my other classes as they currently are:

EntityClass:

Spoiler

package com.siegemod.entities;

import java.util.UUID;

import com.siegemod.container.PeasantContainer;
import com.siegemod.container.PeasantInventory;

import io.netty.buffer.Unpooled;
import net.minecraft.entity.AgeableEntity;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.ILivingEntityData;
import net.minecraft.entity.SharedMonsterAttributes;
import net.minecraft.entity.SpawnReason;
import net.minecraft.entity.ai.goal.HurtByTargetGoal;
import net.minecraft.entity.ai.goal.LookAtGoal;
import net.minecraft.entity.ai.goal.LookRandomlyGoal;
import net.minecraft.entity.ai.goal.MoveThroughVillageGoal;
import net.minecraft.entity.ai.goal.MoveTowardsTargetGoal;
import net.minecraft.entity.ai.goal.MoveTowardsVillageGoal;
import net.minecraft.entity.ai.goal.SwimGoal;
import net.minecraft.entity.merchant.villager.AbstractVillagerEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.entity.player.ServerPlayerEntity;
import net.minecraft.inventory.Inventory;
import net.minecraft.inventory.container.Container;
import net.minecraft.inventory.container.INamedContainerProvider;
import net.minecraft.item.ItemStack;
import net.minecraft.item.MerchantOffer;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.nbt.ListNBT;
import net.minecraft.network.PacketBuffer;
import net.minecraft.pathfinding.GroundPathNavigator;
import net.minecraft.util.Hand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.world.DifficultyInstance;
import net.minecraft.world.IWorld;
import net.minecraft.world.World;
import net.minecraftforge.fml.network.NetworkHooks;

public abstract class SiegeEntity extends AbstractVillagerEntity {

    protected final double walkSpeed = 0.4D;
    // Convert to ItemHandler
    private final PeasantInventory peasantInventory;
    private final SiegeContainerProvider containerProvider;

    // 0 = wander, 1 = follow, 2 = locked follow, 3 = guard, 4 = locked guard.
    protected double stance = 0;
    // The main controller of this peasant
    protected UUID kingUniqueID;
    // Allowed to control this peasant and access inventory
    protected UUID[] royalFamily;
    // Will not attack/be attacked by the soldiers of people on this list
    protected UUID[] allies;

    protected BlockPos destination;
    protected ItemStack targetItem;

    public SiegeEntity(EntityType<? extends AbstractVillagerEntity> entityType, World worldIn, PlayerEntity kingIn) {
        super(entityType, worldIn);
        this.peasantInventory = new PeasantInventory(new Inventory(16), this);
        this.containerProvider = new SiegeContainerProvider(this);
        if (kingIn != null)
            this.kingUniqueID = kingIn.getUniqueID();

        ((GroundPathNavigator) this.getNavigator()).setBreakDoors(true);
        this.getNavigator().setCanSwim(true);
        this.setCanPickUpLoot(true);
    }

    @Override
    public ILivingEntityData onInitialSpawn(IWorld worldIn, DifficultyInstance difficultyIn, SpawnReason reason, ILivingEntityData spawnDataIn, CompoundNBT dataTag) {
        if (!world.isRemote && reason == SpawnReason.COMMAND)
            this.setKing(world.getClosestPlayer(this, 999).getUniqueID());
        if (this.rand.nextInt(10) == 0)
            this.setLeftHanded(true);
        return super.onInitialSpawn(worldIn, difficultyIn, reason, spawnDataIn, dataTag);
    }

    @Override
    protected void registerGoals() {
        super.registerGoals();
        this.goalSelector.addGoal(0, new SwimGoal(this));
        // We're going to need a custom avoid entity goal
        // We're going to need a custom choose target goal 
        // We're going to need a custom "wander near player bed while unclaimed but eventually wander away and despawn" goal
        this.goalSelector.addGoal(2, new MoveTowardsTargetGoal(this, this.walkSpeed, 32.0F));
        this.goalSelector.addGoal(2, new MoveTowardsVillageGoal(this, this.walkSpeed));
        this.goalSelector.addGoal(3, new MoveThroughVillageGoal(this, this.walkSpeed, false, 4, () -> {
            return false;
        }));
        this.goalSelector.addGoal(7, new LookAtGoal(this, PlayerEntity.class, 6.0F));
        this.goalSelector.addGoal(8, new LookRandomlyGoal(this));

        this.targetSelector.addGoal(2, new HurtByTargetGoal(this));
    }

    @Override
    protected void registerAttributes() {
        super.registerAttributes();
        this.getAttribute(SharedMonsterAttributes.MAX_HEALTH).setBaseValue(20.0D);
        this.getAttribute(SharedMonsterAttributes.FOLLOW_RANGE).setBaseValue(64.0D);
        this.getAttribute(SharedMonsterAttributes.MOVEMENT_SPEED).setBaseValue(this.walkSpeed);

        this.getAttributes().registerAttribute(SharedMonsterAttributes.ATTACK_DAMAGE).setBaseValue(1.0D);

        this.getAttribute(SharedMonsterAttributes.ARMOR).setBaseValue(0.0D);
        this.getAttribute(SharedMonsterAttributes.ARMOR_TOUGHNESS).setBaseValue(0.0D);
        this.getAttribute(SharedMonsterAttributes.KNOCKBACK_RESISTANCE).setBaseValue(10.0F);
    }

    @Override
    public boolean attackEntityAsMob(Entity entityIn) {
        this.swingArm(getActiveHand());
        return super.attackEntityAsMob(entityIn);
    }

    public void livingTick() {
        this.updateArmSwingProgress();
        super.livingTick();
    }

    public void writeAdditional(CompoundNBT compound) {
        super.writeAdditional(compound);
        ListNBT listnbt = new ListNBT();
        for (int i = 0; i < this.peasantInventory.getSlots(); ++i) {
            ItemStack itemstack = this.peasantInventory.getStackInSlot(i);
            if (!itemstack.isEmpty()) {
                listnbt.add(itemstack.write(new CompoundNBT()));
            }
        }
        compound.put("PeasantInventory", listnbt);

        if (this.kingUniqueID != null)
            compound.putUniqueId("KingId", this.kingUniqueID);
    }

    public void readAdditional(CompoundNBT compound) {
        super.readAdditional(compound);

        ListNBT listnbt = compound.getList("PeasantInventory", 10);
        for (int i = 0; i < listnbt.size(); ++i) {
            ItemStack itemstack = ItemStack.read(listnbt.getCompound(i));
            if (!itemstack.isEmpty()) {
                this.peasantInventory.insertItem(i, itemstack, false);
            }
        }

        if (this.kingUniqueID == null && compound.hasUniqueId("KingId")) {
            this.setKing(compound.getUniqueId("KingId"));
        }
    }

    public PlayerEntity getKing() {
        return world.getPlayerByUuid(this.kingUniqueID);
    }

    public void setKing(UUID playerUUIDIn) {
        this.kingUniqueID = playerUUIDIn;
    }

    @Override
    public final boolean processInteract(PlayerEntity player, Hand hand) {
        if (hand == Hand.MAIN_HAND && !world.isRemote) {
            if (player.getUniqueID() == this.kingUniqueID && player instanceof ServerPlayerEntity && !world.isRemote) {
                NetworkHooks.openGui((ServerPlayerEntity) player, this.containerProvider);
                return true;
            }
        }
        return super.processInteract(player, hand);
    }

    public PeasantInventory getPeasantInventory() {
        return peasantInventory;
    }
    /*
    public DyeColor getPrimaryColor() {
        return DyeColor.byId(this.dataManager.get(COLLAR_COLOR));
    }
    
    public void setSecondaryColor(DyeColor collarcolor) {
        this.dataManager.set(COLLAR_COLOR, collarcolor.getId());
    }*/

    @Override
    public AgeableEntity createChild(AgeableEntity ageable) {
        return null;
    }

    @Override
    protected void onVillagerTrade(MerchantOffer offer) {
    }

    @Override
    protected void populateTradeData() {
    }

}

Container Factory:

Spoiler

package com.siegemod.util;

import com.siegemod.container.PeasantContainer;

import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.inventory.container.Container;
import net.minecraft.network.PacketBuffer;
import net.minecraftforge.fml.network.IContainerFactory;

public class SiegeContainerFactory implements IContainerFactory<Container> {

    @Override
    public Container create(int windowId, PlayerInventory inv, PacketBuffer data) {
        return new PeasantContainer(windowId, inv, data);
    }

}

Screen Factory:

Spoiler

package com.siegemod.util;

import com.siegemod.container.PeasantScreen;

import net.minecraft.client.gui.ScreenManager.IScreenFactory;
import net.minecraft.client.gui.screen.inventory.ContainerScreen;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.inventory.container.Container;
import net.minecraft.util.text.ITextComponent;

public class SiegeScreenFactory implements IScreenFactory<Container, ContainerScreen<Container>> {

    @Override
    public ContainerScreen<Container> create(Container container, PlayerInventory inv, ITextComponent ITextComponent) {
        return new PeasantScreen(container, inv, ITextComponent);
    }

}

Container:

Spoiler

package com.siegemod.container;

import com.mojang.datafixers.util.Pair;
import com.siegemod.entities.SiegeEntity;

import net.minecraft.enchantment.EnchantmentHelper;
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.PlayerContainer;
import net.minecraft.inventory.container.Slot;
import net.minecraft.item.ItemStack;
import net.minecraft.network.PacketBuffer;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;

public class PeasantContainer extends Container {

    public SiegeEntity peasant;
    public IInventory peasantInventory;

    public static final EquipmentSlotType[] VALID_EQUIPMENT_SLOTS = new EquipmentSlotType[] { EquipmentSlotType.HEAD, EquipmentSlotType.CHEST, EquipmentSlotType.LEGS, EquipmentSlotType.FEET };
    private static final ResourceLocation[] ARMOR_SLOT_TEXTURES = new ResourceLocation[] { PlayerContainer.EMPTY_ARMOR_SLOT_BOOTS, PlayerContainer.EMPTY_ARMOR_SLOT_LEGGINGS,
            PlayerContainer.EMPTY_ARMOR_SLOT_CHESTPLATE, PlayerContainer.EMPTY_ARMOR_SLOT_HELMET };

    public PeasantContainer(int containerId, PlayerInventory playerInv, PacketBuffer containerBuffer) {
        super(SiegeContainerTypes.PEASANT_CONTAINER.get(), containerId);
        this.peasant = (SiegeEntity) playerInv.player.world.getEntityByID(containerBuffer.readInt());
        this.peasantInventory = peasant.getPeasantInventory().getInv();
        this.peasantInventory.openInventory(playerInv.player);

        // MainHand 0
        this.addSlot(new Slot(this.peasantInventory, 0, 32, 62) {

            @Override
            public void onSlotChanged() {
                super.onSlotChanged();
                peasant.getPeasantInventory().markDirty();
            }
        });

        //Armor 1-4
        for (int row = 0; row < 4; row++) {
            final EquipmentSlotType equipmentslottype = VALID_EQUIPMENT_SLOTS[row];
            this.addSlot(new Slot(this.peasantInventory, row + 1, 8, 8 + row * 18) {

                @Override
                public void onSlotChanged() {
                    super.onSlotChanged();
                    peasant.getPeasantInventory().markDirty();
                }

                @Override
                public int getSlotStackLimit() {
                    return 1;
                }

                @Override
                public boolean isItemValid(ItemStack stack) {
                    return stack.canEquip(equipmentslottype, peasant);
                }

                @Override
                public boolean canTakeStack(PlayerEntity playerIn) {
                    ItemStack itemstack = this.getStack();
                    return !itemstack.isEmpty() && !playerIn.isCreative() && EnchantmentHelper.hasBindingCurse(itemstack) ? false : super.canTakeStack(playerIn);
                }

                @OnlyIn(Dist.CLIENT)
                public Pair<ResourceLocation, ResourceLocation> func_225517_c_() {
                    return Pair.of(PlayerContainer.LOCATION_BLOCKS_TEXTURE, ARMOR_SLOT_TEXTURES[equipmentslottype.getIndex()]);
                }
            });
        }

        // OffHand 5
        this.addSlot(new Slot(this.peasantInventory, 5, 56, 62) {

            @Override
            public void onSlotChanged() {
                super.onSlotChanged();
                peasant.getPeasantInventory().markDirty();
            }

            @OnlyIn(Dist.CLIENT)
            public Pair<ResourceLocation, ResourceLocation> func_225517_c_() {
                return Pair.of(PlayerContainer.LOCATION_BLOCKS_TEXTURE, PlayerContainer.EMPTY_ARMOR_SLOT_SHIELD);
            }
        });

        // Main Inventory 6-15
        final int invXPos = 80;
        final int invYPos = 8;
        final int height = 2;
        final int length = 5;
        for (int row = 0; row < height; row++)
            for (int column = 0; column < length; column++)
                this.addSlot(new Slot(this.peasantInventory, (row * length) + column + 6, invXPos + column * 18, invYPos + row * 18));

        // Player Main Inventory
        for (int row = 0; row < 3; ++row)
            for (int column = 0; column < 9; ++column)
                this.addSlot(new Slot(playerInv, column + row * 9 + 9, 8 + column * 18, 102 + row * 18 + -18));

        // Player Hotbar
        for (int row = 0; row < 9; ++row) {
            this.addSlot(new Slot(playerInv, row, 8 + row * 18, 142));
        }
    }

    @Override
    public boolean canInteractWith(PlayerEntity playerIn) {
        return peasant != null && ((playerIn == peasant.getKing() && playerIn.getDistance(peasant) <= PlayerEntity.REACH_DISTANCE.getDefaultValue() + 1) || playerIn.isCreative());
    }

    @Override
    public ItemStack transferStackInSlot(PlayerEntity playerIn, int index) {
        ItemStack itemstack = ItemStack.EMPTY;
        Slot slot = this.inventorySlots.get(index);
        if (slot != null && slot.getHasStack()) {
            ItemStack itemstack1 = slot.getStack();
            itemstack = itemstack1.copy();
            if (index < this.peasantInventory.getSizeInventory()) {
                if (!this.mergeItemStack(itemstack1, this.peasantInventory.getSizeInventory(), this.inventorySlots.size(), true)) {
                    return ItemStack.EMPTY;
                }
            } else if (!this.mergeItemStack(itemstack1, 1, this.peasantInventory.getSizeInventory(), false)) {
                return ItemStack.EMPTY;
            }
            if (itemstack1.isEmpty()) {
                slot.putStack(ItemStack.EMPTY);
            } else {
                slot.onSlotChanged();
            }
        }
        return itemstack;
    }

    public SiegeEntity getPeasant() {
        return this.peasant;
    }
}

Link to comment
Share on other sites

Like so?

Spoiler

    @Override
    public final boolean processInteract(PlayerEntity player, Hand hand) {
        if (hand == Hand.MAIN_HAND && player instanceof ServerPlayerEntity && !world.isRemote) {
            if (this.hasKing() && this.isKing(player)) {
                SiegeEntity peasant = this;
                NetworkHooks.openGui((ServerPlayerEntity) player, this.containerProvider, new Consumer<PacketBuffer>() {
                    @Override
                    public void accept(PacketBuffer buffer) {
                        buffer.writeInt(peasant.getEntityId());
                    }
                });

                return true;
            } else if (!this.hasKing()) {
                return super.processInteract(player, hand);
            }
        }
        return super.processInteract(player, hand);
    }

Link to comment
Share on other sites

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.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Announcements



×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.