Jump to content

SnowyEgret

Members
  • Posts

    112
  • Joined

  • Last visited

Posts posted by SnowyEgret

  1. I have answered the last part of my question. Instead of returning the model looked up in handleBlockState() I return this (which is an IBakedModel). This gives me the oportunity to modify or rebuild the BakedQuads list returned from getFaceQuads() and getGeneralQuads():

     

    package ds.plato.block;
    
    import java.util.Arrays;
    import java.util.List;
    import net.minecraft.block.state.IBlockState;
    import net.minecraft.client.Minecraft;
    import net.minecraft.client.renderer.block.model.BakedQuad;
    import net.minecraft.client.renderer.block.model.ItemCameraTransforms;
    import net.minecraft.client.renderer.texture.TextureAtlasSprite;
    import net.minecraft.client.renderer.vertex.VertexFormat;
    import net.minecraft.client.resources.model.IBakedModel;
    import net.minecraft.client.resources.model.ModelResourceLocation;
    import net.minecraft.util.EnumFacing;
    import net.minecraftforge.client.model.IFlexibleBakedModel;
    import net.minecraftforge.client.model.ISmartBlockModel;
    import net.minecraftforge.common.property.IExtendedBlockState;
    import net.minecraftforge.common.property.IUnlistedProperty;
    
    public class BlockSelectedModel implements ISmartBlockModel {
    
    public static ModelResourceLocation modelResourceLocation = new ModelResourceLocation("plato:blockSelected");
    private IBakedModel defaultModel;
    private IFlexibleBakedModel model;
    private IUnlistedProperty selectedBlockProperty;
    
    public BlockSelectedModel(IBakedModel defaultModel, PropertySelectedBlock selectedBlockProperty) {
    	this.defaultModel = defaultModel;
    	this.selectedBlockProperty = selectedBlockProperty;
    }
    
    @Override
    public IBakedModel handleBlockState(IBlockState state) {
    	assert IExtendedBlockState.class.isAssignableFrom(state.getClass());
    	IBlockState s = ((IExtendedBlockState) state).getValue(selectedBlockProperty);
    	System.out.println("Selected block="+s);
    	IBakedModel m = Minecraft.getMinecraft().getBlockRendererDispatcher().getBlockModelShapes().getModelForState(s);
    	model = (IFlexibleBakedModel) m;
    	return this;
    }
    
    @Override
    public List getFaceQuads(EnumFacing face) {
    	List<BakedQuad> faceQuads = model.getFaceQuads(face);
    	for (BakedQuad q : faceQuads) {
    		int[] vd = q.getVertexData();
    		System.out.println(Arrays.toString(vd));
    	}
    	//Modify list here
    	return faceQuads;
    }
    
    @Override
    public List getGeneralQuads() {
    	List<BakedQuad> generalQuads = model.getGeneralQuads();
    	System.out.println(Arrays.toString(generalQuads.toArray()));
    	for (BakedQuad q : generalQuads) {
    		int[] vd = q.getVertexData();
    		System.out.println(Arrays.toString(vd));
    	}
    	//Modify list here
    	return generalQuads;
    }
    
    @Override
    public boolean isAmbientOcclusion() {
    	return model.isAmbientOcclusion();
    }
    
    @Override
    public boolean isGui3d() {
    	return model.isGui3d();
    }
    
    @Override
    public boolean isBuiltInRenderer() {
    	return model.isBuiltInRenderer();
    }
    
    @Override
    public TextureAtlasSprite getTexture() {
    	// return defaultModel.getTexture();
    	return model.getTexture();
    }
    
    @Override
    public ItemCameraTransforms getItemCameraTransforms() {
    	return model.getItemCameraTransforms();
    }
    }
    

     

    This runs fine. My questions are:

     

    Why does BakedQuad.getVertexData() return ints, and what do they mean?

    The vertex data seems to be the same for every model looked up in handleBlockState():

     

    [10:21:59] [Client thread/INFO] [sTDOUT]: [ds.plato.block.BlockSelectedModel:handleBlockState:35]: Selected block=minecraft:sand[variant=sand]
    [10:21:59] [Client thread/INFO] [sTDOUT]: [ds.plato.block.BlockSelectedModel:getFaceQuads:46]: [0, 0, 1065353216, -8421505, 1058537800, 1046480159, 0, 0, 0, 0, -8421505, 1058537800, 1048574689, 0, 1065353216, 0, 0, -8421505, 1059061432, 1048574689, 0, 1065353216, 0, 1065353216, -8421505, 1059061432, 1046480159, 0]
    [10:21:59] [Client thread/INFO] [sTDOUT]: [ds.plato.block.BlockSelectedModel:getFaceQuads:46]: [0, 1065353216, 0, -1, 1058537800, 1046480159, 0, 0, 1065353216, 1065353216, -1, 1058537800, 1048574689, 0, 1065353216, 1065353216, 1065353216, -1, 1059061432, 1048574689, 0, 1065353216, 1065353216, 0, -1, 1059061432, 1046480159, 0]
    [10:21:59] [Client thread/INFO] [sTDOUT]: [ds.plato.block.BlockSelectedModel:getFaceQuads:46]: [1065353216, 1065353216, 0, -3355444, 1058537800, 1046480159, 0, 1065353216, 0, 0, -3355444, 1058537800, 1048574689, 0, 0, 0, 0, -3355444, 1059061432, 1048574689, 0, 0, 1065353216, 0, -3355444, 1059061432, 1046480159, 0]
    [10:21:59] [Client thread/INFO] [sTDOUT]: [ds.plato.block.BlockSelectedModel:getFaceQuads:46]: [0, 1065353216, 1065353216, -3355444, 1058537800, 1046480159, 0, 0, 0, 1065353216, -3355444, 1058537800, 1048574689, 0, 1065353216, 0, 1065353216, -3355444, 1059061432, 1048574689, 0, 1065353216, 1065353216, 1065353216, -3355444, 1059061432, 1046480159, 0]
    [10:21:59] [Client thread/INFO] [sTDOUT]: [ds.plato.block.BlockSelectedModel:getFaceQuads:46]: [0, 1065353216, 0, -6710887, 1058537800, 1046480159, 0, 0, 0, 0, -6710887, 1058537800, 1048574689, 0, 0, 0, 1065353216, -6710887, 1059061432, 1048574689, 0, 0, 1065353216, 1065353216, -6710887, 1059061432, 1046480159, 0]
    [10:21:59] [Client thread/INFO] [sTDOUT]: [ds.plato.block.BlockSelectedModel:getFaceQuads:46]: [1065353216, 1065353216, 1065353216, -6710887, 1058537800, 1046480159, 0, 1065353216, 0, 1065353216, -6710887, 1058537800, 1048574689, 0, 1065353216, 0, 0, -6710887, 1059061432, 1048574689, 0, 1065353216, 1065353216, 0, -6710887, 1059061432, 1046480159, 0]
    [10:21:59] [Client thread/INFO] [sTDOUT]: [ds.plato.block.BlockSelectedModel:getGeneralQuads:55]: []
    
    {ds.plato.block.PropertySelectedBlock@15af3a9b=Optional.of(minecraft:dirt[snowy=false,variant=dirt])}
    [10:22:06] [Client thread/INFO] [sTDOUT]: [ds.plato.block.BlockSelectedModel:handleBlockState:35]: Selected block=minecraft:dirt[snowy=false,variant=dirt]
    [10:22:06] [Client thread/INFO] [sTDOUT]: [ds.plato.block.BlockSelectedModel:getFaceQuads:46]: [0, 0, 1065353216, -8421505, 1048576655, 1044383007, 0, 0, 0, 0, -8421505, 1048576655, 1046477537, 0, 1065353216, 0, 0, -8421505, 1049623921, 1046477537, 0, 1065353216, 0, 1065353216, -8421505, 1049623921, 1044383007, 0]
    [10:22:06] [Client thread/INFO] [sTDOUT]: [ds.plato.block.BlockSelectedModel:getFaceQuads:46]: [0, 1065353216, 0, -1, 1048576655, 1044383007, 0, 0, 1065353216, 1065353216, -1, 1048576655, 1046477537, 0, 1065353216, 1065353216, 1065353216, -1, 1049623921, 1046477537, 0, 1065353216, 1065353216, 0, -1, 1049623921, 1044383007, 0]
    [10:22:06] [Client thread/INFO] [sTDOUT]: [ds.plato.block.BlockSelectedModel:getFaceQuads:46]: [1065353216, 1065353216, 0, -3355444, 1048576655, 1044383007, 0, 1065353216, 0, 0, -3355444, 1048576655, 1046477537, 0, 0, 0, 0, -3355444, 1049623921, 1046477537, 0, 0, 1065353216, 0, -3355444, 1049623921, 1044383007, 0]
    [10:22:06] [Client thread/INFO] [sTDOUT]: [ds.plato.block.BlockSelectedModel:getFaceQuads:46]: [0, 1065353216, 1065353216, -3355444, 1048576655, 1044383007, 0, 0, 0, 1065353216, -3355444, 1048576655, 1046477537, 0, 1065353216, 0, 1065353216, -3355444, 1049623921, 1046477537, 0, 1065353216, 1065353216, 1065353216, -3355444, 1049623921, 1044383007, 0]
    [10:22:06] [Client thread/INFO] [sTDOUT]: [ds.plato.block.BlockSelectedModel:getFaceQuads:46]: [0, 1065353216, 0, -6710887, 1048576655, 1044383007, 0, 0, 0, 0, -6710887, 1048576655, 1046477537, 0, 0, 0, 1065353216, -6710887, 1049623921, 1046477537, 0, 0, 1065353216, 1065353216, -6710887, 1049623921, 1044383007, 0]
    [10:22:06] [Client thread/INFO] [sTDOUT]: [ds.plato.block.BlockSelectedModel:getFaceQuads:46]: [1065353216, 1065353216, 1065353216, -6710887, 1048576655, 1044383007, 0, 1065353216, 0, 1065353216, -6710887, 1048576655, 1046477537, 0, 1065353216, 0, 0, -6710887, 1049623921, 1046477537, 0, 1065353216, 1065353216, 0, -6710887, 1049623921, 1044383007, 0]
    [10:22:06] [Client thread/INFO] [sTDOUT]: [ds.plato.block.BlockSelectedModel:getGeneralQuads:55]: []
    

     

     

  2. Thanks TGG for the response.

     

    I think the last, more generic, method you proposed is the way I need to go. Just a few questions to begin. Here is a start for new handleBlockState():

     

    	@Override
    public IBakedModel handleBlockState(IBlockState state) {
    	assert IExtendedBlockState.class.isAssignableFrom(state.getClass());
    	IBlockState s = ((IExtendedBlockState) state).getValue(prevBlockProperty);
    	IBakedModel model = Minecraft.getMinecraft().getBlockRendererDispatcher().getBlockModelShapes()
    			.getModelForState(s);
    
    	IFlexibleBakedModel m = (IFlexibleBakedModel) model;
    
    	VertexFormat format = m.getFormat();
    	System.out.println("format=" + format);
    
    	List<BakedQuad> generalQuads = m.getGeneralQuads();
    	System.out.println(Arrays.toString(generalQuads.toArray()));
    	for (BakedQuad q : generalQuads) {
    		int[] vd = q.getVertexData();
    		System.out.println(Arrays.toString(vd));
    	}
    
    	for (EnumFacing face : EnumFacing.values()) {
    		List<BakedQuad> faceQuads = m.getFaceQuads(face);
    		for (BakedQuad q : faceQuads) {
    			int[] vd = q.getVertexData();
    			System.out.println(Arrays.toString(vd));
    		}
    	}
    
    	return m;
    }
    

     

    When I run and select a vanila block sand, it appears to have no generalQuad data(the list of BakedQuads is empty), only faceQuad data. Can I assume that any model which has more than 6 standard sides will implement getGeneralQuads()?

     

    Here is the output of vertex data from the faceQuads:

     

    [19:27:02] [Client thread/INFO] [sTDOUT]: [ds.plato.block.BlockSelectedModel:handleBlockState:55]: [0, 0, 1065353216, -8421505, 1058537800, 1046480159, 0, 0, 0, 0, -8421505, 1058537800, 1048574689, 0, 1065353216, 0, 0, -8421505, 1059061432, 1048574689, 0, 1065353216, 0, 1065353216, -8421505, 1059061432, 1046480159, 0]
    [19:27:02] [Client thread/INFO] [sTDOUT]: [ds.plato.block.BlockSelectedModel:handleBlockState:55]: [0, 1065353216, 0, -1, 1058537800, 1046480159, 0, 0, 1065353216, 1065353216, -1, 1058537800, 1048574689, 0, 1065353216, 1065353216, 1065353216, -1, 1059061432, 1048574689, 0, 1065353216, 1065353216, 0, -1, 1059061432, 1046480159, 0]
    [19:27:02] [Client thread/INFO] [sTDOUT]: [ds.plato.block.BlockSelectedModel:handleBlockState:55]: [1065353216, 1065353216, 0, -3355444, 1058537800, 1046480159, 0, 1065353216, 0, 0, -3355444, 1058537800, 1048574689, 0, 0, 0, 0, -3355444, 1059061432, 1048574689, 0, 0, 1065353216, 0, -3355444, 1059061432, 1046480159, 0]
    [19:27:02] [Client thread/INFO] [sTDOUT]: [ds.plato.block.BlockSelectedModel:handleBlockState:55]: [0, 1065353216, 1065353216, -3355444, 1058537800, 1046480159, 0, 0, 0, 1065353216, -3355444, 1058537800, 1048574689, 0, 1065353216, 0, 1065353216, -3355444, 1059061432, 1048574689, 0, 1065353216, 1065353216, 1065353216, -3355444, 1059061432, 1046480159, 0]
    [19:27:02] [Client thread/INFO] [sTDOUT]: [ds.plato.block.BlockSelectedModel:handleBlockState:55]: [0, 1065353216, 0, -6710887, 1058537800, 1046480159, 0, 0, 0, 0, -6710887, 1058537800, 1048574689, 0, 0, 0, 1065353216, -6710887, 1059061432, 1048574689, 0, 0, 1065353216, 1065353216, -6710887, 1059061432, 1046480159, 0]
    [19:27:02] [Client thread/INFO] [sTDOUT]: [ds.plato.block.BlockSelectedModel:handleBlockState:55]: [1065353216, 1065353216, 1065353216, -6710887, 1058537800, 1046480159, 0, 1065353216, 0, 1065353216, -6710887, 1058537800, 1048574689, 0, 1065353216, 0, 0, -6710887, 1059061432, 1048574689, 0, 1065353216, 1065353216, 0, -6710887, 1059061432, 1046480159, 0]

     

    Do I use the format from VertexFormat format = m.getFormat() to interpret these arrays of ints?

     

    Also, there is no setQuads() method on IFlexibleBakedModel. Is this going to be a problem?

  3. Hi,

     

    I have implemented ISmartModel as instructed in TheGreyGhost's MBE04 tutorial. Things are working fine. In handleBlockState() I am looking up a model from an IBlockState I get from an unlisted property of the incoming IExtendedBlockState.

     

    Before returning the model, can I manipulate it? I am attempting to find a way to modify the color of it's texture (I posted a couple of days ago on this).  There is a method returning the model's texture (of class TextureAtlasSprite), and a method to get the texture's texture data which is also setable. My printlns seem to indicate the texture data is changed, but I am not seeing any difference to the texture in game.

     

    Here is my implentation of ISmartModel:

     

    package ds.plato.block;
    
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.List;
    
    import net.minecraft.block.state.IBlockState;
    import net.minecraft.client.Minecraft;
    import net.minecraft.client.renderer.block.model.BakedQuad;
    import net.minecraft.client.renderer.block.model.ItemCameraTransforms;
    import net.minecraft.client.renderer.texture.TextureAtlasSprite;
    import net.minecraft.client.resources.model.IBakedModel;
    import net.minecraft.client.resources.model.ModelResourceLocation;
    import net.minecraft.util.EnumFacing;
    import net.minecraftforge.client.model.IFlexibleBakedModel;
    import net.minecraftforge.client.model.ISmartBlockModel;
    import net.minecraftforge.common.property.IExtendedBlockState;
    import net.minecraftforge.common.property.IUnlistedProperty;
    
    public class BlockSelectedModel implements ISmartBlockModel {
    
    public static ModelResourceLocation modelResourceLocation = new ModelResourceLocation("plato:blockSelected");
    private IBakedModel defaultModel;
    private IUnlistedProperty prevBlockProperty;
    
    public BlockSelectedModel(IBakedModel defaultModel, PropertyPreviousBlock prevBlockProperty) {
    	super();
    	this.defaultModel = defaultModel;
    	this.prevBlockProperty = prevBlockProperty;
    }
    
    @Override
    public IBakedModel handleBlockState(IBlockState state) {
    	assert IExtendedBlockState.class.isAssignableFrom(state.getClass());
    	IBlockState s = ((IExtendedBlockState) state).getValue(prevBlockProperty);
    	IBakedModel model = Minecraft.getMinecraft().getBlockRendererDispatcher().getBlockModelShapes()
    			.getModelForState(s);
    
    	IFlexibleBakedModel m = (IFlexibleBakedModel)model;
    
    	TextureAtlasSprite t = m.getTexture();
    	int[][] td = t.getFrameTextureData(0);
    	System.out.println(Arrays.deepToString(td));
    
    	td = modifyTextureData(td);
    	List l = new ArrayList();
    	l.add(td);
    	t.setFramesTextureData(l);
    
    	t = m.getTexture();
    	td = t.getFrameTextureData(0);
    	System.out.println(Arrays.deepToString(td));
    
    	return m;
    }
    
    @Override
    public List getFaceQuads(EnumFacing p_177551_1_) {
    	// TODO Auto-generated method stub
    	return null;
    }
    
    @Override
    public List getGeneralQuads() {
    	// TODO Auto-generated method stub
    	return null;
    }
    
    @Override
    public boolean isAmbientOcclusion() {
    	// TODO Auto-generated method stub
    	return false;
    }
    
    @Override
    public boolean isGui3d() {
    	// TODO Auto-generated method stub
    	return false;
    }
    
    @Override
    public boolean isBuiltInRenderer() {
    	// TODO Auto-generated method stub
    	return false;
    }
    
    @Override
    public TextureAtlasSprite getTexture() {
    	return defaultModel.getTexture();
    }
    
    @Override
    public ItemCameraTransforms getItemCameraTransforms() {
    	// TODO Auto-generated method stub
    	return null;
    }
    
    // Private-------------------------------------------------------------
    
    private int[][] modifyTextureData(int[][] data) {
    	for (int i = 0; i < data.length; i++) {
    		for (int j = 0; j < data[i].length; j++) {
    			data[i][j] = 0;
    		}
    	}
    	return data;
    }
    
    }
    

     

    For testing purposes I am just setting the texture data to 0. Seems I can cast the IBakedModel to an IFlexibleBakedModel, for whatever that's worth.

  4. I would like to change the hue of one or more nearby blocks. I do not mean my block, but vanilla blocks, or other mod blocks. I would like to leave the form and texture intact, but modify the hue, for example,  make it more red. I also mean a temporary, in game change, not a resource pack edit. Something like an translucent overlay for a list of blocks.

     

    How would you do this in 1.8?

  5. I have an item with an inventory written to it's item stack (like your ItemInventory class). More specifically, a staff with spells. In survival mode, a player crafts the staff, crafts the spells, then assembles the spells on the staff with a gui. In creative mode, I would like a player to be able to select a staff from his creative tab with spells already on it.

     

    When the staff is moved to the hotbar, it will write spells to it's item stack.

  6. After struggling with similar problems on this thread http://www.minecraftforge.net/forum/index.php/topic,22360.msg114869.html#msg114869, it was pointed out to me that the gui should be opened on the server side only:

     

    if (!world.isRemote) {
            player.openGui(ChargeCore.instance, 0, world, x, y, z);
            return true;
    }
    

     

    If you put printlns in your two gui handler methods, you can see what effect this has on how they are called.

     

    The suggestion by MultiMote to use InventoryBasic will reduce the amount of code you are writing and help pinpoint the problem. Give your tile entity an InventoryBasic instead of implementing IInventory:

     

    public class BaseGeneratorTileEntity extends TileEntity {
    
        IInventory inventory = new InventoryBasic("BaseGenerator", false, 9);
    

  7. Finally! It works. Thank you diesieben07.

     

    Here is my implementation of IInventory based on ItemInventory.WithInventory. It's a little different in that it writes to the tag at every call to setInventorySlotContents and does not maintain an ItemStack arrray. Note second line of setInventorySlotContents();

     

    public class MyInventory implements IInventory {
    
    // This wrapper encapsulates the complexities of writing to the tag
            private MyTagWrapper tag;
    private int size = 9;
    IInventory inventory;
    ItemStack stack;
    private int slot;
    
    public MyInventory(IInventory inventory, int slot) {
    	this.inventory = inventory;
    	this.slot = slot;
    	this.stack = inventory.getStackInSlot(slot);
    	NBTTagCompound t = stack.getTagCompound();
    	if (t == null) {
    		t = new NBTTagCompound();
    		stack.setTagCompound(t);
    	}
    	tag = new MyTagWrapper(t, size);
    }
    
    @Override
    public ItemStack getStackInSlot(int i) {
    	return tag.getItemStack(i);
    }
    
            //Stack limit is 1
            @Override
    public ItemStack decrStackSize(int i, int amount) {
    	ItemStack stack = tag.getItemStack(i);
    	tag.setItemStack(i, null);
    	return stack;
    }
    
    @Override
    public ItemStack getStackInSlotOnClosing(int i) {
    	if (tag.getItemStack(i) != null) {
    		ItemStack itemstack = tag.getItemStack(i);
    		tag.setItemStack(i, null);
    		return itemstack;
    	} else {
    		return null;
    	}
    }
    
    @Override
    public void setInventorySlotContents(int i, ItemStack stack) {
    	tag.setItemStack(i, stack);
                    //This is what was missing previously
    	inventory.setInventorySlotContents(slot, this.stack);
    }
    
    @Override
    public int getSizeInventory() {
    	return size;
    }
    
    @Override
    public String getInventoryName() {
    	return null;
    }
    
    @Override
    public boolean hasCustomInventoryName() {
    	return false;
    }
    
    @Override
    public int getInventoryStackLimit() {
    	return 1;
    }
    
    @Override
    public void markDirty() {
    }
    
    @Override
    public boolean isUseableByPlayer(EntityPlayer p_70300_1_) {
    	return true;
    }
    
    @Override
    public void openInventory() {
    }
    
    @Override
    public void closeInventory() {
    }
    
    @Override
    public boolean isItemValidForSlot(int i, ItemStack stack) {
    	return true;
    }
    }

     

    Here is where it is constructed:

     

    public class MyGuiHandler implements IGuiHandler {
    
    @Override
    public Object getServerGuiElement(int id, EntityPlayer player, World w, int x, int y, int z) {
    	return new MyContainer(player.inventory, new MyInventory(player.inventory, player.inventory.currentItem));
    }
    
    @Override
    public Object getClientGuiElement(int id, EntityPlayer player, World w, int x, int y, int z) {
    	return new MyGui(new MyContainer(player.inventory, new MyInventory(player.inventory, player.inventory.currentItem)));
    }
    }
    

  8. From you javadoc:

     

    >If the ItemStack being written to is in an inventory itself, {@link ItemInventory.WithInventory} should be used instead.

     

    Just to be sure I understand, do you mean "if the ItemStack being written to is referenced by another inventory", or maybe "if you have already constructed an instance of ItemInventory with this ItemStack"?

     

    If so, does this apply to my case? Would I use it something like this:

     

    public class MyGuiHandler implements IGuiHandler {
    
           IInventory inv;
    
    @Override
    public Object getServerGuiElement(int id, EntityPlayer player, World w, int x, int y, int z) {
                    inv =  new ItemInventory(player.getCurrentEquippedItem());
    	return new MyContainer(player.inventory, inv);
    }
    
    @Override
    public Object getClientGuiElement(int id, EntityPlayer player, World w, int x, int y, int z) {
                    int slot = ?;
    	return new MyGui(new MyContainer(player.inventory, new ItemInventory.WithInventory(inv, slot)));
    }
    }

     

    I'm lost ???.

     

  9. Yes, much better. I am no longer getting strange behaviour in my container. Before I was passing the same inventory object to both client and server sides. Thank you.

     

    I still have one problem. I am writing to the tag but I seem to be getting a new empty tag object from getCurrentEquippedItem() every time I reopen the gui.

     

    Should the gui be opened from the client side, the server side, or both in onItemUse()? If I open only from the server, getServerGuiElement() and getClientGuiElement() are called each once:

     

    	@Override
    public boolean onItemUse(ItemStack stack, EntityPlayer player, World world, int x, int y, int z, int s, float sx,
    		float sy, float sz) {
    	if (!world.isRemote) {
    		player.openGui(MyMod.instance, 0, world, x, y, z);
    		return true;
    	}
    	return false;
    }
    

     

    public class MyGuiHandler implements IGuiHandler {
    
    @Override
    public Object getServerGuiElement(int id, EntityPlayer player, World w, int x, int y, int z) {
    	NBTTagCompound t = player.getCurrentEquippedItem().getTagCompound();
    	System.out.println("[MyGuiHandler.getServerGuiElement] w=" + w + ", tag=@" + System.identityHashCode(t) + t);
    	return new MyContainer(player.inventory, new MyInventory(player.getCurrentEquippedItem()));
    }
    
    @Override
    public Object getClientGuiElement(int id, EntityPlayer player, World w, int x, int y, int z) {
    	NBTTagCompound t = player.getCurrentEquippedItem().getTagCompound();
    	System.out.println("[MyGuiHandler.getClientGuiElement] w=" + w + ", tag=@" + System.identityHashCode(t) + t); 
    	return new MyGui(new MyContainer(player.inventory, new MyInventory(player.getCurrentEquippedItem())));
    }
    }
    

     

    Console (opening gui twice):

     

    [MyGuiHandler.getServerGuiElement] w=net.minecraft.world.WorldServer@6c0486cc, tag=@421020847{}
    [MyGuiHandler.getClientGuiElement] w=net.minecraft.client.multiplayer.WorldClient@506382b1, tag=@317245315{}
    
    [MyGuiHandler.getServerGuiElement] w=net.minecraft.world.WorldServer@6c0486cc, tag=@821869132{}
    [MyGuiHandler.getClientGuiElement] w=net.minecraft.client.multiplayer.WorldClient@506382b1, tag=@539684020{}
    

     

    I seem to be getting a different tag object each time.

     

    Opening the gui from both sides gives:

     

    [MyGuiHandler.getClientGuiElement] w=net.minecraft.client.multiplayer.WorldClient@9da1db, tag=@1217657581{}
    [MyGuiHandler.getServerGuiElement] w=net.minecraft.world.WorldServer@1693401c, tag=@1166845275{}
    [MyGuiHandler.getClientGuiElement] w=net.minecraft.client.multiplayer.WorldClient@9da1db, tag=@1217657581{}
    
    [MyGuiHandler.getClientGuiElement] w=net.minecraft.client.multiplayer.WorldClient@9da1db, tag=@824254376{}
    [MyGuiHandler.getServerGuiElement] w=net.minecraft.world.WorldServer@1693401c, tag=@1973774282{}
    [MyGuiHandler.getClientGuiElement] w=net.minecraft.client.multiplayer.WorldClient@9da1db, tag=@824254376{}
    

  10. 07,

     

    I had a look at SevenCommons. If I understand, you would pass an itemStack maybe to the gui handller so that it can construct a new inventory and then the container every time the gui is opened? Something like:

     

    @Override
    public boolean onItemUse(ItemStack stack, EntityPlayer player, World world, int x, int y, int z, int s, float sx, float sy, float sz) {
    MyMod.instance.guiHandler.setItemStack(stack);
    player.openGui(MyMod.instance, 0, world, x, y, z);
    return true;
    }
    

     

     

    public class MyGuiHandler implements IGuiHandler {
    
    IInventory inventory;
    
    public void setItemStack(ItemStack stack) {
    	inventory = new ItemInventory(stack);
    }
    
    @Override
    public Object getServerGuiElement(int id, EntityPlayer player, World world, int x, int y, int z) {
    	return new MyContainer(player.inventory, inventory);
    }
    
    @Override
    public Object getClientGuiElement(int id, EntityPlayer player, World world, int x, int y, int z) {
    	return new MyGui(new MyContainer(player.inventory, inventory));
    }
    }

  11. Thanks again for your reply.

     

    >You would have your item (possibly implement IInventory and) use the ItemStack to load the slots

     

    This is all clear to me. In my case, I have given my item a field named inventory which implements IInventory. This is the inventory that I pass to my container and my gui, and this inventory writes to ItemStack.stackTagCompound. My question is how to pass the stack to the inventory? IIventory has a getter and a setter which is called by the container:

     

    ItemStack getStackInSlot(int p_70301_1_);
    void setInventorySlotContents(int p_70299_1_, ItemStack p_70299_2_);
    

     

    neither of which include a parameter of type ItemStack which I can get the tag from. (The stack in setInventorySlotContents is what I am putting in the slot). Items don't know what stack they are in - they have to be told. In methods like Item.onItemUse() pass the stack as a parameter for this reason.

     

    As a workaround, I am passing the stack (actually just the tag) to the inventory with my own method MyInventory.setTag(NBTTagCompound tag) when the gui is opened. The problem is that this sets a field in MyInventory which, because there is only one instance of the item in the game, will be shared between players, and we are back at square one. It's only a minor problem because the players would have to open the containers at the same time for there to be a conflict.

     

    Thanks also for the suggestion of looking at the backpack mod, which is on GitHub. There are thousands of lines of code there. I will try to slug my way though it  :P

  12. Hi again Ewe,

     

    Searching my workspace gives:

     

    From net.minecraftforge.oredict.RecipeSorter:

     

       @Override
        public int compare(IRecipe r1, IRecipe r2)
        {
            Category c1 = getCategory(r1);
            Category c2 = getCategory(r2);
            if (c1 == SHAPELESS && c2 == SHAPED) return  1;
            if (c1 == SHAPED && c2 == SHAPELESS) return -1;
            if (r2.getRecipeSize() < r1.getRecipeSize()) return -1;
            if (r2.getRecipeSize() > r1.getRecipeSize()) return  1;
            return getPriority(r2) - getPriority(r1); // high priority value first! 
        }
    

     

    and net.minecraft.item.crafting.CraftingManager:

     

    public int compare(IRecipe p_compare_1_, IRecipe p_compare_2_)
    {
        return p_compare_1_ instanceof ShapelessRecipes && p_compare_2_ instanceof ShapedRecipes ? 1 : (p_compare_2_ instanceof ShapelessRecipes && p_compare_1_ instanceof ShapedRecipes ? -1 : (p_compare_2_.getRecipeSize() < p_compare_1_.getRecipeSize() ? -1 : (p_compare_2_.getRecipeSize() > p_compare_1_.getRecipeSize() ? 1 : 0)));
    }
    

  13. Ewe,

     

    >or do all stacks of the item to share the same inventory?

     

    Ideally, each item has its own inventory.

     

    I've given MyItem an instance of MyInventory implementing IInventory instead of extending InventoryBasic. To read and write to the tag I need MyItem's stack. How can I get the stack when it is not passed to IInventory.getStackInSlot(int) and IInventory.setInventorySlotContents(int, ItemStack)? So far, I am passing the stack to MyInventory when MyItem's gui is opened, but this will not work when two players modify the inventory at the same time.

     

    >you should not be changing the inventory on the client, you should only change it on the server

     

    I am not sure where to do this. In the gui handler?, testing for world.isRemote when opening the gui? do I override something in Container? in my implementation of IInventory?

     

    Here is MyInventory (inventory stack limit is 1, so decrStackSize is simplified. MyTagWrapper will read and write the tag) :

     

    public class MyInventory implements IInventory {
    
    private MyTagWrapper tag;
    private String name;
    private boolean hasName;
    
    public MyInventory(int size) {
    	tag = new MyTagWrapper(9);
    }
    
    public void setItemStack(ItemStack stack) {
    	tag.setTag(stack.getTagCompound());
    }
    
           ////// Implementation of IInventory
    
    @Override
    public ItemStack getStackInSlot(int i) {
    	if (i < 0 || i > tag.getSize() - 1) {
    		throw new IllegalArgumentException("Not in tag range: " + i);
    	}
    	return tag.getItemStack(i);
    }
    
    @Override
    public ItemStack decrStackSize(int i, int amount) {
    	ItemStack stack = tag.getItemStack(i);
    	tag.setItemStack(i, null);
    	return stack;
    }
    
    @Override
    public ItemStack getStackInSlotOnClosing(int i) {
    	if (tag.getItemStack(i) != null) {
    		ItemStack itemstack = tag.getItemStack(i);
    		tag.setItemStack(i, null);
    		return itemstack;
    	} else {
    		return null;
    	}
    }
    
    @Override
    public void setInventorySlotContents(int i, ItemStack stack) {
    	if (i < 0 || i > tag.getSize() - 1) {
    		throw new IllegalArgumentException("Not in tag range: " + i);
    	}
    	tag.setItemStack(i, stack);
    	markDirty();
    }
    
    @Override
    public int getSizeInventory() {
    	return tag.getSize();
    }
    
    @Override
    public String getInventoryName() {
    	return name;
    }
    
    @Override
    public boolean hasCustomInventoryName() {
    	return hasName;
    }
    
    @Override
    public int getInventoryStackLimit() {
    	return 1;
    }
    
    @Override
    public void markDirty() {
    }
    
    @Override
    public boolean isUseableByPlayer(EntityPlayer p_70300_1_) {
    	return true;
    }
    
    @Override
    public void openInventory() {
    }
    
    @Override
    public void closeInventory() {
    }
    
    @Override
    public boolean isItemValidForSlot(int i, ItemStack stack) {
    	return true;
    }
    }

     

     

  14. The safest (and easiest) way to override a method in Eclipse is to right click on the window background and choose Source>Override/Implement Methods... You can check to method(s) you want, then click Ok. This way you ensure the signatures are correct and the @Override notation is included.

     

    If you are not sure if you have all your @Override notations, choose Source>Clean Up...

  15. You have set field mirror on Right_Fin before you initialize it on the next line, so, Right_Fin is null.

     

          Right_Fin.mirror = true;
          Right_Fin = new ModelRenderer(this, 0, 0);
    

     

    If you are running from inside Eclipse (and you should be during development) exceptions and their stacktraces are printed to the console window. The file name and line number of each call are links that are hightlighted in red and underlined. You can click on the link and it will bring you directly to the line in the file where the call was made. In your case, clicking on Fish.java:45 will open Fish.java with the line

     

    Right_Fin.mirror = true;

     

    highlighted. There is only one thing that can be null here.

     

    Incidentally, does Techne really generate uppercase variable names?

     

  16. java.lang.NullPointerException: Rendering item

      at net.minecraft.item.ItemStack.getItemDamage(ItemStack.java:267)

     

    Line 267 of ItemStack looks like:

     

    public int getItemDamage()

        {

            return getItem().getDamage(this);

        }

     

    So, you have an ItemStack with a null item. My guess is your class BlockManager is returning null when one (or all) of its fields are being referenced:

     

          GameRegistry.addShapedRecipe(new ItemStack(BlockManager.amythestBlock), "xxx", "xxx", "xxx", 'x', ItemManager.amethyst);

          GameRegistry.addShapedRecipe(new ItemStack(BlockManager.blueTopazBlock), "xxx", "xxx", "xxx", 'x', ItemManager.blueTopaz);

          GameRegistry.addShapedRecipe(new ItemStack(BlockManager.carnelianBlock), "xxx", "xxx", "xxx", 'x', ItemManager.carnelian);

          GameRegistry.addShapedRecipe(new ItemStack(BlockManager.peridotBlock), "xxx", "xxx", "xxx", 'x', ItemManager.peridot);

          GameRegistry.addShapedRecipe(new ItemStack(BlockManager.roseQuartzBlock), "xxx", "xxx", "xxx", 'x', ItemManager.roseQuartz);

     

  17. The first line of your stack trace says you are calling a method on a null object in the constructor of your class Fish, on line 45.

     

    java.lang.NullPointerException: Initializing game

      at com.extraores.model.Fish.<init>(Fish.java:45)

     

    Your problem is not in class RenderMyFishMob. Go to line 45 of class Fish and look for an object you are calling a method on. For some reason, it is null.

×
×
  • Create New...

Important Information

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