Jump to content

[1.11.2] Custom Furnace - Last Step, Saving Data Help [SOLVED]


Recommended Posts

Posted (edited)
Spoiler

 

I followed this Tutorail to make a custom furance to the tee and it works fine, https://youtu.be/UM43rSviBR4

 

Its a great tutorial, I had to make some minor changes because he was using a 1.11 and I am using 1.11.2 so most things were the same except some mappings which is fine. 

 

My issue is that my furance is not saving its inventory. So after the player logs out or the server restarts, what-have-you the furnace clears itself of everything. Now it appears that the information in the TileEntity class is getting written to the NBT properly because the one thing that stays when you log back in/restart server is the furance is still "burning" or at least it appears to be. The flames graphic is still showing and the furnace state is still set to burning so you see the burning version of the block. Perhaps something from 1.11 to 1.11.2 was changed or perhaps I overlooked something which is why I need some help. This is the last step to get my furance live. Here are the classes. If you need more let me know.

 

TileEntityClass - https://pastebin.com/UefnFpEj (Where I Personally Think the Problem Is)

outPutSlot - https://pastebin.com/UzKaMgSi

fuelSlot - https://pastebin.com/qtv0ugHP

container - https://pastebin.com/LdysHppC (Maybe it is in here?)

DualFuranceGUIHandler - https://pastebin.com/fnYrNXD0

DualFurnaceBlockClass - https://pastebin.com/uVgV7Cgz (Maybe I missed a function in here?)

 

Any help is apprecaited. Like I said this is the last step to get my furnace live so I really do appreciate any help, as always.

For those who'd prefer to look at it via github, here is the link: https://github.com/HalestormXV/mysticDivination/commit/db7c278932f47029c968b319f758482827bdf1e6

 

 

 

 

 

 

This issue is now the blockState, check the most recent posts to see what is going on. It is a matter of shifting meta values and I cannot figure it out properly.

Edited by HalestormXV
marked as solved
Posted (edited)

You never write currentBurnTime to the NBT.

 

You also never sync the data with the client.

 

Also, you should be using ItemStackHandler objects (and getCapability()) instead of the IInventory interface.

Edited by Draco18s

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

Posted (edited)

Okay so I took a look at the sync code and I have seen that exact code before although it had some added to it:

@Override
public SPacketUpdateTileEntity getUpdatePacket() {
	NBTTagCompound nbt = new NBTTagCompound();
	this.writeToNBT(nbt);
	int metadata = getBlockMetadata();
	return new SPacketUpdateTileEntity(this.pos, metadata, nbt);
}

@Override
public void onDataPacket(NetworkManager net, SPacketUpdateTileEntity pkt) {
	this.readFromNBT(pkt.getNbtCompound());
}

@Override
public NBTTagCompound getUpdateTag() {
	NBTTagCompound nbt = new NBTTagCompound();
	this.writeToNBT(nbt);
	return nbt;
}

@Override
public void handleUpdateTag(NBTTagCompound tag) {
	this.readFromNBT(tag);
}

@Override
public NBTTagCompound getTileData() {
	NBTTagCompound nbt = new NBTTagCompound();
	this.writeToNBT(nbt);
	return nbt;
}

 

I tried both the code you linked and the code above and the same issue is occuring. Inventory is clearing itself out. I know now that ItemStackHandler objects (and getCapability())  is what the new and correct standard is but is there a way I can solve this with the current setup? Then going forward utilize the correct standard? I would have no way to know how to convert my current setup to utilzie the above unless it is simply a matter of switching things out.

 

And I do appreciate you showing me the correct way becasue going forward I now know what to do, but hopefully there is a way to fix this with my current setup.

Edited by HalestormXV
Posted
9 minutes ago, HalestormXV said:

And I do appreciate you showing me the correct way becasue going forward I now know what to do, but hopefully there is a way to fix this with my current setup.

Use ItemStackHandlers. I don't know how ItemStackHelper.loadAllItems(compound, this.inventory) does its thing, you may be using it wrong.

  • Like 1

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

Posted
34 minutes ago, Draco18s said:

Use ItemStackHandlers. I don't know how ItemStackHelper.loadAllItems(compound, this.inventory) does its thing, you may be using it wrong.

I didn't need to. I managed to fix 90% of it. I mixed my functions up. I utilized loadAllItems in the write and loadAllItems again in the Read. I should have utilized ItemStackHelper.SaveAllItems in the write and ItemStackHelper.LoadAllItem in the read. 

 

The only issue I have left now is the furnace_on texture. The block is not saving the "burning" to true therefore when you log back in or restart the server, everything is still there and the burnTime is calculating and the smelting progress is saved but the block face is not "on"  becasue it doesnt realize it is still smelting. Any idea how to remedy that? Can you perhaps save a BlockState to the NBT so the game knows it is still "burning"? And if so how would one go about that?

Posted (edited)

You need to tell Minecraft that the status has changed.

https://github.com/Draco18s/ReasonableRealism/blob/master/src/main/java/com/draco18s/farming/entities/TileEntityTanner.java#L95-L98

Don't forget to override shouldRefresh (neccessary if you're dealing with metadata states at all)

https://github.com/Draco18s/ReasonableRealism/blob/master/src/main/java/com/draco18s/farming/entities/TileEntityTanner.java#L231-L233

Edited by Draco18s
  • Like 1

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

Posted

Okay that makes sense. So in other words if the block still has some burnTime left in it then we have to update the block to indicate as such. So where would that function be called?

At the end of the update() function?

 

Rather than have the this.markDirty() at the end of it I should have the equivalent of a sendUpdates() since that in and of itself does do a markDirty()?

 

Posted

Any time you change from "burning" to "not burning" or from "not burning" to "burning" you need to call those methods.

  • Like 1

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

Posted (edited)

Thats done in the blockClass of my furnace: (it already uses the 3 flag which I thought was the update)

    public static void setState(boolean active, World worldIn, BlockPos pos)
    {
        IBlockState state = worldIn.getBlockState(pos);
        TileEntity tileEntity = worldIn.getTileEntity(pos);
 
        if(active)
            worldIn.setBlockState(pos, eAngelusBlocks.dual_furnace.getDefaultState().withProperty(FACING, state.getValue(FACING)).withProperty(BURNING, true), 3);
        else
            worldIn.setBlockState(pos, eAngelusBlocks.dual_furnace.getDefaultState().withProperty(FACING, state.getValue(FACING)).withProperty(BURNING, false), 3);
 
        if(tileEntity != null)
        {
            tileEntity.validate();
            worldIn.setTileEntity(pos, tileEntity);
        }
    }

 

In the TileEntity it is done right here: (in the void update() near the end )

            if(flag != this.isBurning())
            {
                flag1 = true;
                DualFurance.setState(this.isBurning(), this.world, this.pos);
            }
        }
        if(flag1)
        this.markDirty();
    }

 

If I call the sendUpdates right below the DualFurance.setState(this.isBurning(), this.world, this.pos) it doesn't seem to do anything. Unless I have to call this in my blockClass since that is where the states are actually being switched and the TileEntity is just calling the method to do the switching?

Edited by HalestormXV
Posted (edited)

BUMP - i'm almost there, and I do recognize what you said Draco but the block is actually switching the state, the TileEnttiy is just calling the switch. Perhaps thats why putting the update in the TileEntity class isn't working because maybe once the block switches the state it needs to let minecraft know? Or maybe I'm just an idiot but like I said this is the first time dabbling in this with 1.11.2 at least so it is probably super easy and I am just missing it.

Edited by HalestormXV
Posted
12 hours ago, HalestormXV said:

BUMP - i'm almost there, and I do recognize what you said Draco but the block is actually switching the state, the TileEnttiy is just calling the switch. Perhaps thats why putting the update in the TileEntity class isn't working because maybe once the block switches the state it needs to let minecraft know? Or maybe I'm just an idiot but like I said this is the first time dabbling in this with 1.11.2 at least so it is probably super easy and I am just missing it.

Have you done this:

On 8/27/2017 at 7:26 PM, Draco18s said:

Don't forget to override shouldRefresh

 

  • Like 1

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

Posted
10 hours ago, Draco18s said:

Have you done this:

 

Yes and I know it returns a boolean so if we get a true, in other words the oldState of the block does not equal the new/current state of the block we return true. If we return true then we must sendUpdates correct? I've tried to do that and it doesn't work. Is it possible there is an error in the block class where the setState is actually found?

Posted
1 hour ago, HalestormXV said:

Yes and I know it returns a boolean so if we get a true, in other words the oldState of the block does not equal the new/current state of the block we return true. If we return true then we must sendUpdates correct? I've tried to do that and it doesn't work. Is it possible there is an error in the block class where the setState is actually found?

No, that is not what that is for. 

What that is for its when we should delete the tile entity and all of its data and create a new one. 

  • Like 2

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

Posted (edited)
23 hours ago, Draco18s said:

No, that is not what that is for. 

What that is for its when we should delete the tile entity and all of its data and create a new one. 

 

 

I'm at a loss. The methods are there the block stores data and saves the inventory but the graphic gets lost on a restart. I pretty much get what you are saying, I think. As the block is ticking away we have to see if it is actually "active." Once the game shuts down that "active" state gets discarded and when you restart it, even though everything is still functional the game doesn't know that the state should be set back to active which is why you have to tell it to re-set it to active. 

 

So in other words for the furnace entity I created, if the furance "isBurning" still when you log back into the game you need to tell the game that it "isBurning" so set the state correctly to update the graphic of the block or in this case since I am using varients in my .json select the correct .json. I know it is probably stupid simple to do since I am able to explain it just about right in plain english but I can't figure out where to place it in the code. I appologize.

 

TileEntity: https://pastebin.com/Wpp4EKHq

Block: https://pastebin.com/BXdDCJCx

Edited by HalestormXV
Posted

You need to save the BURNING property to the metadata in DualFurance#getMetaFromState and then load it from the metadata in DualFurance#getStateFromMeta.

 

You shouldn't be manually changing the TileEntity like you do in DualFurance.setState, just set the state to currentState.withProperty(BURNING, isBurning). Since you've overridden TileEntity#shouldRefresh to return true only when the Block changes, the TileEntity will automatically be preserved when the burning state changes.

 

Vanilla only does this because it uses separate Blocks for the two burning states instead of one Block with a boolean property.

  • Like 1

Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.

Posted (edited)
18 hours ago, Choonster said:

You need to save the BURNING property to the metadata in DualFurance#getMetaFromState and then load it from the metadata in DualFurance#getStateFromMeta.

 

You shouldn't be manually changing the TileEntity like you do in DualFurance.setState, just set the state to currentState.withProperty(BURNING, isBurning). Since you've overridden TileEntity#shouldRefresh to return true only when the Block changes, the TileEntity will automatically be preserved when the burning state changes.

 

Vanilla only does this because it uses separate Blocks for the two burning states instead of one Block with a boolean property.

 

Actually the way you explained it @Choonster makes perfect sense now and I thank you for that. And yes @Draco18s I understood what you were saying as well but I couldn't get it into code terms. So now my only remaining question is since the BURNING is a boolean value, how would I store that as meta data? could I simply create a custom method that if BURNING is true set the int to 1 or if it is false set the into to 2. Or does the true/false default to 0 and 1 respectively on its own as with pretty much any coding? Because I can't use state.getValue(BURNING) as it is in the #getMetaFromState

 

Or in the alternative should i change burning from a PropertyBool to a PropertyInteger

Edited by HalestormXV
Posted

You can combine bools and integers in metadata. You just need to bitwise your data together.

  • Like 1

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

Posted (edited)
2 hours ago, Draco18s said:

You can combine bools and integers in metadata. You just need to bitwise your data together.

Alright so how can I bitWise these values?

@Override
public int getMetaFromState(IBlockState state)
{
    int facingDirection = ((EnumFacing)state.getValue(FACING)).getIndex();
    int blockIsActive = state.getValue(BURNING) ? 1 : 0;
}

 

I know it can't be as simple as return blockIsActive & facingDirection. I haven't bitWised anything since 1.7.10 and coolAlias basically taught me it in the thread lol. So directions have 6 values right that go from  D-U-N-S-W-E meta data can be stored in bits of up to 16 right? So 0-5 are taken by the direction, that leave 6 --> 15. So the boolean for BURNING would have to be stored in value 6 ---> 15 somewhere right? So if I want to store it in 8, which is binary 1000 right? How would I combine the values of 0--->5 with 8? Would I have to shift? For this i really may need an example if at all possible. The last time I attempted to bitWise was in 1.7.10 and it sucked then also (even though it is very important to manipulate metadata) I know bitwising hasn't changed but I am sure a number of other things how to fetch data has so maybe an example of some code so I can actually see it in front of me?

 

@Override
public IBlockState getStateFromMeta(int meta)
{
    boolean blockIsActive = (meta & 1) > 0;  //This is where I lose it and just start randomly guessing things.

    EnumFacing facing = EnumFacing.getFront(meta);
    if(facing.getAxis() == EnumFacing.Axis.Y)
        facing = EnumFacing.NORTH;

    return this.getDefaultState().withProperty(FACING, facing).withProperty(BURNING, blockIsActive);
}

@Override
public int getMetaFromState(IBlockState state)
{
    int facingDirection = ((EnumFacing)state.getValue(FACING)).getIndex();
    int blockIsActive = state.getValue(BURNING) ? 1 : 0;
    int storedStates = facingDirection|blockIsActive; //Should it be stored this way? Would the 1 or the 0 overwrite the stored direction values?
    return storedStates;
}

Edited by HalestormXV
Posted

Facing is 0-6
Active is 0-1
You can't just add those together.

You need to offset one or the other to a free bit.

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

Posted
1 hour ago, Draco18s said:

Facing is 0-6
Active is 0-1
You can't just add those together.

You need to offset one or the other to a free bit.

Alright, Im pretty sure i shifted them correctly becasue now if they are active their face changes to the active face and if you log out and log back in the face still stays as the active one and the direction stays the same, so I am not overwriting any data. 

 

New issue creeped up though which I dont THINK has to do with the way I shifted/offset the data and extracted it. But I haven't done this in ages so I could be wrong.

 

Now once they stopped cooking the items the face doesn't change back to the non-burning face. It just stay as active, even if you log in and out. In other words once the block stops "burning" like a furance its graphic changes. This doesn't happen here. Here is how i offset the data and extracted it. https://pastebin.com/pQe7XN5H

 

Here is the full block class now: https://pastebin.com/XWTxfMgA

Here is the TileEntityClass: https://pastebin.com/MXCbPdzd

 

Perhaps it is in my TileEntity class now? I wil admit I haven't touched it since I started editing the blockClass around. So perhaps i am missing something in there.

DIAMOND_ORE
Posted

Burning: bx0010 (two values, shifted)

Facing: bx0011 (four values, unshifted)

 

Hmmm

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

Posted (edited)
19 minutes ago, Draco18s said:

Burning: bx0010 (two values, shifted)

Facing: bx0011 (four values, unshifted)

 

Hmmm

Okay, so I shifted wrong it would seem. Can you please show me in my code how I should shift it correctly so that it displays properly? I understand if you don't want to and that is fine, you have helped me tremendously and I made it this far with the assistance. Maybe as a reward for the good student lol. :P

 

 Also not shifting the facing values shouldn't be a problem right, and just letting them stay as their defaults. The only issue really is the burning or "blockIsActive" value.

Edited by HalestormXV
Posted

int blockIsActive = (state.getValue(BURNING) ? 1 : 0) << 2;

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

Posted (edited)
1 hour ago, Draco18s said:

int blockIsActive = (state.getValue(BURNING) ? 1 : 0) << 2;

Okay thank you, now I tried that and now blocks facing east, south, and west show the active texture when they are not active and if you look at them with F3 screen opened it says they are "burning" and the block facing north is the only one that is not showing its "burning" texture. The F3 screen shown as burning false,

 

So does this mean that the getStateFromMeta now needs to be fixed? And if so, I am imagining 

@Override
public IBlockState getStateFromMeta(int meta)
{
    boolean blockIsActive = (meta & 7) > 2;
    

    EnumFacing facing = EnumFacing.getFront(meta);
    if(facing.getAxis() == EnumFacing.Axis.Y)
        facing = EnumFacing.NORTH;

    return this.getDefaultState().withProperty(FACING, facing).withProperty(BURNING, blockIsActive);
}

https://pastebin.com/YSEDaJAM (if the colors are messed up above)

 

Is not the correct way to do it. Or at least does not have the correct value to get the boolean blockIsActive.

Edited by HalestormXV
Posted (edited)

Just giving this a BUMP as it is quite literally the last part that is preventing me from releasing the update of my Mod. I am parsing through and I have tried a variety of combinations but cant seem to get anything working. The issue doesn't have to do with the blockIsActive only being either a 1 or 0 does it? Becasue the positions are sticking properly. I'm imagining I am just "unpacking" the data incorrectly? I really am not trying to be annoying lol, I am just trying to figure this out and then learn from it so I can replicate it in the future on my own should I decide to make other blocks in which I may need to manipulate the Meta Data.

Edited by HalestormXV

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.

Announcements



×
×
  • Create New...

Important Information

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