Hello all,
I've worked some time on my Friend Bush and ran into a problem:
How can I save an integer and a string in my block?
My block code is:
public class BlockFriendBush extends BlockFlower
{
public BlockFriendBush(int par1)
{
super(par1, Material.vine);
float f = 0.4F;
this.setBlockBounds(0.5F - f, 0.0F, 0.5F - f, 0.5F + f, 0.8F, 0.5F + f);
}
/**
* Gets passed in the blockID of the block below and supposed to return true if its allowed to grow on the type of
* blockID passed in. Args: blockID
*/
protected boolean canThisPlantGrowOnThisBlockID(int par1)
{
return par1 == Block.sand.blockID;
}
/**
* Returns the ID of the items to drop on destruction.
*/
public int idDropped(int par1, Random par2Random, int par3)
{
return -1;
}
String owner;
int FriendVar = 0;
public boolean onBlockActivated(World world, int par2, int par3, int par4, EntityPlayer player, int par6, float f1, float f2, float f3)
{
int first = 0;
if (first == 0)
{
this.owner = player.username;
first = 1;
}
if(player.username == this.owner){
if(player.getCurrentEquippedItem() != null)
{
ItemStack held = player.getCurrentEquippedItem();
if(held.getItem().itemID == Item.diamond.itemID)
{
if(world.isRemote){
player.addChatMessage("Oh... Is that... a diamond? For ... ME? You're a really good friend!"
+ " Thanks!");
}
player.inventory.consumeInventoryItem(held.itemID);
this.FriendVar = FriendVar +10;
}
else if(held.getItem().itemID == Item.appleRed.itemID)
{
if(world.isRemote){
player.addChatMessage("Now I can grow and become a big and strong Bush! YAAY! You made me happy, my friend!");
}
player.inventory.consumeInventoryItem(held.itemID);
this.FriendVar = FriendVar +3;
}
else if(held.getItem().itemID == Item.goldenCarrot.itemID)
{
if(world.isRemote){
player.addChatMessage("A golden carrot!");
}
player.inventory.consumeInventoryItem(held.itemID);
}
/**
else if(held.getItem().itemID == Item.emerald.itemID)
{
if(world.isRemote){
player.addChatMessage("You want to trade?");
player.addChatMessage("Here you are!");
}
player.inventory.consumeInventoryItem(held.itemID);
}
**/
}
else
{
if(this.FriendVar < 5){
if(world.isRemote){
player.addChatMessage("Hello "+ player.username + ".");
}
}
if(this.FriendVar >= 5 && this.FriendVar < 10){
if(world.isRemote){
player.addChatMessage("Hello my friend "+ player.username + "!");
}
}
else if(this.FriendVar >= 10 && this.FriendVar < 20){
if(world.isRemote){
player.addChatMessage("Hello my really good friend "+ player.username + "!");
}
}
else if(this.FriendVar > 20){
if(world.isRemote){
player.addChatMessage("Hello my really really good friend "+ player.username + "!");
}
}
}
}
return true;
}
/**
* Called when the player destroys a block with an item that can harvest it. (i, j, k) are the coordinates of the
* block and l is the block's subtype/damage.
*/
public void harvestBlock(World par1World, EntityPlayer par2EntityPlayer, int par3, int par4, int par5, int par6)
{
if (!par1World.isRemote && par2EntityPlayer.getCurrentEquippedItem() != null && par2EntityPlayer.getCurrentEquippedItem().itemID == Item.shears.itemID)
{
par2EntityPlayer.addStat(StatList.mineBlockStatArray[this.blockID], 1);
this.dropBlockAsItem_do(par1World, par3, par4, par5, new ItemStack(Base.FriendBush, 1, par6));
}
else
{
super.harvestBlock(par1World, par2EntityPlayer, par3, par4, par5, par6);
}
}
public void registerIcons(IconRegister reg)
{
this.blockIcon = reg.registerIcon("deadbush");
}
}
For the code: All rights reserved!!!
(You can use the chat message code, it was taken from the minecraft forge forum, but for more code you'll have to ask me!)
Also, for the trade thing, how can I make the bush drop an item without destroying it?
For the code: All rights reserved!!!
(You can use the chat message code, it was taken from the minecraft forge forum, but for more code you'll have to ask me!)
There's nothing in the code above that you can legally claim copyright on, so wtf...
Getting to the actual question here:
The only standard storage media you can use for blocks is the metadata, which is only a so-called nibble, a number from 0 to 15. If you think the integer you are storing could fit inside this limited storage, use it.
A string must be stored otherwise, obviously. You will need to create a so-called Tile Entity for your block, which is pretty much an extended block storage with a few more features. I'm not going to cover this because there is a lot of material on this already, so search it up. Use the Tile Entity to store the string (and the integer if the metadata doesn't suffice).
But if I won't do that, anyone could implement a friend bush with MY system. Yes, it's vanilla logic etc., but...
I can't use metadata, so how could I call THIS function of onBlockActivated in a TileEntity?
But if I won't do that, anyone could implement a friend bush with MY system. Yes, it's vanilla logic etc., but...
I can't use metadata, so how could I call THIS function of onBlockActivated in a TileEntity?
Robbi Blechdose
Take a step back, bro. You're claiming copyright on a handful of lines of code, entirely build on someone else's game. You have no claim to copyright whatsoever, and no court in the world will ever take you seriously. So stop this childish behavior already.
Everyone, just ignore the pointless copyright stuff. You are trying to be right instead of trying to be helpful.
What you are going to do is to use the Tile Entity as a container. Add the integer and string to the tile entity class, and remember to connect the block and the belonging tile entity class with the ITileEntityProvider interface. Also remember to register the tile entity with Minecraft Forge with GameRegistry.registerTileEntity(). Whenever you need to access or save this information in a block method, fetch the tile entity with world.getBlockTileEntity(x, y ,z) and do what you need with it.
I'm not giving thorough instructions on this because, as stated earlier, there is already plenty of material on this.
Glenn, you've been REALLY helpful!
Just one question: Do I have to write the speak/chat method into the TileEntity or into the Block?
Robbi Blechdose
It doesn't matter. Code is code. Almost all events tied to a block go directly to the block, therefore it would be intuitive to write it in the block class.
Could work, tested it (in code), but in which class do I have to write the integer and the string?
I know how I could write and read that from NBT, but if I have the int and the string in my block, the TileEntity says:change modifier to static.
If I have it in the TileEntity, the block says: change modifier to static.
What can I do?
You would of course have to put the integer and string in the tile entity class, otherwise there would be absolutely no need to use tile entities in the first place.
You must not have to change any fields in the tile entity to static, you have to do as Mazetar said: Reference it by the tile entity instance. You can get the tile entity for an instance with world.getBlockTileEntity(). You will have to typecast this to your own entity to get the content.
Your block does not implement the ITileEntityProvider interface, which is vital to make blocks have tile entities. To do this, change
public class BlockFriendBush extends BlockFlower
to
public class BlockFriendBush extends BlockFlower implements ITileEntityProvider
When your block implements the ITileEntityProvider interface, a tile entity for the block is always created when the block is placed in the world. If you don't do this, you will get loads of null pointer exceptions.
You also seem to misunderstand the way blocks and tile entities interact. Let me explain with a few examples from my mod, Glenn's Gases.
Glenn's Gases has a gas tank block. A tank is capable of containing certain amount of a certain gas. To save which gas is in the tank and how much there is of it, I use a tile entity. Simplified, the tile entity class looks like this:
public class TileEntityTank extends TileEntity
{
public GasType containedType;
public int amount;
public TileEntityTank()
{
amount = 0;
}
public void readFromNBT(NBTTagCompound par1NBTTagCompound)
{
super.readFromNBT(par1NBTTagCompound);
amount = par1NBTTagCompound.getInteger("amount");
int i = par1NBTTagCompound.getInteger("containedType");
if(i == -1)
{
containedType = null;
}
else
{
containedType = GasType.gasTypes[i];
}
}
public void writeToNBT(NBTTagCompound par1NBTTagCompound)
{
super.writeToNBT(par1NBTTagCompound);
par1NBTTagCompound.setInteger("amount", amount);
par1NBTTagCompound.setInteger("containedType", containedType != null ? containedType.gasIndex : -1);
}
public Packet getDescriptionPacket()
{
NBTTagCompound nbtTag = new NBTTagCompound();
this.writeToNBT(nbtTag);
return new Packet132TileEntityData(this.xCoord, this.yCoord, this.zCoord, 1, nbtTag);
}
public void onDataPacket(INetworkManager net, Packet132TileEntityData packet)
{
readFromNBT(packet.data);
}
}
It's very much a tile entity like yours. Now, how do I use it in the block class? Here's a shortened version:
public class BlockGasTank extends Block implements ITileEntityProvider
{
public BlockGasTank(int blockID)
{
super(blockID, Material.iron);
}
@Override
public TileEntity createNewTileEntity(World world)
{
return new TileEntityTank();
}
public boolean onBlockActivated(World world, int x, int y, int z, EntityPlayer entityPlayer, int par6, float par7, float par8, float par9)
{
//Do whatever with the tile entity
TileEntityTank tileEntity = (TileEntityTank)world.getBlockTileEntity(x, y, z);
//tileEntity.amount += 10 etc.
}
}
You will have to remove the "tile" field in your block class, since tile entities are not global.
I've worked some time on my Friend Bush and ran into a problem:
How can I save an integer and a string in my block?
My block code is:
For the code: All rights reserved!!!
(You can use the chat message code, it was taken from the minecraft forge forum, but for more code you'll have to ask me!)
Also, for the trade thing, how can I make the bush drop an item without destroying it?
Robbi Blechdose
There's nothing in the code above that you can legally claim copyright on, so wtf...
It gave me a good chuckle.
My mods: Archmagus, BetterBoneMeal, BetterVanilla, Brewing-API, NaturalArmors, and PluckableChickens!
What?
I've written the system (without the chat) on my own!!!
And what seriously?
Robbi Blechdose
I'm using the method with two parameters.
Robbi Blechdose
The only standard storage media you can use for blocks is the metadata, which is only a so-called nibble, a number from 0 to 15. If you think the integer you are storing could fit inside this limited storage, use it.
A string must be stored otherwise, obviously. You will need to create a so-called Tile Entity for your block, which is pretty much an extended block storage with a few more features. I'm not going to cover this because there is a lot of material on this already, so search it up. Use the Tile Entity to store the string (and the integer if the metadata doesn't suffice).
I see only calls to forge and vanilla code there, and no real custom logic anywhere.
You are claiming copyright on code belonging to other's..
I can't use metadata, so how could I call THIS function of onBlockActivated in a TileEntity?
Robbi Blechdose
I want to call my speak/chat function with onBlockActivated. How can I do this in a TileEntity?
Robbi Blechdose
And if not, can anyone tell me how to call the method then?
Robbi Blechdose
Take a step back, bro. You're claiming copyright on a handful of lines of code, entirely build on someone else's game. You have no claim to copyright whatsoever, and no court in the world will ever take you seriously. So stop this childish behavior already.
My mods: Archmagus, BetterBoneMeal, BetterVanilla, Brewing-API, NaturalArmors, and PluckableChickens!
What you are going to do is to use the Tile Entity as a container. Add the integer and string to the tile entity class, and remember to connect the block and the belonging tile entity class with the ITileEntityProvider interface. Also remember to register the tile entity with Minecraft Forge with GameRegistry.registerTileEntity(). Whenever you need to access or save this information in a block method, fetch the tile entity with world.getBlockTileEntity(x, y ,z) and do what you need with it.
I'm not giving thorough instructions on this because, as stated earlier, there is already plenty of material on this.
Just one question: Do I have to write the speak/chat method into the TileEntity or into the Block?
Robbi Blechdose
It doesn't matter. Code is code. Almost all events tied to a block go directly to the block, therefore it would be intuitive to write it in the block class.
I know how I could write and read that from NBT, but if I have the int and the string in my block, the TileEntity says:change modifier to static.
If I have it in the TileEntity, the block says: change modifier to static.
What can I do?
Robbi Blechdose
You must not have to change any fields in the tile entity to static, you have to do as Mazetar said: Reference it by the tile entity instance. You can get the tile entity for an instance with world.getBlockTileEntity(). You will have to typecast this to your own entity to get the content.
and
but it doesn't seem to work.
Robbi Blechdose
You have almost set this up correctly.
Your block does not implement the ITileEntityProvider interface, which is vital to make blocks have tile entities. To do this, change
to
When your block implements the ITileEntityProvider interface, a tile entity for the block is always created when the block is placed in the world. If you don't do this, you will get loads of null pointer exceptions.
You also seem to misunderstand the way blocks and tile entities interact. Let me explain with a few examples from my mod, Glenn's Gases.
Glenn's Gases has a gas tank block. A tank is capable of containing certain amount of a certain gas. To save which gas is in the tank and how much there is of it, I use a tile entity. Simplified, the tile entity class looks like this:
It's very much a tile entity like yours. Now, how do I use it in the block class? Here's a shortened version:
You will have to remove the "tile" field in your block class, since tile entities are not global.
Robbi Blechdose