Flandre923
998 words
5 minutes
沉浸工艺多方块03-多方块的破坏过程

03 多方块结构的破坏过程#

在之前我们有提到关于机器的方块的问题,我们大概说了机器的方块(不是构建的方块)是logic来规定,这部分的内容我们会在logic时候信详细的说,这里的机器的方块其实都是`MultiblockPartBlock`​的一个子类或者是`MultiblockPartBlock`​类。

所有的机器方块都使用了这个类,那么所有机器方块的破坏自然会关联在这个类,在block的方法中有这样的一个方法。

// BlockBehaviour
    @Deprecated
    public void onRemove(BlockState p_60515_, Level p_60516_, BlockPos p_60517_, BlockState p_60518_, boolean p_60519_) {
        if (p_60515_.hasBlockEntity() && (!p_60515_.is(p_60518_.getBlock()) || !p_60518_.hasBlockEntity())) {
            p_60516_.removeBlockEntity(p_60517_);
        }
    }

这个方法就是当方块被破坏时候会调用的方法。对于MultiblockPartBlock​自然是重写了这个方法,所以在你破坏机器方块的时候,会掉这个方法,这个方法就会去匹配对应的多方块建筑并替换会对应的机器的构建方块(不是机器方块),例如高卢方块会被替换会高炉砖。

//`MultiblockPartBlock`
	@Override
	public void onRemove(BlockState state, @Nonnull Level level, @Nonnull BlockPos pos, BlockState newState, boolean isMoving)
	{
		if(state.getBlock()!=newState.getBlock())
		{
			BlockEntity blockEntity = level.getBlockEntity(pos);
			if(blockEntity instanceof IMultiblockBE<?> multiblockBE)
			{
				// Remove the BE here before disassembling: The block is already gone, so setting the block state here
				// to a block providing a BE will produce strange results otherwise
				super.onRemove(state, level, pos, newState, isMoving);
				multiblockBE.getHelper().disassemble(); // 方块被移除破坏,通过方块实体掉落存储内容和替换回原有方块的逻辑
				return;
			}
		}
		super.onRemove(state, level, pos, newState, isMoving);
	}

这段代码的作用就是,调用父类的remove方法,并调用对应的多方块结构的破坏方法multiblockBE.getHelper().disassemble();​。其中首先获得了对应的位置的方块实体,然后调用helper的disassemble

// MultiblockBEHelperCommon 
// 对于Helper目前你可以理解为帮助实现方块实体的功能的帮手
// 对于Master方块有对应的masterHelper 对于 dummy 方块实体有 dummyHelper
// 这里的common是两个helper的父类,你可以理解共有的帮手。

	@Override
	public void disassemble()
	{
		if(beingDisassembled)//如果当前正在拆除,则直接返回,避免重复操作。
			return;
		this.masterHelperDuringDisassembly = getMasterHelperWithChunkloads();//方法获取主方块实体的辅助器,并确保相关区块已加载。
		if(masterHelperDuringDisassembly==null)//如果获取不到主辅助器,则表示主方块丢失,无法进行拆除,直接返回。
			// Master BE went missing, can't do anything
			return;
		//从主辅助器获取多方块结构的上下文 ctx。
		final IMultiblockContext<State> ctx = masterHelperDuringDisassembly.getContext();
		//用于处理多方块相关的世界操作。
		final IMultiblockLevel levelWrapper = ctx.getLevel();
		//计算当前方块在世界坐标系中的绝对位置
		final BlockPos absolutePos = levelWrapper.toAbsolute(getPositionInMB());
		//从 levelWrapper 获取原始的 Level 对象 levelRaw,用于直接操作世界。
		final Level levelRaw = levelWrapper.getRawLevel();
		//调用多方块结构的拆除方法 getMultiblock().disassemble().disassemble(),传入原始世界、绝对原点和多方块结构的朝向。
		//从世界中移除当前方块,但不掉落物品。
		getMultiblock().disassemble().disassemble(
				levelRaw, levelWrapper.getAbsoluteOrigin(), levelWrapper.getOrientation()
		);
		levelRaw.removeBlock(absolutePos, false);
	}

helper里面的disassemble​方法就是计算一些数据包含level,原点坐标,以及建筑的朝向等信息。之后就调用了多方块接口的

//IMultiblock
		void disassemble(Level world, BlockPos startPos, boolean mirrored, Direction clickDirectionAtCreation);
//TemplateMultiblock // IMultiblock的实现
	@Override
	public void disassemble(Level world, BlockPos origin, boolean mirrored, Direction clickDirectionAtCreation)
	{
		Mirror mirror = mirrored?Mirror.FRONT_BACK: Mirror.NONE;// 根据参数设置镜像模式
		Rotation rot = DirectionUtils.getRotationBetweenFacings(Direction.NORTH, clickDirectionAtCreation); // 计算旋转角度
		Preconditions.checkNotNull(rot);// 检查旋转角度是否为空,防止空指针异常
		for(StructureBlockInfo block : getStructure(world)) // 遍历结构体中的每个方块信息
		{
			BlockPos actualPos = withSettingsAndOffset(origin, block.pos(), mirror, rot);// 计算方块的实际位置
			prepareBlockForDisassembly(world, actualPos);// 将方块标记为正在拆除,
			world.setBlockAndUpdate(actualPos, applyToState(block.state(), mirror, rot));// 将方块放置回世界,应用镜像和旋转变换
		}
	}

在这里做的主要工作,根据镜像和rot旋转信息,和自己的nbt模板保存的构建方块数据StructureBlockInfo将对应的实际的位置替换为nbt模板建筑的方块。

到此为止就将机器方块替换为了原本的构建方块。

沉浸工艺多方块03-多方块的破坏过程
https://fuwari.vercel.app/posts/imm/03-多方块结构的破坏过程/
Author
Flandre923
Published at
2024-08-10