I have custom block and I want to make when player click on him that will save info about the player..So I knows about the onBlockClicked() but I can't figure out how to save data about the player when it happening...Thank you for all the helpers..
So, in your BlockX class, you should override the method
'public void onBlockClicked(World p_149699_1_, int p_149699_2_, int p_149699_3_, int p_149699_4_, EntityPlayer p_149699_5_) {}'
Now, since Java doesn't look at function names for overriding, we can substitute normal things in:
'public void onBlockClicked(World world, int x, int y, int z, EntityPlayer player) {}'
So, onto the problem. The sort of data you are saving is too complex to store within metadata, so we're going to need a 'TileEntity'. Simple enough, create a new class, let it extend TileEntity, and that's the TE!
Now, by default, this won't really do much. It'll work, but you want to do some more stuff here...
So add a new variable to TileEntityX, and it's gonna be a String. Call it 'playerName', as that's what we're gonna store right now.
Got it? Good, now, you need to add two functions to your TileEntityX: 'public void readFromNBT(NBTTagCompound nbt)' and 'public void writeToNBT(NBTTagCompound nbt)'
Both of these need to call their super methods (so do super.readFromNBT(nbt) for the reading, and super.writeToNBT(nbt) for the writing). These basically store the data, and allow the TE to recover it.
After that, we need to add some content to the methods. In 'readFromNBT', add this:
'this.playerName = nbt.getString("PlayerName");'
For 'writeToNBT', put this:
'nbt.setString("PlayerName", playerName);' <-- Thanks to iTooly for pointing this out xD
Congratulations! Your TileEntity will now store data!
But, we never really set that data, nor does our block use it...
Quick important sidestep: You need to put this in either your preinit, init or postinit methods (or whatever they're called):
'TileEntity.addMapping(TileEntityX.class, "modname:TileEntityX");'
This gives the TileEntity a way to actually store it's data with the level (I believe)
Anyway, back to the block.
First important thing, you need to tell the game you're using a tile entity. So, to do that, let your block implement 'ITileEntityProvider'. This should require you to implement a method: 'TileEntity createNewTileEntity(World var1, int var2);'. This is pretty simple, just put this:
'public void TileEntity createNewTileEntity(World var1, int var2)
{
return new TileEntityX();
}'
This just creates a new instance of TileEntityX when you place the block down.
Now, remember our method at the start? Let's start populating it!
First step is to check if we're on the client or the server. If we're on the client, we can't do anything to the TileEntity, but if we're on the server, then we can do stuff.
So simply put: if(world.isRemote) return true;
Then, we can get onto the fun stuff!
So, put this after your if check:
TileEntity te = world.getTileEntity(x, y, z); //Get the TileEntity at this location
if(!(te instanceof TileEntityX)) return false;//If it's not a TileEntityX, then return
TileEntityX tex = (TileEntityX) te; // Cast te to the right type
tex.playerName = player.getCommandSenderName(); //Get's the name
world.setTileEntity(x, y, z, tex); //Sets the tile entity at that location
That's the fancy stuff that sets the actual string in the tile entity. Then, you can read it using very similar code:
TileEntity te = world.getTileEntity(x, y, z); //Get the TileEntity at this location
if(!(te instanceof TileEntityX)) return false;//If it's not a TileEntityX, then return
TileEntityX tex = (TileEntityX) te; // Cast te to the right type
System.out.println("See? This is their name: " + tex.playerName);
Probably not related, but in onBlockClicked:
Change:
if(tex.playerName == player.getCommandSenderName())
to
if(tex.playerName.equals(player.getCommandSenderName()))
Java doesn't compare strings with ==, it uses .equals()
It mean that it will check for all the blocks from that type..
Just for you I removed the static and it didn't work..
Just for me, eh? Lol. So, what about it 'didn't work' after you removed the static keyword? Did you also change it to run on the server, i.e. when the world is not remote, like the post above mine mentioned?
By the way, that's a pretty ambiguous and vague definition of static, and I certainly hope you read the Oracle documentation on it because the fact that you were using it in the way in which you were using it suggests you don't understand what it means, which is why I suggested you research it. But that's up to you.
One other thing I noticed, that probably isn't breaking your code but is still not necessary and is probably harmful, is that you use 'world.setTileEntity' with the tile entity that you just got and modified, but there is no reason to set the tile entity unless you are changing the type of tile entity that is at that location (which you should never do anyway).
Anyway, you should do some debugging on your own: put println in the read and write NBT methods of your TileEntity to see what the player's name is at those times; do the same in your Block class when interacting, etc. That is one of the most basic programming skills there is, and even advanced programmers use it all the time because it's so dang useful.
So, in your BlockX class, you should override the method
'public void onBlockClicked(World p_149699_1_, int p_149699_2_, int p_149699_3_, int p_149699_4_, EntityPlayer p_149699_5_) {}'
Now, since Java doesn't look at function names for overriding, we can substitute normal things in:
'public void onBlockClicked(World world, int x, int y, int z, EntityPlayer player) {}'
So, onto the problem. The sort of data you are saving is too complex to store within metadata, so we're going to need a 'TileEntity'. Simple enough, create a new class, let it extend TileEntity, and that's the TE!
Now, by default, this won't really do much. It'll work, but you want to do some more stuff here...
So add a new variable to TileEntityX, and it's gonna be a String. Call it 'playerName', as that's what we're gonna store right now.
Got it? Good, now, you need to add two functions to your TileEntityX: 'public void readFromNBT(NBTTagCompound nbt)' and 'public void writeToNBT(NBTTagCompound nbt)'
Both of these need to call their super methods (so do super.readFromNBT(nbt) for the reading, and super.writeToNBT(nbt) for the writing). These basically store the data, and allow the TE to recover it.
After that, we need to add some content to the methods. In 'readFromNBT', add this:
'this.playerName = nbt.getString("PlayerName");'
For 'writeToNBT', put this:
'nbt.setString("PlayerName", playerName);' <-- Thanks to iTooly for pointing this out xD
Congratulations! Your TileEntity will now store data!
But, we never really set that data, nor does our block use it...
Quick important sidestep: You need to put this in either your preinit, init or postinit methods (or whatever they're called):
'TileEntity.addMapping(TileEntityX.class, "modname:TileEntityX");'
This gives the TileEntity a way to actually store it's data with the level (I believe)
Anyway, back to the block.
First important thing, you need to tell the game you're using a tile entity. So, to do that, let your block implement 'ITileEntityProvider'. This should require you to implement a method: 'TileEntity createNewTileEntity(World var1, int var2);'. This is pretty simple, just put this:
'public void TileEntity createNewTileEntity(World var1, int var2)
{
return new TileEntityX();
}'
This just creates a new instance of TileEntityX when you place the block down.
Now, remember our method at the start? Let's start populating it!
First step is to check if we're on the client or the server. If we're on the client, we can't do anything to the TileEntity, but if we're on the server, then we can do stuff.
So simply put: if(world.isRemote) return true;
Then, we can get onto the fun stuff!
So, put this after your if check:
That's the fancy stuff that sets the actual string in the tile entity. Then, you can read it using very similar code:
Anyway, hope that helped.
(Welp. lots of textz)
But not yet
Thank you man! It works!
If somebody wathcing this so little thing that need to be fixed:
The bold row needs to be: nbt.setString("PlayerName", this.playerName);
What error do you get? How are you compiling?
But not yet
I am compiling with the gradlew build command
When I am clicking the block it saves the data but then when I logout it doesn't have it..
Remember to save and read the data in the tile-entity! (readFromNBT, and writeToNBT)
It saves the data but when I disconnect from the world and reconnect the data is no more!
1) Try creating a new world. When you change TileEntities around, worlds can get weird.
2) When are you reading the data?
But not yet
But not yet
BlockDevilStatue.java:
TileEntityDevilStatue.java :
in onBlockClicked(...), change this:
if(world.isRemote){
to this:
if(!world.isRemote){
But not yet
Please research what the word 'static' means in Java - it is the reason your data is not working correctly.
Just for you I removed the static and it didn't work..
Change:
if(tex.playerName == player.getCommandSenderName())
to
if(tex.playerName.equals(player.getCommandSenderName()))
Java doesn't compare strings with ==, it uses .equals()
But not yet
Just for me, eh? Lol. So, what about it 'didn't work' after you removed the static keyword? Did you also change it to run on the server, i.e. when the world is not remote, like the post above mine mentioned?
By the way, that's a pretty ambiguous and vague definition of static, and I certainly hope you read the Oracle documentation on it because the fact that you were using it in the way in which you were using it suggests you don't understand what it means, which is why I suggested you research it. But that's up to you.
One other thing I noticed, that probably isn't breaking your code but is still not necessary and is probably harmful, is that you use 'world.setTileEntity' with the tile entity that you just got and modified, but there is no reason to set the tile entity unless you are changing the type of tile entity that is at that location (which you should never do anyway).
Anyway, you should do some debugging on your own: put println in the read and write NBT methods of your TileEntity to see what the player's name is at those times; do the same in your Block class when interacting, etc. That is one of the most basic programming skills there is, and even advanced programmers use it all the time because it's so dang useful.
And why it writing to me:
XD