Jump to content

[1.3.2 UNSOLVED] Create a flat block that can go between two blocks


Bandayd

Recommended Posts

Hi, I'm writing a very big mod, and there's just one thing that's eluding me...

I need to be able to place a block flat against another block (similar to how signs work, in vanilla 1.3.2), however, I need the player to be able to place a block up against the first block with the plate sandwiched in between.  I have already created a block that acts like a flat plate and uses metadata to remember which side of the block it was on and it works great!, but.... if I try and place a block up against the plate, it actually puts a full block of space between the two.  Here is a picture of how it currently works:

 

 

 

 

As you can see the dirt block is floating 1 block above the plate block.

But what I want it to do, is lay the dirt directly on top of the plate, almost like it's just sitting on the sand (but the plate is sandwiched in between)

 

Here is the code for just the plate block, because I believe it is all that applies:

 

public class BlockPlatePositive extends BlockContainer{
private int dir = 0;
private Class plateEntityClass;

    /**
     * each class overrdies this to return a new <className>
     */
    public TileEntity createNewTileEntity(World par1World)
    {
        try
        {
            return (TileEntity)this.plateEntityClass.newInstance();
        }
        catch (Exception var3)
        {
            throw new RuntimeException(var3);
        }
    }

protected BlockPlatePositive(int par1, Class par2Class, boolean par3)
    {
	super(par1, Material.iron);
	this.plateEntityClass = par2Class;

    // Sets the bounds of the block.  minX, minY, minZ, maxX, maxY, maxZ
    int i = 0;
    this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 0.001F, 1.0F); //.0625
    }

    public String getTextureFile()
    {
    	return "/slideRight/Textures/block.png";
    }

    /**
     * From the specified side and block metadata retrieves the blocks texture. Args: side, metadata
     */
    public int getBlockTextureFromSideAndMetadata(int par1, int par2)
    {
        return 7;//par1 == 1 ? 6 : (par1 == 1 ? 6 : 6);//this.blockIndexInTexture;
    }

    /**
     * Is this block (a) opaque and (b) a full 1m cube?  This determines whether or not to render the shared face of two
     * adjacent blocks and also whether the player can attach torches, redstone wire, etc to this block.
     */
    public boolean isOpaqueCube()
    {
        return false;
    }

    /**
     * If this block doesn't render as an ordinary block it will return False (examples: signs, buttons, stairs, etc)
     */
    public boolean renderAsNormalBlock()
    {
        return false;
    }

    /**
     * The type of render function that is called for this block
     */
    
    public int getRenderType()
    {
        return 0; //0 is the default
        		  //5 is redstone
        		  //2 is torch
    }
    
    
    /**
     * Returns whether this block is collideable based on the arguments passed in Args: blockMetaData, unknownFlag
     */
    @Override
    public boolean canCollideCheck(int par1, boolean par2)
    {
        return true;//par2 && par1 == 0;//return this.isCollidable();
    }
    
    /**
     * Checks to see if its valid to put this block at the specified coordinates. Args: world, x, y, z
     */
    public boolean canPlaceBlockAt(World par1World, int par2, int par3, int par4)
    {
    	return true;
    }

    /**
     * ejects contained items into the world, and notifies neighbours of an update, as appropriate
     */
    public void breakBlock(World par1World, int par2, int par3, int par4, int par5, int par6)
    {
        super.breakBlock(par1World, par2, par3, par4, par5, par6);

        if (!par1World.isRemote)
        {
            par1World.notifyBlocksOfNeighborChange(par2, par3 + 1, par4, this.blockID);
            par1World.notifyBlocksOfNeighborChange(par2, par3 - 1, par4, this.blockID);
            par1World.notifyBlocksOfNeighborChange(par2 + 1, par3, par4, this.blockID);
            par1World.notifyBlocksOfNeighborChange(par2 - 1, par3, par4, this.blockID);
            par1World.notifyBlocksOfNeighborChange(par2, par3, par4 + 1, this.blockID);
            par1World.notifyBlocksOfNeighborChange(par2, par3, par4 - 1, this.blockID);
        }
    }
    
    public int idDropped(int par1, Random par2Random, int par3)
    {
        return CommonProxy.platepositive.shiftedIndex; //CommonProxy.platepositive.;
    }

    
    /**
     * Returns a bounding box from the pool of bounding boxes (this means this box can change after the pool has been
     * cleared to be reused)
     * 
     * THIS IS WHAT ALLOWS YOU TO PASS THROUGH THE BLOCK!!! 
     */
    public AxisAlignedBB getCollisionBoundingBoxFromPool(World par1World, int par2, int par3, int par4)
    {
        return null;
    }
    
    
public void updatePlateDir(int mydir){
	switch (mydir) {
		case 0:
			//Y+
			this.setBlockBounds(0.0F, 0.999F, 0.0F, 1.0F, 1.0F, 1.0F); //.0625				
			break;
		case 1:
			//Y-
			this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 0.001F, 1.0F); //.0625
			break;
		case 2:
			//X+
			this.setBlockBounds(0.999F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F); //.0625
			break;
		case 3:
			//Z+
			this.setBlockBounds(0.0F, 0.0F, 0.999F, 1.0F, 1.0F, 1.0F); //.0625
			break;
		case 4:
			//X-
			this.setBlockBounds(0.0F, 0.0F, 0.0F, 0.001F, 1.0F, 1.0F); //.0625
			break;
		case 5:
			//Z-
			this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 0.001F); //.0625
			break;
	}
}
    
    /**
     * Updates the blocks bounds based on its current state. Args: world, x, y, z
     */
    public void setBlockBoundsBasedOnState(IBlockAccess par1IBlockAccess, int par2, int par3, int par4)
    {
        int var5 = par1IBlockAccess.getBlockMetadata(par2, par3, par4);
        updatePlateDir(var5);
    }

private int getBlockOrientation() {
    Minecraft mc = Minecraft.getMinecraft();
    //String myString = mc.thePlayer.getLookVec().toString();
    Vec3 myVec = mc.thePlayer.getLookVec();
    String myString;
    int returnVal = 0;
    if (Math.abs(myVec.xCoord) > Math.abs(myVec.yCoord)){
    	if (Math.abs(myVec.xCoord) > Math.abs(myVec.zCoord)){
    		if (myVec.xCoord > 0) {
    			myString = "+X";
    			returnVal = 2;
    		}else{
    			myString = "-X";
    			returnVal = 4;
    		}
    	}else{
    		if (myVec.zCoord > 0) {
    			myString = "+Z";
    			returnVal = 3;
    		}else{
    			myString = "-Z";
    			returnVal = 5;
    		}
    	}
    }else{
    	if (Math.abs(myVec.yCoord) > Math.abs(myVec.zCoord)){
    		if (myVec.yCoord > 0) {
    			myString = "+Y";
    			returnVal = 0;
    		}else{
    			myString = "-Y";
    			returnVal = 1;
    		}
    	}else{
    		if (myVec.zCoord > 0) {
    			myString = "+Z";
    			returnVal = 3;
    		}else{
    			myString = "-Z";
    			returnVal = 5;
    		}
    	}
    }
    mc.thePlayer.sendChatMessage(myString);
    Logger.getLogger("Minecraft").info(myString);
    return returnVal;
}
}

 

 

Now my best idea is to somehow get the game to allow two blocks to overlap, because in order for the plate to get sandwiched in between the blocks, one of the blocks are going to have to share space with the plate, at least, that's how I understand it? :-\

 

If anybody has any ideas about how this could be accomplished that would be great!  I do know this CAN be done because I've seen it done in a mod, however, that mod is A: Closed source, and B: is made by a dev that is NOT open to helping me in the slightest, and so I'm on my own on how to accomplish this magic trick, which is why I'm asking for your help! :-) Thanks dev community, you guys are awesome! :-D

Link to comment
Share on other sites

Pretty sure you're referring to RedPower2 there, with it's nice miniblocks. And, yes, you'd have to get the game to allow two blocks to overlap. I'm not entirely sure if this is possible, as All the RedPower blocks that overlap use the same Block ID, and I'm assuming the way they're able to be placed in the same block space is written into the code of the miniblocks. Unless you want to edit the main Blocks class, I'm not sure it's possible to have your block sit in the same space as vanilla or other mod blocks.

Link to comment
Share on other sites

For normal blocks you'll have to write you TE to detect the right click of the blockItem.If you don't have a TE(tileEntity) you'll need one to store extra info. When you TE detect the item as a block you'll need to save the block's class,or ID. From this you need too pull the block's render,texture,bound info. Then turn your block into a mirror of the block's looks with one side of it having your block's texture.

Link to comment
Share on other sites

For normal blocks you'll have to write you TE to detect the right click of the blockItem.If you don't have a TE(tileEntity) you'll need one to store extra info. When you TE detect the item as a block you'll need to save the block's class,or ID. From this you need too pull the block's render,texture,bound info. Then turn your block into a mirror of the block's looks with one side of it having your block's texture.

 

So if I understand you correctly, what I would wind up doing is, modding the dirt class to have metadata to know if it has a plate on each side of it, and then display that block appropriately showing the plate on that side.  I had thought of that idea, and that would work, however, that leaves one problem.  When the user tries to break the plate, I want them to be able to 1-shot the plate, but leave the dirt.  How would I be able to accomplish that?  Because I want it to show the plate being destroyed and have it drop on the ground, but I want it to leave the dirt.  Also, I'm assuming I would have to mod every single type of block, which is FAR from ideal.  Especially because this would now make it impossible for my mod to play nice with other mods because I can't mod blocks that don't exist right? :-\

 

So I believe that leaves me with 2 problems:

1. I'd have to mod EVERY block in minecraft

2. I don't believe it would look like the plate was being destroyed

 

Please, tell me I'm wrong so that I can get this to work :-P Thanks! :-)

 

Ok, sorry, I didn't read your post close enough the first time, so the way I'm understanding you now that I've read it more closely...

I'd basically be making a block that when you place it, it actually replaces the block you're putting it on, but then looks exactly like it but with one side having my plate on it.

That would almost work but the problem with that would be... if i put my plate on the side of, say, a redstone light, a jukebox, a noteblock etc.... these blocks would lose everything except how they look, and they would be disabled, until my plate "came off".  Not to mention, the same would be true for any modded blocks from any other mod.  That block would fail to work, it would just look like it did, until my plate came off.  Isn't there some way to modify the base block class?  I think that would work, then I could just add metadata to that to make it know if it has a plate on it, but I'm not sure that that can be done in forge because that would require me to mod the block.java class. :-(

Link to comment
Share on other sites

Pretty sure you're referring to RedPower2 there, with it's nice miniblocks. And, yes, you'd have to get the game to allow two blocks to overlap. I'm not entirely sure if this is possible, as All the RedPower blocks that overlap use the same Block ID, and I'm assuming the way they're able to be placed in the same block space is written into the code of the miniblocks. Unless you want to edit the main Blocks class, I'm not sure it's possible to have your block sit in the same space as vanilla or other mod blocks.

 

Actually no, although now I might have to take a look at that mod and see how they do things :-)

The mod I'm referring to is actually a VERY awesome mod called UGOcraft, but the dev on that one is not very nice, and the mod is NOT compatible with forge at all :-(

(also, the dev is NOT open to porting it to forge, or providing source, or anything)

 

You know, I'd be ok with editing the main block class, just as long as I can make it act like it should.  for example:

If you hit the plate, the plate will drop off and the block it was attached to will stay and the plate will drop on the ground so the player can pick it back up.  Is this behavior possible? :-\

Any pointers you could give me in that direction would be great! :-D

Link to comment
Share on other sites

You have look in the block halfSlab/doubleSlab?

 

Just changing a little, to check that place block on top, then store the placed block data, remove it and let change your plate to the block.

think must be possible.

I have already looked into the halfslabs/doubeslabs and that wont really help me, the way those work is, they store metadata to keep track of if it's single/double, etc... And so with those blocks, it's not really two blocks when you put a second one down, it just reads the metadata, makes the block bigger, and changes the texture.

Sorry, no dice :-(

Link to comment
Share on other sites

Ok, after thinking about this WAY too much, I think there's really only one way to do what it is that I need....

 

I think I need to be able to define a class at runtime, then, if I could do that, here's how I could accomplish what I need....

Step 1: When I place my plate, I don't really place my plate, instead, I get the class of the block it's being put onto

          a: Therefore, I can dynamically generate a new class that extends the class of the block it's being put onto, but it overrides the texture to show a plate on one side and the amount of damage it can take

Step 2: When the block gets hit with a tool/fist, have it only take 1 hit to destroy this modded block, but then when it gets destroyed, I'll have it replaces itself with a non-modded version of itself, and therefore making it seem like the plate was destroyed

 

Does that sound like it would work?

If so... um, could anybody point me to an easy way to implement what I need?

The basic thing I'm currently missing is...

I need to be able to do this:

public class BlockPlatePositive extends UnknownClass{

Where UnknownClass can be any class that I need it to be.

That way, if the plate is put on a piece of dirt, it will extend the dirt and put a plate on it.

Actually I just thought of something, let's assume I could do what I'm saying....

 

I still don't think it would work though, because if I put down one plate that looked like dirt, then I put down another plate on a piece of wool.  The first plate would now be on a piece of wool.... hmmmm.... apparently I'm back to where I started... so does anybody know how I might be able to do what I need? :-\

 

 

 

 

 

Link to comment
Share on other sites

Ok, after again, thinking about how in the world I can get around this, I've decided to settle on making a "mimic" block, that pretends to be other blocks like DarkGuardsman suggested.  I'm not happy about it, but, really it's the best way I can figure to get done what I needed without modding every class of block in minecraft.  :-\

 

I'll mark this one as solved as soon as I manage to get a proof of concept working.  Thanks for all your help! :-D

Link to comment
Share on other sites

You have look in the block halfSlab/doubleSlab?

 

Just changing a little, to check that place block on top, then store the placed block data, remove it and let change your plate to the block.

think must be possible.

I have already looked into the halfslabs/doubeslabs and that wont really help me, the way those work is, they store metadata to keep track of if it's single/double, etc... And so with those blocks, it's not really two blocks when you put a second one down, it just reads the metadata, makes the block bigger, and changes the texture.

Sorry, no dice :-(

Sorry my english is not so good, i was thinking in using the idea of the slabs, not the code.

you use BlockContainer, so you place a block over your plate, then store which block is placed over your block in your container, and make that your plate looks like the placedBlock, not replace with it.

When you give signal to your Block change back to plate Block and let flip the stored block up.

Hope you understand my Idea.

you can store so many things in the BlockContainer so must be possible.

only switch the rendering when it´s your placed plate or with placed Block.

 

 

Link to comment
Share on other sites

if you do it right you can get your mimic block to act like every single vanilla block. For example if you right click with a chest you can have your block turn into a chest by having the chest code inside your block&TE. It would be very complex coding but would work. However,i recommend just having blocks without function be able to be mimic-ed. This way you avoid issue and headaches trying to get it too work.

 

Also like WiNeTel said your not replacing as much transforming you block to look like the block being placed. You will use the onBlockActivated method and get the item being clicked with. Then you will remove one item from the player's hand and store the item name,or ID in a variable inside you TileEntity. Also from inside you TileEntity you will reference the item that was placed and steal its render,textures,and effects. This way your block will look like the placed block. 

Also if you do it that way add IF statement to check if the block being placed doesn't have a tileEntity, is a solid block, is a normal MC block, etc to prevent crashes.

Link to comment
Share on other sites

Ok, I think I've gotten a lot further, but I'm still stuck, so here's how far I've gotten...

When I try and place my plate, it first finds the block ID of the block that the plate is going against.  Then it replaces the block with my mimicking/plate block, which also stores the block ID and anything else I could want.  I actually set it up similar to a chest so it's actually holding a single stack of that block.  Then when you hit it, it drops the plate, and places the original plate back (or at least one with the same block ID :-P).

 

The problem I'm having is... in the "getBlockTextureFromSideAndMetadata" for my plate block, I need to be able to read the texture of the block I'm storing/mimicking.  The problem is, the only way I know how to do that is to use "world.getBlockTileEntity(x,y,z)" and it would be smooth sailing from there, however, I can't get the x,y,z of our current block in that function.  Here, I'll just post a few screenshots showing how it currently works.....

 

Before placing the plate block

 

 

 

After placing the plate block

 

 

 

After hitting at the plate block

 

 

 

Here is the code for my TileEntityPlate:

 

package myPackage;

import net.minecraft.client.Minecraft;
import net.minecraft.src.Block;
import net.minecraft.src.EntityPlayer;
import net.minecraft.src.IInventory;
import net.minecraft.src.ItemStack;
import net.minecraft.src.Material;
import net.minecraft.src.NBTTagCompound;
import net.minecraft.src.Packet;
import net.minecraft.src.Packet130UpdateSign;
import net.minecraft.src.TileEntity;
import net.minecraft.src.World;
import cpw.mods.fml.common.Side;
import cpw.mods.fml.common.asm.SideOnly;
import cpw.mods.fml.common.registry.GameRegistry;

public class TileEntityPlate extends TileEntity implements IInventory
{

/** An integer to indicate which side the plate is on
 * 
 *		0: Y+
 *		1: Y-
 *		2: X+
 *		3: Z+
 *		4: X-
 *		5: Z-
 *  */
//public int plateDirection = -1;
public byte[] hasPlateOnSide = {0,0,0,0,0,0};
public long fakeBlockID = -1;
public String texturePath = "";
public int[] textureIndexOnSide = {0,0,0,0,0,0};
private ItemStack inv;

    /**
     * Writes a tile entity to NBT.
     */
    public void writeToNBT(NBTTagCompound par1NBTTagCompound)
    {
        super.writeToNBT(par1NBTTagCompound);
        NBTTagCompound temp = par1NBTTagCompound.getCompoundTag("tileEntityPlate");
        //temp.setInteger("plateDirection", this.plateDirection);
        temp.setByteArray("hasPlateOnSide", this.hasPlateOnSide);
        temp.setLong("fakeBlockID", this.fakeBlockID);
        temp.setString("texturePath", texturePath);
        temp.setIntArray("textureIndexOnSide", textureIndexOnSide);
    }
    
    /**
     * Reads a tile entity from NBT.
     */
    public void readFromNBT(NBTTagCompound par1NBTTagCompound)
    {
        super.readFromNBT(par1NBTTagCompound);
        NBTTagCompound temp = par1NBTTagCompound.getCompoundTag("tileEntityPlate");
        //this.plateDirection = temp.getInteger("plateDirection");
        this.hasPlateOnSide = temp.getByteArray("hasPlateOnSide");
        this.fakeBlockID = temp.getLong("fakeBlockID"); 
        texturePath = temp.getString("texturePath");
        textureIndexOnSide = temp.getIntArray("textureIndexOnSide");
    }

    /**
     * signs and mobSpawners use this to send text and meta-data
     *//*
    public Packet getAuxillaryInfoPacket()
    {
        int var2 = new Integer(this.plateDirection);
        return new Packet130UpdateSign(this.xCoord, this.yCoord, this.zCoord, var2);
    }*/

    //@Override
    //public void onBlockActivated() {
    	//TODO
        /*
    	long tempBlockID = getBlockThisDir(par3World, par4, par5, par6, getBlockOrientation());
        Minecraft mc = Minecraft.getMinecraft();
        mc.thePlayer.sendChatMessage(""+ tempBlockID);
        */        
    //}

    
    /**
     * This function gets the block id in the direction of plateDirection
     * @param par3World 
     * 
     * @param plateDirection
     * @param i 
     * @param par6 
     * @param par5 
     * @return blockToReturn
     */
    private long getBlockThisDir(World par3World, int par4, int par5, int par6, int plateDirection){
    	long blockToReturn = -1;
    	//this is the coordinates of this block
    	int x = par4;
    	int y = par5;
    	int z = par6;
    	
    	//now I need to shift those coordinates based on plateDirection
    	switch (plateDirection) {
    	case 0: y++; break; //Y+
    	case 1: y--; break; //Y-
    	case 2: x++; break; //X+
    	case 3: z++; break; //Z+
    	case 4: x--; break; //X-
    	case 5: z--; break; //Z-
    	}
    	blockToReturn = par3World.getBlockId(x, y, z);
    	Minecraft mc = Minecraft.getMinecraft();
    	mc.thePlayer.sendChatMessage(blockToReturn+"");
    	Block TempBlock = new Block((int) blockToReturn, Material.air);
    	texturePath = TempBlock.getTextureFile();
    	//get all the textures from this block
    	for(int i=0;i<6;i++)
    		textureIndexOnSide[i] = TempBlock.getBlockTextureFromSide(i); 
    	//TODO now I need to change the texture based on that block ID
    	return blockToReturn;
    }

@Override
public int getSizeInventory() {
	return 1; //returns 1 because there's only 1 slot
}

@Override
public ItemStack getStackInSlot(int var1) {
	return inv; //return the only one we have
}

@Override
public ItemStack decrStackSize(int slot, int amt) {
	ItemStack stack = getStackInSlot(slot);
	if (stack != null) {
		if (stack.stackSize <= amt) {
			setInventorySlotContents(slot, null);
		} else {
			stack = stack.splitStack(amt);
			if (stack.stackSize == 0) {
				setInventorySlotContents(slot, null);
			}
		}
	}
	return stack;
}

@Override
public ItemStack getStackInSlotOnClosing(int slot) {
	ItemStack stack = getStackInSlot(slot);
	if (stack != null) {
		setInventorySlotContents(slot, null);
	}
	return stack;
}

@Override
public void setInventorySlotContents(int slot, ItemStack stack) {
	inv = stack;
	if (stack != null && stack.stackSize > getInventoryStackLimit()) {
		stack.stackSize = getInventoryStackLimit();
	}
}

@Override
public String getInvName() {
	return "container.plateBlock";
}

@Override
public int getInventoryStackLimit() {
	return 64;
}

@Override
public boolean isUseableByPlayer(EntityPlayer var1) {
	return false; //no, it's not
}

@Override
public void openChest() {}

@Override
public void closeChest() {}
    
    
}

 

 

Here is my tryPlaceItemIntoWorld from my ItemPlate.java:

 

public boolean tryPlaceIntoWorld(ItemStack par1ItemStack, EntityPlayer par2EntityPlayer, World world, int x, int y, int z, int par7, float par8, float par9, float par10)
{
	int myO = 0;
	switch (par7) {
	case 0:myO = 1;break;//--y;break; //1
	case 1:myO = 0;break;//++y;break; //0
	case 2:myO = 5;break;//--z;break; //5
	case 3:myO = 3;break;//++z;break; //3
	case 4:myO = 4;break;//--x;break; //2
	case 5:myO = 2;break;//++x;break; //4
	}

	if (!par2EntityPlayer.canPlayerEdit(x, y, z))
	{
		return false;
	}
	else
	{
		if (true) //(Block.redstoneWire.canPlaceBlockAt(par3World, par4, par5, par6))
		{
			--par1ItemStack.stackSize;
			//store the block ID first
			Block myBlock = Block.blocksList[world.getBlockId(x, y, z)];
		    //Now, I need to back up the original block's metadata (otherwise pistons go all crazy!)


			ItemStack inv = new ItemStack(myBlock);
			//int backupBlockID = world.getBlockId(x, y, z);
			world.setBlockAndMetadataWithNotify(x, y, z, blockIDToPlace(), myO);
			TileEntityPlate blockInv = (TileEntityPlate) world.getBlockTileEntity(x, y, z);
			try{
				blockInv.setInventorySlotContents(0, inv);
			}catch (Exception e){
				//do nothing
			}
			//now get the block ID of the block that is in that direction
		}

		return true;
	}
}

 

 

And lastly, here is the code from my PlateBlock.java that I think I need to use to control my block's texture, so I can make it mimic the blocks I need to:

 

/**
 * From the specified side and block metadata retrieves the blocks texture. Args: side, metadata
 */
public int getBlockTextureFromSideAndMetadata(int side, int par2)
{

	//This is where I think I need to be able to access my TileEntity, but I can't because I don't have my x,y,z coodinates

	//TileEntity tileEntity = blockWorld.getBlockTileEntity(x,y,z);
	//for now, just return 7 on all sides, since that is the texture for my plate
	return 7;
}

 

 

Now I think I'm doing what both of you guys suggested, when the item is placed, it backs up the block it's replacing inside the new block.  When the new block gets destroyed, it just restores it back.  My problem is.... I need to have access to my TileEntity inside my "public int getBlockTextureFromSideAndMetadata(int side, int par2)", that way, if the "side" parameter is the side my plate is on, I'll override that with my plate texture, but on the remaining sides, I'll just use the texture from my stored block, the problem is, I can't access the TiledEntity in getBlockTextureFromSideAndMetadata therefore I can't mimic the block like I need to.  Is there somewhere else I can control my plate block's texture from?  I thought getBlockTextureFromSideAndMetadata was the only place really? :-\ 

 

And remember, my whole problem is really the second picture I showed you (the one labeled "After placing the plate block"), because it's showing the plate texture on ALL sides, rather than displaying dirt on 5 sides, and my plate on 1 side.  (I'm familiar with how to show different textures on different sides, but I need to be able to access the TileEntity information to be able to do that)

 

Thanks in advance for all your help! :-D

Link to comment
Share on other sites

Actually, I've been playing around with metadata and I got it where when you place the block, it backs up the block's metadata, and then when you break the plate, it restores the block's metadata.  What's nice about that is, if you put the plate on a piston, it remembers which way the piston was facing, and if you put a plate on a jack-o-lantern, it remembers what type of pumpkin, and which the jack-o-lantern was facing.

 

So I think I understand the whole metadata thing, which is how your normally determine how to render the block, the problem is, normally metadata is just a single integer.  I need to be able to pass it an int, and 4 textures, and the name of the texture file.  So I think I need a tileentity to do this, but you can't pass a tileentity to the getBlockTextureFromSideAndMetadata function. :-\

 

Any ideas? (sorry if I'm repeating myself a little :-P)

Link to comment
Share on other sites

Nope, I already store it in the tileentity, however, when I try and access the tileentity in the getBlockTextureFromSideAndMetadata function, in order to get the tileentity, I need to use world.getBlockTileEntity(x, y, z);  But.... the function is defined as follows...

public int getBlockTextureFromSideAndMetadata(int side, int metadata)

and there's no way to get the x,y,z of the current block. :-(

 

Unless you know of another way to render the block without using the getBlockTextureFromSideAndMetadata function? That would be GREAT if you could give me a hint? :-D

 

Link to comment
Share on other sites

from inside you TileEntity you will reference the item that was placed and steal its render,textures,and effects. This way your block will look like the placed block. 

Also if you do it that way add IF statement to check if the block being placed doesn't have a tileEntity, is a solid block, is a normal MC block, etc to prevent crashes.

 

I've already re-coded everything to work how I think you suggested (with the block mimicking the block it's replacing).  But I'm having trouble getting the information from the TileEntity, to the actual block texture, is there any way I can set the block texture of my block besides "getBlockTextureFromSideAndMetadata"?  Because I don't think I can access the TileEntity from there? :-\

 

Thanks again for your help with this :)

Link to comment
Share on other sites

You could setup your TileEntity to have its own render class and use packets to send the data from server(or local server) to client. Since the render.class can get TileEntity it can get all the info it needs for rendering the correct sides and such.

 

Any chance you could point me to example code for something like that? :-\

 

Thanks for the quick response! :-D

Link to comment
Share on other sites

here browse my src for steam power i use a render class that contains 3 separate sub models for one block. redpower i believe uses something similar to render all of its diffrent block shapes. Though yours will be more complex so you might want to look at minecraft's block renderer. It has code to bind textures to each side of the block which you need.

Link to comment
Share on other sites

here browse my src for steam power i use a render class that contains 3 separate sub models for one block. redpower i believe uses something similar to render all of its diffrent block shapes. Though yours will be more complex so you might want to look at minecraft's block renderer. It has code to bind textures to each side of the block which you need.

 

Thank you DarkGuardsman, that helped a ton!

 

I did dig around a lot in both WorldRenderer.java and RenderBlocks.java, and the best thing I can come up with would be for forge to add a hook into func_78588_a (on line 3692 of RenderBlocks.java), or wherever it is that I can render a second texture to the same block. :-)

 

Now I'm one step further, I can render a block, and I can even make two separate "models" (rectangles), however, I am only able to apply one texture to both of these rectangles. :-(  I need to be able to specify two separate textures, one for the plate, and one for the "block that I'm mimicking".  I'm starting to wonder if this can be done with forge :-\  I'm going to keep digging though.  I will be sure and update my post if I get anywhere, but at this point, I'm stuck on separating the textures of the two different pieces. 

 

Here is a picture, just showing how I'm able to do two different rectangles.

 

 

 

So the next step would be, I need to be able to apply TWO textures to my "blocks" (I know it's only one block, but it's rendered as two).  One texture will be my plate texture, and the other texture will be the texture of the block I'm mimicking.

 

So I'm off to search for "how to render two textures to one TileEntitySpecialRenderer, OR, how to bindTileEntitySpecialRenderer TWO renderers to ONE class" :-P

 

If anybody has any idea on how to do this, please don't hesitate to pitch in! :-D

I'm starting to think I need forge to add a new hook for binding two textures to one TileEntitySpecialRenderer? :-\

What do you guys think?

 

Also, if it helps any, here is my "TileEntitySpecialRenderer" class that I'm using which give me the awesome picture above... :-P

 

import java.lang.ref.Reference;

import cpw.mods.fml.common.Side;
import cpw.mods.fml.common.asm.SideOnly;
import net.minecraft.src.Block;
import net.minecraft.src.BlockChest;
import net.minecraft.src.ModelLargeChest;
import net.minecraft.src.TileEntity;
import net.minecraft.src.TileEntityChest;
import net.minecraft.src.TileEntitySpecialRenderer;
import net.minecraftforge.client.ForgeHooksClient;
import net.minecraftforge.common.ForgeHooks;

import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL12;

@SideOnly(Side.CLIENT)
public class RenderPlate extends TileEntitySpecialRenderer
{
    /** The normal small chest model. */
private ModelPlate plateModel = new ModelPlate();
private ModelPlateMimic plateModelMimic = new ModelPlateMimic();

    /**
     * Renders the TileEntity for the plate at a position.
     */
    public void renderTileEntityPlateAt(TileEntityPlate tileEntityPlate, double x, double y, double z, float f)
    {
        int md;

        if (!tileEntityPlate.func_70309_m()){
            md = 0;
        }else{
            Block tE = tileEntityPlate.getBlockType();
            md = tileEntityPlate.getBlockMetadata();
            if (tE != null && md == 0){
                md = tileEntityPlate.getBlockMetadata();
            }
        }
        ModelPlate pM;
        ModelPlateMimic pMM;
        pM = this.plateModel;
        pMM = this.plateModelMimic;
        this.bindTextureByName("/myMod/Textures/blockPlate.png");
        GL11.glPushMatrix();
        GL11.glEnable(GL12.GL_RESCALE_NORMAL);
        GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
        GL11.glTranslatef((float)x, (float)y + 1.0F, (float)z + 1.0F);
        GL11.glScalef(1.0F, -1.0F, -1.0F);
        pM.renderAll();
        pMM.renderAll();
        GL11.glDisable(GL12.GL_RESCALE_NORMAL);
        GL11.glPopMatrix();
        GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
    }

    public void renderTileEntityAt(TileEntity par1TileEntity, double par2, double par4, double par6, float par8)
    {
        this.renderTileEntityPlateAt((TileEntityPlate)par1TileEntity, par2, par4, par6, par8);
    }
}

 

 

But as you can see, the line "this.bindTextureByName("/myMod/Textures/blockPlate.png");" is only able to apply a single texture to the current TileEntity :-(

Link to comment
Share on other sites

You can use more than one bindTextureByName.

Something like this:

        this.bindTextureByName("/myMod/Textures/blockPlate.png");
        pM.renderAll();
        this.bindTextureByName("/terrain.png");
        pMM.renderAll();

 

I was already using bindTextureByName... buuuut... it didn't occur to me that I could load one texture.... render it, then load another texture! :-P

Thanks N1xx1!  Not only do I think that will work, but now I feel kinda dumb for not thinking of that! :-P lol

 

I'll give that a shot tonight after I get home from work, and I'll report back here how it worked :-)

 

Thanks again!!! :-D

Link to comment
Share on other sites

I´am not sure how work in 1.3.2 but in 1.2.5 was a method i found a try 1 time:

 

in modfile was something with

public boolean renderWorldBlock(RenderBlocks var1, IBlockAccess var2, int var3, int var4, int var5, Block var6, int var7)

    {

. . . .

.getBlockTileEntity

 

. . .

var1.overrideBlockTexture = texture;

 

something like this, sorry not remember verry good, it´s month ago, that was playing around with it

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.



  • Recently Browsing

    • No registered users viewing this page.
  • Posts

    • https://mclo.gs/4UC49Ao
    • Way back in the Forge 1.17 days, work started for adding JPMS (Java Platform Module Support) to ModLauncher and ForgeModLoader. This has been used internally by Forge and some libraries for a while now, but mods (those with mods.toml specifically) have not been able to take advantage of it. As of Forge 1.21.1 and 1.21.3, this is now possible!   What is JPMS and what does it mean for modders? JPMS is the Java Platform Module System, introduced in Java 9. It allows you to define modules, which are collections of packages and resources that can be exported or hidden from other modules. This allows for much more fine-tuned control over visibility, cleaner syntax for service declarations and support for sealed types across packages. For example, you might have a mod with a module called `com.example.mod` that exports `com.example.mod.api` and `com.example.mod.impl` to other mods, but hides `com.example.mod.internal` from them. This would allow you to have a clean API for other mods to use, while keeping your internal implementation details hidden from IDE hints, helping prevent accidental usage of internals that might break without prior notice. This is particularly useful if you'd like to use public records with module-private constructors or partially module-private record components, as you can create a sealed interface that only your record implements, having the interface be exported and the record hidden. It's also nice for declaring and using services, as you'll get compile-time errors from the Java compiler for typos and the like, rather than deferring to runtime errors. In more advanced cases, you can also have public methods that are only accessible to specific other modules -- handy if you want internal interactions between multiple of your own mods.   How do I bypass it? We understand there may be drama in implementing a system that prevents mods from accessing each other's internals when necessary (like when a mod is abandoned or you need to fix a compat issue) -- after all, we are already modding a game that doesn't have explicit support for Java mods yet. We have already thought of this and are offering APIs from day one to selectively bypass module restrictions. Let me be clear: Forge mods are not required to use JPMS. If you don't want to use it, you don't have to. The default behaviour is to have fully open, fully exported automatic modules. In Java, you can use the `Add-Opens` and `Add-Exports` manifest attributes to selectively bypass module restrictions of other mods at launch time, and we've added explicit support for these when loading your Forge mods. At compile-time, you can use existing solutions such as the extra-java-module-info Gradle plugin to deal with non-modular dependencies and add extra opens and exports to other modules. Here's an example on how to make the internal package `com.example.examplemod.internal` open to your mod in your build.gradle: tasks.named('jar', Jar) { manifest { attributes([ 'Add-Opens' : 'com.example.examplemod/com.example.examplemod.internal' 'Specification-Title' : mod_id, 'Specification-Vendor' : mod_authors // (...) ]) } } With the above in your mod's jar manifest, you can now reflectively access the classes inside that internal package. Multiple entries are separated with a space, as per Java's official spec. You can also use Add-Exports to directly call without reflection, however you'd need to use the Gradle plugin mentioned earlier to be able to compile. The syntax for Add-Exports is the same as Add-Opens, and instructions for the compile-time step with the Gradle plugin are detailed later in this post. Remember to prefer the opens and exports keywords inside module-info.java for sources you control. The Add-Opens/Add-Exports attributes are only intended for forcing open other mods.   What else is new with module support? Previously, the runtime module name was always forced to the first mod ID in your `mods.toml` file and all packages were forced fully open and exported. Module names are now distinguished from mod IDs, meaning the module name in your module-info.java can be different from the mod ID in your `mods.toml`. This allows you to have a more descriptive module name that doesn't have to be the same as your mod ID, however we strongly recommend including your mod ID as part of your module name to aid troubleshooting. The `Automatic-Module-Name` manifest attribute is now also honoured, allowing you to specify a module name for your mod without needing to create a `module-info.java` file. This is particularly useful for mods that don't care about JPMS features but want to have a more descriptive module name and easier integration with other mods that do use JPMS.   How do I use it? The first step is to create a `module-info.java` file in your mod's source directory. This file should be in the same package as your main mod class, and should look something like this: open module com.example.examplemod { requires net.minecraftforge.eventbus; requires net.minecraftforge.fmlcore; requires net.minecraftforge.forge; requires net.minecraftforge.javafmlmod; requires net.minecraftforge.mergetool.api; requires org.slf4j; requires logging; } For now, we're leaving the whole module open to reflection, which is a good starting point. When we know we want to close something off, we can remove the open modifier from the module and open or export individual packages instead. Remember that you need to be open to Forge (module name net.minecraftforge.forge), otherwise it can't call your mod's constructor. Next is fixing modules in Gradle. While Forge and Java support modules properly, Gradle does not put automatic modules on the module path by default, meaning that the logging module (from com.mojang:logging) is not found. To fix this, add the Gradle plugin and add a compile-time module definition for that Mojang library: plugins { // (...) id 'org.gradlex.extra-java-module-info' version "1.9" } // (...) extraJavaModuleInfo { failOnMissingModuleInfo = false automaticModule("com.mojang:logging", "logging") } The automatic module override specified in your build.gradle should match the runtime one to avoid errors. You can do the same for any library or mod dependency that is missing either a module-info or explicit Automatic-Module-Name, however be aware that you may need to update your mod once said library adds one. That's all you need to get started with module support in your mods. You can learn more about modules and how to use them at dev.java.
    • Faire la mise à jour grâce à ce lien m'a aider personnellement, merci à @Paint_Ninja. https://www.amd.com/en/support 
    • When I came across the 'Exit Code: I got a 1 error in my Minecraft mods, so I decided to figure out what was wrong. First, I took a look at the logs. In the mods folder (usually where you'd find logs or crash reports), I found the latest.log file or the corresponding crash report. I read it through carefully, looking for any lines with errors or warnings. Then I checked the Minecraft Forge support site, where you can often find info on what causes errors and how to fix them. I then disabled half of my mods and tried running the game. If the error disappeared, it meant that the problem was with the disabled mod. I repeated this several times to find the problem mod.
    • I have no idea - switch to a pre-configured modpack and use it as working base    
  • Topics

  • Who's Online (See full list)

×
×
  • Create New...

Important Information

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