Jump to content

[1.19] How to Destroy a Multiblock?


Luckydel

Recommended Posts

I have a large workbench 1x3x3, and let's say I break one of the blocks, how can I make all the blocks break?
https://ibb.co/KXTHMHd

How do I set up a workbench and check the place for it:
 

Spoiler
//Відповідає за встановлення
    @Override
    public void setPlacedBy(Level level, BlockPos blockPos, BlockState blockState, LivingEntity p_52752_, ItemStack p_52753_) {
        super.setPlacedBy(level, blockPos, blockState, p_52752_, p_52753_);
        if (!level.isClientSide) {
            BlockPos downLeft = blockPos.relative(blockState.getValue(FACING).getClockWise());
            BlockPos downRight = blockPos.relative(blockState.getValue(FACING).getClockWise().getOpposite());
            BlockPos middleCenter = blockPos.above();
            BlockPos middleLeft = downLeft.above();
            BlockPos middleRight = downRight.above();
            BlockPos upCenter = middleCenter.above();
            BlockPos upLeft = middleLeft.above();
            BlockPos upRight = middleRight.above();
            level.setBlockAndUpdate(downLeft, blockState.setValue(PART, locksmitchPart.NONE));
            level.setBlockAndUpdate(downRight, blockState.setValue(PART, locksmitchPart.NONE));
            level.setBlockAndUpdate(middleCenter, blockState.setValue(PART, locksmitchPart.NONE));
            level.setBlockAndUpdate(middleLeft, blockState.setValue(PART, locksmitchPart.NONE));
            level.setBlockAndUpdate(middleRight, blockState.setValue(PART, locksmitchPart.NONE));
            level.setBlockAndUpdate(upCenter, blockState.setValue(PART, locksmitchPart.NONE));
            level.setBlockAndUpdate(upLeft, blockState.setValue(PART, locksmitchPart.NONE));
            level.setBlockAndUpdate(upRight, blockState.setValue(PART, locksmitchPart.NONE));
            blockState.updateNeighbourShapes(level,blockPos,3);
        }
    }

    //Відповідає за наявність місця, щоб встановити.
    @javax.annotation.Nullable
    public BlockState getStateForPlacement(BlockPlaceContext context) {
        BlockPos blockpos = context.getClickedPos();
        Level level = context.getLevel();
        BlockPos middleCenter = blockpos.above();
        BlockPos upCenter = middleCenter.above();
        BlockPos downLeft = blockpos.relative(context.getHorizontalDirection().getClockWise());
        BlockPos middleLeft = downLeft.above();
        BlockPos upLeft = middleLeft.above();
        BlockPos downRight = blockpos.relative(context.getHorizontalDirection().getClockWise().getOpposite());
        BlockPos middleRight = downRight.above();
        BlockPos upRight = middleRight.above();
        if (blockpos.getY() < level.getMaxBuildHeight() - 3 &&
                level.getBlockState(middleCenter).canBeReplaced()&&
                level.getBlockState(upCenter).canBeReplaced()&&
                level.getBlockState(downLeft).canBeReplaced()&&
                level.getBlockState(middleLeft).canBeReplaced()&&
                level.getBlockState(upLeft).canBeReplaced()&&
                level.getBlockState(downRight).canBeReplaced()&&
                level.getBlockState(middleRight).canBeReplaced()&&
                level.getBlockState(upRight).canBeReplaced()&&
                !level.getBlockState(blockpos.below()).canBeReplaced()&&
                !level.getBlockState(downLeft.below()).canBeReplaced()&&
                !level.getBlockState(downRight.below()).canBeReplaced())
        {
            return defaultBlockState().setValue(FACING, context.getHorizontalDirection().getClockWise().getClockWise());
        } else {
            return null;
        }

    }

 

I've looked at the Door and Bed classes, only paying attention to playerWillDestroy. Poke your finger as they delete 2 blocks at once 😃
------------------------------------------------------------------------------------------------------------------------------------------------
Upd. I thought to write the coordinates of other blocks in the memory of the "main block", but this is probably not the right solution.

Edited by Luckydel
Link to comment
Share on other sites

There are many different ways vanilla does this:

* Besides the Door and Bed you mentioned, there is the DoublePlant or you can look at how Fences work - there are likely others.

* BlockPattern is used by the CarvedPumpkinBlock to detect entity spawning from completed block patterns, e.g. golems - it removes all the blocks used to spawn the entity.

* The NetherPortalBlock uses a PortalInfo to detect if a portal is formed and still complete.

* BeaconBlockEntity does a check periodically in its tick().

 

What most of these have in common is they run a check in updateShape() when a neighbour notifies them about changes or onPlace() for the block itself.

This only works if you can add processing to all the blocks in the structure.

Otherwise you have to do like the beacon block does and scan to see if the structure is (still) complete periodically.

 

There are many mods that have multiblock structures you can look at for other approaches.

e.g. Here is Immersive Engineering using minecraft's structure blocks:

https://github.com/BluSunrize/ImmersiveEngineering/blob/1.19.2/src/main/java/blusunrize/immersiveengineering/common/blocks/multiblocks/IETemplateMultiblock.java

https://github.com/BluSunrize/ImmersiveEngineering/tree/1.19.2/src/main/resources/data/immersiveengineering/structures/multiblocks

 

Edited by warjort

Boilerplate:

If you don't post your logs/debug.log we can't help you. For curseforge you need to enable the forge debug.log in its minecraft settings. You should also post your crash report if you have one.

If there is no error in the log file and you don't have a crash report then post the launcher_log.txt from the minecraft folder. Again for curseforge this will be in your curseforge/minecraft/Install

Large files should be posted to a file sharing site like https://gist.github.com  You should also read the support forum sticky post.

Link to comment
Share on other sites

23 hours ago, warjort said:

Есть много разных способов, которыми ваниль делает это:

* Помимо упомянутых вами Door и Bed, есть DoublePlant или вы можете посмотреть, как работают Fences — вероятно, есть и другие.

* BlockPattern используется CarvedPumpkinBlock для обнаружения объектов, появляющихся из завершенных шаблонов блоков, например, големов - он удаляет все блоки, используемые для создания объектов.

* NetherPortalBlock использует PortalInfo, чтобы определить, сформирован ли портал и все еще ли он завершен.

* BeaconBlockEntity периодически выполняет проверку в своем tick().

 

Что общего у большинства из них, так это то, что они запускают проверку в updateShape(), когда сосед уведомляет их об изменениях, или onPlace() для самого блока.

Это работает только в том случае, если вы можете добавить обработку ко всем блокам в структуре.

В противном случае вы должны делать то же, что и блок маяка, и периодически сканировать, чтобы увидеть, завершена ли структура (все еще).

 

Есть много модов с многоблочной структурой, которые вы можете использовать для других подходов.

Например, вот Immersive Engineering с использованием структурных блоков Minecraft:

https://github.com/BluSunrize/ImmersiveEngineering/blob/1.19.2/src/main/java/blusunrize/immersiveengineering/common/blocks/multiblocks/IETemplateMultiblock.java

https://github.com/BluSunrize/ImmersiveEngineering/tree/1.19.2/src/main/resources/data/immersiveengineering/structures/multiblocks

 

Thanks, it didn't quite help me, but it got me on the right track.

Link to comment
Share on other sites

16 hours ago, blinky000 said:

on each block when destroyed  get the facing, postition  and  regName and use that info to destroy the other 2 blocks by position

What is regName ? Is it a Holder <block> ?
-----------------------------------------------------------------
A problem that I don't know how to solve. Let's say there are 2 workbenches (3x3x1), I need to make sure that if I break 1 workbench, 2 does not break.
I'm thinking of adding 3x3x1 to everyone, some kind of ID that I randomly generate at the setPlacedBy stage. Perhaps your regName will suit me, but I don’t quite understand what it is 😃

Edited by Luckydel
Link to comment
Share on other sites

regName (or registrationName) sounds like the old forge name for what Mojang call ResourceLocation?

Boilerplate:

If you don't post your logs/debug.log we can't help you. For curseforge you need to enable the forge debug.log in its minecraft settings. You should also post your crash report if you have one.

If there is no error in the log file and you don't have a crash report then post the launcher_log.txt from the minecraft folder. Again for curseforge this will be in your curseforge/minecraft/Install

Large files should be posted to a file sharing site like https://gist.github.com  You should also read the support forum sticky post.

Link to comment
Share on other sites

On 8/16/2023 at 10:08 PM, warjort said:

regName (or registrationName) sounds like the old forge name for what Mojang call ResourceLocation?

Does the block have a block identifier(or anything integer) in the world that will always be original?
Kind of like ВlockState.hashCode()

Edited by Luckydel
Link to comment
Share on other sites

On 8/15/2023 at 7:08 PM, Luckydel said:

I've looked at the Door and Bed classes

it's a simple problem, that's why solution is easy to miss.

you will have one main block (if you have a block entity, attach it to that one) and 4 secondary blocks (adjacent to the center one) and 4 tertiary blocks (in corners, adjacent to two secondary ones). you will have block properties (accessed via blockState.getValue) which need to be enough for you to locate the main block. for example if current block is secondary and its "facing" is south, main block is one to the north.

override canSurvive
if block is tertiary
  check two adjacent positions (according to blockState); if either is not secondary, return false.
if block is secondary
  get a position of main, get block, if it isn't primary return false.
if block is primary and was just placed
  return true
if block is primary
  get 4 adjacent postitions, return false if either isnt secondary block
return true.

that's basically it. you may keep canSurvive() it in one block class or split into two (or three if you must), but that method is the only thing that you need to break multiblocks.

you also need this one (identical in all of my multiblocks):
@Override
    public void neighborChanged(BlockState state, Level level, BlockPos rackPos, Block block, BlockPos wallPos, boolean something)
    {
        super.neighborChanged(state, level, rackPos, block, wallPos, something);
        if (!this.canSurvive(state, level, rackPos))
        {
            level.destroyBlock(rackPos, true);
        }
    }

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



×
×
  • Create New...

Important Information

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