- Move code from CTSpriteShiftEntry subclasses into CTType enum fields
- Add ContextRequirement to specify which context directions should be
populated
- Rename CTType to AllCTTypes and add CTType interface and
CTTypeRegistry
- Add methods and fields to QuadHelper to simplify vertex data
manipulation
- Make no bracket mean null instead of air to prevent issues with
non-empty air models
- Remove unused palette classes
- Organize imports
This commit is contained in:
PepperCode1 2022-07-06 12:06:27 -07:00
parent 7443c95553
commit a52116bf0b
44 changed files with 656 additions and 657 deletions

View file

@ -1,16 +1,14 @@
package com.simibubi.create;
import static com.simibubi.create.foundation.block.connected.CTSpriteShifter.getCT;
import static com.simibubi.create.foundation.block.connected.CTSpriteShifter.CTType.HORIZONTAL;
import static com.simibubi.create.foundation.block.connected.CTSpriteShifter.CTType.OMNIDIRECTIONAL;
import static com.simibubi.create.foundation.block.connected.CTSpriteShifter.CTType.VERTICAL;
import java.util.Arrays;
import java.util.EnumMap;
import java.util.IdentityHashMap;
import java.util.Map;
import com.simibubi.create.foundation.block.connected.AllCTTypes;
import com.simibubi.create.foundation.block.connected.CTSpriteShiftEntry;
import com.simibubi.create.foundation.block.connected.CTSpriteShifter.CTType;
import com.simibubi.create.foundation.block.connected.CTSpriteShifter;
import com.simibubi.create.foundation.block.connected.CTType;
import com.simibubi.create.foundation.block.render.SpriteShiftEntry;
import com.simibubi.create.foundation.block.render.SpriteShifter;
import com.simibubi.create.foundation.utility.Couple;
@ -22,22 +20,22 @@ public class AllSpriteShifts {
private static final Map<WoodType, CTSpriteShiftEntry> WOODEN_WINDOWS = new IdentityHashMap<>();
public static final Map<DyeColor, SpriteShiftEntry> DYED_BELTS = new IdentityHashMap<>(),
DYED_OFFSET_BELTS = new IdentityHashMap<>(), DYED_DIAGONAL_BELTS = new IdentityHashMap<>();
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);
public static final SpriteShiftEntry BURNER_FLAME =
SpriteShifter.get("block/blaze_burner_flame", "block/blaze_burner_flame_scroll"),
get("block/blaze_burner_flame", "block/blaze_burner_flame_scroll"),
SUPER_BURNER_FLAME =
SpriteShifter.get("block/blaze_burner_flame", "block/blaze_burner_flame_superheated_scroll");
get("block/blaze_burner_flame", "block/blaze_burner_flame_superheated_scroll");
public static final CTSpriteShiftEntry FRAMED_GLASS =
getCT(OMNIDIRECTIONAL, "palettes/framed_glass", "palettes/framed_glass"),
getCT(AllCTTypes.OMNIDIRECTIONAL, "palettes/framed_glass", "palettes/framed_glass"),
HORIZONTAL_FRAMED_GLASS =
getCT(CTType.HORIZONTAL_KRYPPERS, "palettes/framed_glass", "palettes/horizontal_framed_glass"),
VERTICAL_FRAMED_GLASS = getCT(VERTICAL, "palettes/framed_glass", "palettes/vertical_framed_glass"),
getCT(AllCTTypes.HORIZONTAL_KRYPPERS, "palettes/framed_glass", "palettes/horizontal_framed_glass"),
VERTICAL_FRAMED_GLASS = getCT(AllCTTypes.VERTICAL, "palettes/framed_glass", "palettes/vertical_framed_glass"),
ORNATE_IRON_WINDOW = vertical("palettes/ornate_iron_window");
public static final CTSpriteShiftEntry CRAFTER_FRONT = getCT(CTType.OMNIDIRECTIONAL, "crafter_top", "brass_casing"),
public static final CTSpriteShiftEntry CRAFTER_FRONT = getCT(AllCTTypes.OMNIDIRECTIONAL, "crafter_top", "brass_casing"),
CRAFTER_SIDE = vertical("crafter_side"), CRAFTER_OTHERSIDE = horizontal("crafter_side"),
ANDESITE_ENCASED_COGWHEEL_SIDE = vertical("andesite_encased_cogwheel_side"),
ANDESITE_ENCASED_COGWHEEL_OTHERSIDE = horizontal("andesite_encased_cogwheel_side"),
@ -49,25 +47,25 @@ public class AllSpriteShifts {
BRASS_CASING = omni("brass_casing"), COPPER_CASING = omni("copper_casing"),
SHADOW_STEEL_CASING = omni("shadow_steel_casing"), REFINED_RADIANCE_CASING = omni("refined_radiance_casing"),
RAILWAY_CASING = omni("railway_casing"), RAILWAY_CASING_SIDE = omni("railway_casing_side"),
CREATIVE_CASING = getCT(CTType.CROSS, "creative_casing");
CREATIVE_CASING = getCT(AllCTTypes.CROSS, "creative_casing");
public static final CTSpriteShiftEntry CHASSIS_SIDE = omni("linear_chassis_side"),
SECONDARY_CHASSIS_SIDE = omni("secondary_linear_chassis_side"), CHASSIS = omni("linear_chassis_end"),
CHASSIS_STICKY = omni("linear_chassis_end_sticky");
public static final CTSpriteShiftEntry BRASS_TUNNEL_TOP = vertical("brass_tunnel_top"),
FLUID_TANK = getCT(CTType.RECTANGLE, "fluid_tank"), FLUID_TANK_TOP = getCT(CTType.RECTANGLE, "fluid_tank_top"),
FLUID_TANK_INNER = getCT(CTType.RECTANGLE, "fluid_tank_inner"),
CREATIVE_FLUID_TANK = getCT(CTType.CROSS, "creative_fluid_tank");
FLUID_TANK = getCT(AllCTTypes.RECTANGLE, "fluid_tank"), FLUID_TANK_TOP = getCT(AllCTTypes.RECTANGLE, "fluid_tank_top"),
FLUID_TANK_INNER = getCT(AllCTTypes.RECTANGLE, "fluid_tank_inner"),
CREATIVE_FLUID_TANK = getCT(AllCTTypes.CROSS, "creative_fluid_tank");
public static final Couple<CTSpriteShiftEntry> VAULT_TOP = vault("top"), VAULT_FRONT = vault("front"),
VAULT_SIDE = vault("side"), VAULT_BOTTOM = vault("bottom");
public static final SpriteShiftEntry BELT = SpriteShifter.get("block/belt", "block/belt_scroll"),
BELT_OFFSET = SpriteShifter.get("block/belt_offset", "block/belt_scroll"),
BELT_DIAGONAL = SpriteShifter.get("block/belt_diagonal", "block/belt_diagonal_scroll"),
ANDESIDE_BELT_CASING = SpriteShifter.get("block/brass_casing_belt", "block/andesite_casing_belt"),
CRAFTER_THINGIES = SpriteShifter.get("block/crafter_thingies", "block/crafter_thingies");
public static final SpriteShiftEntry BELT = get("block/belt", "block/belt_scroll"),
BELT_OFFSET = get("block/belt_offset", "block/belt_scroll"),
BELT_DIAGONAL = get("block/belt_diagonal", "block/belt_diagonal_scroll"),
ANDESIDE_BELT_CASING = get("block/brass_casing_belt", "block/andesite_casing_belt"),
CRAFTER_THINGIES = get("block/crafter_thingies", "block/crafter_thingies");
static {
populateMaps();
@ -81,30 +79,44 @@ public class AllSpriteShifts {
for (DyeColor color : DyeColor.values()) {
String id = color.getSerializedName();
DYED_BELTS.put(color, SpriteShifter.get("block/belt", "block/belt/" + id + "_scroll"));
DYED_OFFSET_BELTS.put(color, SpriteShifter.get("block/belt_offset", "block/belt/" + id + "_scroll"));
DYED_BELTS.put(color, get("block/belt", "block/belt/" + id + "_scroll"));
DYED_OFFSET_BELTS.put(color, get("block/belt_offset", "block/belt/" + id + "_scroll"));
DYED_DIAGONAL_BELTS.put(color,
SpriteShifter.get("block/belt_diagonal", "block/belt/" + id + "_diagonal_scroll"));
get("block/belt_diagonal", "block/belt/" + id + "_diagonal_scroll"));
}
}
private static Couple<CTSpriteShiftEntry> vault(String name) {
final String prefixed = "vault_" + name;
return Couple.createWithContext(b -> getCT(CTType.CROSS, prefixed, b ? prefixed : prefixed + "_large"));
return Couple.createWithContext(b -> getCT(AllCTTypes.CROSS, prefixed, b ? prefixed : prefixed + "_large"));
}
//
private static CTSpriteShiftEntry omni(String name) {
return getCT(OMNIDIRECTIONAL, name);
return getCT(AllCTTypes.OMNIDIRECTIONAL, name);
}
private static CTSpriteShiftEntry horizontal(String name) {
return getCT(HORIZONTAL, name);
return getCT(AllCTTypes.HORIZONTAL, name);
}
private static CTSpriteShiftEntry vertical(String name) {
return getCT(VERTICAL, name);
return getCT(AllCTTypes.VERTICAL, name);
}
//
private static SpriteShiftEntry get(String originalLocation, String targetLocation) {
return SpriteShifter.get(Create.asResource(originalLocation), Create.asResource(targetLocation));
}
private static CTSpriteShiftEntry getCT(CTType type, String blockTextureName, String connectedTextureName) {
return CTSpriteShifter.getCT(type, Create.asResource("block/" + blockTextureName), Create.asResource("block/" + connectedTextureName + "_connected"));
}
private static CTSpriteShiftEntry getCT(CTType type, String blockTextureName) {
return getCT(type, blockTextureName, blockTextureName);
}
//

View file

@ -2,11 +2,14 @@ package com.simibubi.create.content.contraptions.components.crafter;
import static com.simibubi.create.content.contraptions.base.HorizontalKineticBlock.HORIZONTAL_FACING;
import org.jetbrains.annotations.Nullable;
import com.simibubi.create.AllSpriteShifts;
import com.simibubi.create.content.contraptions.components.crafter.ConnectedInputHandler.ConnectedInput;
import com.simibubi.create.foundation.block.connected.CTSpriteShiftEntry;
import com.simibubi.create.foundation.block.connected.ConnectedTextureBehaviour;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.Direction.Axis;
@ -14,7 +17,7 @@ import net.minecraft.core.Direction.AxisDirection;
import net.minecraft.world.level.BlockAndTintGetter;
import net.minecraft.world.level.block.state.BlockState;
public class CrafterCTBehaviour extends ConnectedTextureBehaviour {
public class CrafterCTBehaviour extends ConnectedTextureBehaviour.Base {
@Override
public boolean connectsTo(BlockState state, BlockState other, BlockAndTintGetter reader, BlockPos pos, BlockPos otherPos,
@ -58,7 +61,7 @@ public class CrafterCTBehaviour extends ConnectedTextureBehaviour {
}
@Override
public CTSpriteShiftEntry get(BlockState state, Direction direction) {
public CTSpriteShiftEntry getShift(BlockState state, Direction direction, @Nullable TextureAtlasSprite sprite) {
Direction facing = state.getValue(HORIZONTAL_FACING);
boolean isFront = facing.getAxis() == direction.getAxis();
boolean isVertical = direction.getAxis()

View file

@ -1,8 +1,8 @@
package com.simibubi.create.content.contraptions.components.steam.whistle;
import static com.simibubi.create.AllSoundEvents.WHISTLE_MEDIUM;
import static com.simibubi.create.AllSoundEvents.WHISTLE_HIGH;
import static com.simibubi.create.AllSoundEvents.WHISTLE_LOW;
import static com.simibubi.create.AllSoundEvents.WHISTLE_MEDIUM;
import com.simibubi.create.content.contraptions.components.steam.whistle.WhistleBlock.WhistleSize;

View file

@ -1,10 +1,13 @@
package com.simibubi.create.content.contraptions.components.structureMovement.chassis;
import org.jetbrains.annotations.Nullable;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllSpriteShifts;
import com.simibubi.create.foundation.block.connected.CTSpriteShiftEntry;
import com.simibubi.create.foundation.block.connected.ConnectedTextureBehaviour;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.Direction.Axis;
@ -83,10 +86,10 @@ public class LinearChassisBlock extends AbstractChassisBlock {
return state1.getBlock() == state2.getBlock();
}
public static class ChassisCTBehaviour extends ConnectedTextureBehaviour {
public static class ChassisCTBehaviour extends ConnectedTextureBehaviour.Base {
@Override
public CTSpriteShiftEntry get(BlockState state, Direction direction) {
public CTSpriteShiftEntry getShift(BlockState state, Direction direction, @Nullable TextureAtlasSprite sprite) {
Block block = state.getBlock();
BooleanProperty glueableSide = ((LinearChassisBlock) block).getGlueableSide(state, direction);
if (glueableSide == null)

View file

@ -98,9 +98,11 @@ public class PipeAttachmentModel extends BakedModelWrapperWithData {
}
public void putBracket(BlockState state) {
this.bracket = Minecraft.getInstance()
.getBlockRenderer()
.getBlockModel(state);
if (state != null) {
this.bracket = Minecraft.getInstance()
.getBlockRenderer()
.getBlockModel(state);
}
}
public BakedModel getBracket() {

View file

@ -29,7 +29,6 @@ import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.RotatedPillarBlock;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.properties.BooleanProperty;
@ -138,9 +137,8 @@ public class AxisPipeBlock extends RotatedPillarBlock implements IWrenchableWith
BracketedTileEntityBehaviour behaviour = TileEntityBehaviour.get(world, pos, BracketedTileEntityBehaviour.TYPE);
if (behaviour == null)
return Optional.empty();
BlockState bracket = behaviour.getBracket();
behaviour.removeBracket(inOnReplacedContext);
if (bracket == Blocks.AIR.defaultBlockState())
BlockState bracket = behaviour.removeBracket(inOnReplacedContext);
if (bracket == null)
return Optional.empty();
return Optional.of(new ItemStack(bracket.getBlock()));
}

View file

@ -15,7 +15,6 @@ import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.context.UseOnContext;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.state.BlockState;
public class BracketBlockItem extends BlockItem {
@ -62,7 +61,7 @@ public class BracketBlockItem extends BlockItem {
if (player == null || !player.isCreative()) {
context.getItemInHand()
.shrink(1);
if (bracket != Blocks.AIR.defaultBlockState()) {
if (bracket != null) {
ItemStack returnedStack = new ItemStack(bracket.getBlock());
if (player == null)
Block.popResource(world, pos, returnedStack);

View file

@ -35,7 +35,6 @@ import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.PipeBlock;
import net.minecraft.world.level.block.SimpleWaterloggedBlock;
import net.minecraft.world.level.block.entity.BlockEntityType;
@ -312,9 +311,8 @@ public class FluidPipeBlock extends PipeBlock
BracketedTileEntityBehaviour.get(world, pos, BracketedTileEntityBehaviour.TYPE);
if (behaviour == null)
return Optional.empty();
BlockState bracket = behaviour.getBracket();
behaviour.removeBracket(inOnReplacedContext);
if (bracket == Blocks.AIR.defaultBlockState())
BlockState bracket = behaviour.removeBracket(inOnReplacedContext);
if (bracket == null)
return Optional.empty();
return Optional.of(new ItemStack(bracket.getBlock()));
}

View file

@ -1,5 +1,7 @@
package com.simibubi.create.content.contraptions.fluids.tank;
import org.jetbrains.annotations.Nullable;
import com.simibubi.create.api.connectivity.ConnectivityHandler;
import com.simibubi.create.foundation.block.connected.CTSpriteShiftEntry;
import com.simibubi.create.foundation.block.connected.HorizontalCTBehaviour;
@ -21,10 +23,10 @@ public class FluidTankCTBehaviour extends HorizontalCTBehaviour {
}
@Override
public CTSpriteShiftEntry get(BlockState state, Direction direction, TextureAtlasSprite sprite) {
if (direction.getAxis() == Axis.Y && innerShift.getOriginal() == sprite)
public CTSpriteShiftEntry getShift(BlockState state, Direction direction, @Nullable TextureAtlasSprite sprite) {
if (sprite != null && direction.getAxis() == Axis.Y && innerShift.getOriginal() == sprite)
return innerShift;
return super.get(state, direction, sprite);
return super.getShift(state, direction, sprite);
}
public boolean buildContextForOccludedDirections() {
@ -34,6 +36,6 @@ public class FluidTankCTBehaviour extends HorizontalCTBehaviour {
@Override
public boolean connectsTo(BlockState state, BlockState other, BlockAndTintGetter reader, BlockPos pos, BlockPos otherPos,
Direction face) {
return state.getBlock() == other.getBlock() && ConnectivityHandler.isConnected(reader, pos, otherPos); //FluidTankConnectivityHandler.isConnected(reader, pos, otherPos);
return state.getBlock() == other.getBlock() && ConnectivityHandler.isConnected(reader, pos, otherPos);
}
}

View file

@ -8,8 +8,6 @@ import java.util.List;
import javax.annotation.Nonnull;
import com.simibubi.create.foundation.utility.recipe.IRecipeTypeInfo;
import com.simibubi.create.AllRecipeTypes;
import com.simibubi.create.content.contraptions.processing.ProcessingRecipeBuilder.ProcessingRecipeParams;
import com.simibubi.create.content.contraptions.processing.burner.BlazeBurnerBlock.HeatLevel;
@ -19,6 +17,7 @@ import com.simibubi.create.foundation.tileEntity.behaviour.filtering.FilteringBe
import com.simibubi.create.foundation.tileEntity.behaviour.fluid.SmartFluidTankBehaviour;
import com.simibubi.create.foundation.tileEntity.behaviour.fluid.SmartFluidTankBehaviour.TankSegment;
import com.simibubi.create.foundation.utility.Iterate;
import com.simibubi.create.foundation.utility.recipe.IRecipeTypeInfo;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.crafting.Ingredient;

View file

@ -6,13 +6,10 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
import com.mojang.blaze3d.vertex.VertexFormat;
import com.simibubi.create.AllSpriteShifts;
import com.simibubi.create.content.contraptions.relays.belt.BeltTileEntity.CasingType;
import com.simibubi.create.foundation.block.render.QuadHelper;
import com.simibubi.create.foundation.block.render.SpriteShiftEntry;
import com.simibubi.create.foundation.render.SuperByteBuffer;
import net.minecraft.client.renderer.block.model.BakedQuad;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
@ -24,6 +21,8 @@ import net.minecraftforge.client.model.data.IModelData;
public class BeltModel extends BakedModelWrapper<BakedModel> {
private static final SpriteShiftEntry SPRITE_SHIFT = AllSpriteShifts.ANDESIDE_BELT_CASING;
public BeltModel(BakedModel template) {
super(template);
}
@ -36,37 +35,28 @@ public class BeltModel extends BakedModelWrapper<BakedModel> {
CasingType type = extraData.getData(CASING_PROPERTY);
if (type == CasingType.NONE || type == CasingType.BRASS)
return quads;
quads = new ArrayList<>(quads);
SpriteShiftEntry spriteShift = AllSpriteShifts.ANDESIDE_BELT_CASING;
VertexFormat format = DefaultVertexFormat.BLOCK;
quads = new ArrayList<>(quads);
for (int i = 0; i < quads.size(); i++) {
BakedQuad quad = quads.get(i);
if (spriteShift == null)
continue;
if (quad.getSprite() != spriteShift.getOriginal())
TextureAtlasSprite original = quad.getSprite();
if (original != SPRITE_SHIFT.getOriginal())
continue;
TextureAtlasSprite original = quad.getSprite();
TextureAtlasSprite target = spriteShift.getTarget();
BakedQuad newQuad = QuadHelper.clone(quad);
int[] vertexData = newQuad.getVertices();
for (int vertex = 0; vertex < vertexData.length; vertex += format.getIntegerSize()) {
int uvOffset = 16 / 4;
int uIndex = vertex + uvOffset;
int vIndex = vertex + uvOffset + 1;
float u = Float.intBitsToFloat(vertexData[uIndex]);
float v = Float.intBitsToFloat(vertexData[vIndex]);
vertexData[uIndex] =
Float.floatToRawIntBits(target.getU(SuperByteBuffer.getUnInterpolatedU(original, u)));
vertexData[vIndex] =
Float.floatToRawIntBits(target.getV(SuperByteBuffer.getUnInterpolatedV(original, v)));
for (int vertex = 0; vertex < 4; vertex++) {
float u = QuadHelper.getU(vertexData, vertex);
float v = QuadHelper.getV(vertexData, vertex);
QuadHelper.setU(vertexData, vertex, SPRITE_SHIFT.getTargetU(u));
QuadHelper.setV(vertexData, vertex, SPRITE_SHIFT.getTargetV(v));
}
quads.set(i, newQuad);
}
return quads;
}

View file

@ -14,7 +14,6 @@ import net.minecraft.world.item.context.UseOnContext;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.material.PushReaction;
@ -48,9 +47,8 @@ public abstract class AbstractSimpleShaftBlock extends AbstractShaftBlock implem
BracketedTileEntityBehaviour behaviour = TileEntityBehaviour.get(world, pos, BracketedTileEntityBehaviour.TYPE);
if (behaviour == null)
return Optional.empty();
BlockState bracket = behaviour.getBracket();
behaviour.removeBracket(inOnReplacedContext);
if (bracket == Blocks.AIR.defaultBlockState())
BlockState bracket = behaviour.removeBracket(inOnReplacedContext);
if (bracket == null)
return Optional.empty();
return Optional.of(new ItemStack(bracket.getBlock()));
}

View file

@ -55,18 +55,19 @@ public class BracketedKineticBlockModel extends BakedModelWrapper<BakedModel> {
}
private static class BracketedModelData {
BakedModel bracket;
private BakedModel bracket;
public void putBracket(BlockState state) {
this.bracket = Minecraft.getInstance()
.getBlockRenderer()
.getBlockModel(state);
if (state != null) {
this.bracket = Minecraft.getInstance()
.getBlockRenderer()
.getBlockModel(state);
}
}
public BakedModel getBracket() {
return bracket;
}
}
}

View file

@ -1,8 +1,9 @@
package com.simibubi.create.content.contraptions.relays.elementary;
import java.util.Optional;
import java.util.function.Predicate;
import org.jetbrains.annotations.Nullable;
import com.simibubi.create.content.contraptions.components.structureMovement.StructureTransform;
import com.simibubi.create.content.schematics.ItemRequirement;
import com.simibubi.create.foundation.tileEntity.SmartTileEntity;
@ -14,14 +15,13 @@ import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtUtils;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.state.BlockState;
public class BracketedTileEntityBehaviour extends TileEntityBehaviour {
public static final BehaviourType<BracketedTileEntityBehaviour> TYPE = new BehaviourType<>();
private Optional<BlockState> bracket;
private BlockState bracket;
private boolean reRender;
private Predicate<BlockState> pred;
@ -33,7 +33,6 @@ public class BracketedTileEntityBehaviour extends TileEntityBehaviour {
public BracketedTileEntityBehaviour(SmartTileEntity te, Predicate<BlockState> pred) {
super(te);
this.pred = pred;
bracket = Optional.empty();
}
@Override
@ -42,7 +41,7 @@ public class BracketedTileEntityBehaviour extends TileEntityBehaviour {
}
public void applyBracket(BlockState state) {
this.bracket = Optional.of(state);
this.bracket = state;
reRender = true;
tileEntity.notifyUpdate();
Level world = getWorld();
@ -54,35 +53,42 @@ public class BracketedTileEntityBehaviour extends TileEntityBehaviour {
public void transformBracket(StructureTransform transform) {
if (isBracketPresent()) {
BlockState bracket = getBracket();
BlockState transformedBracket = transform.apply(bracket);
applyBracket(transformedBracket);
}
}
public void removeBracket(boolean inOnReplacedContext) {
@Nullable
public BlockState removeBracket(boolean inOnReplacedContext) {
if (bracket == null) {
return null;
}
BlockState removed = this.bracket;
Level world = getWorld();
if (!world.isClientSide)
world.levelEvent(2001, getPos(), Block.getId(getBracket()));
this.bracket = Optional.empty();
world.levelEvent(2001, getPos(), Block.getId(bracket));
this.bracket = null;
reRender = true;
if (inOnReplacedContext) {
tileEntity.sendData();
return;
return removed;
}
tileEntity.notifyUpdate();
if (world.isClientSide)
return;
return removed;
tileEntity.getBlockState()
.updateNeighbourShapes(world, getPos(), 3);
return removed;
}
public boolean isBracketPresent() {
return bracket.isPresent();
return bracket != null;
}
@Nullable
public BlockState getBracket() {
return bracket.orElse(Blocks.AIR.defaultBlockState());
return bracket;
}
public boolean canHaveBracket() {
@ -91,7 +97,10 @@ public class BracketedTileEntityBehaviour extends TileEntityBehaviour {
@Override
public ItemRequirement getRequiredItems() {
return ItemRequirement.of(getBracket(), null);
if (!isBracketPresent()) {
return ItemRequirement.NONE;
}
return ItemRequirement.of(bracket, null);
}
@Override
@ -101,7 +110,9 @@ public class BracketedTileEntityBehaviour extends TileEntityBehaviour {
@Override
public void write(CompoundTag nbt, boolean clientPacket) {
bracket.ifPresent(p -> nbt.put("Bracket", NbtUtils.writeBlockState(p)));
if (isBracketPresent()) {
nbt.put("Bracket", NbtUtils.writeBlockState(bracket));
}
if (clientPacket && reRender) {
NBTHelper.putMarker(nbt, "Redraw");
reRender = false;
@ -111,9 +122,8 @@ public class BracketedTileEntityBehaviour extends TileEntityBehaviour {
@Override
public void read(CompoundTag nbt, boolean clientPacket) {
bracket = Optional.empty();
if (nbt.contains("Bracket"))
bracket = Optional.of(NbtUtils.readBlockState(nbt.getCompound("Bracket")));
bracket = NbtUtils.readBlockState(nbt.getCompound("Bracket"));
if (clientPacket && nbt.contains("Redraw"))
getWorld().sendBlockUpdated(getPos(), tileEntity.getBlockState(), tileEntity.getBlockState(), 16);
super.read(nbt, clientPacket);

View file

@ -1,15 +1,18 @@
package com.simibubi.create.content.contraptions.relays.encased;
import org.jetbrains.annotations.Nullable;
import com.simibubi.create.CreateClient;
import com.simibubi.create.foundation.block.connected.CTSpriteShiftEntry;
import com.simibubi.create.foundation.block.connected.ConnectedTextureBehaviour;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.world.level.BlockAndTintGetter;
import net.minecraft.world.level.block.state.BlockState;
public class EncasedCTBehaviour extends ConnectedTextureBehaviour {
public class EncasedCTBehaviour extends ConnectedTextureBehaviour.Base {
private CTSpriteShiftEntry shift;
@ -35,7 +38,7 @@ public class EncasedCTBehaviour extends ConnectedTextureBehaviour {
}
@Override
public CTSpriteShiftEntry get(BlockState state, Direction direction) {
public CTSpriteShiftEntry getShift(BlockState state, Direction direction, @Nullable TextureAtlasSprite sprite) {
return shift;
}

View file

@ -2,11 +2,14 @@ package com.simibubi.create.content.contraptions.relays.encased;
import static com.simibubi.create.content.contraptions.base.RotatedPillarKineticBlock.AXIS;
import org.jetbrains.annotations.Nullable;
import com.simibubi.create.content.contraptions.base.IRotate;
import com.simibubi.create.content.contraptions.relays.elementary.ICogWheel;
import com.simibubi.create.foundation.block.connected.CTSpriteShiftEntry;
import com.simibubi.create.foundation.utility.Couple;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.Direction.Axis;
@ -80,14 +83,14 @@ public class EncasedCogCTBehaviour extends EncasedCTBehaviour {
}
@Override
public CTSpriteShiftEntry get(BlockState state, Direction direction) {
public CTSpriteShiftEntry getShift(BlockState state, Direction direction, @Nullable TextureAtlasSprite sprite) {
Axis axis = state.getValue(AXIS);
if (large || axis == direction.getAxis()) {
if (axis == direction.getAxis() && state
.getValue(direction.getAxisDirection() == AxisDirection.POSITIVE ? EncasedCogwheelBlock.TOP_SHAFT
: EncasedCogwheelBlock.BOTTOM_SHAFT))
return null;
return super.get(state, direction);
return super.getShift(state, direction, sprite);
}
return sideShifts.get(axis == Axis.X || axis == Axis.Z && direction.getAxis() == Axis.X);
}

View file

@ -1,18 +1,21 @@
package com.simibubi.create.content.curiosities.deco;
import org.jetbrains.annotations.Nullable;
import com.simibubi.create.AllSpriteShifts;
import com.simibubi.create.foundation.block.connected.CTSpriteShiftEntry;
import com.simibubi.create.foundation.block.connected.ConnectedTextureBehaviour;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.world.level.BlockAndTintGetter;
import net.minecraft.world.level.block.state.BlockState;
public class TrapdoorCTBehaviour extends ConnectedTextureBehaviour {
public class TrapdoorCTBehaviour extends ConnectedTextureBehaviour.Base {
@Override
public CTSpriteShiftEntry get(BlockState state, Direction direction) {
public CTSpriteShiftEntry getShift(BlockState state, Direction direction, @Nullable TextureAtlasSprite sprite) {
return AllSpriteShifts.FRAMED_GLASS;
}

View file

@ -242,7 +242,7 @@ public class GirderBlock extends Block implements SimpleWaterloggedBlock, IWrenc
if (behaviour == null)
return false;
BlockState bracket = behaviour.getBracket();
if (!bracket.hasProperty(BracketBlock.FACING))
if (bracket == null || !bracket.hasProperty(BracketBlock.FACING))
return false;
return bracket.getValue(BracketBlock.FACING) == d;
}

View file

@ -1,19 +1,22 @@
package com.simibubi.create.content.curiosities.girder;
import org.jetbrains.annotations.Nullable;
import com.simibubi.create.AllSpriteShifts;
import com.simibubi.create.foundation.block.connected.CTSpriteShiftEntry;
import com.simibubi.create.foundation.block.connected.ConnectedTextureBehaviour;
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.world.level.BlockAndTintGetter;
import net.minecraft.world.level.block.state.BlockState;
public class GirderCTBehaviour extends ConnectedTextureBehaviour {
public class GirderCTBehaviour extends ConnectedTextureBehaviour.Base {
@Override
public CTSpriteShiftEntry get(BlockState state, Direction direction) {
public CTSpriteShiftEntry getShift(BlockState state, Direction direction, @Nullable TextureAtlasSprite sprite) {
if (!state.hasProperty(GirderBlock.X))
return null;
return !state.getValue(GirderBlock.X) && !state.getValue(GirderBlock.Z) && direction.getAxis() != Axis.Y

View file

@ -1,5 +1,7 @@
package com.simibubi.create.content.curiosities.weapons;
import static com.simibubi.create.content.curiosities.weapons.PotatoProjectileRenderMode.entityRandom;
import com.jozufozu.flywheel.util.transform.TransformStack;
import com.mojang.blaze3d.vertex.PoseStack;
import com.simibubi.create.foundation.utility.AngleHelper;

View file

@ -4,6 +4,7 @@ import com.simibubi.create.AllBlocks;
import com.simibubi.create.content.contraptions.relays.belt.BeltHelper;
import com.simibubi.create.content.contraptions.relays.belt.BeltTileEntity;
import com.simibubi.create.content.contraptions.relays.belt.BeltTileEntity.CasingType;
import net.minecraft.core.BlockPos;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.BlockItem;

View file

@ -1,19 +1,22 @@
package com.simibubi.create.content.logistics.block.belts.tunnel;
import org.jetbrains.annotations.Nullable;
import com.simibubi.create.AllSpriteShifts;
import com.simibubi.create.foundation.block.connected.CTSpriteShiftEntry;
import com.simibubi.create.foundation.block.connected.ConnectedTextureBehaviour;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.world.level.BlockAndTintGetter;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
public class BrassTunnelCTBehaviour extends ConnectedTextureBehaviour {
public class BrassTunnelCTBehaviour extends ConnectedTextureBehaviour.Base {
@Override
public CTSpriteShiftEntry get(BlockState state, Direction direction) {
public CTSpriteShiftEntry getShift(BlockState state, Direction direction, @Nullable TextureAtlasSprite sprite) {
return direction == Direction.UP ? AllSpriteShifts.BRASS_TUNNEL_TOP : null;
}
@ -33,24 +36,4 @@ public class BrassTunnelCTBehaviour extends ConnectedTextureBehaviour {
return tunnelTE.isConnected(leftSide);
}
@Override
public CTContext buildContext(BlockAndTintGetter reader, BlockPos pos, BlockState state, Direction face) {
return super.buildContext(reader, pos, state, face);
}
@Override
protected boolean reverseUVs(BlockState state, Direction face) {
return super.reverseUVs(state, face);
}
@Override
protected boolean reverseUVsHorizontally(BlockState state, Direction face) {
return super.reverseUVsHorizontally(state, face);
}
@Override
protected boolean reverseUVsVertically(BlockState state, Direction face) {
return super.reverseUVsVertically(state, face);
}
}

View file

@ -1,10 +1,13 @@
package com.simibubi.create.content.logistics.block.vault;
import org.jetbrains.annotations.Nullable;
import com.simibubi.create.AllSpriteShifts;
import com.simibubi.create.api.connectivity.ConnectivityHandler;
import com.simibubi.create.foundation.block.connected.CTSpriteShiftEntry;
import com.simibubi.create.foundation.block.connected.ConnectedTextureBehaviour;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.Direction.Axis;
@ -12,10 +15,10 @@ import net.minecraft.core.Direction.AxisDirection;
import net.minecraft.world.level.BlockAndTintGetter;
import net.minecraft.world.level.block.state.BlockState;
public class ItemVaultCTBehaviour extends ConnectedTextureBehaviour {
public class ItemVaultCTBehaviour extends ConnectedTextureBehaviour.Base {
@Override
public CTSpriteShiftEntry get(BlockState state, Direction direction) {
public CTSpriteShiftEntry getShift(BlockState state, Direction direction, @Nullable TextureAtlasSprite sprite) {
Axis vaultBlockAxis = ItemVaultBlock.getVaultBlockAxis(state);
boolean small = !ItemVaultBlock.isLarge(state);
if (vaultBlockAxis == null)

View file

@ -11,7 +11,7 @@ import com.simibubi.create.AllSpriteShifts;
import com.simibubi.create.Create;
import com.simibubi.create.content.AllSections;
import com.simibubi.create.foundation.block.connected.HorizontalCTBehaviour;
import com.simibubi.create.foundation.block.connected.StandardCTBehaviour;
import com.simibubi.create.foundation.block.connected.SimpleCTBehaviour;
import com.simibubi.create.foundation.data.BlockStateGen;
import com.simibubi.create.foundation.data.CreateRegistrate;
import com.simibubi.create.foundation.data.WindowGen;
@ -48,7 +48,7 @@ public class AllPaletteBlocks {
.register();
public static final BlockEntry<ConnectedGlassBlock> FRAMED_GLASS =
framedGlass("framed_glass", () -> new StandardCTBehaviour(AllSpriteShifts.FRAMED_GLASS)),
framedGlass("framed_glass", () -> new SimpleCTBehaviour(AllSpriteShifts.FRAMED_GLASS)),
HORIZONTAL_FRAMED_GLASS = framedGlass("horizontal_framed_glass",
() -> new HorizontalCTBehaviour(AllSpriteShifts.HORIZONTAL_FRAMED_GLASS, AllSpriteShifts.FRAMED_GLASS)),
VERTICAL_FRAMED_GLASS = framedGlass("vertical_framed_glass",

View file

@ -1,139 +0,0 @@
package com.simibubi.create.content.palettes;
import java.util.Map;
import com.simibubi.create.foundation.block.connected.CTSpriteShiftEntry;
import com.simibubi.create.foundation.block.connected.ConnectedTextureBehaviour;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.world.level.BlockAndTintGetter;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.properties.BooleanProperty;
public class ConnectedOreCTBehaviour extends ConnectedTextureBehaviour {
private CTSpriteShiftEntry entry;
public ConnectedOreCTBehaviour(CTSpriteShiftEntry entry) {
this.entry = entry;
}
@Override
public boolean connectsTo(BlockState state, BlockState other, BlockAndTintGetter reader, BlockPos pos,
BlockPos otherPos, Direction face, Direction primaryOffset, Direction secondaryOffset) {
if (state.getBlock() instanceof ConnectedSixwayBlock)
return true;
ConnectedSixwayBlock block = (ConnectedSixwayBlock) state.getBlock();
Map<Direction, BooleanProperty> props = ConnectedSixwayBlock.PROPERTY_BY_DIRECTION;
BooleanProperty faceProp = props.get(face);
// Diagonal Connection
if (secondaryOffset != null && primaryOffset != null) {
BooleanProperty primaryProp = props.get(primaryOffset);
BooleanProperty secondaryProp = props.get(secondaryOffset);
BooleanProperty primaryOppositeProp = props.get(primaryOffset.getOpposite());
BooleanProperty secondaryOppositeProp = props.get(secondaryOffset.getOpposite());
BooleanProperty faceOppositeProp = props.get(face.getOpposite());
BlockState adjAbove1 = reader.getBlockState(pos.relative(primaryOffset)
.relative(face));
BlockState adjAbove2 = reader.getBlockState(pos.relative(secondaryOffset)
.relative(face));
boolean adjAbove1Connects = block.connectsToState(adjAbove1);
boolean adjAbove2Connects = block.connectsToState(adjAbove2);
if (adjAbove1Connects && adjAbove2Connects)
return true;
if (isBeingBlocked(state, reader, pos, otherPos, face))
return false;
if (adjAbove1Connects && !(adjAbove1.getValue(secondaryProp)))
return false;
if (adjAbove2Connects && !(adjAbove2.getValue(primaryProp)))
return false;
BlockState diagAbove = reader.getBlockState(pos.relative(primaryOffset)
.relative(secondaryOffset)
.relative(face));
boolean diagAboveConnects = block.connectsToState(diagAbove);
if (diagAboveConnects
&& (!diagAbove.getValue(primaryOppositeProp) || !diagAbove.getValue(secondaryOppositeProp)))
return false;
BlockState diagSameY = reader.getBlockState(pos.relative(primaryOffset)
.relative(secondaryOffset));
boolean diagSameYConnects = block.connectsToState(diagSameY);
BlockState adj1 = reader.getBlockState(pos.relative(primaryOffset));
BlockState adj2 = reader.getBlockState(pos.relative(secondaryOffset));
boolean adj1Connects = block.connectsToState(adj1);
boolean adj2Connects = block.connectsToState(adj2);
boolean coveredDiag = diagAboveConnects || diagSameYConnects;
boolean covered1 = adj1Connects || adjAbove1Connects;
boolean covered2 = adj2Connects || adjAbove2Connects;
boolean fullCover = covered1 && covered2 && coveredDiag;
if (!fullCover && block.disconnectsFromState(diagSameY))
return false;
if (!fullCover && diagAboveConnects && !diagAbove.getValue(faceOppositeProp))
return false;
if (!(fullCover || diagSameYConnects) && adjAbove1Connects && !adjAbove1.getValue(faceOppositeProp))
return false;
if (!(fullCover || diagSameYConnects) && adjAbove2Connects && !adjAbove2.getValue(faceOppositeProp))
return false;
if (diagSameYConnects)
return diagSameY.getValue(faceProp) && (adjAbove1Connects || diagSameY.getValue(secondaryOppositeProp))
&& (adjAbove2Connects || diagSameY.getValue(primaryOppositeProp));
if (!fullCover && adj1Connects && !adj1.getValue(secondaryProp))
return false;
if (!fullCover && adj2Connects && !adj2.getValue(primaryProp))
return false;
if (!fullCover && !state.getValue(primaryProp))
return false;
if (!fullCover && !state.getValue(secondaryProp))
return false;
return true;
}
// Orthogonal Connection
else if (secondaryOffset != null || primaryOffset != null) {
if (isBeingBlocked(state, reader, pos, otherPos, face))
return false;
Direction offset = secondaryOffset == null ? primaryOffset : secondaryOffset;
BlockState checkedState = reader.getBlockState(pos.relative(offset)
.relative(face));
if (block.connectsToState(checkedState))
return checkedState.getValue(props.get(offset.getOpposite()));
checkedState = reader.getBlockState(pos.relative(offset));
if (block.connectsToState(checkedState))
return checkedState.getValue(faceProp);
return state.getValue(props.get(offset));
}
return false;
}
@Override
protected boolean isBeingBlocked(BlockState state, BlockAndTintGetter reader, BlockPos pos, BlockPos otherPos,
Direction face) {
ConnectedSixwayBlock block = (ConnectedSixwayBlock) state.getBlock();
BlockState blockingState = reader.getBlockState(otherPos.relative(face));
return block.disconnectsFromState(blockingState);
}
@Override
public CTSpriteShiftEntry get(BlockState state, Direction direction) {
return state.getValue(ConnectedSixwayBlock.PROPERTY_BY_DIRECTION.get(direction)) ? entry : null;
}
}

View file

@ -1,22 +0,0 @@
package com.simibubi.create.content.palettes;
import net.minecraft.world.level.block.PipeBlock;
import net.minecraft.world.level.block.state.BlockState;
public class ConnectedSixwayBlock extends PipeBlock {
public ConnectedSixwayBlock(float p_55159_, Properties p_55160_) {
super(p_55159_, p_55160_);
}
public boolean disconnectsFromState(BlockState blockingState) {
return false;
}
public boolean connectsToState(BlockState adjAbove1) {
return false;
}
}

View file

@ -11,9 +11,10 @@ import java.util.function.Function;
import java.util.function.Supplier;
import com.simibubi.create.Create;
import com.simibubi.create.foundation.block.connected.AllCTTypes;
import com.simibubi.create.foundation.block.connected.CTSpriteShiftEntry;
import com.simibubi.create.foundation.block.connected.CTSpriteShifter;
import com.simibubi.create.foundation.block.connected.CTSpriteShifter.CTType;
import com.simibubi.create.foundation.block.connected.CTType;
import com.simibubi.create.foundation.block.connected.ConnectedTextureBehaviour;
import com.simibubi.create.foundation.block.connected.HorizontalCTBehaviour;
import com.simibubi.create.foundation.block.connected.RotatedPillarCTBehaviour;
@ -250,9 +251,9 @@ public class PaletteBlockPattern {
public enum CTs {
PILLAR(CTType.RECTANGLE, s -> toLocation(s, "pillar")),
CAP(CTType.OMNIDIRECTIONAL, s -> toLocation(s, "cap")),
LAYERED(CTType.HORIZONTAL_KRYPPERS, s -> toLocation(s, "layered"))
PILLAR(AllCTTypes.RECTANGLE, s -> toLocation(s, "pillar")),
CAP(AllCTTypes.OMNIDIRECTIONAL, s -> toLocation(s, "cap")),
LAYERED(AllCTTypes.HORIZONTAL_KRYPPERS, s -> toLocation(s, "layered"))
;

View file

@ -0,0 +1,133 @@
package com.simibubi.create.foundation.block.connected;
import com.simibubi.create.Create;
import com.simibubi.create.foundation.block.connected.ConnectedTextureBehaviour.CTContext;
import com.simibubi.create.foundation.block.connected.ConnectedTextureBehaviour.ContextRequirement;
import com.simibubi.create.foundation.utility.Lang;
import net.minecraft.resources.ResourceLocation;
public enum AllCTTypes implements CTType {
HORIZONTAL(2, ContextRequirement.builder().horizontal().build()) {
@Override
public int getTextureIndex(CTContext context) {
return (context.right ? 1 : 0) + (context.left ? 2 : 0);
}
},
HORIZONTAL_KRYPPERS(2, ContextRequirement.builder().horizontal().build()) {
@Override
public int getTextureIndex(CTContext context) {
return !context.right && !context.left ? 0 : !context.right ? 3 : !context.left ? 2 : 1;
}
},
VERTICAL(2, ContextRequirement.builder().vertical().build()) {
@Override
public int getTextureIndex(CTContext context) {
return (context.up ? 1 : 0) + (context.down ? 2 : 0);
}
},
OMNIDIRECTIONAL(8, ContextRequirement.builder().all().build()) {
@Override
public int getTextureIndex(CTContext context) {
CTContext c = context;
int tileX = 0, tileY = 0;
int borders = (!c.up ? 1 : 0) + (!c.down ? 1 : 0) + (!c.left ? 1 : 0) + (!c.right ? 1 : 0);
if (c.up)
tileX++;
if (c.down)
tileX += 2;
if (c.left)
tileY++;
if (c.right)
tileY += 2;
if (borders == 0) {
if (c.topRight)
tileX++;
if (c.topLeft)
tileX += 2;
if (c.bottomRight)
tileY += 2;
if (c.bottomLeft)
tileY++;
}
if (borders == 1) {
if (!c.right) {
if (c.topLeft || c.bottomLeft) {
tileY = 4;
tileX = -1 + (c.bottomLeft ? 1 : 0) + (c.topLeft ? 1 : 0) * 2;
}
}
if (!c.left) {
if (c.topRight || c.bottomRight) {
tileY = 5;
tileX = -1 + (c.bottomRight ? 1 : 0) + (c.topRight ? 1 : 0) * 2;
}
}
if (!c.down) {
if (c.topLeft || c.topRight) {
tileY = 6;
tileX = -1 + (c.topLeft ? 1 : 0) + (c.topRight ? 1 : 0) * 2;
}
}
if (!c.up) {
if (c.bottomLeft || c.bottomRight) {
tileY = 7;
tileX = -1 + (c.bottomLeft ? 1 : 0) + (c.bottomRight ? 1 : 0) * 2;
}
}
}
if (borders == 2) {
if ((c.up && c.left && c.topLeft) || (c.down && c.left && c.bottomLeft)
|| (c.up && c.right && c.topRight) || (c.down && c.right && c.bottomRight))
tileX += 3;
}
return tileX + 8 * tileY;
}
},
CROSS(4, ContextRequirement.builder().axisAligned().build()) {
@Override
public int getTextureIndex(CTContext context) {
return (context.up ? 1 : 0) + (context.down ? 2 : 0) + (context.left ? 4 : 0) + (context.right ? 8 : 0);
}
},
RECTANGLE(4, ContextRequirement.builder().axisAligned().build()) {
@Override
public int getTextureIndex(CTContext context) {
int x = context.left && context.right ? 2 : context.left ? 3 : context.right ? 1 : 0;
int y = context.up && context.down ? 1 : context.up ? 2 : context.down ? 0 : 3;
return x + y * 4;
}
};
private final ResourceLocation id;
private final int sheetSize;
private final ContextRequirement contextRequirement;
AllCTTypes(int sheetSize, ContextRequirement contextRequirement) {
this.id = Create.asResource(Lang.asId(name()));
this.sheetSize = sheetSize;
this.contextRequirement = contextRequirement;
CTTypeRegistry.register(this);
}
@Override
public ResourceLocation getId() {
return id;
}
@Override
public int getSheetSize() {
return sheetSize;
}
@Override
public ContextRequirement getContextRequirement() {
return contextRequirement;
}
}

View file

@ -5,8 +5,6 @@ import java.util.Arrays;
import java.util.List;
import java.util.Random;
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
import com.mojang.blaze3d.vertex.VertexFormat;
import com.simibubi.create.foundation.block.connected.ConnectedTextureBehaviour.CTContext;
import com.simibubi.create.foundation.block.render.QuadHelper;
import com.simibubi.create.foundation.utility.Iterate;
@ -14,6 +12,7 @@ import com.simibubi.create.foundation.utility.Iterate;
import net.minecraft.client.renderer.block.model.BakedQuad;
import net.minecraft.client.resources.model.BakedModel;
import net.minecraft.core.BlockPos;
import net.minecraft.core.BlockPos.MutableBlockPos;
import net.minecraft.core.Direction;
import net.minecraft.world.level.BlockAndTintGetter;
import net.minecraft.world.level.block.Block;
@ -24,25 +23,9 @@ import net.minecraftforge.client.model.data.ModelProperty;
public class CTModel extends BakedModelWrapperWithData {
protected static final ModelProperty<CTData> CT_PROPERTY = new ModelProperty<>();
private ConnectedTextureBehaviour behaviour;
private static final ModelProperty<CTData> CT_PROPERTY = new ModelProperty<>();
private class CTData {
int[] indices;
public CTData() {
indices = new int[6];
Arrays.fill(indices, -1);
}
void put(Direction face, int texture) {
indices[face.get3DDataValue()] = texture;
}
int get(Direction face) {
return indices[face.get3DDataValue()];
}
}
private final ConnectedTextureBehaviour behaviour;
public CTModel(BakedModel originalModel, ConnectedTextureBehaviour behaviour) {
super(originalModel);
@ -56,15 +39,16 @@ public class CTModel extends BakedModelWrapperWithData {
protected CTData createCTData(BlockAndTintGetter world, BlockPos pos, BlockState state) {
CTData data = new CTData();
MutableBlockPos mutablePos = new MutableBlockPos();
for (Direction face : Iterate.directions) {
if (!Block.shouldRenderFace(state, world, pos, face, pos.relative(face))
&& !behaviour.buildContextForOccludedDirections())
if (!behaviour.buildContextForOccludedDirections()
&& !Block.shouldRenderFace(state, world, pos, face, mutablePos.setWithOffset(pos, face)))
continue;
CTSpriteShiftEntry spriteShift = behaviour.get(state, face);
if (spriteShift == null)
CTType dataType = behaviour.getDataType(state, face);
if (dataType == null)
continue;
CTContext ctContext = behaviour.buildContext(world, pos, state, face);
data.put(face, spriteShift.getTextureIndex(ctContext));
CTContext context = behaviour.buildContext(world, pos, state, face, dataType.getContextRequirement());
data.put(face, dataType.getTextureIndex(context));
}
return data;
}
@ -74,39 +58,54 @@ public class CTModel extends BakedModelWrapperWithData {
List<BakedQuad> quads = super.getQuads(state, side, rand, extraData);
if (!extraData.hasProperty(CT_PROPERTY))
return quads;
CTData data = extraData.getData(CT_PROPERTY);
quads = new ArrayList<>(quads);
VertexFormat format = DefaultVertexFormat.BLOCK;
for (int i = 0; i < quads.size(); i++) {
BakedQuad quad = quads.get(i);
CTSpriteShiftEntry spriteShift = behaviour.get(state, quad.getDirection(), quad.getSprite());
int index = data.get(quad.getDirection());
if (index == -1)
continue;
CTSpriteShiftEntry spriteShift = behaviour.getShift(state, quad.getDirection(), quad.getSprite());
if (spriteShift == null)
continue;
if (quad.getSprite() != spriteShift.getOriginal())
continue;
int index = data.get(quad.getDirection());
if (index == -1)
continue;
BakedQuad newQuad = QuadHelper.clone(quad);
int[] vertexData = newQuad.getVertices();
for (int vertex = 0; vertex < vertexData.length; vertex += format.getIntegerSize()) {
int uvOffset = 16 / 4;
int uIndex = vertex + uvOffset;
int vIndex = vertex + uvOffset + 1;
float u = Float.intBitsToFloat(vertexData[uIndex]);
float v = Float.intBitsToFloat(vertexData[vIndex]);
vertexData[uIndex] = Float.floatToRawIntBits(spriteShift.getTargetU(u, index));
vertexData[vIndex] = Float.floatToRawIntBits(spriteShift.getTargetV(v, index));
for (int vertex = 0; vertex < 4; vertex++) {
float u = QuadHelper.getU(vertexData, vertex);
float v = QuadHelper.getV(vertexData, vertex);
QuadHelper.setU(vertexData, vertex, spriteShift.getTargetU(u, index));
QuadHelper.setV(vertexData, vertex, spriteShift.getTargetV(v, index));
}
quads.set(i, newQuad);
}
return quads;
}
private static class CTData {
private final int[] indices;
public CTData() {
indices = new int[6];
Arrays.fill(indices, -1);
}
public void put(Direction face, int texture) {
indices[face.get3DDataValue()] = texture;
}
public int get(Direction face) {
return indices[face.get3DDataValue()];
}
}
}

View file

@ -1,188 +1,29 @@
package com.simibubi.create.foundation.block.connected;
import com.simibubi.create.foundation.block.connected.CTSpriteShifter.CTType;
import com.simibubi.create.foundation.block.connected.ConnectedTextureBehaviour.CTContext;
import com.simibubi.create.foundation.block.render.SpriteShiftEntry;
import com.simibubi.create.foundation.render.SuperByteBuffer;
public abstract class CTSpriteShiftEntry extends SpriteShiftEntry {
public class CTSpriteShiftEntry extends SpriteShiftEntry {
protected int textureSheetSize;
protected final CTType type;
public CTSpriteShiftEntry(int sheetSize) {
this.textureSheetSize = sheetSize;
public CTSpriteShiftEntry(CTType type) {
this.type = type;
}
public CTType getType() {
return type;
}
public float getTargetU(float localU, int index) {
float uOffset = (index % textureSheetSize);
float uOffset = (index % type.getSheetSize());
return getTarget().getU(
(SuperByteBuffer.getUnInterpolatedU(getOriginal(), localU) + (uOffset * 16)) / ((float) textureSheetSize));
(getUnInterpolatedU(getOriginal(), localU) + (uOffset * 16)) / ((float) type.getSheetSize()));
}
public float getTargetV(float localV, int index) {
float vOffset = (index / textureSheetSize);
float vOffset = (index / type.getSheetSize());
return getTarget().getV(
(SuperByteBuffer.getUnInterpolatedV(getOriginal(), localV) + (vOffset * 16)) / ((float) textureSheetSize));
}
public abstract int getTextureIndex(CTContext context);
public abstract CTType getType();
public static class Horizontal extends CTSpriteShiftEntry {
// Different sheet arrangement
private boolean kryppers;
public Horizontal(boolean kryppers) {
super(2);
this.kryppers = kryppers;
}
@Override
public int getTextureIndex(CTContext context) {
if (kryppers)
return !context.right && !context.left ? 0 : !context.right ? 3 : !context.left ? 2 : 1;
return (context.right ? 1 : 0) + (context.left ? 2 : 0);
}
@Override
public CTType getType() {
return CTType.HORIZONTAL;
}
}
public static class Vertical extends CTSpriteShiftEntry {
public Vertical() {
super(2);
}
@Override
public int getTextureIndex(CTContext context) {
return (context.up ? 1 : 0) + (context.down ? 2 : 0);
}
@Override
public CTType getType() {
return CTType.VERTICAL;
}
}
public static class Cross extends CTSpriteShiftEntry {
public Cross() {
super(4);
}
@Override
public int getTextureIndex(CTContext context) {
return (context.up ? 1 : 0) + (context.down ? 2 : 0) + (context.left ? 4 : 0) + (context.right ? 8 : 0);
}
@Override
public CTType getType() {
return CTType.CROSS;
}
}
// Same as cross with different sheet arrangement
public static class Rect extends CTSpriteShiftEntry {
public Rect() {
super(4);
}
@Override
public int getTextureIndex(CTContext context) {
int x = context.left && context.right ? 2 : context.left ? 3 : context.right ? 1 : 0;
int y = context.up && context.down ? 1 : context.up ? 2 : context.down ? 0 : 3;
return x + y * 4;
}
@Override
public CTType getType() {
return CTType.RECTANGLE;
}
}
public static class Omnidirectional extends CTSpriteShiftEntry {
public Omnidirectional() {
super(8);
}
@Override
public int getTextureIndex(CTContext context) {
CTContext c = context;
int tileX = 0, tileY = 0;
int borders = (!c.up ? 1 : 0) + (!c.down ? 1 : 0) + (!c.left ? 1 : 0) + (!c.right ? 1 : 0);
if (c.up)
tileX++;
if (c.down)
tileX += 2;
if (c.left)
tileY++;
if (c.right)
tileY += 2;
if (borders == 0) {
if (c.topRight)
tileX++;
if (c.topLeft)
tileX += 2;
if (c.bottomRight)
tileY += 2;
if (c.bottomLeft)
tileY++;
}
if (borders == 1) {
if (!c.right) {
if (c.topLeft || c.bottomLeft) {
tileY = 4;
tileX = -1 + (c.bottomLeft ? 1 : 0) + (c.topLeft ? 1 : 0) * 2;
}
}
if (!c.left) {
if (c.topRight || c.bottomRight) {
tileY = 5;
tileX = -1 + (c.bottomRight ? 1 : 0) + (c.topRight ? 1 : 0) * 2;
}
}
if (!c.down) {
if (c.topLeft || c.topRight) {
tileY = 6;
tileX = -1 + (c.topLeft ? 1 : 0) + (c.topRight ? 1 : 0) * 2;
}
}
if (!c.up) {
if (c.bottomLeft || c.bottomRight) {
tileY = 7;
tileX = -1 + (c.bottomLeft ? 1 : 0) + (c.bottomRight ? 1 : 0) * 2;
}
}
}
if (borders == 2) {
if ((c.up && c.left && c.topLeft) || (c.down && c.left && c.bottomLeft)
|| (c.up && c.right && c.topRight) || (c.down && c.right && c.bottomRight))
tileX += 3;
}
return tileX + 8 * tileY;
}
@Override
public CTType getType() {
return CTType.OMNIDIRECTIONAL;
}
(getUnInterpolatedV(getOriginal(), localV) + (vOffset * 16)) / ((float) type.getSheetSize()));
}
}

View file

@ -1,52 +1,25 @@
package com.simibubi.create.foundation.block.connected;
import com.simibubi.create.Create;
import com.simibubi.create.foundation.block.render.SpriteShifter;
import java.util.HashMap;
import java.util.Map;
import com.simibubi.create.foundation.block.render.SpriteShiftEntry;
import net.minecraft.resources.ResourceLocation;
public class CTSpriteShifter extends SpriteShifter {
public class CTSpriteShifter {
private static final Map<String, SpriteShiftEntry> ENTRY_CACHE = new HashMap<>();
public static CTSpriteShiftEntry getCT(CTType type, ResourceLocation blockTexture, ResourceLocation connectedTexture) {
String key = type.name() + ":" + blockTexture + "->" + connectedTexture;
String key = blockTexture + "->" + connectedTexture + "+" + type.getId();
if (ENTRY_CACHE.containsKey(key))
return (CTSpriteShiftEntry) ENTRY_CACHE.get(key);
CTSpriteShiftEntry entry = create(type);
CTSpriteShiftEntry entry = new CTSpriteShiftEntry(type);
entry.set(blockTexture, connectedTexture);
ENTRY_CACHE.put(key, entry);
return entry;
}
public static CTSpriteShiftEntry getCT(CTType type, String blockTextureName, String connectedTextureName) {
return getCT(type, Create.asResource("block/" + blockTextureName), Create.asResource("block/" + connectedTextureName + "_connected"));
}
public static CTSpriteShiftEntry getCT(CTType type, String blockTextureName) {
return getCT(type, blockTextureName, blockTextureName);
}
private static CTSpriteShiftEntry create(CTType type) {
switch (type) {
case HORIZONTAL:
return new CTSpriteShiftEntry.Horizontal(false);
case HORIZONTAL_KRYPPERS:
return new CTSpriteShiftEntry.Horizontal(true);
case OMNIDIRECTIONAL:
return new CTSpriteShiftEntry.Omnidirectional();
case VERTICAL:
return new CTSpriteShiftEntry.Vertical();
case CROSS:
return new CTSpriteShiftEntry.Cross();
case RECTANGLE:
return new CTSpriteShiftEntry.Rect();
default:
return null;
}
}
public enum CTType {
OMNIDIRECTIONAL, HORIZONTAL, VERTICAL, CROSS, RECTANGLE, HORIZONTAL_KRYPPERS;
}
}

View file

@ -0,0 +1,16 @@
package com.simibubi.create.foundation.block.connected;
import com.simibubi.create.foundation.block.connected.ConnectedTextureBehaviour.CTContext;
import com.simibubi.create.foundation.block.connected.ConnectedTextureBehaviour.ContextRequirement;
import net.minecraft.resources.ResourceLocation;
public interface CTType {
ResourceLocation getId();
int getSheetSize();
ContextRequirement getContextRequirement();
int getTextureIndex(CTContext context);
}

View file

@ -0,0 +1,24 @@
package com.simibubi.create.foundation.block.connected;
import java.util.HashMap;
import java.util.Map;
import javax.annotation.Nullable;
import net.minecraft.resources.ResourceLocation;
public class CTTypeRegistry {
private static final Map<ResourceLocation, CTType> TYPES = new HashMap<>();
public static void register(CTType type) {
ResourceLocation id = type.getId();
if (TYPES.containsKey(id))
throw new IllegalArgumentException("Tried to override CTType registration for id '" + id + "'. This is not supported!");
TYPES.put(id, type);
}
@Nullable
public static CTType get(ResourceLocation id) {
return TYPES.get(id);
}
}

View file

@ -1,6 +1,7 @@
package com.simibubi.create.foundation.block.connected;
import com.simibubi.create.foundation.block.connected.CTSpriteShifter.CTType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.core.BlockPos;
@ -12,17 +13,44 @@ import net.minecraft.world.level.block.state.BlockState;
public abstract class ConnectedTextureBehaviour {
public class CTContext {
boolean up, down, left, right;
boolean topLeft, topRight, bottomLeft, bottomRight;
@Nullable
public abstract CTSpriteShiftEntry getShift(BlockState state, Direction direction, @NotNull TextureAtlasSprite sprite);
// TODO: allow more than one data type per state/face?
@Nullable
public abstract CTType getDataType(BlockState state, Direction direction);
public boolean buildContextForOccludedDirections() {
return false;
}
public CTSpriteShiftEntry get(BlockState state, Direction direction, TextureAtlasSprite sprite) {
return get(state, direction);
protected boolean isBeingBlocked(BlockState state, BlockAndTintGetter reader, BlockPos pos, BlockPos otherPos,
Direction face) {
BlockPos blockingPos = otherPos.relative(face);
return face.getAxis()
.choose(pos.getX(), pos.getY(), pos.getZ()) == face.getAxis()
.choose(otherPos.getX(), otherPos.getY(), otherPos.getZ())
&& connectsTo(state, reader.getBlockState(blockingPos), reader, pos, blockingPos, face);
}
public CTSpriteShiftEntry get(BlockState state, Direction direction) {
return null;
public boolean connectsTo(BlockState state, BlockState other, BlockAndTintGetter reader, BlockPos pos,
BlockPos otherPos, Direction face, Direction primaryOffset, Direction secondaryOffset) {
return connectsTo(state, other, reader, pos, otherPos, face);
}
public boolean connectsTo(BlockState state, BlockState other, BlockAndTintGetter reader, BlockPos pos,
BlockPos otherPos, Direction face) {
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)
.relative(vertical, sv);
boolean test = connectsTo(state, reader.getBlockState(p), reader, pos, p, face,
sh == 0 ? null : sh == -1 ? horizontal.getOpposite() : horizontal,
sv == 0 ? null : sv == -1 ? vertical.getOpposite() : vertical);
return test;
}
protected boolean reverseUVs(BlockState state, Direction face) {
@ -37,36 +65,17 @@ public abstract class ConnectedTextureBehaviour {
return reverseUVs(state, face);
}
public boolean buildContextForOccludedDirections() {
return false;
protected Direction getUpDirection(BlockAndTintGetter reader, BlockPos pos, BlockState state, Direction face) {
Axis axis = face.getAxis();
return axis.isHorizontal() ? Direction.UP : Direction.NORTH;
}
public boolean connectsTo(BlockState state, BlockState other, BlockAndTintGetter reader, BlockPos pos,
BlockPos otherPos, Direction face, Direction primaryOffset, Direction secondaryOffset) {
return connectsTo(state, other, reader, pos, otherPos, face);
protected Direction getRightDirection(BlockAndTintGetter reader, BlockPos pos, BlockState state, Direction face) {
Axis axis = face.getAxis();
return axis == Axis.X ? Direction.SOUTH : Direction.WEST;
}
public boolean connectsTo(BlockState state, BlockState other, BlockAndTintGetter reader, BlockPos pos,
BlockPos otherPos, Direction face) {
return !isBeingBlocked(state, reader, pos, otherPos, face) && state.getBlock() == other.getBlock();
}
protected boolean isBeingBlocked(BlockState state, BlockAndTintGetter reader, BlockPos pos, BlockPos otherPos,
Direction face) {
BlockPos blockingPos = otherPos.relative(face);
return face.getAxis()
.choose(pos.getX(), pos.getY(), pos.getZ()) == face.getAxis()
.choose(otherPos.getX(), otherPos.getY(), otherPos.getZ())
&& connectsTo(state, reader.getBlockState(blockingPos), reader, pos, blockingPos, face);
}
public CTContext buildContext(BlockAndTintGetter reader, BlockPos pos, BlockState state, Direction face) {
CTContext context = new CTContext();
CTSpriteShiftEntry textureEntry = get(state, face);
if (textureEntry == null)
return context;
public CTContext buildContext(BlockAndTintGetter reader, BlockPos pos, BlockState state, Direction face, ContextRequirement requirement) {
boolean positive = face.getAxisDirection() == AxisDirection.POSITIVE;
Direction h = getRightDirection(reader, pos, state, face);
Direction v = getUpDirection(reader, pos, state, face);
@ -84,25 +93,34 @@ public abstract class ConnectedTextureBehaviour {
int sh = flipH ? -1 : 1;
int sv = flipV ? -1 : 1;
CTType type = textureEntry.getType();
CTContext context = new CTContext();
if (type != CTType.HORIZONTAL) {
if (requirement.up) {
context.up = testConnection(reader, pos, state, face, horizontal, vertical, 0, sv);
}
if (requirement.down) {
context.down = testConnection(reader, pos, state, face, horizontal, vertical, 0, -sv);
}
if (type != CTType.VERTICAL) {
if (requirement.left) {
context.left = testConnection(reader, pos, state, face, horizontal, vertical, -sh, 0);
}
if (requirement.right) {
context.right = testConnection(reader, pos, state, face, horizontal, vertical, sh, 0);
}
if (type == CTType.OMNIDIRECTIONAL) {
if (requirement.topLeft) {
context.topLeft =
context.up && context.left && testConnection(reader, pos, state, face, horizontal, vertical, -sh, sv);
}
if (requirement.topRight) {
context.topRight =
context.up && context.right && testConnection(reader, pos, state, face, horizontal, vertical, sh, sv);
}
if (requirement.bottomLeft) {
context.bottomLeft = context.down && context.left
&& testConnection(reader, pos, state, face, horizontal, vertical, -sh, -sv);
}
if (requirement.bottomRight) {
context.bottomRight = context.down && context.right
&& testConnection(reader, pos, state, face, horizontal, vertical, sh, -sv);
}
@ -110,24 +128,128 @@ public abstract class ConnectedTextureBehaviour {
return context;
}
protected Direction getUpDirection(BlockAndTintGetter reader, BlockPos pos, BlockState state, Direction face) {
Axis axis = face.getAxis();
return axis.isHorizontal() ? Direction.UP : Direction.NORTH;
public static class CTContext {
public static final CTContext EMPTY = new CTContext();
public boolean up, down, left, right;
public boolean topLeft, topRight, bottomLeft, bottomRight;
}
protected Direction getRightDirection(BlockAndTintGetter reader, BlockPos pos, BlockState state, Direction face) {
Axis axis = face.getAxis();
return axis == Axis.X ? Direction.SOUTH : Direction.WEST;
public static class ContextRequirement {
public final boolean up, down, left, right;
public final boolean topLeft, topRight, bottomLeft, bottomRight;
public ContextRequirement(boolean up, boolean down, boolean left, boolean right, boolean topLeft, boolean topRight, boolean bottomLeft, boolean bottomRight) {
this.up = up;
this.down = down;
this.left = left;
this.right = right;
this.topLeft = topLeft;
this.topRight = topRight;
this.bottomLeft = bottomLeft;
this.bottomRight = bottomRight;
}
public static Builder builder() {
return new Builder();
}
public static class Builder {
private boolean up, down, left, right;
private boolean topLeft, topRight, bottomLeft, bottomRight;
public Builder up() {
up = true;
return this;
}
public Builder down() {
down = true;
return this;
}
public Builder left() {
left = true;
return this;
}
public Builder right() {
right = true;
return this;
}
public Builder topLeft() {
topLeft = true;
return this;
}
public Builder topRight() {
topRight = true;
return this;
}
public Builder bottomLeft() {
bottomLeft = true;
return this;
}
public Builder bottomRight() {
bottomRight = true;
return this;
}
public Builder horizontal() {
left();
right();
return this;
}
public Builder vertical() {
up();
down();
return this;
}
public Builder axisAligned() {
horizontal();
vertical();
return this;
}
public Builder corners() {
topLeft();
topRight();
bottomLeft();
bottomRight();
return this;
}
public Builder all() {
axisAligned();
corners();
return this;
}
public ContextRequirement build() {
return new ContextRequirement(up, down, left, right, topLeft, topRight, bottomLeft, bottomRight);
}
}
}
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)
.relative(vertical, sv);
boolean test = connectsTo(state, reader.getBlockState(p), reader, pos, p, face,
sh == 0 ? null : sh == -1 ? horizontal.getOpposite() : horizontal,
sv == 0 ? null : sv == -1 ? vertical.getOpposite() : vertical);
return test;
public static abstract class Base extends ConnectedTextureBehaviour {
@Override
@Nullable
public abstract CTSpriteShiftEntry getShift(BlockState state, Direction direction, @Nullable TextureAtlasSprite sprite);
@Override
@Nullable
public CTType getDataType(BlockState state, Direction direction) {
CTSpriteShiftEntry shift = getShift(state, direction, null);
if (shift == null) {
return null;
}
return shift.getType();
}
}
}

View file

@ -6,7 +6,7 @@ import net.minecraft.core.Direction.AxisDirection;
import net.minecraft.world.level.BlockAndTintGetter;
import net.minecraft.world.level.block.state.BlockState;
public class GlassPaneCTBehaviour extends StandardCTBehaviour {
public class GlassPaneCTBehaviour extends SimpleCTBehaviour {
public GlassPaneCTBehaviour(CTSpriteShiftEntry shift) {
super(shift);

View file

@ -1,12 +1,15 @@
package com.simibubi.create.foundation.block.connected;
import org.jetbrains.annotations.Nullable;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.core.Direction;
import net.minecraft.world.level.block.state.BlockState;
public class HorizontalCTBehaviour extends ConnectedTextureBehaviour {
public class HorizontalCTBehaviour extends ConnectedTextureBehaviour.Base {
CTSpriteShiftEntry topShift;
CTSpriteShiftEntry layerShift;
protected CTSpriteShiftEntry topShift;
protected CTSpriteShiftEntry layerShift;
public HorizontalCTBehaviour(CTSpriteShiftEntry layerShift) {
this(layerShift, null);
@ -18,7 +21,7 @@ public class HorizontalCTBehaviour extends ConnectedTextureBehaviour {
}
@Override
public CTSpriteShiftEntry get(BlockState state, Direction direction) {
public CTSpriteShiftEntry getShift(BlockState state, Direction direction, @Nullable TextureAtlasSprite sprite) {
return direction.getAxis()
.isHorizontal() ? layerShift : topShift;
}

View file

@ -3,6 +3,7 @@ package com.simibubi.create.foundation.block.connected;
import com.simibubi.create.content.palettes.ConnectedPillarBlock;
import com.simibubi.create.content.palettes.LayeredBlock;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.Direction.Axis;
@ -100,9 +101,9 @@ public class RotatedPillarCTBehaviour extends HorizontalCTBehaviour {
}
@Override
public CTSpriteShiftEntry get(BlockState state, Direction direction) {
return super.get(state,
direction.getAxis() == state.getValue(LayeredBlock.AXIS) ? Direction.UP : Direction.SOUTH);
public CTSpriteShiftEntry getShift(BlockState state, Direction direction, TextureAtlasSprite sprite) {
return super.getShift(state,
direction.getAxis() == state.getValue(LayeredBlock.AXIS) ? Direction.UP : Direction.SOUTH, sprite);
}
}

View file

@ -0,0 +1,22 @@
package com.simibubi.create.foundation.block.connected;
import org.jetbrains.annotations.Nullable;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.core.Direction;
import net.minecraft.world.level.block.state.BlockState;
public class SimpleCTBehaviour extends ConnectedTextureBehaviour.Base {
protected CTSpriteShiftEntry shift;
public SimpleCTBehaviour(CTSpriteShiftEntry shift) {
this.shift = shift;
}
@Override
public CTSpriteShiftEntry getShift(BlockState state, Direction direction, @Nullable TextureAtlasSprite sprite) {
return shift;
}
}

View file

@ -1,19 +0,0 @@
package com.simibubi.create.foundation.block.connected;
import net.minecraft.core.Direction;
import net.minecraft.world.level.block.state.BlockState;
public class StandardCTBehaviour extends ConnectedTextureBehaviour {
CTSpriteShiftEntry shift;
public StandardCTBehaviour(CTSpriteShiftEntry shift) {
this.shift = shift;
}
@Override
public CTSpriteShiftEntry get(BlockState state, Direction direction) {
return shift;
}
}

View file

@ -2,10 +2,25 @@ package com.simibubi.create.foundation.block.render;
import java.util.Arrays;
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
import com.mojang.blaze3d.vertex.VertexFormat;
import net.minecraft.client.renderer.block.model.BakedQuad;
public final class QuadHelper {
public static final VertexFormat FORMAT = DefaultVertexFormat.BLOCK;
public static final int VERTEX_STRIDE = FORMAT.getIntegerSize();
public static final int X_OFFSET = 0;
public static final int Y_OFFSET = 1;
public static final int Z_OFFSET = 2;
public static final int COLOR_OFFSET = 3;
public static final int U_OFFSET = 4;
public static final int V_OFFSET = 5;
public static final int LIGHT_OFFSET = 6;
public static final int NORMAL_OFFSET = 7;
private QuadHelper() {}
public static BakedQuad clone(BakedQuad quad) {
@ -13,4 +28,20 @@ public final class QuadHelper {
quad.getTintIndex(), quad.getDirection(), quad.getSprite(), quad.isShade());
}
public static float getU(int[] vertexData, int vertex) {
return Float.intBitsToFloat(vertexData[vertex * VERTEX_STRIDE + U_OFFSET]);
}
public static float getV(int[] vertexData, int vertex) {
return Float.intBitsToFloat(vertexData[vertex * VERTEX_STRIDE + V_OFFSET]);
}
public static void setU(int[] vertexData, int vertex, float u) {
vertexData[vertex * VERTEX_STRIDE + U_OFFSET] = Float.floatToRawIntBits(u);
}
public static void setV(int[] vertexData, int vertex, float v) {
vertexData[vertex * VERTEX_STRIDE + V_OFFSET] = Float.floatToRawIntBits(v);
}
}

View file

@ -29,4 +29,22 @@ public class SpriteShiftEntry {
public TextureAtlasSprite getTarget() {
return target.get();
}
public float getTargetU(float localU) {
return getTarget().getU(getUnInterpolatedU(getOriginal(), localU));
}
public float getTargetV(float localV) {
return getTarget().getV(getUnInterpolatedV(getOriginal(), localV));
}
public static float getUnInterpolatedU(TextureAtlasSprite sprite, float u) {
float f = sprite.getU1() - sprite.getU0();
return (u - sprite.getU0()) / f * 16.0F;
}
public static float getUnInterpolatedV(TextureAtlasSprite sprite, float v) {
float f = sprite.getV1() - sprite.getV0();
return (v - sprite.getV0()) / f * 16.0F;
}
}

View file

@ -3,13 +3,11 @@ package com.simibubi.create.foundation.block.render;
import java.util.HashMap;
import java.util.Map;
import com.simibubi.create.Create;
import net.minecraft.resources.ResourceLocation;
public class SpriteShifter {
protected static final Map<String, SpriteShiftEntry> ENTRY_CACHE = new HashMap<>();
private static final Map<String, SpriteShiftEntry> ENTRY_CACHE = new HashMap<>();
public static SpriteShiftEntry get(ResourceLocation originalLocation, ResourceLocation targetLocation) {
String key = originalLocation + "->" + targetLocation;
@ -22,8 +20,4 @@ public class SpriteShifter {
return entry;
}
public static SpriteShiftEntry get(String originalLocation, String targetLocation) {
return get(Create.asResource(originalLocation), Create.asResource(targetLocation));
}
}

View file

@ -27,7 +27,6 @@ import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.LevelRenderer;
import net.minecraft.client.renderer.LightTexture;
import net.minecraft.client.renderer.texture.OverlayTexture;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.util.Mth;
@ -350,11 +349,7 @@ public class SuperByteBuffer implements Transform<SuperByteBuffer>, TStack<Super
public SuperByteBuffer shiftUV(SpriteShiftEntry entry) {
this.spriteShiftFunc = (builder, u, v) -> {
float targetU = entry.getTarget()
.getU((getUnInterpolatedU(entry.getOriginal(), u)));
float targetV = entry.getTarget()
.getV((getUnInterpolatedV(entry.getOriginal(), v)));
builder.uv(targetU, targetV);
builder.uv(entry.getTargetU(u), entry.getTargetV(v));
};
return this;
}
@ -381,9 +376,9 @@ public class SuperByteBuffer implements Transform<SuperByteBuffer>, TStack<Super
public SuperByteBuffer shiftUVtoSheet(SpriteShiftEntry entry, float uTarget, float vTarget, int sheetSize) {
this.spriteShiftFunc = (builder, u, v) -> {
float targetU = entry.getTarget()
.getU((getUnInterpolatedU(entry.getOriginal(), u) / sheetSize) + uTarget * 16);
.getU((SpriteShiftEntry.getUnInterpolatedU(entry.getOriginal(), u) / sheetSize) + uTarget * 16);
float targetV = entry.getTarget()
.getV((getUnInterpolatedV(entry.getOriginal(), v) / sheetSize) + vTarget * 16);
.getV((SpriteShiftEntry.getUnInterpolatedV(entry.getOriginal(), v) / sheetSize) + vTarget * 16);
builder.uv(targetU, targetV);
};
return this;
@ -457,16 +452,6 @@ public class SuperByteBuffer implements Transform<SuperByteBuffer>, TStack<Super
return Mth.clamp((int) (component * scale), 0, 255);
}
public static float getUnInterpolatedU(TextureAtlasSprite sprite, float u) {
float f = sprite.getU1() - sprite.getU0();
return (u - sprite.getU0()) / f * 16.0F;
}
public static float getUnInterpolatedV(TextureAtlasSprite sprite, float v) {
float f = sprite.getV1() - sprite.getV0();
return (v - sprite.getV0()) / f * 16.0F;
}
public static int maxLight(int packedLight1, int packedLight2) {
int blockLight1 = LightTexture.block(packedLight1);
int skyLight1 = LightTexture.sky(packedLight1);

View file

@ -1,5 +1,7 @@
package com.simibubi.create.foundation.tileEntity;
import javax.annotation.Nullable;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.world.level.block.entity.BlockEntity;
@ -8,8 +10,6 @@ import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.IFluidTank;
import javax.annotation.Nullable;
public interface IMultiTileContainer {
BlockPos getController();