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

    • DAFTAR & LOGIN TAYO4D   Slot gacor online adalah permainan yang menarik dan menghasilkan keuntungan untuk banyak pemain di seluruh dunia. Dalam artikel ini, kita akan membahas tentang cara memilih dan memainkan slot gacor online terbaik.
    • Tayo4D : Bandar Online Togel Dan Slot Terbesar Di Indonesia     Pemain taruhan Tayo4D yang berkualitas memerlukan platform yang aman, terpercaya, dan mudah digunakan. Dalam era teknologi ini, banyak situs online yang menawarkan layanan taruhan togel 4D, tetapi memilih yang tepat menjadi tuntas. Berikut adalah cara untuk membuat artikel yang membahas tentang situs online terpercaya untuk permainan taruhan togel 4D.  
    • OLXTOTO: Platform Maxwin dan Gacor Terbesar Sepanjang Masa OLXTOTO telah menetapkan standar baru dalam dunia perjudian dengan menjadi platform terbesar untuk pengalaman gaming yang penuh kemenangan dan kegacoran, sepanjang masa. Dengan fokus yang kuat pada menyediakan permainan yang menghadirkan kesenangan tanpa batas dan peluang kemenangan besar, OLXTOTO telah menjadi pilihan utama bagi para pencinta judi berani di Indonesia. Maxwin: Mengejar Kemenangan Terbesar Maxwin bukan sekadar kata-kata kosong di OLXTOTO. Ini adalah konsep yang ditanamkan dalam setiap aspek permainan yang mereka tawarkan. Dari permainan slot yang menghadirkan jackpot besar hingga berbagai opsi permainan togel dengan hadiah fantastis, para pemain dapat memperoleh peluang nyata untuk mencapai kemenangan terbesar dalam setiap taruhan yang mereka lakukan. OLXTOTO tidak hanya menawarkan kesempatan untuk menang, tetapi juga menjadi wadah bagi para pemain untuk meraih impian mereka dalam perjudian yang berani. Gacor: Keberuntungan yang Tak Tertandingi Keberuntungan seringkali menjadi faktor penting dalam perjudian, dan OLXTOTO memahami betul akan hal ini. Dengan berbagai strategi dan analisis yang disediakan, pemain dapat menemukan peluang gacor yang tidak tertandingi dalam setiap taruhan. Dari hasil togel yang tepat hingga putaran slot yang menguntungkan, OLXTOTO memastikan bahwa setiap taruhan memiliki potensi untuk menjadi momen yang mengubah hidup. Inovasi dan Kualitas Tanpa Batas Tidak puas dengan prestasi masa lalu, OLXTOTO terus berinovasi untuk memberikan pengalaman gaming terbaik kepada para pengguna. Dengan menggabungkan teknologi terbaru dengan desain yang ramah pengguna, platform ini menyajikan antarmuka yang mudah digunakan tanpa mengorbankan kualitas. Setiap pembaruan dan peningkatan dilakukan dengan tujuan tunggal: memberikan pengalaman gaming yang tanpa kompromi kepada setiap pengguna. Komitmen Terhadap Kepuasan Pelanggan Di balik kesuksesan OLXTOTO adalah komitmen mereka terhadap kepuasan pelanggan. Tim dukungan pelanggan yang profesional siap membantu para pemain dalam setiap langkah perjalanan gaming mereka. Dari pertanyaan teknis hingga bantuan dengan transaksi keuangan, OLXTOTO selalu siap memberikan pelayanan terbaik kepada para pengguna mereka. Penutup: Mengukir Sejarah dalam Dunia Perjudian Daring OLXTOTO bukan sekadar platform perjudian berani biasa. Ini adalah ikon dalam dunia perjudian daring Indonesia, sebuah destinasi yang menyatukan kemenangan dan keberuntungan dalam satu tempat yang mengasyikkan. Dengan komitmen mereka terhadap kualitas, inovasi, dan kepuasan pelanggan, OLXTOTO terus mengukir sejarah dalam perjudian dunia berani, menjadi nama yang tak terpisahkan dari pengalaman gaming terbaik. Bersiaplah untuk mengalami sensasi kemenangan terbesar dan keberuntungan tak terduga di OLXTOTO - platform maxwin dan gacor terbesar sepanjang masa.
    • OLXTOTO - Bandar Togel Online Dan Slot Terbesar Di Indonesia OLXTOTO telah lama dikenal sebagai salah satu bandar online terkemuka di Indonesia, terutama dalam pasar togel dan slot. Dengan reputasi yang solid dan pengalaman bertahun-tahun, OLXTOTO menawarkan platform yang aman dan andal bagi para penggemar perjudian daring. DAFTAR OLXTOTO DISINI DAFTAR OLXTOTO DISINI DAFTAR OLXTOTO DISINI Beragam Permainan Togel Sebagai bandar online terbesar di Indonesia, OLXTOTO menawarkan berbagai macam permainan togel. Mulai dari togel Singapura, togel Hongkong, hingga togel Sidney, pemain memiliki banyak pilihan untuk mencoba keberuntungan mereka. Dengan sistem yang transparan dan hasil yang adil, OLXTOTO memastikan bahwa setiap taruhan diproses dengan cepat dan tanpa keadaan. Slot Online Berkualitas Selain togel, OLXTOTO juga menawarkan berbagai permainan slot online yang menarik. Dari slot klasik hingga slot video modern, pemain dapat menemukan berbagai opsi permainan yang sesuai dengan preferensi mereka. Dengan grafis yang memukau dan fitur bonus yang menggiurkan, pengalaman bermain slot di OLXTOTO tidak akan pernah membosankan. Keamanan dan Kepuasan Pelanggan Terjamin Keamanan dan kepuasan pelanggan merupakan prioritas utama di OLXTOTO. Mereka menggunakan teknologi enkripsi terbaru untuk melindungi data pribadi dan keuangan para pemain. Tim dukungan pelanggan yang ramah dan responsif siap membantu pemain dengan setiap pertanyaan atau masalah yang mereka hadapi. Promosi dan Bonus Menarik OLXTOTO sering menawarkan promosi dan bonus menarik kepada para pemainnya. Mulai dari bonus selamat datang hingga bonus deposit, pemain memiliki kesempatan untuk meningkatkan kemenangan mereka dengan memanfaatkan berbagai penawaran yang tersedia. Penutup Dengan reputasi yang solid, beragam permainan berkualitas, dan komitmen terhadap keamanan dan kepuasan pelanggan, OLXTOTO tetap menjadi salah satu pilihan utama bagi para pecinta judi online di Indonesia. Jika Anda mencari pengalaman berjudi yang menyenangkan dan terpercaya, OLXTOTO layak dipertimbangkan.
    • I have been having a problem with minecraft forge. Any version. Everytime I try to launch it it always comes back with error code 1. I have tried launching from curseforge, from the minecraft launcher. I have also tried resetting my computer to see if that would help. It works on my other computer but that one is too old to run it properly. I have tried with and without mods aswell. Fabric works, optifine works, and MultiMC works aswell but i want to use forge. If you can help with this issue please DM on discord my # is Haole_Dawg#6676
  • Topics

×
×
  • Create New...

Important Information

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