Connect-a-block

- Properly integrate both copycat blocks and the connected texture system with forge's built-in 'facade' api
This commit is contained in:
simibubi 2023-05-09 17:40:55 +02:00
parent f201e26f6b
commit 7b00608744
6 changed files with 179 additions and 126 deletions

View file

@ -48,6 +48,7 @@ import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.world.phys.shapes.VoxelShape;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.client.model.data.ModelDataManager;
public abstract class CopycatBlock extends Block implements IBE<CopycatBlockEntity>, IWrenchable {
@ -161,7 +162,7 @@ public abstract class CopycatBlock extends Block implements IBE<CopycatBlockEnti
@Nullable
public BlockState getAcceptedBlockState(Level pLevel, BlockPos pPos, ItemStack item, Direction face) {
if (!(item.getItem()instanceof BlockItem bi))
if (!(item.getItem() instanceof BlockItem bi))
return null;
Block block = bi.getBlock();
@ -244,24 +245,18 @@ public abstract class CopycatBlock extends Block implements IBE<CopycatBlockEnti
// Connected Textures
@Nullable
/**
* The wrapped blockstate at toPos. Wrapper guaranteed to be a block of this
* type <br>
* Return null if the 'from' state shouldn't connect to this block/face
*
* @param from
* @param reader
* @param targetPos
* @param face
* @return
*/
public abstract BlockState getConnectiveMaterial(BlockAndTintGetter reader, BlockState otherState, Direction face,
BlockPos fromPos, BlockPos toPos);
@Override
@OnlyIn(Dist.CLIENT)
public BlockState getAppearance(BlockState state, BlockAndTintGetter level, BlockPos pos, Direction side,
BlockState queryState, BlockPos queryPos) {
public boolean isUnblockableConnectivitySide(BlockAndTintGetter reader, BlockState state, Direction face,
BlockPos fromPos, BlockPos toPos) {
return false;
if (isIgnoredConnectivitySide(level, state, side, pos, queryPos))
return state;
ModelDataManager modelDataManager = level.getModelDataManager();
if (modelDataManager == null)
return getMaterial(level, pos);
return CopycatModel.getMaterial(modelDataManager.getAt(pos));
}
public boolean isIgnoredConnectivitySide(BlockAndTintGetter reader, BlockState state, Direction face,
@ -269,8 +264,13 @@ public abstract class CopycatBlock extends Block implements IBE<CopycatBlockEnti
return false;
}
public abstract boolean canConnectTexturesToward(BlockAndTintGetter reader, BlockPos fromPos, BlockPos toPos,
BlockState state);
//
public static BlockState getMaterial(BlockGetter reader, BlockPos targetPos) {
if (reader.getBlockEntity(targetPos)instanceof CopycatBlockEntity ufte)
if (reader.getBlockEntity(targetPos) instanceof CopycatBlockEntity ufte)
return ufte.getMaterial();
return Blocks.AIR.defaultBlockState();
}

View file

@ -44,13 +44,17 @@ public abstract class CopycatModel extends BakedModelWrapperWithData {
builder.with(MATERIAL_PROPERTY, material);
if (!(state.getBlock() instanceof CopycatBlock copycatBlock))
return builder;
OcclusionData occlusionData = new OcclusionData();
if (state.getBlock() instanceof CopycatBlock copycatBlock) {
gatherOcclusionData(world, pos, state, material, occlusionData, copycatBlock);
builder.with(OCCLUSION_PROPERTY, occlusionData);
}
ModelData wrappedData = getModelOf(material).getModelData(world, pos, material, ModelData.EMPTY);
ModelData wrappedData = getModelOf(material).getModelData(
new FilteredBlockAndTintGetter(world,
targetPos -> copycatBlock.canConnectTexturesToward(world, pos, targetPos, state)),
pos, material, ModelData.EMPTY);
return builder.with(WRAPPED_DATA_PROPERTY, wrappedData);
}

View file

@ -88,12 +88,6 @@ public class CopycatPanelBlock extends WaterloggedCopycatBlock {
return super.use(state, world, pos, player, hand, ray);
}
@Override
public boolean isUnblockableConnectivitySide(BlockAndTintGetter reader, BlockState state, Direction face,
BlockPos fromPos, BlockPos toPos) {
return true;
}
@Override
public boolean isIgnoredConnectivitySide(BlockAndTintGetter reader, BlockState state, Direction face,
BlockPos fromPos, BlockPos toPos) {
@ -112,6 +106,31 @@ public class CopycatPanelBlock extends WaterloggedCopycatBlock {
.getStep());
}
@Override
public boolean canConnectTexturesToward(BlockAndTintGetter reader, BlockPos fromPos, BlockPos toPos,
BlockState state) {
Direction facing = state.getValue(FACING);
BlockState toState = reader.getBlockState(toPos);
if (toPos.equals(fromPos.relative(facing)))
return false;
BlockPos diff = fromPos.subtract(toPos);
int coord = facing.getAxis()
.choose(diff.getX(), diff.getY(), diff.getZ());
if (!toState.is(this))
return coord != -facing.getAxisDirection()
.getStep();
if (isOccluded(state, toState, facing))
return true;
if (toState.setValue(WATERLOGGED, false) == state.setValue(WATERLOGGED, false) && coord == 0)
return true;
return false;
}
@Override
public boolean canFaceBeOccluded(BlockState state, Direction face) {
return state.getValue(FACING)
@ -123,28 +142,6 @@ public class CopycatPanelBlock extends WaterloggedCopycatBlock {
return canFaceBeOccluded(state, face.getOpposite());
}
@Override
public BlockState getConnectiveMaterial(BlockAndTintGetter reader, BlockState otherState, Direction face,
BlockPos fromPos, BlockPos toPos) {
BlockState panelState = reader.getBlockState(toPos);
Direction facing = panelState.getValue(FACING);
if (!otherState.is(this))
return facing == face.getOpposite() ? getMaterial(reader, toPos) : null;
if (isOccluded(panelState, otherState, facing))
return getMaterial(reader, toPos);
BlockPos diff = fromPos.subtract(toPos);
int coord = facing.getAxis()
.choose(diff.getX(), diff.getY(), diff.getZ());
if (otherState.setValue(WATERLOGGED, false) == panelState.setValue(WATERLOGGED, false) && coord == 0)
return getMaterial(reader, toPos);
return null;
}
@Override
public BlockState getStateForPlacement(BlockPlaceContext pContext) {
BlockState stateForPlacement = super.getStateForPlacement(pContext);

View file

@ -4,7 +4,6 @@ import java.util.function.Predicate;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllShapes;
import com.simibubi.create.foundation.utility.Iterate;
import com.simibubi.create.foundation.utility.VoxelShaper;
import com.simibubi.create.foundation.utility.placement.IPlacementHelper;
import com.simibubi.create.foundation.utility.placement.PlacementHelpers;
@ -64,54 +63,13 @@ public class CopycatStepBlock extends WaterloggedCopycatBlock {
return super.use(state, world, pos, player, hand, ray);
}
@Override
public BlockState getConnectiveMaterial(BlockAndTintGetter reader, BlockState otherState, Direction face,
BlockPos fromPos, BlockPos toPos) {
if (!otherState.is(this))
return null;
BlockState stepState = reader.getBlockState(toPos);
Direction facing = stepState.getValue(FACING);
BlockPos diff = fromPos.subtract(toPos);
if (diff.getY() != 0) {
if (isOccluded(stepState, otherState, diff.getY() > 0 ? Direction.UP : Direction.DOWN))
return getMaterial(reader, toPos);
return null;
}
if (isOccluded(stepState, otherState, facing))
return getMaterial(reader, toPos);
int coord = facing.getAxis()
.choose(diff.getX(), diff.getY(), diff.getZ());
if (otherState.setValue(WATERLOGGED, false) == stepState.setValue(WATERLOGGED, false) && coord == 0)
return getMaterial(reader, toPos);
return null;
}
@Override
public boolean isUnblockableConnectivitySide(BlockAndTintGetter reader, BlockState state, Direction face,
BlockPos fromPos, BlockPos toPos) {
return true;
}
@Override
public boolean isIgnoredConnectivitySide(BlockAndTintGetter reader, BlockState state, Direction face,
BlockPos fromPos, BlockPos toPos) {
BlockState toState = reader.getBlockState(toPos);
if (!toState.is(this)) {
if (!canFaceBeOccluded(state, face.getOpposite()))
if (!toState.is(this))
return true;
for (Direction d : Iterate.directions)
if (fromPos.relative(d)
.equals(toPos) && !canFaceBeOccluded(state, d))
return true;
return false;
}
Direction facing = state.getValue(FACING);
BlockPos diff = fromPos.subtract(toPos);
@ -128,6 +86,35 @@ public class CopycatStepBlock extends WaterloggedCopycatBlock {
.getStep());
}
@Override
public boolean canConnectTexturesToward(BlockAndTintGetter reader, BlockPos fromPos, BlockPos toPos,
BlockState state) {
Direction facing = state.getValue(FACING);
BlockState toState = reader.getBlockState(toPos);
BlockPos diff = fromPos.subtract(toPos);
if (fromPos.equals(toPos.relative(facing)))
return false;
if (!toState.is(this))
return false;
if (diff.getY() != 0) {
if (isOccluded(toState, state, diff.getY() > 0 ? Direction.UP : Direction.DOWN))
return true;
return false;
}
if (isOccluded(state, toState, facing))
return true;
int coord = facing.getAxis()
.choose(diff.getX(), diff.getY(), diff.getZ());
if (state.setValue(WATERLOGGED, false) == toState.setValue(WATERLOGGED, false) && coord == 0)
return true;
return false;
}
@Override
public boolean canFaceBeOccluded(BlockState state, Direction face) {
if (face.getAxis() == Axis.Y)

View file

@ -0,0 +1,74 @@
package com.simibubi.create.content.curiosities.frames;
import java.util.function.Predicate;
import org.jetbrains.annotations.Nullable;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.world.level.BlockAndTintGetter;
import net.minecraft.world.level.ColorResolver;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.lighting.LevelLightEngine;
import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.level.material.Fluids;
import net.minecraftforge.client.model.data.ModelDataManager;
public class FilteredBlockAndTintGetter implements BlockAndTintGetter {
private BlockAndTintGetter wrapped;
private Predicate<BlockPos> filter;
public FilteredBlockAndTintGetter(BlockAndTintGetter wrapped, Predicate<BlockPos> filter) {
this.wrapped = wrapped;
this.filter = filter;
}
@Override
public BlockEntity getBlockEntity(BlockPos pPos) {
return filter.test(pPos) ? wrapped.getBlockEntity(pPos) : null;
}
@Override
public BlockState getBlockState(BlockPos pPos) {
return filter.test(pPos) ? wrapped.getBlockState(pPos) : Blocks.AIR.defaultBlockState();
}
@Override
public FluidState getFluidState(BlockPos pPos) {
return filter.test(pPos) ? wrapped.getFluidState(pPos) : Fluids.EMPTY.defaultFluidState();
}
@Override
public int getHeight() {
return wrapped.getHeight();
}
@Override
public int getMinBuildHeight() {
return wrapped.getMinBuildHeight();
}
@Override
public float getShade(Direction pDirection, boolean pShade) {
return wrapped.getShade(pDirection, pShade);
}
@Override
public LevelLightEngine getLightEngine() {
return wrapped.getLightEngine();
}
@Override
public int getBlockTint(BlockPos pBlockPos, ColorResolver pColorResolver) {
return wrapped.getBlockTint(pBlockPos, pColorResolver);
}
@Override
public @Nullable ModelDataManager getModelDataManager() {
return wrapped.getModelDataManager();
}
}

View file

@ -3,14 +3,13 @@ package com.simibubi.create.foundation.block.connected;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import com.simibubi.create.content.curiosities.frames.CopycatBlock;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.Direction.Axis;
import net.minecraft.core.Direction.AxisDirection;
import net.minecraft.world.level.BlockAndTintGetter;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
public abstract class ConnectedTextureBehaviour {
@ -31,15 +30,16 @@ public abstract class ConnectedTextureBehaviour {
Direction face) {
BlockPos blockingPos = otherPos.relative(face);
BlockState blockState = reader.getBlockState(pos);
BlockState blockingState = reader.getBlockState(blockingPos);
if (blockState.getBlock() instanceof CopycatBlock ufb
&& ufb.isUnblockableConnectivitySide(reader, blockState, face, pos, otherPos))
if (!Block.isFaceFull(blockingState.getShape(reader, blockingPos), face.getOpposite()))
return false;
if (face.getAxis()
.choose(pos.getX(), pos.getY(), pos.getZ()) != face.getAxis()
.choose(otherPos.getX(), otherPos.getY(), otherPos.getZ()))
return false;
return face.getAxis()
.choose(pos.getX(), pos.getY(), pos.getZ()) == face.getAxis()
.choose(otherPos.getX(), otherPos.getY(), otherPos.getZ())
&& connectsTo(state,
return connectsTo(state,
getCTBlockState(reader, blockState, face.getOpposite(), pos.relative(face), blockingPos), reader, pos,
blockingPos, face);
}
@ -54,17 +54,14 @@ public abstract class ConnectedTextureBehaviour {
return !isBeingBlocked(state, reader, pos, otherPos, face) && state.getBlock() == other.getBlock();
}
private boolean testConnection(BlockAndTintGetter reader, BlockPos pos, BlockState state, Direction face,
final Direction horizontal, final Direction vertical, int sh, int sv) {
BlockPos p = pos.relative(horizontal, sh)
private boolean testConnection(BlockAndTintGetter reader, BlockPos currentPos, BlockState connectiveCurrentState,
Direction textureSide, final Direction horizontal, final Direction vertical, int sh, int sv) {
BlockState trueCurrentState = reader.getBlockState(currentPos);
BlockPos targetPos = currentPos.relative(horizontal, sh)
.relative(vertical, sv);
BlockState blockState = reader.getBlockState(pos);
if (blockState.getBlock() instanceof CopycatBlock ufb
&& ufb.isIgnoredConnectivitySide(reader, blockState, face, pos, p))
return false;
return connectsTo(state, getCTBlockState(reader, blockState, face, pos, p), reader, pos, p, face,
BlockState connectiveTargetState =
getCTBlockState(reader, trueCurrentState, textureSide, currentPos, targetPos);
return connectsTo(connectiveCurrentState, connectiveTargetState, reader, currentPos, targetPos, textureSide,
sh == 0 ? null : sh == -1 ? horizontal.getOpposite() : horizontal,
sv == 0 ? null : sv == -1 ? vertical.getOpposite() : vertical);
}
@ -72,13 +69,7 @@ public abstract class ConnectedTextureBehaviour {
public BlockState getCTBlockState(BlockAndTintGetter reader, BlockState reference, Direction face, BlockPos fromPos,
BlockPos toPos) {
BlockState blockState = reader.getBlockState(toPos);
if (blockState.getBlock() instanceof CopycatBlock ufb) {
BlockState connectiveMaterial = ufb.getConnectiveMaterial(reader, reference, face, fromPos, toPos);
return connectiveMaterial == null ? blockState : connectiveMaterial;
}
return blockState;
return blockState.getAppearance(reader, toPos, face, reference, fromPos);
}
protected boolean reverseUVs(BlockState state, Direction face) {