Shingle all the ways
- Copper roof blocks now have custom CT behaviour on the top faces. Assets pending
|
@ -58,6 +58,7 @@ import com.simibubi.create.content.decoration.CardboardBlock;
|
|||
import com.simibubi.create.content.decoration.CardboardBlockItem;
|
||||
import com.simibubi.create.content.decoration.MetalLadderBlock;
|
||||
import com.simibubi.create.content.decoration.MetalScaffoldingBlock;
|
||||
import com.simibubi.create.content.decoration.RoofBlockCTBehaviour;
|
||||
import com.simibubi.create.content.decoration.TrainTrapdoorBlock;
|
||||
import com.simibubi.create.content.decoration.TrapdoorCTBehaviour;
|
||||
import com.simibubi.create.content.decoration.bracket.BracketBlock;
|
||||
|
@ -2661,13 +2662,15 @@ public class AllBlocks {
|
|||
"copper_roof_top", CopperBlockSet.DEFAULT_VARIANTS, (c, p) -> {
|
||||
p.stonecutting(DataIngredient.tag(AllTags.forgeItemTag("ingots/copper")), RecipeCategory.BUILDING_BLOCKS,
|
||||
c::get, 2);
|
||||
});
|
||||
}, (ws, block) -> connectedTextures(() -> new RoofBlockCTBehaviour(AllSpriteShifts.COPPER_SHINGLES.get(ws)))
|
||||
.accept(block));
|
||||
|
||||
public static final CopperBlockSet COPPER_TILES =
|
||||
new CopperBlockSet(REGISTRATE, "copper_tiles", "copper_roof_top", CopperBlockSet.DEFAULT_VARIANTS, (c, p) -> {
|
||||
p.stonecutting(DataIngredient.tag(AllTags.forgeItemTag("ingots/copper")), RecipeCategory.BUILDING_BLOCKS,
|
||||
c::get, 2);
|
||||
});
|
||||
}, (ws, block) -> connectedTextures(() -> new RoofBlockCTBehaviour(AllSpriteShifts.COPPER_TILES.get(ws)))
|
||||
.accept(block));
|
||||
|
||||
// Load this class
|
||||
|
||||
|
|
|
@ -13,12 +13,16 @@ import com.simibubi.create.foundation.block.connected.CTType;
|
|||
import net.createmod.catnip.render.SpriteShiftEntry;
|
||||
import net.createmod.catnip.render.SpriteShifter;
|
||||
import net.createmod.catnip.utility.Couple;
|
||||
import net.createmod.catnip.utility.lang.Lang;
|
||||
import net.minecraft.world.item.DyeColor;
|
||||
import net.minecraft.world.level.block.WeatheringCopper.WeatherState;
|
||||
import net.minecraft.world.level.block.state.properties.WoodType;
|
||||
|
||||
public class AllSpriteShifts {
|
||||
|
||||
private static final Map<WoodType, CTSpriteShiftEntry> WOODEN_WINDOWS = new IdentityHashMap<>();
|
||||
public static final Map<WeatherState, CTSpriteShiftEntry> COPPER_SHINGLES = new EnumMap<>(WeatherState.class);
|
||||
public static final Map<WeatherState, CTSpriteShiftEntry> COPPER_TILES = new EnumMap<>(WeatherState.class);
|
||||
|
||||
public static final Map<DyeColor, SpriteShiftEntry> DYED_BELTS = new EnumMap<>(DyeColor.class),
|
||||
DYED_OFFSET_BELTS = new EnumMap<>(DyeColor.class), DYED_DIAGONAL_BELTS = new EnumMap<>(DyeColor.class);
|
||||
|
@ -107,6 +111,12 @@ public class AllSpriteShifts {
|
|||
DYED_OFFSET_BELTS.put(color, get("block/belt_offset", "block/belt/" + id + "_scroll"));
|
||||
DYED_DIAGONAL_BELTS.put(color, get("block/belt_diagonal", "block/belt/" + id + "_diagonal_scroll"));
|
||||
}
|
||||
|
||||
for (WeatherState state : WeatherState.values()) {
|
||||
String pref = "copper/" + (state == WeatherState.UNAFFECTED ? "" : Lang.asId(state.name()) + "_");
|
||||
COPPER_SHINGLES.put(state, getCT(AllCTTypes.ROOF, pref + "copper_roof_top", pref + "copper_shingles_top"));
|
||||
COPPER_TILES.put(state, getCT(AllCTTypes.ROOF, pref + "copper_roof_top", pref + "copper_tiles_top"));
|
||||
}
|
||||
}
|
||||
|
||||
private static Couple<CTSpriteShiftEntry> vault(String name) {
|
||||
|
@ -150,5 +160,5 @@ public class AllSpriteShifts {
|
|||
public static CTSpriteShiftEntry getWoodenWindow(WoodType woodType) {
|
||||
return WOODEN_WINDOWS.get(woodType);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,142 @@
|
|||
package com.simibubi.create.content.decoration;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import com.simibubi.create.foundation.block.connected.AllCTTypes;
|
||||
import com.simibubi.create.foundation.block.connected.CTSpriteShiftEntry;
|
||||
import com.simibubi.create.foundation.block.connected.CTType;
|
||||
import com.simibubi.create.foundation.block.connected.ConnectedTextureBehaviour;
|
||||
|
||||
import net.createmod.catnip.utility.Iterate;
|
||||
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.util.Mth;
|
||||
import net.minecraft.world.level.BlockAndTintGetter;
|
||||
import net.minecraft.world.level.block.SlabBlock;
|
||||
import net.minecraft.world.level.block.StairBlock;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.properties.Half;
|
||||
import net.minecraft.world.level.block.state.properties.SlabType;
|
||||
import net.minecraft.world.level.block.state.properties.StairsShape;
|
||||
|
||||
public class RoofBlockCTBehaviour extends ConnectedTextureBehaviour.Base {
|
||||
|
||||
private CTSpriteShiftEntry shift;
|
||||
|
||||
public RoofBlockCTBehaviour(CTSpriteShiftEntry shift) {
|
||||
this.shift = shift;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable CTSpriteShiftEntry getShift(BlockState state, Direction direction,
|
||||
@Nullable TextureAtlasSprite sprite) {
|
||||
if (direction == Direction.UP)
|
||||
return shift;
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean buildContextForOccludedDirections() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CTContext buildContext(BlockAndTintGetter reader, BlockPos pos, BlockState state, Direction face,
|
||||
ContextRequirement requirement) {
|
||||
|
||||
if (isUprightStair(state))
|
||||
return getStairMapping(state);
|
||||
|
||||
return super.buildContext(reader, pos, state, face, requirement);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean connectsTo(BlockState state, BlockState other, BlockAndTintGetter reader, BlockPos pos,
|
||||
BlockPos otherPos, Direction face, Direction primaryOffset, Direction secondaryOffset) {
|
||||
|
||||
if (connects(reader, pos, state, other)
|
||||
|| connectsHigh(reader, pos, state, other, reader.getBlockState(otherPos.above())))
|
||||
return true;
|
||||
if (primaryOffset != null && secondaryOffset != null)
|
||||
return false;
|
||||
|
||||
for (boolean p : Iterate.trueAndFalse) {
|
||||
Direction offset = p ? primaryOffset : secondaryOffset;
|
||||
if (offset == null)
|
||||
continue;
|
||||
if (offset.getAxis()
|
||||
.isVertical())
|
||||
continue;
|
||||
|
||||
if (connectsHigh(reader, pos, state, reader.getBlockState(pos.relative(offset.getClockWise())),
|
||||
reader.getBlockState(pos.relative(offset.getClockWise())
|
||||
.above()))
|
||||
|| connectsHigh(reader, pos, state, reader.getBlockState(pos.relative(offset.getCounterClockWise())),
|
||||
reader.getBlockState(pos.relative(offset.getCounterClockWise())
|
||||
.above())))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isUprightStair(BlockState state) {
|
||||
return state.hasProperty(StairBlock.SHAPE) && state.getOptionalValue(StairBlock.HALF)
|
||||
.orElse(Half.TOP) == Half.BOTTOM;
|
||||
}
|
||||
|
||||
public CTContext getStairMapping(BlockState state) {
|
||||
CTContext context = new CTContext();
|
||||
StairsShape shape = state.getValue(StairBlock.SHAPE);
|
||||
Direction facing = state.getValue(StairBlock.FACING);
|
||||
|
||||
if (shape == StairsShape.OUTER_LEFT)
|
||||
facing = facing.getCounterClockWise();
|
||||
if (shape == StairsShape.INNER_LEFT)
|
||||
facing = facing.getCounterClockWise();
|
||||
|
||||
int type = shape == StairsShape.STRAIGHT ? 0
|
||||
: (shape == StairsShape.INNER_LEFT || shape == StairsShape.INNER_RIGHT) ? 1 : 2;
|
||||
int rot = facing.get2DDataValue();
|
||||
context.up = type >= 2;
|
||||
context.right = type % 2 == 1;
|
||||
context.left = rot >= 2;
|
||||
context.down = rot % 2 == 1;
|
||||
return context;
|
||||
}
|
||||
|
||||
protected boolean connects(BlockAndTintGetter reader, BlockPos pos, BlockState state, BlockState other) {
|
||||
double top = state.getCollisionShape(reader, pos)
|
||||
.max(Axis.Y);
|
||||
double topOther = other.getCollisionShape(reader, pos)
|
||||
.max(Axis.Y);
|
||||
return Mth.equal(top, topOther);
|
||||
}
|
||||
|
||||
protected boolean connectsHigh(BlockAndTintGetter reader, BlockPos pos, BlockState state, BlockState other,
|
||||
BlockState aboveOther) {
|
||||
if (state.getBlock() instanceof SlabBlock && other.getBlock() instanceof SlabBlock)
|
||||
if (state.getValue(SlabBlock.TYPE) == SlabType.BOTTOM && other.getValue(SlabBlock.TYPE) != SlabType.BOTTOM)
|
||||
return true;
|
||||
|
||||
if (state.getBlock() instanceof SlabBlock && state.getValue(SlabBlock.TYPE) == SlabType.BOTTOM) {
|
||||
double top = state.getCollisionShape(reader, pos)
|
||||
.max(Axis.Y);
|
||||
double topOther = other.getCollisionShape(reader, pos)
|
||||
.max(Axis.Y);
|
||||
return !Mth.equal(top, topOther) && topOther > top;
|
||||
}
|
||||
|
||||
double topAboveOther = aboveOther.getCollisionShape(reader, pos)
|
||||
.max(Axis.Y);
|
||||
return topAboveOther > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable CTType getDataType(BlockAndTintGetter world, BlockPos pos, BlockState state, Direction direction) {
|
||||
return isUprightStair(state) ? AllCTTypes.ROOF_STAIR : AllCTTypes.ROOF;
|
||||
}
|
||||
|
||||
}
|
|
@ -63,26 +63,33 @@ public class CopperBlockSet {
|
|||
protected final Map<Variant<?>, BlockEntry<?>[]> entries = new HashMap<>();
|
||||
protected final NonNullBiConsumer<DataGenContext<Block, ?>, RegistrateRecipeProvider> mainBlockRecipe;
|
||||
protected final String endTextureName;
|
||||
protected final NonNullBiConsumer<WeatherState, Block> onRegister;
|
||||
|
||||
public CopperBlockSet(AbstractRegistrate<?> registrate, String name, String endTextureName, Variant<?>[] variants) {
|
||||
this(registrate, name, endTextureName, variants, NonNullBiConsumer.noop(), "copper/");
|
||||
this(registrate, name, endTextureName, variants, NonNullBiConsumer.noop(), "copper/", NonNullBiConsumer.noop());
|
||||
}
|
||||
|
||||
public CopperBlockSet(AbstractRegistrate<?> registrate, String name, String endTextureName, Variant<?>[] variants, String generalDirectory) {
|
||||
this(registrate, name, endTextureName, variants, NonNullBiConsumer.noop(), generalDirectory);
|
||||
this(registrate, name, endTextureName, variants, NonNullBiConsumer.noop(), generalDirectory, NonNullBiConsumer.noop());
|
||||
}
|
||||
|
||||
public CopperBlockSet(AbstractRegistrate<?> registrate, String name, String endTextureName, Variant<?>[] variants, NonNullBiConsumer<DataGenContext<Block, ?>, RegistrateRecipeProvider> mainBlockRecipe) {
|
||||
this(registrate, name, endTextureName, variants, mainBlockRecipe, "copper/");
|
||||
this(registrate, name, endTextureName, variants, mainBlockRecipe, "copper/", NonNullBiConsumer.noop());
|
||||
}
|
||||
|
||||
public CopperBlockSet(AbstractRegistrate<?> registrate, String name, String endTextureName, Variant<?>[] variants, NonNullBiConsumer<DataGenContext<Block, ?>, RegistrateRecipeProvider> mainBlockRecipe, NonNullBiConsumer<WeatherState, Block> onRegister) {
|
||||
this(registrate, name, endTextureName, variants, mainBlockRecipe, "copper/", onRegister);
|
||||
}
|
||||
|
||||
public CopperBlockSet(AbstractRegistrate<?> registrate, String name, String endTextureName, Variant<?>[] variants,
|
||||
NonNullBiConsumer<DataGenContext<Block, ?>, RegistrateRecipeProvider> mainBlockRecipe, String generalDirectory) {
|
||||
NonNullBiConsumer<DataGenContext<Block, ?>, RegistrateRecipeProvider> mainBlockRecipe, String generalDirectory, NonNullBiConsumer<WeatherState, Block> onRegister) {
|
||||
this.name = name;
|
||||
this.generalDirectory = generalDirectory;
|
||||
this.endTextureName = endTextureName;
|
||||
this.variants = variants;
|
||||
this.mainBlockRecipe = mainBlockRecipe;
|
||||
this.onRegister = onRegister;
|
||||
|
||||
for (boolean waxed : Iterate.falseAndTrue) {
|
||||
for (Variant<?> variant : this.variants) {
|
||||
BlockEntry<?>[] entries =
|
||||
|
@ -128,6 +135,7 @@ public class CopperBlockSet {
|
|||
.blockstate((ctx, prov) -> variant.generateBlockState(ctx, prov, this, state, waxed))
|
||||
.recipe((c, p) -> variant.generateRecipes(entries.get(BlockVariant.INSTANCE)[state.ordinal()], c, p))
|
||||
.transform(TagGen.pickaxeOnly())
|
||||
.onRegister(block -> onRegister.accept(state, block))
|
||||
.tag(BlockTags.NEEDS_STONE_TOOL)
|
||||
.simpleItem();
|
||||
|
||||
|
|
|
@ -89,6 +89,71 @@ public enum AllCTTypes implements CTType {
|
|||
return tileX + 8 * tileY;
|
||||
}
|
||||
},
|
||||
ROOF(4, ContextRequirement.builder().all().build()) {
|
||||
@Override
|
||||
public int getTextureIndex(CTContext context) {
|
||||
boolean upDrops = context.down && !context.up && (context.left || context.right);
|
||||
boolean downDrops = !context.down && context.up && (context.left || context.right);
|
||||
boolean leftDrops = !context.left && context.right && (context.up || context.down);
|
||||
boolean rightDrops = context.left && !context.right && (context.up || context.down);
|
||||
|
||||
if (upDrops) {
|
||||
if (leftDrops)
|
||||
return context.bottomRight ? 0 : 5;
|
||||
if (rightDrops)
|
||||
return context.bottomLeft ? 2 : 5;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (downDrops) {
|
||||
if (leftDrops)
|
||||
return context.topRight ? 8 : 5;
|
||||
if (rightDrops)
|
||||
return context.topLeft ? 10 : 5;
|
||||
return 9;
|
||||
}
|
||||
|
||||
if (leftDrops)
|
||||
return 4;
|
||||
if (rightDrops)
|
||||
return 6;
|
||||
|
||||
if (!context.up || !context.down || !context.left || !context.right)
|
||||
return 5;
|
||||
|
||||
if (context.bottomLeft && context.topRight) {
|
||||
if (context.topLeft && !context.bottomRight)
|
||||
return 12;
|
||||
if (context.bottomRight && !context.topLeft)
|
||||
return 15;
|
||||
if (!context.bottomRight && !context.topLeft)
|
||||
return 7;
|
||||
}
|
||||
|
||||
if (context.bottomRight && context.topLeft) {
|
||||
if (context.topRight && !context.bottomLeft)
|
||||
return 13;
|
||||
if (context.bottomLeft && !context.topRight)
|
||||
return 14;
|
||||
if (!context.bottomLeft && !context.topRight)
|
||||
return 11;
|
||||
}
|
||||
|
||||
return 5;
|
||||
}
|
||||
},
|
||||
ROOF_STAIR(4, ContextRequirement.builder()
|
||||
.axisAligned()
|
||||
.build()) {
|
||||
private static final int[][] MAPPING = { { 1, 6, 9, 4 }, { 14, 12, 13, 15 }, { 2, 10, 8, 0 }, { 5, 5, 5, 5 } };
|
||||
|
||||
@Override
|
||||
public int getTextureIndex(CTContext context) {
|
||||
int type = (context.up ? 2 : 0) + (context.right ? 1 : 0);
|
||||
int rot = (context.left ? 2 : 0) + (context.down ? 1 : 0);
|
||||
return MAPPING[type][rot];
|
||||
}
|
||||
},
|
||||
CROSS(4, ContextRequirement.builder().axisAligned().build()) {
|
||||
@Override
|
||||
public int getTextureIndex(CTContext context) {
|
||||
|
|
After Width: | Height: | Size: 1.8 KiB |
After Width: | Height: | Size: 1.8 KiB |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 1.9 KiB |