Jump to content

Help with GUI opening.


AlmightyElement

Recommended Posts

 

Hello,

It's my first time working with Gui's and containers within forge.

I created a basic mod that includes two containers: a chest and a sort of furnace,

but I can't seem to acces them no matter what I try.

 

onBlockActivated gets called but the GUI jus't doesn't want to open. 

I hope someone can help me 

 

BlockLogStripper:

package com.almightyelement.thirteen.objects.machines.stripper;

import java.util.Random;

import com.almightyelement.thirteen.Main;
import com.almightyelement.thirteen.init.ModBlocks;
import com.almightyelement.thirteen.items.BlockBase;
import com.almightyelement.thirteen.objects.tileentity.TileEntityLogStripper;
import com.almightyelement.thirteen.util.Reference;

import com.almightyelement.thirteen.Main;
import com.almightyelement.thirteen.objects.tileentity.TileEntityLogStripper;
import com.almightyelement.thirteen.util.Reference;

import net.minecraft.block.BlockHorizontal;
import net.minecraft.block.SoundType;
import net.minecraft.block.material.Material;
import net.minecraft.block.properties.IProperty;
import net.minecraft.block.properties.PropertyBool;
import net.minecraft.block.properties.PropertyDirection;
import net.minecraft.block.state.BlockStateContainer;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumBlockRenderType;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraft.util.Mirror;
import net.minecraft.util.Rotation;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;

public class BlockLogStripper extends BlockBase
{
	public static final PropertyDirection FACING = BlockHorizontal.FACING;
	public static final PropertyBool BURNING = PropertyBool.create("burning");
	
	public BlockLogStripper(String name) 
	{
		super(name, Material.IRON);
		setSoundType(SoundType.METAL);
		this.setDefaultState(this.blockState.getBaseState().withProperty(FACING, EnumFacing.NORTH).withProperty(BURNING, false));
	}
	
	@Override
	public Item getItemDropped(IBlockState state, Random rand, int fortune) 
	{
		return Item.getItemFromBlock(ModBlocks.LOG_STRIPPER);
	}
	
	@Override
	public ItemStack getItem(World worldIn, BlockPos pos, IBlockState state)
	{
		return new ItemStack(ModBlocks.LOG_STRIPPER);
	}
	

	@Override
	public boolean onBlockActivated(World worldIn, BlockPos pos, IBlockState state, EntityPlayer playerIn, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ) 
	{
		if(!worldIn.isRemote)
		{
			playerIn.openGui(Main.instance, Reference.GUI_LOG_STRIPPER, worldIn, pos.getX(), pos.getY(), pos.getZ());
		}
		
		return true;
	}
	
	@Override
	public void onBlockAdded(World worldIn, BlockPos pos, IBlockState state) 
	{
		if (!worldIn.isRemote) 
        {
            IBlockState north = worldIn.getBlockState(pos.north());
            IBlockState south = worldIn.getBlockState(pos.south());
            IBlockState west = worldIn.getBlockState(pos.west());
            IBlockState east = worldIn.getBlockState(pos.east());
            EnumFacing face = (EnumFacing)state.getValue(FACING);

            if (face == EnumFacing.NORTH && north.isFullBlock() && !south.isFullBlock()) face = EnumFacing.SOUTH;
            else if (face == EnumFacing.SOUTH && south.isFullBlock() && !north.isFullBlock()) face = EnumFacing.NORTH;
            else if (face == EnumFacing.WEST && west.isFullBlock() && !east.isFullBlock()) face = EnumFacing.EAST;
            else if (face == EnumFacing.EAST && east.isFullBlock() && !west.isFullBlock()) face = EnumFacing.WEST;
            worldIn.setBlockState(pos, state.withProperty(FACING, face), 2);
        }
	}
	
	public static void setState(boolean active, World worldIn, BlockPos pos) 
	{
		IBlockState state = worldIn.getBlockState(pos);
		TileEntity tileentity = worldIn.getTileEntity(pos);
		
		if(active) worldIn.setBlockState(pos, ModBlocks.LOG_STRIPPER.getDefaultState().withProperty(FACING, state.getValue(FACING)).withProperty(BURNING, true), 3);
		else worldIn.setBlockState(pos, ModBlocks.LOG_STRIPPER.getDefaultState().withProperty(FACING, state.getValue(FACING)).withProperty(BURNING, false), 3);
		
		if(tileentity != null) 
		{
			tileentity.validate();
			worldIn.setTileEntity(pos, tileentity);
		}
	}
	
	@Override
	public boolean hasTileEntity(IBlockState state) 
	{
		return true;
	}
	
	@Override
	public TileEntity createTileEntity(World world, IBlockState state) 
	{
		return new TileEntityLogStripper();
	}
	
	@Override
	public IBlockState getStateForPlacement(World world, BlockPos pos, EnumFacing facing, float hitX, float hitY, float hitZ, int meta, EntityLivingBase placer, EnumHand hand) 
	{
		return this.getDefaultState().withProperty(FACING, placer.getHorizontalFacing().getOpposite());
	}
	
	@Override
	public void onBlockPlacedBy(World worldIn, BlockPos pos, IBlockState state, EntityLivingBase placer, ItemStack stack) 
	{
		worldIn.setBlockState(pos, this.getDefaultState().withProperty(FACING, placer.getHorizontalFacing().getOpposite()), 2);
	}
	
	@Override
	public EnumBlockRenderType getRenderType(IBlockState state) 
	{
		return EnumBlockRenderType.MODEL;
	}
	
	@Override
	public IBlockState withRotation(IBlockState state, Rotation rot)
	{
		return state.withProperty(FACING, rot.rotate((EnumFacing)state.getValue(FACING)));
	}
	
	@Override
	public IBlockState withMirror(IBlockState state, Mirror mirrorIn) 
	{
		return state.withRotation(mirrorIn.toRotation((EnumFacing)state.getValue(FACING)));
	}
	
	@Override
	protected BlockStateContainer createBlockState() 
	{
		return new BlockStateContainer(this, new IProperty[] {BURNING,FACING});
	}
	
	@Override
	public IBlockState getStateFromMeta(int meta) 
	{
		EnumFacing facing = EnumFacing.getFront(meta);
		if(facing.getAxis() == EnumFacing.Axis.Y) facing = EnumFacing.NORTH;
		return this.getDefaultState().withProperty(FACING, facing);
	}
	
	@Override
	public int getMetaFromState(IBlockState state) 
	{
		return ((EnumFacing)state.getValue(FACING)).getIndex();
	}	
}

GuiLogStripper:

package com.almightyelement.thirteen.objects.machines.stripper;


import com.almightyelement.thirteen.objects.tileentity.TileEntityLogStripper;
import com.almightyelement.thirteen.util.Reference;

import net.minecraft.client.gui.inventory.GuiContainer;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.util.ResourceLocation;

public class GuiLogStripper extends GuiContainer
{
	private static final ResourceLocation TEXTURES = new ResourceLocation(Reference.MOD_ID + ":textures/gui/log_stripper.png");
	private final InventoryPlayer player;
	private final TileEntityLogStripper tileentity;
	
	public GuiLogStripper(InventoryPlayer player, TileEntityLogStripper tileentity) 
	{
		super(new ContainerLogStripper(player, tileentity));
		this.player = player;
		this.tileentity = tileentity;
	}
	
	@Override
	protected void drawGuiContainerForegroundLayer(int mouseX, int mouseY) 
	{
		String tileName = this.tileentity.getDisplayName().getUnformattedText();
		this.fontRenderer.drawString(tileName, (this.xSize / 2 - this.fontRenderer.getStringWidth(tileName) / 2) + 3, 8, 4210752);
		this.fontRenderer.drawString(this.player.getDisplayName().getUnformattedText(), 122, this.ySize - 96 + 2, 4210752);
	}
	
	@Override
	protected void drawGuiContainerBackgroundLayer(float partialTicks, int mouseX, int mouseY)
	{
		GlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f);
		this.mc.getTextureManager().bindTexture(TEXTURES);
		this.drawTexturedModalRect(this.guiLeft, this.guiTop, 0, 0, this.xSize, this.ySize);
		
		if(TileEntityLogStripper.isBurning(tileentity))
		{
			int k = this.getBurnLeftScaled(13);
			this.drawTexturedModalRect(this.guiLeft + 8, this.guiTop + 54 + 12 - k, 176, 12 - k, 14, k + 1);
		}
		
		int l = this.getCookProgressScaled(24);
		this.drawTexturedModalRect(this.guiLeft + 44, this.guiTop + 36, 176, 14, l + 1, 16);
	}
	
	private int getBurnLeftScaled(int pixels)
	{
		int i = this.tileentity.getField(1);
		if(i == 0) i = 200;
		return this.tileentity.getField(0) * pixels / i;
	}
	
	private int getCookProgressScaled(int pixels)
	{
		int i = this.tileentity.getField(2);
		int j = this.tileentity.getField(3);
		return j != 0 && i != 0 ? i * pixels / j : 0;
	}
}

GuiHandler:

package com.almightyelement.thirteen.util.handlers;

import com.almightyelement.thirteen.objects.container.ContainerCopperChest;
import com.almightyelement.thirteen.objects.container.ContainerLogStripper;
import com.almightyelement.thirteen.objects.gui.GuiCopperChest;
import com.almightyelement.thirteen.objects.gui.GuiLogStripper;
import com.almightyelement.thirteen.objects.tileentity.TileEntityCopperChest;
import com.almightyelement.thirteen.objects.tileentity.TileEntityLogStripper;
import com.almightyelement.thirteen.util.Reference;

import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraftforge.fml.common.network.IGuiHandler;

public class GuiHandler implements IGuiHandler
{
	@Override
	public Object getServerGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z) 
	{
		if(ID == Reference.GUI_LOG_STRIPPER) return new ContainerLogStripper(player.inventory, (TileEntityLogStripper)world.getTileEntity(new BlockPos(x,y,z)));
		if(ID == Reference.GUI_COPPER_CHEST) return new ContainerCopperChest(player.inventory, (TileEntityCopperChest)world.getTileEntity(new BlockPos(x,y,z)), player);

		return null;

	}
	
	@Override
	public Object getClientGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z){
		if(ID == Reference.GUI_LOG_STRIPPER) return new GuiLogStripper(player.inventory, (TileEntityLogStripper)world.getTileEntity(new BlockPos(x,y,z)));
		if(ID == Reference.GUI_COPPER_CHEST) return new GuiCopperChest(player.inventory, (TileEntityCopperChest)world.getTileEntity(new BlockPos(x,y,z)), player);

		return null;

	}
}

 

Thanks in advance,

AlmightyElement

Edited by AlmightyElement
Additional info
Link to comment
Share on other sites

1 hour ago, AlmightyElement said:

extends BlockBase

BlockBase is an antipattern. You don't need it.

 

@Override
	public Item getItemDropped(IBlockState state, Random rand, int fortune) 
	{
		return Item.getItemFromBlock(ModBlocks.LOG_STRIPPER);
	}
	
	@Override
	public ItemStack getItem(World worldIn, BlockPos pos, IBlockState state)
	{
		return new ItemStack(ModBlocks.LOG_STRIPPER);
	}
@Override
	public EnumBlockRenderType getRenderType(IBlockState state) 
	{
		return EnumBlockRenderType.MODEL;
	}

These are not needed at all. This is the default implementation of these methods. There is no reason to override them since you are not providing a different implementation.

 

Don't set the blockstate in Block#onBlockPlaced and Block#onBlockPlacedBy. Return the blockstate you need in Block#getStateForPlacement.

 

if(tileentity != null) 
		{
			tileentity.validate();
			worldIn.setTileEntity(pos, tileentity);
		}

You do not need these TE manipulations. Just override TileEntity#shouldRefresh and return false if it is a simple blockstate property change.

 

You have not provided enough code. Have you registered your IGuiHandler implementation at all? Does your container override Container#canInteractWith and if it does what does it return there? And if it references your TEs what do they return in their methods? What did the debugger told you? Are your IGuiHandler methods being invoked? Are your Container/GUI constructors getting invoked?

Link to comment
Share on other sites

Hey,

This is a guiHandler that I'm using

 

package com.almightyelement.thirteen.util.handlers;

import com.almightyelement.thirteen.objects.container.ContainerCopperChest;
import com.almightyelement.thirteen.objects.container.ContainerLogStripper;
import com.almightyelement.thirteen.objects.gui.GuiCopperChest;
import com.almightyelement.thirteen.objects.gui.GuiLogStripper;
import com.almightyelement.thirteen.objects.tileentity.TileEntityCopperChest;
import com.almightyelement.thirteen.objects.tileentity.TileEntityLogStripper;
import com.almightyelement.thirteen.util.Reference;

import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraftforge.fml.common.network.IGuiHandler;

public class GuiHandler implements IGuiHandler
{
	@Override
	public Object getServerGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z) 
	{
		if(ID == Reference.GUI_LOG_STRIPPER) return new ContainerLogStripper(player.inventory, (TileEntityLogStripper)world.getTileEntity(new BlockPos(x,y,z)));
		if(ID == Reference.GUI_COPPER_CHEST) return new ContainerCopperChest(player.inventory, (TileEntityCopperChest)world.getTileEntity(new BlockPos(x,y,z)), player);

		return null;

	}
	
	@Override
	public Object getClientGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z){
		if(ID == Reference.GUI_LOG_STRIPPER) return new GuiLogStripper(player.inventory, (TileEntityLogStripper)world.getTileEntity(new BlockPos(x,y,z)));
		if(ID == Reference.GUI_COPPER_CHEST) return new GuiCopperChest(player.inventory, (TileEntityCopperChest)world.getTileEntity(new BlockPos(x,y,z)), player);

		return null;

	}
}

This is the container:

package com.almightyelement.thirteen.objects.machines.stripper;

import com.almightyelement.thirteen.objects.recipes.LogStripperRecipes;
import com.almightyelement.thirteen.objects.tileentity.TileEntityCopperChest;
import com.almightyelement.thirteen.objects.tileentity.TileEntityLogStripper;

import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.inventory.Container;
import net.minecraft.inventory.IContainerListener;
import net.minecraft.inventory.Slot;
import net.minecraft.item.ItemStack;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.SlotItemHandler;

public class ContainerLogStripper extends Container {
//{InventoryPlayer playerInv; TileEntityCopperChest tileEntityCopperChest;}
	private final TileEntityLogStripper tileentity;
	private int cookTime, totalCookTime, burnTime, currentBurnTime;
	
	public ContainerLogStripper(InventoryPlayer player, TileEntityLogStripper tileentity) 
	{
		this.tileentity = tileentity;
		IItemHandler handler = tileentity.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null);
		
		this.addSlotToContainer(new SlotItemHandler(handler, 0, 26, 11));
		this.addSlotToContainer(new SlotItemHandler(handler, 1, 26, 59));
		this.addSlotToContainer(new SlotItemHandler(handler, 2, 7, 35));
		this.addSlotToContainer(new SlotItemHandler(handler, 3, 81, 36));
		
		for(int y = 0; y < 3; y++)
		{
			for(int x = 0; x < 9; x++)
			{
				this.addSlotToContainer(new Slot(player, x + y*9 + 9, 8 + x*18, 84 + y*18));
			}
		}
		
		for(int x = 0; x < 9; x++)
		{
			this.addSlotToContainer(new Slot(player, x, 8 + x * 18, 142));
		}
	}
	
	@Override
	public void detectAndSendChanges() 
	{
		super.detectAndSendChanges();
		
		for(int i = 0; i < this.listeners.size(); ++i) 
		{
			IContainerListener listener = (IContainerListener)this.listeners.get(i);
			
			if(this.cookTime != this.tileentity.getField(2)) listener.sendWindowProperty(this, 2, this.tileentity.getField(2));
			if(this.burnTime != this.tileentity.getField(0)) listener.sendWindowProperty(this, 0, this.tileentity.getField(0));
			if(this.currentBurnTime != this.tileentity.getField(1)) listener.sendWindowProperty(this, 1, this.tileentity.getField(1));
			if(this.totalCookTime != this.tileentity.getField(3)) listener.sendWindowProperty(this, 3, this.tileentity.getField(3));
		}
		
		this.cookTime = this.tileentity.getField(2);
		this.burnTime = this.tileentity.getField(0);
		this.currentBurnTime = this.tileentity.getField(1);
		this.totalCookTime = this.tileentity.getField(3);
	}
	
	@Override
	@SideOnly(Side.CLIENT)
	public void updateProgressBar(int id, int data) 
	{
		this.tileentity.setField(id, data);
	}
	
	@Override
	public boolean canInteractWith(EntityPlayer playerIn) 
	{
		return this.tileentity.isUsableByPlayer(playerIn);
	}
	
	@Override
	public ItemStack transferStackInSlot(EntityPlayer playerIn, int index) 
	{
		ItemStack stack = ItemStack.EMPTY;
		Slot slot = (Slot)this.inventorySlots.get(index);
		
		if(slot != null && slot.getHasStack()) 
		{
			ItemStack stack1 = slot.getStack();
			stack = stack1.copy();
			
			if(index == 3) 
			{
				if(!this.mergeItemStack(stack1, 4, 40, true)) return ItemStack.EMPTY;
				slot.onSlotChange(stack1, stack);
			}
			else if(index != 2 && index != 1 && index != 0) 
			{		
				Slot slot1 = (Slot)this.inventorySlots.get(index + 1);
				
				if(!LogStripperRecipes.getInstance().getLogStripperResult(stack1, slot1.getStack()).isEmpty())
				{
					if(!this.mergeItemStack(stack1, 0, 2, false)) 
					{
						return ItemStack.EMPTY;
					}
					else if(TileEntityLogStripper.isItemFuel(stack1))
					{
						if(!this.mergeItemStack(stack1, 2, 3, false)) return ItemStack.EMPTY;
					}
					else if(TileEntityLogStripper.isItemFuel(stack1))
					{
						if(!this.mergeItemStack(stack1, 2, 3, false)) return ItemStack.EMPTY;
					}
					else if(TileEntityLogStripper.isItemFuel(stack1))
					{
						if(!this.mergeItemStack(stack1, 2, 3, false)) return ItemStack.EMPTY;
					}
					else if(index >= 4 && index < 31)
					{
						if(!this.mergeItemStack(stack1, 31, 40, false)) return ItemStack.EMPTY;
					}
					else if(index >= 31 && index < 40 && !this.mergeItemStack(stack1, 4, 31, false))
					{
						return ItemStack.EMPTY;
					}
				}
			} 
			else if(!this.mergeItemStack(stack1, 4, 40, false)) 
			{
				return ItemStack.EMPTY;
			}
			if(stack1.isEmpty())
			{
				slot.putStack(ItemStack.EMPTY);
			}
			else
			{
				slot.onSlotChanged();

			}
			if(stack1.getCount() == stack.getCount()) return ItemStack.EMPTY;
			slot.onTake(playerIn, stack1);
		}
		return stack;
	}
}

 

Link to comment
Share on other sites

You still haven't answered most of my questions.

16 minutes ago, V0idWa1k3r said:

Have you registered your IGuiHandler implementation at all? Does your container override Container#canInteractWith and if it does what does it return there? And if it references your TEs what do they return in their methods? What did the debugger told you? Are your IGuiHandler methods being invoked? Are your Container/GUI constructors getting invoked?

 

8 minutes ago, AlmightyElement said:

the debugger doesn't give any errors

It is not supposed to. Place a breakpoint in your IGuiHandler implementation when returning the GUI or the Container object to see if it is getting called. Place a breakpoint in your GUI/Container constructor to see if they are getting invoked.

Link to comment
Share on other sites

Excuse me if I'm giving you wrong answers but I'm pretty new to all of this.

 

And I don't really understand the rest too well.

 

@Override

public boolean canInteractWith(EntityPlayer playerIn)

{

return this.tileentity.isUsableByPlayer(playerIn);

}

 

I set some breakpoints and they returned :

GuiHandler [line: 32] - getClientGuiElement(int, EntityPlayer, World, int, int, int)    
 

Link to comment
Share on other sites

First of all your actual issue - you've never actually registered your gui handler. You have the method that registered it correctly... in an another method that is never called from anywhere.

 

BlockBase/ItemBase is an antipattern. Composition over inheritance.

 

Quote

IHasModel

IHasModel is stupid. All items need models, no exceptions. And nothing about item model registration requires access to private/protected stuff. Register your models in the ModelRegistryEvent directly.

 

@SubscribeEvent
	public static void registerBlock(RegistryEvent.Register<Block> event)
	{
		event.getRegistry().registerAll(ModBlocks.BLOCKS.toArray(new Block[0]));
		TileEntityHandler.registerTileEntities();
		ClientRegistry.bindTileEntitySpecialRenderer(TileEntityCopperChest.class, new RenderCopperChest());
		
	}

You can't do this. Registering a renderer for a TE is a client-side only operation, while RegistryEvents are common code. This will crash the server.

 

public static final Block COPPER_BLOCK = new BlockBase("copper_block", Material.IRON);
public static final Block COPPER_CHEST = new BlockCopperChest("copper_chest");
public static final Block LOG_STRIPPER = new BlockLogStripper("log_stripper");

Never ever use static initializers. Instantinate your stuff in the registry event directly, not in static final fields.

 

compound.setInteger("BurnTime", (short)this.burnTime);
compound.setInteger("CookTime", (short)this.cookTime);
compound.setInteger("CookTimeTotal", (short)this.totalCookTime);

Any particular reason you are replicating a vanilla bug of casting things to a short but saving them as ints?

 

public static int getItemBurnTime(ItemStack fuel) 

*Sigh*. This is like the tenth time I see this method in custom TEs that have a fuel unedited and blindly copied from TileEntityFurnace. You are not changing the implementation of this method. It is static. And public. Just invoke it from TileEntityFurnace, there is absolutely zero need to mindlessly copy-paste it from TileEntityFurnace, this is not how programming works.

 

Quote

public int getField(int id)

You are not using IInventory, why are you copying this abomination of a method from it? Just reference your fields directly, you do not need this.

 

@Override
public void tick()
  
public void update() 

So, you've blindly copied TileEntityFurnace and yet it never occured to you that it is a little bit strange that the TileEntityFurnace has no tick method at all yet you are for some reason required to override it, and when you put @Override over the update method you get an error? No, no concern at all? Again - you need to understand what is actually going on, not blindly copy classes and then hope everything works out. If you ever want to learn you need to start understanding. Also, auto-fix in eclipe isn't a magical "fix all my issues" button. Instead of using it here you need to try and understand why do you need to implement tick here. I am kinda going on a tangent here, and I am sorry if I sound rude or something, but I am trying to help you. The issue in this case is simple - you've implemented the wrong ITickable but if you actually stopped and thought about the issue for a minute instead of blindly applying auto-fix of eclipse then you woundn't have this issue in the first place. This applies to your other TileEntity too, the copper chest one.

 

public Table<ItemStack, ItemStack, ItemStack> getDualSmeltingList()

Again, this is not the first time I am seeing this. Why are you using a Table exactly? There is no reason to use Table here, this is not it's use case. Use a Triple<ItemStack, ItemStack, ItemStack> instead.

 

Why do you have 2 of the same class LogStripperRecipes in 2 different packages? They are identical after all.

 

Your TileEntityCopperChest implements IInventory. Not directly, through inheritance but still. Never do that. IInventory is a horrible artifact of the past and nobody should be ever using it. Use capabilities instead, like you are doing in your furnace TE.

 

CommonProxy makes no sense. Proxies are to separate sided only code. If the code is common it goes into your main class. Do not use a CommonProxy, use an interface instead.

 

Your NBTHandler methods are kinda broken. First of all when saving an ItemStack you also need to save it's NBT and capability data, not just it's registry name and count. And second of all ItemStack already implements the methods for (de)serializing it into NBT, there is no need for duplicate functionality.

 

public interface IStructure 
{
	public static final WorldServer worldServer = FMLCommonHandler.instance().getMinecraftServerInstance().getWorld(0);
	public static final PlacementSettings settings = (new PlacementSettings()).setChunk(null).setIgnoreEntities(false).setIgnoreStructureBlock(false).setMirror(Mirror.NONE).setRotation(Rotation.NONE);
}

You really can't do this. This is not how anything works at all. These are static final fields meaning they get instantinated when the class is loaded. A lot of the things you are referencing here will be null by then.

 

Quote

public static final String SERVER = "com.almightyelement.thirteen.proxy.CommonProxy";

This makes even less sense than a CommonProxy. A server proxy is NOT your CommonProxy, it's a collection of methods that either provide a noop implementation for client-only stuff or reference server-only things. A server proxy can't and musn't be a CommonProxy. This is not how proxies work and they are not meant to be used like this.

Link to comment
Share on other sites

11 minutes ago, AlmightyElement said:

And then implemented the things that most other people did in this mod.

Popular != good. A lot of popular mods are actually quite badly written with a lot of bad practices in place and a ton of cargo-cult programming in place. I can recommend some trustworthy repositories for learning:

 

  • Thanks 1
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



  • Recently Browsing

    • No registered users viewing this page.
  • Posts

    • I was just trying to play my modded world when i randomly got this crash for no reason. I sorted through like every mod and eventually I realized it was LLibrary but I can't seem to find a solution to fix the crashing. I can't lose the world that I have that uses this mod please help me. Here's the report: https://pastebin.com/0D00B79i If anyone has a solution please let me know.  
    • 🤑DAFTAR & LOGIN🤑 🤑DAFTAR & LOGIN🤑 🤑DAFTAR & LOGIN🤑   Daftar Slot Ligawin88 adalah bocoran slot rekomendasi gacor dari Ligawin88 yang bisa anda temukan di SLOT Ligawin88. Situs SLOT Ligawin88 hari ini yang kami bagikan di sini adalah yang terbaik dan bersiaplah untuk mengalami sensasi tak terlupakan dalam permainan slot online. Temukan game SLOT Ligawin88 terbaik dengan 100 pilihan provider ternama yang dipercaya akan memberikan kepuasan dan kemenangan hari ini untuk meraih x500. RTP SLOT Ligawin88 merupakan SLOT Ligawin88 hari ini yang telah menjadi pilihan utama bagi pemain judi online di seluruh Indonesia. Setiap harinya jutaan pemain memasuki dunia maya untuk memperoleh hiburan seru dan kemenangan besar dalam bermain slot dengan adanya bocoran RTP SLOT Ligawin88. Tidak ada yang lebih menyenangkan daripada mengungguli mesin slot dan meraih jackpot x500 yang menggiurkan di situs SLOT Ligawin88 hari ini yang telah disediakan SLOT Ligawin88. Menangkan jackpot besar x500 rajanya maxwin dari segala slot dan raih kemenangan spektakuler di situs Ligawin88 terbaik 2024 adalah tempat yang menyediakan mesin slot dengan peluang kemenangan lebih tinggi daripada situs slot lainnya. Bagi anda yang mencari pengalaman judi slot paling seru dan mendebarkan, situs bo SLOT Ligawin88 terbaik 2024 adalah pilihan yang tepat. Jelajahi dunia slot online melalui situs SLOT Ligawin88 di link SLOT Ligawin88.
    • 🤑DAFTAR & LOGIN🤑 🤑DAFTAR & LOGIN🤑 🤑DAFTAR & LOGIN🤑   Daftar Slot Asusslot adalah bocoran slot rekomendasi gacor dari Asusslot yang bisa anda temukan di SLOT Asusslot. Situs SLOT Asusslot hari ini yang kami bagikan di sini adalah yang terbaik dan bersiaplah untuk mengalami sensasi tak terlupakan dalam permainan slot online. Temukan game SLOT Asusslot terbaik dengan 100 pilihan provider ternama yang dipercaya akan memberikan kepuasan dan kemenangan hari ini untuk meraih x500. RTP SLOT Asusslot merupakan SLOT Asusslot hari ini yang telah menjadi pilihan utama bagi pemain judi online di seluruh Indonesia. Setiap harinya jutaan pemain memasuki dunia maya untuk memperoleh hiburan seru dan kemenangan besar dalam bermain slot dengan adanya bocoran RTP SLOT Asusslot. Tidak ada yang lebih menyenangkan daripada mengungguli mesin slot dan meraih jackpot x500 yang menggiurkan di situs SLOT Asusslot hari ini yang telah disediakan SLOT Asusslot. Menangkan jackpot besar x500 rajanya maxwin dari segala slot dan raih kemenangan spektakuler di situs Asusslot terbaik 2024 adalah tempat yang menyediakan mesin slot dengan peluang kemenangan lebih tinggi daripada situs slot lainnya. Bagi anda yang mencari pengalaman judi slot paling seru dan mendebarkan, situs bo SLOT Asusslot terbaik 2024 adalah pilihan yang tepat. Jelajahi dunia slot online melalui situs SLOT Asusslot di link SLOT Asusslot.
    • 🤑DAFTAR & LOGIN🤑 🤑DAFTAR & LOGIN🤑 🤑DAFTAR & LOGIN🤑 Daftar Slot Galeri555 adalah bocoran slot rekomendasi gacor dari Galeri555 yang bisa anda temukan di SLOT Galeri555. Situs SLOT Galeri555 hari ini yang kami bagikan di sini adalah yang terbaik dan bersiaplah untuk mengalami sensasi tak terlupakan dalam permainan slot online. Temukan game SLOT Galeri555 terbaik dengan 100 pilihan provider ternama yang dipercaya akan memberikan kepuasan dan kemenangan hari ini untuk meraih x500. RTP SLOT Galeri555 merupakan SLOT Galeri555 hari ini yang telah menjadi pilihan utama bagi pemain judi online di seluruh Indonesia. Setiap harinya jutaan pemain memasuki dunia maya untuk memperoleh hiburan seru dan kemenangan besar dalam bermain slot dengan adanya bocoran RTP SLOT Galeri555. Tidak ada yang lebih menyenangkan daripada mengungguli mesin slot dan meraih jackpot x500 yang menggiurkan di situs SLOT Galeri555 hari ini yang telah disediakan SLOT Galeri555. Menangkan jackpot besar x500 rajanya maxwin dari segala slot dan raih kemenangan spektakuler di situs Galeri555 terbaik 2024 adalah tempat yang menyediakan mesin slot dengan peluang kemenangan lebih tinggi daripada situs slot lainnya. Bagi anda yang mencari pengalaman judi slot paling seru dan mendebarkan, situs bo SLOT Galeri555 terbaik 2024 adalah pilihan yang tepat. Jelajahi dunia slot online melalui situs SLOT Galeri555 di link SLOT Galeri555.
    • 🤑DAFTAR & LOGIN🤑 🤑DAFTAR & LOGIN🤑 🤑DAFTAR & LOGIN🤑 Daftar Slot Kocok303 adalah bocoran slot rekomendasi gacor dari Kocok303 yang bisa anda temukan di SLOT Kocok303. Situs SLOT Kocok303 hari ini yang kami bagikan di sini adalah yang terbaik dan bersiaplah untuk mengalami sensasi tak terlupakan dalam permainan slot online. Temukan game SLOT Kocok303 terbaik dengan 100 pilihan provider ternama yang dipercaya akan memberikan kepuasan dan kemenangan hari ini untuk meraih x500. RTP SLOT Kocok303 merupakan SLOT Kocok303 hari ini yang telah menjadi pilihan utama bagi pemain judi online di seluruh Indonesia. Setiap harinya jutaan pemain memasuki dunia maya untuk memperoleh hiburan seru dan kemenangan besar dalam bermain slot dengan adanya bocoran RTP SLOT Kocok303. Tidak ada yang lebih menyenangkan daripada mengungguli mesin slot dan meraih jackpot x500 yang menggiurkan di situs SLOT Kocok303 hari ini yang telah disediakan SLOT Kocok303. Menangkan jackpot besar x500 rajanya maxwin dari segala slot dan raih kemenangan spektakuler di situs Kocok303 terbaik 2024 adalah tempat yang menyediakan mesin slot dengan peluang kemenangan lebih tinggi daripada situs slot lainnya. Bagi anda yang mencari pengalaman judi slot paling seru dan mendebarkan, situs bo SLOT Kocok303 terbaik 2024 adalah pilihan yang tepat. Jelajahi dunia slot online melalui situs SLOT Kocok303 di link SLOT Kocok303.
  • Topics

×
×
  • Create New...

Important Information

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