Crafter Connectivity

- Mechanical Crafters can now be connected using a wrench
- Connected crafters "share" an input inventory
- Added texture connectivity for all faces
This commit is contained in:
simibubi 2020-01-15 21:56:53 +01:00
parent dea7a9869f
commit cea90d50e4
27 changed files with 911 additions and 204 deletions

View file

@ -135,10 +135,10 @@ public enum AllBlocks {
MECHANICAL_MIXER_HEAD(new RenderUtilityBlock()),
BASIN(new BasinBlock()),
MECHANICAL_CRAFTER(new MechanicalCrafterBlock()),
MECHANICAL_CRAFTER_LID(new RenderUtilityDirectionalBlock()),
MECHANICAL_CRAFTER_ARROW(new RenderUtilityDirectionalBlock()),
MECHANICAL_CRAFTER_BELT_FRAME(new RenderUtilityDirectionalBlock()),
MECHANICAL_CRAFTER_BELT(new RenderUtilityDirectionalBlock()),
MECHANICAL_CRAFTER_LID(new RenderUtilityBlock()),
MECHANICAL_CRAFTER_ARROW(new RenderUtilityBlock()),
MECHANICAL_CRAFTER_BELT_FRAME(new RenderUtilityBlock()),
MECHANICAL_CRAFTER_BELT(new RenderUtilityBlock()),
SPEED_GAUGE(new GaugeBlock(GaugeBlock.Type.SPEED)),
STRESS_GAUGE(new GaugeBlock(GaugeBlock.Type.STRESS)),
GAUGE_DIAL(new RenderUtilityBlock()),
@ -221,10 +221,9 @@ public enum AllBlocks {
LIMESTONE_BRICKS(new Block(Properties.from(LIMESTONE.block)), ComesWith.STAIRS, ComesWith.SLAB, ComesWith.WALL),
POLISHED_LIMESTONE(new Block(Properties.from(LIMESTONE.block)), ComesWith.SLAB),
LIMESTONE_PILLAR(new RotatedPillarBlock(Properties.from(LIMESTONE.block))),
LIMESTONE_LAYERS(
new LayeredCTBlock(Properties.from(LIMESTONE.block),
CTSpriteShifter.get(CTType.HORIZONTAL, "limestone_layers"),
CTSpriteShifter.get(CTType.OMNIDIRECTIONAL, "polished_limestone"))),
LIMESTONE_LAYERS(new LayeredCTBlock(Properties.from(LIMESTONE.block),
CTSpriteShifter.get(CTType.HORIZONTAL, "limestone_layers"),
CTSpriteShifter.get(CTType.OMNIDIRECTIONAL, "polished_limestone"))),
WEATHERED_LIMESTONE(new Block(Properties.from(Blocks.ANDESITE)), ComesWith.STAIRS, ComesWith.SLAB, ComesWith.WALL),
WEATHERED_LIMESTONE_BRICKS(new Block(Properties.from(WEATHERED_LIMESTONE.block)), ComesWith.STAIRS, ComesWith.SLAB,
ComesWith.WALL),
@ -240,7 +239,7 @@ public enum AllBlocks {
__MATERIALS__(),
COPPER_ORE(new CopperOreBlock()),
ZINC_ORE(new Block(Properties.from(Blocks.GOLD_ORE))),
;
private enum ComesWith {

View file

@ -79,6 +79,8 @@ public class CTModel extends BakedModelWrapper<IBakedModel> {
CTSpriteShiftEntry spriteShift = behaviour.get(state, quad.getFace());
if (spriteShift == null)
continue;
if (quad.getSprite() != spriteShift.getOriginal())
continue;
int index = data.get(quad.getFace());
if (index == -1)
continue;

View file

@ -17,8 +17,8 @@ public class CTSpriteShifter extends SpriteShifter {
public static CTSpriteShiftEntry get(CTType type, String blockTextureName, String connectedTextureName) {
String originalLocation = "block/" + blockTextureName;
String targetLocation = "block/connected/" + blockTextureName;
String key = originalLocation + "->" + targetLocation;
String targetLocation = "block/connected/" + connectedTextureName;
String key = type.name() + ":" + originalLocation + "->" + targetLocation;
if (textures.containsKey(key))
return (CTSpriteShiftEntry) textures.get(key);

View file

@ -0,0 +1,287 @@
package com.simibubi.create.modules.contraptions.components.crafter;
import static com.simibubi.create.AllBlocks.MECHANICAL_CRAFTER;
import static com.simibubi.create.modules.contraptions.base.HorizontalKineticBlock.HORIZONTAL_FACING;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import org.apache.commons.lang3.tuple.Pair;
import com.google.common.base.Predicates;
import com.simibubi.create.AllItems;
import com.simibubi.create.foundation.utility.RaycastHelper;
import com.simibubi.create.foundation.utility.VecHelper;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.nbt.ListNBT;
import net.minecraft.nbt.NBTUtil;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.ActionResultType;
import net.minecraft.util.Direction;
import net.minecraft.util.Hand;
import net.minecraft.util.SoundCategory;
import net.minecraft.util.SoundEvents;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.IEnviromentBlockReader;
import net.minecraft.world.World;
import net.minecraftforge.common.util.Constants.NBT;
import net.minecraftforge.event.entity.player.PlayerInteractEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.LogicalSide;
import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.IItemHandlerModifiable;
import net.minecraftforge.items.ItemStackHandler;
import net.minecraftforge.items.wrapper.CombinedInvWrapper;
@EventBusSubscriber
public class ConnectedInputHandler {
@SubscribeEvent
public static void onBlockActivated(PlayerInteractEvent.RightClickBlock event) {
World world = event.getWorld();
BlockPos pos = event.getPos();
PlayerEntity player = event.getPlayer();
Hand hand = event.getHand();
ItemStack heldItem = player.getHeldItem(hand);
if (player.isSneaking())
return;
if (!AllItems.WRENCH.typeOf(heldItem))
return;
BlockState blockState = world.getBlockState(pos);
if (!MECHANICAL_CRAFTER.typeOf(blockState))
return;
BlockRayTraceResult ray = RaycastHelper.rayTraceRange(world, player, 10);
if (ray == null)
return;
if (ray.getFace() == blockState.get(MechanicalCrafterBlock.HORIZONTAL_FACING))
return;
Direction activatedDirection = getActivatedDirection(world, pos, ray.getFace(), ray.getHitVec());
if (activatedDirection != null) {
if (event.getSide() != LogicalSide.CLIENT)
toggleConnection(world, pos, pos.offset(activatedDirection));
event.setCanceled(true);
event.setCancellationResult(ActionResultType.SUCCESS);
world.playSound(null, pos, SoundEvents.ENTITY_ITEM_FRAME_ADD_ITEM, SoundCategory.BLOCKS, .25f, .1f);
}
}
public static List<Pair<Direction, Vec3d>> getConnectiveSides(World world, BlockPos pos, Direction face) {
List<Pair<Direction, Vec3d>> sides = new ArrayList<>(6);
BlockState refState = world.getBlockState(pos);
Direction refDirection = refState.get(HORIZONTAL_FACING);
Vec3d faceOffset = new Vec3d(face.getDirectionVec()).scale(.5).add(VecHelper.getCenterOf(BlockPos.ZERO));
if (Block.hasSolidSide(world.getBlockState(pos.offset(face)), world, pos.offset(face), face.getOpposite()))
return sides;
for (Direction direction : Direction.values()) {
if (direction.getAxis() == face.getAxis())
continue;
if (direction.getAxis() == refDirection.getAxis())
continue;
BlockPos neighbourPos = pos.offset(direction);
BlockState neighbour = world.getBlockState(neighbourPos);
if (!MECHANICAL_CRAFTER.typeOf(neighbour))
continue;
if (refDirection != neighbour.get(HORIZONTAL_FACING))
continue;
if (Block.hasSolidSide(world.getBlockState(neighbourPos.offset(face)), world, neighbourPos.offset(face),
face.getOpposite()))
continue;
Vec3d bbPos = new Vec3d(direction.getDirectionVec()).scale(.5).add(faceOffset);
sides.add(Pair.of(direction, bbPos));
}
return sides;
}
public static Direction getActivatedDirection(World world, BlockPos pos, Direction face, Vec3d hit) {
Vec3d localHit = hit.subtract(pos.getX(), pos.getY(), pos.getZ());
for (Pair<Direction, Vec3d> pair : getConnectiveSides(world, pos, face)) {
Vec3d bbPos = pair.getRight();
AxisAlignedBB bb = new AxisAlignedBB(bbPos, bbPos).grow(1 / 6f);
if (bb.contains(localHit))
return pair.getKey();
}
return null;
}
public static void toggleConnection(World world, BlockPos pos, BlockPos pos2) {
MechanicalCrafterTileEntity crafter1 = getCrafter(world, pos);
MechanicalCrafterTileEntity crafter2 = getCrafter(world, pos2);
if (crafter1 == null || crafter2 == null)
return;
BlockPos controllerPos1 = crafter1.getPos().add(crafter1.input.data.get(0));
BlockPos controllerPos2 = crafter2.getPos().add(crafter2.input.data.get(0));
if (controllerPos1.equals(controllerPos2)) {
MechanicalCrafterTileEntity controller = getCrafter(world, controllerPos1);
Set<BlockPos> positions = controller.input.data.stream().map(l -> controllerPos1.add(l))
.collect(Collectors.toSet());
List<BlockPos> frontier = new LinkedList<>();
List<BlockPos> splitGroup = new ArrayList<>();
frontier.add(pos2);
positions.remove(pos2);
positions.remove(pos);
while (!frontier.isEmpty()) {
BlockPos current = frontier.remove(0);
for (Direction direction : Direction.values()) {
BlockPos next = current.offset(direction);
if (!positions.remove(next))
continue;
splitGroup.add(next);
frontier.add(next);
}
}
initAndAddAll(world, crafter1, positions);
initAndAddAll(world, crafter2, splitGroup);
crafter1.markDirty();
crafter1.connectivityChanged();
crafter2.markDirty();
crafter2.connectivityChanged();
return;
}
if (!crafter1.input.isController)
crafter1 = getCrafter(world, controllerPos1);
if (!crafter2.input.isController)
crafter2 = getCrafter(world, controllerPos2);
if (crafter1 == null || crafter2 == null)
return;
connectControllers(world, crafter1, crafter2);
world.setBlockState(crafter1.getPos(), crafter1.getBlockState(), 3);
crafter1.markDirty();
crafter1.connectivityChanged();
crafter2.markDirty();
crafter2.connectivityChanged();
}
public static void initAndAddAll(World world, MechanicalCrafterTileEntity crafter, Collection<BlockPos> positions) {
crafter.input = new ConnectedInput();
positions.forEach(splitPos -> {
modifyAndUpdate(world, splitPos, input -> {
input.attachTo(crafter.getPos(), splitPos);
crafter.input.data.add(splitPos.subtract(crafter.getPos()));
});
});
}
public static void connectControllers(World world, MechanicalCrafterTileEntity crafter1,
MechanicalCrafterTileEntity crafter2) {
crafter1.input.data.forEach(offset -> {
BlockPos connectedPos = crafter1.getPos().add(offset);
modifyAndUpdate(world, connectedPos, input -> {
});
});
crafter2.input.data.forEach(offset -> {
if (offset.equals(BlockPos.ZERO))
return;
BlockPos connectedPos = crafter2.getPos().add(offset);
modifyAndUpdate(world, connectedPos, input -> {
input.attachTo(crafter1.getPos(), connectedPos);
crafter1.input.data.add(BlockPos.ZERO.subtract(input.data.get(0)));
});
});
crafter2.input.attachTo(crafter1.getPos(), crafter2.getPos());
crafter1.input.data.add(BlockPos.ZERO.subtract(crafter2.input.data.get(0)));
}
public static MechanicalCrafterTileEntity getCrafter(IEnviromentBlockReader reader, BlockPos pos) {
TileEntity te = reader.getTileEntity(pos);
if (!(te instanceof MechanicalCrafterTileEntity))
return null;
return (MechanicalCrafterTileEntity) te;
}
public static ConnectedInput getInput(IEnviromentBlockReader reader, BlockPos pos) {
MechanicalCrafterTileEntity crafter = getCrafter(reader, pos);
return crafter == null ? null : crafter.input;
}
private static void modifyAndUpdate(World world, BlockPos pos, Consumer<ConnectedInput> callback) {
TileEntity te = world.getTileEntity(pos);
if (!(te instanceof MechanicalCrafterTileEntity))
return;
MechanicalCrafterTileEntity crafter = (MechanicalCrafterTileEntity) te;
callback.accept(crafter.input);
crafter.markDirty();
crafter.connectivityChanged();
}
public static class ConnectedInput {
boolean isController;
List<BlockPos> data = new ArrayList<>();
public ConnectedInput() {
isController = true;
data.add(BlockPos.ZERO);
}
public void attachTo(BlockPos controllerPos, BlockPos myPos) {
isController = false;
data.clear();
data.add(controllerPos.subtract(myPos));
}
public IItemHandler getItemHandler(World world, BlockPos pos) {
if (!isController) {
BlockPos controllerPos = pos.add(data.get(0));
ConnectedInput input = getInput(world, controllerPos);
if (input == this || input == null || !input.isController)
return new ItemStackHandler();
return input.getItemHandler(world, controllerPos);
}
List<IItemHandlerModifiable> list = data.stream().map(l -> getCrafter(world, pos.add(l)))
.filter(Predicates.notNull()).map(crafter -> crafter.inventory).collect(Collectors.toList());
return new CombinedInvWrapper(Arrays.copyOf(list.toArray(), list.size(), IItemHandlerModifiable[].class));
}
public void write(CompoundNBT nbt) {
nbt.putBoolean("Controller", isController);
ListNBT list = new ListNBT();
data.forEach(pos -> list.add(NBTUtil.writeBlockPos(pos)));
nbt.put("Data", list);
}
public void read(CompoundNBT nbt) {
isController = nbt.getBoolean("Controller");
data.clear();
nbt.getList("Data", NBT.TAG_COMPOUND).forEach(inbt -> data.add(NBTUtil.readBlockPos((CompoundNBT) inbt)));
}
}
}

View file

@ -0,0 +1,84 @@
package com.simibubi.create.modules.contraptions.components.crafter;
import org.apache.commons.lang3.tuple.Pair;
import com.mojang.blaze3d.platform.GlStateManager;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllItems;
import com.simibubi.create.foundation.behaviour.ValueBox;
import com.simibubi.create.foundation.behaviour.ValueBoxRenderer;
import com.simibubi.create.foundation.utility.AngleHelper;
import com.simibubi.create.foundation.utility.GlHelper;
import com.simibubi.create.foundation.utility.TessellatorHelper;
import net.minecraft.block.BlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Direction;
import net.minecraft.util.Hand;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.math.RayTraceResult.Type;
import net.minecraft.util.math.Vec3d;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.client.event.DrawBlockHighlightEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
@EventBusSubscriber(value = Dist.CLIENT)
public class ConnectedInputRenderer {
@SubscribeEvent
public static void renderBlockHighlight(DrawBlockHighlightEvent event) {
RayTraceResult target = event.getTarget();
if (!(target instanceof BlockRayTraceResult))
return;
BlockRayTraceResult result = (BlockRayTraceResult) target;
ClientWorld world = Minecraft.getInstance().world;
BlockPos pos = result.getPos();
BlockState blockState = world.getBlockState(pos);
PlayerEntity player = Minecraft.getInstance().player;
ItemStack heldItem = player.getHeldItem(Hand.MAIN_HAND);
Direction face = result.getFace();
if (player.isSneaking())
return;
if (!AllItems.WRENCH.typeOf(heldItem))
return;
if (!AllBlocks.MECHANICAL_CRAFTER.typeOf(blockState))
return;
if (target.getType() != Type.BLOCK)
return;
if (face == blockState.get(MechanicalCrafterBlock.HORIZONTAL_FACING))
return;
TessellatorHelper.prepareForDrawing();
GlStateManager.translated(pos.getX(), pos.getY(), pos.getZ());
Direction activatedDirection = ConnectedInputHandler.getActivatedDirection(world, pos, face,
result.getHitVec());
for (Pair<Direction, Vec3d> pair : ConnectedInputHandler.getConnectiveSides(world, pos, face)) {
int zRot = face == Direction.UP ? 90 : face == Direction.DOWN ? 270 : 0;
float yRot = AngleHelper.horizontalAngle(face.getOpposite());
Vec3d rotation = new Vec3d(0, yRot, zRot);
GlHelper.renderTransformed(pair.getValue(), rotation, .5f, () -> {
String label = "Connect / Disconnect";// Lang.translate("crafter.connect");
AxisAlignedBB bb = new AxisAlignedBB(Vec3d.ZERO, Vec3d.ZERO).grow(1/3f);
ValueBox box = new ValueBox(label, bb);
box.withColors(0x018383, 0x42e6a4).offsetLabel(new Vec3d(10, 0, 0));
ValueBoxRenderer.renderBox(box, activatedDirection == pair.getKey());
});
}
TessellatorHelper.cleanUpAfterDrawing();
}
}

View file

@ -0,0 +1,73 @@
package com.simibubi.create.modules.contraptions.components.crafter;
import static com.simibubi.create.modules.contraptions.base.HorizontalKineticBlock.HORIZONTAL_FACING;
import java.util.Arrays;
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.ConnectedTextureBehaviour;
import com.simibubi.create.modules.contraptions.components.crafter.ConnectedInputHandler.ConnectedInput;
import net.minecraft.block.BlockState;
import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.Direction.AxisDirection;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IEnviromentBlockReader;
public class InputCTBehaviour extends ConnectedTextureBehaviour {
static final CTSpriteShiftEntry front = CTSpriteShifter.get(CTType.OMNIDIRECTIONAL, "crafter_top", "brass_casing");
static final CTSpriteShiftEntry side = CTSpriteShifter.get(CTType.VERTICAL, "crafter_side");
static final CTSpriteShiftEntry otherSide = CTSpriteShifter.get(CTType.HORIZONTAL, "crafter_side");
@Override
public boolean connectsTo(BlockState state, BlockState other, IEnviromentBlockReader reader, BlockPos pos,
BlockPos otherPos, Direction face) {
if (state.getBlock() != other.getBlock())
return false;
if (state.get(HORIZONTAL_FACING) != other.get(HORIZONTAL_FACING))
return false;
ConnectedInput input1 = ConnectedInputHandler.getInput(reader, pos);
ConnectedInput input2 = ConnectedInputHandler.getInput(reader, otherPos);
if (input1 == null || input2 == null)
return false;
if (pos.add(input1.data.get(0)).equals(otherPos.add(input2.data.get(0))))
return true;
return false;
}
@Override
protected boolean shouldFlipUVs(BlockState state, Direction direction) {
if (!direction.getAxis().isVertical())
return false;
Direction facing = state.get(HORIZONTAL_FACING);
if (facing.getAxis() == direction.getAxis())
return false;
boolean isNegative = facing.getAxisDirection() == AxisDirection.NEGATIVE;
if (direction == Direction.DOWN && facing.getAxis() == Axis.Z)
return !isNegative;
return isNegative;
}
@Override
public CTSpriteShiftEntry get(BlockState state, Direction direction) {
Direction facing = state.get(HORIZONTAL_FACING);
boolean isFront = facing.getAxis() == direction.getAxis();
boolean isVertical = direction.getAxis().isVertical();
boolean facingX = facing.getAxis() == Axis.X;
return isFront ? front : isVertical && !facingX ? otherSide : side;
}
@Override
public Iterable<CTSpriteShiftEntry> getAllCTShifts() {
return Arrays.asList(front, side);
}
}

View file

@ -1,24 +1,52 @@
package com.simibubi.create.modules.contraptions.components.crafter;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.foundation.block.IWithTileEntity;
import com.simibubi.create.modules.contraptions.base.DirectionalKineticBlock;
import com.simibubi.create.foundation.block.connected.ConnectedTextureBehaviour;
import com.simibubi.create.foundation.block.connected.IHaveConnectedTextures;
import com.simibubi.create.foundation.utility.AngleHelper;
import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.modules.contraptions.base.HorizontalKineticBlock;
import com.simibubi.create.modules.contraptions.components.crafter.ConnectedInputHandler.ConnectedInput;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.BlockItemUseContext;
import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemUseContext;
import net.minecraft.state.EnumProperty;
import net.minecraft.state.StateContainer.Builder;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.ActionResultType;
import net.minecraft.util.BlockRenderLayer;
import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.Direction.AxisDirection;
import net.minecraft.util.Hand;
import net.minecraft.util.IStringSerializable;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.IBlockReader;
import net.minecraft.world.World;
import net.minecraftforge.items.ItemHandlerHelper;
public class MechanicalCrafterBlock extends DirectionalKineticBlock
implements IWithTileEntity<MechanicalCrafterTileEntity> {
public class MechanicalCrafterBlock extends HorizontalKineticBlock
implements IWithTileEntity<MechanicalCrafterTileEntity>, IHaveConnectedTextures {
public static final EnumProperty<Pointing> POINTING = EnumProperty.create("pointing", Pointing.class);
public MechanicalCrafterBlock() {
super(Properties.from(Blocks.GOLD_BLOCK));
setDefaultState(getDefaultState().with(POINTING, Pointing.UP));
}
@Override
protected void fillStateContainer(Builder<Block, BlockState> builder) {
super.fillStateContainer(builder.add(POINTING));
}
@Override
@ -33,21 +61,106 @@ public class MechanicalCrafterBlock extends DirectionalKineticBlock
@Override
public boolean hasCogsTowards(World world, BlockPos pos, BlockState state, Direction face) {
return state.get(FACING).getAxis() != face.getAxis();
return state.get(HORIZONTAL_FACING).getAxis() != face.getAxis();
}
@Override
public Axis getRotationAxis(BlockState state) {
return state.get(FACING).getAxis();
return state.get(HORIZONTAL_FACING).getAxis();
}
@Override
public BlockState getStateForPlacement(BlockItemUseContext context) {
BlockPos placedOnPos = context.getPos().offset(context.getFace().getOpposite());
Direction face = context.getFace();
BlockPos placedOnPos = context.getPos().offset(face.getOpposite());
BlockState blockState = context.getWorld().getBlockState(placedOnPos);
if ((blockState.getBlock() == this) && !context.isPlacerSneaking())
return getDefaultState().with(FACING, blockState.get(FACING));
return super.getStateForPlacement(context);
if ((blockState.getBlock() != this) || context.isPlacerSneaking()) {
BlockState stateForPlacement = super.getStateForPlacement(context);
Direction direction = stateForPlacement.get(HORIZONTAL_FACING);
if (direction != face)
stateForPlacement = stateForPlacement.with(POINTING, pointingFromFacing(face, direction));
return stateForPlacement;
}
Direction otherFacing = blockState.get(HORIZONTAL_FACING);
Pointing pointing = pointingFromFacing(face, otherFacing);
return getDefaultState().with(HORIZONTAL_FACING, otherFacing).with(POINTING, pointing);
}
@Override
public void onReplaced(BlockState state, World worldIn, BlockPos pos, BlockState newState, boolean isMoving) {
if (state.hasTileEntity() && state.getBlock() != newState.getBlock()) {
for (Direction direction : Direction.values()) {
if (direction.getAxis() == state.get(HORIZONTAL_FACING).getAxis())
continue;
BlockPos otherPos = pos.offset(direction);
ConnectedInput thisInput = ConnectedInputHandler.getInput(worldIn, pos);
ConnectedInput otherInput = ConnectedInputHandler.getInput(worldIn, otherPos);
if (thisInput == null || otherInput == null)
continue;
if (!pos.add(thisInput.data.get(0)).equals(otherPos.add(otherInput.data.get(0))))
continue;
ConnectedInputHandler.toggleConnection(worldIn, pos, otherPos);
}
worldIn.removeTileEntity(pos);
}
}
public static Pointing pointingFromFacing(Direction pointingFace, Direction blockFacing) {
boolean positive = blockFacing.getAxisDirection() == AxisDirection.POSITIVE;
Pointing pointing = pointingFace == Direction.DOWN ? Pointing.UP : Pointing.DOWN;
if (pointingFace == Direction.EAST)
pointing = positive ? Pointing.LEFT : Pointing.RIGHT;
if (pointingFace == Direction.WEST)
pointing = positive ? Pointing.RIGHT : Pointing.LEFT;
if (pointingFace == Direction.NORTH)
pointing = positive ? Pointing.LEFT : Pointing.RIGHT;
if (pointingFace == Direction.SOUTH)
pointing = positive ? Pointing.RIGHT : Pointing.LEFT;
return pointing;
}
@Override
public ActionResultType onWrenched(BlockState state, ItemUseContext context) {
if (context.getFace() == state.get(HORIZONTAL_FACING)) {
context.getWorld().setBlockState(context.getPos(), state.cycle(POINTING));
return ActionResultType.SUCCESS;
}
return super.onWrenched(state, context);
}
@Override
public boolean onBlockActivated(BlockState state, World worldIn, BlockPos pos, PlayerEntity player, Hand handIn,
BlockRayTraceResult hit) {
ItemStack heldItem = player.getHeldItem(handIn);
boolean isHand = heldItem.isEmpty() && handIn == Hand.MAIN_HAND;
TileEntity te = worldIn.getTileEntity(pos);
if (!(te instanceof MechanicalCrafterTileEntity))
return false;
MechanicalCrafterTileEntity crafter = (MechanicalCrafterTileEntity) te;
if (hit.getFace() == state.get(HORIZONTAL_FACING)) {
ItemStack inSlot = crafter.inventory.getStackInSlot(0);
if (inSlot.isEmpty())
return false;
if (!isHand && !ItemHandlerHelper.canItemStacksStack(heldItem, inSlot))
return false;
if (worldIn.isRemote)
return true;
player.inventory.placeItemBackInInventory(worldIn, inSlot);
crafter.inventory.setStackInSlot(0, ItemStack.EMPTY);
return true;
}
return false;
}
@Override
@ -65,4 +178,50 @@ public class MechanicalCrafterBlock extends DirectionalKineticBlock
return .75f;
}
public static Direction getTargetDirection(BlockState state) {
Direction facing = state.get(HORIZONTAL_FACING);
Pointing point = state.get(POINTING);
Vec3d targetVec = new Vec3d(0, 1, 0);
targetVec = VecHelper.rotate(targetVec, -point.getXRotation(), Axis.Z);
targetVec = VecHelper.rotate(targetVec, AngleHelper.horizontalAngle(facing), Axis.Y);
return Direction.getFacingFromVector(targetVec.x, targetVec.y, targetVec.z);
}
public static boolean isValidTarget(World world, BlockPos targetPos, BlockState crafterState) {
BlockState targetState = world.getBlockState(targetPos);
if (!world.isBlockPresent(targetPos))
return false;
if (!AllBlocks.MECHANICAL_CRAFTER.typeOf(targetState))
return false;
if (crafterState.get(HORIZONTAL_FACING) != targetState.get(HORIZONTAL_FACING))
return false;
if (Math.abs(crafterState.get(POINTING).xRotation - targetState.get(POINTING).xRotation) == 180)
return false;
return true;
}
public enum Pointing implements IStringSerializable {
UP(0), LEFT(270), DOWN(180), RIGHT(90);
private int xRotation;
private Pointing(int xRotation) {
this.xRotation = xRotation;
}
@Override
public String getName() {
return Lang.asId(name());
}
public int getXRotation() {
return xRotation;
}
}
@Override
public ConnectedTextureBehaviour getBehaviour() {
return new InputCTBehaviour();
}
}

View file

@ -2,16 +2,107 @@ package com.simibubi.create.modules.contraptions.components.crafter;
import com.simibubi.create.AllTileEntities;
import com.simibubi.create.modules.contraptions.base.KineticTileEntity;
import com.simibubi.create.modules.contraptions.components.crafter.ConnectedInputHandler.ConnectedInput;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.util.Direction;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.ItemStackHandler;
public class MechanicalCrafterTileEntity extends KineticTileEntity {
enum Phase {
IDLE, ACCEPTING, ASSEMBLING, EXPORTING
}
protected ItemStackHandler inventory = new ItemStackHandler(1) {
@Override
public int getSlotLimit(int slot) {
return 1;
}
public ItemStack extractItem(int slot, int amount, boolean simulate) {
return ItemStack.EMPTY;
};
protected void onContentsChanged(int slot) {
markDirty();
sendData();
};
};
protected ConnectedInput input = new ConnectedInput();
protected LazyOptional<IItemHandler> invSupplier = LazyOptional.of(() -> input.getItemHandler(world, pos));
protected boolean reRender;
public MechanicalCrafterTileEntity() {
super(AllTileEntities.MECHANICAL_CRAFTER.type);
}
@Override
public boolean hasFastRenderer() {
return false;
}
@Override
public CompoundNBT write(CompoundNBT compound) {
compound.put("Inventory", inventory.serializeNBT());
CompoundNBT inputNBT = new CompoundNBT();
input.write(inputNBT);
compound.put("ConnectedInput", inputNBT);
return super.write(compound);
}
@Override
public CompoundNBT writeToClient(CompoundNBT tag) {
if (reRender) {
tag.putBoolean("Redraw", true);
reRender = false;
}
return super.writeToClient(tag);
}
@Override
public void readClientUpdate(CompoundNBT tag) {
if (tag.contains("Redraw"))
world.notifyBlockUpdate(getPos(), getBlockState(), getBlockState(), 16);
super.readClientUpdate(tag);
}
@Override
public void read(CompoundNBT compound) {
inventory.deserializeNBT(compound.getCompound("Inventory"));
input.read(compound.getCompound("ConnectedInput"));
super.read(compound);
}
@Override
public void remove() {
invSupplier.invalidate();
super.remove();
}
@Override
public <T> LazyOptional<T> getCapability(Capability<T> cap, Direction side) {
if (cap == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) {
if (getBlockState().get(MechanicalCrafterBlock.HORIZONTAL_FACING) == side)
return LazyOptional.empty();
return invSupplier.cast();
}
return super.getCapability(cap, side);
}
public void connectivityChanged() {
reRender = true;
sendData();
invSupplier.invalidate();
invSupplier = LazyOptional.of(() -> input.getItemHandler(world, pos));
}
}

View file

@ -1,35 +1,100 @@
package com.simibubi.create.modules.contraptions.components.crafter;
import com.mojang.blaze3d.platform.GlStateManager;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.CreateClient;
import com.simibubi.create.foundation.utility.AngleHelper;
import com.simibubi.create.foundation.utility.SuperByteBuffer;
import com.simibubi.create.foundation.utility.TessellatorHelper;
import com.simibubi.create.modules.contraptions.base.KineticTileEntityRenderer;
import net.minecraft.block.BlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.RenderHelper;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.model.ItemCameraTransforms.TransformType;
import net.minecraft.client.renderer.tileentity.TileEntityRenderer;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.item.ItemStack;
import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
@SuppressWarnings("deprecation")
public class MechanicalCrafterTileEntityRenderer extends TileEntityRenderer<MechanicalCrafterTileEntity> {
@Override
public void render(MechanicalCrafterTileEntity tileEntityIn, double x, double y, double z, float partialTicks,
public void render(MechanicalCrafterTileEntity te, double x, double y, double z, float partialTicks,
int destroyStage) {
super.render(tileEntityIn, x, y, z, partialTicks, destroyStage);
super.render(te, x, y, z, partialTicks, destroyStage);
if (!AllBlocks.MECHANICAL_CRAFTER.typeOf(te.getBlockState()))
return;
GlStateManager.pushMatrix();
Direction facing = te.getBlockState().get(MechanicalCrafterBlock.HORIZONTAL_FACING);
Vec3d vec = new Vec3d(facing.getDirectionVec()).scale(.58).add(.5, .5, .5);
GlStateManager.translated(x + vec.x, y + vec.y, z + vec.z);
GlStateManager.scalef(1 / 2f, 1 / 2f, 1 / 2f);
float yRot = AngleHelper.horizontalAngle(facing);
GlStateManager.rotated(yRot, 0, 1, 0);
renderItems(te);
GlStateManager.popMatrix();
TessellatorHelper.prepareFastRender();
TessellatorHelper.begin(DefaultVertexFormats.BLOCK);
renderTileEntityFast(tileEntityIn, x, y, z, partialTicks, destroyStage, Tessellator.getInstance().getBuffer());
renderTileEntityFast(te, x, y, z, partialTicks, destroyStage, Tessellator.getInstance().getBuffer());
TessellatorHelper.draw();
}
public void renderItems(MechanicalCrafterTileEntity te) {
RenderHelper.enableStandardItemLighting();
ItemStack stack = te.inventory.getStackInSlot(0);
if (!stack.isEmpty())
Minecraft.getInstance().getItemRenderer().renderItem(stack, TransformType.FIXED);
RenderHelper.disableStandardItemLighting();
}
@Override
public void renderTileEntityFast(MechanicalCrafterTileEntity te, double x, double y, double z, float partialTicks,
int destroyStage, BufferBuilder buffer) {
BlockState blockState = te.getBlockState();
BlockState renderedState = AllBlocks.SHAFTLESS_COGWHEEL.get().getDefaultState().with(BlockStateProperties.AXIS,
te.getBlockState().get(BlockStateProperties.FACING).getAxis());
blockState.get(MechanicalCrafterBlock.HORIZONTAL_FACING).getAxis());
KineticTileEntityRenderer.renderRotatingKineticBlock(te, getWorld(), renderedState, x, y, z, buffer);
Direction targetDirection = MechanicalCrafterBlock.getTargetDirection(blockState);
BlockPos pos = te.getPos();
// SuperByteBuffer lidBuffer = renderAndTransform(AllBlocks.MECHANICAL_CRAFTER_LID, blockState, pos);
// lidBuffer.translate(x, y, z).renderInto(buffer);
if (MechanicalCrafterBlock.isValidTarget(getWorld(), pos.offset(targetDirection), blockState)) {
SuperByteBuffer beltBuffer = renderAndTransform(AllBlocks.MECHANICAL_CRAFTER_BELT, blockState, pos);
SuperByteBuffer beltFrameBuffer = renderAndTransform(AllBlocks.MECHANICAL_CRAFTER_BELT_FRAME, blockState,
pos);
beltBuffer.translate(x, y, z).renderInto(buffer);
beltFrameBuffer.translate(x, y, z).renderInto(buffer);
} else {
SuperByteBuffer arrowBuffer = renderAndTransform(AllBlocks.MECHANICAL_CRAFTER_ARROW, blockState, pos);
arrowBuffer.translate(x, y, z).renderInto(buffer);
}
}
private SuperByteBuffer renderAndTransform(AllBlocks renderBlock, BlockState crafterState, BlockPos pos) {
SuperByteBuffer buffer = CreateClient.bufferCache.renderGenericBlockModel(renderBlock.getDefault());
float xRot = crafterState.get(MechanicalCrafterBlock.POINTING).getXRotation();
float yRot = AngleHelper.horizontalAngle(crafterState.get(MechanicalCrafterBlock.HORIZONTAL_FACING));
buffer.rotateCentered(Axis.X, (float) ((xRot) / 180 * Math.PI));
buffer.rotateCentered(Axis.Y, (float) ((yRot + 90) / 180 * Math.PI));
buffer.light(crafterState.getPackedLightmapCoords(getWorld(), pos));
return buffer;
}
}

View file

@ -4,13 +4,17 @@
"model": "create:block/crafter/casing"
},
"variants": {
"pointing": {
"up": {},
"left": {},
"down": {},
"right": {}
},
"facing": {
"north": { "x": 90 },
"south": { "x": 90, "y": 180 },
"west": { "x": 90, "y": 270 },
"up": { },
"down": { "x": 180 },
"east": { "x": 90, "y": 90 }
"north": { "y": 90 },
"south": { "y": 270 },
"west": { "y": 0 },
"east": { "y": 180 }
}
}
}

View file

@ -1,16 +1,5 @@
{
"forge_marker": 1,
"defaults": {
"model": "create:block/crafter/arrow"
},
"variants": {
"facing": {
"north": { "y": 180 },
"south": { },
"west": { "y": 90 },
"up": { "x": 90 },
"down": { "x": 270 },
"east": { "y": 270 }
}
}
"variants": {
"": { "model": "create:block/crafter/arrow" }
}
}

View file

@ -1,16 +1,5 @@
{
"forge_marker": 1,
"defaults": {
"model": "create:block/crafter/belt_animated"
},
"variants": {
"facing": {
"north": { "y": 180 },
"south": { },
"west": { "y": 90 },
"up": { "x": 90 },
"down": { "x": 270 },
"east": { "y": 270 }
}
}
"variants": {
"": { "model": "create:block/crafter/belt_animated" }
}
}

View file

@ -1,16 +1,5 @@
{
"forge_marker": 1,
"defaults": {
"model": "create:block/crafter/belt"
},
"variants": {
"facing": {
"north": { "y": 180 },
"south": { },
"west": { "y": 90 },
"up": { "x": 90 },
"down": { "x": 270 },
"east": { "y": 270 }
}
}
"variants": {
"": { "model": "create:block/crafter/belt" }
}
}

View file

@ -1,16 +1,5 @@
{
"forge_marker": 1,
"defaults": {
"model": "create:block/crafter/lid"
},
"variants": {
"facing": {
"north": { "y": 180 },
"south": { },
"west": { "y": 90 },
"up": { "x": 90 },
"down": { "x": 270 },
"east": { "y": 270 }
}
}
"variants": {
"": { "model": "create:block/crafter/lid" }
}
}

View file

@ -7,36 +7,36 @@
"elements": [
{
"name": "arrow",
"from": [5, 16, 12],
"to": [11, 17, 14],
"from": [-1, 12, 5],
"to": [0, 14, 11],
"faces": {
"north": {"uv": [12, 0, 13, 6], "rotation": 90, "texture": "#3"},
"east": {"uv": [12, 0, 14, 1], "rotation": 180, "texture": "#3"},
"south": {"uv": [13, 0, 14, 6], "rotation": 90, "texture": "#3"},
"west": {"uv": [12, 5, 14, 6], "texture": "#3"},
"up": {"uv": [12, 0, 14, 6], "rotation": 90, "texture": "#3"}
"north": {"uv": [12, 0, 14, 1], "rotation": 270, "texture": "#3"},
"south": {"uv": [12, 5, 14, 6], "rotation": 270, "texture": "#3"},
"west": {"uv": [12, 0, 14, 6], "rotation": 270, "texture": "#3"},
"up": {"uv": [13, 0, 14, 6], "texture": "#3"},
"down": {"uv": [12, 0, 13, 6], "texture": "#3"}
}
},
{
"name": "arrow",
"from": [6, 16, 14],
"to": [10, 17, 15],
"from": [-1, 14, 6],
"to": [0, 15, 10],
"faces": {
"east": {"uv": [14, 1, 15, 2], "rotation": 180, "texture": "#3"},
"south": {"uv": [14, 1, 15, 5], "rotation": 90, "texture": "#3"},
"west": {"uv": [14, 4, 15, 5], "texture": "#3"},
"up": {"uv": [14, 1, 15, 5], "rotation": 90, "texture": "#3"}
"north": {"uv": [14, 1, 15, 2], "rotation": 270, "texture": "#3"},
"south": {"uv": [14, 4, 15, 5], "rotation": 270, "texture": "#3"},
"west": {"uv": [14, 1, 15, 5], "rotation": 270, "texture": "#3"},
"up": {"uv": [14, 1, 15, 5], "texture": "#3"}
}
},
{
"name": "arrow",
"from": [7, 16, 15],
"to": [9, 17, 16],
"from": [-1, 15, 7],
"to": [0, 16, 9],
"faces": {
"east": {"uv": [15, 2, 16, 3], "rotation": 180, "texture": "#3"},
"south": {"uv": [15, 2, 16, 4], "rotation": 90, "texture": "#3"},
"west": {"uv": [15, 3, 16, 4], "texture": "#3"},
"up": {"uv": [15, 2, 16, 4], "rotation": 90, "texture": "#3"}
"north": {"uv": [15, 2, 16, 3], "rotation": 270, "texture": "#3"},
"south": {"uv": [15, 3, 16, 4], "rotation": 270, "texture": "#3"},
"west": {"uv": [15, 2, 16, 4], "rotation": 270, "texture": "#3"},
"up": {"uv": [15, 2, 16, 4], "texture": "#3"}
}
}
]

View file

@ -7,22 +7,20 @@
"elements": [
{
"name": "belt",
"from": [10, 15.5, 12],
"to": [11, 16.5, 20],
"rotation": {"angle": 0, "axis": "y", "origin": [8, 17, 8]},
"from": [-0.5, 12, 5],
"to": [0.5, 20, 6],
"faces": {
"east": {"uv": [2, 4, 3, 12], "rotation": 90, "texture": "#5"},
"up": {"uv": [2, 4, 3, 12], "rotation": 180, "texture": "#5"}
"north": {"uv": [2, 4, 3, 12], "rotation": 180, "texture": "#5"},
"west": {"uv": [2, 4, 3, 12], "texture": "#5"}
}
},
{
"name": "belt",
"from": [5, 15.5, 12],
"to": [6, 16.5, 20],
"rotation": {"angle": 0, "axis": "y", "origin": [8, 17, 8]},
"from": [-0.5, 12, 10],
"to": [0.5, 20, 11],
"faces": {
"west": {"uv": [2, 4, 3, 12], "rotation": 90, "texture": "#5"},
"up": {"uv": [13, 4, 14, 12], "rotation": 180, "texture": "#5"}
"south": {"uv": [2, 4, 3, 12], "texture": "#5"},
"west": {"uv": [13, 4, 14, 12], "texture": "#5"}
}
}
]

View file

@ -7,11 +7,10 @@
"elements": [
{
"name": "belt_animated",
"from": [6, 15.5, 12],
"to": [10, 16.5, 20],
"rotation": {"angle": 0, "axis": "y", "origin": [8, 17, 8]},
"from": [-0.5, 12, 6],
"to": [0.5, 20, 10],
"faces": {
"up": {"uv": [0, 6, 4, 14], "rotation": 180, "texture": "#3"}
"west": {"uv": [0, 6, 4, 14], "texture": "#3"}
}
}
]

View file

@ -12,124 +12,120 @@
"elements": [
{
"name": "Top",
"from": [0, 10, 0],
"to": [16, 16, 16],
"from": [0, 0, 0],
"to": [6, 16, 16],
"faces": {
"north": {"uv": [0, 0, 16, 6], "texture": "#4"},
"east": {"uv": [0, 0, 16, 6], "texture": "#4"},
"south": {"uv": [0, 0, 16, 6], "texture": "#4"},
"west": {"uv": [0, 0, 16, 6], "texture": "#4"},
"up": {"uv": [0, 0, 2, 2], "rotation": 270, "texture": "#6"},
"down": {"uv": [0, 0, 16, 16], "rotation": 90, "texture": "#7"}
"north": {"uv": [0, 0, 16, 6], "rotation": 90, "texture": "#4"},
"east": {"uv": [0, 0, 16, 16], "texture": "#7"},
"south": {"uv": [16, 0, 0, 6], "rotation": 270, "texture": "#4"},
"west": {"uv": [0, 0, 16, 16], "texture": "#6"},
"up": {"uv": [0, 0, 16, 6], "rotation": 270, "texture": "#4"},
"down": {"uv": [0, 0, 16, 6], "rotation": 270, "texture": "#4"}
}
},
{
"name": "Bottom",
"from": [0, 0, 0],
"to": [16, 6, 16],
"from": [10, 0, 0],
"to": [16, 16, 16],
"faces": {
"north": {"uv": [0, 10, 16, 16], "texture": "#4"},
"east": {"uv": [0, 10, 16, 16], "texture": "#4"},
"south": {"uv": [0, 10, 16, 16], "texture": "#4"},
"west": {"uv": [0, 10, 16, 16], "texture": "#4"},
"up": {"uv": [0, 0, 16, 16], "texture": "#5"},
"down": {"uv": [0, 0, 2, 2], "texture": "#6"}
"north": {"uv": [0, 10, 16, 16], "rotation": 90, "texture": "#4"},
"east": {"uv": [0, 0, 16, 16], "texture": "#6"},
"south": {"uv": [16, 10, 0, 16], "rotation": 270, "texture": "#4"},
"west": {"uv": [0, 0, 16, 16], "rotation": 270, "texture": "#5"},
"up": {"uv": [0, 10, 16, 16], "rotation": 270, "texture": "#4"},
"down": {"uv": [0, 10, 16, 16], "rotation": 270, "texture": "#4"}
}
},
{
"name": "Side1",
"from": [16, 6, 0],
"to": [16, 10, 16],
"rotation": {"angle": 0, "axis": "y", "origin": [24, 8, 8]},
"from": [6, 15.9, 0],
"to": [10, 16, 16],
"faces": {
"east": {"uv": [0, 6, 16, 10], "texture": "#4"},
"west": {"uv": [0, 6, 16, 10], "texture": "#4"}
"up": {"uv": [0, 6, 16, 10], "rotation": 270, "texture": "#4"},
"down": {"uv": [0, 6, 16, 10], "rotation": 270, "texture": "#4"}
}
},
{
"name": "Side2",
"from": [0, 6, 0],
"to": [0, 10, 16],
"rotation": {"angle": 0, "axis": "y", "origin": [-8, 8, 8]},
"from": [6, 0, 0],
"to": [10, 0.1, 16],
"faces": {
"east": {"uv": [0, 6, 16, 10], "texture": "#4"},
"west": {"uv": [0, 6, 16, 10], "texture": "#4"}
"up": {"uv": [0, 6, 16, 10], "rotation": 270, "texture": "#4"},
"down": {"uv": [0, 6, 16, 10], "rotation": 270, "texture": "#4"}
}
},
{
"name": "Side3",
"from": [0, 6, 0],
"to": [16, 10, 0],
"rotation": {"angle": 0, "axis": "y", "origin": [8, 8, -8]},
"from": [6, 0, 0],
"to": [10, 16, 0.1],
"faces": {
"north": {"uv": [0, 6, 16, 10], "texture": "#4"},
"south": {"uv": [0, 6, 16, 10], "texture": "#4"}
"north": {"uv": [0, 6, 16, 10], "rotation": 90, "texture": "#4"},
"south": {"uv": [0, 6, 16, 10], "rotation": 270, "texture": "#4"}
}
},
{
"name": "Side4",
"from": [0, 6, 16],
"to": [16, 10, 16],
"rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 24]},
"from": [6, 0, 15.9],
"to": [10, 16, 16],
"faces": {
"north": {"uv": [0, 6, 16, 10], "texture": "#4"},
"south": {"uv": [0, 6, 16, 10], "texture": "#4"}
"north": {"uv": [0, 6, 16, 10], "rotation": 90, "texture": "#4"},
"south": {"uv": [16, 6, 0, 10], "rotation": 270, "texture": "#4"}
}
},
{
"name": "valve_case",
"from": [4, 16, 4],
"to": [5, 17, 12],
"from": [-1, 4, 4],
"to": [0, 5, 12],
"faces": {
"north": {"uv": [8, 2, 9, 3], "texture": "#5"},
"east": {"uv": [4, 2, 12, 3], "texture": "#5"},
"south": {"uv": [7, 2, 8, 3], "texture": "#5"},
"west": {"uv": [4, 2, 12, 3], "texture": "#5"},
"up": {"uv": [2, 4, 3, 12], "texture": "#5"}
"north": {"uv": [8, 2, 9, 3], "rotation": 90, "texture": "#5"},
"south": {"uv": [7, 2, 8, 3], "rotation": 270, "texture": "#5"},
"west": {"uv": [2, 4, 3, 12], "rotation": 270, "texture": "#5"},
"up": {"uv": [4, 2, 12, 3], "rotation": 270, "texture": "#5"},
"down": {"uv": [4, 2, 12, 3], "rotation": 270, "texture": "#5"}
}
},
{
"name": "valve_case",
"from": [11, 16, 4],
"to": [12, 17, 12],
"from": [-1, 11, 4],
"to": [0, 12, 12],
"faces": {
"north": {"uv": [8, 2, 9, 3], "texture": "#5"},
"east": {"uv": [4, 2, 12, 3], "texture": "#5"},
"south": {"uv": [7, 2, 8, 3], "texture": "#5"},
"west": {"uv": [4, 2, 12, 3], "texture": "#5"},
"up": {"uv": [2, 4, 3, 12], "texture": "#5"}
"north": {"uv": [8, 2, 9, 3], "rotation": 90, "texture": "#5"},
"south": {"uv": [7, 2, 8, 3], "rotation": 270, "texture": "#5"},
"west": {"uv": [2, 4, 3, 12], "rotation": 270, "texture": "#5"},
"up": {"uv": [4, 2, 12, 3], "rotation": 270, "texture": "#5"},
"down": {"uv": [4, 2, 12, 3], "rotation": 270, "texture": "#5"}
}
},
{
"name": "valve_case",
"from": [5, 16, 4],
"to": [11, 17, 5],
"from": [-1, 5, 4],
"to": [0, 11, 5],
"faces": {
"north": {"uv": [6, 2, 12, 3], "texture": "#5"},
"east": {"uv": [2, 4, 3, 5], "texture": "#5"},
"south": {"uv": [5, 2, 11, 3], "texture": "#5"},
"west": {"uv": [2, 4, 3, 5], "texture": "#5"},
"up": {"uv": [5, 2, 11, 3], "texture": "#5"}
"north": {"uv": [6, 2, 12, 3], "rotation": 90, "texture": "#5"},
"south": {"uv": [5, 2, 11, 3], "rotation": 270, "texture": "#5"},
"west": {"uv": [5, 2, 11, 3], "rotation": 270, "texture": "#5"},
"up": {"uv": [2, 4, 3, 5], "rotation": 270, "texture": "#5"},
"down": {"uv": [2, 4, 3, 5], "rotation": 270, "texture": "#5"}
}
},
{
"name": "valve_case",
"from": [5, 16, 11],
"to": [11, 17, 12],
"from": [-1, 5, 11],
"to": [0, 11, 12],
"faces": {
"north": {"uv": [6, 2, 12, 3], "texture": "#5"},
"east": {"uv": [2, 4, 3, 5], "texture": "#5"},
"south": {"uv": [5, 2, 11, 3], "texture": "#5"},
"west": {"uv": [2, 4, 3, 5], "texture": "#5"},
"up": {"uv": [5, 2, 11, 3], "texture": "#5"}
"north": {"uv": [6, 2, 12, 3], "rotation": 90, "texture": "#5"},
"south": {"uv": [5, 2, 11, 3], "rotation": 270, "texture": "#5"},
"west": {"uv": [5, 2, 11, 3], "rotation": 270, "texture": "#5"},
"up": {"uv": [2, 4, 3, 5], "rotation": 270, "texture": "#5"},
"down": {"uv": [2, 4, 3, 5], "rotation": 270, "texture": "#5"}
}
},
{
"name": "opening",
"from": [5, 15.5, 5],
"to": [11, 16.5, 11],
"from": [-0.5, 5, 5],
"to": [0.5, 11, 11],
"faces": {
"up": {"uv": [6, 0, 12, 6], "texture": "#3"}
"west": {"uv": [6, 0, 12, 6], "rotation": 270, "texture": "#3"}
}
}
]

View file

@ -9,8 +9,7 @@
"5": "create:block/brass_casing",
"6": "create:block/crafter_top",
"7": "create:block/crafter_topunderside",
"particle": "block/stripped_spruce_log",
"2_3": "create:block/crafter_thingies"
"particle": "block/stripped_spruce_log"
},
"elements": [
{
@ -22,7 +21,7 @@
"east": {"uv": [0, 0, 16, 6], "texture": "#4"},
"south": {"uv": [0, 0, 16, 6], "texture": "#4"},
"west": {"uv": [0, 0, 16, 6], "texture": "#4"},
"up": {"uv": [0, 0, 2, 2], "rotation": 270, "texture": "#6"},
"up": {"uv": [0, 0, 16, 16], "rotation": 270, "texture": "#6"},
"down": {"uv": [0, 0, 16, 16], "rotation": 90, "texture": "#7"}
}
},
@ -36,7 +35,7 @@
"south": {"uv": [0, 10, 16, 16], "texture": "#4"},
"west": {"uv": [0, 10, 16, 16], "texture": "#4"},
"up": {"uv": [0, 0, 16, 16], "texture": "#5"},
"down": {"uv": [0, 0, 2, 2], "texture": "#6"}
"down": {"uv": [0, 0, 16, 16], "texture": "#6"}
}
},
{
@ -224,7 +223,7 @@
"from": [5, 16, 5],
"to": [11, 17, 11],
"faces": {
"up": {"uv": [0, 0, 6, 6], "texture": "#2_3"}
"up": {"uv": [0, 0, 6, 6], "texture": "#3"}
}
}
],

View file

@ -7,10 +7,10 @@
"elements": [
{
"name": "valve_lid",
"from": [5, 16, 5],
"to": [11, 17, 11],
"from": [-1, 5, 5],
"to": [0, 11, 11],
"faces": {
"up": {"uv": [0, 0, 6, 6], "texture": "#3"}
"west": {"uv": [0, 0, 6, 6], "rotation": 270, "texture": "#3"}
}
}
]

View file

@ -3,7 +3,6 @@
"parent": "block/cube",
"ambientocclusion": false,
"textures": {
"1": "block/stripped_spruce_log",
"2": "block/spruce_log_top",
"4": "create:block/mixer_base_side",
"11": "create:block/mechanical_press_top",
@ -39,7 +38,7 @@
{
"name": "Side1",
"from": [0, 6, 0],
"to": [0, 10, 16],
"to": [0.1, 10, 16],
"faces": {
"east": {"uv": [0, 6, 16, 10], "texture": "#4"},
"west": {"uv": [0, 6, 16, 10], "texture": "#4"}
@ -47,7 +46,7 @@
},
{
"name": "Side2",
"from": [16, 6, 0],
"from": [15.9, 6, 0],
"to": [16, 10, 16],
"faces": {
"east": {"uv": [0, 6, 16, 10], "texture": "#4"},
@ -56,7 +55,7 @@
},
{
"name": "Side3",
"from": [0, 6, 16],
"from": [0, 6, 15.9],
"to": [16, 10, 16],
"faces": {
"north": {"uv": [0, 6, 16, 10], "texture": "#4"},
@ -66,7 +65,7 @@
{
"name": "Side4",
"from": [0, 6, 0],
"to": [16, 10, 0],
"to": [16, 10, 0.1],
"faces": {
"north": {"uv": [0, 6, 16, 10], "texture": "#4"},
"south": {"uv": [0, 6, 16, 10], "texture": "#4"}

View file

@ -49,9 +49,7 @@
"to": [13, 1.5, 4],
"faces": {
"north": {"uv": [2, 7, 12, 8], "texture": "#2"},
"east": {"uv": [0, 0, 1, 1], "texture": "#missing"},
"south": {"uv": [3, 7, 13, 8], "texture": "#2"},
"west": {"uv": [0, 0, 1, 1], "texture": "#missing"},
"up": {"uv": [3, 7, 13, 8], "texture": "#2"},
"down": {"uv": [3, 7, 13, 8], "texture": "#2"}
}
@ -62,9 +60,7 @@
"to": [13, 1.5, 13],
"faces": {
"north": {"uv": [13, 7, 3, 8], "texture": "#2"},
"east": {"uv": [1, 0, 0, 1], "texture": "#missing"},
"south": {"uv": [14, 7, 4, 8], "texture": "#2"},
"west": {"uv": [1, 0, 0, 1], "texture": "#missing"},
"up": {"uv": [3, 8, 13, 7], "texture": "#2"},
"down": {"uv": [3, 8, 13, 7], "texture": "#2"}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 841 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 809 B

After

Width:  |  Height:  |  Size: 776 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 464 B

After

Width:  |  Height:  |  Size: 477 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 540 B