Rotated Disassembly & Powered Latch

- Chassis blocks now visualize their range blocks when selected with a wrench
- Fixed Bearings and other actors selecting moved blocks as if they were being pushed in a direction
- Fixed Radial chassis not connecting to each other consistently
- Added Powered Latch and Powered Toggle Latch (Redstone circuits)
- Window-logging now works with modded glass panes, that do not have the tag on their item, but the block only
- Chassis can now be edited in bulk by holding down Ctrl
- Chained block movement no longer marks blocks for movement if they are in front of a block breaker
- Making a chassis sticky no longer uses up slime balls
- Chassis can now be made sticky on all sides if a sticky side is clicked once again
- Fixed linear chassis picking up blocks attached to other chassis' lines, even if not sticky
- Fixed horizontal rotation and mirroring of chassis blocks and their sticky sides
- Structures rotated in a Contraption now try to rotate themselves and their blocks toward the nearest axis-alinged direction when disassembled
- Fans no longer shoot testing rays if the target block shape is completely filled or empty (trivial case)
- Fans can now blow through iron bars again
- Fixed crash when adjusting motors
- Fixed missing icons in blockzapper & schematicannon interface
- Reworked the drill model
- Added more tags to #windowable
- Leather horse armor no longer crushes into iron nuggets
This commit is contained in:
simibubi 2020-02-27 18:09:41 +01:00
parent c7e8698ce8
commit 068b7c0c37
59 changed files with 1970 additions and 665 deletions

View file

@ -61,7 +61,9 @@ import com.simibubi.create.modules.logistics.block.StockswitchBlock;
import com.simibubi.create.modules.logistics.block.belts.BeltObserverBlock;
import com.simibubi.create.modules.logistics.block.belts.FunnelBlock;
import com.simibubi.create.modules.logistics.block.diodes.FlexpeaterBlock;
import com.simibubi.create.modules.logistics.block.diodes.LatchBlock;
import com.simibubi.create.modules.logistics.block.diodes.PulseRepeaterBlock;
import com.simibubi.create.modules.logistics.block.diodes.ToggleLatchBlock;
import com.simibubi.create.modules.logistics.block.extractor.ExtractorBlock;
import com.simibubi.create.modules.logistics.block.extractor.LinkedExtractorBlock;
import com.simibubi.create.modules.logistics.block.inventories.FlexcrateBlock;
@ -184,6 +186,8 @@ public enum AllBlocks {
PULSE_REPEATER(new PulseRepeaterBlock()),
FLEXPEATER(new FlexpeaterBlock()),
FLEXPULSEPEATER(new FlexpeaterBlock()),
REDSTONE_LATCH(new LatchBlock()),
TOGGLE_LATCH(new ToggleLatchBlock()),
__CURIOSITIES__(),
SYMMETRY_PLANE(new PlaneSymmetryBlock()),

View file

@ -11,6 +11,7 @@ import com.simibubi.create.foundation.item.TooltipHelper;
import com.simibubi.create.foundation.utility.AnimationTickHolder;
import com.simibubi.create.modules.contraptions.KineticDebugger;
import com.simibubi.create.modules.contraptions.base.KineticTileEntityRenderer;
import com.simibubi.create.modules.contraptions.components.contraptions.ChassisRangeDisplay;
import com.simibubi.create.modules.contraptions.components.turntable.TurntableHandler;
import com.simibubi.create.modules.contraptions.relays.belt.BeltConnectorItemHandler;
@ -67,6 +68,7 @@ public class ClientEvents {
CreateClient.schematicAndQuillHandler.render();
CreateClient.schematicHologram.render();
KineticDebugger.renderSourceOutline();
ChassisRangeDisplay.renderOutlines(event.getPartialTicks());
}
@SubscribeEvent

View file

@ -11,6 +11,7 @@ import com.simibubi.create.foundation.block.render.SpriteShiftEntry;
import com.simibubi.create.foundation.item.IHaveCustomItemModel;
import com.simibubi.create.foundation.utility.SuperByteBufferCache;
import com.simibubi.create.modules.contraptions.base.KineticTileEntityRenderer;
import com.simibubi.create.modules.contraptions.components.contraptions.ChassisRangeDisplay;
import com.simibubi.create.modules.contraptions.components.contraptions.ContraptionRenderer;
import com.simibubi.create.modules.schematics.ClientSchematicLoader;
import com.simibubi.create.modules.schematics.client.SchematicAndQuillHandler;
@ -81,6 +82,7 @@ public class CreateClient {
schematicAndQuillHandler.tick();
schematicHandler.tick();
schematicHologram.tick();
ChassisRangeDisplay.clientTick();
}
@OnlyIn(Dist.CLIENT)

View file

@ -71,10 +71,12 @@ public class Events {
ItemStack stack = event.getItemStack();
if (stack.isEmpty())
return;
if (!stack.getItem().isIn(Tags.Items.GLASS_PANES))
return;
if (!(stack.getItem() instanceof BlockItem))
return;
BlockItem item = (BlockItem) stack.getItem();
if (!item.isIn(Tags.Items.GLASS_PANES)
&& (item.getBlock() == null || !item.getBlock().isIn(Tags.Blocks.GLASS_PANES)))
return;
BlockPos pos = event.getPos();
World world = event.getWorld();
@ -89,7 +91,7 @@ public class Events {
TileEntity te = world.getTileEntity(pos);
if (te != null && te instanceof WindowInABlockTileEntity) {
WindowInABlockTileEntity wte = (WindowInABlockTileEntity) te;
wte.setWindowBlock(((BlockItem) stack.getItem()).getBlock().getDefaultState());
wte.setWindowBlock(item.getBlock().getDefaultState());
wte.updateWindowConnections();
if (blockState.getBlock() instanceof FourWayBlock) {

View file

@ -124,30 +124,30 @@ public enum ScreenResources {
I_MOVE_NEVER_PLACE(11, 1),
I_DONT_REPLACE(0, 2),
I_REPLACE_SOLID(4, 2),
I_REPLACE_SOLID(1, 2),
I_REPLACE_ANY(2, 2),
I_REPLACE_EMPTY(3, 2),
I_TOOL_DEPLOY(0, 3),
I_SKIP_TILES(2, 3),
I_SKIP_MISSING(4, 3),
I_SKIP_MISSING(1, 3),
I_TOOL_MOVE_XZ(0, 4),
I_TOOL_MOVE_Y(4, 4),
I_TOOL_MOVE_Y(1, 4),
I_TOOL_ROTATE(2, 4),
I_TOOL_MIRROR(3, 4),
I_PLAY(0, 5),
I_PAUSE(4, 5),
I_PAUSE(1, 5),
I_STOP(2, 5),
I_PATTERN_SOLID(0, 6),
I_PATTERN_CHECKERED(4, 6),
I_PATTERN_CHECKERED(1, 6),
I_PATTERN_CHECKERED_INVERSED(2, 6),
I_PATTERN_CHANCE_25(3, 6),
I_PATTERN_CHANCE_50(0, 7),
I_PATTERN_CHANCE_75(4, 7),
I_PATTERN_CHANCE_75(1, 7),
I_FOLLOW_DIAGONAL(2, 7),
I_FOLLOW_MATERIAL(3, 7),

View file

@ -0,0 +1,23 @@
package com.simibubi.create.foundation.behaviour.scrollvalue;
import java.util.List;
import java.util.function.Function;
import com.simibubi.create.foundation.behaviour.ValueBoxTransform;
import com.simibubi.create.foundation.behaviour.base.SmartTileEntity;
public class BulkScrollValueBehaviour extends ScrollValueBehaviour {
Function<SmartTileEntity, List<? extends SmartTileEntity>> groupGetter;
public BulkScrollValueBehaviour(String label, SmartTileEntity te, ValueBoxTransform slot,
Function<SmartTileEntity, List<? extends SmartTileEntity>> groupGetter) {
super(label, te, slot);
this.groupGetter = groupGetter;
}
List<? extends SmartTileEntity> getBulk() {
return groupGetter.apply(tileEntity);
}
}

View file

@ -26,11 +26,12 @@ public class ScrollValueBehaviour extends TileEntityBehaviour {
int min = 0;
int max = 1;
public int value;
int scrollableValue;
public int scrollableValue;
int ticksUntilScrollPacket;
boolean forceClientState;
String label;
Consumer<Integer> callback;
Consumer<Integer> clientCallback;
Function<Integer, String> formatter;
Function<Integer, String> unit;
BiFunction<Integer, Boolean, Integer> step;
@ -42,6 +43,8 @@ public class ScrollValueBehaviour extends TileEntityBehaviour {
slotPositioning = slot;
callback = i -> {
};
clientCallback = i -> {
};
textShift = Vec3d.ZERO;
formatter = i -> Integer.toString(i);
step = (i, b) -> 1;
@ -91,6 +94,11 @@ public class ScrollValueBehaviour extends TileEntityBehaviour {
ticksUntilScrollPacket = -1;
}
public ScrollValueBehaviour withClientCallback(Consumer<Integer> valueCallback) {
clientCallback = valueCallback;
return this;
}
public ScrollValueBehaviour withCallback(Consumer<Integer> valueCallback) {
callback = valueCallback;
return this;

View file

@ -1,7 +1,9 @@
package com.simibubi.create.foundation.behaviour.scrollvalue;
import com.simibubi.create.AllItems;
import com.simibubi.create.AllKeys;
import com.simibubi.create.foundation.behaviour.ValueBoxTransform.Sided;
import com.simibubi.create.foundation.behaviour.base.SmartTileEntity;
import com.simibubi.create.foundation.behaviour.base.TileEntityBehaviour;
import net.minecraft.client.Minecraft;
@ -40,13 +42,29 @@ public class ScrollValueHandler {
if (!scrolling.testHit(objectMouseOver.getHitVec()))
return false;
scrolling.ticksUntilScrollPacket = 10;
scrolling.scrollableValue = (int) MathHelper.clamp(
scrolling.scrollableValue
+ Math.signum(delta) * scrolling.step.apply(scrolling.scrollableValue, delta > 0),
scrolling.min, scrolling.max);
if (scrolling instanceof BulkScrollValueBehaviour && AllKeys.ctrlDown()) {
BulkScrollValueBehaviour bulkScrolling = (BulkScrollValueBehaviour) scrolling;
for (SmartTileEntity smartTileEntity : bulkScrolling.getBulk()) {
ScrollValueBehaviour other = TileEntityBehaviour.get(smartTileEntity, ScrollValueBehaviour.TYPE);
if (other != null)
applyTo(delta, other);
}
} else
applyTo(delta, scrolling);
return true;
}
protected static void applyTo(double delta, ScrollValueBehaviour scrolling) {
scrolling.ticksUntilScrollPacket = 10;
int valueBefore = scrolling.scrollableValue;
scrolling.scrollableValue = (int) MathHelper.clamp(
scrolling.scrollableValue
+ Math.signum(delta) * scrolling.step.apply(scrolling.scrollableValue, delta > 0),
scrolling.min, scrolling.max);
if (valueBefore != scrolling.scrollableValue)
scrolling.clientCallback.accept(scrolling.scrollableValue);
}
}

View file

@ -2,11 +2,13 @@ package com.simibubi.create.foundation.behaviour.scrollvalue;
import com.mojang.blaze3d.platform.GlStateManager;
import com.simibubi.create.AllItems;
import com.simibubi.create.AllKeys;
import com.simibubi.create.foundation.behaviour.ValueBox;
import com.simibubi.create.foundation.behaviour.ValueBox.IconValueBox;
import com.simibubi.create.foundation.behaviour.ValueBox.TextValueBox;
import com.simibubi.create.foundation.behaviour.ValueBoxRenderer;
import com.simibubi.create.foundation.behaviour.ValueBoxTransform.Sided;
import com.simibubi.create.foundation.behaviour.base.SmartTileEntity;
import com.simibubi.create.foundation.behaviour.base.TileEntityBehaviour;
import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.foundation.utility.TessellatorHelper;
@ -14,6 +16,7 @@ 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.util.Direction;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult;
@ -36,22 +39,39 @@ public class ScrollValueRenderer {
BlockRayTraceResult result = (BlockRayTraceResult) target;
ClientWorld world = Minecraft.getInstance().world;
BlockPos pos = result.getPos();
BlockState state = world.getBlockState(pos);
Direction face = result.getFace();
ScrollValueBehaviour behaviour = TileEntityBehaviour.get(world, pos, ScrollValueBehaviour.TYPE);
if (behaviour == null)
return;
if (behaviour.needsWrench && !AllItems.WRENCH.typeOf(Minecraft.getInstance().player.getHeldItemMainhand()))
return;
boolean highlight = behaviour.testHit(target.getHitVec());
TessellatorHelper.prepareForDrawing();
GlStateManager.translated(pos.getX(), pos.getY(), pos.getZ());
if (behaviour instanceof BulkScrollValueBehaviour && AllKeys.ctrlDown()) {
BulkScrollValueBehaviour bulkScrolling = (BulkScrollValueBehaviour) behaviour;
for (SmartTileEntity smartTileEntity : bulkScrolling.getBulk()) {
GlStateManager.pushMatrix();
ScrollValueBehaviour other = TileEntityBehaviour.get(smartTileEntity, ScrollValueBehaviour.TYPE);
if (other != null)
render(world, smartTileEntity.getPos(), face, other, highlight);
GlStateManager.popMatrix();
}
} else
render(world, pos, face, behaviour, highlight);
TessellatorHelper.cleanUpAfterDrawing();
}
protected static void render(ClientWorld world, BlockPos pos, Direction face, ScrollValueBehaviour behaviour,
boolean highlight) {
GlStateManager.translated(pos.getX(), pos.getY(), pos.getZ());
BlockState state = world.getBlockState(pos);
if (behaviour.slotPositioning instanceof Sided)
((Sided) behaviour.slotPositioning).fromSide(result.getFace());
((Sided) behaviour.slotPositioning).fromSide(face);
behaviour.slotPositioning.renderTransformed(state, () -> {
AxisAlignedBB bb =
new AxisAlignedBB(Vec3d.ZERO, Vec3d.ZERO).grow(.5f).contract(0, 0, -.5f).offset(0, 0, -.125f);
AxisAlignedBB bb = new AxisAlignedBB(Vec3d.ZERO, Vec3d.ZERO).grow(.5f).contract(0, 0, -.5f).offset(0, 0,
-.125f);
String label = behaviour.label;
ValueBox box;
@ -65,11 +85,8 @@ public class ScrollValueRenderer {
box.scrollTooltip("[" + Lang.translate("action.scroll") + "]");
box.offsetLabel(behaviour.textShift.add(20, -10, 0)).withColors(0xbe970b, 0xffe75e);
ValueBoxRenderer.renderBox(box, behaviour.testHit(target.getHitVec()));
ValueBoxRenderer.renderBox(box, highlight);
});
TessellatorHelper.cleanUpAfterDrawing();
}
}

View file

@ -0,0 +1,50 @@
package com.simibubi.create.modules.contraptions.components.contraptions;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.modules.contraptions.components.contraptions.chassis.AbstractChassisBlock;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.block.ShulkerBoxBlock;
import net.minecraft.block.material.PushReaction;
import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
public class BlockMovementTraits {
public static boolean movementAllowed(World world, BlockPos pos) {
BlockState blockState = world.getBlockState(pos);
if (blockState.getBlock() instanceof AbstractChassisBlock)
return true;
if (blockState.getBlock() instanceof ShulkerBoxBlock)
return false;
if (blockState.getBlockHardness(world, pos) == -1)
return false;
if (blockState.getBlock() == Blocks.OBSIDIAN)
return false;
return blockState.getPushReaction() != PushReaction.BLOCK;
}
public static boolean notSupportive(BlockState state, Direction facing) {
if (AllBlocks.DRILL.typeOf(state))
return state.get(BlockStateProperties.FACING) == facing;
if (AllBlocks.SAW.typeOf(state))
return state.get(BlockStateProperties.FACING) == facing;
if (AllBlocks.HARVESTER.typeOf(state))
return state.get(BlockStateProperties.HORIZONTAL_FACING) == facing;
return false;
}
public static boolean movementIgnored(BlockState state) {
if (AllBlocks.MECHANICAL_PISTON.typeOf(state))
return true;
if (AllBlocks.STICKY_MECHANICAL_PISTON.typeOf(state))
return true;
if (AllBlocks.MECHANICAL_PISTON_HEAD.typeOf(state))
return true;
return false;
}
}

View file

@ -0,0 +1,202 @@
package com.simibubi.create.modules.contraptions.components.contraptions;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import com.mojang.blaze3d.platform.GlStateManager;
import com.simibubi.create.AllItems;
import com.simibubi.create.AllKeys;
import com.simibubi.create.foundation.utility.TessellatorHelper;
import com.simibubi.create.modules.contraptions.components.contraptions.chassis.ChassisTileEntity;
import net.minecraft.block.Block;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.WorldRenderer;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.math.shapes.VoxelShape;
import net.minecraft.util.math.shapes.VoxelShapes;
import net.minecraft.world.World;
public class ChassisRangeDisplay {
private static final VoxelShape BLOCK_OUTLINE = Block.makeCuboidShape(-.5f, -.5f, -.5f, 16.5f, 16.5f, 16.5f);
private static final int DISPLAY_TIME = 200;
private static GroupEntry lastHoveredGroup = null;
private static class Entry {
VoxelShape shape;
ChassisTileEntity te;
int timer;
public Entry(ChassisTileEntity te) {
this.te = te;
this.shape = createSelection(te);
timer = DISPLAY_TIME;
}
protected VoxelShape createSelection(ChassisTileEntity chassis) {
List<BlockPos> positions = chassis.getIncludedBlockPositions(null, true);
VoxelShape shape = VoxelShapes.empty();
if (positions == null)
return shape;
for (BlockPos blockPos : positions)
shape = VoxelShapes.or(shape,
BLOCK_OUTLINE.withOffset(blockPos.getX(), blockPos.getY(), blockPos.getZ()));
return shape;
}
}
private static class GroupEntry extends Entry {
List<ChassisTileEntity> includedTEs;
public GroupEntry(ChassisTileEntity te) {
super(te);
}
@Override
protected VoxelShape createSelection(ChassisTileEntity chassis) {
VoxelShape shape = VoxelShapes.empty();
includedTEs = te.collectChassisGroup();
if (includedTEs == null)
return shape;
for (ChassisTileEntity chassisTileEntity : includedTEs)
shape = VoxelShapes.or(shape, super.createSelection(chassisTileEntity));
return shape;
}
}
static Map<BlockPos, Entry> entries = new HashMap<>();
static List<GroupEntry> groupEntries = new ArrayList<>();
public static void clientTick() {
PlayerEntity player = Minecraft.getInstance().player;
World world = Minecraft.getInstance().world;
boolean hasWrench = AllItems.WRENCH.typeOf(player.getHeldItemMainhand());
for (Iterator<BlockPos> iterator = entries.keySet().iterator(); iterator.hasNext();)
if (tickEntry(entries.get(iterator.next()), hasWrench))
iterator.remove();
for (Iterator<GroupEntry> iterator = groupEntries.iterator(); iterator.hasNext();) {
GroupEntry group = iterator.next();
if (tickEntry(group, hasWrench)) {
iterator.remove();
if (group == lastHoveredGroup)
lastHoveredGroup = null;
}
}
if (hasWrench) {
RayTraceResult over = Minecraft.getInstance().objectMouseOver;
if (!(over instanceof BlockRayTraceResult))
return;
BlockRayTraceResult ray = (BlockRayTraceResult) over;
BlockPos pos = ray.getPos();
TileEntity tileEntity = world.getTileEntity(pos);
if (tileEntity == null || tileEntity.isRemoved())
return;
if (tileEntity instanceof ChassisTileEntity) {
ChassisTileEntity chassisTileEntity = (ChassisTileEntity) tileEntity;
if (AllKeys.ctrlDown()) {
GroupEntry existingGroupForPos = getExistingGroupForPos(pos);
if (existingGroupForPos != null) {
for (ChassisTileEntity included : existingGroupForPos.includedTEs)
entries.remove(included.getPos());
existingGroupForPos.timer = DISPLAY_TIME;
return;
}
}
if (!entries.containsKey(pos) || AllKeys.ctrlDown())
display(chassisTileEntity);
else {
deselect();
if (!AllKeys.ctrlDown())
entries.get(pos).timer = DISPLAY_TIME;
}
}
}
}
private static void deselect() {
for (Entry entry : entries.values())
if (entry.timer > 10)
entry.timer = 10;
for (Entry entry : groupEntries)
if (entry.timer > 10)
entry.timer = 10;
}
private static boolean tickEntry(Entry entry, boolean hasWrench) {
ChassisTileEntity chassisTileEntity = entry.te;
World teWorld = chassisTileEntity.getWorld();
World world = Minecraft.getInstance().world;
if (chassisTileEntity.isRemoved() || teWorld == null || teWorld != world
|| !world.isBlockPresent(chassisTileEntity.getPos())) {
return true;
}
if (!hasWrench && entry.timer > 20) {
entry.timer = 20;
return false;
}
entry.timer--;
if (entry.timer == 0)
return true;
return false;
}
public static void display(ChassisTileEntity chassis) {
deselect();
if (AllKeys.ctrlDown()) {
groupEntries.clear();
GroupEntry hoveredGroup = new GroupEntry(chassis);
for (ChassisTileEntity included : hoveredGroup.includedTEs)
entries.remove(included.getPos());
groupEntries.add(hoveredGroup);
} else {
entries.put(chassis.getPos(), new Entry(chassis));
}
}
public static void renderOutlines(float partialTicks) {
GlStateManager.lineWidth(2);
TessellatorHelper.prepareForDrawing();
GlStateManager.disableTexture();
for (Entry entry : entries.values()) {
float timer = entry.timer - partialTicks;
float alpha = timer > 20 ? 1 : timer / 20f;
WorldRenderer.drawShape(entry.shape, 0, 0, 0, 1, .7f, 0, alpha);
}
for (Entry entry : groupEntries) {
float timer = entry.timer - partialTicks;
float alpha = timer > 20 ? 1 : timer / 20f;
WorldRenderer.drawShape(entry.shape, 0, 0, 0, 1, .7f, 0, alpha);
}
GlStateManager.enableTexture();
TessellatorHelper.cleanUpAfterDrawing();
GlStateManager.lineWidth(1);
}
private static GroupEntry getExistingGroupForPos(BlockPos pos) {
for (GroupEntry groupEntry : groupEntries)
for (ChassisTileEntity chassis : groupEntry.includedTEs)
if (pos.equals(chassis.getPos()))
return groupEntry;
return null;
}
}

View file

@ -1,21 +1,18 @@
package com.simibubi.create.modules.contraptions.components.contraptions;
import static net.minecraft.state.properties.BlockStateProperties.AXIS;
import static net.minecraft.state.properties.BlockStateProperties.FACING;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.BiPredicate;
import java.util.function.Function;
import java.util.stream.Collectors;
import javax.annotation.Nullable;
import org.apache.commons.lang3.tuple.MutablePair;
import org.apache.commons.lang3.tuple.Pair;
@ -24,26 +21,18 @@ import com.simibubi.create.config.AllConfigs;
import com.simibubi.create.foundation.utility.NBTHelper;
import com.simibubi.create.modules.contraptions.components.contraptions.chassis.AbstractChassisBlock;
import com.simibubi.create.modules.contraptions.components.contraptions.chassis.ChassisTileEntity;
import com.simibubi.create.modules.contraptions.components.contraptions.chassis.LinearChassisBlock;
import com.simibubi.create.modules.contraptions.components.contraptions.chassis.RadialChassisBlock;
import com.simibubi.create.modules.contraptions.components.saw.SawBlock;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.block.FallingBlock;
import net.minecraft.block.ShulkerBoxBlock;
import net.minecraft.block.SlimeBlock;
import net.minecraft.block.material.PushReaction;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.nbt.ListNBT;
import net.minecraft.nbt.NBTUtil;
import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.tileentity.TileEntity;
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.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
@ -76,44 +65,6 @@ public abstract class Contraption {
renderOrder = new ArrayList<>();
}
private static List<BlockInfo> getChassisClusterAt(World world, BlockPos pos) {
List<BlockPos> search = new LinkedList<>();
Set<BlockPos> visited = new HashSet<>();
List<BlockInfo> chassis = new LinkedList<>();
BlockState anchorChassis = world.getBlockState(pos);
Axis axis = anchorChassis.get(AXIS);
search.add(pos);
while (!search.isEmpty()) {
if (chassis.size() > AllConfigs.SERVER.kinetics.maxChassisForTranslation.get())
return null;
BlockPos current = search.remove(0);
if (visited.contains(current))
continue;
if (!world.isAreaLoaded(current, 1))
return null;
BlockState state = world.getBlockState(current);
if (!isLinearChassis(state))
continue;
if (!LinearChassisBlock.sameKind(anchorChassis, state))
continue;
if (state.get(AXIS) != axis)
continue;
visited.add(current);
chassis.add(new BlockInfo(current, world.getBlockState(current), getTileEntityNBT(world, current)));
for (Direction offset : Direction.values()) {
if (offset.getAxis() == axis)
continue;
search.add(current.offset(offset));
}
}
return chassis;
}
public Set<BlockPos> getColliders(World world, Direction movementDirection) {
if (blocks == null)
return null;
@ -138,7 +89,7 @@ public abstract class Contraption {
return cachedColliders;
}
public boolean searchMovedStructure(World world, BlockPos pos, Direction direction) {
public boolean searchMovedStructure(World world, BlockPos pos, @Nullable Direction forcedDirection) {
List<BlockPos> frontier = new ArrayList<>();
Set<BlockPos> visited = new HashSet<>();
anchor = pos;
@ -147,29 +98,30 @@ public abstract class Contraption {
constructCollisionBox = new AxisAlignedBB(BlockPos.ZERO);
frontier.add(pos);
if (!addToInitialFrontier(world, pos, direction, frontier))
if (!addToInitialFrontier(world, pos, forcedDirection, frontier))
return false;
for (int limit = 1000; limit > 0; limit--) {
if (frontier.isEmpty())
return true;
if (!moveBlock(world, frontier.remove(0), direction, frontier, visited))
if (!moveBlock(world, frontier.remove(0), forcedDirection, frontier, visited))
return false;
}
return false;
}
public void gatherStoredItems() {
List<IItemHandlerModifiable> list =
storage.values().stream().map(MountedStorage::getItemHandler).collect(Collectors.toList());
List<IItemHandlerModifiable> list = storage.values().stream().map(MountedStorage::getItemHandler)
.collect(Collectors.toList());
inventory = new CombinedInvWrapper(Arrays.copyOf(list.toArray(), list.size(), IItemHandlerModifiable[].class));
}
protected boolean addToInitialFrontier(World world, BlockPos pos, Direction direction, List<BlockPos> frontier) {
protected boolean addToInitialFrontier(World world, BlockPos pos, Direction forcedDirection,
List<BlockPos> frontier) {
return true;
}
protected boolean moveBlock(World world, BlockPos pos, Direction direction, List<BlockPos> frontier,
protected boolean moveBlock(World world, BlockPos pos, Direction forcedDirection, List<BlockPos> frontier,
Set<BlockPos> visited) {
visited.add(pos);
frontier.remove(pos);
@ -181,22 +133,21 @@ public abstract class Contraption {
return true;
if (state.getCollisionShape(world, pos).isEmpty())
return true;
if (!canPush(world, pos, direction))
if (!BlockMovementTraits.movementAllowed(world, pos))
return false;
if (isLinearChassis(state) && !moveLinearChassis(world, pos, direction, frontier, visited))
return false;
if (isRadialChassis(state) && !moveRadialChassis(world, pos, direction, frontier, visited))
if (isChassis(state) && !moveChassis(world, pos, forcedDirection, frontier, visited))
return false;
if (state.getBlock() instanceof SlimeBlock)
for (Direction offset : Direction.values()) {
BlockPos offsetPos = pos.offset(offset);
if (offset.getAxis() == direction.getAxis()) {
BlockState blockState = world.getBlockState(offsetPos);
if (AllBlocks.MECHANICAL_PISTON.typeOf(blockState)
|| AllBlocks.STICKY_MECHANICAL_PISTON.typeOf(blockState)
|| AllBlocks.MECHANICAL_PISTON_HEAD.typeOf(blockState))
continue;
BlockState blockState = world.getBlockState(offsetPos);
if (BlockMovementTraits.movementIgnored(blockState))
continue;
if (!BlockMovementTraits.movementAllowed(world, offsetPos)) {
if (offset == forcedDirection)
return false;
continue;
}
if (!visited.contains(offsetPos))
frontier.add(offsetPos);
@ -206,243 +157,23 @@ public abstract class Contraption {
return true;
}
private boolean moveLinearChassis(World world, BlockPos pos, Direction movementDirection, List<BlockPos> frontier,
protected static boolean isChassis(BlockState state) {
return state.getBlock() instanceof AbstractChassisBlock;
}
private boolean moveChassis(World world, BlockPos pos, Direction movementDirection, List<BlockPos> frontier,
Set<BlockPos> visited) {
List<BlockInfo> cluster = getChassisClusterAt(world, pos);
if (cluster == null)
TileEntity te = world.getTileEntity(pos);
if (!(te instanceof ChassisTileEntity))
return false;
if (cluster.isEmpty())
return true;
Set<BlockPos> validChassis = new HashSet<>(cluster.size());
cluster.forEach(info -> validChassis.add(info.pos));
BlockInfo anchorChassis = cluster.get(0);
Axis chassisAxis = anchorChassis.state.get(AXIS);
int chassisCoord =
chassisAxis.getCoordinate(anchorChassis.pos.getX(), anchorChassis.pos.getY(), anchorChassis.pos.getZ());
Function<BlockPos, BlockPos> getChassisPos =
position -> new BlockPos(chassisAxis == Axis.X ? chassisCoord : position.getX(),
chassisAxis == Axis.Y ? chassisCoord : position.getY(),
chassisAxis == Axis.Z ? chassisCoord : position.getZ());
// Collect blocks on both sides
for (AxisDirection axisDirection : AxisDirection.values()) {
Direction chassisDirection = Direction.getFacingFromAxis(axisDirection, chassisAxis);
List<BlockPos> chassisFrontier = new LinkedList<>();
Set<BlockPos> chassisVisited = new HashSet<>();
cluster.forEach(c -> chassisFrontier.add(c.pos));
boolean pushing = chassisDirection == movementDirection;
Search: while (!chassisFrontier.isEmpty()) {
BlockPos currentPos = chassisFrontier.remove(0);
if (!world.isAreaLoaded(currentPos, 1))
return false;
if (!world.isBlockPresent(currentPos))
continue;
if (chassisVisited.contains(currentPos))
continue;
chassisVisited.add(currentPos);
BlockState state = world.getBlockState(currentPos);
BlockPos currentChassisPos = getChassisPos.apply(currentPos);
BlockState chassisState = world.getBlockState(currentChassisPos);
// Not attached to a chassis
if (!isLinearChassis(chassisState) || chassisState.get(AXIS) != chassisAxis)
continue;
if (AllBlocks.MECHANICAL_PISTON_HEAD.typeOf(state)
&& state.get(FACING) == chassisDirection.getOpposite())
continue;
int chassisRange = ((ChassisTileEntity) world.getTileEntity(currentChassisPos)).getRange();
boolean chassisSticky = chassisState.get(((AbstractChassisBlock) chassisState.getBlock())
.getGlueableSide(chassisState, chassisDirection));
// Ignore replaceable Blocks and Air-like
if (state.getMaterial().isReplaceable() || state.isAir(world, currentPos))
continue;
if (state.getCollisionShape(world, currentPos).isEmpty())
continue;
// Too many Blocks
boolean notInRange = !currentChassisPos.withinDistance(currentPos, chassisRange + 1);
if (pushing && notInRange)
return false;
if (!pushing && notInRange)
continue;
// Chassis not part of cluster
if (!validChassis.contains(currentChassisPos))
continue;
boolean isBaseChassis = currentPos.equals(currentChassisPos);
if (!isBaseChassis) {
// Don't pull if chassis not sticky
if (!chassisSticky && !pushing)
continue;
// Skip if pushed column ended already
for (BlockPos posInbetween = currentPos; !posInbetween.equals(currentChassisPos); posInbetween =
posInbetween.offset(chassisDirection.getOpposite())) {
BlockState blockState = world.getBlockState(posInbetween);
if (!chassisSticky && (blockState.getMaterial().isReplaceable()))
continue Search;
if (!pushing && chassisSticky && !canPush(world, posInbetween, movementDirection))
continue Search;
}
}
// Ignore sand and co.
if (chassisSticky && !pushing && state.getBlock() instanceof FallingBlock)
continue;
// Structure is immobile
boolean cannotPush = !canPush(world, currentPos, movementDirection);
if (pushing && cannotPush)
return false;
if (!pushing && cannotPush)
continue;
if (isBaseChassis) {
add(currentPos, capture(world, currentPos));
visited.add(currentPos);
} else {
frontier.add(currentPos);
}
// Expand search
for (Direction facing : Direction.values()) {
if (isBaseChassis && facing == chassisDirection.getOpposite())
continue;
if (notSupportive(world, pos, facing))
continue;
chassisFrontier.add(currentPos.offset(facing));
}
}
}
ChassisTileEntity chassis = (ChassisTileEntity) te;
chassis.addAttachedChasses(frontier, visited);
for (BlockPos blockPos : chassis.getIncludedBlockPositions(movementDirection, false))
if (!visited.contains(blockPos))
frontier.add(blockPos);
return true;
}
private boolean moveRadialChassis(World world, BlockPos pos, Direction movementDirection, List<BlockPos> frontier,
Set<BlockPos> visited) {
RadialChassisBlock def = (RadialChassisBlock) AllBlocks.ROTATION_CHASSIS.block;
List<BlockPos> chassisPositions = new ArrayList<>();
BlockState chassisState = world.getBlockState(pos);
Axis axis = chassisState.get(RadialChassisBlock.AXIS);
chassisPositions.add(pos);
// Collect chain of chassis
for (int offset : new int[] { -1, 1 }) {
for (int distance = 1; distance <= AllConfigs.SERVER.kinetics.maxChassisForRotation.get(); distance++) {
Direction direction = Direction.getFacingFromAxis(AxisDirection.POSITIVE, axis);
BlockPos currentPos = pos.offset(direction, distance * offset);
if (!world.isBlockPresent(currentPos))
return false;
BlockState state = world.getBlockState(currentPos);
if (!AllBlocks.ROTATION_CHASSIS.typeOf(state))
break;
if (direction.getAxis() != state.get(BlockStateProperties.AXIS))
break;
chassisPositions.add(currentPos);
}
}
// Add attached blocks to frontier
for (BlockPos chassisPos : chassisPositions) {
add(chassisPos, capture(world, chassisPos));
visited.add(chassisPos);
BlockPos currentPos = chassisPos;
BlockState state = world.getBlockState(currentPos);
TileEntity tileEntity = world.getTileEntity(currentPos);
if (!(tileEntity instanceof ChassisTileEntity))
return false;
int chassisRange = ((ChassisTileEntity) tileEntity).getRange();
for (Direction facing : Direction.values()) {
if (facing.getAxis() == axis)
continue;
if (!state.get(def.getGlueableSide(state, facing)))
continue;
BlockPos startPos = currentPos.offset(facing);
List<BlockPos> localFrontier = new LinkedList<>();
Set<BlockPos> localVisited = new HashSet<>();
localFrontier.add(startPos);
while (!localFrontier.isEmpty()) {
BlockPos searchPos = localFrontier.remove(0);
BlockState searchedState = world.getBlockState(searchPos);
if (localVisited.contains(searchPos))
continue;
if (!searchPos.withinDistance(currentPos, chassisRange + .5f))
continue;
if (searchedState.getMaterial().isReplaceable() || state.isAir(world, searchPos))
continue;
if (searchedState.getCollisionShape(world, searchPos).isEmpty())
continue;
localVisited.add(searchPos);
if (!visited.contains(searchPos))
frontier.add(searchPos);
for (Direction offset : Direction.values()) {
if (offset.getAxis() == axis)
continue;
if (searchPos.equals(currentPos) && offset != facing)
continue;
localFrontier.add(searchPos.offset(offset));
}
}
}
}
return true;
}
private static boolean isLinearChassis(BlockState state) {
return LinearChassisBlock.isChassis(state);
}
private static boolean isRadialChassis(BlockState state) {
return AllBlocks.ROTATION_CHASSIS.typeOf(state);
}
private boolean notSupportive(World world, BlockPos pos, Direction facing) {
BlockState state = world.getBlockState(pos);
if (AllBlocks.DRILL.typeOf(state))
return state.get(BlockStateProperties.FACING) == facing;
if (AllBlocks.HARVESTER.typeOf(state))
return state.get(BlockStateProperties.HORIZONTAL_FACING) == facing;
return false;
}
protected static boolean canPush(World world, BlockPos pos, Direction direction) {
BlockState blockState = world.getBlockState(pos);
if (isLinearChassis(blockState) || isRadialChassis(blockState))
return true;
if (blockState.getBlock() instanceof ShulkerBoxBlock)
return false;
if (blockState.getBlockHardness(world, pos) == -1)
return false;
if (blockState.getBlock() == Blocks.OBSIDIAN)
return false;
return blockState.getPushReaction() != PushReaction.BLOCK;
}
protected Pair<BlockInfo, TileEntity> capture(World world, BlockPos pos) {
BlockState blockstate = world.getBlockState(pos);
if (AllBlocks.SAW.typeOf(blockstate))
@ -520,8 +251,8 @@ public abstract class Contraption {
CompoundNBT comp = (CompoundNBT) c;
storage.put(NBTUtil.readBlockPos(comp.getCompound("Pos")), new MountedStorage(comp.getCompound("Data")));
});
List<IItemHandlerModifiable> list =
storage.values().stream().map(MountedStorage::getItemHandler).collect(Collectors.toList());
List<IItemHandlerModifiable> list = storage.values().stream().map(MountedStorage::getItemHandler)
.collect(Collectors.toList());
inventory = new CombinedInvWrapper(Arrays.copyOf(list.toArray(), list.size(), IItemHandlerModifiable[].class));
if (nbt.contains("BoundsFront"))
@ -582,8 +313,8 @@ public abstract class Contraption {
return AllConfigs.SERVER.control.freezePistonConstructs.get();
}
public void disassemble(World world, BlockPos offset, float yaw, float pitch) {
disassemble(world, offset, yaw, pitch, (pos, state) -> false);
public void disassemble(World world, BlockPos offset, Vec3d rotation) {
disassemble(world, offset, rotation, (pos, state) -> false);
}
public void removeBlocksFromWorld(IWorld world, BlockPos offset) {
@ -600,12 +331,15 @@ public abstract class Contraption {
}
}
public void disassemble(World world, BlockPos offset, float yaw, float pitch,
public void disassemble(World world, BlockPos offset, Vec3d rotation,
BiPredicate<BlockPos, BlockState> customPlacement) {
stop(world);
StructureTransform transform = new StructureTransform(offset, rotation);
for (BlockInfo block : blocks.values()) {
BlockPos targetPos = block.pos.add(offset);
BlockState state = block.state;
BlockPos targetPos = transform.apply(block.pos);
BlockState state = transform.apply(block.state);
if (customPlacement.test(targetPos, state))
continue;

View file

@ -43,8 +43,8 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
protected Vec3d motionBeforeStall;
protected boolean stationary;
private static final DataParameter<Boolean> STALLED =
EntityDataManager.createKey(ContraptionEntity.class, DataSerializers.BOOLEAN);
private static final DataParameter<Boolean> STALLED = EntityDataManager.createKey(ContraptionEntity.class,
DataSerializers.BOOLEAN);
public float prevYaw;
public float prevPitch;
@ -365,7 +365,8 @@ public class ContraptionEntity extends Entity implements IEntityAdditionalSpawnD
public void disassemble() {
if (getContraption() != null)
getContraption().disassemble(world, new BlockPos(getPositionVec().add(.5, .5, .5)), yaw, pitch);
getContraption().disassemble(world, new BlockPos(getPositionVec().add(.5, .5, .5)),
new Vec3d(getRoll(1), getYaw(1), getPitch(1)));
remove();
}

View file

@ -0,0 +1,154 @@
package com.simibubi.create.modules.contraptions.components.contraptions;
import com.simibubi.create.foundation.utility.VecHelper;
import com.simibubi.create.modules.contraptions.components.contraptions.chassis.AbstractChassisBlock;
import net.minecraft.block.BlockState;
import net.minecraft.block.SlabBlock;
import net.minecraft.block.StairsBlock;
import net.minecraft.state.BooleanProperty;
import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.state.properties.Half;
import net.minecraft.state.properties.SlabType;
import net.minecraft.util.Direction;
import net.minecraft.util.Direction.Axis;
import net.minecraft.util.Direction.AxisDirection;
import net.minecraft.util.Rotation;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
public class StructureTransform {
// Assuming structures cannot be rotated around multiple axes at once
Rotation rotation;
int angle;
Axis rotationAxis;
BlockPos offset;
public StructureTransform(BlockPos offset, Vec3d rotation) {
this.offset = offset;
if (rotation.x != 0) {
rotationAxis = Axis.X;
angle = (int) (Math.round(rotation.x / 90) * 90);
}
if (rotation.y != 0) {
rotationAxis = Axis.Y;
angle = (int) (Math.round(rotation.y / 90) * 90);
}
if (rotation.z != 0) {
rotationAxis = Axis.Z;
angle = (int) (Math.round(rotation.z / 90) * 90);
}
angle %= 360;
if (angle < -90)
angle += 360;
this.rotation = Rotation.NONE;
if (angle == -90 || angle == 270)
this.rotation = Rotation.CLOCKWISE_90;
if (angle == 90)
this.rotation = Rotation.COUNTERCLOCKWISE_90;
if (angle == 180)
this.rotation = Rotation.CLOCKWISE_180;
}
public BlockPos apply(BlockPos localPos) {
Vec3d vec = VecHelper.getCenterOf(localPos);
vec = VecHelper.rotateCentered(vec, angle, rotationAxis);
localPos = new BlockPos(vec);
return localPos.add(offset);
}
/**
* Minecraft does not support blockstate rotation around axes other than y. Add
* specific cases here for blockstates, that should react to rotations around
* horizontal axes
*/
public BlockState apply(BlockState state) {
if (rotationAxis == Axis.Y)
state = state.rotate(rotation);
else {
if (state.getBlock() instanceof AbstractChassisBlock)
return rotateChassis(state);
if (state.getBlock() instanceof StairsBlock) {
if (state.get(StairsBlock.FACING).getAxis() != rotationAxis) {
for (int i = 0; i < rotation.ordinal(); i++) {
Direction direction = state.get(StairsBlock.FACING);
Half half = state.get(StairsBlock.HALF);
if (direction.getAxisDirection() == AxisDirection.POSITIVE ^ half == Half.BOTTOM
^ direction.getAxis() == Axis.Z)
state = state.cycle(StairsBlock.HALF);
else
state = state.with(StairsBlock.FACING, direction.getOpposite());
}
} else {
if (rotation == Rotation.CLOCKWISE_180) {
state = state.cycle(StairsBlock.HALF);
}
}
return state;
}
if (state.has(BlockStateProperties.FACING)) {
state = state.with(BlockStateProperties.FACING,
transformFacing(state.get(BlockStateProperties.FACING)));
} else if (state.has(BlockStateProperties.AXIS)) {
state = state.with(BlockStateProperties.AXIS, transformAxis(state.get(BlockStateProperties.AXIS)));
} else if (rotation == Rotation.CLOCKWISE_180) {
state = state.rotate(rotation);
if (state.has(SlabBlock.TYPE) && state.get(SlabBlock.TYPE) != SlabType.DOUBLE)
state = state.with(SlabBlock.TYPE,
state.get(SlabBlock.TYPE) == SlabType.BOTTOM ? SlabType.TOP : SlabType.BOTTOM);
}
}
return state;
}
protected Axis transformAxis(Axis axisIn) {
Direction facing = Direction.getFacingFromAxis(AxisDirection.POSITIVE, axisIn);
facing = transformFacing(facing);
Axis axis = facing.getAxis();
return axis;
}
protected Direction transformFacing(Direction facing) {
for (int i = 0; i < rotation.ordinal(); i++)
facing = facing.rotateAround(rotationAxis);
return facing;
}
private BlockState rotateChassis(BlockState state) {
if (rotation == Rotation.NONE)
return state;
BlockState rotated = state.with(BlockStateProperties.AXIS, transformAxis(state.get(BlockStateProperties.AXIS)));
AbstractChassisBlock block = (AbstractChassisBlock) state.getBlock();
for (Direction face : Direction.values()) {
BooleanProperty glueableSide = block.getGlueableSide(rotated, face);
if (glueableSide != null)
rotated = rotated.with(glueableSide, false);
}
for (Direction face : Direction.values()) {
BooleanProperty glueableSide = block.getGlueableSide(state, face);
if (glueableSide == null || !state.get(glueableSide))
continue;
Direction rotatedFacing = transformFacing(face);
BooleanProperty rotatedGlueableSide = block.getGlueableSide(rotated, rotatedFacing);
if (rotatedGlueableSide != null)
rotated = rotated.with(rotatedGlueableSide, true);
}
return rotated;
}
}

View file

@ -28,7 +28,7 @@ public class BearingContraption extends Contraption {
return null;
BearingContraption construct = new BearingContraption();
construct.facing = direction;
if (!construct.searchMovedStructure(world, pos.offset(direction), direction))
if (!construct.searchMovedStructure(world, pos.offset(direction), null))
return null;
construct.initActors(world);
return construct;

View file

@ -3,7 +3,6 @@ package com.simibubi.create.modules.contraptions.components.contraptions.bearing
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.function.BiPredicate;
import org.apache.commons.lang3.tuple.Pair;
@ -11,7 +10,6 @@ import com.simibubi.create.foundation.utility.NBTHelper;
import com.simibubi.create.modules.contraptions.components.contraptions.AllContraptionTypes;
import com.simibubi.create.modules.contraptions.components.contraptions.Contraption;
import net.minecraft.block.BlockState;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
@ -76,13 +74,7 @@ public class ClockworkContraption extends Contraption {
@Override
public boolean searchMovedStructure(World world, BlockPos pos, Direction direction) {
return super.searchMovedStructure(world, pos.offset(direction, offset + 1), direction);
}
@Override
public void disassemble(World world, BlockPos offset, float yaw, float pitch,
BiPredicate<BlockPos, BlockState> customPlacement) {
super.disassemble(world, offset, yaw, pitch, customPlacement);
return super.searchMovedStructure(world, pos.offset(direction, offset + 1), null);
}
@Override

View file

@ -1,20 +1,18 @@
package com.simibubi.create.modules.contraptions.components.contraptions.chassis;
import java.util.List;
import com.simibubi.create.AllSoundEvents;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.RotatedPillarBlock;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.particles.ParticleTypes;
import net.minecraft.state.BooleanProperty;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Direction;
import net.minecraft.util.Hand;
import net.minecraft.util.Mirror;
import net.minecraft.util.Rotation;
import net.minecraft.util.SoundCategory;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult;
@ -45,12 +43,32 @@ public abstract class AbstractChassisBlock extends RotatedPillarBlock {
if (!player.isAllowEdit())
return false;
ItemStack heldItem = player.getHeldItem(handIn);
boolean isSlimeBall = heldItem.getItem().isIn(Tags.Items.SLIMEBALLS);
BooleanProperty affectedSide = getGlueableSide(state, hit.getFace());
if (affectedSide == null)
return false;
ItemStack heldItem = player.getHeldItem(handIn);
boolean isSlimeBall = heldItem.getItem().isIn(Tags.Items.SLIMEBALLS);
if (isSlimeBall && state.get(affectedSide)) {
for (Direction face : Direction.values()) {
BooleanProperty glueableSide = getGlueableSide(state, face);
if (glueableSide != null && !state.get(glueableSide)) {
if (worldIn.isRemote) {
Vec3d vec = hit.getHitVec();
worldIn.addParticle(ParticleTypes.ITEM_SLIME, vec.x, vec.y, vec.z, 0, 0, 0);
return true;
}
worldIn.playSound(null, pos, AllSoundEvents.SLIME_ADDED.get(), SoundCategory.BLOCKS, .5f, 1);
if (!player.isCreative())
heldItem.shrink(1);
state = state.with(glueableSide, true);
}
}
if (!worldIn.isRemote)
worldIn.setBlockState(pos, state);
return true;
}
if ((!heldItem.isEmpty() || !player.isSneaking()) && !isSlimeBall)
return false;
@ -63,27 +81,61 @@ public abstract class AbstractChassisBlock extends RotatedPillarBlock {
}
worldIn.playSound(null, pos, AllSoundEvents.SLIME_ADDED.get(), SoundCategory.BLOCKS, .5f, 1);
if (isSlimeBall && !player.isCreative())
heldItem.shrink(1);
if (!isSlimeBall && !player.isCreative())
Block.spawnAsEntity(worldIn, pos.offset(hit.getFace()), new ItemStack(Items.SLIME_BALL));
worldIn.setBlockState(pos, state.with(affectedSide, isSlimeBall));
return true;
}
public abstract BooleanProperty getGlueableSide(BlockState state, Direction face);
@Override
public List<ItemStack> getDrops(BlockState state, net.minecraft.world.storage.loot.LootContext.Builder builder) {
public BlockState rotate(BlockState state, Rotation rotation) {
if (rotation == Rotation.NONE)
return state;
@SuppressWarnings("deprecation")
List<ItemStack> drops = super.getDrops(state, builder);
BlockState rotated = super.rotate(state, rotation);
for (Direction face : Direction.values()) {
BooleanProperty glueableSide = getGlueableSide(rotated, face);
if (glueableSide != null)
rotated = rotated.with(glueableSide, false);
}
for (Direction face : Direction.values()) {
BooleanProperty glueableSide = getGlueableSide(state, face);
if (glueableSide != null && state.get(glueableSide))
drops.add(new ItemStack(Items.SLIME_BALL));
if (glueableSide == null || !state.get(glueableSide))
continue;
Direction rotatedFacing = rotation.rotate(face);
BooleanProperty rotatedGlueableSide = getGlueableSide(rotated, rotatedFacing);
if (rotatedGlueableSide != null)
rotated = rotated.with(rotatedGlueableSide, true);
}
return drops;
return rotated;
}
@Override
public BlockState mirror(BlockState state, Mirror mirrorIn) {
if (mirrorIn == Mirror.NONE)
return state;
BlockState mirrored = state;
for (Direction face : Direction.values()) {
BooleanProperty glueableSide = getGlueableSide(mirrored, face);
if (glueableSide != null)
mirrored = mirrored.with(glueableSide, false);
}
for (Direction face : Direction.values()) {
BooleanProperty glueableSide = getGlueableSide(state, face);
if (glueableSide == null || !state.get(glueableSide))
continue;
Direction mirroredFacing = mirrorIn.mirror(face);
BooleanProperty mirroredGlueableSide = getGlueableSide(mirrored, mirroredFacing);
if (mirroredGlueableSide != null)
mirrored = mirrored.with(mirroredGlueableSide, true);
}
return mirrored;
}
public abstract BooleanProperty getGlueableSide(BlockState state, Direction face);
}

View file

@ -1,14 +1,35 @@
package com.simibubi.create.modules.contraptions.components.contraptions.chassis;
import java.util.List;
import static net.minecraft.state.properties.BlockStateProperties.AXIS;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import com.simibubi.create.AllBlocks;
import com.simibubi.create.AllTileEntities;
import com.simibubi.create.config.AllConfigs;
import com.simibubi.create.foundation.behaviour.CenteredSideValueBoxTransform;
import com.simibubi.create.foundation.behaviour.base.SmartTileEntity;
import com.simibubi.create.foundation.behaviour.base.TileEntityBehaviour;
import com.simibubi.create.foundation.behaviour.scrollvalue.BulkScrollValueBehaviour;
import com.simibubi.create.foundation.behaviour.scrollvalue.ScrollValueBehaviour;
import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.modules.contraptions.components.contraptions.BlockMovementTraits;
import com.simibubi.create.modules.contraptions.components.contraptions.ChassisRangeDisplay;
import net.minecraft.block.BlockState;
import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.tileentity.TileEntity;
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.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.fml.DistExecutor;
public class ChassisTileEntity extends SmartTileEntity {
@ -21,9 +42,12 @@ public class ChassisTileEntity extends SmartTileEntity {
@Override
public void addBehaviours(List<TileEntityBehaviour> behaviours) {
int max = AllConfigs.SERVER.kinetics.maxChassisRange.get();
range = new ScrollValueBehaviour(Lang.translate("generic.range"), this, new CenteredSideValueBoxTransform());
range = new BulkScrollValueBehaviour(Lang.translate("generic.range"), this, new CenteredSideValueBoxTransform(),
te -> ((ChassisTileEntity) te).collectChassisGroup());
range.requiresWrench();
range.between(1, max);
range.withClientCallback(
i -> DistExecutor.runWhenOn(Dist.CLIENT, () -> () -> ChassisRangeDisplay.display(this)));
range.value = max / 2;
behaviours.add(range);
}
@ -39,4 +63,178 @@ public class ChassisTileEntity extends SmartTileEntity {
return range.getValue();
}
public List<BlockPos> getIncludedBlockPositions(Direction forcedMovement, boolean visualize) {
if (!(getBlockState().getBlock() instanceof AbstractChassisBlock))
return Collections.emptyList();
return isRadial() ? getIncludedBlockPositionsRadial(forcedMovement, visualize)
: getIncludedBlockPositionsLinear(forcedMovement, visualize);
}
protected boolean isRadial() {
return world.getBlockState(pos).getBlock() instanceof RadialChassisBlock;
}
public List<ChassisTileEntity> collectChassisGroup() {
List<BlockPos> frontier = new ArrayList<>();
List<ChassisTileEntity> collected = new ArrayList<>();
Set<BlockPos> visited = new HashSet<>();
frontier.add(pos);
while (!frontier.isEmpty()) {
BlockPos current = frontier.remove(0);
if (visited.contains(current))
continue;
visited.add(current);
TileEntity tileEntity = world.getTileEntity(current);
if (tileEntity instanceof ChassisTileEntity) {
ChassisTileEntity chassis = (ChassisTileEntity) tileEntity;
collected.add(chassis);
visited.add(current);
chassis.addAttachedChasses(frontier, visited);
}
}
return collected;
}
public boolean addAttachedChasses(List<BlockPos> frontier, Set<BlockPos> visited) {
BlockState state = getBlockState();
if (!(state.getBlock() instanceof AbstractChassisBlock))
return false;
Axis axis = state.get(AbstractChassisBlock.AXIS);
if (isRadial()) {
// Collect chain of radial chassis
for (int offset : new int[] { -1, 1 }) {
Direction direction = Direction.getFacingFromAxis(AxisDirection.POSITIVE, axis);
BlockPos currentPos = pos.offset(direction, offset);
if (!world.isBlockPresent(currentPos))
return false;
BlockState neighbourState = world.getBlockState(currentPos);
if (!AllBlocks.ROTATION_CHASSIS.typeOf(neighbourState))
continue;
if (axis != neighbourState.get(BlockStateProperties.AXIS))
continue;
if (!visited.contains(currentPos))
frontier.add(currentPos);
}
return true;
}
// Collect group of connected linear chassis
for (Direction offset : Direction.values()) {
if (offset.getAxis() == axis)
continue;
BlockPos current = pos.offset(offset);
if (visited.contains(current))
continue;
if (!world.isBlockPresent(current))
return false;
BlockState neighbourState = world.getBlockState(current);
if (!LinearChassisBlock.isChassis(neighbourState))
continue;
if (!LinearChassisBlock.sameKind(state, neighbourState))
continue;
if (neighbourState.get(AXIS) != axis)
continue;
frontier.add(current);
}
return true;
}
private List<BlockPos> getIncludedBlockPositionsLinear(Direction forcedMovement, boolean visualize) {
List<BlockPos> positions = new ArrayList<>();
BlockState state = getBlockState();
AbstractChassisBlock block = (AbstractChassisBlock) state.getBlock();
Axis axis = state.get(AbstractChassisBlock.AXIS);
Direction facing = Direction.getFacingFromAxis(AxisDirection.POSITIVE, axis);
int chassisRange = visualize ? range.scrollableValue : getRange();
for (int offset : new int[] { 1, -1 }) {
if (offset == -1)
facing = facing.getOpposite();
boolean sticky = state.get(block.getGlueableSide(state, facing));
for (int i = 1; i <= chassisRange; i++) {
BlockPos current = pos.offset(facing, i);
BlockState currentState = world.getBlockState(current);
if (forcedMovement != facing && !visualize && !sticky)
break;
// Ignore replaceable Blocks and Air-like
if (currentState.getMaterial().isReplaceable())
break;
if (currentState.getCollisionShape(world, current).isEmpty())
break;
if (AllBlocks.MECHANICAL_PISTON_HEAD.typeOf(currentState))
break;
if (AllBlocks.MECHANICAL_PISTON.typeOf(currentState))
break;
if (AllBlocks.STICKY_MECHANICAL_PISTON.typeOf(currentState))
break;
positions.add(current);
if (BlockMovementTraits.notSupportive(currentState, facing))
break;
}
}
return positions;
}
private List<BlockPos> getIncludedBlockPositionsRadial(Direction forcedMovement, boolean visualize) {
List<BlockPos> positions = new ArrayList<>();
BlockState state = world.getBlockState(pos);
Axis axis = state.get(AbstractChassisBlock.AXIS);
AbstractChassisBlock block = (AbstractChassisBlock) state.getBlock();
int chassisRange = visualize ? range.scrollableValue : getRange();
for (Direction facing : Direction.values()) {
if (facing.getAxis() == axis)
continue;
if (!state.get(block.getGlueableSide(state, facing)))
continue;
BlockPos startPos = pos.offset(facing);
List<BlockPos> localFrontier = new LinkedList<>();
Set<BlockPos> localVisited = new HashSet<>();
localFrontier.add(startPos);
while (!localFrontier.isEmpty()) {
BlockPos searchPos = localFrontier.remove(0);
BlockState searchedState = world.getBlockState(searchPos);
if (localVisited.contains(searchPos))
continue;
if (!searchPos.withinDistance(pos, chassisRange + .5f))
continue;
if (searchedState.getMaterial().isReplaceable())
continue;
if (searchedState.getCollisionShape(world, searchPos).isEmpty())
continue;
localVisited.add(searchPos);
if (!searchPos.equals(pos))
positions.add(searchPos);
for (Direction offset : Direction.values()) {
if (offset.getAxis() == axis)
continue;
if (searchPos.equals(pos) && offset != facing)
continue;
if (BlockMovementTraits.notSupportive(searchedState, offset))
continue;
localFrontier.add(searchPos.offset(offset));
}
}
}
return positions;
}
}

View file

@ -30,8 +30,8 @@ import net.minecraft.world.World;
public class CartAssemblerBlock extends AbstractRailBlock {
public static IProperty<RailShape> RAIL_SHAPE =
EnumProperty.create("shape", RailShape.class, RailShape.EAST_WEST, RailShape.NORTH_SOUTH);
public static IProperty<RailShape> RAIL_SHAPE = EnumProperty.create("shape", RailShape.class, RailShape.EAST_WEST,
RailShape.NORTH_SOUTH);
public static BooleanProperty POWERED = BlockStateProperties.POWERED;
public CartAssemblerBlock() {
@ -72,7 +72,7 @@ public class CartAssemblerBlock extends AbstractRailBlock {
if (!cart.getPassengers().isEmpty())
return;
Contraption contraption = MountedContraption.assembleMinecart(world, pos, cart);
Contraption contraption = MountedContraption.assembleMinecart(world, pos);
if (contraption == null)
return;
float initialAngle = ContraptionEntity.yawFromVector(cart.getMotion());

View file

@ -11,7 +11,6 @@ import com.simibubi.create.modules.contraptions.components.contraptions.AllContr
import com.simibubi.create.modules.contraptions.components.contraptions.Contraption;
import net.minecraft.block.BlockState;
import net.minecraft.entity.item.minecart.AbstractMinecartEntity;
import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.state.properties.RailShape;
import net.minecraft.tileentity.TileEntity;
@ -30,8 +29,8 @@ public class MountedContraption extends Contraption {
protected AllContraptionTypes getType() {
return AllContraptionTypes.MOUNTED;
}
public static Contraption assembleMinecart(World world, BlockPos pos, AbstractMinecartEntity cart) {
public static Contraption assembleMinecart(World world, BlockPos pos) {
if (isFrozen())
return null;
@ -40,8 +39,7 @@ public class MountedContraption extends Contraption {
return null;
Contraption contraption = new MountedContraption();
Vec3d vec = cart.getMotion();
if (!contraption.searchMovedStructure(world, pos, Direction.getFacingFromVector(vec.x, vec.y, vec.z)))
if (!contraption.searchMovedStructure(world, pos, null))
return null;
Axis axis = state.get(RAIL_SHAPE) == RailShape.EAST_WEST ? Axis.X : Axis.Z;
@ -83,8 +81,8 @@ public class MountedContraption extends Contraption {
}
@Override
public void disassemble(World world, BlockPos offset, float yaw, float pitch) {
super.disassemble(world, offset, yaw, pitch, (pos, state) -> AllBlocks.MINECART_ANCHOR.typeOf(state));
public void disassemble(World world, BlockPos offset, Vec3d rotation) {
super.disassemble(world, offset, rotation, (pos, state) -> AllBlocks.MINECART_ANCHOR.typeOf(state));
}
}

View file

@ -14,6 +14,7 @@ import com.simibubi.create.AllBlocks;
import com.simibubi.create.config.AllConfigs;
import com.simibubi.create.foundation.utility.NBTHelper;
import com.simibubi.create.modules.contraptions.components.contraptions.AllContraptionTypes;
import com.simibubi.create.modules.contraptions.components.contraptions.BlockMovementTraits;
import com.simibubi.create.modules.contraptions.components.contraptions.Contraption;
import com.simibubi.create.modules.contraptions.components.contraptions.piston.MechanicalPistonBlock.PistonState;
@ -26,6 +27,7 @@ import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Direction;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.IWorld;
import net.minecraft.world.World;
import net.minecraft.world.gen.feature.template.Template.BlockInfo;
@ -140,9 +142,11 @@ public class PistonContraption extends Contraption {
break;
if (AllBlocks.MECHANICAL_PISTON_HEAD.typeOf(state) && state.get(FACING) == direction.getOpposite())
break;
if (!canPush(world, currentPos, direction))
if (!BlockMovementTraits.movementAllowed(world, currentPos))
return retracting;
frontier.add(currentPos);
if (BlockMovementTraits.notSupportive(state, orientation))
break;
}
return true;
}
@ -153,8 +157,8 @@ public class PistonContraption extends Contraption {
}
@Override
public void disassemble(World world, BlockPos offset, float yaw, float pitch) {
super.disassemble(world, offset, yaw, pitch, (pos, state) -> {
public void disassemble(World world, BlockPos offset, Vec3d rotation) {
super.disassemble(world, offset, rotation, (pos, state) -> {
BlockPos pistonPos = anchor.offset(orientation, -1);
BlockState pistonState = world.getBlockState(pistonPos);
TileEntity te = world.getTileEntity(pistonPos);

View file

@ -14,6 +14,7 @@ import com.simibubi.create.modules.logistics.InWorldProcessing;
import com.simibubi.create.modules.logistics.InWorldProcessing.Type;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.entity.Entity;
import net.minecraft.entity.item.ItemEntity;
import net.minecraft.nbt.CompoundNBT;
@ -31,7 +32,9 @@ import net.minecraft.util.math.Vec3d;
import net.minecraft.util.math.Vec3i;
import net.minecraft.util.math.shapes.ISelectionContext;
import net.minecraft.util.math.shapes.VoxelShape;
import net.minecraft.util.math.shapes.VoxelShapes;
import net.minecraft.world.World;
import net.minecraftforge.common.Tags;
public class AirCurrent {
@ -155,7 +158,15 @@ public class AirCurrent {
if (!world.isBlockPresent(currentPos))
break;
BlockState state = world.getBlockState(currentPos);
if (shouldAlwaysPass(state))
continue;
VoxelShape voxelshape = state.getCollisionShape(world, currentPos, ISelectionContext.dummy());
if (voxelshape.isEmpty())
continue;
if (voxelshape == VoxelShapes.fullCube()) {
maxDistance = i - 1;
break;
}
for (Vec3d offset : offsets) {
Vec3d rayStart = VecHelper.getCenterOf(currentPos).subtract(directionVec.scale(.5f + 1 / 32f))
@ -273,6 +284,14 @@ public class AirCurrent {
}
private static boolean shouldAlwaysPass(BlockState state) {
if (state.isIn(Tags.Blocks.FENCES))
return true;
if (state.getBlock() == Blocks.IRON_BARS)
return true;
return false;
}
public InWorldProcessing.Type getSegmentAt(float offset) {
for (AirCurrentSegment airCurrentSegment : segments) {
if (offset > airCurrentSegment.endOffset && pushing)

View file

@ -11,6 +11,8 @@ import com.simibubi.create.foundation.behaviour.scrollvalue.ScrollValueBehaviour
import com.simibubi.create.foundation.utility.Lang;
import com.simibubi.create.modules.contraptions.base.GeneratingKineticTileEntity;
import net.minecraft.entity.player.PlayerEntity;
public class MotorTileEntity extends GeneratingKineticTileEntity {
public static final int DEFAULT_SPEED = 16;
@ -47,7 +49,8 @@ public class MotorTileEntity extends GeneratingKineticTileEntity {
}
private int step(int current, boolean forward) {
if (world.getClosestPlayer(pos.getX(), pos.getY(), pos.getZ()).isSneaking())
PlayerEntity closestPlayer = world.getClosestPlayer(pos.getX(), pos.getY(), pos.getZ());
if (closestPlayer != null && closestPlayer.isSneaking())
return 1;
int magnitude = Math.abs(current) - (forward == current > 0 ? 0 : 1);

View file

@ -0,0 +1,91 @@
package com.simibubi.create.modules.logistics.block.diodes;
import java.util.Random;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.state.BooleanProperty;
import net.minecraft.state.StateContainer.Builder;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IBlockReader;
import net.minecraft.world.TickPriority;
import net.minecraft.world.World;
public class LatchBlock extends ToggleLatchBlock {
public static BooleanProperty POWERED_SIDE = BooleanProperty.create("powered_side");
public LatchBlock() {
setDefaultState(getDefaultState().with(POWERED_SIDE, false));
}
@Override
protected void fillStateContainer(Builder<Block, BlockState> builder) {
super.fillStateContainer(builder.add(POWERED_SIDE));
}
@Override
protected void updateState(World worldIn, BlockPos pos, BlockState state) {
boolean back = state.get(POWERED);
boolean shouldBack = this.shouldBePowered(worldIn, pos, state);
boolean side = state.get(POWERED_SIDE);
boolean shouldSide = getPowerOnSides(worldIn, pos, state) > 0;
TickPriority tickpriority = TickPriority.HIGH;
if (this.isFacingTowardsRepeater(worldIn, pos, state))
tickpriority = TickPriority.EXTREMELY_HIGH;
else if (side || back)
tickpriority = TickPriority.VERY_HIGH;
if (worldIn.getPendingBlockTicks().isTickPending(pos, this))
return;
if (back != shouldBack || side != shouldSide)
worldIn.getPendingBlockTicks().scheduleTick(pos, this, this.getDelay(state), tickpriority);
}
@Override
public void tick(BlockState state, World worldIn, BlockPos pos, Random random) {
boolean back = state.get(POWERED);
boolean shouldBack = this.shouldBePowered(worldIn, pos, state);
boolean side = state.get(POWERED_SIDE);
boolean shouldSide = getPowerOnSides(worldIn, pos, state) > 0;
BlockState stateIn = state;
if (back != shouldBack) {
state = state.with(POWERED, shouldBack);
if (shouldBack)
state = state.with(POWERING, true);
else if (side)
state = state.with(POWERING, false);
}
if (side != shouldSide) {
state = state.with(POWERED_SIDE, shouldSide);
if (shouldSide)
state = state.with(POWERING, false);
else if (back)
state = state.with(POWERING, true);
}
if (state != stateIn)
worldIn.setBlockState(pos, state, 2);
}
@Override
protected boolean activated(World worldIn, BlockPos pos, BlockState state) {
if (state.get(POWERED) != state.get(POWERED_SIDE))
return false;
if (!worldIn.isRemote)
worldIn.setBlockState(pos, state.cycle(POWERING), 2);
return true;
}
@Override
public boolean canConnectRedstone(BlockState state, IBlockReader world, BlockPos pos, Direction side) {
if (side == null)
return false;
return side.getAxis().isHorizontal();
}
}

View file

@ -0,0 +1,80 @@
package com.simibubi.create.modules.logistics.block.diodes;
import java.util.Random;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.block.RedstoneDiodeBlock;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.state.BooleanProperty;
import net.minecraft.state.StateContainer.Builder;
import net.minecraft.util.Direction;
import net.minecraft.util.Hand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.world.IBlockReader;
import net.minecraft.world.World;
public class ToggleLatchBlock extends RedstoneDiodeBlock {
public static BooleanProperty POWERING = BooleanProperty.create("powering");
public ToggleLatchBlock() {
super(Properties.from(Blocks.REPEATER));
setDefaultState(getDefaultState().with(POWERING, false).with(POWERED, false));
}
@Override
protected void fillStateContainer(Builder<Block, BlockState> builder) {
builder.add(POWERED, POWERING, HORIZONTAL_FACING);
}
@Override
public int getWeakPower(BlockState blockState, IBlockReader blockAccess, BlockPos pos, Direction side) {
return blockState.get(HORIZONTAL_FACING) == side ? this.getActiveSignal(blockAccess, pos, blockState) : 0;
}
@Override
protected int getDelay(BlockState state) {
return 1;
}
@Override
public boolean onBlockActivated(BlockState state, World worldIn, BlockPos pos, PlayerEntity player, Hand handIn,
BlockRayTraceResult hit) {
if (!player.isAllowEdit())
return false;
if (player.isSneaking())
return false;
return activated(worldIn, pos, state);
}
@Override
protected int getActiveSignal(IBlockReader worldIn, BlockPos pos, BlockState state) {
return state.get(POWERING) ? 15 : 0;
}
@Override
public void tick(BlockState state, World worldIn, BlockPos pos, Random random) {
boolean poweredPreviously = state.get(POWERED);
super.tick(state, worldIn, pos, random);
BlockState newState = worldIn.getBlockState(pos);
if (newState.get(POWERED) && !poweredPreviously)
worldIn.setBlockState(pos, newState.cycle(POWERING), 2);
}
protected boolean activated(World worldIn, BlockPos pos, BlockState state) {
if (!worldIn.isRemote)
worldIn.setBlockState(pos, state.cycle(POWERING), 2);
return true;
}
@Override
public boolean canConnectRedstone(BlockState state, IBlockReader world, BlockPos pos, Direction side) {
if (side == null)
return false;
return side.getAxis() == state.get(HORIZONTAL_FACING).getAxis();
}
}

View file

@ -0,0 +1,15 @@
{
"forge_marker": 1,
"variants": {
"powering": {
"true": { "model": "create:block/repeaters/redstone_latch_powered" },
"false": { "model": "create:block/repeaters/redstone_latch" }
},
"facing": {
"north": { "y": 180 },
"east": { "y": 270 },
"south": { "y": 0 },
"west": { "y": 90 }
}
}
}

View file

@ -0,0 +1,24 @@
{
"forge_marker": 1,
"variants": {
"powered=false,powering=false,facing=north": { "model": "create:block/repeaters/toggle_latch", "y": 180 },
"powered=false,powering=false,facing=east": { "model": "create:block/repeaters/toggle_latch", "y": 270 },
"powered=false,powering=false,facing=south": { "model": "create:block/repeaters/toggle_latch", "y": 0 },
"powered=false,powering=false,facing=west": { "model": "create:block/repeaters/toggle_latch", "y": 90 },
"powered=true,powering=false,facing=north": { "model": "create:block/repeaters/toggle_latch_powered", "y": 180 },
"powered=true,powering=false,facing=east": { "model": "create:block/repeaters/toggle_latch_powered", "y": 270 },
"powered=true,powering=false,facing=south": { "model": "create:block/repeaters/toggle_latch_powered", "y": 0 },
"powered=true,powering=false,facing=west": { "model": "create:block/repeaters/toggle_latch_powered", "y": 90 },
"powered=false,powering=true,facing=north": { "model": "create:block/repeaters/toggle_latch_powering", "y": 180 },
"powered=false,powering=true,facing=east": { "model": "create:block/repeaters/toggle_latch_powering", "y": 270 },
"powered=false,powering=true,facing=south": { "model": "create:block/repeaters/toggle_latch_powering", "y": 0 },
"powered=false,powering=true,facing=west": { "model": "create:block/repeaters/toggle_latch_powering", "y": 90 },
"powered=true,powering=true,facing=north": { "model": "create:block/repeaters/toggle_latch_powered_powering", "y": 180 },
"powered=true,powering=true,facing=east": { "model": "create:block/repeaters/toggle_latch_powered_powering", "y": 270 },
"powered=true,powering=true,facing=south": { "model": "create:block/repeaters/toggle_latch_powered_powering", "y": 0 },
"powered=true,powering=true,facing=west": { "model": "create:block/repeaters/toggle_latch_powered_powering", "y": 90 }
}
}

View file

@ -138,6 +138,8 @@
"block.create.linked_transposer": "Linked Transposer",
"block.create.pulse_repeater": "Pulse Repeater",
"block.create.flexpulsepeater": "Adjustable Pulse Repeater",
"block.create.redstone_latch": "Powered Latch",
"block.create.toggle_latch": "Powered Toggle Latch",
"block.create.flexpeater": "Adjustable Repeater",
"block.create.entity_detector": "Belt Observer",
"block.create.logistical_casing": "Logistical Casing",

View file

@ -1,81 +1,161 @@
{
"__comment": "Model generated using MrCrayfish's Model Creator (https://mrcrayfish.com/tools?id=mc)",
"textures": {
"gearbox_top": "create:block/gearbox_top",
"anvil": "create:block/noisy_iron_block",
"anvil2": "minecraft:block/anvil",
"gearbox": "create:block/gearbox",
"axis_top": "create:block/axis_top",
"axis": "create:block/axis",
"andesite_casing_short": "create:block/andesite_casing_short"
},
"elements": [
{
"name": "Drill",
"from": [ 4, 4, 11 ],
"to": [ 12, 12, 13 ],
"faces": {
"north": { "texture": "#anvil2", "uv": [ 3, 3, 11, 11 ] },
"east": { "texture": "#anvil2", "uv": [ 10, 5, 12, 13 ] },
"south": { "texture": "#anvil2", "uv": [ 3, 3, 11, 11 ] },
"west": { "texture": "#anvil2", "uv": [ 8, 4, 10, 12 ] },
"up": { "texture": "#anvil2", "uv": [ 5, 5, 13, 7 ] },
"down": { "texture": "#anvil2", "uv": [ 4, 3, 12, 5 ] }
}
},
{
"name": "Drill",
"from": [ 5, 5, 13 ],
"to": [ 11, 11, 15 ],
"rotation": { "origin": [ 8, 8, 8 ], "axis": "z", "angle": 22.5 },
"faces": {
"north": { "texture": "#anvil", "uv": [ 3, 3, 9, 9 ] },
"east": { "texture": "#anvil", "uv": [ 10, 5, 12, 11 ] },
"south": { "texture": "#anvil", "uv": [ 3, 3, 9, 9 ] },
"west": { "texture": "#anvil", "uv": [ 8, 4, 10, 10 ] },
"up": { "texture": "#anvil", "uv": [ 5, 5, 11, 7 ] },
"down": { "texture": "#anvil", "uv": [ 4, 3, 10, 5 ] }
}
},
{
"name": "Drill",
"from": [ 6, 6, 15 ],
"to": [ 10, 10, 17 ],
"rotation": { "origin": [ 8, 8, 8 ], "axis": "z", "angle": 45.0 },
"faces": {
"north": { "texture": "#anvil", "uv": [ 3, 3, 7, 7 ] },
"east": { "texture": "#anvil", "uv": [ 10, 5, 12, 9 ] },
"south": { "texture": "#anvil", "uv": [ 3, 3, 7, 7 ] },
"west": { "texture": "#anvil", "uv": [ 8, 4, 10, 8 ] },
"up": { "texture": "#anvil", "uv": [ 5, 5, 9, 7 ] },
"down": { "texture": "#anvil", "uv": [ 4, 3, 8, 5 ] }
}
},
{
"name": "Drill",
"from": [ 7, 7, 17 ],
"to": [ 9, 9, 19 ],
"rotation": { "origin": [ 8, 8, 8 ], "axis": "z", "angle": -22.5 },
"faces": {
"north": { "texture": "#anvil", "uv": [ 3, 3, 5, 5 ] },
"east": { "texture": "#anvil", "uv": [ 10, 5, 12, 7 ] },
"south": { "texture": "#anvil", "uv": [ 3, 3, 5, 5 ] },
"west": { "texture": "#anvil", "uv": [ 8, 4, 10, 6 ] },
"up": { "texture": "#anvil", "uv": [ 5, 5, 7, 7 ] },
"down": { "texture": "#anvil", "uv": [ 4, 3, 6, 5 ] }
}
},
{
"name": "Shaft",
"from": [ 6, 6, 0 ],
"to": [ 10, 10, 11 ],
"faces": {
"north": { "texture": "#axis_top", "uv": [ 6, 6, 10, 10 ] },
"east": { "texture": "#axis", "uv": [ 6, 0, 10, 11 ], "rotation": 90 },
"west": { "texture": "#axis", "uv": [ 6, 0, 10, 11 ], "rotation": 270 },
"up": { "texture": "#axis", "uv": [ 6, 0, 10, 11 ] },
"down": { "texture": "#axis", "uv": [ 6, 0, 10, 11 ] }
}
}
]
"credit": "Made with Blockbench",
"parent": "block/block",
"textures": {
"0": "create:block/axis_top",
"1": "create:block/axis",
"2": "block/anvil",
"7": "block/polished_andesite",
"10": "create:block/andesite_casing_very_short",
"particle": "block/anvil"
},
"elements": [
{
"name": "Axle",
"from": [6, 6, 0],
"to": [10, 10, 4],
"shade": false,
"faces": {
"north": {"uv": [6, 6, 10, 10], "texture": "#0"},
"east": {"uv": [6, 12, 10, 16], "rotation": 90, "texture": "#1"},
"west": {"uv": [6, 0, 10, 4], "rotation": 270, "texture": "#1"},
"up": {"uv": [6, 12, 10, 16], "texture": "#1"},
"down": {"uv": [6, 0, 10, 4], "rotation": 180, "texture": "#1"}
}
},
{
"name": "Core",
"from": [5, 5, 9],
"to": [11, 11, 12],
"rotation": {"angle": 45, "axis": "z", "origin": [8, 8, 8]},
"faces": {
"north": {"uv": [0, 0, 6, 6], "texture": "#7"},
"east": {"uv": [0, 2, 6, 5], "rotation": 270, "texture": "#10"},
"south": {"uv": [5, 0, 11, 6], "texture": "#2"},
"west": {"uv": [0, 2, 6, 5], "rotation": 90, "texture": "#10"},
"up": {"uv": [0, 2, 6, 5], "rotation": 180, "texture": "#10"},
"down": {"uv": [0, 2, 6, 5], "texture": "#10"}
}
},
{
"name": "Top",
"from": [6, 11, 9],
"to": [10, 13, 13],
"rotation": {"angle": -45, "axis": "z", "origin": [8, 8, 8]},
"faces": {
"north": {"uv": [0, 0, 4, 2], "texture": "#10"},
"east": {"uv": [0, 1, 4, 3], "texture": "#10"},
"south": {"uv": [0, 0, 2, 4], "rotation": 90, "texture": "#10"},
"west": {"uv": [0, 1, 4, 3], "texture": "#10"},
"up": {"uv": [0, 0, 4, 4], "rotation": 90, "texture": "#10"},
"down": {"uv": [0, 0, 4, 4], "texture": "#10"}
}
},
{
"name": "Bottom",
"from": [6, 3, 9],
"to": [10, 5, 13],
"rotation": {"angle": -45, "axis": "z", "origin": [8, 8, 8]},
"faces": {
"north": {"uv": [0, 0, 4, 2], "texture": "#10"},
"east": {"uv": [0, 1, 4, 3], "rotation": 180, "texture": "#10"},
"south": {"uv": [0, 0, 2, 4], "rotation": 90, "texture": "#10"},
"west": {"uv": [0, 1, 4, 3], "rotation": 180, "texture": "#10"},
"up": {"uv": [0, 0, 4, 4], "texture": "#10"},
"down": {"uv": [0, 0, 4, 4], "rotation": 90, "texture": "#10"}
}
},
{
"name": "Left",
"from": [3, 6, 9],
"to": [5, 10, 13],
"rotation": {"angle": -45, "axis": "z", "origin": [8, 8, 8]},
"faces": {
"north": {"uv": [0, 0, 2, 4], "texture": "#10"},
"east": {"uv": [0, 0, 4, 4], "texture": "#10"},
"south": {"uv": [0, 0, 2, 4], "texture": "#10"},
"west": {"uv": [0, 0, 4, 4], "texture": "#10"},
"up": {"uv": [0, 1, 4, 3], "rotation": 270, "texture": "#10"},
"down": {"uv": [0, 1, 4, 3], "rotation": 270, "texture": "#10"}
}
},
{
"name": "Right",
"from": [11, 6, 9],
"to": [13, 10, 13],
"rotation": {"angle": -45, "axis": "z", "origin": [8, 8, 8]},
"faces": {
"north": {"uv": [0, 0, 2, 4], "texture": "#10"},
"east": {"uv": [0, 0, 4, 4], "texture": "#10"},
"south": {"uv": [0, 0, 2, 4], "texture": "#10"},
"west": {"uv": [0, 0, 4, 4], "texture": "#10"},
"up": {"uv": [0, 1, 4, 3], "rotation": 90, "texture": "#10"},
"down": {"uv": [0, 1, 4, 3], "rotation": 90, "texture": "#10"}
}
},
{
"name": "Bit1",
"from": [5.5, 5.5, 12],
"to": [10.5, 10.5, 14],
"rotation": {"angle": 45, "axis": "z", "origin": [8, 8, 8]},
"faces": {
"north": {"uv": [0, 0, 5, 5], "texture": "#2"},
"east": {"uv": [0, 0, 5, 2], "rotation": 90, "texture": "#2"},
"south": {"uv": [1, 2, 6, 7], "texture": "#2"},
"west": {"uv": [0, 0, 5, 2], "rotation": 270, "texture": "#2"},
"up": {"uv": [0, 0, 5, 2], "texture": "#2"},
"down": {"uv": [0, 0, 5, 2], "texture": "#2"}
}
},
{
"name": "Bit2",
"from": [6, 6, 14],
"to": [10, 10, 16],
"rotation": {"angle": 45, "axis": "z", "origin": [8, 8, 7]},
"faces": {
"north": {"uv": [0, 0, 4, 4], "texture": "#2"},
"east": {"uv": [0, 0, 4, 2], "rotation": 90, "texture": "#2"},
"south": {"uv": [0, 0, 4, 4], "texture": "#2"},
"west": {"uv": [0, 0, 4, 2], "rotation": 270, "texture": "#2"},
"up": {"uv": [0, 0, 4, 2], "texture": "#2"},
"down": {"uv": [0, 0, 4, 2], "rotation": 180, "texture": "#2"}
}
},
{
"name": "Bit3",
"from": [6.5, 6.5, 16],
"to": [9.5, 9.5, 18],
"rotation": {"angle": -45, "axis": "z", "origin": [8, 8, 7]},
"faces": {
"north": {"uv": [0, 0, 3, 3], "texture": "#2"},
"east": {"uv": [0, 0, 2, 3], "texture": "#2"},
"south": {"uv": [0, 0, 3, 3], "texture": "#2"},
"west": {"uv": [0, 0, 3, 2], "rotation": 270, "texture": "#2"},
"up": {"uv": [0, 0, 3, 2], "texture": "#2"},
"down": {"uv": [0, 0, 3, 2], "texture": "#2"}
}
},
{
"name": "Bit4",
"from": [7, 7, 18],
"to": [9, 9, 20],
"rotation": {"angle": 45, "axis": "z", "origin": [8, 8, 7]},
"faces": {
"north": {"uv": [0, 0, 2, 2], "texture": "#2"},
"east": {"uv": [0, 0, 2, 2], "texture": "#2"},
"south": {"uv": [5, 5, 7, 7], "texture": "#2"},
"west": {"uv": [0, 0, 2, 2], "texture": "#2"},
"up": {"uv": [0, 0, 2, 2], "texture": "#2"},
"down": {"uv": [0, 0, 2, 2], "texture": "#2"}
}
}
],
"display": {},
"groups": [
{
"name": "head",
"origin": [8, 8, 8],
"children": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
}
]
}

View file

@ -1,69 +1,78 @@
{
"__comment": "Model generated using MrCrayfish's Model Creator (https://mrcrayfish.com/tools?id=mc)",
"credit": "Made with Blockbench",
"parent": "block/block",
"textures": {
"particle": "create:block/gearbox_top",
"gearbox_top": "create:block/gearbox_top",
"anvil": "minecraft:block/anvil",
"gearbox": "create:block/gearbox",
"andesite_casing_short": "create:block/andesite_casing_short"
},
"elements": [
{
"name": "Body",
"from": [ 2, 2, 1 ],
"to": [ 14, 14, 11 ],
"faces": {
"north": { "texture": "#gearbox", "uv": [ 2, 2, 14, 14 ] },
"south": { "texture": "#gearbox", "uv": [ 2, 2, 14, 14 ] }
}
},
{
"name": "Bottom",
"from": [ 0, 0, 0 ],
"to": [ 16, 2, 12 ],
"faces": {
"north": { "texture": "#gearbox_top", "uv": [ 0, 14, 16, 16 ] },
"east": { "texture": "#andesite_casing_short", "uv": [ 0, 4, 2, 16 ], "rotation": 270 },
"south": { "texture": "#gearbox_top", "uv": [ 0, 14, 16, 16 ] },
"west": { "texture": "#andesite_casing_short", "uv": [ 0, 4, 2, 16 ], "rotation": 270 },
"up": { "texture": "#andesite_casing_short", "uv": [ 0, 4, 16, 16 ] },
"down": { "texture": "#andesite_casing_short", "uv": [ 0, 4, 16, 16 ] }
}
},
{
"name": "Top",
"from": [ 0, 14, 0 ],
"to": [ 16, 16, 12 ],
"faces": {
"north": { "texture": "#gearbox_top", "uv": [ 0, 0, 16, 2 ] },
"east": { "texture": "#andesite_casing_short", "uv": [ 14, 4, 16, 16 ], "rotation": 270 },
"south": { "texture": "#gearbox_top", "uv": [ 0, 0, 16, 2 ] },
"west": { "texture": "#andesite_casing_short", "uv": [ 14, 4, 16, 16 ], "rotation": 270 },
"up": { "texture": "#andesite_casing_short", "uv": [ 0, 4, 16, 16 ] },
"down": { "texture": "#andesite_casing_short", "uv": [ 0, 4, 16, 16 ] }
}
},
{
"name": "Side",
"from": [ 0, 2, 0 ],
"to": [ 2, 14, 12 ],
"faces": {
"north": { "texture": "#gearbox_top", "uv": [ 14, 2, 16, 14 ] },
"east": { "texture": "#andesite_casing_short", "uv": [ 2, 4, 14, 16 ], "rotation": 90 },
"south": { "texture": "#gearbox_top", "uv": [ 0, 2, 2, 14 ] },
"west": { "texture": "#andesite_casing_short", "uv": [ 2, 4, 14, 16 ], "rotation": 270 }
}
},
{
"name": "Side",
"from": [ 14, 2, 0 ],
"to": [ 16, 14, 12 ],
"faces": {
"north": { "texture": "#gearbox_top", "uv": [ 0, 2, 2, 14 ] },
"east": { "texture": "#andesite_casing_short", "uv": [ 2, 4, 14, 16 ], "rotation": 90 },
"south": { "texture": "#gearbox_top", "uv": [ 14, 2, 16, 14 ] },
"west": { "texture": "#andesite_casing_short", "uv": [ 2, 4, 14, 16 ], "rotation": 270 }
}
}
]
"10": "create:block/andesite_casing_very_short",
"particle": "block/anvil",
"gearbox_top": "create:block/gearbox_top",
"gearbox": "create:block/gearbox",
"andesite_casing_short": "create:block/andesite_casing_short"
},
"elements": [
{
"name": "Body",
"from": [2, 2, 1],
"to": [14, 14, 9],
"faces": {
"north": {"uv": [2, 2, 14, 14], "texture": "#gearbox"},
"south": {"uv": [2, 2, 14, 14], "texture": "#gearbox"}
}
},
{
"name": "Bottom",
"from": [0, 0, 0],
"to": [16, 2, 10],
"faces": {
"north": {"uv": [0, 14, 16, 16], "texture": "#gearbox_top"},
"east": {"uv": [14, 6, 16, 16], "rotation": 90, "texture": "#10"},
"south": {"uv": [0, 14, 16, 16], "texture": "#gearbox_top"},
"west": {"uv": [14, 6, 16, 16], "rotation": 90, "texture": "#10"},
"up": {"uv": [0, 4, 16, 16], "texture": "#andesite_casing_short"},
"down": {"uv": [0, 6, 16, 16], "texture": "#10"}
}
},
{
"name": "Top",
"from": [0, 14, 0],
"to": [16, 16, 10],
"faces": {
"north": {"uv": [0, 0, 16, 2], "texture": "#gearbox_top"},
"east": {"uv": [0, 6, 2, 16], "rotation": 90, "texture": "#10"},
"south": {"uv": [0, 0, 16, 2], "texture": "#gearbox_top"},
"west": {"uv": [0, 6, 2, 16], "rotation": 90, "texture": "#10"},
"up": {"uv": [0, 6, 16, 16], "texture": "#10"},
"down": {"uv": [0, 4, 16, 16], "texture": "#andesite_casing_short"}
}
},
{
"name": "Side",
"from": [0, 2, 0],
"to": [2, 14, 10],
"faces": {
"north": {"uv": [14, 2, 16, 14], "texture": "#gearbox_top"},
"east": {"uv": [2, 4, 14, 16], "rotation": 90, "texture": "#andesite_casing_short"},
"south": {"uv": [0, 2, 2, 14], "texture": "#gearbox_top"},
"west": {"uv": [2, 6, 14, 16], "rotation": 90, "texture": "#10"}
}
},
{
"name": "Side",
"from": [14, 2, 0],
"to": [16, 14, 10],
"faces": {
"north": {"uv": [0, 2, 2, 14], "texture": "#gearbox_top"},
"east": {"uv": [2, 6, 14, 16], "rotation": 90, "texture": "#10"},
"south": {"uv": [14, 2, 16, 14], "texture": "#gearbox_top"},
"west": {"uv": [2, 4, 14, 16], "rotation": 270, "texture": "#andesite_casing_short"}
}
}
],
"display": {},
"groups": [
{
"name": "casing",
"origin": [8, 8, 8],
"children": [0, 1, 2, 3, 4]
}
]
}

View file

@ -0,0 +1,7 @@
{
"parent": "create:block/repeaters/toggle_latch",
"textures": {
"3": "create:block/redstone_latch",
"particle": "create:block/redstone_latch"
}
}

View file

@ -0,0 +1,7 @@
{
"parent": "create:block/repeaters/toggle_latch_powering",
"textures": {
"3": "create:block/redstone_latch_powered",
"particle": "create:block/redstone_latch_powered"
}
}

View file

@ -0,0 +1,100 @@
{
"credit": "Made with Blockbench",
"parent": "block/block",
"textures": {
"3": "create:block/toggle_latch",
"torch": "minecraft:block/redstone_torch_off",
"smooth_stone": "minecraft:block/smooth_stone",
"particle": "minecraft:block/cobblestone",
"base": "minecraft:block/cobblestone",
"lever": "minecraft:block/lever"
},
"elements": [
{
"name": "Top",
"from": [3, 2, 4],
"to": [13, 3, 12],
"faces": {
"north": {"uv": [3, 4, 13, 5], "rotation": 180, "texture": "#3"},
"east": {"uv": [12, 4, 13, 12], "rotation": 90, "texture": "#3"},
"south": {"uv": [3, 11, 13, 12], "texture": "#3"},
"west": {"uv": [3, 4, 4, 12], "rotation": 90, "texture": "#3"},
"up": {"uv": [3, 4, 13, 12], "texture": "#3"}
}
},
{
"name": "circuit",
"from": [0, 0, 0],
"to": [16, 2, 16],
"faces": {
"north": {"uv": [0, 0, 16, 2], "texture": "#smooth_stone"},
"east": {"uv": [0, 0, 16, 2], "texture": "#smooth_stone"},
"south": {"uv": [0, 0, 16, 2], "texture": "#smooth_stone"},
"west": {"uv": [0, 0, 16, 2], "texture": "#smooth_stone"},
"up": {"uv": [0, 0, 16, 16], "texture": "#3"},
"down": {"uv": [0, 0, 16, 16], "texture": "#smooth_stone"}
}
},
{
"name": "Front Torch",
"from": [6, 2, 1],
"to": [10, 8, 3],
"rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 7]},
"faces": {
"north": {"uv": [6, 5, 10, 11], "texture": "#torch"},
"south": {"uv": [6, 5, 10, 11], "texture": "#torch"}
}
},
{
"name": "Front Torch",
"from": [7, 2, 0],
"to": [9, 8, 4],
"rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 7]},
"faces": {
"east": {"uv": [6, 5, 10, 11], "texture": "#torch"},
"west": {"uv": [6, 5, 10, 11], "texture": "#torch"}
}
},
{
"name": "Front Torch Top",
"from": [7, 6, 1],
"to": [9, 7, 3],
"rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 7]},
"faces": {
"up": {"uv": [7, 6, 9, 8], "texture": "#torch"}
}
},
{
"from": [4, 2, 5],
"to": [12, 5, 11],
"rotation": {"angle": 0, "axis": "y", "origin": [8, 9, 8]},
"faces": {
"north": {"uv": [4, 0, 12, 3], "texture": "#base"},
"east": {"uv": [5, 0, 11, 3], "texture": "#base"},
"south": {"uv": [4, 0, 12, 3], "texture": "#base"},
"west": {"uv": [5, 0, 11, 3], "texture": "#base"},
"up": {"uv": [5, 4, 11, 12], "rotation": 90, "texture": "#base"},
"down": {"uv": [5, 4, 11, 12], "rotation": 270, "texture": "#base", "cullface": "down"}
}
},
{
"from": [11.24264, 4.75736, 7],
"to": [13.24264, 14.75736, 9],
"rotation": {"angle": -45, "axis": "z", "origin": [8, 9, 8]},
"faces": {
"north": {"uv": [7, 6, 9, 16], "texture": "#lever"},
"east": {"uv": [7, 6, 9, 16], "texture": "#lever"},
"south": {"uv": [7, 6, 9, 16], "texture": "#lever"},
"west": {"uv": [7, 6, 9, 16], "texture": "#lever"},
"up": {"uv": [7, 6, 9, 8], "rotation": 90, "texture": "#lever"}
}
}
],
"groups": [0, 1, 2, 3, 4,
{
"name": "lever",
"origin": [8, 8, 8],
"children": [5, 6]
}
]
}

View file

@ -0,0 +1,7 @@
{
"parent": "create:block/repeaters/toggle_latch",
"textures": {
"3": "create:block/toggle_latch_powered",
"particle": "create:block/toggle_latch_powered"
}
}

View file

@ -0,0 +1,7 @@
{
"parent": "create:block/repeaters/toggle_latch_powering",
"textures": {
"3": "create:block/toggle_latch_powered_powering",
"particle": "create:block/toggle_latch_powered_powering"
}
}

View file

@ -0,0 +1,103 @@
{
"credit": "Made with Blockbench",
"parent": "block/block",
"ambientocclusion": false,
"textures": {
"3": "create:block/toggle_latch",
"5": "create:block/toggle_latch_powered_powering",
"torch": "minecraft:block/redstone_torch",
"smooth_stone": "minecraft:block/smooth_stone",
"particle": "minecraft:block/cobblestone",
"base": "minecraft:block/cobblestone",
"lever": "minecraft:block/lever"
},
"elements": [
{
"name": "Top",
"from": [3, 2, 4],
"to": [13, 3, 12],
"faces": {
"north": {"uv": [3, 4, 13, 5], "rotation": 180, "texture": "#5"},
"east": {"uv": [12, 4, 13, 12], "rotation": 90, "texture": "#5"},
"south": {"uv": [3, 11, 13, 12], "texture": "#5"},
"west": {"uv": [3, 4, 4, 12], "rotation": 90, "texture": "#5"},
"up": {"uv": [3, 4, 13, 12], "texture": "#5"},
"down": {"uv": [0, 0, 10, 8], "texture": "#5"}
}
},
{
"name": "circuit",
"from": [0, 0, 0],
"to": [16, 2, 16],
"faces": {
"north": {"uv": [0, 0, 16, 2], "texture": "#smooth_stone"},
"east": {"uv": [0, 0, 16, 2], "texture": "#smooth_stone"},
"south": {"uv": [0, 0, 16, 2], "texture": "#smooth_stone"},
"west": {"uv": [0, 0, 16, 2], "texture": "#smooth_stone"},
"up": {"uv": [0, 0, 16, 16], "texture": "#3"},
"down": {"uv": [0, 0, 16, 16], "texture": "#smooth_stone"}
}
},
{
"name": "Front Torch",
"from": [6, 2, 1],
"to": [10, 8, 3],
"rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 7]},
"faces": {
"north": {"uv": [6, 5, 10, 11], "texture": "#torch"},
"south": {"uv": [6, 5, 10, 11], "texture": "#torch"}
}
},
{
"name": "Front Torch",
"from": [7, 2, 0],
"to": [9, 8, 4],
"rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 7]},
"faces": {
"east": {"uv": [6, 5, 10, 11], "texture": "#torch"},
"west": {"uv": [6, 5, 10, 11], "texture": "#torch"}
}
},
{
"name": "Front Torch Top",
"from": [7, 6, 1],
"to": [9, 7, 3],
"rotation": {"angle": 0, "axis": "y", "origin": [8, 8, 7]},
"faces": {
"up": {"uv": [7, 6, 9, 8], "texture": "#torch"}
}
},
{
"from": [4, 2, 5],
"to": [12, 5, 11],
"rotation": {"angle": 0, "axis": "y", "origin": [8, 9, 8]},
"faces": {
"north": {"uv": [4, 0, 12, 3], "texture": "#base"},
"east": {"uv": [5, 0, 11, 3], "texture": "#base"},
"south": {"uv": [4, 0, 12, 3], "texture": "#base"},
"west": {"uv": [5, 0, 11, 3], "texture": "#base"},
"up": {"uv": [5, 4, 11, 12], "rotation": 90, "texture": "#base"},
"down": {"uv": [5, 4, 11, 12], "rotation": 270, "texture": "#base", "cullface": "down"}
}
},
{
"from": [7, 3, 7],
"to": [9, 13, 9],
"rotation": {"angle": 45, "axis": "z", "origin": [8, 3, 8]},
"faces": {
"north": {"uv": [7, 6, 9, 16], "texture": "#lever"},
"east": {"uv": [7, 6, 9, 16], "texture": "#lever"},
"south": {"uv": [7, 6, 9, 16], "texture": "#lever"},
"west": {"uv": [7, 6, 9, 16], "texture": "#lever"},
"up": {"uv": [7, 6, 9, 8], "rotation": 90, "texture": "#lever"}
}
}
],
"groups": [0, 1, 2, 3, 4,
{
"name": "lever",
"origin": [8, 8, 8],
"children": [5, 6]
}
]
}

View file

@ -1,125 +1,226 @@
{
"__comment": "Model generated using MrCrayfish's Model Creator (https://mrcrayfish.com/tools?id=mc)",
"textures": {
"gearbox_top": "create:block/gearbox_top",
"anvil": "create:block/noisy_iron_block",
"anvil2": "minecraft:block/anvil",
"gearbox": "create:block/gearbox",
"andesite_casing_short": "create:block/andesite_casing_short"
},
"credit": "Made with Blockbench",
"parent": "create:block/block",
"elements": [
{
"name": "Body",
"from": [ 2, 2, 1 ],
"to": [ 14, 14, 11 ],
"faces": {
"north": { "texture": "#gearbox", "uv": [ 2, 2, 14, 14 ] },
"south": { "texture": "#gearbox", "uv": [ 2, 2, 14, 14 ] }
}
},
{
"name": "Bottom",
"from": [ 0, 0, 0 ],
"to": [ 16, 2, 12 ],
"faces": {
"north": { "texture": "#gearbox_top", "uv": [ 0, 14, 16, 16 ] },
"east": { "texture": "#andesite_casing_short", "uv": [ 0, 4, 2, 16 ], "rotation": 270 },
"south": { "texture": "#gearbox_top", "uv": [ 0, 14, 16, 16 ] },
"west": { "texture": "#andesite_casing_short", "uv": [ 0, 4, 2, 16 ], "rotation": 270 },
"up": { "texture": "#andesite_casing_short", "uv": [ 0, 4, 16, 16 ] },
"down": { "texture": "#andesite_casing_short", "uv": [ 0, 4, 16, 16 ] }
}
},
{
"name": "Top",
"from": [ 0, 14, 0 ],
"to": [ 16, 16, 12 ],
"faces": {
"north": { "texture": "#gearbox_top", "uv": [ 0, 0, 16, 2 ] },
"east": { "texture": "#andesite_casing_short", "uv": [ 14, 4, 16, 16 ], "rotation": 270 },
"south": { "texture": "#gearbox_top", "uv": [ 0, 0, 16, 2 ] },
"west": { "texture": "#andesite_casing_short", "uv": [ 14, 4, 16, 16 ], "rotation": 270 },
"up": { "texture": "#andesite_casing_short", "uv": [ 0, 4, 16, 16 ] },
"down": { "texture": "#andesite_casing_short", "uv": [ 0, 4, 16, 16 ] }
}
},
{
"name": "Side",
"from": [ 0, 2, 0 ],
"to": [ 2, 14, 12 ],
"faces": {
"north": { "texture": "#gearbox_top", "uv": [ 14, 2, 16, 14 ] },
"east": { "texture": "#andesite_casing_short", "uv": [ 2, 4, 14, 16 ], "rotation": 90 },
"south": { "texture": "#gearbox_top", "uv": [ 0, 2, 2, 14 ] },
"west": { "texture": "#andesite_casing_short", "uv": [ 2, 4, 14, 16 ], "rotation": 270 }
}
},
{
"name": "Side",
"from": [ 14, 2, 0 ],
"to": [ 16, 14, 12 ],
"faces": {
"north": { "texture": "#gearbox_top", "uv": [ 0, 2, 2, 14 ] },
"east": { "texture": "#andesite_casing_short", "uv": [ 2, 4, 14, 16 ], "rotation": 90 },
"south": { "texture": "#gearbox_top", "uv": [ 14, 2, 16, 14 ] },
"west": { "texture": "#andesite_casing_short", "uv": [ 2, 4, 14, 16 ], "rotation": 270 }
}
},
{
"name": "Drill",
"from": [ 4, 4, 11 ],
"to": [ 12, 12, 13 ],
"faces": {
"north": { "texture": "#anvil2", "uv": [ 3, 3, 11, 11 ] },
"east": { "texture": "#anvil2", "uv": [ 10, 5, 12, 13 ] },
"south": { "texture": "#anvil2", "uv": [ 3, 3, 11, 11 ] },
"west": { "texture": "#anvil2", "uv": [ 8, 4, 10, 12 ] },
"up": { "texture": "#anvil2", "uv": [ 5, 5, 13, 7 ] },
"down": { "texture": "#anvil2", "uv": [ 4, 3, 12, 5 ] }
}
},
{
"name": "Drill",
"from": [ 5, 5, 13 ],
"to": [ 11, 11, 15 ],
"rotation": { "origin": [ 8, 8, 8 ], "axis": "z", "angle": 22.5 },
"faces": {
"north": { "texture": "#anvil", "uv": [ 3, 3, 9, 9 ] },
"east": { "texture": "#anvil", "uv": [ 10, 5, 12, 11 ] },
"south": { "texture": "#anvil", "uv": [ 3, 3, 9, 9 ] },
"west": { "texture": "#anvil", "uv": [ 8, 4, 10, 10 ] },
"up": { "texture": "#anvil", "uv": [ 5, 5, 11, 7 ] },
"down": { "texture": "#anvil", "uv": [ 4, 3, 10, 5 ] }
}
},
{
"name": "Drill",
"from": [ 6, 6, 15 ],
"to": [ 10, 10, 17 ],
"rotation": { "origin": [ 8, 8, 8 ], "axis": "z", "angle": 45.0 },
"faces": {
"north": { "texture": "#anvil", "uv": [ 3, 3, 7, 7 ] },
"east": { "texture": "#anvil", "uv": [ 10, 5, 12, 9 ] },
"south": { "texture": "#anvil", "uv": [ 3, 3, 7, 7 ] },
"west": { "texture": "#anvil", "uv": [ 8, 4, 10, 8 ] },
"up": { "texture": "#anvil", "uv": [ 5, 5, 9, 7 ] },
"down": { "texture": "#anvil", "uv": [ 4, 3, 8, 5 ] }
}
},
{
"name": "Drill",
"from": [ 7, 7, 17 ],
"to": [ 9, 9, 19 ],
"rotation": { "origin": [ 8, 8, 8 ], "axis": "z", "angle": -22.5 },
"faces": {
"north": { "texture": "#anvil", "uv": [ 3, 3, 5, 5 ] },
"east": { "texture": "#anvil", "uv": [ 10, 5, 12, 7 ] },
"south": { "texture": "#anvil", "uv": [ 3, 3, 5, 5 ] },
"west": { "texture": "#anvil", "uv": [ 8, 4, 10, 6 ] },
"up": { "texture": "#anvil", "uv": [ 5, 5, 7, 7 ] },
"down": { "texture": "#anvil", "uv": [ 4, 3, 6, 5 ] }
}
}
]
"textures": {
"0": "create:block/axis_top",
"1": "create:block/axis",
"2": "block/anvil",
"7": "block/polished_andesite",
"10": "create:block/andesite_casing_very_short",
"particle": "block/anvil",
"gearbox_top": "create:block/gearbox_top",
"gearbox": "create:block/gearbox",
"andesite_casing_short": "create:block/andesite_casing_short"
},
"elements": [
{
"name": "Axle",
"from": [6, 6, 0],
"to": [10, 10, 4],
"shade": false,
"faces": {
"north": {"uv": [6, 6, 10, 10], "texture": "#0"},
"east": {"uv": [6, 12, 10, 16], "rotation": 90, "texture": "#1"},
"west": {"uv": [6, 0, 10, 4], "rotation": 270, "texture": "#1"},
"up": {"uv": [6, 12, 10, 16], "texture": "#1"},
"down": {"uv": [6, 0, 10, 4], "rotation": 180, "texture": "#1"}
}
},
{
"name": "Core",
"from": [5, 5, 9],
"to": [11, 11, 12],
"rotation": {"angle": 45, "axis": "z", "origin": [8, 8, 8]},
"faces": {
"north": {"uv": [0, 0, 6, 6], "texture": "#7"},
"east": {"uv": [0, 2, 6, 5], "rotation": 270, "texture": "#10"},
"south": {"uv": [5, 0, 11, 6], "texture": "#2"},
"west": {"uv": [0, 2, 6, 5], "rotation": 90, "texture": "#10"},
"up": {"uv": [0, 2, 6, 5], "rotation": 180, "texture": "#10"},
"down": {"uv": [0, 2, 6, 5], "texture": "#10"}
}
},
{
"name": "Top",
"from": [6, 11, 9],
"to": [10, 13, 13],
"rotation": {"angle": -45, "axis": "z", "origin": [8, 8, 8]},
"faces": {
"north": {"uv": [0, 0, 4, 2], "texture": "#10"},
"east": {"uv": [0, 1, 4, 3], "texture": "#10"},
"south": {"uv": [0, 0, 2, 4], "rotation": 90, "texture": "#10"},
"west": {"uv": [0, 1, 4, 3], "texture": "#10"},
"up": {"uv": [0, 0, 4, 4], "rotation": 90, "texture": "#10"},
"down": {"uv": [0, 0, 4, 4], "texture": "#10"}
}
},
{
"name": "Bottom",
"from": [6, 3, 9],
"to": [10, 5, 13],
"rotation": {"angle": -45, "axis": "z", "origin": [8, 8, 8]},
"faces": {
"north": {"uv": [0, 0, 4, 2], "texture": "#10"},
"east": {"uv": [0, 1, 4, 3], "rotation": 180, "texture": "#10"},
"south": {"uv": [0, 0, 2, 4], "rotation": 90, "texture": "#10"},
"west": {"uv": [0, 1, 4, 3], "rotation": 180, "texture": "#10"},
"up": {"uv": [0, 0, 4, 4], "texture": "#10"},
"down": {"uv": [0, 0, 4, 4], "rotation": 90, "texture": "#10"}
}
},
{
"name": "Left",
"from": [3, 6, 9],
"to": [5, 10, 13],
"rotation": {"angle": -45, "axis": "z", "origin": [8, 8, 8]},
"faces": {
"north": {"uv": [0, 0, 2, 4], "texture": "#10"},
"east": {"uv": [0, 0, 4, 4], "texture": "#10"},
"south": {"uv": [0, 0, 2, 4], "texture": "#10"},
"west": {"uv": [0, 0, 4, 4], "texture": "#10"},
"up": {"uv": [0, 1, 4, 3], "rotation": 270, "texture": "#10"},
"down": {"uv": [0, 1, 4, 3], "rotation": 270, "texture": "#10"}
}
},
{
"name": "Right",
"from": [11, 6, 9],
"to": [13, 10, 13],
"rotation": {"angle": -45, "axis": "z", "origin": [8, 8, 8]},
"faces": {
"north": {"uv": [0, 0, 2, 4], "texture": "#10"},
"east": {"uv": [0, 0, 4, 4], "texture": "#10"},
"south": {"uv": [0, 0, 2, 4], "texture": "#10"},
"west": {"uv": [0, 0, 4, 4], "texture": "#10"},
"up": {"uv": [0, 1, 4, 3], "rotation": 90, "texture": "#10"},
"down": {"uv": [0, 1, 4, 3], "rotation": 90, "texture": "#10"}
}
},
{
"name": "Bit1",
"from": [5.5, 5.5, 12],
"to": [10.5, 10.5, 14],
"rotation": {"angle": 45, "axis": "z", "origin": [8, 8, 8]},
"faces": {
"north": {"uv": [0, 0, 5, 5], "texture": "#2"},
"east": {"uv": [0, 0, 5, 2], "rotation": 90, "texture": "#2"},
"south": {"uv": [1, 2, 6, 7], "texture": "#2"},
"west": {"uv": [0, 0, 5, 2], "rotation": 270, "texture": "#2"},
"up": {"uv": [0, 0, 5, 2], "texture": "#2"},
"down": {"uv": [0, 0, 5, 2], "texture": "#2"}
}
},
{
"name": "Bit2",
"from": [6, 6, 14],
"to": [10, 10, 16],
"rotation": {"angle": 45, "axis": "z", "origin": [8, 8, 7]},
"faces": {
"north": {"uv": [0, 0, 4, 4], "texture": "#2"},
"east": {"uv": [0, 0, 4, 2], "rotation": 90, "texture": "#2"},
"south": {"uv": [0, 0, 4, 4], "texture": "#2"},
"west": {"uv": [0, 0, 4, 2], "rotation": 270, "texture": "#2"},
"up": {"uv": [0, 0, 4, 2], "texture": "#2"},
"down": {"uv": [0, 0, 4, 2], "rotation": 180, "texture": "#2"}
}
},
{
"name": "Bit3",
"from": [6.5, 6.5, 16],
"to": [9.5, 9.5, 18],
"rotation": {"angle": -45, "axis": "z", "origin": [8, 8, 7]},
"faces": {
"north": {"uv": [0, 0, 3, 3], "texture": "#2"},
"east": {"uv": [0, 0, 2, 3], "texture": "#2"},
"south": {"uv": [0, 0, 3, 3], "texture": "#2"},
"west": {"uv": [0, 0, 3, 2], "rotation": 270, "texture": "#2"},
"up": {"uv": [0, 0, 3, 2], "texture": "#2"},
"down": {"uv": [0, 0, 3, 2], "texture": "#2"}
}
},
{
"name": "Bit4",
"from": [7, 7, 18],
"to": [9, 9, 20],
"rotation": {"angle": 45, "axis": "z", "origin": [8, 8, 7]},
"faces": {
"north": {"uv": [0, 0, 2, 2], "texture": "#2"},
"east": {"uv": [0, 0, 2, 2], "texture": "#2"},
"south": {"uv": [5, 5, 7, 7], "texture": "#2"},
"west": {"uv": [0, 0, 2, 2], "texture": "#2"},
"up": {"uv": [0, 0, 2, 2], "texture": "#2"},
"down": {"uv": [0, 0, 2, 2], "texture": "#2"}
}
},
{
"name": "Body",
"from": [2, 2, 1],
"to": [14, 14, 9],
"faces": {
"north": {"uv": [2, 2, 14, 14], "texture": "#gearbox"},
"south": {"uv": [2, 2, 14, 14], "texture": "#gearbox"}
}
},
{
"name": "Bottom",
"from": [0, 0, 0],
"to": [16, 2, 10],
"faces": {
"north": {"uv": [0, 14, 16, 16], "texture": "#gearbox_top"},
"east": {"uv": [14, 6, 16, 16], "rotation": 90, "texture": "#10"},
"south": {"uv": [0, 14, 16, 16], "texture": "#gearbox_top"},
"west": {"uv": [14, 6, 16, 16], "rotation": 90, "texture": "#10"},
"up": {"uv": [0, 4, 16, 16], "texture": "#andesite_casing_short"},
"down": {"uv": [0, 6, 16, 16], "texture": "#10"}
}
},
{
"name": "Top",
"from": [0, 14, 0],
"to": [16, 16, 10],
"faces": {
"north": {"uv": [0, 0, 16, 2], "texture": "#gearbox_top"},
"east": {"uv": [0, 6, 2, 16], "rotation": 90, "texture": "#10"},
"south": {"uv": [0, 0, 16, 2], "texture": "#gearbox_top"},
"west": {"uv": [0, 6, 2, 16], "rotation": 90, "texture": "#10"},
"up": {"uv": [0, 6, 16, 16], "texture": "#10"},
"down": {"uv": [0, 4, 16, 16], "texture": "#andesite_casing_short"}
}
},
{
"name": "Side",
"from": [0, 2, 0],
"to": [2, 14, 10],
"faces": {
"north": {"uv": [14, 2, 16, 14], "texture": "#gearbox_top"},
"east": {"uv": [2, 4, 14, 16], "rotation": 90, "texture": "#andesite_casing_short"},
"south": {"uv": [0, 2, 2, 14], "texture": "#gearbox_top"},
"west": {"uv": [2, 6, 14, 16], "rotation": 90, "texture": "#10"}
}
},
{
"name": "Side",
"from": [14, 2, 0],
"to": [16, 14, 10],
"faces": {
"north": {"uv": [0, 2, 2, 14], "texture": "#gearbox_top"},
"east": {"uv": [2, 6, 14, 16], "rotation": 90, "texture": "#10"},
"south": {"uv": [14, 2, 16, 14], "texture": "#gearbox_top"},
"west": {"uv": [2, 4, 14, 16], "rotation": 270, "texture": "#andesite_casing_short"}
}
}
],
"display": {},
"groups": [
{
"name": "head",
"origin": [8, 8, 8],
"children": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
},
{
"name": "casing",
"origin": [8, 8, 8],
"children": [10, 11, 12, 13, 14]
}
]
}

View file

@ -0,0 +1,10 @@
{
"parent": "create:block/repeaters/redstone_latch",
"display": {
"fixed": {
"rotation": [ 270, 0, 0 ],
"translation": [ 0, 0, -3],
"scale":[ 0.5, 0.5, 0.5 ]
}
}
}

View file

@ -0,0 +1,10 @@
{
"parent": "create:block/repeaters/toggle_latch",
"display": {
"fixed": {
"rotation": [ 270, 0, 0 ],
"translation": [ 0, 0, -3],
"scale":[ 0.5, 0.5, 0.5 ]
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 489 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 513 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 510 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 510 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 515 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 504 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 510 B

View file

@ -0,0 +1,19 @@
{
"type": "minecraft:block",
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "create:redstone_latch"
}
],
"conditions": [
{
"condition": "minecraft:survives_explosion"
}
]
}
]
}

View file

@ -0,0 +1,19 @@
{
"type": "minecraft:block",
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "create:toggle_latch"
}
],
"conditions": [
{
"condition": "minecraft:survives_explosion"
}
]
}
]
}

View file

@ -0,0 +1,32 @@
{
"type": "crafting_shaped",
"pattern": [
" T ",
"RCR",
"SSS"
],
"key": {
"S": {
"item": "minecraft:stone"
},
"C": {
"item": "minecraft:lever"
},
"R": {
"item": "minecraft:redstone"
},
"T": {
"item": "minecraft:redstone_torch"
}
},
"result": {
"item": "create:redstone_latch",
"count": 1
},
"conditions": [
{
"type": "create:module",
"module": "logistics"
}
]
}

View file

@ -0,0 +1,29 @@
{
"type": "crafting_shaped",
"pattern": [
" T ",
" C ",
"SSS"
],
"key": {
"S": {
"item": "minecraft:stone"
},
"C": {
"item": "minecraft:lever"
},
"T": {
"item": "minecraft:redstone_torch"
}
},
"result": {
"item": "create:toggle_latch",
"count": 1
},
"conditions": [
{
"type": "create:module",
"module": "logistics"
}
]
}

View file

@ -1,6 +1,5 @@
{
"type": "create:crushing",
"group": "minecraft:misc",
"ingredients": [
{
"item": "minecraft:blue_orchid"

View file

@ -1,6 +1,5 @@
{
"type": "create:crushing",
"group": "minecraft:misc",
"ingredients": [
{
"item": "minecraft:leather_horse_armor"
@ -9,22 +8,12 @@
"results": [
{
"item": "minecraft:leather",
"count": 3
"count": 2
},
{
"item": "minecraft:leather",
"count": 2,
"chance": 0.5
},
{
"item": "minecraft:string",
"count": 2,
"chance": 0.25
},
{
"item": "minecraft:iron_nugget",
"count": 8,
"chance": 0.25
}
],
"processingTime": 200

View file

@ -1,6 +1,5 @@
{
"type": "create:mixing",
"group": "minecraft:misc",
"ingredients": [
{
"item": "create:crushed_copper"

View file

@ -11,6 +11,5 @@
"item": "create:lapis_plate",
"count": 1
}
],
"processingTime": 100
]
}

View file

@ -0,0 +1,14 @@
{
"type": "create:splashing",
"ingredients": [
{
"item": "create:limestone"
}
],
"results": [
{
"item": "create:weathered_limestone",
"count": 1
}
]
}

View file

@ -17,6 +17,5 @@
"count": 1,
"chance": 0.05
}
],
"processingTime": 100
]
}

View file

@ -1,6 +1,15 @@
{
"replace": false,
"values": [
"#minecraft:stairs", "#minecraft:slabs", "#minecraft:walls", "#minecraft:fences", "#forge:fences"
"#minecraft:stairs",
"#minecraft:wooden_stairs",
"#minecraft:wooden_slabs",
"#minecraft:slabs",
"#minecraft:walls",
"#minecraft:fences",
"#minecraft:wooden_fences",
"#forge:fences",
"#forge:fences/wooden",
"#forge:fences/nether_brick"
]
}

View file

@ -1,6 +1,16 @@
{
"replace": false,
"values": [
"create:tiled_glass_pane"
"create:tiled_glass_pane",
"create:framed_glass_pane",
"create:horizontal_framed_glass_pane",
"create:vertical_framed_glass_pane",
"create:oak_glass_pane",
"create:spruce_glass_pane",
"create:birch_glass_pane",
"create:jungle_glass_pane",
"create:dark_oak_glass_pane",
"create:acacia_glass_pane",
"create:iron_glass_pane"
]
}

View file

@ -0,0 +1,52 @@
Some of the most prominent machines and components require **Rotational Force** to operate. Sometimes the provided rotation speed and direction reflects their behaviour, and some components may have a more significant _cost_ than others.
1. Generate & Convey
2. Changing Gear
3. Stress & Capacity
## Generate & Convey
Using appropiate generators(link), you can start setting things in motion. These kinetic components will apply the speed they generate at to attached shafts, cogs, etc. Any component can be connected to any other, so long as their integrated shafts/cogs are linked together.
(waterwheel powering something) (mechanical crafters powering each other)
**Multiple generators** can be connected together in order achieve a greater Capacity score for the attached kinetic network. When attaching new generators to running components, it is important that the added generator rotates in the **same direction** as the component it is attached to. When connecting two kinetic blocks with **incompatible direction** of rotation, you'll notice that the blocks just break. However, trouble-shooting this will be quite straight-forward - all you need to do is to include a means of reversing the rotation between the generator and the rest:
Relaying rotational power between two components is one of the most important tasks when creating with Create. There are a variety of options and multiple possible solutions for each situation. These are the components that allow you to move, spread and modify rotational behaviour most effectively:
(mesh of these components showing off their behaviour)
- **Shafts**, cheapest option for relaying in a straight line.
- **Cogwheels**, move sideways while keeping the same rotation axis; reverse the direction
- **Belts**, move sideways while while keeping the same rotation axis; cannot be vertical; do not reverse direction
- **Gearboxes**, relay between two different rotation axes in a compact fashion; reverse connections on the same axis
- **Encased Belts**, relay sideways and between different rotation axes; do not reverse direction
Best is play around with each component and familiarizing yourself with its abilities. It is important to know the options when having to deal with complex connection tasks in a potentially less forgiving environment.
## Changing Gear
Some kinetic blocks have the ability to **speed up** or **slow down** connected components. Attach a large to a regular cogwheel diagonally: powering one of them at their shaft will result in the other rotating twice or half the speed respectively.
With this and other more compact blocks, you will have full control over the speed provided to your contraptions. This is especially important for machines that require a **minimum level of speed** to operate (e.g. the Mechanical Mixer).
Connecting faster components to other slower components **directly** will cause the faster network to overpower the rest, alinging the speed of everything that is now part of it. (That is, if the direction lines up)
(image of something ridiculous)
With this mechanic you can take things to the extreme and either rotate machines at the configurated maximum speed (256rpm by default) or slow them down to a fraction. But you may notice that speeding up brings a cost with it...
## Stress & Capacity
_In Create 0.2+, a bit of balance had been brought to rotational power: something to resemble torque in a highly simplified fashion._
Rotational generators have limited capacity for what they power. "Stress Impact" and "Stress Capacity" are the two opposing values in a kinetic network: **generators add capacity, machines and components add impact**. If the capacity is exhausted, all connected parts will simply stop moving, until capacity is increased or stress is relieved again.
**Stress Impact is tied to rotation speed**. Increasing the speed increases a components stress impact or capacity proportionally.
(image of fans and water wheel)
Consider the following example:
Assume one Water Wheel can provide just enough power in order to power four fans at the same speed.
* Doubling the speed of the fans using cogwheels will make the fans blow stronger, but the network will cease to function until the count of fans is halved, or the count of water wheels is doubled.
* Similarly, you would be able to power eight fans running at half the speed of the water wheel.
By default, components used **only for relaying** rotational power, such as shafts and cogwheels, have **no stress impact** at all. This makes predicting the amount of generators required for your contraptions much simpler and prevents punishment for aesthetic detours between machines and generators.
Optimizing stress impact and comparing net capacity of sources at base speed can become quite scientific. For those who are interested in seeing some actual numbers and more exhaustive information, it is recommended to look into crafting a pair of Goggles and a Stress Gauge.