Jump to content

[1.7.2] Persist TileEntity data when Block is broken


Shinaka

Recommended Posts

Hey guys. I've been trying to suss through most of this without asking any questions on the forums - but I've hit an issue I can't seem to find an answer to. I have a TileEntity that when placed, assigns the placing player as its owner (just a string on the tileentity that gets saved in the nbt). However, I want that data to persist if the player breaks the block (and thus its in their inventory) and later places it. Sort of like how the Tesseracts in TE remember their owner (and other settings), etc. Any ideas?

Link to comment
Share on other sites

You'll need to use the ItemStack's NBTTagCompound.

 

In your Block's getDrops method you should get the TileEntity. TileYours being your TileEntity

 

TileYours tile = (TileYours)world.getTileEntity(x, y, z)

You should probably also perform a check on the tile to ensure it is instanceof TileYours

Then you need to get the value from the tile. You need to create the getPlayerName method in your tile entity class and insert it into a new stack's nbttag

	@Override
public ArrayList<ItemStack> getDrops(World world, int x, int y, int z, int metadata, int fortune) {
	ArrayList<ItemStack> items = new ArrayList<ItemStack>();

	TileEntity t = world.getTileEntity(x, y, z);

	if (t instanceof TileYours) {
		TileYours tile = (TileYours)t;
		String name = tile.getPlayerName();

		ItemStack stack = new ItemStack(world.getBlock(x, y, z), 1, metadata);
		if (!stack.hasTagCompound()) {
			stack.setTagCompound(new NBTTagCompound());
		}
		stack.getTagCompound().setString("playerName", name);
		items.add(stack);
	}

	return items;

}

 

And in your onBlockPlaced you will need do the opposite and set the name in the tileentity

I'm Sparkst3r, that kid who makes Sphax textures.

Well hi there. :D

Link to comment
Share on other sites

Hmm. It seems as though the TileEntity has already been destroyed by the time getDrops is called. Any ideas?

 

You'll need to use the ItemStack's NBTTagCompound.

 

In your Block's getDrops method you should get the TileEntity. TileYours being your TileEntity

 

TileYours tile = (TileYours)world.getTileEntity(x, y, z)

You should probably also perform a check on the tile to ensure it is instanceof TileYours

Then you need to get the value from the tile. You need to create the getPlayerName method in your tile entity class and insert it into a new stack's nbttag

	@Override
public ArrayList<ItemStack> getDrops(World world, int x, int y, int z, int metadata, int fortune) {
	ArrayList<ItemStack> items = new ArrayList<ItemStack>();

	TileEntity t = world.getTileEntity(x, y, z);

	if (t instanceof TileYours) {
		TileYours tile = (TileYours)t;
		String name = tile.getPlayerName();

		ItemStack stack = new ItemStack(world.getBlock(x, y, z), 1, metadata);
		if (!stack.hasTagCompound()) {
			stack.setTagCompound(new NBTTagCompound());
		}
		stack.getTagCompound().setString("playerName", name);
		items.add(stack);
	}

	return items;

}

 

And in your onBlockPlaced you will need do the opposite and set the name in the tileentity

Link to comment
Share on other sites

Hmm, I was afraid of that. TE uses a tool to dismantle the blocks safely by purposely calling the methods to break the block and saving the tile data in the correct order. You'll have to look around for a method in your block that calls before the tile is deleted so long as you have access to the world and coordinates and able to return the stack to drop.

I'm Sparkst3r, that kid who makes Sphax textures.

Well hi there. :D

Link to comment
Share on other sites

Override the breakBlock() method and put your code in that.

if (user.hasKnowledgeOfJava) {

    if (user.question.hasCode) {

        return interpetHelpfulResponse(user.getQuestion());

    } else {

        return "Could you post your code please?";

    }

} else {

    return "Learn some freaking Java!";

}

Link to comment
Share on other sites

Yeah, I was just going to post the same thing.  The TileEntity is removed in the block's breakBlock() method.  So you just need to Override that in your custom block where you save the data somehow before the tile entity is removed.

 

Here's the vanilla method:

 

public void breakBlock(World p_149749_1_, int p_149749_2_, int p_149749_3_, int p_149749_4_, Block p_149749_5_, int p_149749_6_)

    {

        if (hasTileEntity(p_149749_6_) && !(this instanceof BlockContainer))

        {

            p_149749_1_.removeTileEntity(p_149749_2_, p_149749_3_, p_149749_4_);

        }

    }

 

 

Check out my tutorials here: http://jabelarminecraft.blogspot.com/

Link to comment
Share on other sites

Yeah, that'd work. But you'll also need to make sure the normal drop is disabled or you'll have 2 items dropping.

You'll also need to create an entityitem in the breakBlock method and spawn that in the world manually for your drop.

I'm Sparkst3r, that kid who makes Sphax textures.

Well hi there. :D

Link to comment
Share on other sites

Is there a good example to look at for spawning the entityItem?

 

Yeah, that'd work. But you'll also need to make sure the normal drop is disabled or you'll have 2 items dropping.

You'll also need to create an entityitem in the breakBlock method and spawn that in the world manually for your drop.

Link to comment
Share on other sites

If you look at the BlockContainer class, inside the breakBlock method, there is a removeTileEntity method. My guess is, you could pop your NBT-adding code into there. Of course, there is always events, but if you don't have to use them, then don't.

Link to comment
Share on other sites

I'll give you an alternative idea that assumes one bloke per player.

 

On the savenbt method in the tile, check for the owner to be online and save its nbt to the player.  Then you never need to mess with the rest.

Long time Bukkit & Forge Programmer

Happy to try and help

Link to comment
Share on other sites

  • 7 months later...

You'll need to use the ItemStack's NBTTagCompound.

 

In your Block's getDrops method you should get the TileEntity. TileYours being your TileEntity

 

TileYours tile = (TileYours)world.getTileEntity(x, y, z)

You should probably also perform a check on the tile to ensure it is instanceof TileYours

Then you need to get the value from the tile. You need to create the getPlayerName method in your tile entity class and insert it into a new stack's nbttag

	@Override
public ArrayList<ItemStack> getDrops(World world, int x, int y, int z, int metadata, int fortune) {
	ArrayList<ItemStack> items = new ArrayList<ItemStack>();

	TileEntity t = world.getTileEntity(x, y, z);

	if (t instanceof TileYours) {
		TileYours tile = (TileYours)t;
		String name = tile.getPlayerName();

		ItemStack stack = new ItemStack(world.getBlock(x, y, z), 1, metadata);
		if (!stack.hasTagCompound()) {
			stack.setTagCompound(new NBTTagCompound());
		}
		stack.getTagCompound().setString("playerName", name);
		items.add(stack);
	}

	return items;

}

 

And in your onBlockPlaced you will need do the opposite and set the name in the tileentity

 

I have the part that you put in breakBlock(), but what do you put in onBlockPlaced? You said "the opposite" and I don't quite get what the code for that would be.

glubglubglubglubglubglubglubglubglubglubglubglubglubglubglubglubglubglubglubglubglubglubglubglubglubglubglubglubglubglubglubglubglubglubglubglubglubglubglubglubglubglubglubglubglubglubglubglubglubglubglub.

Link to comment
Share on other sites

It is pretty much exactly the same as what I currently have.

 

This is the code that I have in the PotentialBlock class in the breakBlock() method.

 

@Override
public void breakBlock(World world, int x, int y, int z, Block block, int p_149749_6_)
{
	TilePotBlock t = (TilePotBlock)world.getTileEntity(x, y, z);
	ArrayList<ItemStack> items = new ArrayList<ItemStack>();
	if (t instanceof TilePotBlock) {
		TilePotBlock tile = (TilePotBlock)t;

		ItemStack stack = new ItemStack(world.getBlock(x, y, z), 1);
		if (!stack.hasTagCompound()) {
			stack.setTagCompound(new NBTTagCompound());
		}
		stack.getTagCompound().setBoolean("potBlockR", tile.red);
		stack.getTagCompound().setBoolean("potBlockG", tile.green);
		stack.getTagCompound().setBoolean("potBlockB", tile.blue);
		stack.getTagCompound().setBoolean("potBlockIR", tile.ir);


		items.add(stack);
		world.spawnEntityInWorld(new EntityItem(world, x, y, z, items.get(0)));
		world.setBlock(x, y, z, Blocks.air);

	}


}

It is deleting the information when I'm placing it back down.

glubglubglubglubglubglubglubglubglubglubglubglubglubglubglubglubglubglubglubglubglubglubglubglubglubglubglubglubglubglubglubglubglubglubglubglubglubglubglubglubglubglubglubglubglubglubglubglubglubglubglub.

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.

Announcements



  • Recently Browsing

    • No registered users viewing this page.
  • Posts

    • Hello everyone, I'm making this post to seek help for my modded block, It's a special block called FrozenBlock supposed to take the place of an old block, then after a set amount of ticks, it's supposed to revert its Block State, Entity, data... to the old block like this :  The problem I have is that the system breaks when handling multi blocks (I tried some fix but none of them worked) :  The bug I have identified is that the function "setOldBlockFields" in the item's "setFrozenBlock" function gets called once for the 1st block of multiblock getting frozen (as it should), but gets called a second time BEFORE creating the first FrozenBlock with the data of the 1st block, hence giving the same data to the two FrozenBlock :   Old Block Fields set BlockState : Block{minecraft:black_bed}[facing=east,occupied=false,part=head] BlockEntity : net.minecraft.world.level.block.entity.BedBlockEntity@73681674 BlockEntityData : id:"minecraft:bed",x:3,y:-60,z:-6} Old Block Fields set BlockState : Block{minecraft:black_bed}[facing=east,occupied=false,part=foot] BlockEntity : net.minecraft.world.level.block.entity.BedBlockEntity@6d1aa3da BlockEntityData : {id:"minecraft:bed",x:2,y:-60,z:-6} Frozen Block Entity set BlockState : Block{minecraft:black_bed}[facing=east,occupied=false,part=foot] BlockPos{x=3, y=-60, z=-6} BlockEntity : net.minecraft.world.level.block.entity.BedBlockEntity@6d1aa3da BlockEntityData : {id:"minecraft:bed",x:2,y:-60,z:-6} Frozen Block Entity set BlockState : Block{minecraft:black_bed}[facing=east,occupied=false,part=foot] BlockPos{x=2, y=-60, z=-6} BlockEntity : net.minecraft.world.level.block.entity.BedBlockEntity@6d1aa3da BlockEntityData : {id:"minecraft:bed",x:2,y:-60,z:-6} here is the code inside my custom "freeze" item :    @Override     public @NotNull InteractionResult useOn(@NotNull UseOnContext pContext) {         if (!pContext.getLevel().isClientSide() && pContext.getHand() == InteractionHand.MAIN_HAND) {             BlockPos blockPos = pContext.getClickedPos();             BlockPos secondBlockPos = getMultiblockPos(blockPos, pContext.getLevel().getBlockState(blockPos));             if (secondBlockPos != null) {                 createFrozenBlock(pContext, secondBlockPos);             }             createFrozenBlock(pContext, blockPos);             return InteractionResult.SUCCESS;         }         return super.useOn(pContext);     }     public static void createFrozenBlock(UseOnContext pContext, BlockPos blockPos) {         BlockState oldState = pContext.getLevel().getBlockState(blockPos);         BlockEntity oldBlockEntity = oldState.hasBlockEntity() ? pContext.getLevel().getBlockEntity(blockPos) : null;         CompoundTag oldBlockEntityData = oldState.hasBlockEntity() ? oldBlockEntity.serializeNBT() : null;         if (oldBlockEntity != null) {             pContext.getLevel().removeBlockEntity(blockPos);         }         BlockState FrozenBlock = setFrozenBlock(oldState, oldBlockEntity, oldBlockEntityData);         pContext.getLevel().setBlockAndUpdate(blockPos, FrozenBlock);     }     public static BlockState setFrozenBlock(BlockState blockState, @Nullable BlockEntity blockEntity, @Nullable CompoundTag blockEntityData) {         BlockState FrozenBlock = BlockRegister.FROZEN_BLOCK.get().defaultBlockState();         ((FrozenBlock) FrozenBlock.getBlock()).setOldBlockFields(blockState, blockEntity, blockEntityData);         return FrozenBlock;     }  
    • It is an issue with quark - update it to this build: https://www.curseforge.com/minecraft/mc-mods/quark/files/3642325
    • Remove Instant Massive Structures Mod from your server     Add new crash-reports with sites like https://paste.ee/  
    • Update your drivers: https://www.amd.com/en/support/graphics/amd-radeon-r9-series/amd-radeon-r9-200-series/amd-radeon-r9-280x
  • Topics

×
×
  • Create New...

Important Information

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