Jump to content

Recommended Posts

Posted

Hello guys,

I'm trying to make a mod that adds auto miner block. To do this I created a block and a block entity that save the itemStack when a user right click on the block (the auo miner will generate item depending on the itemStack set), and I need to save this itemstack in order to keep it even after a game restart.

If I understood correctly, we need to use the "saveAdditional" function in order to save some tag on the entity. The thing is, how do you trigger this function everytime a user right click on the corresponding block entity ?  In my case this function is sometimes called when we right click on the block entity and sometimes it takes many seconds before the function is called.

Just below it's the saveAdditional fuction I'm using in a class that extends BlockEntity.

@Override
    protected void saveAdditional(CompoundTag pTag) {
        if (target != null) {
            System.out.println("target not null");
            pTag.put("target", target.serializeNBT());
        }
        super.saveAdditional(pTag);
    }

Thanks

Posted

Thanks @diesieben07 for your answer.

I noticed that when I apply a modification on the BlockEntity and immediately exit the game, the state of the blockEntity is not properly saved. It seems that it takes some seconds for the game to save it, but sometime it is immediately saved. Is there a way to avoid that ?

Posted

I have 2 classes : Miner (extends BaseEntityBlock) and MinerEntity (extends BlockEntity).

Miner

Spoiler
public class Miner extends BaseEntityBlock {

    private Block target;
    private Level level;
    private BlockPos pos;
    private Timer miningTimer;

    public Miner() {
        super(BlockBehaviour.Properties.of(Material.STONE).strength(5f));
    }

    @Override
    public void setPlacedBy(Level pLevel, BlockPos pPos, BlockState pState, @Nullable LivingEntity pPlacer, ItemStack pStack) {
        super.setPlacedBy(pLevel, pPos, pState, pPlacer, pStack);

        if (!pLevel.isClientSide()) {
            pPlacer.sendMessage(new TextComponent("Placed"), pPlacer.getUUID());
            level = pLevel;
            pos = pPos;
            miningTimer = new Timer();
        }
    }

    public void initialiseMining() {
        if (miningTimer != null) {
            miningTimer.cancel();
        }

        miningTimer = new Timer();
        miningLoop();
    }

    public void mine() {
        Block.dropResources(target.defaultBlockState(), level, pos.above());
    }

    public void miningLoop() {
        miningTimer.schedule(new TimerTask() {
            @Override
            public void run() {
                mine();
            }
        }, 0, 1000);
    }

    public void cancelMining() {
        miningTimer.cancel();
    }

    public Block getTarget() {
        return target;
    }

    public void setTarget(Block target) {
        this.target = target;
    }

    @Override
    public RenderShape getRenderShape(BlockState pState) {
        return RenderShape.MODEL;
    }

    @Override
    public void onRemove(BlockState pState, Level pLevel, BlockPos pPos, BlockState pNewState, boolean pIsMoving) {
        super.onRemove(pState, pLevel, pPos, pNewState, pIsMoving);
    }

    @Override
    public InteractionResult use(BlockState pState, Level pLevel, BlockPos pPos,
                                 Player pPlayer, InteractionHand pHand, BlockHitResult pHit) {
        if (!pLevel.isClientSide()) {
            BlockEntity entity = pLevel.getBlockEntity(pPos);
            if (entity instanceof MinerEntity miner) {
                if (!pPlayer.isCrouching()) {
                    ItemStack nextTarget = pPlayer.getItemInHand(pHand);
                    pPlayer.sendMessage(new TextComponent("Item in hand : " + nextTarget.getDisplayName().getString()), pPlayer.getUUID());
                    miner.setTarget(nextTarget);
                } else {
                    ItemStack currentTarget = miner.getTarget();
                    if (currentTarget != null) {
                        pPlayer.sendMessage(new TextComponent("Item set : " + currentTarget.getDisplayName().getString()), pPlayer.getUUID());
                    } else {
                        pPlayer.sendMessage(new TextComponent("No Item has been set"), pPlayer.getUUID());
                    }
                }
            }
        }

        return InteractionResult.sidedSuccess(pLevel.isClientSide());
    }

    @Nullable
    @Override
    public <T extends BlockEntity> BlockEntityTicker<T> getTicker(Level pLevel, BlockState pState, BlockEntityType<T> pBlockEntityType) {
        return (level0, pos, state0, blockEntity) -> ((MinerEntity) blockEntity).tick();
    }

    @Nullable
    @Override
    public BlockEntity newBlockEntity(BlockPos pPos, BlockState pState) {
        return new MinerEntity(pPos, pState);
    }
}

 

 

MinerEntity

Spoiler
public class MinerEntity extends BlockEntity {

    private ItemStack target;
    private boolean requiresUpdate;

    private final ItemStackHandler itemHandler = new ItemStackHandler(1) {
        @Override
        protected void onContentsChanged(int slot) {
            setChanged();
        }
    };

    private LazyOptional<IItemHandler> lazyItemHandler = LazyOptional.empty();

    public MinerEntity(BlockPos pWorldPosition, BlockState pBlockState) {
        super(BlockEntitiesManager.MINER_ENTITY.get(), pWorldPosition, pBlockState);
        this.requiresUpdate = false;
    }

    @NotNull
    @Override
    public <T> LazyOptional<T> getCapability(@NotNull Capability<T> cap, @Nullable Direction side) {
        if (cap == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) {
            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();
    }

    @Override
    protected void saveAdditional(CompoundTag pTag) {
        if (target != null) {
            System.out.println("target not null");
            pTag.put("target", target.serializeNBT());
        }
        super.saveAdditional(pTag);
    }

    @Override
    public void load(CompoundTag pTag) {
        super.load(pTag);
        itemHandler.deserializeNBT(pTag.getCompound("inventory"));
        if (!(pTag.getCompound("target").isEmpty())) {
            System.out.println("Load target is not empty " + pTag.getCompound("target"));
            target = ItemStack.of(pTag.getCompound("target"));
        }
    }

    @Override
    public void onDataPacket(Connection net, ClientboundBlockEntityDataPacket pkt) {
        load(pkt.getTag());
        super.onDataPacket(net, pkt);
    }

    @Override
    public void setRemoved() {
        super.setRemoved();
    }

    @Override
    public ClientboundBlockEntityDataPacket getUpdatePacket() {
        return ClientboundBlockEntityDataPacket.create(this);
    }

    @Override
    public CompoundTag getUpdateTag() {
        return serializeNBT();
    }

    @Override
    public void handleUpdateTag(CompoundTag tag) {
        load(tag);
        super.handleUpdateTag(tag);
    }

    public ItemStack getCurrentTarget() {
        return itemHandler.getStackInSlot(0);
    }

    public void update() {
        requestModelDataUpdate();
        setChanged();
        if (this.level != null) {
            this.level.setBlockAndUpdate(this.worldPosition, getBlockState());
        }
    }

    public void tick() {
        System.out.println("ticked, requiresUpdate = " + this.requiresUpdate);
        if(this.requiresUpdate) {
            update();
            this.requiresUpdate = false;
        }
    }

    public void drops() {
        SimpleContainer inventory = new SimpleContainer(itemHandler.getSlots());
        for (int i = 0; i < itemHandler.getSlots(); i++) {
            inventory.setItem(i, itemHandler.getStackInSlot(i));
        }

        Containers.dropContents(this.level, this.worldPosition, inventory);
    }

    public void setTarget(ItemStack target) {
        this.target = target;
        this.requiresUpdate = true;
    }

    public ItemStack getTarget() {
        return target;
    }
}

 

Everytime a user right click on Miner block, it calls MinerEntity#update. When debugging I noticed that when I call setChanged(), it takes many seconds to print "target not null" in the terminal.

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.