Posted April 11, 20241 yr I have problems whit mi blockEntities they just save data only when it feels like I just retake he topic after several weeks i know it not the menu nor the packages system was thinking something xtreame like make the block entities to read write the data as .nbt text files just coze i can but think don't worts the effort ################# mi question is if theres a way to espose and directly messup whit the minecraft nbt database system ?? like SELECT nbt FROM miwarudo WHERE x='127' and y='80' and z='-3627' or something whit CompoundTag worldnbt = warudo.getLevelData().something; ?? CompoundTag blockentitynbt = worldnbt.getDataAt(x,y,z) ??
April 15, 20241 yr I'm struggling to guess what on earth are you trying to achieve, or what do you want cause your post is a lil bit wonky, but the BlockEntity class has methods like SaveAdditional(CompoundTag) and load(CompoundTag) that should manage serialization and deserialization of your block entity NBT data for most cases and that you can override. If you mean reading NBT data of things "Inside" your BE, (in a slot) I'm pretty sure you can get an ItemStack out of any slot inside your BE from which to acess NBT data of the item in the slot. If you need the NBT data of a specific block entity you can call ServerLevel.getBlockEntity() Blocks don't have NBT data iirc. It would help to get an explanation on what is that your BE does and whats the current look of your BE class. Edited April 15, 20241 yr by chxr Typos
April 15, 20241 yr Author well The problem is the data in mi blockentity, its not being saved when i close the game i put items on it i retrive items from it all just seems good, the problem cames until i close minecraft then when i reload the word i have an older version of the items saved or just an empty briefcase normally when you declare an entity or a block entity or an item capability, forge automatically keeps track of changes and save the data in nbt format all of this by itself in this moments i have some items whit capabilities, those work right i have entities , those also works right but all of mi blockentities all of them are storages briefcase and all of them fails, save the data sometimes most of the time don't well i have only like 3 blockentities up now
April 16, 20241 yr I'm sure load and SaveAdditional are what you are looking for, probably. Mind sharing your BE class code? You also need to override onLoad method if you haven't Edited April 16, 20241 yr by chxr
April 17, 20241 yr Author hola thanks for answering i set some system outs to test and see whats going on @Override protected void saveAdditional( CompoundTag nbt ){ nbt.put("itemhandler", itemhandler.serializeNBT() ); nbt.putInt("progress", this.progress ); System.out.println("saveAdditional(nbt)"); System.out.println(NbtUtils.prettyPrint(nbt)); //<-- this is whats getting saved super.saveAdditional( nbt ); } @Override public void load( CompoundTag nbt ){ itemhandler.deserializeNBT( nbt.getCompound("itemhandler") ); this.progress = nbt.getInt("progress" ); System.out.println(NbtUtils.prettyPrint(nbt)); //<-- this is whats minecraft is giving back to the entity System.out.println("load(nbt)"); super.load( nbt ); } This dead adventurer body has two parts a block and a block Item both has their own item-handlers and their own menus all of that seems fine Testing remarks : *when i change some element inside the gui it triggers the saveAdditional(nbt) system out and shows a pretty print of the data being saved *when the world map loads it triggers the load(nbt) system out and shows a pretty print of the data minecraft is giving to this Block Entity For the testing i gonna set mi BlockEntityBodyBlock, save something in it, close minecraft, fireup the game again and check if the items remain ################ first try set the block entity (dead adventurer body like shaped) and left only a weath seed in the slot 10 the console says its all right Spoiler saveAdditional(nbt) { "itemhandler": { "Items" : list<TAG_Compound>[3] [ { "Count": 1b, "Slot" : 10, "id" : "minecraft:wheat_seeds" } ], "action" : 0b, "limit" : 100s, "start_time": 0L, "time" : 0s }, "progress" : 0 } close minecraft, launch it again i see the system out whit the data returned to the entity and its look good theres is only a weed seed Spoiler load(nbt) { "id" : "mercmod:blockentitymobblock", "itemhandler": { "Items" : list<TAG_Compound>[1] [ { "Count": 1b, "Slot" : 10, "id" : "minecraft:wheat_seeds" } ], "action" : 0b, "limit" : 100s, "start_time": 0L, "time" : 0s }, "keepPacked" : 0b, "progress" : 0, "x" : -40, "y" : 72, "z" : 38 } ################ Second try, now i gonna change the seed for two arrows the console says its all right the two arrows are being saved Spoiler saveAdditional(nbt) { "itemhandler": { "Items" : list<TAG_Compound>[3] [ { "Count": 1b, "Slot" : 9, "id" : "minecraft:arrow" }, { "Count": 1b, "Slot" : 11, "id" : "minecraft:arrow" } ], "action" : 0b, "limit" : 100s, "start_time": 0L, "time" : 0s }, "progress" : 0 } ######### Now close and run again bam Error minecraft returns the original data whit only a wheat seed the two arrows has been loss Spoiler load(nbt) { "id" : "mercmod:blockentitymobblock", "itemhandler": { "Items" : list<TAG_Compound>[1] [ { "Count": 1b, "Slot" : 10, "id" : "minecraft:wheat_seeds" } ], "action" : 0b, "limit" : 100s, "start_time": 0L, "time" : 0s }, ########## try again now i gonna put 3 wheat seeds Console system out says it gets it and is saving the data Spoiler saveAdditional(nbt) { "itemhandler": { "Items" : list<TAG_Compound>[3] [ { "Count": 1b, "Slot" : 9, "id" : "minecraft:wheat_seeds" }, { "Count": 1b, "Slot" : 10, "id" : "minecraft:wheat_seeds" }, { "Count": 1b, "Slot" : 11, "id" : "minecraft:wheat_seeds" } ], "action" : 0b, "limit" : 100s, "start_time": 0L, "time" : 0s }, "progress" : 0 } ############## but after close fire again Spoiler load(nbt) { "id" : "mercmod:blockentitymobblock", "itemhandler": { "Items" : list<TAG_Compound>[1] [ { "Count": 1b, "Slot" : 10, "id" : "minecraft:wheat_seeds" } ], "action" : 0b, "limit" : 100s, "start_time": 0L, "time" : 0s }, "keepPacked" : 0b, "progress" : 0, "x" : -40, "y" : 72, "z" : 38 } wheat seed, data losed once more time and it just throw the original ####################################################################################### sorry for the long post and the crappy video this is the reason why i say its saving the Block Entity data only when it feels like coze its saves data when it feels like ¿ its something wrong whit mi BlockEntity.saveAdditional() if i keep trying eventually it updates and the data chages i alredy try to level.removeBlockEntity(pos); level.setBlockEntity(pos, bebb); BlockEntityBodyBlock.class Spoiler package mercmod.blockentitys;//panel_blockentity import mercmod.capabity.be_handler; import mercmod.capabity.briefcase_be_handler; import mercmod.menus.MenuBodyBlock; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.NbtUtils; import net.minecraft.network.chat.Component; import net.minecraft.world.Containers; import net.minecraft.world.MenuProvider; import net.minecraft.world.SimpleContainer; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.inventory.ContainerData; import net.minecraft.world.item.Item; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.capabilities.ForgeCapabilities; import net.minecraftforge.common.util.LazyOptional; import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.ItemStackHandler; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; public class BlockEntityBodyBlock extends BlockEntity implements MenuProvider { //https://youtu.be/uV81DhuZ96w?t=687 protected final ContainerData data; private int progress = 0; private int maxprogress = 70; private static final int INPUT_SLOT = 0; private static final int OUTPUT_SLOT = 1; public BlockEntityBodyBlock(BlockPos pos, BlockState blkstate) { super(BlockEntityInit.BLOCKENTITYMOBBLOCK.get() , pos, blkstate); this.data = new ContainerData() { @Override public int get(int pindex) { return switch(pindex){ case 0 -> BlockEntityBodyBlock.this.progress; case 1 -> BlockEntityBodyBlock.this.maxprogress; default -> 0; }; } @Override public void set(int pindex, int pvalue) { switch(pindex) { case 0 -> BlockEntityBodyBlock.this.progress = pvalue; case 1 -> BlockEntityBodyBlock.this.maxprogress = pvalue; } } @Override public int getCount() { return 2; } }; } @Override public Component getDisplayName() { return Component.literal("Dead Body Block"); } @Nullable @Override public AbstractContainerMenu createMenu(int id, Inventory inventory, Player pe) { //System.out.println("#BlockEntityClass createMenu"); return new MenuBodyBlock(id, inventory,this, this.data); } private LazyOptional<IItemHandler> lazyitemhandler = LazyOptional.empty(); //private final ItemStackHandler itemhandler = new ItemStackHandler(14); private final be_handler itemhandler = new be_handler(this, 14); @Override public @NotNull <T> LazyOptional<T> getCapability(@NotNull Capability<T> cap, @Nullable Direction side){ if(cap == ForgeCapabilities.ITEM_HANDLER){ return lazyitemhandler.cast(); } return super.getCapability(cap, side); } @Override public void onLoad(){ super.onLoad(); lazyitemhandler = LazyOptional.of(() -> itemhandler); } @Override public void invalidateCaps(){ super.invalidateCaps(); lazyitemhandler.invalidate(); } public void drops(){ SimpleContainer inventory = new SimpleContainer( itemhandler.getSlots() ); for(int index = 0 ; index < itemhandler.getSlots() ; index ++){ inventory.setItem(index, itemhandler.getStackInSlot(index)); } Containers.dropContents(this.level, this.worldPosition, inventory); } @Override protected void saveAdditional( CompoundTag nbt ){ nbt.put("itemhandler", itemhandler.serializeNBT() ); nbt.putInt("progress", this.progress ); System.out.println("saveAdditional(nbt)"); System.out.println(NbtUtils.prettyPrint(nbt)); super.saveAdditional( nbt ); } @Override public void load( CompoundTag nbt ){ itemhandler.deserializeNBT( nbt.getCompound("itemhandler") ); this.progress = nbt.getInt("progress" ); System.out.println("load(nbt)"); System.out.println(NbtUtils.prettyPrint(nbt)); super.load( nbt ); } //@Override public void tick(Level pLevel, BlockPos pPos, BlockState pState) { } private boolean canInsertItemIntoOutputSlot(Item item) { return this.itemhandler.getStackInSlot(OUTPUT_SLOT).isEmpty() || this.itemhandler.getStackInSlot(OUTPUT_SLOT).is(item); } private boolean canInsertAmountIntoOutputSlot(int count) { return this.itemhandler.getStackInSlot(OUTPUT_SLOT).getCount() + count <= this.itemhandler.getStackInSlot(OUTPUT_SLOT).getMaxStackSize(); } } BlockEntityInit.class Spoiler package mercmod.blockentitys; import mercmod.blocks.BlockInit; import mercmod.mercmod; import net.minecraft.Util; import net.minecraft.resources.ResourceLocation; import net.minecraft.util.datafix.fixes.References; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraftforge.eventbus.api.IEventBus; import net.minecraftforge.registries.DeferredRegister; import net.minecraftforge.registries.ForgeRegistries; import net.minecraftforge.registries.RegistryObject; import java.util.function.BiConsumer; import com.mojang.datafixers.types.Type; public class BlockEntityInit { public static final DeferredRegister<BlockEntityType<?>> BLOCK_ENTITIES = DeferredRegister.create(ForgeRegistries.BLOCK_ENTITY_TYPES, mercmod.MOD_ID); public static final RegistryObject<BlockEntityType<Panel_BlockEntity>> PANEL_BLOCKENTITY = BLOCK_ENTITIES.register( "panel_blockentity", () -> BlockEntityType.Builder.of( Panel_BlockEntity::new, BlockInit.OAK_LADDER.get() ).build(null) ); public static final RegistryObject<BlockEntityType<BlockEntityBriefcase>> BLOCKENTITYBRIEFCASE = BLOCK_ENTITIES.register( "blockentitybriefcase", () -> BlockEntityType.Builder.of( BlockEntityBriefcase::new, BlockInit.BRIEFCASE.get() ).build(null) ); public static final RegistryObject<BlockEntityType<BlockEntityHardcase>> BLOCKENTITYHARDCASE = BLOCK_ENTITIES.register( "blockentityhardcase", () -> BlockEntityType.Builder.of( BlockEntityHardcase::new, BlockInit.HARDCASE.get() ).build( null) ); public static final RegistryObject<BlockEntityType<BlockEntityBodyBlock>> BLOCKENTITYMOBBLOCK = BLOCK_ENTITIES.register( "blockentitymobblock", () -> BlockEntityType.Builder.of( BlockEntityBodyBlock::new, BlockInit.DEAD_BODY.get() ).build( null ) ); public static void register(IEventBus eventBus) { BLOCK_ENTITIES.register(eventBus); } } body_blockitem.class Spoiler package mercmod.blockitems; import mercmod.blockentitys.BlockEntityBodyBlock; import mercmod.capabity.bi_c_provider; import mercmod.capabity.bi_handler; import mercmod.menus.MenuBodyBlockItem; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.NbtUtils; import net.minecraft.network.chat.Component; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.InteractionResultHolder; import net.minecraft.world.MenuProvider; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.item.BlockItem; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.context.BlockPlaceContext; import net.minecraft.world.item.context.UseOnContext; import net.minecraft.world.level.ClipContext; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.HitResult; import net.minecraft.world.phys.Vec3; import net.minecraftforge.common.capabilities.ForgeCapabilities; import net.minecraftforge.common.capabilities.ICapabilityProvider; import net.minecraftforge.common.extensions.IForgeServerPlayer; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; public class body_blockitem extends BlockItem implements MenuProvider { public static final String BLOCK_ENTITY_TAG = "BlockEntityTag"; public static final String BLOCK_STATE_TAG = "BlockStateTag"; /** @deprecated */ @Deprecated private final Block block; public body_blockitem(Block blk, Properties properties) { super(blk, properties); this.block = blk; } // ########## ########## ########## ########## @Override public @NotNull Component getDisplayName() { return Component.literal("Body as Item"); } // ########## ########## ########## ########## public int getContainerSize() { return 14; } // ########## ########## ########## ########## public static CompoundTag get_nbt(ItemStack container){ CompoundTag nbt = ( container.hasTag() )? container.getTag() : new CompoundTag() ; if(!nbt.contains("time")) { nbt.putLong("tick", 0L); } return nbt; } // ########## ########## ########## ########## public static boolean can_do_it(ItemStack container){ // System.out.print("can_do_it(" ); CompoundTag nbt = get_nbt(container); long millis = System.currentTimeMillis(); if( ( millis - nbt.getLong("time" ) ) > 1000 ){ //only once every second nbt.putLong("time", millis ); container.setTag(nbt); //System.out.println("true);" ); return true; } // System.out.println("false);" ); return false; } // ########## ########## ########## ########## @Nullable @Override public ICapabilityProvider initCapabilities(ItemStack container, @Nullable CompoundTag nbt) { return new bi_c_provider(container, 14); } // ########## ########## ########## ########## public static bi_handler get_itemhandler(ItemStack helditem) { //bi_handler bh = get_itemhandler(helditem); bi_handler bh = ((bi_handler) helditem.getCapability(ForgeCapabilities.ITEM_HANDLER) .orElseThrow(() -> new RuntimeException("O_O"))); return bh; } // ########## ########## ########## ########## @Nullable @Override public AbstractContainerMenu createMenu(int containerId, @NotNull Inventory inventory, @NotNull Player player) { return new MenuBodyBlockItem( containerId, inventory ); } // ########## ########## ########## ########## //override normal block set process @Override public InteractionResult useOn(UseOnContext p_40581_) { return InteractionResult.PASS; } // ########## ########## ########## ########## @Override public InteractionResultHolder<ItemStack> use(Level warudo, Player pe, InteractionHand hand) { //System.out.println("use()"); ItemStack helditem = pe.getItemInHand(hand); if(can_do_it(helditem)){ if( !warudo.isClientSide() ) { if (!pe.isCrouching()) { open_briefcase(warudo, pe, helditem);//<--- } if (pe.isCrouching()) { set_as_block(warudo, pe, hand, helditem);//<--- } } } return InteractionResultHolder.success(helditem); } // ########## ########## ########## ########## public void open_briefcase(Level warudo, Player pe, ItemStack helditem){ if (helditem.getCapability(ForgeCapabilities.ITEM_HANDLER).isPresent()) { bi_handler bh = get_itemhandler(helditem); IForgeServerPlayer ifpe = (IForgeServerPlayer) pe; ifpe.openMenu((MenuProvider) this, friendlyByteBuf -> friendlyByteBuf.writeItem(ItemStack.EMPTY)); } } // ########## ########## ########## ########## @Override public boolean onEntitySwing(ItemStack helditem, LivingEntity le) { Level warudo = le.level(); if(!warudo.isClientSide()){ CompoundTag nbt = get_nbt(helditem); System.out.println(NbtUtils.prettyPrint(nbt)); } return true; } // ########## ########## ########## ########## public BlockPlaceContext getContext(Level warudo, Player pe, float dist, InteractionHand hand, ItemStack helditem){ Vec3 vi = pe.getEyePosition(); Vec3 vo = pe.getLookAngle();//is a delta //float dist = 6.0F; Vec3 vh; vh = new Vec3( (vi.x + (vo.x * dist) ), (vi.y + (vo.y * dist) ), (vi.z + (vo.z * dist) ) ); BlockState clicked_blkstate; //if( !warudo.isClientSide() ) { HitResult hitresult = warudo.clip( new ClipContext(vi, vh, ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, pe)); if (hitresult.getType() == HitResult.Type.BLOCK) { BlockPlaceContext context = new BlockPlaceContext(pe, hand, helditem, (BlockHitResult) hitresult); return context; } } return null; } // ########## ########## ########## ########## public ItemStack set_as_block(Level warudo, Player pe, InteractionHand hand, ItemStack helditem){ if( !warudo.isClientSide() ) {// && can_do_it(helditem) BlockPlaceContext context = getContext(warudo, pe, 5.0F ,hand, helditem); BlockState blkstate = this.getBlock().getStateForPlacement(context);//ask the blockstate from the block BlockPos pos = context.getClickedPos(); BlockState clicked_blkstate = warudo.getBlockState(pos); if ( clicked_blkstate.canBeReplaced() ) { warudo.setBlock(pos, blkstate, 2); fill_blockentity_whit(warudo, pos, helditem); helditem.shrink(1); } } return helditem; } // ########## ########## ########## ########## //@Override public void fill_blockentity_whit(Level warudo, BlockPos pos, ItemStack container) { BlockState blkstate = this.getBlock().defaultBlockState(); BlockEntity blockentity = warudo.getBlockEntity(pos); container.getCapability(ForgeCapabilities.ITEM_HANDLER).ifPresent(handleritem -> { BlockEntityBodyBlock bebb = null; if(blockentity instanceof BlockEntityBodyBlock){ bebb = (BlockEntityBodyBlock)blockentity; } if(!(blockentity instanceof BlockEntityBodyBlock)){ warudo.removeBlockEntity(pos); bebb = new BlockEntityBodyBlock(pos, blkstate); warudo.setBlockEntity(bebb); } bebb.getCapability(ForgeCapabilities.ITEM_HANDLER).ifPresent(handlerblock -> { ItemStack cosa = null; for (int i = 0; i < handlerblock.getSlots(); ++i) { cosa = handleritem.getStackInSlot(i); handlerblock.insertItem(i, cosa, false); } }); }); } // ########## ########## ########## ########## // ########## ########## ########## ########## } Edited April 17, 20241 yr by perromercenary00 Gramar missmatch
April 17, 20241 yr WIthout entering on menu class and capability shenanigans, in the load method try calling the super.load(nbt) before doing anything else. It might not be it, but that's really the only difference i can see with the very basic be i have. If you have a repo i can make a clone of to take a quick look at the whole thing on I'll maybe help you out quicker
April 17, 20241 yr Author i has that anyway i test it at the beginning and the end of the function just to be sure @Override public void load( CompoundTag nbt ){ super.load( nbt ); Level warudo = this.getLevel(); itemhandler.deserializeNBT( nbt.getCompound("itemhandler") ); this.progress = nbt.getInt("progress" ); System.out.println("load(nbt)"); System.out.println(NbtUtils.prettyPrint(nbt)); //super.load( nbt ); } but it does the same looking at it a second time it seems like it only store the nbt data when the entity is created and set into the world then never update values
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.