I've added test comments to other tile entities and they work just fine, so it's not the output method. Is there some location where available tile entities is listed or where tile entities are enabled etc. that I'm overlooking? Surely this can't be the first time someone has tried to add a tile entity.
5 days later and I'm still at a loss as to what's going wrong here, it definitely seems like at minimum the tile entity isn't being saved into memory.
Is there a tutorial anywhere that deals with adding new tile entities? I find it hard to believe, given the number of BlockContainer blocks added in mods, that something like this hasn't been attempted before.
Hmm... try searching the project for the text "instanceof BlockContainer", then of whatever pops up, refactor it like you did before to care only if the new block isn't null. Let me know if anything pops up-- I don't think we left out anything trivial, but you never know I guess.
Well a quick search finds 6 instances of "instanceof BlockContainer" inside of Chunk.java, plus a few castings of things into it.
By commenting those out, I've managed to get the PlayerBlock entities saving and loading, with no immediately-apparent negative effects. Chests still work, signs still work, even doors are unaffected. I'm currently working in 1.1 so that's not 100% certainty for 1.2 but since there hasn't been any gigantic rewrite it should be okay.
So, if I have this right, I can retrieve the block entity using (block).getBlockEntity() and see if it's a player block by using instanceof TileEntityPlayerBlock.
I can then either continue using my current method or I can add an age variable to the entity and retrieve it, increment it by the tick delay of decay, and use that to determine the odds of a block decaying. If I get the watcher working, I can also use the tile entity to add and remove decaying blocks from a looping list.
The first is simply that whilst no errors are spat out when I check for the TileEntityPlayerBlock, it shuts my code down, nothing ever happens. I'm not sure if it's fiddling with the RNG or whatever, but for some reason having any of my code subject to the condition of that tile entity existing eliminates it from ever happening.
However, I can demonstrate very readily that the tile entity exists, by logging out and viewing the world in MCEdit I can see all the entities neatly. Which brings me to my second bug that I discovered whilst doing so:
The player block entities don't die.
Or at least, they don't die when their attached block does, just when the world is re-loaded. Until then, they hang around in state, which is a problem not only for memory concerns but also because if another block is placed in the now-empty space, it inherits the pre-existing entity. Signs are still fine but I can't seem to find where they kill off their entities or such in the code. I've tested this bug by having the player block entity print out the block ID of it's associated block after a certain (short) period of time after creation, and blocks placed in previously occupied spaces don't print out.
EDIT: Bug #1 seems to be that the entity isn't getting associated with a given block, adding "if(getBlockEntity() instanceof TileEntityPlayerBlock){ System.out.println("Player block found!"); }" to the updateTick code of Block.java returns nothing. This might also be the cause of bug #2.
EDIT the Sequel: Bug #2 has been resolved, I added the code from BlockContainer's onBlockAdded and onBlockRemoval code to the main Block.java and now the entities seem to be dying properly, but they're not being related to the blocks properly and my test code above still outputs nothing.
I haven't resolved the entity-referencing issue, but I've begun changing operations over to a watcher method using a list of 3D points that is updated predominantly by the player block entities, such that I won't have to reference the entity directly except to find out the age. If I get something working properly I'll post up the altered files so others in need of player-block functionality might benefit.
Hmm... "getBlockEntity() instanceof TileEntityPlayerBlock" will return false when it ain't an instance, but I'm wondering if it returns false on null or crashes... do you have Eclipse set up where you can debug it? If not, just check if getBlockEntity() is returning null with a println.
Oh wait-- is getBlockEntity() the method that creates a new block entity??? That would be a major problem, haha. It would be poorly named, as such, but you definitely should only use it once to actually create the tileentity, not grab it.
Hmm... "getBlockEntity() instanceof TileEntityPlayerBlock" will return false when it ain't an instance, but I'm wondering if it returns false on null or crashes... do you have Eclipse set up where you can debug it? If not, just check if getBlockEntity() is returning null with a println.
Oh wait-- is getBlockEntity() the method that creates a new block entity??? That would be a major problem, haha. It would be poorly named, as such, but you definitely should only use it once to actually create the tileentity, not grab it.
Okay, so after revising my code to get it functional in 1.2.5, I've just got a couple more things to work out here.
The first is that regardless of what I try, I can't seem to get the code to recognise Point3D (cannot find symbol), including if I write my own class for it in the nature_reclaims.java code. I'm having similar (if not identical) issues with my own DecayData class that I'm using to shift the decay information out of Block.java.
private int clock = 0;
//Decay clock, determines the frequency of decay sequences, also lag control
private static ArrayList<Point3D> positions = new ArrayList<Point3D>(); //PlayerBlock listing
// this function is called routinely from the onTickIngame() function
public void runDecay()
{
System.out.println("Attempting to run decay");
clock = 0;
Iterator<Point3D> itr = positions.iterator();
Point3D testPoint;
while(itr.hasNext()){
testpoint = itr.next()
System.out.println("Player block at point: "+testpoint.x()+", "+testpoint.y()+", "+testpoint.z()+" tested!");
}
}
public static void addBlock(int i, int j, int k){
positions.add(new Point3D(i,j,k));
System.out.println("Player block at point: "+i+", "+j+", "+k+" marked!");
}
public static void deleteBlock(int i, int j, int k){
positions.remove(new Point3D(i,j,k));
System.out.println("Player block at point: "+i+", "+j+", "+k+" unmarked!");
}
The second is interfacing with the TileEntityPlayerBlock, since getBlockEntity now returns either null (as it originally did) or a new tile entity (which has age 0, the value I'm trying to reference). I need a way to first retrieve the tile entity and second check its age value. I assume given the former that a getter function will do for that, so it's mostly the former I need to resolve.
//From TileEntityPlayerBlock.java
public class TileEntityPlayerBlock extends TileEntity
{
public float Age=0;
public TileEntityPlayerBlock()
{
}
/**
* Writes a tile entity to NBT.
*/
public void writeToNBT(NBTTagCompound par1NBTTagCompound)
{
nature_reclaims.addBlock(xCoord, yCoord, zCoord);
par1NBTTagCompound.setFloat("Age", Age);
super.writeToNBT(par1NBTTagCompound);
}
/**
* Reads a tile entity from NBT.
*/
public void readFromNBT(NBTTagCompound par1NBTTagCompound)
{
Age = par1NBTTagCompound.getFloat((new StringBuilder()).append("Age").toString());
nature_reclaims.deleteBlock(xCoord, yCoord, zCoord);
super.readFromNBT(par1NBTTagCompound);
}
}
//From Block.java, the getBlockEntity function (transplanted from Chunk.java)
public TileEntity getBlockEntity()
{
if( shouldMark && blockID != 0 ){
shouldMark = false;
return new TileEntityPlayerBlock();
}
return null;
};
I'm sure my unfamiliarity with Java is to blame here, however I'm having trouble finding an example of class creation/usage that disagrees with my implementation here.
Have tried to see if the blocks will save? I know they won't load, but that could be because they're not getting saved.
Is there a tutorial anywhere that deals with adding new tile entities? I find it hard to believe, given the number of BlockContainer blocks added in mods, that something like this hasn't been attempted before.
By commenting those out, I've managed to get the PlayerBlock entities saving and loading, with no immediately-apparent negative effects. Chests still work, signs still work, even doors are unaffected. I'm currently working in 1.1 so that's not 100% certainty for 1.2 but since there hasn't been any gigantic rewrite it should be okay.
I can then either continue using my current method or I can add an age variable to the entity and retrieve it, increment it by the tick delay of decay, and use that to determine the odds of a block decaying. If I get the watcher working, I can also use the tile entity to add and remove decaying blocks from a looping list.
The first is simply that whilst no errors are spat out when I check for the TileEntityPlayerBlock, it shuts my code down, nothing ever happens. I'm not sure if it's fiddling with the RNG or whatever, but for some reason having any of my code subject to the condition of that tile entity existing eliminates it from ever happening.
However, I can demonstrate very readily that the tile entity exists, by logging out and viewing the world in MCEdit I can see all the entities neatly. Which brings me to my second bug that I discovered whilst doing so:
The player block entities don't die.
Or at least, they don't die when their attached block does, just when the world is re-loaded. Until then, they hang around in state, which is a problem not only for memory concerns but also because if another block is placed in the now-empty space, it inherits the pre-existing entity. Signs are still fine but I can't seem to find where they kill off their entities or such in the code. I've tested this bug by having the player block entity print out the block ID of it's associated block after a certain (short) period of time after creation, and blocks placed in previously occupied spaces don't print out.
EDIT: Bug #1 seems to be that the entity isn't getting associated with a given block, adding "if(getBlockEntity() instanceof TileEntityPlayerBlock){ System.out.println("Player block found!"); }" to the updateTick code of Block.java returns nothing. This might also be the cause of bug #2.
EDIT the Sequel: Bug #2 has been resolved, I added the code from BlockContainer's onBlockAdded and onBlockRemoval code to the main Block.java and now the entities seem to be dying properly, but they're not being related to the blocks properly and my test code above still outputs nothing.
I haven't resolved the entity-referencing issue, but I've begun changing operations over to a watcher method using a list of 3D points that is updated predominantly by the player block entities, such that I won't have to reference the entity directly except to find out the age. If I get something working properly I'll post up the altered files so others in need of player-block functionality might benefit.
Oh wait-- is getBlockEntity() the method that creates a new block entity??? That would be a major problem, haha. It would be poorly named, as such, but you definitely should only use it once to actually create the tileentity, not grab it.
u need to ask the world object for the TileEntity
The first is that regardless of what I try, I can't seem to get the code to recognise Point3D (cannot find symbol), including if I write my own class for it in the nature_reclaims.java code. I'm having similar (if not identical) issues with my own DecayData class that I'm using to shift the decay information out of Block.java.
The second is interfacing with the TileEntityPlayerBlock, since getBlockEntity now returns either null (as it originally did) or a new tile entity (which has age 0, the value I'm trying to reference). I need a way to first retrieve the tile entity and second check its age value. I assume given the former that a getter function will do for that, so it's mostly the former I need to resolve.